Skip to content

Publish only :latest; consumer skill watches digest#10

Merged
nirmalgupta merged 1 commit into
mainfrom
feat/latest-only-publish
Jun 2, 2026
Merged

Publish only :latest; consumer skill watches digest#10
nirmalgupta merged 1 commit into
mainfrom
feat/latest-only-publish

Conversation

@nirmalgupta
Copy link
Copy Markdown
Member

Summary

Switch the release model from "per-version tag + :latest" to ":latest only, identity = digest". Old versioned tags accumulate as noise on Docker Hub; each `publish` creates a new immutable digest that the consumer skill picks up.

What changed

  • `security-scan.sh publish`: drop the positional `[vX.Y.Z]` arg; push only `leverj/security-scan:latest`. Keep the pyproject/manifest version-alignment check — the `version` field inside the manifest is still the human-readable identifier (shown in upgrade prompts), just not a docker tag. After push, print the resulting digest so you can confirm the skill will see it.
  • README + spec §15 + §16: updated for the new flow. Rollback becomes "pin a specific digest in the consumer's state" — the skill already stores `pinned_digest` for that.
  • Version bumped `0.2.2` → `0.2.3` (pyproject, `init.py`, manifest). Manifest changelog leads with the release-flow note.

Existing v0.2.0 / v0.2.1 / v0.2.2 tags on Docker Hub aren't touched — they stay for historical reference. Nothing publishes new versioned tags going forward.

Companion change (ai-skills)

A separate commit will update the `feat/security-scan-skill` branch over in `leverj/ai-skills` so the SKILL.md uses digest comparison (querying Docker Hub's tags/latest endpoint or `docker manifest inspect` for `.images[0].digest`) instead of listing tags.

Test plan

  • 221 tests pass.
  • `./security-scan.sh publish --help` reflects the new (simpler) flag set.
  • `./security-scan.sh publish --no-push` end-to-end: version check passes, multi-arch buildx with SBOM + provenance succeeds, prints "built locally (not pushed): leverj/security-scan:latest (version label: 0.2.3)".
  • Post-merge: `./security-scan.sh publish` to push v0.2.3 as the new `:latest` digest.

🤖 Generated with Claude Code

Switch the release model from "per-version tag + :latest" to ":latest only,
identity = digest". Old versioned tags would just accumulate noise on Docker
Hub; each `publish` creates a new immutable image digest that the consumer
skill picks up via the registry API.

  ./security-scan.sh publish        # builds multi-arch, pushes leverj/security-scan:latest
  ./security-scan.sh publish --no-push       # release dry-run, build only

What changed:

- security-scan.sh: drop the [vX.Y.Z] positional arg and the versioned-tag
  output entirely. Push only :latest. Keep the pyproject/manifest version-
  alignment check — the `version` label inside the manifest is still the
  human-readable identifier, just not a docker tag anymore. After push,
  print the resulting image digest so the maintainer can confirm the skill
  will see it.

- README + spec §15 + §16: updated to describe the new flow. Rollback
  becomes "pin a specific digest in the consumer's state" — the skill
  already stores pinned_digest for this.

- pyproject.toml + __init__.py + manifest version bumped 0.2.2 -> 0.2.3.

- Manifest changelog leads with the 0.2.3 release-flow note so the skill
  surfaces it on the upgrade prompt.

Existing v0.2.0 / v0.2.1 / v0.2.2 tags on Docker Hub are not touched —
they remain for historical reference. Nothing publishes new versioned
tags going forward.

Verified: 221 tests pass; ./security-scan.sh publish --no-push runs end-
to-end with SBOM + provenance against the multi-arch builder.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 2, 2026 20:42
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR changes the release/publish model for the leverj/security-scan Docker image: instead of pushing both vX.Y.Z and :latest, it now publishes only :latest and treats the image digest as the immutable identity that consumers watch.

Changes:

  • Update security-scan.sh publish to remove version/tag arguments, always push :latest, and print the resulting digest after publish.
  • Update docs/spec to describe digest-based release detection and rollback via digest pinning.
  • Bump the scanner’s human-readable version from 0.2.20.2.3 across code + manifest.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
security-scan.sh Drops versioned tag publishing, enforces version alignment, pushes :latest, and attempts to surface the pushed digest.
security-scan-spec.md Updates the image contract and release workflow docs to match digest-identity + :latest-only publishing.
SECURITY-SCAN-MANIFEST.yaml Bumps manifest version/release notes to 0.2.3 and documents the new publish flow in changelog.
security_scan/init.py Bumps package __version__ to 0.2.3.
README.md Updates publish instructions and rationale for :latest-only + digest identity.
pyproject.toml Bumps project version to 0.2.3.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread security-scan.sh
Comment on lines +234 to +237
# Surface the new digest so the user can verify the skill picks it up.
local digest
digest="$(docker buildx imagetools inspect "$image_latest" 2>/dev/null | grep -E '^Digest:' | head -1 | awk '{print $2}')"
[[ -n "$digest" ]] && echo "digest: $digest"
@nirmalgupta nirmalgupta merged commit 5f89162 into main Jun 2, 2026
3 checks passed
@nirmalgupta nirmalgupta deleted the feat/latest-only-publish branch June 2, 2026 20:56
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