Cherry-pick a pull request #2075
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Cherry-pick a pull request | |
on: | |
workflow_dispatch: | |
inputs: | |
PULL_REQUEST_NUMBER: | |
description: The number of a pull request to CP | |
required: true | |
jobs: | |
validateActor: | |
runs-on: ubuntu-latest | |
outputs: | |
IS_DEPLOYER: ${{ fromJSON(steps.isDeployer.outputs.IS_DEPLOYER) || github.actor == 'OSBotify' || github.actor == 'os-botify[bot]' }} | |
steps: | |
- name: Check if user is deployer | |
id: isDeployer | |
run: | | |
if gh api /orgs/Expensify/teams/mobile-deployers/memberships/${{ github.actor }} --silent; then | |
echo "IS_DEPLOYER=true" >> "$GITHUB_OUTPUT" | |
else | |
echo "IS_DEPLOYER=false" >> "$GITHUB_OUTPUT" | |
fi | |
env: | |
GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} | |
createNewVersion: | |
needs: validateActor | |
if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} | |
uses: ./.github/workflows/createNewVersion.yml | |
secrets: inherit | |
cherryPick: | |
needs: createNewVersion | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout staging branch | |
uses: actions/checkout@v4 | |
with: | |
ref: staging | |
token: ${{ secrets.OS_BOTIFY_TOKEN }} | |
submodules: true | |
- name: Set up git for OSBotify | |
id: setupGitForOSBotify | |
uses: ./.github/actions/composite/setupGitForOSBotifyApp | |
with: | |
GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} | |
OS_BOTIFY_APP_ID: ${{ secrets.OS_BOTIFY_APP_ID }} | |
OS_BOTIFY_PRIVATE_KEY: ${{ secrets.OS_BOTIFY_PRIVATE_KEY }} | |
- name: Get previous app version | |
id: getPreviousVersion | |
uses: ./.github/actions/javascript/getPreviousVersion | |
with: | |
SEMVER_LEVEL: "PATCH" | |
- name: Fetch history of relevant refs | |
run: | | |
git fetch origin main staging --no-tags --shallow-exclude ${{ steps.getPreviousVersion.outputs.PREVIOUS_VERSION }} | |
- name: Get version bump commit | |
id: getVersionBumpCommit | |
run: | | |
git switch main | |
VERSION_BUMP_COMMIT="$(git log --format='%H' --author='OSBotify' --grep 'Update version to ${{ needs.createNewVersion.outputs.NEW_VERSION }}')" | |
echo "VERSION_BUMP_SHA=$VERSION_BUMP_COMMIT" >> "$GITHUB_OUTPUT" | |
- name: Get merge commit for pull request to CP | |
id: getCPMergeCommit | |
uses: ./.github/actions/javascript/getPullRequestDetails | |
with: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
USER: ${{ github.actor }} | |
PULL_REQUEST_NUMBER: ${{ github.event.inputs.PULL_REQUEST_NUMBER }} | |
- name: Cherry-pick the version-bump to staging | |
run: | | |
git switch staging | |
git cherry-pick -S -x --mainline 1 --strategy=recursive -Xtheirs ${{ steps.getVersionBumpCommit.outputs.VERSION_BUMP_SHA }} | |
- name: Cherry-pick the merge commit of target PR | |
id: cherryPick | |
run: | | |
echo "Attempting to cherry-pick ${{ steps.getCPMergeCommit.outputs.MERGE_COMMIT_SHA }}" | |
if git cherry-pick -S -x --mainline 1 ${{ steps.getCPMergeCommit.outputs.MERGE_COMMIT_SHA }}; then | |
echo "🎉 No conflicts! CP was a success, PR can be automerged 🎉" | |
echo "HAS_CONFLICTS=false" >> "$GITHUB_OUTPUT" | |
git commit --amend -m "$(git log -1 --pretty=%B)" -m "(CP triggered by ${{ github.actor }})" | |
else | |
echo "😞 PR can't be automerged, there are merge conflicts in the following files:" | |
git --no-pager diff --name-only --diff-filter=U | |
git cherry-pick --abort | |
echo "HAS_CONFLICTS=true" >> "$GITHUB_OUTPUT" | |
fi | |
- name: Push changes | |
run: | | |
if [[ ${{steps.cherryPick.outputs.HAS_CONFLICTS}} == 'true' ]]; then | |
git checkout -b ${{ github.actor }}-cherry-pick-staging-${{ github.event.inputs.PULL_REQUEST_NUMBER }}-${{ github.run_attempt }} | |
git push --set-upstream origin ${{ github.actor }}-cherry-pick-staging-${{ github.event.inputs.PULL_REQUEST_NUMBER }}-${{ github.run_attempt }} | |
else | |
git push origin staging | |
fi | |
- name: Create Pull Request to manually finish CP | |
if: fromJSON(steps.cherryPick.outputs.HAS_CONFLICTS) | |
id: createPullRequest | |
run: | | |
gh pr create \ | |
--title "🍒 Cherry pick PR #${{ github.event.inputs.PULL_REQUEST_NUMBER }} to staging 🍒" \ | |
--body \ | |
"🍒 Cherry pick https://github.com/Expensify/App/pull/${{ github.event.inputs.PULL_REQUEST_NUMBER }} to staging 🍒 | |
This PR had conflicts when we tried to cherry-pick it to staging. You'll need to manually perform the cherry-pick, using the following steps: | |
\`\`\`bash | |
git fetch | |
git checkout ${{ github.actor }}-cherry-pick-staging-${{ github.event.inputs.PULL_REQUEST_NUMBER }}-${{ github.run_attempt }} | |
git cherry-pick -S -x --mainline 1 ${{ steps.getCPMergeCommit.outputs.MERGE_COMMIT_SHA }} | |
\`\`\` | |
Then manually resolve conflicts, and commit the change with \`git cherry-pick --continue\`. Lastly, please run: | |
\`\`\`bash | |
git commit --amend -m \"$(git log -1 --pretty=%B)\" -m \"(CP triggered by ${{ github.actor }})\" | |
\`\`\` | |
That will help us keep track of who triggered this CP. Once all that's done, push your changes with \`git push origin ${{ github.actor }}-cherry-pick-staging-${{ github.event.inputs.PULL_REQUEST_NUMBER }}-${{ github.run_attempt }}\`, and then open this PR for review. | |
Note that you **must** test this PR, and both the author and reviewer checklist should be completed, just as if you were merging the PR to main." \ | |
--label "Engineering,Hourly" \ | |
--base "staging" | |
sleep 5 | |
gh pr comment --body \ | |
"This pull request has merge conflicts and can not be automatically merged. :disappointed: | |
Please manually resolve the conflicts, push your changes, and then request another reviewer to review and merge. | |
**Important:** There may be conflicts that GitHub is not able to detect, so please _carefully_ review this pull request before approving." | |
ORIGINAL_PR_AUTHOR="$(gh pr view ${{ github.event.inputs.PULL_REQUEST_NUMBER }} --json author --jq .author.login)" | |
gh pr edit --add-assignee "${{ github.actor }},${{ steps.getCPMergeCommit.outputs.MERGE_ACTOR }},$ORIGINAL_PR_AUTHOR" | |
env: | |
GITHUB_TOKEN: ${{ steps.setupGitForOSBotify.outputs.OS_BOTIFY_API_TOKEN }} | |
- name: Label original PR with CP Staging | |
run: gh pr edit ${{ inputs.PULL_REQUEST_NUMBER }} --add-label 'CP Staging' | |
env: | |
GITHUB_TOKEN: ${{ github.token }} | |
- name: "Announces a CP failure in the #announce Slack room" | |
uses: 8398a7/action-slack@v3 | |
if: ${{ failure() }} | |
with: | |
status: custom | |
custom_payload: | | |
{ | |
channel: '#announce', | |
attachments: [{ | |
color: "#DB4545", | |
pretext: `<!subteam^S4TJJ3PSL>`, | |
text: `💥 Failed to CP https://github.com/Expensify/App/pull/${{ github.event.inputs.PULL_REQUEST_NUMBER }} to staging 💥`, | |
}] | |
} | |
env: | |
GITHUB_TOKEN: ${{ github.token }} | |
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} |