Skip to content

feat: issue labeler logic moves to scripts/issue-labeler.js with a durable test - #63

Merged
TzuH-Hsu merged 1 commit into
mainfrom
feat/49-labeler-script
Sep 16, 2026
Merged

TzuH-Hsu merged 1 commit into
mainfrom
feat/49-labeler-script

Conversation

@TzuH-Hsu

Copy link
Copy Markdown
Owner

Summary

The labeler was the one workflow carrying logic — ~150 lines of JS inline in the YAML, testable only by hand-extracting it (#48 was validated that way). Per #49 option 1:

  • scripts/issue-labeler.js: the logic as a plain Node module — pure parseSections / matchAllowed / parseAllowedAreas / computeChanges, one I/O run({github, context, core}). labels.yml is read from the checkout instead of the API (same trust boundary: on issues events GITHUB_SHA is the default-branch head).
  • .github/workflows/issue-labeler.yml: pinned actions/checkout (persist-credentials: false, fetch-depth: 1, the SHA already used by ci.yml) + a two-line github-script require. No adopter values; replace whole on upgrade, together with the script.
  • scripts/issue-labeler.test.js (14 cases, node built-ins only) run by scripts/check-issue-labeler.sh from make check. A missing node fails with an install hint like every other tool make needs — deviation from the issue text, which said "SKIP visibly locally": the Makefile's convention is fail-with-hint, and a green skip is what validation-ladder rule 7 forbids. node added to CONTRIBUTING's tool table.
  • scripts/check-label-forms.sh follows the constants to the script, and now fails two torn-upgrade states: a thin-caller workflow without the script, and the script present while the workflow still carries the inline copy.
  • ADR-0008; hygiene rule 1, AGENTS.md, design principle 5, the architecture ledger, upgrading.md (full travel set), CODEOWNERS example.

Related issue

Closes #49

Validation

  • L0 static — make verify green (actionlint, yamllint, markdownlint, lychee, checks incl. the new test step)
  • L1 unit — node --test scripts/issue-labeler.test.js: 14/14. Includes the read-failure-throws-before-any-API-call guarantee, the empty-allowlist warning, a 65k-char heading line parsing in linear time, and stray CR / U+2028 heading lines.
  • L2 — differential against the inline original on main: 3,000 random bodies (LF and CRLF; dropdown case variants, _No response_, ticked/unticked/undeclared areas, exotic heading lines) × random current labels → 0 differences in add/remove decisions. check-label-forms.sh verified on four labeler generations (pre-fix: issue labeler reads the area:* allowlist from labels.yml instead of a hardcoded list #48 inline, fix: issue labeler reads the area:* allowlist from labels.yml instead of a hardcoded list #48–v0.4.1 inline, extracted, and both torn states).
  • Pre-review — three adversarial lenses (parity, security, repo rules) ran before this PR was opened; 14 findings, all folded in. Security lens: body never reaches a shell or a path; every added label is allowlist-derived; 5,000-iteration fuzz found no escape; checkout on issues events cannot be a fork ref.
  • L3 — after merge (the workflow runs from main on issues events): open an issue ticking area:ci, confirm the label; edit to area:docs, confirm the swap. Recorded in a comment here.

Risk / rollback

RISK: one more pinned action (Dependabot covers github-actions) and a checkout
on every issue event. The script is now protected by what protects scripts/
on the default branch rather than GitHub's workflows-scope rule; blast
radius unchanged (issues: write only) — ADR-0008 Consequences, with the
CODEOWNERS recipe for adopters who want a review barrier.
Rollback: revert; the inline workflow returns.

Checklist

  • Conventional Commit PR title
  • Linked issue using "Closes #N"
  • No secrets, no *.local.md files committed
  • Documentation updated where affected

…rable test

The labeler was the one workflow carrying logic — ~150 lines of JS inline
in the YAML, testable only by extracting it by hand. The logic is now a
plain Node module with pure functions and one run() entry point; the
workflow checks out the default branch (pinned checkout, no credentials)
and calls it in two lines. labels.yml is read from the checkout instead
of the API. scripts/issue-labeler.test.js pins the behaviour (12 cases,
node built-ins only) and runs from make check; in CI a missing node
fails, locally it skips loudly. Hygiene rule 1 and AGENTS.md name the
shape; ADR-0008 records it; check-label-forms.sh follows the constants
to the script.

Closes #49

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@TzuH-Hsu TzuH-Hsu added this to the v0.5.0 milestone Sep 16, 2026
@TzuH-Hsu TzuH-Hsu added the area:ci CI workflows and automation label Sep 16, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-16T06:10:30.688099Z 286ddbf PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@TzuH-Hsu
TzuH-Hsu merged commit f464cfb into main Sep 16, 2026
1 check passed
@TzuH-Hsu
TzuH-Hsu deleted the feat/49-labeler-script branch September 16, 2026 06:11
@github-actions github-actions Bot mentioned this pull request Sep 16, 2026
@TzuH-Hsu

Copy link
Copy Markdown
Owner Author

L3 done on main after merge (issue #64, closed): the workflow checked out f464cfb, required scripts/issue-labeler.js, applied type:docs, priority:p3, area:ci on open (run 35062583686) and logged Added: area:docs / Removed: area:ci on edit (run 35062634271).

TzuH-Hsu pushed a commit that referenced this pull request Sep 16, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.5.0](v0.4.1...v0.5.0)
(2026-09-16)


### Features

* issue labeler logic moves to scripts/issue-labeler.js with a durable
test ([#63](#63))
([f464cfb](f464cfb))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:ci CI workflows and automation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Issue labeler logic lives inline in the workflow, outside the Makefile-owns-logic rule and without a durable test

1 participant