Skip to content

docs: move and rewrite the image tagging guidance [OD-707] - #2757

Merged
claudiacodacy merged 9 commits into
masterfrom
docs-move-and-rewrite-the-image-tagging-guidance-and-state-od-707
Sep 22, 2026
Merged

claudiacodacy merged 9 commits into
masterfrom
docs-move-and-rewrite-the-image-tagging-guidance-and-state-od-707

Conversation

@claudiacodacy

@claudiacodacy claudiacodacy commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Closes OD-707. Docs half of OD-679; the wording tracks the final mockups in Figma section 22034:10 "Deliverable".

File
docs/security/container-scanning.md the tagging guidance, the cap, and CLI pipeline examples
docs/codacy-cloud-cli/index.md new — the container image commands shipping in 1.12.0
docs/codacy-api/examples/uploading-container-image-sboms.md new — the API path, mirroring uploading-dast-results.md
mkdocs.yml nav entry for the new example page

What was wrong

The tagging trade-off lived in an !!! important block below the tag list — four screens from where the tag is actually chosen. It omitted the painful consequence (dismissals, owners and SLA clocks reset on every new tag) and framed the 1,000-tag cap as housekeeping.

The tagging guidance

New ## How tagging affects your findings section, placed before the setup instructions. Carries the comparison table from the issue and the two options in the same words the product uses — "One list, kept up to date" / "A separate list per release".

### What the image tag limit does. The cap does not reject uploads, it rejects image tags Codacy has not seen before. An org on a rolling tag can sit at 1,000/1,000 indefinitely and never notice; an org tagging per release stops being scanned on its next release while the stale tags keep being scanned, and the only signal is the pipeline error. Read from ContainersDAO.scala:70-77 (the write tries an UPDATE first and raises only when it touches zero rows) and reference.conf:115.

Two false bullets corrected in the CI/CD section: "Images pushed through your pipeline are automatically detected" and "New tags are picked up as they're published". Nothing is detected or picked up — you upload the image and tag you name.

The Cloud CLI container image commands

#49, #50 and #52 have merged and ship as 1.12.0 in the pending release PR #54. codacy-cloud-cli/index.md gains two sections:

  • Manage container images — codacy images, codacy image, --tag, --upload, --delete, and the 100/1000 limit defaults.
  • Keep container image tags under the organization limit — --delete --keep-latest, --dry-run, the --output json shape, and the per-image vs organization-wide caveat the command itself warns about.

Surface read from src/commands/image.ts and images.ts on origin/main, not from the changeset prose; token handling confirmed at src/utils/auth.ts:171.

The per-release pipeline example now cleans up before it uploads, which is the order the backend forces: at the cap the upload is rejected, so cleaning up afterwards strands the organization there.

Worked examples

Every command was executed, not just written:

  • the three-line install + init — bash <(curl …) leaves no codacy-cli.sh behind, so the next line dies;
  • upload-sbom refuses without init. The error text on the page is quoted from a real run: No configuration file was found, execute init command first.;
  • docker tag before a rolling upload — upload-sbom shells out to trivy image, which silently falls back to the registry, so without the alias a pipeline that built 1.4.2 scans whatever stale :prod the registry holds.

Structure: consistent with App scanning

app-scanning.md keeps concepts and UI, and links out to codacy-api/examples/* for the runnable API calls. Container scanning now has the same shape:

  • CLI examples stay on the feature page, matching how codacy-cloud-cli/index.md and codacy-analysis-cli/index.md document CLI usage;
  • a !!! note links out to the new API example page, exactly as app-scanning.md does for ZAP;
  • both new pages use the DAST placeholder convention — "Replace the placeholders with your own values" followed by a description list and a Git provider table.

The provider table lists only gh/gl/bb. The DAST one also carries ghe/gle/bbe, but both CLIs document three values, so the enterprise rows were not copied across.

Things found while writing this

The cap does not return the 409 the swagger declares. SbomFilesHandler.uploadImageSbom maps the ContainerSbomError family to 400 and everything else to 500. InsertConflict — the cap — is not in that family, so it falls through to the generic branch and is indistinguishable from a server fault. The API page tells readers to match on the message Organization has reached the maximum limit of 1000 image SBOMs instead. Relevant to OD-691, which is specced to add a typed rejection error.

Every container-scanning docs link in the SPA is currently broken. They point at organizations/managing-security-and-risk/#cicd-integration and #container-scanning. #2756 split that page, and the redirect sends them to /security/ — which has neither anchor, so readers land at the top of the Security overview. Confirmed against the built site. #dashboard survives because it was pinned. Needs an FE change in codacy-spa; a redirect cannot rescue a fragment.

For the bfi-finance conversation

Added after the #product-help thread: that organization is carrying roughly 1.5M container findings across about 970 of its 1,000 image tags, and nothing here told them what to do about it. Two sections close that:

### Reducing findings on an image that already has many tags — the recovery path, which is what a customer already in this position needs. The load-bearing point is that switching the tag your pipeline uploads to does nothing on its own: the tags already stored keep their own findings and keep being scanned every night, so the count does not move until the tags go. Deleting a tag is what removes them — verified through RemovedImageTag → RemovedImageTagWriterStream → itemsDAO.deleteContainerScanItemsByImageTag, which deletes rather than closes, asynchronously. The section walks through list → --dry-run → delete, and says to start by finding which images hold the tags, since it is usually a small number of them.

#### If your pipeline already produces an SBOM — the Cloud CLI upload for both strategies. The mockups draw this as a tab; this page previously only mentioned --upload in passing. Worth noting it needs no docker tag alias, because --upload attaches the file you name to the tag you name and never resolves the image.

Link targets this gives the product

Design / SPA label URL
"How tagging affects your findings" (manual setup caption + all three tag-limit banners) https://docs.codacy.com/security/container-scanning/#how-tagging-affects-your-findings
"Setting up via your CI/CD" https://docs.codacy.com/security/container-scanning/#cicd-integration
"Check our container scanning documentation" https://docs.codacy.com/security/container-scanning/
"upload it using our API v3" https://docs.codacy.com/codacy-api/examples/uploading-container-image-sboms/

Checks

  • mkdocs build --strict — clean, no warnings (validation.anchors: warn).
  • Anchors confirmed in the built HTML: #how-tagging-affects-your-findings, #cicd-integration, #container-scanning, #keep-latest; cross-page links to api-tokens/#account-api-tokens, using-the-codacy-api/#using-pagination and codacy-cloud-cli/#keep-latest resolve with their fragments.
  • New page registered in mkdocs.yml nav.
  • Investigation checks: no lockstep <!--NOTE header on the pages touched; no shared includes; no inbound anchor links in-repo; no existing heading reworded, so no anchor retired and no redirect needed. No Self-hosted claim added.
  • API contract read from the generated client (SbomService.ts:227-280, :286-345, :395-440) and the Scala handler.
  • Snippets: every bash block on the three pages run through the project's static harness. The two pipeline examples pass in the order the page presents them; the CLI install block and the init requirement were executed. docker tag itself was not run (no Docker daemon on this machine) — everything downstream of it was.
  • Vale: remaining errors are Microsoft.Contractions on consequence statements about the tag limit. Kept deliberately — .claude/reference/voice.md says to avoid contractions in exactly those sentences. Vale is advisory here.

Left alone

  • codacy-cloud-cli/index.md has a pre-existing block, codacy issue gh my-org my-repo <issueId>, that is not valid shell — <issueId> parses as a redirect. Predates this PR.
  • The ## How our container image scanning Works heading has a stray capital W.
  • The manual upload tab says the file input takes .json while it also accepts .xml.
  • DOC-3 (per-CI worked examples as sibling pages) is not attempted here.

Sequencing

The Cloud CLI sections describe 1.12.0, which publishes when codacy-cloud-cli#54 merges. Worth holding this until that release is on npm, or the version note will point at something npm install cannot get yet.

🤖 Generated with Claude Code

The tagging trade-off sat in an admonition below the tag list, four
screens from where the decision is made, and framed the 1,000-tag cap
as housekeeping.

- Add "How tagging affects your findings" before the setup section, with
  the rolling-vs-per-release comparison and the consequences the old
  admonition omitted: dismissals, owners and SLA clocks reset on every
  new tag.
- State what the cap actually does. Reaching it makes Codacy reject
  image tags it has not seen before, while existing tags carry on being
  scanned, so the release you just shipped silently stops being covered.
  Verified against ContainersDAO.scala:70-77 and reference.conf:115.
- Add worked pipeline examples for both strategies. Every command was
  executed, not just written.
- Correct two false bullets in the CI/CD section: nothing is detected or
  picked up automatically, you upload the image and tag you name.

The new "#how-tagging-affects-your-findings" anchor is the target the
Container Scanning designs link to from the manual setup caption and
from all three tag-limit banners.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@claudiacodacy
claudiacodacy requested a review from a team as a code owner September 22, 2026 10:49
@codacy-production

Copy link
Copy Markdown
Contributor

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Overall readability score: 54.1 (🟢 +0.12)

File Readability
container-scanning.md 80.17 (🟢 +9.44)
index.md 65.2 (🟢 +4.24)
uploading-container-image-sboms.md 73.36 (-)
View detailed metrics

🟢 - Shows an increase in readability
🔴 - Shows a decrease in readability

File Readability FRE GF ARI CLI DCRS
container-scanning.md 80.17 57.87 7.61 7.8 8.92 5.95
  🟢 +9.44 🟢 +8.86 🟢 +1.46 🟢 +1 🟢 +0.82 🟢 +0.89
index.md 65.2 48.2 9.21 10.5 11.19 7.04
  🟢 +4.24 🟢 +7.55 🟢 +0.44 🟢 +0.3 🟢 +0.87 🟢 +0.18
uploading-container-image-sboms.md 73.36 57.47 8.75 8.6 9.62 6.77
  - - - - - -

Averages:

  Readability FRE GF ARI CLI DCRS
Average 54.1 42.93 10.92 12.35 12.28 8
  🟢 +0.12 🟢 +0.11 🟢 +0.02 🟢 +0.02 🟢 +0.02 🟢 +0.01
View metric targets
Metric Range Ideal score
Flesch Reading Ease 100 (very easy read) to 0 (extremely difficult read) 60
Gunning Fog 6 (very easy read) to 17 (extremely difficult read) 8 or less
Auto. Read. Index 6 (very easy read) to 14 (extremely difficult read) 8 or less
Coleman Liau Index 6 (very easy read) to 17 (extremely difficult read) 8 or less
Dale-Chall Readability 4.9 (very easy read) to 9.9 (extremely difficult read) 6.9 or less

@codacy-production codacy-production Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull Request Overview

No merge-blocking issues were identified. Codacy reports the PR as up to standards, with no new issues or coverage findings. The recommended documentation validation scenarios are not represented by automated tests.

Test suggestions

  • Verify the tagging comparison explains rolling and per-release findings behavior, including dismissals, owners, SLA/MTTR, and historical tracking.
  • Verify the 1,000-tag limit behavior is documented, including acceptance of existing tags, rejection of unseen tags, and deletion guidance.
  • Verify the rolling-tag CI/CD example aliases the built image locally before running upload-sbom.
  • Verify the per-release CI/CD example uploads the versioned image tag and explains tag cleanup.
  • Verify outdated automatic-detection and automatic-tag-pickup claims are removed or corrected.
  • Verify manual upload guidance links to the tagging strategy section.
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Verify the tagging comparison explains rolling and per-release findings behavior, including dismissals, owners, SLA/MTTR, and historical tracking.
2. Verify the 1,000-tag limit behavior is documented, including acceptance of existing tags, rejection of unseen tags, and deletion guidance.
3. Verify the rolling-tag CI/CD example aliases the built image locally before running upload-sbom.
4. Verify the per-release CI/CD example uploads the versioned image tag and explains tag cleanup.
5. Verify outdated automatic-detection and automatic-tag-pickup claims are removed or corrected.
6. Verify manual upload guidance links to the tagging strategy section.
Low confidence findings
  • Consider adding automated documentation or snippet validation for the tagging guidance so future edits cannot regress the documented workflows and behavior.

TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback

@github-actions
github-actions Bot temporarily deployed to Netlify September 22, 2026 10:50 Inactive
Match the convention in codacy-api/examples/uploading-dast-results.md:
"Replace the placeholders with your own values" followed by a
description list, with the Git provider values in a table.

Only gh/gl/bb are listed. The DAST table also carries ghe/gle/bbe, but
codacy-cli-v2 documents three values for -p (upload_sbom.go:54), so the
enterprise rows are not copied across.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to Netlify September 22, 2026 10:54 Inactive
claudiacodacy and others added 2 commits September 22, 2026 11:59
Mirrors codacy-api/examples/uploading-dast-results.md, so container
scanning gets the same shape App scanning has: the feature page keeps
the concepts, a "!!! note" links out to the API example.

Covers uploadImageSbom, listImageTags and deleteImageTag. Delete is
worth documenting now because it is the only way to stay under the
1,000-tag cap in CI today: the Cloud CLI's --delete --keep-latest is
still an open PR.

Contract read from the generated client (SbomService.ts:227-280,
:286-345, :395-440) and the handler (SbomFilesHandler.uploadImageSbom):
multipart sbom/imageName/tag with optional repositoryName and
environment, 204 on success, 400 for the ContainerSbomError family.

The cap rejection is not one of those errors, so it falls through to the
generic handler rather than the 409 the swagger declares. The page tells
readers to match on the message instead of the status.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to Netlify September 22, 2026 11:02 Inactive
codacy-cloud-cli#49, #50 and #52 have merged and ship as 1.12.0 in the
pending release PR #54, so the commands are real and the docs no longer
have to route everything through the API.

codacy-cloud-cli/index.md gains two sections:

- "Manage container images" — images, image, --tag, --upload, --delete,
  and the 100/1000 limit defaults.
- "Keep container image tags under the organization limit" —
  --delete --keep-latest, --dry-run, the JSON shape, and the per-image
  vs organization-wide caveat the command warns about.

container-scanning.md's per-release example now runs the cleanup before
the upload, which is the order the backend forces: at the cap the upload
is rejected, so cleaning up afterwards strands the organization there.

Surface read from src/commands/image.ts and images.ts on origin/main,
not from the changeset prose. Token handling confirmed at
src/utils/auth.ts:171.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to Netlify September 22, 2026 11:09 Inactive
…[OD-707]

Two gaps, both raised against the bfi-finance thread in #product-help:
that organization is carrying ~1.5M container findings on ~970 of its
1,000 image tags, and nothing in the docs told them what to do about it.

"If your pipeline already produces an SBOM" adds the Cloud CLI upload
for both strategies, which the mockups draw as a tab but this page only
mentioned in passing. No docker tag alias is needed there: --upload
attaches a file to a tag and never resolves the image.

"Reducing findings on an image that already has many tags" is the
recovery path. Switching the tag a pipeline uploads to does nothing on
its own, because the tags already stored keep their findings and keep
being scanned nightly. Deleting a tag is what removes them: verified
through RemovedImageTag -> RemovedImageTagWriterStream ->
itemsDAO.deleteContainerScanItemsByImageTag, which deletes rather than
closes, and does so asynchronously.

Both new sections carry a token pointer, so the snippet harness is clean
on every block: the recovery reader arrives from a support conversation
rather than from step 1 of the setup page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to Netlify September 22, 2026 13:18 Inactive
Vale blocks in CI — it runs through reviewdog against the diff, so the
lines this PR adds have to be clean even though the files around them
are not. I had left the contraction errors on the grounds that Vale is
advisory, which docs-edit says but CI does not.

.vale.ini settles the underlying conflict with voice.md: the "do not"
style is explicitly scoped to the agent instruction files, and docs/**
is expected to contract.

Also replaces an inline `codacy images gh <organization>` with a fenced
block. IgnoredScopes covers code, but the <organization> token inside
the span still tripped Vale.Terms and Vale.Spelling in CI, and the
fenced form matches the rest of the section anyway.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to Netlify September 22, 2026 13:24 Inactive
Both options pointed at #example-pipeline-steps, which covers both, so
neither bullet led anywhere specific. The two examples are now sibling
#### headings with pinned ids, and each option links to its own.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1.12.0 shipped the commands but 404s on any namespaced image name, which
is the usual shape. codacy-cloud-cli#55 fixes the path encoding and
publishes as 1.12.1 in the pending release PR #56, so that is the floor
the examples here need.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@claudiacodacy
claudiacodacy enabled auto-merge (squash) September 22, 2026 13:53
@github-actions
github-actions Bot temporarily deployed to Netlify September 22, 2026 13:54 Inactive
@claudiacodacy
claudiacodacy merged commit e73d8c3 into master Sep 22, 2026
5 checks passed
@claudiacodacy
claudiacodacy deleted the docs-move-and-rewrite-the-image-tagging-guidance-and-state-od-707 branch September 22, 2026 13:54

This branch was previously deployed

1 inactive deployment
Netlify — e99c7257 Deployed Sep 22, 2026 by github-actions[bot]
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