Skip to content

Extend hotfix label automation to cover issues - #4741

Open
mdaigle wants to merge 20 commits into
dotnet:mainfrom
mdaigle:mdaigle-hotfix-label-issue-automation
Open

mdaigle wants to merge 20 commits into
dotnet:mainfrom
mdaigle:mdaigle-hotfix-label-issue-automation

Conversation

@mdaigle

@mdaigle mdaigle commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Description

Extends the existing "Hotfix X.Y.Z" PR cherry-pick automation to also cover issues, so backport tracking issues are created and linked automatically instead of manually (as done for #4737/#4738).

  • create-backport-issue.sh + hotfix-label-issue.yml: labeling a parent issue Hotfix X.Y.Z creates a child backport issue milestoned to that version and links it as a native GitHub sub-issue. Includes duplicate detection (by milestone or title prefix) so a re-fired labeled event won't create a second backport issue.
  • sync-hotfix-label-to-pr.sh + sync-hotfix-label-to-pr.yml: when a PR's closing issue references include a Hotfix-labeled issue, that label is copied onto the PR, feeding it into the existing cherry-pick automation.
  • cherry-pick-to-release.sh (extended): looks up the milestone-matched backport issue via the original PR's closing references and appends Fixes #N to the auto-generated cherry-pick PR body (both the clean and conflict paths), so merging the backport PR automatically closes the backport issue.
  • Added issues: read permission to cherry-pick-hotfix.yml for the new lookup.

End-to-end flow: label an issue Hotfix 7.1.1 -> backport issue #N created and sub-issued -> PR opened closing the parent issue picks up the Hotfix 7.1.1 label -> merging that PR triggers the existing cherry-pick automation -> generated backport PR links Fixes #N.

Issues

Not tied to a specific bug fix; this generalizes the manual backport-issue pattern used for #4737 and #4738 into automation.

Testing

Added bats coverage for all new/changed behavior, run locally with bats-core:

  • create-backport-issue.bats (10 tests): label validation, duplicate detection, milestone lookup, issue creation, sub-issue linking.
  • sync-hotfix-label-to-pr.bats (7 tests): closing-reference parsing, label collection/dedup, idempotent sync.
  • cherry-pick-to-release.bats (19 tests, 4 new): backport-issue lookup and Fixes #N linking in both the clean and conflict PR-body paths; all 16 pre-existing tests still pass unmodified.

Also ran shellcheck against the new/modified scripts with no new findings.

Guidelines

Please review the contribution guidelines before submitting a pull request:

- create-backport-issue.sh + hotfix-label-issue.yml: labeling an issue
  "Hotfix X.Y.Z" creates a child backport issue milestoned to that
  version and links it as a native GitHub sub-issue.
- sync-hotfix-label-to-pr.sh + sync-hotfix-label-to-pr.yml: copies the
  Hotfix label onto a PR when its closing issue references include a
  Hotfix-labeled issue, feeding the existing cherry-pick automation.
- cherry-pick-to-release.sh: looks up the milestone-matched backport
  issue via the PR's closing references and appends "Fixes #N" to the
  generated cherry-pick PR body (both clean and conflict paths), so
  merging it auto-closes the backport issue.
- Added bats tests for all new/changed behavior and updated the tests
  README.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@mdaigle
mdaigle requested review from a team and a balanced review from Copilot September 23, 2026 18:52
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board Sep 23, 2026
@mdaigle mdaigle added this to the 8.0.0-preview1 milestone Sep 23, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Missing checkout permissions and broken or ambiguous issue lookups prevent reliable end-to-end automation.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 6 Medium severity

Open (6)
What changed in this PR

Extends hotfix automation from pull requests to linked issues and backport tracking.

Changes:

  • Creates milestone-targeted backport sub-issues.
  • Propagates issue hotfix labels to closing PRs.
  • Links generated cherry-pick PRs to backport issues.
File Description
.github/​workflows/​sync-hotfix-label-to-pr.yml Runs issue-label synchronization for PRs.
.github/​workflows/​hotfix-label-issue.yml Triggers backport issue creation.
.github/​workflows/​cherry-pick-hotfix.yml Grants issue lookup permission.
.github/​scripts/​sync-hotfix-label-to-pr.sh Copies hotfix labels from closing issues.
.github/​scripts/​create-backport-issue.sh Creates and links backport sub-issues.
.github/​scripts/​cherry-pick-to-release.sh Adds backport closure links to cherry-pick PRs.
.github/​scripts/​tests/​sync-hotfix-label-to-pr.bats Tests label synchronization.
.github/​scripts/​tests/​create-backport-issue.bats Tests backport issue creation.
.github/​scripts/​tests/​cherry-pick-to-release.bats Tests backport issue lookup and linking.
.github/​scripts/​tests/​README.md Documents the expanded Bats suite.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/scripts/cherry-pick-to-release.sh Outdated
Comment thread .github/scripts/create-backport-issue.sh Outdated
Comment thread .github/scripts/sync-hotfix-label-to-pr.sh Outdated
Comment thread .github/scripts/sync-hotfix-label-to-pr.sh Outdated
Comment thread .github/workflows/hotfix-label-issue.yml
Comment thread .github/workflows/sync-hotfix-label-to-pr.yml Outdated
Live-testing lookup_backport_issue() against real GitHub issues/PRs
revealed that 'gh api --jq --arg v "$version" ...' silently fails
(gh's --jq flag takes a single query string; it isn't a passthrough
to the jq binary's own flags). The stderr redirect masked the failure,
so the function always returned no match.

Fix by escaping and interpolating the version directly into the jq
filter string instead of relying on --arg.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 23, 2026 20:29
…error handling, exact label matching, workflow permissions

- cherry-pick-to-release.sh / sync-hotfix-label-to-pr.sh: filter
  closingIssuesReferences by repository before extracting issue numbers, so a
  cross-repo closing reference can't collide with a same-numbered local issue.
- create-backport-issue.sh: fail loudly instead of silently proceeding when
  the sub-issues duplicate-guard lookup itself fails, to avoid creating a
  duplicate backport issue on a rerun after a transient API error.
- sync-hotfix-label-to-pr.sh: require the exact "Hotfix X.Y.Z" grammar
  when collecting labels from referenced issues, matching the validation used
  elsewhere, instead of accepting any "Hotfix "-prefixed label.
- hotfix-label-issue.yml / sync-hotfix-label-to-pr.yml: add the missing
  'contents: read' permission needed by actions/checkout.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Retry safety and multi-issue handling can currently create duplicate tracking issues or leave valid backports open.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity · 6 Medium severity

Open (7)
Previously missed (3)

In code that hasn't changed since last review

Medium severity Process all matching parent issues before returning

.github/​scripts/​cherry-pick-to-release.sh:202

Returning after the first match leaves other backport issues open when one PR closes multiple Hotfix-labeled parent issues for the same version. Accumulate one Fixes line per matching parent and finish the loop instead.

Medium severity Fail on milestone API errors before using fallback

.github/​scripts/​create-backport-issue.sh:125

Because this API call is the left side of an if pipeline, an API failure is treated exactly like a missing milestone. The workflow then creates an unmilestoned issue despite the milestone potentially existing. Fetch the titles first so set -e stops on API failure, and only use the fallback after a successful lookup.

Medium severity Recover orphaned issues after partial creation failure

.github/​scripts/​create-backport-issue.sh:154

Issue creation is committed before the child is linked. If either the child-ID lookup or sub-issue POST fails, rerunning checks only linked sub-issues, does not find this orphan, and creates another backport issue. Before creating, detect and relink an existing issue with this generated title/parent marker (or otherwise persist recovery state) so retries remain idempotent after partial failure.

Comment thread .github/workflows/hotfix-label-issue.yml
Copilot AI review requested due to automatic review settings September 23, 2026 20:37
…ck-then-create race

Duplicate detection is a check-then-create sequence with no atomic guard.
Two deliveries/re-runs for the same issue+label could both observe no
existing child and create duplicates. A job-level concurrency group keyed
by issue number and label serializes runs so a second run always re-checks
after the first has finished.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Reliability gaps can miss labels, create duplicate orphan issues, or leave some backport issues unclosed.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Resolved since last review (7)
Previously missed (4)

In code that hasn't changed since last review

Medium severity Process all matching Hotfix child issues

.github/​scripts/​cherry-pick-to-release.sh:214

A PR can close multiple Hotfix-labeled issues, but this returns after the first matching child, so only one generated backport issue gets a Fixes line and the others remain open after the cherry-pick PR merges. Accumulate every version-matched child instead of stopping at the first.

Medium severity Use fixed-string matching for exact versions

.github/​scripts/​create-backport-issue.sh:137

This exact-version check is using a regular expression, so the dots in 7.1.1 match arbitrary characters; for example, milestone 7x1y1 is treated as a match and the subsequent create call then requests nonexistent milestone 7.1.1. Use fixed-string matching.

Medium severity Recover orphaned backport issues on rerun

.github/​scripts/​create-backport-issue.sh:166

After this issue is created, a failure while resolving its ID or linking it leaves an orphan. On rerun, the duplicate guard only searches existing sub-issues, so it cannot find that orphan and creates another backport issue. Make the create/link sequence recoverable by discovering and linking a previously created matching child before creating a new one.

Medium severity Sync labels to already-open closing PRs

.github/​workflows/​sync-hotfix-label-to-pr.yml:25

If an issue receives its Hotfix label after a closing PR is already open, none of these PR events is emitted. The backport child is created, but the PR never receives the label and can merge without triggering the cherry-pick workflow. Handle the issues:labeled path by finding and labeling existing closing PRs (or dispatching a reusable sync workflow), not only future PR events.

Comment thread .github/scripts/sync-hotfix-label-to-pr.sh Outdated
Copilot AI review requested due to automatic review settings September 23, 2026 20:43
The trailing '|| true' covered the whole 'gh issue view | grep' pipeline, so
a real gh API/permission failure was indistinguishable from an issue simply
having no Hotfix labels, and the run would succeed without labeling the PR.
Capture 'gh issue view' separately and fail loudly on its error; only grep's
no-match exit status is now tolerated.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

API failures can silently prevent synchronization or create duplicate orphan issues, and multi-issue PRs close only one backport issue.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (1)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Prevent orphaned duplicate child issues after linking failures

.github/​scripts/​create-backport-issue.sh:180

Issue creation and sub-issue linking are separate writes. If this POST fails after creation, the child remains orphaned; a rerun checks only linked sub-issues and creates another child, defeating duplicate protection. Before creating, detect and reuse an existing matching issue that references this parent, or otherwise make the failed link recoverable on rerun.

Low severity Update reported test count from 10 to 11

.github/​scripts/​tests/​README.md:125

This table reports 10 tests, but create-backport-issue.bats currently contains 11 @test cases. Update the count so the test inventory is accurate.

Comment thread .github/scripts/cherry-pick-to-release.sh
Copilot AI review requested due to automatic review settings September 23, 2026 20:48
Document how hotfix-label-issue.yml, sync-hotfix-label-to-pr.yml, and
cherry-pick-hotfix.yml work together, with a Mermaid diagram of the
end-to-end flow from labeling an issue through to the linked
cherry-pick PR. Link the new doc from each workflow's header comment.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
lookup_backport_issue() returned as soon as it found a matching
sub-issue for the first closing issue reference, so a PR that closes
multiple Hotfix-labeled parent issues for the same release only linked
one backport issue and left the others open. Accumulate a Fixes line
for every closing issue that has a matching backport sub-issue instead
of stopping at the first match.

Also simplify the hotfix-label-automation.md diagram to show actions
and results rather than individual workflow/script names.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Workflow-source placement and backport reconciliation defects can block CI or leave duplicate and unclosed tracking issues.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (1)
Previously missed (6)

In code that hasn't changed since last review

Low severity Replace non-ASCII punctuation in source comments

.github/​scripts/​cherry-pick-to-release.sh:170

This changed block adds literal non-ASCII em dashes to source comments. Repository policy requires Unicode escapes for non-ASCII source characters (policy/coding-style.md:56-58); use ASCII punctuation in the added comments.

Low severity Replace non-ASCII comment punctuation with ASCII

.github/​scripts/​create-backport-issue.sh:27

This file introduces literal non-ASCII punctuation in comments, including this em dash. Repository policy requires Unicode escapes for non-ASCII source characters (policy/coding-style.md:56-58); use ASCII punctuation throughout this new script.

This issue also appears on line 176 of the same file.

Low severity Replace non-ASCII comment punctuation with ASCII

.github/​scripts/​sync-hotfix-label-to-pr.sh:66

This file introduces literal non-ASCII punctuation in comments, including this em dash. Repository policy requires Unicode escapes for non-ASCII source characters (policy/coding-style.md:56-58); use ASCII punctuation throughout this new script.

Low severity Replace box-drawing separator with ASCII

.github/​scripts/​tests/​cherry-pick-to-release.bats:300

This added separator contains literal non-ASCII box-drawing characters, contrary to policy/coding-style.md:56-58. Use an ASCII-only comment separator.

Low severity Replace non-ASCII test comments with ASCII

.github/​scripts/​tests/​create-backport-issue.bats:92

The new test file uses literal box-drawing characters and em dashes in comments. Repository policy requires Unicode escapes for non-ASCII source characters (policy/coding-style.md:56-58); replace these comment separators and punctuation with ASCII throughout the file.

Low severity Replace non-ASCII test comments with ASCII

.github/​scripts/​tests/​sync-hotfix-label-to-pr.bats:94

The new test file uses literal box-drawing characters and em dashes in comments. Repository policy requires Unicode escapes for non-ASCII source characters (policy/coding-style.md:56-58); replace these comment separators and punctuation with ASCII throughout the file.

Comment thread .github/hotfix-label-automation.md Outdated
Copilot AI review requested due to automatic review settings September 23, 2026 20:54
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Release PRs can close unrelated issues, and backport creation is not retry-safe after partial failures.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity · 1 Low severity

Open (2)
Resolved since last review (4)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Reuse orphaned issues after partial backport link failure

.github/​scripts/​create-backport-issue.sh:180

If this POST fails after gh issue create succeeds, the new issue remains orphaned. A rerun only searches already-linked sub-issues, so it creates another issue instead of resuming the link, defeating idempotency during a partial API failure. Before creating, discover and reuse an existing generated issue (or otherwise persist/roll back this partial state) so retries can complete the link.

Comment thread .github/scripts/close-backport-issue.sh
Comment thread .github/scripts/tests/README.md
Copilot AI review requested due to automatic review settings September 23, 2026 21:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Release merges can close unrelated issues, while stale labels and partial failures can produce incorrect backports or duplicates.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 2 High severity · 1 Low severity

Open (3)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Reconcile stale backport labels on PR synchronization

.github/​scripts/​sync-hotfix-label-to-pr.sh:120

The synchronization is add-only. If a parent issue is retargeted from Hotfix 7.1.1 to Hotfix 7.1.2, a later PR edit or synchronize adds the new label but leaves the copied old label on the PR, so merging triggers cherry-picks to both release lines. Reconcile labels that no longer exist on current closing references, with a way to preserve labels intentionally applied directly to the PR.

Comment thread .github/workflows/close-backport-issue.yml Outdated
Comment thread .github/scripts/create-backport-issue.sh Outdated
…esReferences

closingIssuesReferences is not populated by closing keywords on PRs
targeting a non-default branch (only manually sidebar-linked issues show
up there), so close-backport-issue.sh could never actually find the
backport issue(s) to close for a cherry-pick PR. cherry-pick-to-release.sh
now also embeds a machine-readable
'<!-- backport-issue-numbers: N N ... -->' marker in the cherry-pick PR
body, and close-backport-issue.sh reads that marker instead. This also
scopes closing to only the issues our own automation recorded, never an
arbitrary 'Fixes #N' a human wrote in an unrelated manual release PR.

Also close the sync-hotfix-label-to-pr.yml timing gap: if an issue is
labeled 'Hotfix X.Y.Z' after its closing PR is already open, the workflow
now also reacts to the issue 'labeled' event, looks up the PR(s) that
will close it via closedByPullRequestsReferences, and re-runs the label
sync for each.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 23, 2026 21:23
@mdaigle

mdaigle commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up for the next agent:

  • sync-hotfix-label-to-pr.yml only runs on PR events. If an issue gets a Hotfix label after its closing PR opens, merging that PR without another update skips the cherry-pick. Re-sync on issue labeling or at merge.
  • close-backport-issue.sh reads closingIssuesReferences on release-branch PRs. GitHub ignores closing keywords outside the default branch, so this will not find the backport issues to close. Track the generated backport IDs instead.

Both addressed in 052b8f0:

  • sync-hotfix-label-to-pr.yml now also triggers on the issue labeled event; it looks up the PR(s) closing that issue via closedByPullRequestsReferences and re-runs the label sync for each.
  • close-backport-issue.sh no longer reads closingIssuesReferences. cherry-pick-to-release.sh now embeds a <!-- backport-issue-numbers: N N ... --> marker in the cherry-pick PR body, and close-backport-issue.sh parses that marker directly to find the backport issue(s) to close.

…matching

close-backport-issue.yml: note that the workflow's release/* guard is
intentionally broad because close-backport-issue.sh only acts on issues
named in the PR body's marker, making a manual release PR with no
marker a safe no-op.

create-backport-issue.sh: fix stale comments that implied a milestone
match alone is sufficient to detect a duplicate backport issue; the
code has always matched on the title prefix only.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Untrusted PR metadata can close arbitrary issues, and several reliability gaps can break backport tracking.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity · 1 Low severity

Open (2)
Resolved since last review (3)
Previously missed (1)

In code that hasn't changed since last review

Low severity Runtime help describes removed milestone-only duplicate guard

.github/​scripts/​create-backport-issue.sh:24

This runtime help text still says a matching milestone alone prevents creation, but the duplicate guard now deliberately matches only the deterministic [X.Y.Z] title prefix. Update the overview so it does not describe the behavior that was removed.

This issue also appears in the following locations of the same file:

  • line 145
  • line 171

Comment thread .github/scripts/sync-hotfix-label-from-issue.sh Outdated
Comment thread .github/scripts/tests/README.md
Copilot AI review requested due to automatic review settings September 23, 2026 21:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Independent workflow sequencing and non-atomic child linking can strand or duplicate backport issues.

Review effort: Balanced
Findings: 1 Medium severity · 1 Low severity

Open (2)
Previously missed (12)

In code that hasn't changed since last review

Medium severity Issue creation and linking are not rerun-safe

.github/​scripts/​create-backport-issue.sh:177

Issue creation and sub-issue linking are not failure-atomic. If either child-ID lookup or the POST at line 187 fails after this command succeeds, the run leaves an unlinked issue; a rerun only searches the parent's linked sub-issues, so it creates a second backport issue. Make reruns recover and link the already-created issue (using a unique automation marker/exact identity) before creating another one.

Medium severity Race can strand the backport child issue

.github/​workflows/​sync-hotfix-label-to-pr.yml:41

This issue-side job races the independent hotfix-label-issue.yml run triggered by the same labeled event. It can copy the label to an already-open (or auto-merge-ready) PR before the backport child is created; if that PR then merges, lookup_backport_issue finds nothing and silently generates a cherry-pick PR with no marker, and creation of the child later does not retry that lookup. Sequence child creation/linking before label propagation (for example, in one workflow with dependent jobs) so the advertised end-to-end flow cannot permanently strand the child issue.

Low severity Helper comments contain disallowed non-ASCII em dashes

.github/​scripts/​cherry-pick-to-release.sh:186

The newly added helper comments introduce literal non-ASCII em dashes, contrary to policy/coding-style.md:56-58, which requires non-ASCII source characters to be escaped. Use ASCII punctuation in the added comments.

Low severity Source comments contain literal non-ASCII em dashes

.github/​scripts/​close-backport-issue.sh:18

This added source file contains literal non-ASCII em dashes, contrary to policy/coding-style.md:56-58, which requires non-ASCII source characters to be escaped. Use ASCII punctuation in shell comments throughout this file.

Low severity Source comments contain disallowed non-ASCII punctuation

.github/​scripts/​create-backport-issue.sh:29

This added source file contains literal non-ASCII punctuation (including em dashes), contrary to policy/coding-style.md:56-58, which requires non-ASCII source characters to be escaped. Use ASCII punctuation in shell comments throughout this file to avoid encoding corruption.

Low severity Replace non-ASCII em dashes with ASCII punctuation

.github/​scripts/​sync-hotfix-label-to-pr.sh:68

This added source file uses literal non-ASCII em dashes, contrary to policy/coding-style.md:56-58, which requires non-ASCII source characters to be escaped. Replace them with ASCII punctuation throughout this file.

Low severity Test inventory omits label-sync coverage and marker behavior

.github/​scripts/​tests/​README.md:129

The inventory omits the new seven-test sync-hotfix-label-from-issue.bats suite, and the close suite no longer reads closing issue references—it reads the PR-body marker. Include the missing suite and describe the marker-based behavior so the manual test inventory matches the files.

Low severity Separators and comments contain disallowed non-ASCII characters

.github/​scripts/​tests/​close-backport-issue.bats:77

These decorative separators use literal non-ASCII box-drawing characters, contrary to policy/coding-style.md:56-58. Replace the separators and added em dashes with ASCII punctuation throughout this source file.

Low severity Decorative separators use disallowed box-drawing characters

.github/​scripts/​tests/​create-backport-issue.bats:92

These decorative separators use literal non-ASCII box-drawing characters, contrary to policy/coding-style.md:56-58. Replace the separators and added em dashes with ASCII punctuation throughout this source file.

Low severity Decorative separators contain non-ASCII box-drawing characters

.github/​scripts/​tests/​sync-hotfix-label-from-issue.bats:112

These decorative separators use literal non-ASCII box-drawing characters, contrary to policy/coding-style.md:56-58. Replace them with ASCII punctuation throughout this source file.

Low severity Decorative separators use disallowed box-drawing characters

.github/​scripts/​tests/​sync-hotfix-label-to-pr.bats:94

These decorative separators use literal non-ASCII box-drawing characters, contrary to policy/coding-style.md:56-58. Replace the separators and added em dashes with ASCII punctuation throughout this source file.

Low severity Workflow comment contains a disallowed non-ASCII em dash

.github/​workflows/​hotfix-label-issue.yml:44

This added workflow comment uses a literal non-ASCII em dash, contrary to policy/coding-style.md:56-58, which requires non-ASCII source characters to be escaped. Replace it with ASCII punctuation.

sync-hotfix-label-from-issue.sh only synced the Hotfix label onto OPEN
PRs and relied on cherry-pick-hotfix.yml's 'labeled' webhook to pick it
up. Two problems:

1. If the fixing PR was already merged before the issue got labeled
   (as in dotnet#4737/dotnet#4738), it was excluded by the OPEN-only filter.
2. Even once included, adding the label via the workflow's own
   GITHUB_TOKEN doesn't fire a new 'labeled' event for GitHub Actions
   to react to, so cherry-pick-hotfix.yml would never run anyway.

Fix:
- extract-hotfix-versions.sh: add a 'reconcile' EVENT_ACTION mode that
  re-derives all current Hotfix labels on a PR (like 'closed') but
  still skips any version that already has a cherry-pick branch/PR
  (like 'labeled'), so it's safe to re-run after earlier events have
  already processed some of the labels.
- cherry-pick-hotfix.yml: add a workflow_dispatch trigger (pr_number
  input) with a new resolve-pr job that fetches PR context via the API
  when dispatched, instead of relying solely on the pull_request_target
  payload; uses EVENT_ACTION=reconcile for the dispatch path.
- sync-hotfix-label-from-issue.sh: broaden the closedByPullRequestsReferences
  filter to include MERGED (not just OPEN) PRs, and explicitly dispatch
  cherry-pick-hotfix.yml for any merged PR after syncing its label.
- sync-hotfix-label-to-pr.yml: grant 'actions: write' so the script can
  dispatch the workflow.

Also add sync-hotfix-label-from-issue.bats to the README's per-file
test command list.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 23, 2026 21:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Untrusted PR-title interpolation enables command execution, and workflow races can leave duplicate or unclosed backport issues.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
Resolved since last review (2)
Previously missed (4)

In code that hasn't changed since last review

Medium severity Duplicate check accepts invalid marker prefix

.github/​scripts/​create-backport-issue.sh:124

The generated marker is [VERSION] (including a space), and lookup_backport_issue requires that exact prefix, but this check accepts any title beginning with [VERSION]. An unrelated child titled [7.1.1]notes would suppress creation even though it can never be found later as the backport issue. Include the trailing space in the duplicate predicate.

Medium severity Use fixed-string milestone matching

.github/​scripts/​create-backport-issue.sh:148

grep treats the dots in VERSION as regex wildcards, so an unrelated open milestone such as 7x1y1 makes 7.1.1 appear to exist. The subsequent gh issue create --milestone 7.1.1 then fails instead of taking the documented milestone-missing path. Use fixed-string matching.

Medium severity Unlinked issue creation causes duplicate backport issues

.github/​scripts/​create-backport-issue.sh:191

Issue creation and sub-issue linking are not recoverable as a unit. If this POST fails after gh issue create succeeds, the new issue remains unlinked; a rerun only searches linked sub-issues, so it creates another backport issue and can repeat indefinitely. Before creating, detect/recover an orphan using a deterministic parent/version marker, or close/delete the just-created issue when linking fails.

Low severity Update stale manual test count

.github/​scripts/​tests/​README.md:131

The inventory is stale: close-backport-issue.bats currently contains 9 @test cases, not 8. Update the count so the documented manual test inventory remains accurate.

Comment thread .github/workflows/cherry-pick-hotfix.yml Outdated
Comment thread .github/scripts/sync-hotfix-label-from-issue.sh
Two follow-up review findings on the reconcile-mode fix (ce8ba9f):

- cherry-pick-hotfix.yml: the "Merge resolved outputs" step re-embedded
  the already-resolved PR title directly into an expression inside the
  run script, reintroducing the same injection risk the earlier
  resolve_event step took care to avoid via env. Pass it through env
  (RESOLVED_PR_TITLE) instead.

- cherry-pick-to-release.sh: sync-hotfix-label-from-issue.sh's new
  workflow_dispatch (reconcile) call and hotfix-label-issue.yml's
  backport-issue creation are both triggered by the same issue "labeled"
  event, with no ordering guarantee between them. For an already-merged
  PR, the cherry-pick could reach lookup_backport_issue before the
  backport issue exists, silently finding nothing to link. Retry the
  sub-issue lookup a few times (bounded, with a short delay) as long as
  the parent issue still carries the Hotfix label that would have
  triggered its creation, so the far more common "no backport issue
  expected" case still returns immediately.

Adds bats coverage for both the retry-then-find and
retry-then-give-up cases; full suite (128 tests) passing.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 23, 2026 21:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Reconciliation can omit later backport issues, marker trust permits unintended issue closure, and issue creation is not recoverable after partial failure.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (2)
Previously missed (3)

In code that hasn't changed since last review

Medium severity Backport prefix check omits required trailing space

.github/​scripts/​create-backport-issue.sh:124

The generated title prefix includes a trailing space, but this check does not. An unrelated child such as [7.1.1]-investigation therefore suppresses creation of the real [7.1.1] <parent title> backport issue, while the later lookup correctly requires the space. Match the same exact prefix grammar in both places.

This issue also appears on line 173 of the same file.

Medium severity Existing cherry-pick PR omits later matching backport issues

.github/​scripts/​extract-hotfix-versions.sh:150

A later Hotfix label on another issue closed by the same merged PR is lost here. The first label can create the version's cherry-pick PR and marker; when the second issue is labeled, reconcile sees that branch/PR and skips the version before lookup_backport_issue can add the newly created child, so that backport issue is never linked or closed. Reconciliation needs to update the existing cherry-pick PR's marker/body with all current matching backport issues rather than treating an existing PR as a complete no-op.

Low severity Update inventory for PR body marker parsing

.github/​scripts/​tests/​README.md:131

This suite no longer reads GitHub closing-issue references; it parses the backport-issue-numbers marker from the PR body. Update the inventory so it describes the mechanism the tests and script now exercise.

Comment thread .github/workflows/close-backport-issue.yml Outdated
The backport-issue-numbers marker in a PR body is plain text any PR
author could include. Since this workflow runs as pull_request_target
with issues: write, a merged fork PR carrying a forged marker could
close arbitrary issues. Require the merged PR's head to be same-repo
and match the "dev/automation/pr-<N>-to-<version>" branch naming
convention that cherry-pick-to-release.sh always uses, so the job only
ever fires for PRs our own automation created.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 23, 2026 21:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Concurrent reconciliation and partial issue-link failures can leave hotfix automation incomplete or duplicated.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (1)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Require consistent space-delimited title prefix matching

.github/​scripts/​create-backport-issue.sh:124

The generated title prefix includes a trailing space, and lookup_backport_issue requires that exact [VERSION] prefix, but this broader match also accepts unrelated titles such as [7.1.1]follow-up. That false positive suppresses creation while the later lookup cannot recognize the issue, leaving the backport untracked. Match the same space-delimited prefix used by creation and lookup.

This issue also appears on line 185 of the same file.

Low severity Update stale test count and coverage description

.github/​scripts/​tests/​README.md:131

This inventory is stale: close-backport-issue.bats currently contains 9 tests, and the suite parses the backport-issue-numbers body marker rather than GitHub closing issue references. Update both the count and coverage description.

Comment thread .github/workflows/cherry-pick-hotfix.yml
A single merged PR can carry multiple "Hotfix <version>" labels, and each
labeling event, the 'closed' event, and any 'workflow_dispatch' reconcile
run from sync-hotfix-label-from-issue.sh independently triggers this
workflow. Concurrent runs for the same PR raced on the shared
branch/PR-existence check in cherry-pick-to-release.sh: one run's push or
'gh pr create' could fail because another run already created the
branch/PR, or a run that checked existence just before another run
created it could skip a version permanently. Add a workflow-level
concurrency group keyed by PR number, queuing (not cancelling) runs so
each one's existence check always reflects every earlier run for that PR.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 23, 2026 22:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Partial issue-linking failures can create duplicate backport issues, and duplicate-prefix matching is inconsistent.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (3)

In code that hasn't changed since last review

Medium severity Require trailing space after version prefix

.github/​scripts/​create-backport-issue.sh:124

This does not require the documented [VERSION] prefix because the wildcard starts immediately after ]. An unrelated child such as [7.1.1]-notes would suppress creation, while lookup_backport_issue only recognizes [7.1.1] , leaving no backport issue to link. Include the trailing space in this match.

Medium severity Recover orphaned issues before creating duplicates

.github/​scripts/​create-backport-issue.sh:177

Issue creation and sub-issue linking are separate operations, but rerun detection only scans already-linked children. If creation succeeds and either the child lookup or POST fails transiently, the rerun cannot rediscover the orphan and creates a duplicate. Recover an existing issue using the deterministic title/body before creating a new one, then retry linking it.

Low severity Correct test inventory count from 8 to 9

.github/​scripts/​tests/​README.md:131

The inventory is off by one: close-backport-issue.bats currently contains 9 @test cases, not 8.

@paulmedynski
paulmedynski self-requested a review September 23, 2026 23:29

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: To triage

Development

Successfully merging this pull request may close these issues.

3 participants