Skip to content

CLI-1510 Generate a release report from the Harbor benchmark (PoC) - #1241

Draft
jonathan-balli-sonarsource wants to merge 2 commits into
masterfrom
task/jb/CLI-1510-harbor-release-report
Draft

jonathan-balli-sonarsource wants to merge 2 commits into
masterfrom
task/jb/CLI-1510-harbor-release-report

Conversation

@jonathan-balli-sonarsource

Copy link
Copy Markdown
Contributor

Why

The benchmark artifacts expire after 90 days, and the ones of a run started from a PR branch are deleted when the PR is closed (pr-cleanup.yml). To follow the CLI over time, each run must be kept in a small, durable form. This is a draft PoC for CLI-1510, opened only to run the workflow and the CI from this branch. It is not for review and should not be merged.

What

  • report/to-json.ts <runDir> writes one JSON per run on the standard output: the release (CLI version, run id, commit, date, optional iteration) and one line per trial (OS, task, agent, model, status, agent time, steps, tokens, cost). It reads the harbor-jobs directory of the report job (merged artifacts) or a run downloaded with gh run download, and stops with a non-zero code on anything unexpected. The OS is the name of the job directory.
  • report/dashboard.ts <dataDir> and dashboard-template.html build a standalone HTML dashboard (no network, no dependency) from a directory of those JSON.
  • report/adapters/git-branch.sh and local-dir.sh are the storage: push <file> adds a JSON, pull <dir> gets them all back. git-branch.sh keeps them on the orphan branch benchmark-data of a git repository, and another storage only needs another adapter, so the two scripts above do not depend on where the data lives.
  • The workflow gets three manual inputs (cli-version, iteration, store-report). The report job always builds the JSON and uploads it as the release-report artifact. A new store job runs only when store-report is checked: it pushes the JSON, pulls all of them and uploads dashboard.html.
  • The README describes the report in one paragraph.

Testing

bun run typecheck and Prettier pass. to-json.ts was run on three real runs (48, 40 and 40 trials) in both directory forms, with the same trials each time, and on the error cases (no folder, mixed forms, a job without trial, wrong number of arguments). The adapters were tested against a local bare repository (no branch, first push, same file twice, modified file, unreachable repository) and against a private test repository on GitHub. The steps of the report job were replayed locally on a real run: 40 trials, push, pull and a dashboard. Not tested yet: a run of the workflow on GitHub (the token, the write access of the store job and the boolean input).

Open points

The storage is a private test repository (jonathan-balli-sonarsource/harbor-benchmark-data-poc), written in the workflow and reached with the repository secret HB_BENCHMARK_DATA_TOKEN (a fine-grained token limited to that repository). Both are temporary. Whether a public repository is acceptable for these numbers, where to keep them, and what triggers the report (release.yml or a schedule) are still to be decided.

@netlify

netlify Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for sonarqube-cli canceled.

Name Link
🔨 Latest commit 1e72d52
🔍 Latest deploy log https://app.netlify.com/projects/sonarqube-cli/deploys/6af3340e4fc73a87b9d6aba6

@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

CLI-1510

@datadog-sonarsource

datadog-sonarsource Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Pipelines

⚠️ Warnings

Your PR has warnings. Please review the issues below.

🚦 1 Pipeline job failed

Harbor Benchmark | Report

View more details · View in GitHub Actions

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 1e72d52 | Docs | View more details | Give us feedback!

Comment thread benchmarks/harbor/report/to-json.ts Resolved
Comment on lines +182 to +196
- name: Build the release report
id: release-report
if: ${{ !cancelled() && hashFiles('harbor-jobs/**') != '' }}
shell: bash
env:
CLI_VERSION: ${{ inputs.cli-version }}
ITERATION: ${{ inputs.iteration }}
run: |
iteration=()
[ -n "${ITERATION}" ] && iteration=(--iteration "${ITERATION}")
mkdir release-report
bun benchmarks/harbor/report/to-json.ts \
--cli-version "${CLI_VERSION}" --run-id "${GITHUB_RUN_ID}" --commit "${GITHUB_SHA}" \
--date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" ${iteration[@]+"${iteration[@]}"} \
harbor-jobs > "release-report/${GITHUB_RUN_ID}.json"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Security: Release JSON and dashboard are published without the secrets scan

The README sets the rule "Nothing is published before it is scanned". It also says the report job scans its report text, even though that text is built only from result.json fields and numbers taken from artifacts that were already scanned. The new release JSON comes from the same fields: task names, agent and model names, config.json model names and trial folder names. Yet it is uploaded as the release-report artifact and pushed to a durable external repository, and dashboard.html is uploaded too, without ci/scan-secrets.py running on either. This bypasses the scan the README describes, and the data store may become public (see open points). Fix: run python3 -I benchmarks/harbor/ci/scan-secrets.py release-report before the upload, the same way report.txt is scanned.

Was this helpful? React with 👍 / 👎

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changed. The release JSON is built only from task, agent and model names and from numbers in result.json and trajectory.json final_metrics, never from message text, so I see no way for a secret to reach it. The artifacts it reads were already scanned and redacted by the benchmark jobs. I would rather not add a scan step to a PoC for this.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked benchmarks/harbor/report/to-json.ts. The output has no message text: the only free-form strings are task, agent and model, and everything else is a number or a fixed status. The leak risk is lower than the finding suggests.

One gap remains. On the crash path (crashedTrialRecord, lines 100-109), task comes from the trial folder name and agent/model from config.json. Those files were not read from result.json, and the agent may be able to write them. The README says the artifacts were "already scanned and redacted", but a value in a field that no scan flagged would still be published to the external repository and the dashboard.

If you accept that small risk for the PoC, the finding can stay as a known limitation. Running python3 -I benchmarks/harbor/ci/scan-secrets.py release-report before the upload is a one-line step if you change your mind. I made no code changes.

Comment thread .github/workflows/harbor-benchmark.yml Resolved
Comment thread .github/workflows/harbor-benchmark.yml Resolved
@jonathan-balli-sonarsource
jonathan-balli-sonarsource force-pushed the task/jb/CLI-1510-harbor-release-report branch from 3044cac to 1e72d52 Compare November 10, 2026 15:11
@gitar-bot

gitar-bot Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
CI failed: The Harbor release report job ran exit 1 after the report was generated and uploaded, likely because one macOS integrate--happy claude-sonnet trial failed (1/2 passed); the exit condition is not shown in the log, and the link to this PR is unclear.

Overview

One unique error template across 5 analyzed logs from the Report job. Report generation and artifact upload succeeded, but the job ended with an explicit exit 1. The log does not show the triggering condition, so the failed benchmark trial is the likely cause, not a confirmed one.

Failures

Report job exits 1 after successful report generation (confidence: medium)

  • Type: test
  • Affected jobs: 129923404058
  • Related to change: unclear
  • Root cause: The Report workflow reached an explicit exit 1 after uploading release-report (1595 bytes). The results table includes a failed trial for macOS / integrate--happy / claude-code / claude-sonnet-5-5 (1/2 passed). The log does not show that the exit was triggered by this failure, and the supplied workflow evidence is only a diff statistic, so the link to this PR is unconfirmed.
  • Suggested fix: Inspect the failed macOS integrate--happy claude-sonnet trial's Harbor artifact and log to find the underlying benchmark failure. Check the Report workflow's exit condition to confirm it propagates the benchmark result. Rerun only if the trial failure is suspected to be transient.

Summary

  • Change-related failures: 0 confirmed. The single failure is marked unclear.
  • Infrastructure/flaky failures: None identified. The failed trial has not been shown to be flaky.
  • Recommended action: Review the failed macOS integrate--happy trial artifact and the Report workflow exit logic before rerunning. The PR is still a draft, so this may be expected during the PoC.
Code Review 👍 Approved with suggestions 3 closed / 4 findings

🟡 Medium risk · The opt-in workflow writes benchmark metadata to an external repository with a token, so misconfiguration could retain or expose data beyond artifact expiry.

Adds a Harbor benchmark release report: per-run JSON from trial results, a standalone HTML dashboard, and git-branch and local-dir storage adapters wired into a new workflow with a store job. Three earlier issues were resolved (plain gh run download breakage, job-level storage token exposure, and a concurrency group that could cancel a pending store job). One open minor finding remains: the release JSON and dashboard.html are uploaded and pushed without the secrets scan that the README requires for published output, so ci/scan-secrets.py should run on release-report before upload.

💡 Security: Release JSON and dashboard are published without the secrets scan

📄 .github/workflows/harbor-benchmark.yml:165-176 📄 .github/workflows/harbor-benchmark.yml:182-196 📄 .github/workflows/harbor-benchmark.yml:251-263 📄 benchmarks/harbor/README.md:22

The README sets the rule "Nothing is published before it is scanned". It also says the report job scans its report text, even though that text is built only from result.json fields and numbers taken from artifacts that were already scanned. The new release JSON comes from the same fields: task names, agent and model names, config.json model names and trial folder names. Yet it is uploaded as the release-report artifact and pushed to a durable external repository, and dashboard.html is uploaded too, without ci/scan-secrets.py running on either. This bypasses the scan the README describes, and the data store may become public (see open points). Fix: run python3 -I benchmarks/harbor/ci/scan-secrets.py release-report before the upload, the same way report.txt is scanned.

✅ 3 closed
✅ Bug: New release-report artifact breaks to-json.ts on a plain gh run download

📄 benchmarks/harbor/report/to-json.ts:161-175 📄 .github/workflows/harbor-benchmark.yml:198-203 📄 .github/workflows/harbor-benchmark.yml:259-263 📄 benchmarks/harbor/README.md:24
The README and the PR say to-json.ts accepts "a run downloaded with gh run download". With no pattern, that command puts every artifact of the run in its own folder. This PR adds the release-report artifact (and the harbor-dashboard artifact when store-report is on) to every run, so the download now contains release-report/ next to the harbor-jobs-* folders. jobsOf then throws '<runDir>' mixes 'harbor-jobs-*' folders and other folders. The PR's tests used older runs that don't have these artifacts, so they couldn't catch it. Fix: ignore folders without the harbor-jobs- prefix once at least one artifact folder is present, or tell users in the README to run gh run download -p 'harbor-jobs-*'.

✅ Security: Storage token is in job-level env, so every step in the store job gets it

📄 .github/workflows/harbor-benchmark.yml:225-226 📄 .github/workflows/harbor-benchmark.yml:251-257
BENCHMARK_DATA_REMOTE, which contains secrets.HB_BENCHMARK_DATA_TOKEN, is set in the store job's env:. So every step can read it, including third-party and composite actions (actions/checkout, SonarSource/vault-action-wrapper, ./.github/actions/setup-bun, actions/download-artifact, actions/upload-artifact) and the bun dashboard.ts step, although only the two git-branch.sh calls need it. Fix: move the variable into the env: of the "Store the release report" and "Build the dashboard" steps, which keeps the write token away from the other steps.

✅ Edge Case: Concurrency group without a queue can cancel a pending store job

📄 .github/workflows/harbor-benchmark.yml:223-224
store uses concurrency: group: benchmark-data. A GitHub Actions concurrency group allows one running job and one pending job. When a third job joins the group, the job that was pending is cancelled. So if three benchmark runs with store-report reach the store job close together, the middle run's report is never pushed to the data branch, and the only sign is a cancelled job. Since the point of the PR is to keep every run durably, this silently drops data. Fix: allow queueing (for example queue: max where available), or make git-branch.sh push retry on a non-fast-forward and drop the concurrency group.

🤖 Prompt for agents
Code Review: Adds a Harbor benchmark release report: per-run JSON from trial results, a standalone HTML dashboard, and git-branch and local-dir storage adapters wired into a new workflow with a store job. Three earlier issues were resolved (plain `gh run download` breakage, job-level storage token exposure, and a concurrency group that could cancel a pending store job). One open minor finding remains: the release JSON and dashboard.html are uploaded and pushed without the secrets scan that the README requires for published output, so `ci/scan-secrets.py` should run on `release-report` before upload.

1. 💡 Security: Release JSON and dashboard are published without the secrets scan
   Files: .github/workflows/harbor-benchmark.yml:165-176, .github/workflows/harbor-benchmark.yml:182-196, .github/workflows/harbor-benchmark.yml:251-263, benchmarks/harbor/README.md:22

   The README sets the rule "Nothing is published before it is scanned". It also says the report job scans its report text, even though that text is built only from `result.json` fields and numbers taken from artifacts that were already scanned. The new release JSON comes from the same fields: task names, agent and model names, `config.json` model names and trial folder names. Yet it is uploaded as the `release-report` artifact and pushed to a durable external repository, and `dashboard.html` is uploaded too, without `ci/scan-secrets.py` running on either. This bypasses the scan the README describes, and the data store may become public (see open points). Fix: run `python3 -I benchmarks/harbor/ci/scan-secrets.py release-report` before the upload, the same way `report.txt` is scanned.

Verification Rules 3/3 met

Functional validation No results

Rules 3 passed 1 not applicable

✅ Approved GitHub Actions runners
✅ Internal artifact registries
✅ Repository license compliance

Auto-approval Withheld

For more verification details, comment gitar display:verbose.

Tip

Comment Gitar fix CI or enable auto-apply: gitar auto-apply:on

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing compact verification results.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
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