diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000000..19386e433a --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# Biome on staged files, the same check `bun run check` runs in CI. +# Installed by `bun install` (core.hooksPath). Skip once with --no-verify. +set -euo pipefail +files=() +while IFS= read -r file; do files+=("$file"); done < <( + git diff --cached --name-only --diff-filter=ACMR | + grep -E '\.(ts|tsx|js|jsx|mjs|cjs|json|jsonc|css|md|mdx)$' || true +) +[ ${#files[@]} -eq 0 ] && exit 0 +bun run --silent check --no-errors-on-unmatched --diagnostic-level=error --write "${files[@]}" +git add -- "${files[@]}" diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100755 index 0000000000..0ebe7166e2 --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Fast local mirror of the CI quality job for what this branch changes. +# Full parity: `bun run ci`. Skip once with `git push --no-verify`. +set -euo pipefail + +base=$(git merge-base HEAD origin/main 2>/dev/null || echo origin/main) +changed=$(git diff --name-only "$base" HEAD) + +if echo "$changed" | grep -qE '(^|/)package\.json$|^bun\.lock$'; then + echo "pre-push: checking bun.lock is in sync" + if ! bun install --frozen-lockfile --dry-run >/dev/null 2>&1; then + echo "pre-push: bun.lock is out of date. Run \`bun install\` and commit bun.lock." >&2 + exit 1 + fi +fi + +echo "pre-push: lint" +bun run --silent check + +echo "pre-push: typecheck and test changed packages" +bun run --silent ci:changed --filter="...[$base]" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fce7f42723..bdb37e3af3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,12 +18,16 @@ jobs: steps: - uses: actions/checkout@v4 - # Pinned to match `packageManager` in package.json. Unpinned, this floats - # to whatever bun is latest, so a bun release can break the gate with no - # change in the repo — and CI then disagrees with what contributors run. + # Read from `packageManager` in package.json, so CI runs the same bun as + # contributors and a bun release cannot change the gate on its own. - uses: oven-sh/setup-bun@v2 with: - bun-version: 1.3.14 + bun-version-file: package.json + + # Turbo remote cache backed by the Actions cache: packages whose inputs + # did not change replay check-types/test/build instead of rerunning. + - name: Turbo cache + uses: rharkor/caching-for-turbo@2238fae6eb9a9936f92356f54cb3660200d105e7 # v2.5.1 - name: Install dependencies run: bun install --frozen-lockfile @@ -52,7 +56,10 @@ jobs: - uses: oven-sh/setup-bun@v2 with: - bun-version: 1.3.14 + bun-version-file: package.json + + - name: Turbo cache + uses: rharkor/caching-for-turbo@2238fae6eb9a9936f92356f54cb3660200d105e7 # v2.5.1 - uses: actions/setup-node@v4 with: @@ -64,6 +71,9 @@ jobs: - name: Smoke-test the packed CLI and editor runtime env: PASCAL_PORTABLE_BUILD: "1" + # Node's default heap ran out during the editor build on the 7 GB + # macOS runner ("Reached heap limit", exit 137). + NODE_OPTIONS: --max-old-space-size=5120 run: | bun run build --filter editor cd packages/cli diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index accfafce74..e5341376ca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,8 +32,11 @@ We use [Biome](https://biomejs.dev/) for linting and formatting. Before submitti ```bash bun check # Check for issues bun check:fix # Auto-fix issues +bun run ci # Everything the CI quality job runs: lint, skills, types, tests, build ``` +`bun install` points git at `.githooks/`: the pre-commit hook runs Biome on staged files (and fixes what it can), and the pre-push hook lints and runs `check-types` and tests for the packages your branch changes. Skip once with `--no-verify`. + ### Tests Run the whole suite from the repo root: @@ -73,7 +76,7 @@ New node kinds and sidebar panels can ship as a plugin instead of editing the bu 1. **Fork the repo** and create a branch from `main` 2. **Make your changes** and test locally with `bun dev` -3. **Run `bun check` and `bun run test`** to make sure linting and tests pass +3. **Run `bun run ci`** to make sure linting, types, tests and the build pass 4. **Open a PR** with a clear description of what changed and why 5. **Link related issues** if applicable (e.g., "Fixes #42") diff --git a/package.json b/package.json index 10310d335c..16bb044633 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,9 @@ "check:fix": "biome check --write", "check-types": "turbo run check-types", "test": "turbo run test", + "ci": "bun run check && bun run skills:validate && bun run check-types && bun run test && bun run build", + "ci:changed": "turbo run check-types test --output-logs=errors-only", + "postinstall": "[ -n \"$CI\" ] || [ ! -e .git ] || git config core.hooksPath .githooks", "skills:validate": "bun scripts/validate-skills.ts && bun test scripts/cursor-plugin-policy.test.ts scripts/clawhub-ignore-policy.test.ts scripts/claude-mcp-config-policy.test.ts scripts/openai-tool-annotation-policy.test.ts scripts/path-containment.test.ts scripts/public-skill-discovery-policy.test.ts", "kill": "lsof -ti:3002 | xargs kill -9 2>/dev/null || echo 'No processes found on port 3002'", "clean:cache": "rm -rf apps/*/.next apps/*/.swc apps/*/.turbo packages/*/.turbo tooling/*/.turbo .turbo node_modules/.cache",