Status: ✅ Done (2026-03-05)
Show analysis status of the HEAD commit in the repository and pull-request commands, and allow triggering reanalysis.
codacy repository <provider> <organization> <repository> --reanalyze
codacy pull-request <provider> <organization> <repository> <prNumber> --reanalyze
On success, show: "Reanalysis requested successfully, new results will be available in a few minutes." On failure, show: "Failed to request reanalysis: <error message>".
A second variant triggers the reanalysis and waits for it to complete, then
prints what changed. The fire-and-forget --reanalyze stays as-is.
codacy repository <provider> <organization> <repository> --reanalyze-and-wait
codacy pull-request <provider> <organization> <repository> <prNumber> --reanalyze-and-wait
Flow:
- Capture a baseline of current issues — for the repository from
issuesOverview(counts by severity / category / pattern as independent lists); for the pull request by paginglistPullRequestIssues(status="new")(each issue carries its pattern's category + severity). - Trigger
reanalyzeCommitByIdon the HEAD commit. - Poll every 10 s (giving up after 20 min), with the spinner showing
"Analysis requested. Waiting for it to start..."→"Analysis in progress. This may take a few minutes..."→"Analysis done. Fetching results to compare...". On each poll, read the first commit from the/commitsendpoint (listRepositoryCommitsfor the repo,getPullRequestCommitsfor the PR, bothlimit=1) and look at itsstartedAnalysis/endedAnalysis:- In progress =
startedAnalysismore recent thanendedAnalysisand more recent thant0(the moment we triggered) — i.e. the analysis that started is ours, not a previous one. - Done =
startedAnalysismore recent thant0andendedAnalysisat or afterstartedAnalysis(our analysis has since finished).
- In progress =
- Fetch a fresh snapshot, diff against the baseline, and print:
Analysis finished in <duration>headline (from the commit'sstartedAnalysis→endedAnalysis, falling back to wall-clock).- By pattern / By severity / By category signed net-delta lists. PR
pattern rows are annotated
(Category · Severity); repo pattern rows are title-only (the overview doesn't map patterns to category/severity). In total: <before> → <after> issues (net ±N).
Notes:
- The overview only exposes net per-bucket change, so deltas are signed net values per dimension, not a literal "added vs removed" split or a severity×category cross-tab.
- The pattern list is soft-capped at 20 rows with a
… (N more)line. --output jsonemits{ durationMs, durationHuman, totals, deltas }.- On timeout, the spinner fails with a "didn't finish within 20 minutes" message.
Shared logic lives in src/utils/reanalyze-wait.ts (pollForAnalysis,
snapshotFromOverview, snapshotFromPrIssues, diffSnapshots,
renderReanalyzeReport, reanalyzeJson, and a timers.sleep indirection that
tests stub for instant polling). formatDuration lives in utils/formatting.ts.
The "Last Analysis" row is replaced by "Analysis", showing the current analysis status of the HEAD commit:
- Reanalysis in progress (HEAD commit already analyzed, but currently being reanalyzed):
Analysis Finished 12h ago (c00e638) — Reanalysis in progress...
- First analysis (HEAD commit not yet analyzed):
Analysis In progress... (c00e638)
- Analysis finished, waiting for coverage (within 3h):
Analysis Finished 12h ago (c00e638) — Waiting for coverage reports...
- Analysis finished, coverage overdue (>3h):
Analysis Finished 12h ago (c00e638) — Missing coverage reports
- Normal finished state:
Analysis Finished 12h ago (c00e638)
"In progress..." and "Reanalysis in progress..." are colored light blue. "Missing coverage reports" is yellow.
Same "Analysis" row replaces the former "Head Commit" row, with the same status logic applied to the PR's HEAD commit.
- Being analyzed:
startedAnalysisis set AND (endedAnalysisis absent ORstartedAnalysis > endedAnalysis) - Coverage expected: determined by
listCoverageReports(limit=1).data.hasCoverageOverview - Coverage data present:
diffCoverage.value !== undefined OR deltaCoverage !== undefined(PR);coveragePercentage !== undefined(repo) - Wait threshold: 3 hours from
endedAnalysis
Implemented in formatAnalysisStatus() in src/utils/formatting.ts.
reanalyzeCommitById—RepositoryService.reanalyzeCommitById(provider, org, repo, { commitUuid: sha })getPullRequestCommitswithlimit=1— head commit timing for PRlistRepositoryCommitswithlimit=1— head commit timing for repolistCoverageReportswithlimit=1— checkhasCoverageOverview
Additionally used by --reanalyze-and-wait:
listRepositoryCommits(limit=1) — repo first-commit analysis timestamps, polled for statusgetPullRequestCommits(limit=1) — PR first-commit analysis timestamps, polled for statusgetRepositoryPullRequest— fetched once to resolve the PRheadCommitShaissuesOverview— repo baseline/after issue counts (severity / category / pattern)listPullRequestIssues(status="new", paginated) — PR baseline/after issue list
- Update analysis status in the About section of the
repositorycommand - Update analysis status in the About section of the
pull-requestcommand - Add
--reanalyzeoption to therepositorycommand - Add
--reanalyzeoption to thepull-requestcommand - Update existing tests for the status sections
- Add tests for the new
--reanalyzeoption - Add
--reanalyze-and-wait(-w) blocking variant to both commands (2026-06-02)
src/utils/formatting.test.ts— 6 unit tests forformatAnalysisStatus; +formatDurationandisBeingAnalyzedtestssrc/commands/repository.test.ts— 4 tests (analysis status, reanalyze) + 3 for--reanalyze-and-waitsrc/commands/pull-request.test.ts— 3 tests (analysis status, reanalyze) + 3 for--reanalyze-and-waitsrc/utils/reanalyze-wait.test.ts— 12 unit tests (snapshots, diff, poll loop incl. timeout, render, json)