Skip to content

fix(sonar): attest a SonarQube Cloud short-lived branch by project key - #1295

Merged
AlexKantor87 merged 3 commits into
mainfrom
claude/sonar-short-lived-branch
Oct 23, 2026
Merged

AlexKantor87 merged 3 commits into
mainfrom
claude/sonar-short-lived-branch

Conversation

@AlexKantor87

@AlexKantor87 AlexKantor87 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1294

Release together: don't merge this on its own. It ships in the same release as #1297. That PR fixes the report-task.txt and --sonar-ce-task-url paths. That PR builds on this branch, so the short-lived branch rule stays in one function.

What

On SonarQube Cloud, --sonar-branch failed on a feature branch with Branch '...' is not of type LONG. The analysis search only serves long-lived branches.

When that search fails and the branch is listed as short-lived, the CLI now:

  • reads the branch's latest commit and date from api/project_branches/list.
  • fails clearly if that commit isn't --sonar-revision. SonarQube Cloud keeps only the latest analysis of a short-lived branch, as it does for pull requests.
  • reads the quality gate by project key and branch, then lists the branch again. The gate can't be asked for by commit, so if a newer push landed in between, it fails.

Any other SonarQube error is returned unchanged. A long-lived branch makes no extra calls.

Evidence

  • New tests in internal/sonar/sonar_short_branch_test.go. On main, the four short-branch tests fail with the reported error. All pass with the fix, and mutating each guard turns its test red.
  • Live: we ran the built binary against sonarcloud.io through a local proxy. It attests the public short branch cyber-dojo_differ / run-workflow-196. It rejects a wrong revision. main behaves as before.
  • Full suite against a local server: 3657 tests green.

Not covered

  • report-task.txt and --sonar-ce-task-url very likely fail the same way (see the issue).
  • With no analysis ID, task ID, status and project name stay empty. That already happens when a token can't read api/ce/activity.
  • If a newer push lands mid-run, the error suggests retrying, which won't help. Its "check the revision" advice still applies.

🤖 Generated with Claude Code

AlexKantor87 and others added 2 commits October 23, 2026 08:26
SonarQube Cloud serves api/project_analyses/search only for long-lived
branches, so --sonar-branch on a feature branch failed with "Branch '...'
is not of type LONG". When the search fails and the branch is listed as
short-lived, use its latest analysis from api/project_branches/list and
its quality gate by project key and branch. The revision must be that
latest commit, checked again after reading the gate in case a newer push
was processed in between.

Fixes #1294

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rmed

The check after reading a short-lived branch's quality gate let the
attestation through when the second branch listing failed or no longer
listed the branch, so a gate of another commit could be attested. Fail
instead, and decide "gate is the branch's latest" in one place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added go Pull requests that update go code fix labels Oct 23, 2026
@claude

claude Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @AlexKantor87's task in 2m 6s —— View job


Follow-up review of c33ffba — findings re-checked

  • Fetch existing review comments and PR state
  • Diff BEFORE..AFTER (2374801..c33ffba)
  • Assess status of each previous finding
  • Flag any new bugs/regressions introduced by the fix in changed lines
  • Post summary comment

Status of each previously-raised finding:

  1. Re-check hides the cause (inline thread on sonar.go) — Resolved. listedShortLivedBranch now returns sonarResponseError(status) for a non-2xx/unparseable response, and the re-check in GetSonarResults wraps it with %w into the "could not confirm…" message. Thread is marked resolved on GitHub.
  2. Mark the branch short-lived explicitly — Not addressed, by design (not a location touched by this commit). Author's rationale: gateIsBranchLatest deliberately keys off "no analysis ID" rather than Type == "SHORT", to stay correct once a follow-up PR gives short-lived branches an analysis ID via report-task.txt/--sonar-ce-task-url. Reasonable tradeoff, not a bug.
  3. Re-check error says "try again later" — Resolved. The newer-analysis message now names both commits and states the revision can no longer be attested, with no retry advice.
  4. No test for a failed first listing — Resolved. TestGetSonarResults_ShortLivedBranch_FirstListingFails added, asserting SonarQube's original error is preserved when the first branch listing fails.

New issues in the changed lines (2374801..c33ffba): none found. Checked for: nil-pointer risk on branch after the err/branch == nil merge (safe — the synthesized "no longer listed" error is checked before dereferencing branch.Commit.SHA), and taking &branch of the for _, branch := range loop variable in listedShortLivedBranch (safe under Go 1.26's per-iteration loop variable scoping, matching go.mod's go 1.26.10). Behavior for the first-call path (shortLivedBranchAnalysis) is unchanged: any listedShortLivedBranch error is still swallowed so the original SonarQube error surfaces, as verified by the new test above.

No new inline comments posted — the one open thread was already resolved by the fix, and no regressions were found in the touched lines.

Note: I wasn't able to execute go test/make test_integration in this environment (Bash tool required approval that wasn't available), so this assessment is based on static diff review of internal/sonar/sonar.go and internal/sonar/sonar_short_branch_test.go, cross-checked against the author's described mutation tests.

Comment thread internal/sonar/sonar.go Outdated
@AlexKantor87

AlexKantor87 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Here's what happened to each finding in c33ffba.

  1. The re-check hides the cause. Fixed; see the inline thread.
  2. Mark the branch short-lived explicitly. Not taken. gateIsBranchLatest checks for "no analysis ID", because that is why the gate has to be read by branch. A follow-up PR handles the report-task.txt and --sonar-ce-task-url paths. There, short-lived branches do have an analysis ID, and their gate should be read by that ID. Checking Type == "SHORT" would send those to the branch gate instead. If the rule is ever broken, the re-check fails safe.
  3. The re-check error says "try again later". Fixed. When a newer analysis has replaced the revision, the error names both commits and says that revision can no longer be attested.
  4. No test for a failed first listing. Added TestGetSonarResults_ShortLivedBranch_FirstListingFails. It passes on the old code too, so it guards against a regression rather than proving a fix.

search: grep -nE 'try again later' internal/sonar/sonar.go

277: pull request analysis is of another revision (existing)
363: CE task not found (existing)
487: analysis for revision not found (existing)
510: short-lived branch has no analysis yet
513: short-lived branch's latest analysis is of another revision

In each of these, the scan may not be processed yet, so a retry can help. The newer-analysis message has none.

mutation: make listedShortLivedBranch errors reach the user on the first call -> TestGetSonarResults_ShortLivedBranch_FirstListingFails red
mutation: skip the commit check in the re-check -> TestGetSonarResults_ShortLivedBranch_NewerAnalysisDuringLookup red

The full local suite is green on this tree (3661 tests).

🤖 Addressed by Claude Code

…irmed

The branch lookup now reports a non-2xx response as an error, so the
re-check after reading the gate keeps the HTTP status, and a branch no
longer listed is named as the cause. When a newer analysis has replaced
the attested revision, the error says so rather than suggesting a retry
that cannot help.

search: grep -nE 'isShort|shortLivedBranchAnalysis' internal/sonar/sonar.go
  465-466 the first lookup in GetProjectAnalysisFromRevision, still the
  only caller; 499/504 its definition. The re-check no longer calls it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@AlexKantor87
AlexKantor87 merged commit 5598303 into main Oct 23, 2026
25 of 27 checks passed
@AlexKantor87
AlexKantor87 deleted the claude/sonar-short-lived-branch branch October 23, 2026 08:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix go Pull requests that update go code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

attest sonar: --sonar-branch fails on a SonarQube Cloud short-lived branch

2 participants