feat(routing): say when an account is refusing, and route around it #997
Workflow file for this run
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: | |
| pull_request: | |
| branches: | |
| - main | |
| push: | |
| branches: | |
| - main | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: "22" | |
| - uses: oven-sh/setup-bun@v2 | |
| - run: bun install | |
| - run: npm run typecheck | |
| - run: npm test | |
| - run: bun run build | |
| # Windows smoke test — catches platform-specific regressions in: | |
| # - claude-code postinstall on Windows (issue #445 class) | |
| # - the resolver picking up the bundled binary or platform-package binary (#417) | |
| # - cross-platform path handling in TS code | |
| # - bundle output spawning under node on Windows | |
| # We don't run the full unit suite here — that's covered by the Linux job | |
| # above and the resolver's logic is mock-driven so platform doesn't matter | |
| # for unit-level coverage. This job exercises the REAL install + start flow. | |
| windows-smoke: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: "22" | |
| - uses: oven-sh/setup-bun@v2 | |
| # Install — this also runs claude-code's postinstall, which is the | |
| # single most common source of Windows install-time bugs. | |
| # | |
| # NOTE: bun runs lifecycle scripts through its own bundled POSIX-ish | |
| # shell, even on Windows. That makes this step blind to POSIX syntax in | |
| # our own `postinstall` — see the npm step below. | |
| - run: bun install | |
| # Run our `postinstall` the way npm does: through cmd.exe. bun's shell | |
| # happily parses POSIX constructs like `2>/dev/null || true` on Windows, | |
| # so the `bun install` above cannot catch them — which is exactly how | |
| # #688 shipped a postinstall that broke `npm install` for every Windows | |
| # user while this job stayed green. | |
| # | |
| # `npm run` uses script-shell (cmd.exe on Windows) for the script body, | |
| # so a non-portable postinstall fails here with a non-zero exit. | |
| - name: postinstall must be cmd.exe-portable | |
| run: npm run postinstall | |
| shell: cmd | |
| # Run only the resolver tests on Windows. Useful even though they use | |
| # mocked deps, because the test runner itself exercises path joining, | |
| # file URL parsing, etc., on the real Windows runtime. | |
| - run: bun test src/__tests__/claude-executable-resolver.test.ts | |
| shell: bash | |
| # Plugin loader exercises `await import(absolutePath)` which on Windows | |
| # rejects raw backslash paths with `Received protocol c:`. The test | |
| # writes a real plugin file to a tempdir and loads it, so it actually | |
| # round-trips the buggy code path on the Windows runtime — keeps regressions | |
| # in `loader.ts`'s URL handling from sneaking back in. See PR #480. | |
| - run: bun test src/__tests__/plugin-loader.test.ts | |
| shell: bash | |
| # Build the bundle. | |
| - run: bun run build | |
| shell: bash | |
| # Smoke-start: launch the bundled CLI in the background, hit /health, | |
| # verify it responds with a body. We don't have Claude auth in CI, so | |
| # the auth check inside /health may report loggedIn:false — that's | |
| # fine; what we're verifying is the resolver finds the executable | |
| # and the proxy boots without throwing. | |
| - name: smoke start + /health probe | |
| shell: pwsh | |
| run: | | |
| $env:MERIDIAN_PORT = "3458" | |
| $env:MERIDIAN_HOST = "127.0.0.1" | |
| # Start meridian in the background. | |
| $proc = Start-Process -FilePath "node" -ArgumentList "dist/cli.js" -PassThru -RedirectStandardOutput "meridian.out.log" -RedirectStandardError "meridian.err.log" -WindowStyle Hidden | |
| try { | |
| # Poll /health up to 30s. | |
| $ok = $false | |
| for ($i = 0; $i -lt 30; $i++) { | |
| Start-Sleep -Seconds 1 | |
| try { | |
| $r = Invoke-WebRequest -Uri "http://127.0.0.1:3458/health" -UseBasicParsing -TimeoutSec 2 | |
| if ($r.StatusCode -eq 200) { $ok = $true; break } | |
| } catch { } | |
| } | |
| if (-not $ok) { | |
| Write-Host "===== meridian.out.log =====" | |
| if (Test-Path "meridian.out.log") { Get-Content "meridian.out.log" } | |
| Write-Host "===== meridian.err.log =====" | |
| if (Test-Path "meridian.err.log") { Get-Content "meridian.err.log" } | |
| throw "Meridian did not respond on /health within 30s — resolver or startup likely failed on Windows" | |
| } | |
| $body = Invoke-RestMethod -Uri "http://127.0.0.1:3458/health" -TimeoutSec 5 | |
| Write-Host "/health response: $($body | ConvertTo-Json -Compress)" | |
| if (-not $body.version) { throw "/health missing version field" } | |
| Write-Host "OK — meridian booted on Windows and /health returned a version." | |
| } | |
| finally { | |
| try { Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue } catch { } | |
| } | |
| # Merge settings are load-bearing, not cosmetic. Release Please parses every | |
| # commit on main for the changelog, so a squash body carrying branch commit | |
| # subjects produces DUPLICATE entries — that is what #693/#700 hit via | |
| # --merge, and the same trap reaches --squash for any 2+ commit PR. | |
| # | |
| # PR_TITLE + BLANK closes it structurally: the changelog line is the PR | |
| # title, and the body holds nothing but the Co-authored-by trailer GitHub | |
| # appends (verified — contributor credit survives BLANK). | |
| # | |
| # This exists so the invariant is enforced rather than remembered. If it | |
| # fails, someone changed the repo settings; restore them, do not "fix" this. | |
| # Release Please parses every commit on main, INCLUDING the body. A commit | |
| # whose body carries conventional-commit lines therefore emits the same | |
| # changelog entry twice — that is what #693/#700 hit via --merge, and the | |
| # same trap reaches --squash whenever a branch has 2+ conventional commits. | |
| # | |
| # Repo settings (PR_TITLE + BLANK) prevent it, but settings live outside the | |
| # repo and nothing stops them drifting back. This checks the OUTCOME on main | |
| # rather than the configuration, so it also catches a hand-written --body or | |
| # a stray --merge — any cause, not just the one we thought of. | |
| # | |
| # Deliberately not a settings check: GITHUB_TOKEN cannot read repository | |
| # merge settings at all (there is no such permission scope), so that version | |
| # compared empty strings and failed whether the settings were right or wrong. | |
| changelog-duplication: | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Head commit body must not contain conventional-commit lines | |
| run: | | |
| subject=$(git log -1 --format=%s) | |
| body=$(git log -1 --format=%b) | |
| echo "subject: ${subject}" | |
| # Release Please's own release commits are merged with --merge by | |
| # design (squashing breaks its version anchor), so their body legally | |
| # carries the release subject. Exempt only those. | |
| case "${subject}" in | |
| *"release-please"*|*"chore(main): release"*) | |
| echo "release commit — exempt"; exit 0 ;; | |
| esac | |
| if printf '%s\n' "${body}" | grep -q 'release-please--branches'; then | |
| echo "release-please merge commit — exempt"; exit 0 | |
| fi | |
| # The optional bullet matters: GitHub's COMMIT_MESSAGES body renders | |
| # each squashed commit as "* feat: subject", while a --merge body | |
| # carries the bare "feat: subject". Match both — missing the bulleted | |
| # form would leave the exact trap this job exists for undetected. | |
| offenders=$(printf '%s\n' "${body}" \ | |
| | grep -nE '^[[:space:]]*([*-][[:space:]]+)?(feat|fix|perf|refactor|docs|chore|test|build|ci|style|revert)(\([^)]*\))?!?:' || true) | |
| if [ -n "${offenders}" ]; then | |
| echo "::error::This commit's BODY contains conventional-commit lines:" | |
| printf '%s\n' "${offenders}" | while IFS= read -r l; do echo "::error:: ${l}"; done | |
| echo "::error::Release Please will emit each of these as a duplicate changelog entry." | |
| echo "::error::Cause is usually one of:" | |
| echo "::error:: - repo squash settings drifted off PR_TITLE + BLANK" | |
| echo "::error:: - the PR was merged with a hand-written --body" | |
| echo "::error:: - a non-release PR was merged with --merge instead of --squash" | |
| echo "::error::Check the release PR before it ships; see CLAUDE.md 'Development workflow'." | |
| exit 1 | |
| fi | |
| echo "clean — body carries no conventional-commit lines" |