name: check-milestones
description: "Check and fix milestones on PRs and their associated issues. Sets PR milestones based on the branch they merged into, and issue milestones based on the smallest version with a merged uplift. Triggers on: check milestones, fix milestones, /check-milestones."
argument-hint: [github-username] [all|PR1,PR2,PR3]
disable-model-invocation: true
allowed-tools: Bash, Read, WebFetch, Grep, Glob
Check Milestones
Check and fix milestones on a contributor's merged PRs and their associated GitHub issues.
Inputs
- Arguments:
$ARGUMENTS — space-separated values:
- First argument: GitHub username (the author whose merged PRs to check)
- Second argument (optional): PR filter — either:
all — evaluate all closed/merged PRs from this author in the past 30 days. Use gh pr list --repo brave/brave-core --author <username> --state closed --limit 200 --search "closed:>YYYY-MM-DD" --json number,title,mergedAt,mergeCommit,labels,body,url,baseRefName,milestone --jq 'sort_by(.mergedAt)' where YYYY-MM-DD is 30 days ago.
- A comma-separated list of PR numbers with no spaces (e.g.,
33534,33547,33580) — only evaluate these specific PRs. Fetch each one individually with gh pr view <number> --repo brave/brave-core --json number,title,mergedAt,mergeCommit,labels,body,url,baseRefName,milestone.
- If omitted, defaults to the recent 50 closed PRs.
Parse the arguments by splitting $ARGUMENTS on whitespace. Examples:
/check-milestones netzenbot → username=netzenbot, filter=recent 50
/check-milestones netzenbot all → username=netzenbot, filter=all PRs (past 30 days)
/check-milestones netzenbot 33534,33547,33580 → username=netzenbot, filter=only those 3 PRs
Step 1: Gather Information
Run these in parallel:
Fetch PRs (method depends on the second argument):
- Default (no second arg): Use
gh pr list --repo brave/brave-core --author <username> --state closed --limit 50 --json number,title,mergedAt,mergeCommit,labels,body,url,baseRefName,milestone --jq 'sort_by(.mergedAt)'
all: Use gh pr list --repo brave/brave-core --author <username> --state closed --limit 200 --search "closed:>YYYY-MM-DD" --json number,title,mergedAt,mergeCommit,labels,body,url,baseRefName,milestone --jq 'sort_by(.mergedAt)' where YYYY-MM-DD is 30 days ago from today.
- Comma-separated PR list: For each PR number, use
gh pr view <number> --repo brave/brave-core --json number,title,mergedAt,mergeCommit,labels,body,url,baseRefName,milestone. Collect results into a list sorted by mergedAt.
Skip any PR where mergedAt is null (not merged).
Fetch the release schedule: Fetch the content at https://github.com/brave/brave-browser/wiki/Brave-Release-Schedule and find the "Current channel information" table. Extract the version numbers for each channel:
- Nightly row → version (e.g.,
1.89.x)
- Beta row → version (e.g.,
1.88.x)
- Release row → version (e.g.,
1.87.x)
These map to milestone names:
<nightly-version> - Nightly (e.g., 1.89.x - Nightly)
<beta-version> - Beta (e.g., 1.88.x - Beta)
<release-version> - Release (e.g., 1.87.x - Release)
Step 2: Determine Correct PR Milestones
For each merged PR, determine the correct milestone based on its baseRefName (the branch it was merged into):
- If
baseRefName is master or main → milestone is <nightly-version> - Nightly
- If
baseRefName matches the beta branch (e.g., 1.88.x) → milestone is <beta-version> - Beta
- If
baseRefName matches the release branch (e.g., 1.87.x) → milestone is <release-version> - Release
- If
baseRefName is some other branch → skip (cannot determine milestone)
Compare the PR's current milestone (from the milestone field) against the correct one. If they differ (or the milestone is not set), add the PR to the list of PRs that need updating.
Step 3: Determine Correct Issue Milestones
For each merged PR, extract the associated issue number(s) from the PR body. Look for patterns like:
Resolves #XXXXX or Resolves brave/brave-browser#XXXXX
Fixes #XXXXX or Fixes brave/brave-browser#XXXXX
Fixes https://github.com/brave/brave-browser/issues/XXXXX
Resolves https://github.com/brave/brave-browser/issues/XXXXX
For each associated issue:
Find all PRs that reference this issue — check if the issue has uplift PRs by searching for other merged PRs that reference the same issue across different branches. You can use:
gh api search/issues --method GET \
-f q="repo:brave/brave-core is:pr is:merged $ISSUE_NUMBER" \
--jq '.items[] | {number, title, html_url, pull_request}'
Or check the PR's labels for uplift/beta and uplift/release to identify if uplift PRs exist.
Determine which branches this fix has been merged into (considering uplifts):
- The original PR's base branch (e.g.,
master)
- If there is a merged uplift PR to beta → the beta branch
- If there is a merged uplift PR to release → the release branch
- Uplifts that are NOT merged do not count
The correct issue milestone is the smallest version where the fix is merged:
- If merged into release branch → milestone is
<release-version> - Release
- Else if merged into beta branch → milestone is
<beta-version> - Beta
- Else if merged into master → milestone is
<nightly-version> - Nightly
Check the issue's current milestone and compare:
gh issue view <ISSUE_NUMBER> --repo brave/brave-browser --json milestone --jq '.milestone.title'
Step 4: Apply Milestone Updates
Update PR Milestones
For each PR that needs a milestone update:
gh pr edit <PR_NUMBER> --repo brave/brave-core --milestone "<milestone-name>"
Update Issue Milestones
For each issue that needs a milestone update:
gh issue edit <ISSUE_NUMBER> --repo brave/brave-browser --milestone "<milestone-name>"
Important: Only update an issue's milestone to a smaller version number than what is currently set. For example:
- Milestone is unset → set it to the computed milestone
- Milestone is
1.89.x - Nightly but fix was uplifted to beta → update to 1.88.x - Beta
- Milestone is
1.88.x - Beta but fix was uplifted to release → update to 1.87.x - Release
Do NOT update if the current milestone already has a smaller version number than the computed one (e.g., do not change 1.87.x - Release to 1.88.x - Beta).
Step 5: Summary
Output a clear summary of all actions taken:
PR Milestones Updated:
| PR |
Title |
Base Branch |
Old Milestone |
New Milestone |
| #XXXXX |
PR title |
master |
(none) |
1.89.x - Nightly |
Issue Milestones Updated:
| Issue |
Old Milestone |
New Milestone |
Reason |
| brave/brave-browser#XXXXX |
(none) |
1.88.x - Beta |
Merged uplift to beta (#YYYY) |
Already Correct:
List PRs and issues that already had the correct milestone (brief count or list).
Skipped:
List any PRs or issues that were skipped with the reason (e.g., "no associated issue", "could not determine branch", "unmerged uplift").
1---2name: check-milestones3description: Check and fix milestones on a contributor's merged PRs and their associated GitHub issues.4---5
6---
7name: check-milestones
8description: "Check and fix milestones on PRs and their associated issues. Sets PR milestones based on the branch they merged into, and issue milestones based on the smallest version with a merged uplift. Triggers on: check milestones, fix milestones, /check-milestones."
9argument-hint: [github-username] [all|PR1,PR2,PR3]
10disable-model-invocation: true
11allowed-tools: Bash, Read, WebFetch, Grep, Glob
12---
13
14# Check Milestones
15
16Check and fix milestones on a contributor's merged PRs and their associated GitHub issues.
17
18## Inputs
19
20- **Arguments**: `$ARGUMENTS` — space-separated values:
21 - First argument: **GitHub username** (the author whose merged PRs to check)
22 - Second argument (optional): **PR filter** — either:
23 - `all` — evaluate all closed/merged PRs from this author in the past 30 days. Use `gh pr list --repo brave/brave-core --author <username> --state closed --limit 200 --search "closed:>YYYY-MM-DD" --json number,title,mergedAt,mergeCommit,labels,body,url,baseRefName,milestone --jq 'sort_by(.mergedAt)'` where `YYYY-MM-DD` is 30 days ago.
24 - A comma-separated list of PR numbers with no spaces (e.g., `33534,33547,33580`) — only evaluate these specific PRs. Fetch each one individually with `gh pr view <number> --repo brave/brave-core --json number,title,mergedAt,mergeCommit,labels,body,url,baseRefName,milestone`.
25 - If omitted, defaults to the recent 50 closed PRs.
26
27Parse the arguments by splitting `$ARGUMENTS` on whitespace. Examples:
28- `/check-milestones netzenbot` → username=`netzenbot`, filter=recent 50
29- `/check-milestones netzenbot all` → username=`netzenbot`, filter=all PRs (past 30 days)
30- `/check-milestones netzenbot 33534,33547,33580` → username=`netzenbot`, filter=only those 3 PRs
31
32---
33
34## Step 1: Gather Information
35
36Run these in parallel:
37
381. **Fetch PRs** (method depends on the second argument):
39 - **Default (no second arg)**: Use `gh pr list --repo brave/brave-core --author <username> --state closed --limit 50 --json number,title,mergedAt,mergeCommit,labels,body,url,baseRefName,milestone --jq 'sort_by(.mergedAt)'`
40 - **`all`**: Use `gh pr list --repo brave/brave-core --author <username> --state closed --limit 200 --search "closed:>YYYY-MM-DD" --json number,title,mergedAt,mergeCommit,labels,body,url,baseRefName,milestone --jq 'sort_by(.mergedAt)'` where `YYYY-MM-DD` is 30 days ago from today.
41 - **Comma-separated PR list**: For each PR number, use `gh pr view <number> --repo brave/brave-core --json number,title,mergedAt,mergeCommit,labels,body,url,baseRefName,milestone`. Collect results into a list sorted by `mergedAt`.
42
43 Skip any PR where `mergedAt` is null (not merged).
44
452. **Fetch the release schedule**: Fetch the content at `https://github.com/brave/brave-browser/wiki/Brave-Release-Schedule` and find the "Current channel information" table. Extract the version numbers for each channel:
46 - **Nightly** row → version (e.g., `1.89.x`)
47 - **Beta** row → version (e.g., `1.88.x`)
48 - **Release** row → version (e.g., `1.87.x`)
49
50 These map to milestone names:
51 - `<nightly-version> - Nightly` (e.g., `1.89.x - Nightly`)
52 - `<beta-version> - Beta` (e.g., `1.88.x - Beta`)
53 - `<release-version> - Release` (e.g., `1.87.x - Release`)
54
55---
56
57## Step 2: Determine Correct PR Milestones
58
59For each merged PR, determine the correct milestone based on its `baseRefName` (the branch it was merged into):
60
61- If `baseRefName` is `master` or `main` → milestone is `<nightly-version> - Nightly`
62- If `baseRefName` matches the beta branch (e.g., `1.88.x`) → milestone is `<beta-version> - Beta`
63- If `baseRefName` matches the release branch (e.g., `1.87.x`) → milestone is `<release-version> - Release`
64- If `baseRefName` is some other branch → skip (cannot determine milestone)
65
66Compare the PR's current milestone (from the `milestone` field) against the correct one. If they differ (or the milestone is not set), add the PR to the list of PRs that need updating.
67
68---
69
70## Step 3: Determine Correct Issue Milestones
71
72For each merged PR, extract the associated issue number(s) from the PR body. Look for patterns like:
73- `Resolves #XXXXX` or `Resolves brave/brave-browser#XXXXX`
74- `Fixes #XXXXX` or `Fixes brave/brave-browser#XXXXX`
75- `Fixes https://github.com/brave/brave-browser/issues/XXXXX`
76- `Resolves https://github.com/brave/brave-browser/issues/XXXXX`
77
78For each associated issue:
79
801. **Find all PRs that reference this issue** — check if the issue has uplift PRs by searching for other merged PRs that reference the same issue across different branches. You can use:
81 ```bash
82 gh api search/issues --method GET \
83 -f q="repo:brave/brave-core is:pr is:merged $ISSUE_NUMBER" \
84 --jq '.items[] | {number, title, html_url, pull_request}'
85 ```
86 Or check the PR's labels for `uplift/beta` and `uplift/release` to identify if uplift PRs exist.
87
882. **Determine which branches this fix has been merged into** (considering uplifts):
89 - The original PR's base branch (e.g., `master`)
90 - If there is a **merged** uplift PR to beta → the beta branch
91 - If there is a **merged** uplift PR to release → the release branch
92 - Uplifts that are NOT merged do not count
93
943. **The correct issue milestone is the smallest version** where the fix is merged:
95 - If merged into release branch → milestone is `<release-version> - Release`
96 - Else if merged into beta branch → milestone is `<beta-version> - Beta`
97 - Else if merged into master → milestone is `<nightly-version> - Nightly`
98
994. **Check the issue's current milestone** and compare:
100 ```bash
101 gh issue view <ISSUE_NUMBER> --repo brave/brave-browser --json milestone --jq '.milestone.title'
102 ```
103
104---
105
106## Step 4: Apply Milestone Updates
107
108### Update PR Milestones
109
110For each PR that needs a milestone update:
111```bash
112gh pr edit <PR_NUMBER> --repo brave/brave-core --milestone "<milestone-name>"
113```
114
115### Update Issue Milestones
116
117For each issue that needs a milestone update:
118```bash
119gh issue edit <ISSUE_NUMBER> --repo brave/brave-browser --milestone "<milestone-name>"
120```
121
122**Important**: Only update an issue's milestone to a **smaller** version number than what is currently set. For example:
123- Milestone is unset → set it to the computed milestone
124- Milestone is `1.89.x - Nightly` but fix was uplifted to beta → update to `1.88.x - Beta`
125- Milestone is `1.88.x - Beta` but fix was uplifted to release → update to `1.87.x - Release`
126
127Do NOT update if the current milestone already has a smaller version number than the computed one (e.g., do not change `1.87.x - Release` to `1.88.x - Beta`).
128
129---
130
131## Step 5: Summary
132
133Output a clear summary of all actions taken:
134
135### PR Milestones Updated:
136| PR | Title | Base Branch | Old Milestone | New Milestone |
137|----|-------|-------------|---------------|---------------|
138| #XXXXX | PR title | master | (none) | 1.89.x - Nightly |
139
140### Issue Milestones Updated:
141| Issue | Old Milestone | New Milestone | Reason |
142|-------|---------------|---------------|--------|
143| brave/brave-browser#XXXXX | (none) | 1.88.x - Beta | Merged uplift to beta (#YYYY) |
144
145### Already Correct:
146List PRs and issues that already had the correct milestone (brief count or list).
147
148### Skipped:
149List any PRs or issues that were skipped with the reason (e.g., "no associated issue", "could not determine branch", "unmerged uplift").