mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #183] [MERGED] feat(linear-ticket): require a linked Linear issue on every PR #194
Labels
No labels
cursor-review-catalog-drift
groom
groom
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/github-workflows#194
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/github-workflows/pull/183
Author: @luke-mino-altherr
Created: 8/18/2026
Status: ✅ Merged
Merged: 8/19/2026
Merged by: @luke-mino-altherr
Base:
main← Head:luke/linear-ticket-enforcement📝 Commits (4)
d9d6882feat(linear-ticket): require a linked Linear issue on every PR96db157refactor(linear-ticket): implement in Python instead of shellc58b7e6fix(linear-ticket): address CodeRabbit reviewebb68c8feat(linear-ticket): add opt-in exempt-actors for bot PRs; address Wei's review📊 Changes
9 files changed (+1499 additions, -6 deletions)
View changed files
➕
.github/workflows/linear-ticket.yml(+213 -0)➕
.github/workflows/test-linear-ticket.yml(+51 -0)📝
README.md(+1 -0)📝
docs/callers/README.md(+14 -6)➕
docs/callers/linear-ticket.md(+163 -0)➕
scripts/linear-ticket/README.md(+60 -0)➕
scripts/linear-ticket/lib.py(+249 -0)➕
scripts/linear-ticket/tests/test_lib.py(+216 -0)➕
scripts/linear-ticket/validate.py(+532 -0)📄 Description
What
Adds a reusable workflow that requires every PR to carry a Linear issue Linear has linked to that exact PR before it can merge — flexible about the linking method, resistant to spoofing. Implements the
pr-linear-ticket-enforcementdesign.The only thing that turns the check green is an attachment Linear returns for the PR's canonical
html_url(attachmentsForURL, PR URL passed as a GraphQL variable) whose issue satisfies the configured team/state policy. ATEAM-123-shaped string in author-controlled text never passes; identifiers mined from branch/title/body are diagnostics only (20-cap, one batched lookup).Shape
Same split as the risk-grader/area-label reusables — logic here, a thin caller in each consumer repo. Implemented in stdlib Python to match this repo's convention (
groom,refresh-reviewers,agents-md-integrity,cursor-review)..github/workflows/linear-ticket.yml—on: workflow_callvalidator. Inputsworkflows_ref(required, shape+ancestry-guarded),team-keys,exempt-label,require-open-issue,enforce; secretLINEAR_API_TOKEN; min job permissionsactions:read,contents:read,pull-requests:write,statuses:write. Sets up Python 3.12 and runsvalidate.py.scripts/linear-ticket/lib.py— pure, network-free core (candidate extraction,team-keysvalidation, thefilter_issuespolicy gate, error classification, failure-category selection, copy, diagnostic-query builder).scripts/linear-ticket/validate.py— orchestration: resolve exactly one open PR from theworkflow_runevent (same-repopull_requestsor fork commit→PR association), refetch, publish thelinear-ticketcommit status, query with bounded backoff (2/4/8/16s ×5), apply the gate, run one batched diagnostic query, maintain one marker comment, recheck the head SHA before every terminal write, fail closed on infra errors, warn-only mode. GitHub via theghCLI (subprocess), Linear viaurllib.scripts/linear-ticket/tests/test_lib.py(40-caseunittestsuite) + path-filteredtest-linear-ticket.yml(unittest discover+ apy_compilegate forvalidate.py).docs/callers/linear-ticket.md(the two consumer workflows, permissions, rollout, footguns),scripts/linear-ticket/README.md, README + callers-index rows.Fork/Dependabot safety
The
pull_request→workflow_runsplit: an unprivileged signal workflow (checks out nothing, no secret) triggers a privileged validator onworkflow_run: completed, which GitHub grants the secret + write token. The validator runs on the default branch, so its job check is not the merge gate — branch protection requires thelinear-ticketcommit status it publishes on the refetched PR head SHA.Verification
Local gates all green:
python3 -m unittest discover(40 tests),py_compile, theworkflow-pinslint (workflows_refrequired, no default, guarded), YAML parse. Also smoke-testedvalidate.pyend-to-end against a local HTTP server standing in for Linear + a stubghon PATH, across pass / fail / warn-only / policy-mismatch paths.Rollout (per the design)
Land here with tests → add pinned callers with
enforce: false→ observe ~a week → flipenforce: true→ add thelinear-ticketstatus to themainruleset as required. No bump-caller fleet yet (deliberate: the pilot pins callers manually, repo-by-repo).Requires the org secret
LINEAR_API_TOKEN(being provisioned separately).🤖 Generated with Claude Code
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.