diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 618c7cc..4c67522 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -23,6 +23,7 @@ # Example: Require infrastructure ownership # /scripts/bootstrap.sh @infra-owner +# /scripts/issue-labeler.js @infra-owner # Example: Solo dev auto-request # * @your-username diff --git a/.github/workflows/issue-labeler.yml b/.github/workflows/issue-labeler.yml index e22d8c4..b053984 100644 --- a/.github/workflows/issue-labeler.yml +++ b/.github/workflows/issue-labeler.yml @@ -1,18 +1,21 @@ name: Issue labeler -# Syncs priority:*, area:* and the four type:* SUBTYPE labels from -# the issue form fields on open/edit. The issue body is untrusted input — it is -# only ever read inside the actions/github-script JS sandbox -# (context.payload.issue.body), never interpolated into a shell `run:` step. +# Syncs priority:*, area:* and the four type:* SUBTYPE labels from the issue +# form fields on open/edit. The logic lives in scripts/issue-labeler.js +# (ADR-0008); this file only checks out the default branch and calls it, so +# it carries no adopter values and can be replaced whole on upgrade. The +# script is tested by `make check` (scripts/check-issue-labeler.sh). # -# "the four type:* subtype labels", not "type:*": the type: namespace also -# carries labels no form produces, so this workflow owns an exact list rather -# than a prefix. See FORM_MANAGED_TYPES below. +# The issue body is untrusted input — it is only ever read inside the +# actions/github-script JS sandbox (context.payload.issue.body), never +# interpolated into a shell `run:` step, and every label the script adds is +# validated against an allowlist the body cannot influence. # -# area:* is the family adopters are told to rename, so its allowlist is not -# written here: it is read from .github/labels.yml on the default branch at -# run time (see loadAllowedAreas below). This file carries no adopter values -# and can be replaced whole on upgrade. +# Why a checkout on an issue event: the script and .github/labels.yml (the +# run-time source of the area:* allowlist) live in the repository. On `issues` +# events GITHUB_SHA is the head of the default branch, so this checks out +# exactly the code and label declarations that were merged — never a PR +# branch's copy. on: issues: @@ -34,203 +37,17 @@ jobs: timeout-minutes: 5 permissions: issues: write - contents: read # getContent on .github/labels.yml + contents: read # checkout of the default branch steps: + - name: Check out the default branch + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + fetch-depth: 1 + - name: Sync form-managed labels uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | - // Parses the GitHub issue-form markdown body (###