Skip to content

Add Github workflow to automatically create uplift PRs#792

Open
jonathanmendez wants to merge 22 commits intomozilla:enterprise-mainfrom
jonathanmendez:auto-uplift
Open

Add Github workflow to automatically create uplift PRs#792
jonathanmendez wants to merge 22 commits intomozilla:enterprise-mainfrom
jonathanmendez:auto-uplift

Conversation

@jonathanmendez
Copy link
Copy Markdown
Contributor

@jonathanmendez jonathanmendez commented Apr 24, 2026

Description

Bugzilla: Bug-TODO
Adds a workflow that:

  • triggers when a PR is merged
  • checks whether labels uplift-to-beta or uplift-to-release are present in the PR and if the PR's target branch is one we would uplift from (enterprise-main for beta or release, and enterprise-beta for release)
  • if so, cherry-picks the commit(s) from the merge into the enterprise-beta/enterprise-release branch(es) and creates uplift PR(s)
    • if the PR was done as a merge, cherry-picks the individual commits
    • if the PR was done as a squash, cherry-picks the squash commit
  • if a conflict is encountered during a cherry-pick, the created uplift PR is changed to a Draft, and the original author is added as a reviewer with a comment for resolution instructions

Testing

TODO??

  • Added tests
  • Manual testing performed

@jonathanmendez jonathanmendez added the branch:main PR that should be merged on enterprise-main branch label Apr 24, 2026
@gcp gcp requested a review from Copilot April 25, 2026 18:37
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an “Auto Uplift” GitHub Actions workflow intended to automatically create uplift PRs to enterprise-beta and/or enterprise-release when PRs are merged into enterprise-main and carry uplift labels.

Changes:

  • Introduces .github/workflows/uplift.yml triggered on merged PRs to enterprise-main.
  • Detects uplift-to-beta / uplift-to-release labels and cherry-picks merged changes onto the corresponding branch.
  • Opens uplift PRs via peter-evans/create-pull-request@v6 with a generated commit summary.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/uplift.yml
Comment on lines +80 to +135
PARENTS=$(git rev-list --parents -n 1 $SHA)
COUNT=$(echo $PARENTS | wc -w)

APPLIED=0

if [ "$COUNT" -eq 3 ]; then
echo "Merge commit → multi-commit mode"

COMMITS=$(git log --reverse --no-merges --pretty=format:"%H" $SHA^1..$SHA^2)

for commit in $COMMITS; do
SHORT=$(git rev-parse --short $commit)
MSG=$(git log -1 --pretty=format:"%s" $commit)
LINK="$REPO_URL/commit/$commit"

if git branch -r --contains $commit | grep -q "origin/$TARGET"; then
echo "- [$SHORT]($LINK) $MSG (already in branch)" >> $SUMMARY_FILE
continue
fi

set +e
git cherry-pick -x -X theirs $commit
STATUS=$?
set -e

if [ $STATUS -ne 0 ]; then
# Check if it's an empty cherry-pick
if git diff --cached --quiet && git diff --quiet; then
echo "Empty cherry-pick for $commit → skipping"

git cherry-pick --skip

echo "- [$SHORT]($LINK) $MSG (already applied)" >> $SUMMARY_FILE
continue
fi

git add -A
git commit -m "Cherry-pick $commit with conflicts"
echo "- [$SHORT]($LINK) $MSG (⚠️ conflict)" >> $SUMMARY_FILE
else
echo "- [$SHORT]($LINK) $MSG" >> $SUMMARY_FILE
fi

APPLIED=1
done

else
echo "Single commit mode"

SHORT=$(git rev-parse --short $SHA)
MSG=$(git log -1 --pretty=format:"%s" $SHA)
LINK="$REPO_URL/commit/$SHA"

set +e
git cherry-pick -x -X theirs $SHA
STATUS=$?
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

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

The script assumes that any non-merge merge_commit_sha implies a single-commit uplift, but for GitHub’s “rebase and merge” (and sometimes other non-merge merge strategies), the PR may have multiple commits and merge_commit_sha will only reference the last one. In that case this workflow would uplift only one commit and silently miss the rest. Consider deriving the commit list from the PR (e.g., via gh pr view --json commits / GitHub API) and cherry-picking all PR commits (or the single squash commit when applicable) rather than branching on parent count of merge_commit_sha.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@lissyx I wonder if we should disallow the 'rebase and merge' strategy (for general reasons, not just for this). AFAIK we don't use it and wouldn't want to use it?

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.

rebase and merge is mostly what i always do manually :'( :'(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well I'm only talking about the PR completion action, not any manual rebasing/merging. And I haven't put a lot of thought into "we shouldn't use the rebase-and-merge PR completion", I just know that we've previously said among ourselves to use merge if our commit history is good or squash if not, so I thought we'd implicitly ruled it out.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I haven't found a way to detect when the merge was done with squash vs rebase-and-merge. If we think it makes sense to remove rebase-and-merge as a PR merge strategy, then this workflow can work as-is. Otherwise I'll just have to leave a warning comment or something to go manually check if the original PR was merged via rebase-and-merge and tell the reviewers to abandon the created uplift PR and do it manually.

Comment thread .github/workflows/uplift.yml Outdated
Comment thread .github/workflows/uplift.yml Outdated
Comment thread .github/workflows/uplift.yml Outdated
Comment thread .github/workflows/uplift.yml Outdated
Comment on lines +29 to +33
env:
MERGE_SHA: ${{ github.event.pull_request.merge_commit_sha }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
REPO_URL: https://github.com/${{ github.repository }}
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.

I am not sure it is worth duplicating those

Comment on lines +58 to +174
cat << 'EOF' > uplift.sh
set -e

TARGET=$1
SHA=$2

BRANCH="uplift-${TARGET}-${SHA}"
SUMMARY_FILE=summary.txt

echo "---- Uplifting to $TARGET ----"

git fetch origin $TARGET

# Skip entire operation if merge commit already in branch
if git branch -r --contains $SHA | grep -q "origin/$TARGET"; then
echo "Already fully present in $TARGET"
echo "summary=Already present, nothing to uplift." >> $GITHUB_OUTPUT
echo "branch=" >> $GITHUB_OUTPUT
exit 0
fi

# Avoid duplicate branch
if git ls-remote --heads origin $BRANCH | grep -q $BRANCH; then
echo "Branch already exists, skipping"
echo "summary=Uplift branch already exists." >> $GITHUB_OUTPUT
echo "branch=" >> $GITHUB_OUTPUT
exit 0
fi

git checkout -b $BRANCH origin/$TARGET

touch $SUMMARY_FILE

PARENTS=$(git rev-list --parents -n 1 $SHA)
COUNT=$(echo $PARENTS | wc -w)

APPLIED=0

if [ "$COUNT" -eq 3 ]; then
echo "Merge commit → multi-commit mode"

COMMITS=$(git log --reverse --no-merges --pretty=format:"%H" $SHA^1..$SHA^2)

for commit in $COMMITS; do
SHORT=$(git rev-parse --short $commit)
MSG=$(git log -1 --pretty=format:"%s" $commit)
LINK="$REPO_URL/commit/$commit"

if git branch -r --contains $commit | grep -q "origin/$TARGET"; then
echo "- [$SHORT]($LINK) $MSG (already in branch)" >> $SUMMARY_FILE
continue
fi

set +e
git cherry-pick -x $commit
STATUS=$?
set -e

if [ $STATUS -ne 0 ]; then
# Check if it's an empty cherry-pick
if git diff --cached --quiet && git diff --quiet; then
echo "Empty cherry-pick for $commit → skipping"

git cherry-pick --skip

echo "- [$SHORT]($LINK) $MSG (already applied)" >> $SUMMARY_FILE
continue
fi

git add -A
git cherry-pick --continue
echo "- [$SHORT]($LINK) $MSG (⚠️ conflict)" >> $SUMMARY_FILE
else
echo "- [$SHORT]($LINK) $MSG" >> $SUMMARY_FILE
fi

APPLIED=1
done

else
echo "Single commit mode"

SHORT=$(git rev-parse --short $SHA)
MSG=$(git log -1 --pretty=format:"%s" $SHA)
LINK="$REPO_URL/commit/$SHA"

set +e
git cherry-pick -x $SHA
STATUS=$?
set -e

if [ $STATUS -ne 0 ]; then
git add -A
git cherry-pick --continue
echo "- [$SHORT]($LINK) $MSG (⚠️ conflict)" >> $SUMMARY_FILE
else
echo "- [$SHORT]($LINK) $MSG" >> $SUMMARY_FILE
fi

APPLIED=1
fi

if [ "$APPLIED" -eq 0 ]; then
echo "No new commits applied"
echo "summary=All commits already exist in $TARGET." >> $GITHUB_OUTPUT
echo "branch=" >> $GITHUB_OUTPUT
exit 0
fi

git push origin $BRANCH

echo "branch=$BRANCH" >> $GITHUB_OUTPUT

DELIM="GITHUB_OUTPUT_$(uuidgen)"
echo "summary<<$DELIM" >> $GITHUB_OUTPUT
cat $SUMMARY_FILE >> $GITHUB_OUTPUT
echo "$DELIM" >> $GITHUB_OUTPUT
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.

This should be a file in the repo, and not on the action, would make it easier to review as well

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I intentionally avoided making a script because it is generally seen as a security vulnerability when using on: pull_request_target that executes with privilege. The idea of the security vulnerability is that while the existing/committed version of the workflow will be what runs (even if the PR contains changes to it), having the workflow call a script could in theory run a (maliciously) modified version of the script in the PR.

It may be enough mitigation that I am only running this code when the PR is closed and merged, but I guess I'll let the github admins weigh in on that.

Comment thread .github/workflows/uplift.yml Outdated
Comment thread .github/workflows/uplift.yml Outdated
Comment thread .github/workflows/uplift.yml Outdated
Comment thread .github/workflows/uplift.yml Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/uplift.yml
Comment thread .github/workflows/uplift.yml
jonathanmendez and others added 2 commits May 1, 2026 11:15
Copilot AI review requested due to automatic review settings May 1, 2026 18:50
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/uplift.yml
Comment thread .github/workflows/uplift.yml
Comment thread .github/workflows/uplift.yml
Comment thread .github/workflows/uplift.yml
Comment thread .github/workflows/uplift.yml Outdated
@jonathanmendez jonathanmendez requested a review from lissyx May 1, 2026 21:08
Copilot AI review requested due to automatic review settings May 1, 2026 22:23
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

#
# Crucially, no external code is loaded or run as part of this workflow.
#
# [0] https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request_target:~:text=Warning-,Running,websitehttps://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request_target:~:text=Warning-,Running,website
Copy link

Copilot AI May 1, 2026

Choose a reason for hiding this comment

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

The reference link in this comment looks malformed (it contains websitehttps://...). This makes the warning harder to follow; please replace it with the correct GitHub Docs URL (the same one referenced in the text).

Suggested change
# [0] https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request_target:~:text=Warning-,Running,websitehttps://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request_target:~:text=Warning-,Running,website
# [0] https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request_target

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

branch:main PR that should be merged on enterprise-main branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants