Skip to content

Pin freshness audit

Pin freshness audit #3

name: Pin freshness audit
# Validates that every action pin (workflow + composite) still resolves
# upstream — closes the silently-deprecated-tag class. Complements the
# shape-only `Action pinning audit` job in ci.yml (which checks pin
# *shape* on every PR; this checks pin *freshness* on a schedule).
#
# Schedule: weekly + workflow_dispatch. Not on every PR — rate-limit
# aware (5000 req/hr per token, this audit costs ~70 req/run) and not
# blocking. Findings are surfaced as `::warning::` annotations and (when
# any are found) auto-file an issue tagged `harness,security`.
#
# Script + 15 unit tests live in
# `.github/scripts/check_pin_freshness.py` + `tests/test_check_pin_freshness.py`.
on:
schedule:
# Monday 06:00 UTC — alongside artifact-cleanup. Avoids weekend
# noise; weekly cadence is enough for a non-blocking gate.
- cron: "0 6 * * 1"
workflow_dispatch:
inputs:
strict:
description: "Run in strict mode (findings → errors, exit 1)"
type: boolean
default: false
permissions:
contents: read
issues: write
jobs:
audit:
name: Pin freshness audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.14"
- name: Run pin-freshness audit
id: audit
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PIN_FRESHNESS_STRICT: ${{ inputs.strict && '1' || '' }}
run: python .github/scripts/check_pin_freshness.py
- name: File issue on findings
# Only fire when default-mode (warn) found something — strict mode
# already failed the workflow and operator attention is automatic.
if: >
always() &&
steps.audit.outputs.findings_count != '0' &&
steps.audit.outputs.findings_count != ''
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FINDINGS: ${{ steps.audit.outputs.findings_count }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
set -euo pipefail
gh issue create \
--title "chore: pin-freshness audit found ${FINDINGS} stale pin(s)" \
--label "harness,security" \
--body "$(cat <<EOF
The weekly pin-freshness audit flagged ${FINDINGS} stale pin(s).
See the run log for the per-pin annotations: ${RUN_URL}
Each finding is one of:
- **Tag pin no longer resolves** — upstream tag was deleted or renamed; bump to a current tag or SHA pin per \`docs/DEVELOPMENT.md#action-pinning-policy\`.
- **SHA pin: documented tag re-tagged** — the trailing \`# vN.M.P\` comment names a tag that now points at a different SHA upstream. Either bump the pin to the new SHA (preferred) or update the comment to a tag that still matches.
- **API failure** — couldn't reach the upstream registry; transient, will likely clear on the next weekly run.
Closes when the offending pin is updated and the next audit run is clean.
EOF
)"