Skip to content

Analyze merge-queue commits with trusted Sonar controls - #788

Merged
rmcdaniel merged 7 commits into
mainfrom
ci/merge-queue-sonar
Oct 26, 2026
Merged

rmcdaniel merged 7 commits into
mainfrom
ci/merge-queue-sonar

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Queued commits need a genuine Sonar App result on their synthetic SHA. The first protected queue merge proves that reporting path works; this PR makes scanning automatic and repairs the reference-heartbeat retry gap exposed by its own queue qualification.

A dedicated queue-sonar.yml runs from the default branch after a successful merge-group PHPUnit workflow. It validates repository, workflow, queue branch and exact synthetic SHA, checks out trusted controls separately from analysis data, rejects linked files/submodules, and applies trusted scanner configuration. Only the pinned static scanner receives SONAR_TOKEN; automatic Clippy execution is explicitly disabled. Existing PR/main analysis stays unchanged.

Upload with sonar.qualitygate.wait=false: GitHub still requires SonarCloud Code Analysis from genuine Sonar App 12526 on the queued SHA. The account permits App decoration but rejects branch-status polling. Required PHPUnit and Shared Server fixtures also remain intact. Shared policy prerequisites durable-workflow/.github#266 and #267 are merged. CodeQL140 and the candidate-data checkout findings have their independent false-positive dispositions recorded.

The first group correctly failed closed on a real corpus failure: published PHP returned an explicit, retryable SQLite heartbeat deferral in HTTP200, which the probe recorded as a final answer. The probe now retries only documented activity/task/worker heartbeat deferrals with the exact negative acknowledgement, backend_lock_pressure and retryable=true. Existing 15-retry/30-second bounds, request timeout, replayable-body check and stderr retry evidence remain; frozen fixture expectations are unchanged. Original group evidence.

Validation: 336 focused Node scanner, merge-group, aggregate and parity-runner contracts pass. Six PHP retry tests/70 assertions cover accepted and rejected deferred-heartbeat shapes, unchanged budgets and a real Guzzle middleware replay whose recorder sees the terminal result only. All 21 shared-policy tests and 23 hostile workflow mutations passed for the unchanged scanner profile. A genuine Sonar App check succeeded on the first synthetic group with zero new issues. The failed-job retry was superseded and cancelled when this forward CI repair was pushed; it is not a passing qualification receipt.

Final-head hosted qualification and a protected merge remain. After landing, the next real merge group must exercise the trusted default-branch scanner automatically. Follow-up to #742; existing CI and credential trust are in scope for source review.

Comment thread .github/workflows/sonar.yml Fixed
Comment thread .github/workflows/queue-sonar.yml Dismissed
@rmcdaniel

Copy link
Copy Markdown
Member Author

Security review of exact head a01293dffb491b954fcb3f881abe58c6c860b339:

CodeQL alert 140 and Sonar githubactions:S7631 are false positives for candidate code execution in this exact workflow shape. The checkout is real, but the checked-out synthetic tree is data for a static scanner, not an executable control surface:

  • workflow_run loads the controller from the default branch, and the first checkout is pinned to github.workflow_sha (the commit containing the workflow file).
  • The helper accepts only a successful same-repository merge_group run with a strict synthetic-branch form and a 40-hex SHA.
  • No command, local action, dependency install, build, hook, submodule, LFS object, or persisted checkout credential comes from the candidate tree.
  • Tracked gitlinks/symlinks and any non-regular filesystem entry are rejected before scanning. The candidate sonar-project.properties is replaced with the trusted controller's file.
  • Only the immutable pinned Sonar action receives SONAR_TOKEN. Its pinned source installs a fixed Scanner CLI version with signature verification and invokes it with an argument array. The working directory is outside the candidate tree, scanner arguments are trusted, and sonar.rust.clippy.enabled=false disables the Rust analyzer's documented automatic candidate command.
  • The job has read-only repository permission and no post-scan candidate-controlled step. The central policy admits only this exact profile and rejects added execution or privilege.

GitHub documents that workflow_run uses the default branch and that github.workflow_sha is the workflow-file commit: https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#workflow_run and https://docs.github.com/en/actions/reference/workflows-and-actions/contexts#github-context. Sonar documents that automatic Clippy execution is disabled by sonar.rust.clippy.enabled=false: https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/languages/rust.

The residual trust is the pinned scanner/analyzers parsing hostile source, not candidate command execution. That is the bounded input risk inherent in this static-analysis job.

The two Sonar javascript:S4036 findings on execFileSync('git', ...) are also not candidate-controlled here: this is a GitHub-hosted ubuntu-latest job, no earlier candidate command runs, and neither pinned checkout step changes PATH. Using /usr/bin/git would make that invariant syntactic, but it is not a security blocker.

This classification does not override required CI. The current head still fails the central policy preflight because its deliberate qualitygate.wait=false update is newer than the merged exact policy profile. Align and test that prerequisite before merge. Any change to the trigger, permissions, controller checkout, candidate preparation, scanner pin/arguments, credential placement, or post-scan steps requires fresh review.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security recheck of exact head 1a3c2fd, tree ebef456ae2f0fcc125a6384b0dbed5be366cb0ea: the four-line delta is semantically equivalent ASCII-digit matching plus absolute /usr/bin/git for the fixed ubuntu-latest runner. It removes the reviewed S6353/S4036 noise without changing trigger, permissions, candidate isolation, scanner configuration, action pins, token placement, or the prior CodeQL/Sonar classification. No Security objection and no further Security wait; normal CI remains authoritative.

@rmcdaniel
rmcdaniel marked this pull request as ready for review October 26, 2026 18:59
@rmcdaniel
rmcdaniel added this pull request to the merge queue Oct 26, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 26, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

The first protected merge group for this PR was ce170deb444ae3fddce5e7ae77adbf951456ac89 (tree ebef456ae2f0fcc125a6384b0dbed5be366cb0ea, approved PR head 1a3c2fd02a6267a63f964977bcd22a2835b160e3, base a3e0bab0191f9fc004c297f98fa78eabc5136273).

  • Genuine Sonar App 12526 completed successfully on that exact group, check 121790990909: zero new issues, accepted issues, hotspots or new duplication. Bootstrap analysis task: AaF5o0bYjqIWVyoQY4a8. Required PHPUnit also succeeded.
  • The queue held the merge when Shared Server fixtures failed. In the original corpus job, cancellation-scopes/activity_heartbeat_after_delivery received the published PHP reference's explicit SQLite backend_lock_pressure response: HTTP 200, retryable: true, retry_after_seconds: 1, heartbeat_recorded: false. The strict fixture expected the eventual attempt_closed observation. The PHP maintenance log independently reports SQLite database is locked.
  • This PR changes only CI controls/tests; its product source equals the already qualified base. I am retrying only the failed job once after diagnosing that temporary reference-backend refusal. No required check, expected fixture outcome or Sonar App identity has been waived. The failed group was removed from the queue, which verifies that a real failed fixture cell blocks merging.

After this CI failure clears, this PR still needs a successful protected merge. The next real merge group will then verify the default-branch workflow_run scanner automatically; the manual bootstrap alone does not prove that path.

@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel

Copy link
Copy Markdown
Member Author

Exact head e4f29e6cb49b2b390b386327fd5e8d216073d276 has passed the scanner trust, PHP retry, contract and Sonar checks. Its first Shared fixtures attempt had one failed cell: MariaDB corpus, job121806185100.

The failure is the published PHP2.11.1 update-validation/approved_update response: bare HTTP500 {"message":"Server Error"} where202 was expected. It is not a native result. This PR changes no PHP product code, and the new retry accepts only documented heartbeat paths; this update request is outside that change. The original fixture diff is preserved in the job and bounded artifact.

The bounded PHP log retained a tail after the failing request, so it does not preserve the originating exception. I am not claiming a particular lock error from that evidence. Published update-validation contention defects remain tracked in #726/#754. After the complete workflow ended, I requested one rerun of this failed job only, with runner debug logging enabled. It must pass the original assertion; no generic500 retry or fixture relaxation was added. All other matrix cells retain their completed qualification.

The diagnostic gap and duplicate full PR/merge-group cycles are CI follow-ups. Full qualification of the protected merge group remains required. The already qualified native #773 may advance in parallel with a genuine Sonar bootstrap, while this PHP-reference failure is handled by General.

@rmcdaniel
rmcdaniel added this pull request to the merge queue Oct 26, 2026
Merged via the queue into main with commit 5dfd448 Oct 26, 2026
98 of 100 checks passed
@rmcdaniel

rmcdaniel commented Oct 26, 2026 •

Copy link
Copy Markdown
Member Author

Automatic merge-queue analysis is verified on the real #790 group 65b11820a475d7bc8147df00bc2ac4259babeab5, branch gh-readonly-queue/main/pr-790-5dfd44873dc9cbd99c738fb7537cf36e7e65bd0b.

  • The source PHPUnit workflow completed successfully at21:22:52UTC.
  • The trusted follow-up workflow ran from default-branch commit 5dfd44873dc9cbd99c738fb7537cf36e7e65bd0b. Its analysis job ran21:22:57–21:23:54UTC. Identity validation, separate candidate checkout, trusted configuration and the pinned static scanner all passed.
  • Genuine Sonar App12526, check 121856922968, reports SUCCESS / Quality Gate passed on exact 65b11820..., with zero new issues, hotspots or duplication. No manual analysis was uploaded for that group.

This completes automatic-scanner acceptance after #788's protected merge at20:44:29UTC. The full Shared Server fixture matrix remains mandatory for each protected group; #790 subsequently merged through the protected queue at21:33:05UTC as the exact qualified commit 65b11820a475d7bc8147df00bc2ac4259babeab5.

The active main queue retains ALLGREEN, two concurrent builds, one entry per merge, a120-minute check timeout and zero queue bypass actors. Required PHPUnit, Shared Server fixtures aggregate (App15368) and genuine Sonar (App12526) remain enforced. A real failed corpus cell previously blocked and removed a group, proving the required aggregate fails closed.

Protected merges #785, #773, #788 and #790 have passed the queue. Two-build concurrency started #788's full group15m10s before #773 merged, preserving all qualification. Bootstrap-only clone/cache, the unused custom policy-tools image/build context and both completed clean worktrees were removed after checking for active mounts and unrelated work. Ordinary product delivery continues; General's PHP handoffs are in #791.

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.

2 participants