Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: CI

on:
pull_request:
branches: [main]

permissions:
contents: write
pull-requests: write
checks: write
id-token: write

jobs:
test:
name: Lint, Test, and Format Check
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x

- name: Run deno lint
run: deno lint

- name: Run deno fmt --check
run: deno fmt --check

- name: Run deno test
run: deno test --allow-read --allow-write --allow-env --allow-run

claude-review:
name: Claude Code Review
needs: test
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Claude Code Review
uses: anthropics/claude-code-action@v1
with:
prompt: |
Review this PR for:
1. Code quality and adherence to the project's TypeScript strict mode requirements
2. Compliance with the code style guidelines in CLAUDE.md (named exports, no any types, etc.)
3. Domain-driven design principles (use the ddd skill if needed)
4. Test coverage (unit tests should live next to source files)
5. Security vulnerabilities and best practices
6. Any potential bugs or edge cases

Please provide constructive feedback and suggest improvements where needed.
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

auto-merge:
name: Auto-merge PR
needs: [test, claude-review]
runs-on: ubuntu-latest
if: |
github.event.pull_request.head.repo.full_name == github.repository &&
(github.actor == 'dependabot[bot]' || contains(github.event.pull_request.labels.*.name, 'automerge'))

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Enable auto-merge
run: gh pr merge --auto --squash "$PR_NUMBER"
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3 changes: 2 additions & 1 deletion design/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ Shows the models input, schema, resource, methods, etc.

### model validate <model_id_or_name>

Runs the models zod validations for the models inputs and resources. Run them in parallel and print the output as it comes.
Runs the models zod validations for the models inputs and resources. Run them in
parallel and print the output as it comes.

### model method run <model_id_or_name> <method_name>

Expand Down
8 changes: 8 additions & 0 deletions src/infrastructure/logging/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ export interface LoggingOptions {
debugLogs: boolean;
}

let isInitialized = false;

export async function initializeLogging(
options: LoggingOptions,
): Promise<void> {
// LogTape can only be configured once per process
if (isInitialized) {
return;
}
const sinks: Record<string, ReturnType<typeof getConsoleSink>> = {
console: getConsoleSink(),
};
Expand Down Expand Up @@ -57,6 +63,8 @@ export async function initializeLogging(
},
],
});

isInitialized = true;
}

export function getSwampLogger(name: string) {
Expand Down
20 changes: 9 additions & 11 deletions src/infrastructure/logging/logger_test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { assertEquals } from "@std/assert";
import { existsSync } from "@std/fs";
import { getSwampLogger, initializeLogging } from "./logger.ts";

// Note: LogTape can only be configured once per process.
Expand Down Expand Up @@ -32,14 +31,13 @@ Deno.test("initializeLogging and getSwampLogger", async (t) => {
});
});

// Test debugLogs: true in isolation - this creates the dev-logs directory
Deno.test({
name: "initializeLogging with debugLogs true creates dev-logs directory",
ignore: existsSync("dev-logs"), // Skip if already exists from previous runs
fn: async () => {
// This test is designed to run only when dev-logs doesn't exist
// In practice, the directory may already exist from normal CLI usage
await initializeLogging({ debugLogs: true });
assertEquals(existsSync("dev-logs"), true);
},
Deno.test("initializeLogging is idempotent", async () => {
// Calling initializeLogging multiple times should not throw an error
// LogTape can only be configured once, so subsequent calls are no-ops
await initializeLogging({ debugLogs: false });
await initializeLogging({ debugLogs: true });
await initializeLogging({ debugLogs: false });

// If we get here without errors, the test passes
assertEquals(true, true);
});
4 changes: 3 additions & 1 deletion src/infrastructure/persistence/yaml_input_repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ export class YamlInputRepository implements InputRepository {
const typeDir = join(vendorDir, typeEntry.name);
// Read all inputs in this type directory
for await (const fileEntry of Deno.readDir(typeDir)) {
if (!fileEntry.isFile || !fileEntry.name.endsWith(".yaml")) continue;
if (!fileEntry.isFile || !fileEntry.name.endsWith(".yaml")) {
continue;
}

const path = join(typeDir, fileEntry.name);
const content = await Deno.readTextFile(path);
Expand Down
Loading