feat: default to Altimate Base with no consent gate; stop falling back to keyless Zen #3450
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Detect which areas of the codebase changed to skip unaffected jobs. | |
| # On push to main, all jobs run unconditionally (safety net). | |
| # --------------------------------------------------------------------------- | |
| changes: | |
| name: Detect Changes | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 2 | |
| outputs: | |
| typescript: ${{ steps.filter.outputs.typescript }} | |
| drivers: ${{ steps.filter.outputs.drivers }} | |
| dbt-tools: ${{ steps.filter.outputs.dbt-tools }} | |
| installer: ${{ steps.filter.outputs.installer }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3 | |
| id: filter | |
| with: | |
| filters: | | |
| typescript: | |
| # altimate_change start — upstream_fix: typecheck every declared TypeScript workspace | |
| - 'packages/cli/**' | |
| - 'packages/core/**' | |
| - 'packages/dbt-tools/**' | |
| - 'packages/effect-drizzle-sqlite/**' | |
| - 'packages/effect-sqlite-node/**' | |
| - 'packages/http-recorder/**' | |
| - 'packages/llm/**' | |
| - 'packages/opencode/**' | |
| - 'packages/server/**' | |
| - 'packages/tui/**' | |
| # altimate_change end | |
| - 'packages/drivers/**' | |
| - 'packages/plugin/**' | |
| - 'packages/sdk/**' | |
| - 'packages/util/**' | |
| - 'packages/script/**' | |
| - 'bun.lock' | |
| - 'package.json' | |
| - 'tsconfig.json' | |
| drivers: | |
| - 'packages/drivers/src/**' | |
| - 'packages/opencode/src/altimate/native/connections/**' | |
| - 'packages/opencode/test/altimate/drivers-e2e.test.ts' | |
| - 'packages/opencode/test/altimate/drivers-docker-e2e.test.ts' | |
| - 'packages/opencode/test/altimate/drivers-mongodb-e2e.test.ts' | |
| - 'packages/opencode/test/altimate/drivers-clickhouse-e2e.test.ts' | |
| - 'packages/opencode/test/altimate/connections.test.ts' | |
| # Run by the "DuckDB store-open E2E" step in the driver-e2e job. | |
| # Without these, a PR touching only these files skips that job, | |
| # and the main TypeScript job runs them with ALTIMATE_DUCKDB_E2E | |
| # unset, which skips every test in them — no execution anywhere. | |
| - 'packages/opencode/test/altimate/duckdb-open-e2e.test.ts' | |
| - 'packages/opencode/test/altimate/warehouse-test-duckdb-e2e.test.ts' | |
| - 'packages/opencode/test/altimate/duckdb-lock-helper.ts' | |
| - 'packages/opencode/src/altimate/tools/warehouse-test.ts' | |
| - 'packages/drivers/test/**' | |
| # These govern whether the native DuckDB binding is fetched at all | |
| # (`trustedDependencies`, and the pinned version). A change to them | |
| # can break every real-DuckDB test while touching no test file. | |
| - 'package.json' | |
| - 'bun.lock' | |
| - 'packages/drivers/package.json' | |
| dbt-tools: | |
| - 'packages/dbt-tools/**' | |
| installer: | |
| - 'install.ps1' | |
| - 'test/windows/**' | |
| # --------------------------------------------------------------------------- | |
| # altimate_change start — run the tracker-leak guard on every PR. | |
| # `script/check-tracker-leaks.ts` and its tests already existed but were wired | |
| # into no workflow, so nothing enforced them: v0.10.0 shipped three new | |
| # `AI-####` references into tracked files on this PUBLIC repo before a human | |
| # review caught them. It scans the branch name, the commits ahead of | |
| # origin/main, and the diff, so it needs full history and the base ref. | |
| tracker-leaks: | |
| name: Tracker Leaks | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| # This job runs pull-request code, so it gets read-only scope and no | |
| # persisted credentials — the checked-out branch must not be able to reach | |
| # the token in `.git/config`. (bot review) | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Fetch base branch | |
| # `--depth=0` is not valid git ("depth 0 is not a positive number") and | |
| # failed the job before the guard could run. `fetch-depth: 0` on the | |
| # checkout above already gives full history, so a plain fetch of the | |
| # base ref is all this needs. | |
| run: git fetch origin main | |
| - name: Check for internal tracker references | |
| # `actions/checkout` lands on the synthetic merge commit in detached | |
| # HEAD, so the script's own `rev-parse --abbrev-ref HEAD` yields "HEAD" | |
| # and the branch-name source -- one of the three it documents -- is | |
| # inert. Pass the real head ref explicitly. (review) | |
| env: | |
| PR_BRANCH: ${{ github.head_ref }} | |
| run: bun script/check-tracker-leaks.ts | |
| # altimate_change end | |
| # Main TypeScript tests — excludes driver E2E tests (separate job) and | |
| # cloud credential tests (local-only). | |
| # --------------------------------------------------------------------------- | |
| typescript: | |
| name: TypeScript | |
| needs: changes | |
| if: needs.changes.outputs.typescript == 'true' || github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Cache Bun dependencies | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }} | |
| restore-keys: | | |
| bun-${{ runner.os }}- | |
| - name: Configure git for tests | |
| run: | | |
| git config --global user.name "CI" | |
| git config --global user.email "ci@test.local" | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Install merge tooling deps (script/upstream) | |
| # The script/upstream/ workspace is its own bun project (depends on | |
| # minimatch). Root `bun install` doesn't reach it. Tests in | |
| # test/upstream/bridge-merge-e2e.test.ts shell out to | |
| # `bun run script/upstream/analyze.ts --branding` which requires this. | |
| # Mirrors the install step in the marker-guard job below. | |
| run: bun install | |
| working-directory: script/upstream | |
| # NOTE: there is no "prebuild test CLI" step. We tried pointing the subprocess harness at a | |
| # prebuilt single-file binary (OPENCODE_TEST_CLI) to dodge `bun run src` cold-boot, but the | |
| # compiled binary has a load-triggered hang on the run+mock happy path (it never exits under CPU | |
| # pressure). The robust answer is the dedicated bounded subprocess pass below: `bun run src` (no | |
| # such hang) at --max-concurrency=2, which stays green even under heavy load (~43s locally at | |
| # load 21). Do not reintroduce OPENCODE_TEST_CLI for these tests without fixing that binary hang. | |
| # altimate_change start — deliberate exception: the cold-start-regression job below DOES set | |
| # OPENCODE_TEST_CLI, for exactly one test (test/cli/serve/fresh-start.test.ts). That is safe | |
| # despite the warning above because it is a single bounded cold-start smoke check with its own | |
| # --timeout, not the general run+mock subprocess suite this NOTE is about — the load-triggered | |
| # hang needs sustained CPU pressure across many concurrent mock round-trips to manifest. | |
| # altimate_change end | |
| - name: SDK codegen is reproducible | |
| # The v2 gen tree is committed AND regenerated on every release build | |
| # (script/build.ts, clean: true) with post-codegen patches re-applied. | |
| # A clean checkout must round-trip to itself, or a release ships | |
| # something the review never saw. | |
| working-directory: packages/sdk/js | |
| run: | | |
| # The build mutates the checkout (both gen trees, openapi.json, dist); | |
| # restore it whatever happens so later steps see the committed tree. | |
| # An EXIT trap runs on `bash -e` aborts too. | |
| cleanup() { | |
| git checkout -- src/gen src/v2/gen 2>/dev/null | |
| git clean -qfd src/gen src/v2/gen 2>/dev/null | |
| rm -rf dist openapi.json build.log | |
| } | |
| trap cleanup EXIT | |
| # Prove codegen actually ran: a sentinel comment on the asserted file | |
| # (a comment, because the generator itself imports this client) must | |
| # be gone afterwards. A failure anywhere before the clean:true wipe | |
| # leaves the committed copy — and the sentinel — in place, so it can | |
| # no longer pass the drift check untouched. | |
| sed -i '1i // CI-SENTINEL: not regenerated' src/v2/gen/client/client.gen.ts | |
| build_rc=0; bun script/build.ts > build.log 2>&1 || build_rc=$? | |
| cat build.log | |
| if grep -q 'CI-SENTINEL: not regenerated' src/v2/gen/client/client.gen.ts; then | |
| echo "::error::codegen did not regenerate src/v2/gen/client/client.gen.ts (build exit $build_rc)" | |
| exit 1 | |
| fi | |
| drift_rc=0; git diff --exit-code -- src/v2/gen/client/client.gen.ts || drift_rc=$? | |
| # build.ts ends with `bun tsc`, which fails on a clean main until the | |
| # types.gen.ts round-trip is fixed (issue #1148). That ONE failure is | |
| # whitelisted by its EXACT diagnostic set — not merely "tsc failed", | |
| # which would silently whitelist new type regressions in the | |
| # regenerated SDK (script/check-known-tsc-failure.sh, unit-tested) — | |
| # and only when the file was regenerated AND round-trips (the two | |
| # assertions above); any other non-zero build — codegen, a patch, | |
| # prettier — fails the step. Remove the whitelist with #1148. | |
| if [ "$build_rc" -ne 0 ]; then | |
| wl_rc=0; bash script/check-known-tsc-failure.sh build.log || wl_rc=$? | |
| if [ "$wl_rc" -eq 0 ]; then | |
| echo "::warning::build.ts exited $build_rc at tsc with exactly the known #1148 diagnostic (TS2305 FileSystemEntry); codegen+patch asserted above" | |
| elif [ "$wl_rc" -eq 2 ]; then | |
| echo "::error::build.ts exited $build_rc before tsc — not the whitelisted #1148 failure" | |
| exit "$build_rc" | |
| else | |
| echo "::error::tsc failed with diagnostics beyond the whitelisted #1148 set (see output above)" | |
| exit "$build_rc" | |
| fi | |
| fi | |
| exit "$drift_rc" | |
| - name: Run tests | |
| working-directory: packages/opencode | |
| # Cloud E2E tests (Snowflake, BigQuery, Databricks) auto-skip when | |
| # ALTIMATE_CODE_CONN_* env vars are not set. Docker E2E tests auto-skip | |
| # when Docker is not available. No exclusion needed — skipIf handles it. | |
| # --timeout 90000: the full suite (9500+ tests across 379 files) runs in | |
| # one parallel bun process. Under CPU contention a handful of slower tests | |
| # (real fs/spawn/git-bootstrap work) get starved and exceed a tight timeout | |
| # NON-deterministically — different tests each run — failing CI with | |
| # "timed out after Nms" (observed 32s/51s at the old 30s limit). 90s gives | |
| # ~3x headroom over the worst observed, killing the resource-contention | |
| # flakiness without masking genuinely-hung tests. | |
| # | |
| # Bun 1.3.x has a known segfault during process cleanup after all tests | |
| # pass (exit code 143/SIGTERM or 134/SIGABRT). We capture test output and | |
| # check for real failures vs Bun crashes to avoid false CI failures. | |
| shell: bash | |
| run: | | |
| # Redirect bun output to files, then cat for CI visibility (avoids tee/SIGTERM-flush issues). | |
| # | |
| # Two passes: | |
| # - MAIN: the full suite EXCEPT the subprocess tests (OPENCODE_SKIP_SUBPROCESS=1 makes cliIt | |
| # skip them), at default parallelism — fast. | |
| # - SUBPROCESS: test/cli/{acp,smokes,serve} + run-process/mcp-add/help-snapshots, run in a | |
| # DEDICATED pass with --max-concurrency=2 (default 20). These each spawn a real CLI + an | |
| # in-process mock LLM server; at 20-concurrent the runner is CPU-starved and the mock | |
| # round-trips time out (the load-variance flakes). NOTE: do NOT add --parallel=1 — a single | |
| # worker hosts the mock server AND runs the tests on one event loop, so the mock gets starved | |
| # and round-trips time out anyway. Default --parallel spreads the mocks across workers; the | |
| # pass is isolated from the 11k main-suite tests so 2-per-worker is plenty bounded. | |
| # (Bun 1.3.x can segfault during cleanup after all tests pass — we parse the summary, not the | |
| # exit code. --timeout 90000 gives headroom for slow fs/spawn tests.) | |
| SUBPROCESS_PATHS="test/cli/acp/ test/cli/smokes/ test/cli/serve/ test/cli/run/run-process.test.ts test/cli/mcp-add.test.ts test/cli/help/help-snapshots.test.ts" | |
| OPENCODE_SKIP_SUBPROCESS=1 bun test --timeout 90000 > /tmp/test-main.txt 2>&1 || true | |
| bun test --timeout 90000 --max-concurrency=2 $SUBPROCESS_PATHS > /tmp/test-sub.txt 2>&1 || true | |
| echo "===== MAIN SUITE ====="; cat /tmp/test-main.txt | |
| echo "===== SUBPROCESS SUITE (bounded) ====="; cat /tmp/test-sub.txt | |
| # Sum pass/fail across both passes (one summary line each) | |
| sum_field() { awk -v f="$1" '$0 ~ ("^ *[0-9]+ " f "$"){s+=$1} END{print s+0}' /tmp/test-main.txt /tmp/test-sub.txt; } | |
| PASS_COUNT=$(sum_field pass) | |
| FAIL_COUNT=$(sum_field fail) | |
| echo "" | |
| echo "--- Test Summary (main + subprocess) ---" | |
| echo "pass=$PASS_COUNT fail=$FAIL_COUNT" | |
| # Real test failures — always fail CI | |
| if [ "$FAIL_COUNT" != "0" ]; then | |
| echo "::error::$FAIL_COUNT test(s) failed" | |
| exit 1 | |
| fi | |
| # Each pass must have produced a summary, else Bun crashed before finishing | |
| if ! grep -qE "^ *[0-9]+ pass$" /tmp/test-main.txt || ! grep -qE "^ *[0-9]+ pass$" /tmp/test-sub.txt; then | |
| echo "::error::Missing test summary in a pass — Bun may have crashed before running tests" | |
| exit 1 | |
| fi | |
| if [ "$PASS_COUNT" -gt 0 ] 2>/dev/null; then | |
| exit 0 | |
| fi | |
| echo "::error::No test results found" | |
| exit 1 | |
| # --------------------------------------------------------------------------- | |
| # Driver E2E tests — only when driver code changes. | |
| # Uses GitHub Actions services (no Docker-in-Docker). | |
| # Cloud tests (Snowflake, BigQuery, Databricks) are NOT run here — | |
| # they require real credentials and are run locally only. | |
| # --------------------------------------------------------------------------- | |
| driver-e2e: | |
| name: Driver E2E | |
| needs: changes | |
| if: needs.changes.outputs.drivers == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| services: | |
| postgres: | |
| image: postgres:16-alpine | |
| env: | |
| POSTGRES_PASSWORD: testpass123 | |
| ports: | |
| - 15432:5432 | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 10 | |
| mysql: | |
| image: mysql:8.0 | |
| env: | |
| MYSQL_ROOT_PASSWORD: testpass123 | |
| MYSQL_DATABASE: testdb | |
| ports: | |
| - 13306:3306 | |
| options: >- | |
| --health-cmd "mysqladmin ping -h 127.0.0.1" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 20 | |
| mssql: | |
| image: mcr.microsoft.com/azure-sql-edge:latest | |
| env: | |
| ACCEPT_EULA: Y | |
| MSSQL_SA_PASSWORD: TestPass123! | |
| ports: | |
| - 11433:1433 | |
| options: >- | |
| --health-cmd "/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'TestPass123!' -Q 'SELECT 1' || exit 1" | |
| --health-interval 10s | |
| --health-timeout 10s | |
| --health-retries 20 | |
| redshift: | |
| image: postgres:16-alpine | |
| env: | |
| POSTGRES_PASSWORD: testpass123 | |
| POSTGRES_DB: dev | |
| ports: | |
| - 15439:5432 | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 10 | |
| mongodb: | |
| image: mongo:7.0 | |
| ports: | |
| - 27017:27017 | |
| options: >- | |
| --health-cmd "mongosh --eval 'db.runCommand({ping:1})' --quiet" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 10 | |
| clickhouse: | |
| image: clickhouse/clickhouse-server:latest | |
| env: | |
| CLICKHOUSE_DB: testdb | |
| CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1 | |
| ports: | |
| - 18123:8123 | |
| options: >- | |
| --health-cmd "wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 15 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Cache Bun dependencies | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }} | |
| restore-keys: | | |
| bun-${{ runner.os }}- | |
| - name: Install dependencies | |
| run: bun install | |
| # `packages/drivers` declares no scripts and no job had it as a working | |
| # directory, so its 141 unit tests — including the driver's lock, timeout | |
| # and read-only regressions — never ran in CI at all. The main TypeScript | |
| # job runs `bun test` from `packages/opencode` only. | |
| - name: Run drivers unit suite | |
| run: bun test --timeout 60000 | |
| working-directory: packages/drivers | |
| - name: Run local driver E2E (DuckDB, SQLite, PostgreSQL) | |
| run: bun test test/altimate/drivers-e2e.test.ts | |
| working-directory: packages/opencode | |
| env: | |
| TEST_PG_HOST: 127.0.0.1 | |
| TEST_PG_PORT: "15432" | |
| TEST_PG_PASSWORD: testpass123 | |
| # Needs a dedicated process: four files in test/altimate install a | |
| # top-level mock.module("@altimateai/drivers/duckdb", …), and Bun | |
| # evaluates every test file's top level before running any test, so in a | |
| # whole-directory run these would silently exercise a fake. With | |
| # ALTIMATE_DUCKDB_E2E=1 a missing or mocked driver fails the step rather | |
| # than skipping it. | |
| # | |
| # `--timeout` is explicit because invoking `bun test` directly does not use | |
| # the package's `test` script, so it would otherwise take the CLI default | |
| # of 5000ms — shorter than both the driver's 30s default open budget and | |
| # the lock helper's 30s readiness budget, which would reimpose exactly the | |
| # kind of too-short outer deadline this PR removes. | |
| - name: Run DuckDB store-open E2E (real store, no mocks) | |
| run: bun test --timeout 90000 test/altimate/duckdb-open-e2e.test.ts test/altimate/warehouse-test-duckdb-e2e.test.ts | |
| working-directory: packages/opencode | |
| env: | |
| ALTIMATE_DUCKDB_E2E: "1" | |
| - name: Run Docker driver E2E (MySQL, SQL Server, Redshift) | |
| run: bun test test/altimate/drivers-docker-e2e.test.ts | |
| working-directory: packages/opencode | |
| env: | |
| TEST_MYSQL_HOST: 127.0.0.1 | |
| TEST_MYSQL_PORT: "13306" | |
| TEST_MYSQL_PASSWORD: testpass123 | |
| TEST_MSSQL_HOST: 127.0.0.1 | |
| TEST_MSSQL_PORT: "11433" | |
| TEST_MSSQL_PASSWORD: "TestPass123!" | |
| TEST_REDSHIFT_HOST: 127.0.0.1 | |
| TEST_REDSHIFT_PORT: "15439" | |
| TEST_REDSHIFT_PASSWORD: testpass123 | |
| - name: Run MongoDB driver E2E | |
| run: bun test test/altimate/drivers-mongodb-e2e.test.ts | |
| working-directory: packages/opencode | |
| env: | |
| TEST_MONGODB_HOST: 127.0.0.1 | |
| TEST_MONGODB_PORT: "27017" | |
| - name: Run ClickHouse driver E2E | |
| run: bun test test/altimate/drivers-clickhouse-e2e.test.ts | |
| working-directory: packages/opencode | |
| env: | |
| TEST_CLICKHOUSE_HOST: 127.0.0.1 | |
| TEST_CLICKHOUSE_PORT: "18123" | |
| # Cloud tests NOT included — they require real credentials | |
| # Run locally with: | |
| # ALTIMATE_CODE_CONN_SNOWFLAKE_TEST='...' bun test test/altimate/drivers-snowflake-e2e.test.ts | |
| # ALTIMATE_CODE_CONN_BIGQUERY_TEST='...' bun test test/altimate/drivers-bigquery-e2e.test.ts | |
| # ALTIMATE_CODE_CONN_DATABRICKS_TEST='...' bun test test/altimate/drivers-databricks-e2e.test.ts | |
| # --------------------------------------------------------------------------- | |
| # dbt-tools unit tests — fast (< 5s), run on PRs when dbt-tools changes. | |
| # --------------------------------------------------------------------------- | |
| dbt-tools: | |
| name: dbt-tools | |
| needs: changes | |
| if: needs.changes.outputs.dbt-tools == 'true' || github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Run dbt-tools unit tests | |
| run: bun run test | |
| working-directory: packages/dbt-tools | |
| # --------------------------------------------------------------------------- | |
| # Windows installer (install.ps1) — Pester behavioral tests on real Windows. | |
| # Runs the script as a subprocess (stopping early via -Help / unknown version | |
| # so nothing is downloaded) to cover arg parsing, the WOW64 arch fix, and | |
| # unknown-version rejection. Only when install.ps1 / its tests change. | |
| # --------------------------------------------------------------------------- | |
| windows-installer: | |
| name: Windows Installer (Pester) | |
| needs: changes | |
| if: needs.changes.outputs.installer == 'true' || github.event_name == 'push' | |
| runs-on: windows-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install Pester | |
| shell: pwsh | |
| run: Install-Module Pester -MinimumVersion 5.0.0 -Force -Scope CurrentUser -SkipPublisherCheck | |
| - name: Run installer Pester tests | |
| shell: pwsh | |
| run: | | |
| $config = New-PesterConfiguration | |
| $config.Run.Path = "./test/windows/install.Tests.ps1" | |
| $config.Run.Throw = $true | |
| $config.Output.Verbosity = "Detailed" | |
| Invoke-Pester -Configuration $config | |
| # altimate_change start — Windows ripgrep E2E (issue #1072) | |
| # --------------------------------------------------------------------------- | |
| # Real Windows check for ripgrep binary resolution. Downloads and extracts the | |
| # actual archive with PowerShell stripped from PATH, then executes the binary. | |
| # This is the condition that broke grep for 99 Windows machines; no amount of | |
| # unit testing on Linux/macOS covers it. | |
| # --------------------------------------------------------------------------- | |
| windows-ripgrep-e2e: | |
| name: Windows ripgrep E2E | |
| needs: changes | |
| if: needs.changes.outputs.typescript == 'true' || github.event_name == 'push' | |
| runs-on: windows-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| # --ignore-scripts: `tree-sitter-powershell` has no Windows prebuild and its fallback | |
| # compile needs Visual Studio Build Tools, which this runner does not have (see | |
| # anomalyco/opencode#25563). This check only needs the pure-JS dependency graph | |
| # (effect, @zip.js/zip.js, which, xdg-basedir), so skipping lifecycle scripts is enough. | |
| - name: Install dependencies | |
| run: bun install --ignore-scripts | |
| # Run from packages/core so `effect` and the other deps resolve — they are not root deps. | |
| - name: Resolve ripgrep with PowerShell unavailable | |
| working-directory: packages/core | |
| run: bun run script/windows-ripgrep-e2e.ts | |
| # altimate_change end | |
| # --------------------------------------------------------------------------- | |
| # dbt-tools E2E — slow (~3 min), only on push to main. | |
| # Tests dbt CLI fallbacks against real dbt versions (1.8, 1.10, 1.11) and | |
| # real Python environments (venv, uv, system). | |
| # --------------------------------------------------------------------------- | |
| dbt-tools-e2e: | |
| name: "dbt-tools E2E" | |
| needs: changes | |
| if: github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install uv | |
| run: curl -LsSf https://astral.sh/uv/install.sh | sh | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Cache dbt venvs | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: packages/dbt-tools/test/.dbt-venvs | |
| key: dbt-venvs-${{ runner.os }}-1.8-1.10-1.11 | |
| - name: Cache Python env scenarios | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: packages/dbt-tools/test/.dbt-resolve-envs | |
| key: dbt-resolve-envs-${{ runner.os }}-v1 | |
| - name: Set up dbt versions | |
| run: ./test/e2e/setup-versions.sh 1.8 1.10 1.11 | |
| working-directory: packages/dbt-tools | |
| - name: Set up Python env scenarios | |
| run: ./test/e2e/setup-resolve.sh venv uv system | |
| working-directory: packages/dbt-tools | |
| - name: Run dbt-tools E2E tests | |
| run: bun run test:e2e | |
| working-directory: packages/dbt-tools | |
| env: | |
| DBT_E2E_VERSIONS: "1.8,1.10,1.11" | |
| DBT_RESOLVE_SCENARIOS: "venv,uv,system" | |
| # --------------------------------------------------------------------------- | |
| # Verdaccio sanity suite — tests the real `npm install -g` flow. | |
| # Only on push to main (too slow for PRs, needs Docker Compose). | |
| # Catches publish-pipeline bugs: missing files, broken symlinks, wrong bin | |
| # field, dependency resolution failures, postinstall script issues. | |
| # --------------------------------------------------------------------------- | |
| sanity-verdaccio: | |
| name: Sanity (Verdaccio) | |
| needs: changes | |
| if: github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Cache Bun dependencies | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }} | |
| restore-keys: | | |
| bun-${{ runner.os }}- | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Build CLI binary | |
| # target-index=1 = linux-x64 (see release.yml matrix) | |
| run: bun run packages/opencode/script/build.ts --target-index=1 | |
| env: | |
| OPENCODE_VERSION: 0.0.0-sanity-${{ github.sha }} | |
| OPENCODE_RELEASE: "1" | |
| ALTIMATE_BASE_GATEWAY_URL: https://gateway.test | |
| MODELS_DEV_API_JSON: test/tool/fixtures/models-api.json | |
| - name: Build dbt-tools | |
| run: bun run build | |
| working-directory: packages/dbt-tools | |
| - name: Run Verdaccio sanity suite | |
| run: | | |
| docker compose -f test/sanity/docker-compose.verdaccio.yml up \ | |
| --build --abort-on-container-exit --exit-code-from sanity | |
| env: | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| # altimate_change start — cold-start config regression, split out of sanity-verdaccio so it also | |
| # runs on PRs. sanity-verdaccio stays push-only by design (Docker Compose, too slow for PRs — see | |
| # its header above); this check only needs the compiled binary, so it gets its own job gated like | |
| # `typescript` above: on PRs that touch TS, and unconditionally on push (safety net). | |
| # --------------------------------------------------------------------------- | |
| cold-start-regression: | |
| name: Cold-start Config Regression | |
| needs: changes | |
| if: needs.changes.outputs.typescript == 'true' || github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Cache Bun dependencies | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }} | |
| restore-keys: | | |
| bun-${{ runner.os }}- | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Build CLI binary | |
| # target-index=1 = linux-x64 (see release.yml matrix) | |
| run: bun run packages/opencode/script/build.ts --target-index=1 | |
| env: | |
| OPENCODE_VERSION: 0.0.0-sanity-${{ github.sha }} | |
| OPENCODE_RELEASE: "1" | |
| ALTIMATE_BASE_GATEWAY_URL: https://gateway.test | |
| MODELS_DEV_API_JSON: test/tool/fixtures/models-api.json | |
| # --version and PURE-mode tests never exercise ordinary config installs. This is the | |
| # deliberate exception to the "no OPENCODE_TEST_CLI" NOTE in the `typescript` job above: a | |
| # single bounded cold-start check with its own --timeout, not the general run+mock subprocess | |
| # suite, so the compiled-binary load hang that NOTE warns about cannot stall CI here. | |
| - name: Cold-start config regression (compiled, non-PURE) | |
| working-directory: packages/opencode | |
| env: | |
| OPENCODE_TEST_CLI: ${{ github.workspace }}/packages/opencode/dist/@altimateai/altimate-code-linux-x64/bin/altimate-code | |
| run: bun test test/cli/serve/fresh-start.test.ts --timeout 90000 | |
| # altimate_change end | |
| marker-guard: | |
| name: Marker Guard | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Add upstream remote | |
| run: | | |
| git remote add upstream https://github.com/anomalyco/opencode.git || true | |
| git fetch upstream --quiet --no-tags | |
| - name: Install merge tooling deps | |
| run: bun install | |
| working-directory: script/upstream | |
| - name: Run marker parser tests | |
| run: bun test | |
| working-directory: script/upstream | |
| - name: Run release preflight tests | |
| # Root bunfig.toml pins `bun test` away from the repo root, so run from | |
| # script/ — same pattern as the marker parser tests above. | |
| run: bun test release-preflight.test.ts | |
| working-directory: script | |
| - name: Check for missing altimate_change markers | |
| run: | | |
| if [[ "${{ github.event_name }}" == "push" ]]; then | |
| if [[ "${{ github.event.before }}" == "0000000000000000000000000000000000000000" ]]; then | |
| echo "Initial push (zero-SHA) — skipping marker check" | |
| exit 0 | |
| fi | |
| # Squash-merging an `upstream/merge-*` PR lands as a single commit | |
| # on main, so the second-parent / branch-name signal is gone here. | |
| # Detect bridge/merge-upstream commits in the pushed range by subject | |
| # and downgrade to non-strict — the PR-side review already gated this. | |
| if git log --format=%s "${{ github.event.before }}..${{ github.sha }}" \ | |
| | grep -qiE '(bridge|merge) upstream'; then | |
| echo "Bridge/upstream-merge commit detected in push range — running marker check in non-strict mode" | |
| bun run script/upstream/analyze.ts --markers --base "${{ github.event.before }}" | |
| else | |
| echo "Push to main — running marker check against pre-push state" | |
| bun run script/upstream/analyze.ts --markers --base "${{ github.event.before }}" --strict | |
| fi | |
| elif [[ "${{ github.head_ref }}" == merge-upstream-* ]] || [[ "${{ github.head_ref }}" == upstream/merge-* ]]; then | |
| echo "Upstream merge PR detected — running marker check in non-strict mode" | |
| bun run script/upstream/analyze.ts --markers --base origin/${{ github.event.pull_request.base.ref }} | |
| else | |
| bun run script/upstream/analyze.ts --markers --base origin/${{ github.event.pull_request.base.ref }} --strict | |
| fi | |
| - name: Branding leak audit (broadened scan, see analyze.ts LEAK_PATTERNS) | |
| # Catches user-visible bare "opencode" strings that markers alone miss — | |
| # yargs describe text, console output, MCP client identity, workflow YAML, | |
| # User-Agent strings, OIDC audience, infrastructure identifiers. | |
| # Caught 13 of 16 v1.4.0 bridge merge regressions in retrospective testing. | |
| run: bun run script/upstream/analyze.ts --branding | |
| - name: Require-markers regression backstop | |
| # Verifies every file in config.requireMarkers (38 files known to hold | |
| # altimate behavioral patches) has at least one altimate_change block. | |
| # If any patches were silently lost (refactor, accidental delete, bridge | |
| # merge oversight), CI fails here BEFORE the bug reaches production. | |
| run: bun run script/upstream/analyze.ts --require-markers --strict |