forgejo-mcp/.tekton/tasks/cosign-sign-release.yaml
Christoph Görn 763366673a
fix: 🔒️ repoint cosign-sign-release task at cosign-signing-key-artifacts
Switch artifact signing from the shared cosign-signing-key to the
purpose-named cosign-signing-key-artifacts Secret (same key material,
no rotation). Completes the isolation split from op1st-emea-b4mad-yn5.

Gate: merge only after cosign-signing-key-artifacts is reflected in
op1st-pipelines (op1st-emea-b4mad PR landed 2026-05-26).

Closes op1st-emea-b4mad-ueq. Related: forgejo-mcp-j52.
2026-05-26 11:06:06 +02:00

116 lines
4 KiB
YAML

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: cosign-sign-release
annotations:
tekton.dev/displayName: "cosign sign-blob checksums + upload to Codeberg release"
spec:
description: |
Signs the GoReleaser-produced `checksums.txt` with cosign (key from the
`cosign-signing-key-artifacts` Secret) and uploads the resulting `.sig` as a
release asset. Signing the checksum file covers all archives + SBOMs
transitively via the checksum chain.
Skipped (exit 0) if the cosign secret is empty/missing — mirrors the
behavior of .forgejo/workflows/release.yml so releases continue to ship
if signing infrastructure is unavailable.
The `cosign-signing-key-artifacts` Secret is provisioned in op1st-pipelines
upstream of this Task (typically via the op1st-gitops repo + emberstack
reflector). Expected keys: cosign.key, cosign.password, cosign.pub.
All tools (cosign, jq, curl) are pre-baked into RELEASE_TOOLS_IMAGE.
No runtime installs.
params:
- name: RELEASE_TOOLS_IMAGE
description: |
Pre-built release-tools image containing go, goreleaser, syft, cosign,
govulncheck, node, npm, jq, curl, mcpb, and openspec.
type: string
default: codeberg.org/operate-first/release-tools:latest
- name: TAG
description: Tag ref name (e.g. v2.24.0).
type: string
- name: REPO
description: Repo slug owner/name (e.g. goern/forgejo-mcp).
type: string
- name: CODEBERG_API
description: Codeberg API base URL.
type: string
default: https://codeberg.org/api/v1
workspaces:
- name: source
mountPath: /workspace/src
stepTemplate:
workingDir: $(workspaces.source.path)
steps:
- name: sign-checksums
image: $(params.RELEASE_TOOLS_IMAGE)
env:
- name: COSIGN_PRIVATE_KEY
valueFrom:
secretKeyRef:
name: cosign-signing-key-artifacts
key: cosign.key
optional: true
- name: COSIGN_PASSWORD
valueFrom:
secretKeyRef:
name: cosign-signing-key-artifacts
key: cosign.password
optional: true
script: |
#!/usr/bin/env sh
set -eu
if [ -z "${COSIGN_PRIVATE_KEY:-}" ]; then
echo "WARN: COSIGN_PRIVATE_KEY not set; skipping signature step."
exit 0
fi
TAG="$(params.TAG)"
VERSION="${TAG#v}"
CHECKSUMS="dist/forgejo-mcp_${VERSION}_checksums.txt"
if [ ! -f "$CHECKSUMS" ]; then
echo "ERROR: Expected $CHECKSUMS not produced by GoReleaser" >&2
exit 1
fi
SIG="${CHECKSUMS}.sig"
KEY_FILE="$(mktemp)"
trap 'rm -f "$KEY_FILE"' EXIT
printf '%s' "$COSIGN_PRIVATE_KEY" > "$KEY_FILE"
cosign sign-blob --yes \
--key "$KEY_FILE" \
--bundle "$SIG" \
"$CHECKSUMS"
ls -l "$SIG"
- name: upload-signature
image: $(params.RELEASE_TOOLS_IMAGE)
env:
- name: GITEA_TOKEN
valueFrom:
secretKeyRef:
name: op1st-release-token
key: token
script: |
#!/usr/bin/env bash
set -euo pipefail
TAG="$(params.TAG)"
VERSION="${TAG#v}"
SIG="dist/forgejo-mcp_${VERSION}_checksums.txt.sig"
if [ ! -f "$SIG" ]; then
echo "INFO: No signature file present; signing step was skipped."
exit 0
fi
RELEASE_ID=$(curl -fsSL \
-H "Authorization: token ${GITEA_TOKEN}" \
"$(params.CODEBERG_API)/repos/$(params.REPO)/releases/tags/${TAG}" \
| jq -r '.id')
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then
echo "ERROR: Could not resolve release ID for tag ${TAG}" >&2
exit 1
fi
ASSET_NAME=$(basename "$SIG")
curl -fsSL -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-F "attachment=@${SIG}" \
"$(params.CODEBERG_API)/repos/$(params.REPO)/releases/${RELEASE_ID}/assets?name=${ASSET_NAME}"