From b0a7608bffa1da9ffe0d5425a51a93480a6cef9e Mon Sep 17 00:00:00 2001 From: Yimin Jin Date: Tue, 23 Jun 2026 17:33:41 +0800 Subject: [PATCH] ci: guard sample-catalog.json against manual edits Add a pull_request check that fails any PR modifying samples/hosted-agent/sample-catalog.json unless it originates from a Sync Sample Catalog branch (ci/sync-sample-catalog-*). The catalog is a generated artifact and must only be updated by CI. Enforcement requires marking guard-catalog as a required status check and disallowing direct pushes on the protected branch. --- .github/workflows/guard-sample-catalog.yml | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/workflows/guard-sample-catalog.yml diff --git a/.github/workflows/guard-sample-catalog.yml b/.github/workflows/guard-sample-catalog.yml new file mode 100644 index 0000000..fadc1d9 --- /dev/null +++ b/.github/workflows/guard-sample-catalog.yml @@ -0,0 +1,55 @@ +name: Guard Generated Catalog + +# samples/hosted-agent/sample-catalog.json is GENERATED by the "Sync Sample +# Catalog" workflow and must never be edited or committed by hand. This check +# fails any PR that modifies it unless the PR originates from a sync-workflow +# branch (ci/sync-sample-catalog-*). +# +# For this to ENFORCE (not merely report), the protected branch must also: +# - mark the "guard-catalog" check as a REQUIRED status check, and +# - disallow direct pushes (PRs only) — a pull_request guard cannot catch a +# direct push. +# +# A pull_request workflow only guards PRs targeting the branch it lives on, so +# this file must exist on every protected branch you want covered. + +on: + pull_request: + +permissions: + contents: read + +jobs: + guard-catalog: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Reject manual edits to sample-catalog.json + env: + HEAD_REF: ${{ github.head_ref }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + shell: bash + run: | + set -euo pipefail + CATALOG="samples/hosted-agent/sample-catalog.json" + + # Did this PR change the generated catalog at all? + if git diff --quiet "$BASE_SHA" "$HEAD_SHA" -- "$CATALOG"; then + echo "PR does not touch $CATALOG — OK." + exit 0 + fi + + # It did. Only the Sync Sample Catalog workflow (which opens PRs from + # ci/sync-sample-catalog-* branches) is allowed to change it. + if [[ "$HEAD_REF" == ci/sync-sample-catalog-* ]]; then + echo "Change to $CATALOG came from sync branch '$HEAD_REF' — OK." + exit 0 + fi + + echo "::error file=$CATALOG::$CATALOG is generated by the 'Sync Sample Catalog' workflow and must not be edited or committed manually. Revert your changes to this file; CI will regenerate it." + exit 1