Skip to content

fix: clear the Sonar issues and the planner's stop-test flake - #207

Merged
Bakhomious merged 5 commits into
mainfrom
step/sonar-flake-fixes
Oct 30, 2026
Merged

Bakhomious merged 5 commits into
mainfrom
step/sonar-flake-fixes

Conversation

@Bakhomious

@Bakhomious Bakhomious commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Brief

Goal. Clear the two open issues from SonarQube Cloud's run 41026989231 on 00caae0, which turned the gate red on the new code's security rating (C), and fix the planner's flaky TestStopEndsTheQuestions, which failed CI run 41027630840 on #127 and the first run of #206. One PR before the next step, as AGENTS.md asks (decision 419).

Scope.

  • services/planner/Dockerfile (docker:S6506, "HTTPS should be enforced on HTTP clients following redirects"): the wget of the CLI's tarball followed GitHub's redirect to another host. BuildKit's ADD --checksum=sha256:$COPILOT_SHA256 now fetches it and checks it against the pinned SHA-256, so no HTTP client runs in a RUN. The build arguments, the platform check and copilot:check stay as they were.
  • apps/web/e2e/notes-edit.spec.ts (typescript:S1607): the ⌘S test's phone skip gives its reason in a comment right above test.skip, as pulls.spec.ts and nudge's spec do (decision 168), since SonarJS reads the specs with its Vitest rules.
  • services/planner/internal/copilot:
    • TestStopEndsTheQuestions ends the questions' waits with stop, Stop's first step, while the connection is open, and still checks that the CLI gets the error. Its cleanup stops the client.
    • Stop's doc comment no longer promises that the CLI gets the error.
  • Docs: decision 419, which amends decision 410's stop; the §0 row; a §10 note on the SDK's Stop.

Out of scope.

  • Any change on screen or on the wire.
  • Making Stop wait for the SDK's handlers (see decision 419's Rejected).

Acceptance criteria.

  1. The Dockerfile has no wget or curl; a build fetches the tarball, checks its SHA-256 and fails on a mismatch; a build for another platform still fails with "The planner's image is for linux/amd64 alone."; the image's CLI runs on a read-only root.
  2. copilot:check still reads the version and the checksum from the Dockerfile and passes.
  3. The ⌘S test has a comment on the line above test.skip, and still skips on the phone and passes on desktop.
  4. TestStopEndsTheQuestions passes the orchestrator's go test -race -count=200, and doesn't fail under load, where it failed before.
  5. Every gate passes with no limit raised.

Size. 11 lines added and 10 removed outside the docs, comments included.

QA

  • Criterion 1, on colima (BuildKit v0.30.0, amd64 under emulation):
    • --target cli builds; the ADD expands $COPILOT_SHA256 and $COPILOT_VERSION from the build arguments.
    • --build-arg COPILOT_SHA256=000…0 fails with "digest mismatch".
    • --platform linux/arm64 fails with "The planner's image is for linux/amd64 alone."
    • The full amd64 image builds, and copilot --version on a read-only root says "GitHub Copilot CLI 1.0.105.".
    • The build's Alpine image has BusyBox's wget and no curl.
  • Criterion 2: mise run copilot:check passes.
  • Criterion 3: in mise run check, the ⌘S test passed on desktop and was skipped on the phone.
  • Criterion 4:
    • Reproduced the flake first: 12 copies of the race-built test binary at once, 150 runs each, failed 8 of 1,800. Each failure had one "Failed to send JSON-RPC error response: … use of closed network connection".
    • The cause, in the SDK v1.0.28: its JSON-RPC layer runs each handler on a goroutine of its own and sends the handler's error after the handler returns; its Stop sends session.detach, then closes the connection, without waiting for those goroutines.
    • After the fix: 7,200 runs with 12 copies at once, then 1,800 more, with no failure; the whole package 240 runs with no failure; the orchestrator's go test -race -count=200 -run TestStopEndsTheQuestions passes.
    • "Failed to close JSON-RPC writer: use of closed network connection" shows on every stop over a TCP connection; it's the SDK's noise, not a failure.

Review

No blocking findings. Non-blocking:

  • Sonar publishes no more than S6506's name, so its next run on main tells whether ADD satisfies it.
  • A PR's CI builds no image; the images workflow builds it after the merge, on BuildKit v0.34.1, whose Dockerfile frontend has ADD --checksum for URLs (stable since Dockerfile 1.6).
  • The platform check now runs after the download, so a build for another platform fetches the tarball before it fails. Only the images workflow builds the image, for linux/amd64.
  • The stop test calls stop, Stop's first step, rather than Stop; every test's cleanup still calls Stop and checks its error.

Gates

BAKHYARD_E2E_PORT=8480 mise run check passed locally on the head with main at 8feff43 (#194) merged in:

  • Go: lint 0 issues, fmt:check no diff, gen:check, copilot:check, vuln with no vulnerabilities; coverage 97.1% total, the copilot package 99.6%.
  • Workflows and compose: lint:actions, lint:compose.
  • Web: 1,341 unit tests; Biome, svelte-check, knip and pnpm audit clean.
  • End to end: 438 passed, 8 skipped, the same skips as on main. An earlier run, before the merges, failed on timeouts while the Mac slept in the middle of it (clamshell sleep 10:19 to 11:11); every run since, awake, passed.

Credits

SonarQube Cloud's run on 00caae0 failed its gate on two issues from the
planner's steps, and TestStopEndsTheQuestions failed now and then in CI.

- The planner's image fetches the Copilot CLI with ADD --checksum, so no
  HTTP client follows GitHub's redirect in a RUN (docker:S6506).
- The notes editor's ⌘S test gives its skip's reason in a comment, as
  SonarJS's Vitest rules want (typescript:S1607).
- The SDK sends a handler's error after the handler returns and closes
  the connection in Stop without waiting for it, so the stop test ends
  the questions' waits alone, with the connection open.

See decision 419.
@Bakhomious
Bakhomious merged commit 7f6919e into main Oct 30, 2026
2 checks passed
@Bakhomious
Bakhomious deleted the step/sonar-flake-fixes branch October 30, 2026 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant