From 5dea5eee2cad7b0b42a55c8ec49b46105b556a9c Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Nov 2026 18:20:40 +0000 Subject: [PATCH] fix(scripts): the SPDX recipe writes the template rule that stops at an indented body The recipe `fix-workflow-linter-spdx-rule.sh` writes the SPDX rule of the estate template. That rule stopped the scan only at a body line in column 1, so it accepted a licence comment after the body of a workflow with an indented root mapping. A review of pull request 658 found this, and the thread stayed open because the rule text belongs to the template. The template gets the repair in rsr-template-repo pull request 323 (owner decision, 2026-11-10: the template first, then the recipe). The recipe now writes the same text: the stop condition is `/^[[:space:]]*[^#[:space:]]/`. - The test expects the new text, and runs the new rule on 2 more sample files: an indented body with a late licence line (must fail), and an indented body with the licence first (must pass). - The campaign note names the template pull request, and has 1 new limit: a linter that has the first form of the template rule is not a target. The target of the recipe does not change: the `head -1` rule only. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_0136P7ZmiFSCoB3UR9Kk56rK --- campaigns/TEMPLATE-DRIFT-CAMPAIGN.adoc | 8 +++++++- scripts/fix-workflow-linter-spdx-rule.sh | 2 +- tests/template-drift-recipes-test.sh | 8 +++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/campaigns/TEMPLATE-DRIFT-CAMPAIGN.adoc b/campaigns/TEMPLATE-DRIFT-CAMPAIGN.adoc index 8cb402a6..60db62c2 100644 --- a/campaigns/TEMPLATE-DRIFT-CAMPAIGN.adoc +++ b/campaigns/TEMPLATE-DRIFT-CAMPAIGN.adoc @@ -70,7 +70,9 @@ repair refuses the repository, and no file is changed. Each recipe was also run on the files of `system-et` at `main` (`04a8b6e`): -* SPDX rule: the step is identical to the step of the template (`c5a1da7`). +* SPDX rule: the step is identical to the step of the template branch + (`rsr-template-repo` pull request 323, `915acb2`). That pull request makes + the rule stop at an indented workflow body also. * Token guard: the job is identical to the job in pull request 92 (`9f529ef`). The guard step is identical to the guard step of the template branch (`rsr-template-repo` pull request 321, `806dac0`). @@ -100,6 +102,10 @@ and `fix-lock-self-sha-refs.sh` already cover these. inactive file (`e2e.yml.template`). * The token guard recipe edits only the shape of the old template. It does not rewrite a workflow that a person changed. +* The SPDX recipe has 1 target: the `head -1` rule. A linter that has the + first form of the template rule (the form before `rsr-template-repo` pull + request 323, for example in `system-et`) is not a target, and keeps that + form. * The number of repositories with each target is not known. No estate scan was made. diff --git a/scripts/fix-workflow-linter-spdx-rule.sh b/scripts/fix-workflow-linter-spdx-rule.sh index f5b21188..7ec4113a 100755 --- a/scripts/fix-workflow-linter-spdx-rule.sh +++ b/scripts/fix-workflow-linter-spdx-rule.sh @@ -27,7 +27,7 @@ set -euo pipefail REL=".github/workflows/workflow-linter.yml" OLD_RULE='^[[:space:]]*if ! head -1 "\$[A-Za-z_][A-Za-z0-9_]*" \| grep -q "\^# SPDX-License-Identifier:"; then[[:space:]]*$' -NEW_RULE='/^# SPDX-License-Identifier:/ { found=1 } /^[^#[:space:]]/ { exit } END { exit !found }' +NEW_RULE='/^# SPDX-License-Identifier:/ { found=1 } /^[[:space:]]*[^#[:space:]]/ { exit } END { exit !found }' # Print the path of the linter when it is a regular file inside the repository. # A missing file, a symlink, or a path that leaves the repository is no target. diff --git a/tests/template-drift-recipes-test.sh b/tests/template-drift-recipes-test.sh index 6224a0e5..7a82140f 100644 --- a/tests/template-drift-recipes-test.sh +++ b/tests/template-drift-recipes-test.sh @@ -82,7 +82,7 @@ cat > "$TMP/expected" <<'YAML' for file in .github/workflows/*.yml; do # actions-lock may prepend its own comment. Require the licence # in the leading comment block, before the workflow body. - if ! awk '/^# SPDX-License-Identifier:/ { found=1 } /^[^#[:space:]]/ { exit } END { exit !found }' "$file"; then + if ! awk '/^# SPDX-License-Identifier:/ { found=1 } /^[[:space:]]*[^#[:space:]]/ { exit } END { exit !found }' "$file"; then echo "ERROR: $file missing SPDX header" fi done @@ -100,6 +100,12 @@ printf '# comment\nname: a\n# SPDX-License-Identifier: MPL-2.0\n' > "$TMP/s3" awk "$RULE" "$TMP/s1" || fail "$R: the new rule refuses a licence on line 2" if awk "$RULE" "$TMP/s2"; then fail "$R: the new rule accepts a file with no licence"; fi if awk "$RULE" "$TMP/s3"; then fail "$R: the new rule accepts a licence after the body"; fi +# A workflow with an indented root mapping: the body starts at the first line +# that is not a comment, so a licence line after it does not count. +printf '# comment\n name: a\n jobs: {}\n# SPDX-License-Identifier: MPL-2.0\n' > "$TMP/s4" +printf '# SPDX-License-Identifier: MPL-2.0\n name: a\n jobs: {}\n' > "$TMP/s5" +if awk "$RULE" "$TMP/s4"; then fail "$R: the new rule accepts a licence after an indented body"; fi +awk "$RULE" "$TMP/s5" || fail "$R: the new rule refuses a licence before an indented body" # A linter with a different rule is not a target. REPO=$(new_repo spdx-other); F="$REPO/.github/workflows/workflow-linter.yml"