Skip to content

fix(ci): reuse product CI provenance across metadata descendants #46

fix(ci): reuse product CI provenance across metadata descendants

fix(ci): reuse product CI provenance across metadata descendants #46

name: SpecSync trusted lifecycle policy
on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review]
permissions:
contents: read
pull-requests: read
concurrency:
group: specsync-trusted-policy-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
policy:
name: Inspect trusted lifecycle policy
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check out the immutable base workflow revision
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.workflow_sha }}
fetch-depth: 0
persist-credentials: false
- name: Verify the candidate without checking it out
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PR_NUMBER: ${{ github.event.pull_request.number }}
TRUSTED_WORKFLOW_SHA: ${{ github.workflow_sha }}
shell: bash
run: |
set -euo pipefail
if [[ ! "$BASE_SHA" =~ ^[0-9a-f]{40}$ \
|| ! "$HEAD_SHA" =~ ^[0-9a-f]{40}$ \
|| ! "$TRUSTED_WORKFLOW_SHA" =~ ^[0-9a-f]{40}$ \
|| ! "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
echo "The pull-request target payload contains an invalid immutable identity." >&2
exit 1
fi
if [[ "$(git rev-parse HEAD)" != "$TRUSTED_WORKFLOW_SHA" ]]; then
echo "The trusted checkout does not match github.workflow_sha." >&2
exit 1
fi
if [[ "$BASE_SHA" != "$TRUSTED_WORKFLOW_SHA" ]]; then
echo "The PR base and trusted workflow revision are not the same commit." >&2
exit 1
fi
git fetch --no-tags --no-recurse-submodules origin \
"+refs/pull/${PR_NUMBER}/head:refs/specsync/candidate"
if [[ "$(git rev-parse refs/specsync/candidate)" != "$HEAD_SHA" ]]; then
echo "Fetched candidate object does not match the event head SHA." >&2
exit 1
fi
changed="${RUNNER_TEMP}/specsync-trusted-policy-paths.txt"
git diff --name-only --no-renames -z "$BASE_SHA" "$HEAD_SHA" > "$changed"
protected="${RUNNER_TEMP}/specsync-protected-policy-paths.txt"
python3 - "$changed" "$protected" <<'PY'
import pathlib
import re
import sys
pattern = re.compile(rb'^(fledge\.toml|action\.(yml|yaml)|\.github/workflows/[^/]*\.(yml|yaml)|\.github/actions(/[^/]*)*|\.github/scripts/(classify-ci-paths|test-classify-ci-paths|test-lifecycle-workflows)\.sh|\.github/scripts/(lifecycle-validation-limits\.json|(test-)?verify-(archive-introduction|trusted-policy-check)\.py|(test-)?validate-release-candidate\.py)|\.specsync/workflow-v2-baseline\.json)$')
paths = pathlib.Path(sys.argv[1]).read_bytes().split(b"\0")
protected = [path for path in paths if path and pattern.fullmatch(path)]
payload = b"\0".join(protected) + (b"\0" if protected else b"")
pathlib.Path(sys.argv[2]).write_bytes(payload)
PY
if [[ -s "$protected" ]]; then
echo "This PR changes the SHA-pinned SpecSync trust policy:" >&2
python3 - "$protected" <<'PY' >&2
import pathlib
import sys
for path in pathlib.Path(sys.argv[1]).read_bytes().split(b"\0"):
if path:
print(f" - {path!r}")
PY
echo "Policy changes require a separately pinned GitHub required-workflow update; optimized lifecycle reuse is forbidden." >&2
exit 1
fi
echo "Trusted lifecycle policy revision: ${TRUSTED_WORKFLOW_SHA}"
echo "Candidate inspected as Git objects only: ${HEAD_SHA}"
echo "No protected lifecycle policy file changed."
publish:
name: Publish trusted lifecycle policy result
needs: policy
if: always()
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
checks: write
steps:
- name: Publish the exact revision-bound check
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
PR_NUMBER: ${{ github.event.pull_request.number }}
POLICY_RESULT: ${{ needs.policy.result }}
TRUSTED_WORKFLOW_SHA: ${{ github.workflow_sha }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
shell: bash
run: |
set -euo pipefail
conclusion=failure
title="Trusted lifecycle policy blocked"
if [[ "$POLICY_RESULT" == "success" ]]; then
conclusion=success
title="Trusted lifecycle policy unchanged"
fi
summary="$(
printf '%s\n' \
"PR #${PR_NUMBER} candidate: \`${HEAD_SHA}\`" \
"Base commit: \`${BASE_SHA}\`" \
"Trusted workflow revision: \`${TRUSTED_WORKFLOW_SHA}\`" \
"Policy inspection: \`${POLICY_RESULT}\`"
)"
payload="${RUNNER_TEMP}/specsync-trusted-policy-check.json"
jq -n \
--arg name "SpecSync trusted policy" \
--arg head_sha "$HEAD_SHA" \
--arg external_id "specsync-trusted-policy:${TRUSTED_WORKFLOW_SHA}:${HEAD_SHA}" \
--arg details_url "$RUN_URL" \
--arg conclusion "$conclusion" \
--arg title "$title" \
--arg summary "$summary" \
'{
name: $name,
head_sha: $head_sha,
status: "completed",
conclusion: $conclusion,
external_id: $external_id,
details_url: $details_url,
output: {title: $title, summary: $summary}
}' > "$payload"
gh api --method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"repos/${REPOSITORY}/check-runs" \
--input "$payload"
if [[ "$conclusion" != "success" ]]; then
exit 1
fi