diff --git a/skills/github-release/checkpoints.yaml b/skills/github-release/checkpoints.yaml index 9c913ab..2aa6d93 100644 --- a/skills/github-release/checkpoints.yaml +++ b/skills/github-release/checkpoints.yaml @@ -3,102 +3,125 @@ skill_id: github-release preconditions: - type: file_exists - path: ".git" - message: "Must be inside a git repository" + target: ".git" mechanical: # Release workflow checks - id: GR-1 type: file_exists + target: ".github/workflows/release.yml" severity: error desc: "Release workflow must exist" - path: ".github/workflows/release.yml" - id: GR-2 type: contains + target: ".github/workflows/release.yml" + pattern: "tags:" severity: error desc: "Release workflow must trigger on version tags" - path: ".github/workflows/release.yml" - content: "tags:" - id: GR-3 type: contains + target: ".github/workflows/release.yml" + pattern: "id-token: write" severity: error desc: "Release workflow must have id-token write permission for signing" - path: ".github/workflows/release.yml" - content: "id-token: write" - id: GR-4 type: contains + target: ".github/workflows/release.yml" + pattern: "attestations: write" severity: error desc: "Release workflow must have attestations write permission" - path: ".github/workflows/release.yml" - content: "attestations: write" - id: GR-5 type: contains - severity: warning - desc: "Release workflow should have workflow_dispatch for manual triggers" - path: ".github/workflows/release.yml" - content: "workflow_dispatch" + target: ".github/workflows/release.yml" + pattern: "workflow_dispatch" + severity: info + desc: >- + Release workflow may have workflow_dispatch for manual triggers (info + only — netresearch skill-repo release workflow is intentionally + tag-push-only because workflow_dispatch + auto-bump produced unsigned + tags. Inline workflows that build on it can opt-in safely). # Tag integrity checks - id: GR-6 type: command + pattern: "test -z \"$(git for-each-ref refs/tags/v* --format='%(objecttype) %(refname:short)' | grep -v '^tag ')\"" severity: error - desc: "All version tags must be annotated (not lightweight)" - command: "test -z \"$(git for-each-ref refs/tags/v* --format='%(objecttype) %(refname:short)' | grep '^commit ')\"" + desc: >- + All version tags must be annotated (not lightweight). The `grep -v` + pipeline emits any tag whose objecttype is NOT `tag` (i.e. lightweight + commit-tags). Wrapping in `test -z "$(...)"` makes the command exit 0 + only when the pipeline is empty — i.e. all tags are annotated, or no + tags exist at all. # Version sync checks - id: GR-7 type: command + pattern: "vendor/bin/validate-pre-release.sh --version-sync-only 2>/dev/null" severity: warning - desc: "Version files must be in sync" - command: "${CLAUDE_PLUGIN_ROOT}/skills/github-release/scripts/validate-pre-release.sh --version-sync-only 2>/dev/null" + desc: >- + Version files must be in sync. Requires the github-release skill's + validate-pre-release.sh to be installed at vendor/bin/ (the runner's + command whitelist disallows ${CLAUDE_PLUGIN_ROOT} paths). # CHANGELOG checks - id: GR-8 type: contains + target: "CHANGELOG.md" + pattern: "[Unreleased]" severity: warning desc: "CHANGELOG.md must have an Unreleased section" - path: "CHANGELOG.md" - content: "[Unreleased]" # Supply chain security checks - id: GR-9 type: command + pattern: "gh release view --json assets --jq -e 'any(.assets[].name; test(\"sbom\"))' >/dev/null 2>&1" severity: warning - desc: "Latest published release should have SBOM assets" - command: "gh release view --json assets --jq '[.assets[].name | select(test(\"sbom\"))] | length > 0' 2>/dev/null || echo true" + desc: >- + Latest published release should have SBOM assets. `jq -e` exits with + code 1 when no asset name matches, so the runner sees a real failure + instead of a literal "false" stdout that would otherwise count as a + successful zero-exit. - id: GR-10 type: command + pattern: "gh release view --json assets --jq -e '[.assets[].name] as $n | ($n|any(test(\"\\\\.bundle$\"))) or ($n|any(test(\"\\\\.sig$\")) and ($n|any(test(\"\\\\.pem$\"))))' >/dev/null 2>&1" severity: warning - desc: "Latest published release should have cosign signature bundles" - command: "gh release view --json assets --jq '[.assets[].name | select(test(\"\\.bundle$\"))] | length > 0' 2>/dev/null || echo true" + desc: >- + Latest published release should have cosign signature artefacts: + either a modern `.bundle` (Sigstore bundle), or BOTH a detached `.sig` + and matching `.pem` certificate (used by netresearch/skill-repo-skill + release workflow). A lone `.sig` or lone `.pem` is incomplete and + fails. `jq -e` ensures the boolean is reflected in the exit code. - id: GR-11 type: command + pattern: "git config user.signingkey >/dev/null 2>&1" severity: info - desc: "Git signing is configured" - command: "git config user.signingkey >/dev/null 2>&1 || git config gpg.format >/dev/null 2>&1" + desc: "Git signing is configured (signing key set)" # Release pipeline integrity checks - id: GR-12 type: command + pattern: "vendor/bin/validate-reusable-workflows.sh" severity: error desc: >- Reusable-workflow reference in `.github/workflows/release*.yml` files - (override the default glob via the WORKFLOW_GLOB env var) points to a - path that no longer exists at the pinned SHA. Release workflow will - fail on tag push. Update the ref or remove the job. - command: "${CLAUDE_PLUGIN_ROOT}/skills/github-release/scripts/validate-reusable-workflows.sh" + points to a path that no longer exists at the pinned SHA. Release + workflow will fail on tag push. Update the ref or remove the job. + Requires the validator at vendor/bin/. - id: GR-13 type: command + pattern: "vendor/bin/check-changelog-links.py" severity: warning - desc: "CHANGELOG.md reference-style header [X.Y.Z] missing matching [X.Y.Z]: footer link. Add the link entry and update the [Unreleased]: compare/vX.Y.Z...HEAD range to the new version." - command: "python3 ${CLAUDE_PLUGIN_ROOT}/skills/github-release/scripts/check-changelog-links.py" + desc: >- + CHANGELOG.md reference-style header [X.Y.Z] missing matching + [X.Y.Z]: footer link. Add the link entry and update the + [Unreleased]: compare/vX.Y.Z...HEAD range to the new version. llm_reviews: - id: GR-R1