Cherry-pick a pull request #1875
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 }} | |
- 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" | |
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 add . | |
GIT_MERGE_AUTOEDIT=no git cherry-pick --continue | |
echo "HAS_CONFLICTS=true" >> "$GITHUB_OUTPUT" | |
fi | |
git commit --amend -m "$(git log -1 --pretty=%B)" -m "(CP triggered by ${{ github.actor }})" | |
- 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 🍒" \ | |
--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." | |
gh pr edit --add-assignee "${{ github.actor }},${{ steps.getCPMergeCommit.outputs.MERGE_ACTOR }}" | |
env: | |
GITHUB_TOKEN: ${{ steps.setupGitForOSBotify.outputs.OS_BOTIFY_API_TOKEN }} | |
- name: Label 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 }} |