feat: sync linked issue labels to pull requests#2015
feat: sync linked issue labels to pull requests#2015cheese-cakee wants to merge 35 commits intohiero-ledger:mainfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds two new GitHub Actions workflows to copy labels from linked issues to PRs, plus updates harden-runner steps in an existing CI workflow to include three explicit egress allowlist endpoints; also updates CHANGELOG.md. Changes
Sequence DiagramsequenceDiagram
participant GH as "GitHub Events"
participant Compute as "sync-issue-labels-compute (job)"
participant API as "GitHub API"
participant Artifact as "Artifact Storage"
participant Add as "sync-issue-labels-add (job)"
GH->>Compute: PR event or workflow_dispatch (pr_number)
Compute->>API: Fetch PR details & author
API-->>Compute: PR info
Compute->>Compute: Parse PR body → extract linked issue numbers
loop for each linked issue
Compute->>API: Fetch issue by number
API-->>Compute: Issue labels (or 404)
Compute->>Compute: Aggregate labels
end
Compute->>Compute: Deduplicate & compute new labels for PR
Compute->>Artifact: Upload labels.json (pr-labels-<pr>)
Compute->>GH: Dispatch `sync-issue-labels-add` (when applicable)
GH->>Add: Workflow dispatch (with upstream_run_id, pr_number, dry_run)
Add->>Artifact: Download pr-labels artifact
Artifact-->>Add: labels.json
Add->>Add: Validate payload, dry-run & fork checks
alt apply labels
Add->>API: Add labels to PR
API-->>GH: Labels applied to PR
else skip
Add-->>GH: No-op / dry-run
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📋 Issue PlannerLet us write the prompt for your AI agent so you can ship faster (with fewer bugs). View plan for ticket: ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: f0b7bc26-2115-4014-9b8d-f879134d21e2
📒 Files selected for processing (5)
.github/scripts/sync-issue-labels.js.github/workflows/pr-check-test.yml.github/workflows/sync-issue-labels-add.yml.github/workflows/sync-issue-labels-compute.ymlCHANGELOG.md
a2a6b4f to
fce3a4d
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (4)
.github/workflows/sync-issue-labels-compute.yml (2)
4-5:⚠️ Potential issue | 🔴 CriticalCritical: untrusted fork code can run on self-hosted runner
Line 4 uses
pull_request, and Line 35 checks outpull_request.head.ref. That combination executes fork PR head code on your self-hosted runner before any fork guard.🔐 Hardening patch
on: - pull_request: + pull_request_target: types: [opened, edited, reopened, synchronize, ready_for_review] @@ - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - ref: ${{ github.event.pull_request.head.ref || 'main' }} + ref: ${{ github.event_name == 'workflow_dispatch' && 'main' || github.event.pull_request.base.sha }}As per coding guidelines, “Workflows must behave safely when executed from forks.”
Also applies to: 32-35
91-97:⚠️ Potential issue | 🟠 MajorGuard dispatch step for fork PRs and missing PAT
Line 91 dispatches the write workflow unconditionally, but Line 97 depends on
secrets.GH_ACCESS_TOKEN. On fork PR runs this secret is typically unavailable, so this path is brittle/failing.🛡️ Suggested guard
- name: Trigger add workflow + if: ${{ steps.compute.outputs.is_fork_pr != 'true' && secrets.GH_ACCESS_TOKEN != '' }} uses: step-security/workflow-dispatch@acca1a315af3bf7f33dd116d3cb405cb83f5cbdc # v1.2.8As per coding guidelines, “Workflows must behave safely when executed from forks.”
.github/scripts/sync-issue-labels.js (1)
67-80:⚠️ Potential issue | 🟠 MajorBound linked-issue extraction to prevent API amplification
PR body is untrusted input, but Line 80 returns all matches with no limit, and Lines 165-169 make one API call per linked issue. Add a hard upper bound and log truncation.
🧱 Suggested safeguard
+const MAX_LINKED_ISSUES = Number(process.env.MAX_LINKED_ISSUES || "20"); + function extractLinkedIssueNumbers(prBody, owner, repo) { const numbers = new Set(); @@ - return Array.from(numbers); + const all = Array.from(numbers); + if (all.length > MAX_LINKED_ISSUES) { + console.log(`[sync] Limiting linked issue refs from ${all.length} to ${MAX_LINKED_ISSUES}.`); + } + return all.slice(0, MAX_LINKED_ISSUES); }As per coding guidelines, “Treat all GitHub event data as potentially untrusted input.”
Also applies to: 165-169
.github/workflows/sync-issue-labels-add.yml (1)
43-62: 🧹 Nitpick | 🔵 TrivialMake artifact read deterministic
Line 61 uses
find ... -print -quit, which can pick the wrong payload if multiple artifacts/files exist. Download the expected artifact by name and read a fixed path.♻️ Suggested refactor
- name: Download labels artifact id: download continue-on-error: true uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: + name: pr-labels-${{ github.event.inputs.pr_number }} path: artifacts run-id: ${{ github.event.inputs.upstream_run_id }} github-token: ${{ secrets.GITHUB_TOKEN }} @@ - labels_file="" - if [ -d artifacts ]; then - labels_file=$(find artifacts -name labels.json -print -quit) - fi + labels_file="artifacts/labels.json"As per coding guidelines, “Workflows that mutate state should use concurrency groups and duplicate prevention patterns (marker-based comments, check-before-create for labels).”
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: b4d35402-05f5-438a-9cda-aa0b7b228e15
📒 Files selected for processing (5)
.github/scripts/sync-issue-labels.js.github/workflows/pr-check-test.yml.github/workflows/sync-issue-labels-add.yml.github/workflows/sync-issue-labels-compute.ymlCHANGELOG.md
There was a problem hiding this comment.
Pull request overview
Adds GitHub Actions automation to propagate labels from linked issues (referenced via closing keywords in PR bodies) onto pull requests, aiming to reduce manual labeling effort.
Changes:
- Introduces a “compute” workflow to parse linked issues from PR text, gather issue labels, and publish the label delta as an artifact.
- Introduces an “add” workflow to download the computed artifact payload and apply labels to the PR.
- Updates Harden-Runner egress allowlisting in
pr-check-test.yml(and records related entries in the changelog).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
CHANGELOG.md |
Adds .github changelog bullets (but currently not for the label-sync feature) and unintentionally modifies the file header encoding. |
.github/workflows/sync-issue-labels-compute.yml |
New workflow to compute missing PR labels from linked issues and dispatch the add workflow. |
.github/workflows/sync-issue-labels-add.yml |
New workflow to download computed label payload and add labels to the PR. |
.github/workflows/pr-check-test.yml |
Adds additional allowed-endpoints entries for Harden-Runner. |
.github/scripts/sync-issue-labels.js |
Adds a reusable JS implementation of label syncing logic (currently not wired into the workflows). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
.github/scripts/sync-issue-labels.js (1)
61-79:⚠️ Potential issue | 🟠 MajorOnly collect refs that are actually paired with a closing keyword.
Once Line 96 sees any closing keyword, Line 99 pulls every issue ref on that line. A body like
Fixes#1, related to#2`` will still copy labels from#2. Use one regex that matches keyword+reference pairs instead of keyword-presence + broad extraction.As per coding guidelines, “Do not trust free-form text from issues, PRs, or comments.”
Also applies to: 90-100
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 581c12ad-9b23-4f5a-abc3-64bcbaea4a17
📒 Files selected for processing (3)
.github/scripts/sync-issue-labels.js.github/workflows/sync-issue-labels-add.yml.github/workflows/sync-issue-labels-compute.yml
|
Hi, this is WorkflowBot.
|
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #2015 +/- ##
=======================================
Coverage 93.68% 93.68%
=======================================
Files 144 144
Lines 9350 9350
=======================================
Hits 8760 8760
Misses 590 590 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
.github/workflows/sync-issue-labels-compute.yml (1)
187-188:⚠️ Potential issue | 🔴 CriticalMove the PAT presence check out of the step
if.Line 188 will not validate as written:
jobs.<job_id>.steps.ifdoes not allow thesecretscontext, and GitHub’s secrets docs explicitly say secrets cannot be referenced directly inif:conditionals. Put the presence check into a job-levelenvvalue and gate onenv.HAS_GH_ACCESS_TOKENinstead. (docs.github.com)Suggested fix
compute-labels: + env: + HAS_GH_ACCESS_TOKEN: ${{ secrets.GH_ACCESS_TOKEN != '' }} concurrency: group: sync-issue-labels-compute-pr-${{ github.event.pull_request.number || github.event.inputs.pr_number }} cancel-in-progress: true- - name: Trigger add workflow - if: ${{ steps.compute.outputs.is_fork_pr != 'true' && secrets.GH_ACCESS_TOKEN != '' }} + - name: Trigger add workflow + if: ${{ steps.compute.outputs.is_fork_pr != 'true' && env.HAS_GH_ACCESS_TOKEN == 'true' }} uses: step-security/workflow-dispatch@acca1a315af3bf7f33dd116d3cb405cb83f5cbdc # v1.2.8
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 3f6f4172-be62-4c6c-8bf4-89f10ce5d8a5
📒 Files selected for processing (3)
.github/workflows/sync-issue-labels-add.yml.github/workflows/sync-issue-labels-compute.ymlCHANGELOG.md
There was a problem hiding this comment.
Actionable comments posted: 5
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4126f20c-adb3-4d4e-96ee-48372aef0147
📒 Files selected for processing (2)
.github/workflows/sync-issue-labels-add.yml.github/workflows/sync-issue-labels-compute.yml
Fork E2E Test ResultsTested the workflow end-to-end on Test setup:
Compute workflow — run: Add workflow — run: The label-adding step fails on the fork because |
Co-authored-by: Roger Barker <roger.barker@swirldslabs.com> Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Co-authored-by: Roger Barker <roger.barker@swirldslabs.com> Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Co-authored-by: Roger Barker <roger.barker@swirldslabs.com> Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Co-authored-by: Roger Barker <roger.barker@swirldslabs.com> Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
- Switch compute workflow from pull_request to pull_request_target - Checkout base.sha instead of head.ref for fork safety - Guard dispatch step for fork PRs and missing PAT - Add MAX_LINKED_ISSUES=20 cap to prevent API amplification - Download artifact by name for deterministic reads - Add JSDoc docstrings to sync-issue-labels.js functions Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
…l_request_target Remove checkout step entirely. Script logic is now inline in the github-script step, eliminating the need to checkout PR branch code and avoiding the fork code execution vulnerability. Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Script logic is inlined in the github-script step, eliminating the need to checkout code entirely. With read-only permissions and no checkout, the workflow is safe for fork PRs without requiring maintainer approval for pull_request_target. Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
…spatch Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
- Remove dead .github/scripts/sync-issue-labels.js (logic is inlined) - Add CHANGELOG entry for label-sync feature (hiero-ledger#1716) - Remove BOM character from CHANGELOG.md - Fail add workflow on missing artifact instead of silent no-op Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
- Move secrets check to job-level if (secrets unavailable in steps.if) - Split dispatch into separate dispatch-add job - Set cancel-in-progress: true for add workflow - Only match issue refs directly after closing keywords Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
…ther) Use fork guard only + continue-on-error on dispatch step for resilience. Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
- Pre-compute should_apply flag for readable step condition
- Fix dry_run artifact fallback to match workflow input default ('true')
- Address parvninama review feedback
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
7289ce6 to
fd09465
Compare
Up to standards ✅🟢 Issues
|
Description
Adds an automated GitHub workflow system to sync labels from linked issues to pull requests.
When a PR body includes closing keywords (for example
Fixes #123), the workflow fetches labels from those linked issues and adds missing labels to the PR.Continuation of closed PR #1877 - all review feedback has been addressed.
Related issue(s)
Fixes #1716
What changed
.github/workflows/sync-issue-labels-compute.ymlpull_requesttrigger onopened,edited,reopened,synchronize, andready_for_reviewactions/github-scriptstep (no checkout needed, eliminates fork code execution risk)MAX_LINKED_ISSUEScapworkflow_dispatchwithpr_number+dry_run.github/workflows/sync-issue-labels-add.ymlworkflow_dispatch(called by compute workflow)actions-ecosystem/action-add-labelswithnumberinput[Unreleased] -> .GithubScope note
This PR intentionally implements label sync only (additive). It does not remove labels from PRs and does not include assignee sync.
Architecture
Two separate workflows to separate read and write permissions:
sync-issue-labels-compute.yml- reads labels from linked issues (read-only permissions, inline script)sync-issue-labels-add.yml- writes labels to PR (write permissions,issues: write)The compute workflow triggers on PR events and dispatches the add workflow via
workflow_dispatch, passing computed labels as an artifact.Testing
Fixes #NkeywordsChecklist