Summary
kosli attest sonar cannot resolve scan results for any branch other than the project's main branch. The CLI knows which branch the scan ran on (it's in the CE task response) but never passes it to SonarQube's project_analyses/search API. Without the branch parameter, SonarQube returns analyses for the main branch only, the analysis ID lookup fails, and the CLI exits with:
Error: analysis with ID <uuid> not found on https://sonarcloud.io. Snapshot may have been deleted by SonarQube
Reproduction
- Run a SonarQube scan on a non-default branch (any branch other than
main/master). The branch must be classified as LONG (or the scan must produce queryable analysis history).
- Run
kosli attest sonar --sonar-working-dir .scannerwork --flow ... --trail ... --name ... --sonar-api-token ... --max-wait 300.
- Observe the CLI exits with
analysis with ID <uuid> not found on https://sonarcloud.io.
This is reliably reproducible — every push to a release branch in our repo hits it.
Direct API verification
# Kosli's call (no branch param) — returns 30 analyses, all from main:
GET https://sonarcloud.io/api/project_analyses/search?project=<key>
→ analyses for main only
# Same call WITH branch param — returns the analysis Kosli is looking for:
GET https://sonarcloud.io/api/project_analyses/search?project=<key>&branch=release/11.2.0
→ 1 analysis with key=dbe8a11e-21f8-460d-8765-802d4e0db490 (matches what CE task returned)
The analysis exists; the CLI just can't see it because it's not on the main branch.
Source
internal/sonar/sonar.go:
// GetProjectAnalysisFromAnalysisID
projectAnalysesURL, err := sonarURL(sonarResults.ServerUrl, "api/project_analyses/search",
url.Values{"project": {project.Key}}) // ← no branch param
// GetProjectAnalysisFromRevision — same omission
The CE task response (internal/sonar/sonar.go:Task) already exposes Branch and BranchType, and GetCETaskData populates sonarResults.Branch from it. The branch name is right there; it's just never used in the project_analyses/search URL.
Expected behavior
When the CE task reports a non-empty branch name, kosli attest sonar should pass it as branch=<name> to project_analyses/search so the analysis can be located on the correct branch.
Suggested fix
In both GetProjectAnalysisFromAnalysisID and GetProjectAnalysisFromRevision:
values := url.Values{"project": {project.Key}}
if sonarResults.Branch != nil && sonarResults.Branch.Name != "" {
values.Set("branch", sonarResults.Branch.Name)
}
projectAnalysesURL, err := sonarURL(sonarResults.ServerUrl, "api/project_analyses/search", values)
api/qualitygates/project_status (called from GetQualityGate) is already analysis-ID-based so it doesn't need branch — but worth a once-over for the same class of bug.
Affected versions
Confirmed on v2.17.1 (used by kosli-dev/setup-cli-action@v3 default) and verified the bug is still present on main at v2.17.5 — same code path in internal/sonar/sonar.go.
Workaround
There is no CLI-side workaround — there's no --branch flag on kosli attest sonar, and --sonar-revision / --pull-request modes route through the same buggy project_analyses/search lookup. Affected users have to either:
- Skip sonar attestation for non-main branches.
- Bypass
kosli attest sonar entirely and call SonarQube + kosli attest generic themselves.
- Or run the scan against
main (defeats the purpose).
A small CLI patch is by far the cleanest fix.
Summary
kosli attest sonarcannot resolve scan results for any branch other than the project's main branch. The CLI knows which branch the scan ran on (it's in the CE task response) but never passes it to SonarQube'sproject_analyses/searchAPI. Without thebranchparameter, SonarQube returns analyses for the main branch only, the analysis ID lookup fails, and the CLI exits with:Reproduction
main/master). The branch must be classified as LONG (or the scan must produce queryable analysis history).kosli attest sonar --sonar-working-dir .scannerwork --flow ... --trail ... --name ... --sonar-api-token ... --max-wait 300.analysis with ID <uuid> not found on https://sonarcloud.io.This is reliably reproducible — every push to a release branch in our repo hits it.
Direct API verification
The analysis exists; the CLI just can't see it because it's not on the main branch.
Source
internal/sonar/sonar.go:The CE task response (
internal/sonar/sonar.go:Task) already exposesBranchandBranchType, andGetCETaskDatapopulatessonarResults.Branchfrom it. The branch name is right there; it's just never used in the project_analyses/search URL.Expected behavior
When the CE task reports a non-empty branch name,
kosli attest sonarshould pass it asbranch=<name>toproject_analyses/searchso the analysis can be located on the correct branch.Suggested fix
In both
GetProjectAnalysisFromAnalysisIDandGetProjectAnalysisFromRevision:api/qualitygates/project_status(called fromGetQualityGate) is already analysis-ID-based so it doesn't need branch — but worth a once-over for the same class of bug.Affected versions
Confirmed on
v2.17.1(used bykosli-dev/setup-cli-action@v3default) and verified the bug is still present onmainatv2.17.5— same code path ininternal/sonar/sonar.go.Workaround
There is no CLI-side workaround — there's no
--branchflag onkosli attest sonar, and--sonar-revision/--pull-requestmodes route through the same buggyproject_analyses/searchlookup. Affected users have to either:kosli attest sonarentirely and call SonarQube +kosli attest genericthemselves.main(defeats the purpose).A small CLI patch is by far the cleanest fix.