Remove last runtime installs from .tekton/tasks/: - govulncheck (go install) → baked via GOBIN in tools-builder stage, copied to final - @fission-ai/openspec (npm install -g at runtime) → added to npm/package-lock.json (npm ci integrity), symlinked at /usr/local/bin/openspec Also: add GOVULNCHECK_VERSION ARG (default: latest), update VERSIONS.md, renovate.json (govulncheck + openspec tracking), README bundled tools list, and OCI description label. Tracked via forgejo-mcp-7g9: refactor into smaller images (P4, deferred).
5.2 KiB
release-tools image
A versioned, signed OCI image bundling the full toolchain needed to cut a forgejo-mcp release.
Purpose
The op1st Tekton release pipeline historically installed tools at Step runtime, causing three production failures (v2.24.0/1/2). This image bakes all tooling in once, version-pinned and cosign-signed, so release Steps simply consume a known-good image.
Bundled tools: go, goreleaser, syft, cosign, govulncheck, node, npm, jq, curl,
ca-certificates, @anthropic-ai/mcpb, @fission-ai/openspec
See VERSIONS.md for pinned versions and digest.
Image Tag Scheme
Tags follow release-tools/vMAJOR.MINOR.PATCH in this repository.
The published OCI tag is vMAJOR.MINOR.PATCH at the agreed registry.
| Bump | Triggers |
|---|---|
| MAJOR | base image swap, removed tool, moved binary path, breaking CLI change, shell removed |
| MINOR | new tool added, Hummingbird base MINOR bump, Go version bump within same major, tool MINOR bump |
| PATCH | tool PATCH bumps, security backports, rebuild with no contract change |
Pulling the Image
podman pull codeberg.org/operate-first/release-tools:v1.0.0
# or by digest (preferred for reproducibility):
podman pull codeberg.org/operate-first/release-tools@sha256:<digest>
Consumers SHOULD pin by full vMAJOR.MINOR.PATCH tag or by digest for maximum stability.
Verifying the Cosign Signature
The published image is signed with the op1st cosign key (same key used for forgejo-mcp release
artifacts). The normative key source is the
op1st-emea-b4mad
GitOps repo — same source that provisions the cosign-signing-key Secret in op1st-pipelines.
# Fetch the public key pinned to a specific commit (avoids mutable-branch trust-root drift).
curl -sSfL -o cosign.pub \
https://codeberg.org/operate-first/op1st-emea-b4mad/raw/commit/8a3c55e5b8c892754fd61f9141dc4817a6915f45/manifests/applications/op1st-pipelines-tokens/cosign-signing-key.pub
cosign verify \
--key cosign.pub \
codeberg.org/operate-first/release-tools:v1.0.0
Expected output: Verification for codeberg.org/operate-first/release-tools:v1.0.0 -- The following checks were performed on each of these signatures: ...
Update the commit SHA when the signing key rotates (see the op1st-emea-b4mad rotation runbook).
Running Locally
# Run all tools version check
podman run --rm codeberg.org/operate-first/release-tools:v1.0.0 \
sh -c 'go version && syft version && goreleaser --version && cosign version && jq --version && curl --version && node --version'
# Run goreleaser in release mode
podman run --rm \
-v $(pwd):/workspace:z \
-w /workspace \
codeberg.org/operate-first/release-tools:v1.0.0 \
goreleaser release --clean
Building Locally
Use build.sh to reproduce the image build without pushing:
bash image/release-tools/build.sh
This mirrors the PR pipeline build step. Requires podman and git.
Verifying Tool Versions (local image)
bash image/release-tools/verify.sh
Runs the locally built image and asserts all tool versions match the pins in VERSIONS.md.
Bumping Versions
- Edit VERSIONS.md with the new version string(s).
- If bumping
@anthropic-ai/mcpb: regenerate the lockfile:cd image/release-tools/npm npm install --package-lock-only - Rebuild and verify locally:
bash image/release-tools/build.sh && bash image/release-tools/verify.sh - Open a PR. The PR build pipeline fires automatically when files under
image/release-tools/change (CEL-gated).
Renovate manages automated bump PRs. Manual review is required for all bumps — see renovate.json.
Lift-Out to a Separate Project
The image source is structurally isolated so it can be moved to a dedicated repository via:
git mv image/release-tools/ .tekton/release-tools/ <new-repo>/- Register the new repository as a PaC
RepositoryCR inop1st-pipelines. - Ensure
cosign-signing-keySecret is accessible in the new namespace (extend the emberstack reflector ruleset or keep PipelineRuns inop1st-pipelines). - Update the registry path string in
on-tag-publish.yamlif publishing to a different registry. - Update ADR cross-references in
docs/design/release-pipeline-migration.mdto point at the new location.
No Go code in operation/, pkg/, cmd/, or main.go is affected.
Architecture
image/release-tools/
Containerfile # Multi-stage build (tools-builder + final stage)
VERSIONS.md # Single source of truth for all pinned versions
renovate.json # Renovate bump config
.dockerignore # Narrows build context to image/release-tools/ only
build.sh # Local build script (no push)
verify.sh # Local verification script
npm/
package.json # @anthropic-ai/mcpb dependency declaration
package-lock.json # Lockfile with integrity hashes for all transitive deps
.tekton/release-tools/
on-pull-request-build.yaml # PR build pipeline (CEL-gated to image tree)
on-tag-publish.yaml # Tag publish pipeline (CEL-gated to release-tools/v* tags)