diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..da1682e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: CI + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +jobs: + ci: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Bun + uses: oven-sh/setup-bun@v2 + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Build + run: bun run build + + - name: Typecheck + run: bun run typecheck + + - name: Test + run: bun test diff --git a/CHANGELOG.md b/CHANGELOG.md index 90c7422..835e460 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [Unreleased] +### Added +- Added pull request and main branch CI checks for build, type checking, and tests. + ## [4.3.18] - 2026-06-29 ### Changed - Removed the retired shared cloud MCP helper registration and dependency from diff --git a/package.json b/package.json index 950b72a..706536a 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "benchmark": "bun run build && bun benchmarks/benchmark.mjs", "benchmark:real": "bun run build && bun benchmarks/real-cli-benchmark.mjs", "test": "bun test", + "typecheck": "tsc --noEmit", "no-cloud:source": "bun test src/no-cloud-contract.test.ts", "no-cloud:pack": "bun run build && bun scripts/no-cloud-artifact-scan.mjs", "prepack": "bun run build && bun scripts/no-cloud-artifact-scan.mjs", diff --git a/src/output-store.test.ts b/src/output-store.test.ts index 6361dcb..d126541 100644 --- a/src/output-store.test.ts +++ b/src/output-store.test.ts @@ -1,21 +1,30 @@ import { describe, expect, it } from "bun:test"; -import { existsSync, mkdtempSync, readFileSync } from "node:fs"; +import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; describe("output store manifests", () => { it("stores compact task evidence with a lossless raw ref", async () => { - process.env.HASNA_TERMINAL_DIR = mkdtempSync(join(tmpdir(), "terminal-store-")); - const { saveOutputManifest } = await import("./output-store.js"); - const raw = Array.from({ length: 8 }, (_, i) => `src/file-${i}.test.ts:${i + 1}:describe("case")`).join("\n"); - const manifestPath = saveOutputManifest('rg -n "describe" src', raw); - expect(manifestPath).toBeTruthy(); + const previousDir = process.env.HASNA_TERMINAL_DIR; + const terminalDir = mkdtempSync(join(tmpdir(), "terminal-store-")); + process.env.HASNA_TERMINAL_DIR = terminalDir; - const manifest = readFileSync(manifestPath ?? "", "utf8"); - const rawRef = manifest.match(/^raw-ref:\s*(.+)$/m)?.[1]; - expect(manifest).toContain("search refs: 8 matches"); - expect(rawRef).toBeTruthy(); - expect(existsSync(rawRef ?? "")).toBe(true); - expect(readFileSync(rawRef ?? "", "utf8")).toContain("describe"); + try { + const { saveOutputManifest } = await import("./output-store.js"); + const raw = Array.from({ length: 8 }, (_, i) => `src/file-${i}.test.ts:${i + 1}:describe("case")`).join("\n"); + const manifestPath = saveOutputManifest('rg -n "describe" src', raw); + expect(manifestPath).toBeTruthy(); + + const manifest = readFileSync(manifestPath ?? "", "utf8"); + const rawRef = manifest.match(/^raw-ref:\s*(.+)$/m)?.[1]; + expect(manifest).toContain("search refs: 8 matches"); + expect(rawRef).toBeTruthy(); + expect(existsSync(rawRef ?? "")).toBe(true); + expect(readFileSync(rawRef ?? "", "utf8")).toContain("describe"); + } finally { + rmSync(terminalDir, { recursive: true, force: true }); + if (previousDir === undefined) delete process.env.HASNA_TERMINAL_DIR; + else process.env.HASNA_TERMINAL_DIR = previousDir; + } }); });