From ba869a315b1b6f618f7fd66c9805dd5c758d783d Mon Sep 17 00:00:00 2001 From: Tatiana Bobritsky Date: Tue, 25 Aug 2026 15:19:24 -0400 Subject: [PATCH 1/5] fix: only merge older RCs with open release PRs --- .github/scripts/merge-previous-releases.sh | 64 ++++++++++++++++------ CHANGELOG.md | 4 ++ 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/.github/scripts/merge-previous-releases.sh b/.github/scripts/merge-previous-releases.sh index 75ff04d0..5783956e 100644 --- a/.github/scripts/merge-previous-releases.sh +++ b/.github/scripts/merge-previous-releases.sh @@ -3,16 +3,20 @@ # Merge Previous Release Branches Script # # This script is triggered when a new release branch is created (e.g., release/2.1.2). -# It finds all previous release branches and merges them into the new release branch. +# It finds older *active* release branches (those with an open/draft release PR) and +# merges them into the new release branch. # # Key behaviors: -# - Merges ALL older release branches into the new one +# - Only considers release branches with open release PRs targeting stable +# (closed RCs are already covered by the stable sync process) +# - Merges those older active RCs into the new release branch # - For merge conflicts, favors the destination branch (new release) # - Both branches remain open after merge # - Fails fast on errors to prevent pushing partial merges # # Environment variables: # - NEW_RELEASE_BRANCH: The newly created release branch (e.g., release/2.1.2) +# - GITHUB_TOKEN: Token used by `gh` to list open release PRs set -e @@ -135,6 +139,25 @@ merge_with_favor_destination() { return 0 # Return 0 to indicate merged } + +# Find release branches that still have an open/draft release PR targeting stable. +# Returns: newline-separated list of branch names (e.g., release/7.36.0) +get_active_release_branches() { + local pr_heads + # Fail loudly on auth/API errors so we do not silently skip merges. + if ! pr_heads=$(gh pr list \ + --state open \ + --base stable \ + --limit 500 \ + --json headRefName \ + --jq '.[] | select(.headRefName | test("^release/[0-9]+\\.[0-9]+\\.[0-9]+$")) | .headRefName'); then + echo "Error: failed to query open release PRs (check GitHub token permissions)" >&2 + return 1 + fi + + echo "$pr_heads" +} + main() { if [[ -z "$NEW_RELEASE_BRANCH" ]]; then echo "Error: NEW_RELEASE_BRANCH environment variable is not set" @@ -154,34 +177,39 @@ main() { read -r new_major new_minor new_patch <<< "$new_version" echo "Parsed version: ${new_major}.${new_minor}.${new_patch}" - # Fetch all remote branches + # Fetch remotes so merge-base / merge use up-to-date refs git_exec fetch origin - # Get all release branches - local all_release_branches=() + echo "" + echo "Finding older release branches with open release PRs targeting stable..." + local active_release_branches=() + local active_branches_raw + active_branches_raw=$(get_active_release_branches) || exit 1 while IFS= read -r branch; do - # Remove "origin/" prefix and whitespace - branch="${branch#*origin/}" branch="${branch// /}" - if [[ -n "$branch" ]] && [[ -n "$(parse_release_version "$branch")" ]]; then - all_release_branches+=("$branch") + if [[ -n "$branch" ]] && [[ "$branch" != "$NEW_RELEASE_BRANCH" ]]; then + active_release_branches+=("$branch") fi - done < <(git branch -r --list "origin/release/*") + done <<< "$active_branches_raw" - echo "" - echo "Found ${#all_release_branches[@]} release branches:" - for b in "${all_release_branches[@]}"; do + echo "Found ${#active_release_branches[@]} active release branch(es) (open/draft PRs):" + for b in "${active_release_branches[@]}"; do echo " - $b" done - # Filter to only branches older than the new one + # Keep only active branches older than the new release local older_branches=() - for branch in "${all_release_branches[@]}"; do + for branch in "${active_release_branches[@]}"; do local version version=$(parse_release_version "$branch") if [[ -n "$version" ]]; then read -r major minor patch <<< "$version" if is_version_older "$major" "$minor" "$patch" "$new_major" "$new_minor" "$new_patch"; then + # Skip if the branch no longer exists on the remote + if ! git ls-remote --heads origin "$branch" | grep -Fq "$branch"; then + echo "⚠️ Skipping ${branch} (open PR found, but branch does not exist on remote)" + continue + fi older_branches+=("$branch") fi fi @@ -196,18 +224,18 @@ main() { if [[ ${#older_branches[@]} -eq 0 ]]; then echo "" - echo "No older release branches found. Nothing to merge." + echo "No older active release branches found. Nothing to merge." exit 0 fi echo "" - echo "Older release branches found (oldest to newest):" + echo "Older active release branches to merge (oldest to newest):" for b in "${older_branches[@]}"; do echo " - $b" done echo "" - echo "Will merge all ${#older_branches[@]} older branches." + echo "Will merge ${#older_branches[@]} older active branch(es)." # Verify we're on the right branch local current_branch diff --git a/CHANGELOG.md b/CHANGELOG.md index 441fb4fc..978b75ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Restrict `merge-previous-releases` to older branches that still have an open/draft release PR targeting `stable`, instead of every older `release/*` branch ([MCRM-80](https://consensyssoftware.atlassian.net/browse/MCRM-80)) + ## [1.18.0] ### Changed From 9b9e95fc9d7dedd97baebbdcf816d32df08e66e3 Mon Sep 17 00:00:00 2001 From: Tatiana Bobritsky Date: Wed, 26 Aug 2026 10:12:29 -0400 Subject: [PATCH 2/5] Address Mark's feedback --- .github/scripts/merge-previous-releases.sh | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/scripts/merge-previous-releases.sh b/.github/scripts/merge-previous-releases.sh index 5783956e..91139a93 100644 --- a/.github/scripts/merge-previous-releases.sh +++ b/.github/scripts/merge-previous-releases.sh @@ -7,9 +7,7 @@ # merges them into the new release branch. # # Key behaviors: -# - Only considers release branches with open release PRs targeting stable -# (closed RCs are already covered by the stable sync process) -# - Merges those older active RCs into the new release branch +# - Merges older active RCs into the new release branch # - For merge conflicts, favors the destination branch (new release) # - Both branches remain open after merge # - Fails fast on errors to prevent pushing partial merges @@ -187,7 +185,7 @@ main() { active_branches_raw=$(get_active_release_branches) || exit 1 while IFS= read -r branch; do branch="${branch// /}" - if [[ -n "$branch" ]] && [[ "$branch" != "$NEW_RELEASE_BRANCH" ]]; then + if [[ -n "$branch" ]] && [[ -n "$(parse_release_version "$branch")" ]]; then active_release_branches+=("$branch") fi done <<< "$active_branches_raw" @@ -205,11 +203,6 @@ main() { if [[ -n "$version" ]]; then read -r major minor patch <<< "$version" if is_version_older "$major" "$minor" "$patch" "$new_major" "$new_minor" "$new_patch"; then - # Skip if the branch no longer exists on the remote - if ! git ls-remote --heads origin "$branch" | grep -Fq "$branch"; then - echo "⚠️ Skipping ${branch} (open PR found, but branch does not exist on remote)" - continue - fi older_branches+=("$branch") fi fi From 6b0010185627c8f723864ce0ef59aa744a734687 Mon Sep 17 00:00:00 2001 From: Tatiana Bobritsky Date: Wed, 26 Aug 2026 12:03:03 -0400 Subject: [PATCH 3/5] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 978b75ae..4c8169f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- `merge-previous-releases` now requires `GITHUB_TOKEN` to query open release PRs via GitHub API ([MCRM-80](https://consensyssoftware.atlassian.net/browse/MCRM-80)) + ### Fixed - Restrict `merge-previous-releases` to older branches that still have an open/draft release PR targeting `stable`, instead of every older `release/*` branch ([MCRM-80](https://consensyssoftware.atlassian.net/browse/MCRM-80)) From f5531827d5ea16881954248adfdf6a5e03db79b8 Mon Sep 17 00:00:00 2001 From: Tatiana Bobritsky Date: Wed, 26 Aug 2026 12:45:28 -0400 Subject: [PATCH 4/5] Fix changelog: add prefix and PR instead of Jira issue --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c8169f6..fe09bff4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- `merge-previous-releases` now requires `GITHUB_TOKEN` to query open release PRs via GitHub API ([MCRM-80](https://consensyssoftware.atlassian.net/browse/MCRM-80)) +- **BREAKING:** `merge-previous-releases` now requires `GITHUB_TOKEN` to query open release PRs via GitHub API ([#282](https://github.com/MetaMask/github-tools/pull/282)) ### Fixed -- Restrict `merge-previous-releases` to older branches that still have an open/draft release PR targeting `stable`, instead of every older `release/*` branch ([MCRM-80](https://consensyssoftware.atlassian.net/browse/MCRM-80)) +- Restrict `merge-previous-releases` to older branches that still have an open/draft release PR targeting `stable`, instead of every older `release/*` branch ([#282](https://github.com/MetaMask/github-tools/pull/282)) ## [1.18.0] From f8da6c3291dfa1110fd9202644a58507c5900d3b Mon Sep 17 00:00:00 2001 From: Tatiana Bobritsky Date: Wed, 26 Aug 2026 13:32:38 -0400 Subject: [PATCH 5/5] Remove Changed section --- CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe09bff4..3ab0af51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Changed - -- **BREAKING:** `merge-previous-releases` now requires `GITHUB_TOKEN` to query open release PRs via GitHub API ([#282](https://github.com/MetaMask/github-tools/pull/282)) - ### Fixed - Restrict `merge-previous-releases` to older branches that still have an open/draft release PR targeting `stable`, instead of every older `release/*` branch ([#282](https://github.com/MetaMask/github-tools/pull/282))