Uplift PR Creator
Create an uplift pull request that cherry-picks intermittent test fixes and crash fixes from a contributor's recently closed/merged PRs into a target channel branch.
Inputs
- •Arguments:
$ARGUMENTS— space-separated values:- •First argument: GitHub username (the author whose closed PRs to review)
- •Second argument (optional): Target channel — either
betaorrelease. Defaults tobetaif not specified. - •Third argument (optional): PR filter — either:
- •
all— evaluate all closed/merged PRs from this author in the past 30 days. Usegh 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 --jq 'sort_by(.mergedAt)'whereYYYY-MM-DDis 30 days ago. - •A duration like
<N>d(e.g.,10d,60d,7d) — evaluate all closed/merged PRs from this author in the past N days. Usegh 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 --jq 'sort_by(.mergedAt)'whereYYYY-MM-DDis N days ago from today. Parse the number by stripping the trailingd. - •A comma-separated list of PR numbers with no spaces (e.g.,
33534,33547,33580) — only evaluate these specific PRs. Fetch each one individually withgh pr view <number> --repo brave/brave-core --json number,title,mergedAt,mergeCommit,labels,body,url. - •If omitted, defaults to the recent 50 closed PRs (current behavior).
- •
Parse the arguments by splitting $ARGUMENTS on whitespace. Examples:
- •
/uplift netzenbot→ username=netzenbot, channel=beta, filter=recent 50 - •
/uplift netzenbot beta→ username=netzenbot, channel=beta, filter=recent 50 - •
/uplift netzenbot release→ username=netzenbot, channel=release, filter=recent 50 - •
/uplift netzenbot beta all→ username=netzenbot, channel=beta, filter=all PRs (past 30 days) - •
/uplift netzenbot beta 10d→ username=netzenbot, channel=beta, filter=all PRs (past 10 days) - •
/uplift netzenbot release 60d→ username=netzenbot, channel=release, filter=all PRs (past 60 days) - •
/uplift netzenbot release 33534,33547,33580→ username=netzenbot, channel=release, filter=only those 3 PRs
Step 1: Gather Information
Run these in parallel:
- •
Fetch closed PRs (method depends on the third argument):
- •Default (no third arg): Use
gh pr list --repo brave/brave-core --author <username> --state closed --limit 50 --json number,title,mergedAt,mergeCommit,labels,body,url --jq 'sort_by(.mergedAt)' - •
all: Usegh 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 --jq 'sort_by(.mergedAt)'whereYYYY-MM-DDis 30 days ago from today. - •
<num>dduration (e.g.,10d,60d): Usegh 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 --jq 'sort_by(.mergedAt)'whereYYYY-MM-DDis<num>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. Collect results into a list sorted bymergedAt.
The
mergedAtfield is a GitHub API property — if it isnull, the PR was closed without being merged and should be skipped. - •Default (no third arg): Use
- •
Determine the target branch: Fetch the content at
https://github.com/brave/brave-browser/wiki/Brave-Release-Scheduleand find the "Current channel information" table. Look for the row matching the target channel:- •If channel is
beta: find the Beta row to get its branch name (e.g.,1.88.x) - •If channel is
release: find the Release row to get its branch name (e.g.,1.87.x)
This branch is:
- •The base branch to create the uplift PR against
- •The branch to cherry-pick commits into
- •If channel is
Step 2: Classify PRs
Review each merged PR (skip any where mergedAt is null) and classify it as either include or exclude for the uplift:
INCLUDE if the PR is any of:
- •Intermittent/flaky test fix (titles often contain "Fix flaky", "Fix test:", "Fix intermittent", "Disable flaky")
- •Crash fix (titles mention "crash", "null dereference", "EXCEPTION_ACCESS_VIOLATION", etc.)
- •Test filter updates (disabling broken upstream tests, updating stale filter entries)
EXCLUDE if the PR is:
- •A feature addition (not a fix)
- •A refactor unrelated to test stability or crashes
- •Already has the uplift label for the target channel (check the
labelsarray in the PR JSON foruplift/betaoruplift/releasedepending on the target channel) - •Not merged (
mergedAtis null)
Step 3: Cherry-Pick in Chronological Order
- •Detect the remote: Run
git remote -vto determine whetherupstreamororiginpoints tobrave/brave-core. Use whichever remote is correct (typicallyoriginif there's noupstream). - •Fetch the target branch:
git fetch <remote> <target-branch> - •Choose a unique branch name: Use
uplift_<username>_<target-branch>as the base name. If that branch already exists (locally or on the remote), append a numeric suffix (e.g.,uplift_<username>_<target-branch>_2,_3, etc.) until you find an unused name. Create the branch:git checkout -b <branch-name> <remote>/<target-branch> - •Filter out commits already in the target branch: Before cherry-picking, check which included commits are already present in the target branch. For each commit, search the target branch log for the PR number from the commit message (e.g.,
git log <remote>/<target-branch> --oneline --grep="#XXXXX"). If a match is found, that PR is already in the target branch — mark it as excluded with reason "Already in target branch" and skip it. This avoids empty cherry-picks and unnecessary merge conflicts. - •Cherry-pick the remaining commits sorted by
mergedAttimestamp (earliest first):bashgit cherry-pick <merge_commit_sha>
- •If a cherry-pick has conflicts, try to resolve them. If unresolvable, skip that PR and note it in the summary.
Step 4: Pre-submission Checks
After all cherry-picks are complete but before pushing, run these checks:
- •Run format:
npm run format - •Run gn_check:
npm run gn_check
If either command indicates changes are needed (e.g., formatting fixes, GN file updates), make the necessary fixes and amend the last commit:
git add -A && git commit --amend --no-edit
- •Run presubmit:
npm run presubmit -- --base=<remote>/<target-branch> --fix(e.g.,npm run presubmit -- --base=origin/1.87.x --fix)
If the presubmit check fails for reasons unrelated to the cherry-picked changes (e.g., pre-existing issues in the target branch), note the failures in the summary but proceed with the uplift.
Step 5: Create the Uplift PR
Title Format
Generate the title dynamically based on the categories of PRs actually included:
- •If the uplift contains only intermittent/flaky test fixes and test filter updates (no crash fixes):
Uplift intermittent test fixes to <target-branch> - •If the uplift contains only crash fixes (no test fixes):
Uplift crash fixes to <target-branch> - •If the uplift contains both test fixes and crash fixes:
Uplift intermittent test fixes and crash fixes to <target-branch>
Body Format
Only list the PRs being uplifted. Do NOT mention excluded PRs in the PR body.
Use a HEREDOC for correct formatting:
gh pr create --repo brave/brave-core --base <target-branch> --title "<title>" --body "$(cat <<'EOF'
Uplift of #XXXX, #YYYY, #ZZZZ
## Included PRs
- #XXXX - <PR title>
- #YYYY - <PR title>
...
Pre-approval checklist:
- [ ] You have tested your change on Nightly.
- [ ] This contains text which needs to be translated.
- [ ] There are more than 7 days before the release.
- [ ] I've notified folks in #l10n on Slack that translations are needed.
- [ ] The PR milestones match the branch they are landing to.
Pre-merge checklist:
- [ ] You have checked CI and the builds, lint, and tests all pass or are not related to your PR.
Post-merge checklist:
- [ ] The associated issue milestone is set to the smallest version that the changes is landed on.
EOF
)"
Labels
- •If all included PRs are test filter-only changes (i.e., only modifying files in
test/filters/), add theCI/skiplabel to the uplift PR. - •Do NOT add
CI/skipif any included PR contains code changes beyond filter files.
Push and Create
git push -u origin <branch-name>
Step 6: Label the Base PRs
After the uplift PR is created, add the appropriate uplift label to each base PR that was included in the uplift:
- •For beta:
uplift/beta - •For release:
uplift/release
gh pr edit <PR_NUMBER> --repo brave/brave-core --add-label "uplift/<channel>"
Do this for every PR that was successfully cherry-picked and included.
Step 7: Summary
After creating the PR, output a clear summary to the user:
Uplifted:
List each included PR with its number, title, and merge commit SHA.
Not Uplifted:
List each excluded PR with its number, title, and the reason it was excluded (e.g., "not merged", "already uplifted (has uplift label)", "already in target branch", "not a test fix or crash fix", "cherry-pick conflict").
PR Link:
Provide the URL of the newly created uplift PR.