Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/cli-version-checker.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 25 additions & 24 deletions .github/workflows/cli-version-checker.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ evals:
- id: cli_versions_checked
question: Did the agent check for new versions of agentic CLI tools (Claude Code, GitHub Copilot CLI, Codex, MCP servers, etc.)?
- id: docker_images_checked
question: Did the agent check for new versions of Docker images in pkg/cli/docker_images.go (actionlint, syft, grype, grant, zizmor, poutine, runner-guard, yamllint)?
question: Did the agent check for new versions and digest changes of Docker images in pkg/cli/docker_images.go (actionlint, syft, grype, grant, zizmor, poutine, runner-guard, yamllint)?
- id: updates_applied_or_noop
question: Were version updates applied and a PR created, or was noop used when all tools were already up to date?
question: Were version or digest updates applied and a PR created, or was noop used when all tools were already up to date?
---

# CLI Version Checker
Expand All @@ -57,9 +57,9 @@ Monitor and update agentic CLI tools: Claude Code, GitHub Copilot CLI, OpenAI Co
**EFFICIENCY FIRST**: Before starting:
1. Check cache-memory at `/tmp/gh-aw/cache-memory/` for previous version checks and help outputs
2. If cached versions exist and are recent (< 24h), verify if updates are needed before proceeding
3. If no version changes detected, exit early with success
3. If no CLI version, Docker image version, or Docker image digest changes are detected, exit early with success

**CRITICAL**: If ANY version changes are detected, you MUST create an issue using safe-outputs.create-issue. Do not skip issue creation even for minor updates.
**CRITICAL**: If ANY version or digest changes are detected, you MUST create an issue using safe-outputs.create-issue. Do not skip issue creation even for minor updates.

For each CLI/MCP server:
1. Fetch latest version from NPM registry or GitHub releases (use npm view commands for package metadata)
Expand Down Expand Up @@ -159,7 +159,7 @@ For each CLI tool update, install (`npm install -g <package>@<version>`), run `-

### Update Process
1. Edit `./pkg/constants/constants.go` with new CLI version(s)
2. Edit `./pkg/cli/docker_images.go` with new Docker image version(s) and digest(s) (if any Docker images were updated)
2. Edit `./pkg/cli/docker_images.go` with new Docker image version(s) and digest(s), including digest-only changes where the tag is unchanged
3. Run `make fmt` after editing any Go files
4. **REQUIRED**: Run `make recompile` in the **foreground** — do NOT background it with `&` or follow it with `sleep`. Wait for it to finish completely before proceeding. Example: `make recompile && echo "done"`.
5. Verify changes with `git status`
Expand Down Expand Up @@ -200,37 +200,37 @@ For each updated CLI, include: version old → new, release timeline, changes ca

## Docker Image Version Checking

After checking CLI tools, also check the Docker images defined in `./pkg/cli/docker_images.go` for updates.
After checking CLI tools, also check the Docker images defined in `./pkg/cli/docker_images.go` for version and digest updates. Resolve the registry digest for every image on every run and compare it with the digest pinned in the Go constant. A changed digest is an update even when the image tag is unchanged.

### Docker Image Sources

Fetch the latest release for each image from its GitHub repository:

| Constant | Current image | GitHub releases URL |
|---|---|---|
| `ActionlintImage` | `rhysd/actionlint:<version>` | `https://api.github.com/repos/rhysd/actionlint/releases/latest` |
| `ActionlintImage` | `rhysd/actionlint:<version>@sha256:<digest>` | `https://api.github.com/repos/rhysd/actionlint/releases/latest` |
| `SyftImage` | `anchore/syft:<version>@sha256:<digest>` | `https://api.github.com/repos/anchore/syft/releases/latest` |
| `GrypeImage` | `anchore/grype:<version>@sha256:<digest>` | `https://api.github.com/repos/anchore/grype/releases/latest` |
| `GrantImage` | `anchore/grant:<version>@sha256:<digest>` | `https://api.github.com/repos/anchore/grant/releases/latest` |
| `ZizmorImage` | `ghcr.io/zizmorcore/zizmor:latest` | `https://api.github.com/repos/zizmorcore/zizmor/releases/latest` |
| `PoutineImage` | `ghcr.io/boostsecurityio/poutine:latest` | `https://api.github.com/repos/boostsecurityio/poutine/releases/latest` |
| `RunnerGuardImage` | `ghcr.io/vigilant-llc/runner-guard:latest` | `https://api.github.com/repos/vigilant-llc/runner-guard/releases/latest` |
| `YamllintImage` | `pipelinecomponents/yamllint:latest` | `https://api.github.com/repos/PipelineComponents/yamllint/releases/latest` |
| `ZizmorImage` | `ghcr.io/zizmorcore/zizmor:<version>@sha256:<digest>` | `https://api.github.com/repos/zizmorcore/zizmor/releases/latest` |
| `PoutineImage` | `ghcr.io/boostsecurityio/poutine:<version>@sha256:<digest>` | `https://api.github.com/repos/boostsecurityio/poutine/releases/latest` |
| `RunnerGuardImage` | `ghcr.io/vigilant-llc/runner-guard:<version>@sha256:<digest>` | `https://api.github.com/repos/vigilant-llc/runner-guard/releases/latest` |
| `YamllintImage` | `pipelinecomponents/yamllint:<version>@sha256:<digest>` | `https://api.github.com/repos/PipelineComponents/yamllint/releases/latest` |

**Optimization**: Fetch all GitHub release endpoints in parallel in a single turn.

### 3-Day Cooldown

Before considering any Docker image update, check that the release is **at least 3 days old**:
Before considering any Docker image version update, check that the release is **at least 3 days old**:
1. Parse the `published_at` field from the GitHub releases API response.
2. Compute `(current date) - published_at`. If less than 3 days, **skip** that image — do not update it or include it in the issue.
3. Only proceed with images whose latest release is ≥ 3 days old.

This avoids picking up immature or quickly-retracted releases.
This avoids picking up immature or quickly-retracted releases. Digest-only updates for an already-pinned version are not subject to the release cooldown.

### Fetching the Container SHA

For each Docker image that has a newer version (and passed the 3-day cooldown), fetch its digest:
For every Docker image, fetch the registry digest for the target tag. For a newer version, apply the 3-day cooldown first. Also fetch and compare the digest when the version is unchanged so mutable or republished tags are reflected in `docker_images.go`.

**Docker Hub images** (actionlint, syft, grype, grant, yamllint):
```bash
Expand Down Expand Up @@ -265,38 +265,39 @@ curl -sI \

**CRITICAL**: Always record the digest as `sha256:<hex>`. This is the value that goes after `@` in the image reference.

### Updating docker_images.go
### Comparing and Updating docker_images.go

After fetching the new version and digest, edit `./pkg/cli/docker_images.go`:
Compare each fetched digest with the `@sha256:...` value in `./pkg/cli/docker_images.go`. If the constant has no digest, treat it as needing an update. Edit the file whenever the version or digest differs:

- **Versioned images with existing digest** (syft, grype, grant): update both the version tag and the `@sha256:...` digest in the existing string format, e.g.:
- **All images**: pin the selected version tag and registry digest in the existing string format, e.g.:
```
SyftImage = "anchore/syft:v1.49.0@sha256:<new-digest>"
```
- **Versioned images without digest** (actionlint): update only the version tag, e.g.:
- **Digest-only changes**: preserve the current version tag and replace only the digest, e.g.:
```
ActionlintImage = "rhysd/actionlint:1.7.13"
ActionlintImage = "rhysd/actionlint:1.7.13@sha256:<new-digest>"
```
- **Images currently tagged `:latest`** (zizmor, poutine, runner-guard, yamllint): **pin** them to the new versioned tag with digest, e.g.:
- **Images currently tagged `:latest`**: replace `latest` with the latest stable release tag that passed the cooldown and pin its digest, e.g.:
```
ZizmorImage = "ghcr.io/zizmorcore/zizmor:v1.0.0@sha256:<digest>"
```

### Docker Image Update Process

1. Fetch all latest releases in parallel via `api.github.com`.
2. Apply the 3-day cooldown — skip any image whose release is < 3 days old.
3. For images with a passing release, fetch the container digest (see "Fetching the Container SHA" above).
4. Edit `./pkg/cli/docker_images.go` with the new version(s) and digest(s).
2. Apply the 3-day cooldown to version updates — skip a newer release if it is < 3 days old.
3. Fetch the container digest for every selected tag, including unchanged versions (see "Fetching the Container SHA" above).
4. Compare each fetched digest with `./pkg/cli/docker_images.go` and edit the constant for version changes, digest changes, or missing digests.
5. Run `make fmt` to format any changed Go files.
6. Include Docker image update details in the issue created by safe-outputs.

### Docker Image Section in the Issue

For each updated Docker image, include:
- Image name and constant (e.g., `SyftImage`)
- Version change: old → new
- Version change: old → new (or "unchanged" for a digest-only update)
- Release date and cooldown confirmation (e.g., "Released 2026-07-20 — 5 days ago, cooldown passed")
- Digest change: old digest → new digest (or "missing → new digest")
- Container digest (e.g., `sha256:abc123...`)
- Full image reference: `anchore/syft:v1.49.0@sha256:abc123...`
- Link to the GitHub release
Expand Down