Create milestone if missing in label-and-milestone workflow#37946
Conversation
When the label-and-milestone-issues workflow sets a milestone on closed issues, create the milestone via the REST API if it doesn't already exist, instead of failing with 'milestone not found'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the automation workflow which labels issues and sets milestones when a PR is merged, adding support for creating the target milestone automatically if it doesn’t already exist.
Changes:
- Switch milestone lookup variable from
consttoletto allow fallback behavior. - If the version milestone isn’t found via GraphQL, create it via the REST API and then continue setting it on closing issues.
You can also share your feedback on Copilot code review. Take the survey.
- Include closed milestones in GraphQL query (states: [OPEN, CLOSED]) and increase first to 10 to avoid missing exact matches - Wrap createMilestone in try/catch with a descriptive error message Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| query($owner: String!, $repo: String!, $title: String!) { | ||
| repository(owner: $owner, name: $repo) { | ||
| milestones(query: $title, first: 1) { | ||
| milestones(query: $title, states: [OPEN, CLOSED], first: 10) { |
There was a problem hiding this comment.
I'm actually not sure why copilot suggested changing 1 to anything - we're already filtering by the milestone name/title, so I don't think we need to worry about getting more than one result here.
There was a problem hiding this comment.
Pull request overview
Updates the issue labeling/milestoning workflow to be more resilient when the expected target milestone doesn’t already exist, ensuring merged PRs can still auto-apply milestones based on eng/Versions.props.
Changes:
- Expands the milestone lookup to include both open and closed milestones.
- Creates the target milestone via REST API when it isn’t found by the GraphQL lookup.
You can also share your feedback on Copilot code review. Take the survey.
| query($owner: String!, $repo: String!, $title: String!) { | ||
| repository(owner: $owner, name: $repo) { | ||
| milestones(query: $title, first: 1) { | ||
| milestones(query: $title, states: [OPEN, CLOSED], first: 1) { |
There was a problem hiding this comment.
Ah, I understand it now - apparently the graphql search for the milestone name is fuzzy, so 10.0.5 may match 10.0.50; so it left some margin for multiple milestones and then filters for the exact name client-side. Seems legit, I guess.
5a2eea3 to
e80b9c8
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Updates the issue labeling/milestoning GitHub Actions workflow to be more resilient when identifying the correct milestone for a merged PR by searching a broader milestone set and creating the milestone when missing.
Changes:
- Extend the milestone GraphQL query to include both open and closed milestones and fetch more candidates.
- Add client-side exact-title filtering and fallback logic to create the milestone if not found.
- Improve inline documentation/comments to explain GraphQL fuzzy matching behavior and the rationale.
You can also share your feedback on Copilot code review. Take the survey.
| }); | ||
| milestoneNode = { number: created.number, title: created.title }; | ||
| } catch (error) { | ||
| throw new Error(`Failed to create milestone '${targetMilestoneName}': ${error.message}`); |
When the
label-and-milestone-issuesworkflow sets a milestone on closed issues, the target milestone may not exist yet (e.g. at the start of a new release cycle). Previously, the workflow would fail with "milestone not found". This is what caused the recent failure in https://github.com/dotnet/efcore/actions/runs/23209020591.This change creates the milestone via the GitHub REST API (
issues.createMilestone) when it doesn't already exist, so the workflow succeeds without manual intervention.