Files
santifer--career-ops/.github/workflows/plugin-registry-validate.yml
T
wehub-resource-sync d083df1fdb
CodeQL Analysis / Analyze (javascript-typescript) (push) Failing after 2s
Web CI / web typecheck + build (push) Failing after 1s
Release Please / release-please (push) Failing after 1s
CodeQL Analysis / Analyze (go) (push) Failing after 16s
chore: import upstream snapshot with attribution
2026-07-13 12:02:43 +08:00

64 lines
2.8 KiB
YAML

name: 'Plugin registry validate'
# Runs on PRs that touch the curated plugin registry. Uses `pull_request` (NOT
# pull_request_target), read-only permissions, and NO secrets — so cloning +
# statically auditing a submitter's plugin can never reach a token or write the
# repo. No plugin code is executed (the manifest is parsed, the audit is static).
on:
pull_request:
paths:
- 'plugins-registry/**'
- 'plugins-registry.json' # legacy single-file location (pre-migration forks)
permissions:
contents: read
# Cancel superseded runs when the same PR is pushed again.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
validate:
name: Validate registry entries
runs-on: ubuntu-latest
steps:
# fetch-depth: 0 so the "One plugin per PR" diff below has the base
# branch's history + merge-base available (a shallow checkout truncates it).
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version: '24'
# Deterministic shape gate (no network).
- name: Validate registry shape
run: node validate-plugin-registry.mjs
# Deep gate: clone each entry at its pinned SHA + static-validate + audit.
# No secrets are present in this job; nothing the plugin ships is executed.
- name: Clone + audit each registry entry
run: node validate-plugin-registry.mjs --deep
- name: One plugin per PR
# base_ref goes through env, never ${{ }}-spliced into the script —
# anything expanded inside run: is literal shell code (template injection).
env:
BASE_REF: ${{ github.base_ref }}
run: |
# Make origin/$BASE_REF resolvable (checkout of a PR merge ref does not
# create the base remote-tracking branch on its own).
git fetch --no-tags origin "$BASE_REF"
# One-time migration exemption: the PR that removes the legacy single
# file necessarily rewrites every entry into plugins-registry/<id>.json.
# This can only ever match the migration itself — once it lands,
# plugins-registry.json no longer exists for any future PR to delete,
# so the one-plugin gate below still holds for all registration PRs.
if git diff --name-only --diff-filter=D "origin/$BASE_REF"...HEAD -- plugins-registry.json | grep -q .; then
echo "Migration PR (removes legacy plugins-registry.json) — one-plugin-per-PR gate not applicable."
exit 0
fi
CHANGED=$(git diff --name-only "origin/$BASE_REF"...HEAD -- 'plugins-registry/*.json' plugins-registry.json | wc -l)
if [ "$CHANGED" -gt 1 ]; then echo "A registry PR may add or bump exactly one plugins-registry/<id>.json file"; exit 1; fi