Merge pull request #2523 from cyclinder/ci/templetes #761
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: Auto CherryPick PR | |
permissions: write-all | |
env: | |
PR_LABEL_PREFIX_CHERRYPICK: "cherrypick-" | |
CHERRYPICK_LABEL: "robot-cherrypick" | |
DEFAULT_REVIEWER: "weizhoublue" | |
on: | |
push: | |
branches: | |
- 'release-*' | |
- 'main' | |
workflow_dispatch: | |
inputs: | |
prNumber: | |
description: 'pr number' | |
required: true | |
destBranch: | |
description: 'dest branch, if empty, follow the pr label' | |
required: false | |
jobs: | |
cherry_pick: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
# ${{ secrets.GITHUB_TOKEN }} is forbidden to create or approve pull requests | |
- name: cherry pick | |
env: | |
GITHUB_TOKEN: ${{ secrets.WELAN_PAT}} | |
JSON: ${{ toJSON(github) }} | |
run: | | |
set -x | |
echo "============ print var ======== " | |
if ${{ github.event_name == 'workflow_dispatch' }}; then | |
PR_NUMBER=${{ github.event.inputs.prNumber }} | |
else | |
grep -Eio "Merge pull request #[0-9]+ " <<< "${JSON}" || true | |
echo "try to get PR from commit" | |
COMMIT=` echo "${JSON}" | jq '.event.commits[0].id' | tr -d '"' ` || true | |
if [ -n "${COMMIT}" ]; then | |
PR_NUMBER=`curl --retry 10 -s -H "Accept: application/vnd.github.groot-preview+json" https://api.github.com/repos/${{ github.repository }}/commits/${COMMIT}/pulls | jq -r '.[].number' ` | |
else | |
echo "error, failed to get any commit ID" | |
fi | |
if [ -z "${PR_NUMBER}" ] ; then | |
PR_NUMBER=` grep -Eio "Merge pull request #[0-9]+ " <<< "${JSON}" | grep -Eo "[0-9]+" | uniq ` || true | |
fi | |
if [ -z "${PR_NUMBER}" ] ; then | |
echo "error, failed to get PR NUMBER" | |
exit 1 | |
fi | |
# grep -Ei "https://github.com/.*/commit" <<< "${JSON}" | |
#PR_COMMITS=` grep -Ei "https://github.com/.*/commit" <<< "${JSON}" | awk -F'"' '{print $4}' | uniq -c | awk '{ if ($1 == 1 ) print $2}' | awk -F'/' '{print $NF}' | tr '\n' ' ' ` | |
# grep '"username":' <<< "${JSON}" | |
#PR_AUTHOR=` grep '"username":' <<< "${JSON}" | awk -F'"' '{print $4}' | sort | uniq | grep -v "web-flow" | head -1 | tr -d '\n' ` | |
# [ -n "${PR_AUTHOR}" ] || { echo "no PR_AUTHOR, ignore" ; } | |
# | |
fi | |
RP_API_BODY=` curl --retry 10 https://api.github.com/repos/${{ github.repository }}/pulls/${PR_NUMBER} -s -H "Accept: application/vnd.github.groot-preview+json" ` | |
PR_COMMITS=` echo "${RP_API_BODY}" | jq ' .merge_commit_sha ' | tr -d '"' ` | |
PR_AUTHOR=` echo "${RP_API_BODY}" | jq ' .user.login ' | tr -d '"' ` | |
PR_URL="https://github.com/${{ github.repository }}/pull/${PR_NUMBER}" | |
ACTION_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
#gh pr view ${PR_NUMBER} || { echo "failed to get pr ${PR_NUMBER}" ; exit 1 ; } | |
#PR_LABEL=` gh pr view ${PR_NUMBER} | grep -i "^labels:" | tr ',' ' ' | tr -s ' ' | sed 's/labels://g' ` | |
# [ -n "${PR_LABEL}" ] || { echo "no PR_LABEL, ignore" ; } | |
PR_LABEL=` echo "${RP_API_BODY}" | jq ' .labels[].name ' | tr -d '"' | tr '\n' ' ' ` | |
#PR_TITLE=`gh pr view ${PR_NUMBER} | sed -n '1 p' ` | |
# [ -n "${PR_TITLE}" ] || { echo "error, no PR_TITLE " ; exit 1 ; } | |
PR_TITLE=` echo "${RP_API_BODY}" | jq ' .title ' | tr -d '"' ` | |
# | |
if [ -z "${PR_COMMITS}" ]; then | |
echo "error, failed to get pr commits" | |
fi | |
echo "number: ${PR_NUMBER}" | |
echo "action url: ${ACTION_URL}" | |
echo "PR_COMMITS: ${PR_COMMITS}" | |
echo "author: ${PR_AUTHOR}" | |
echo "url: ${PR_URL}" | |
echo "PR_LABEL: ${PR_LABEL}" | |
echo "PR_TITLE: ${PR_TITLE}" | |
# | |
# | |
echo "=============================== get dest branch from labels ======== " | |
WANT_MERGE_BRANCH_LIST="" | |
if ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.destBranch != '' }}; then | |
WANT_MERGE_BRANCH_LIST=${{ github.event.inputs.destBranch }} | |
else | |
for LABEL in ${PR_LABEL} ; do | |
echo "checking label $LABEL " | |
PREFIX="${{ env.PR_LABEL_PREFIX_CHERRYPICK }}" | |
grep -E "^${PREFIX}" <<< "${LABEL}" &>/dev/null || continue | |
BRANCH_NAME=` sed 's?'"${PREFIX}"'??' <<< "$LABEL" ` | |
WANT_MERGE_BRANCH_LIST+=" $BRANCH_NAME " | |
done | |
fi | |
[ -z "$WANT_MERGE_BRANCH_LIST" ] && echo "no branch to cherry pick" && exit 0 | |
echo "cherry pick to $WANT_MERGE_BRANCH_LIST " | |
# | |
# | |
echo "============ begin to cherry pick ============ " | |
FINAL_FAILURE=false | |
git branch | |
git config user.email "[email protected]" | |
git config user.name "robot" | |
gh label create ${{ env.CHERRYPICK_LABEL }} || true | |
for BRANCH in $WANT_MERGE_BRANCH_LIST ; do | |
echo "************** cherry for branch ${BRANCH}" | |
if ! git ls-remote --exit-code --heads origin ${BRANCH} ; then | |
# todo: create issue | |
echo "error, branch $BRANCH does not exist" | |
gh issue create \ | |
--body "reason: the branch $BRANCH does not exist. PR <${PR_URL}> , action <${ACTION_URL}> " \ | |
--title "failed to auto cherry pick PR ${PR_NUMBER} to branch ${BRANCH}" \ | |
--label "${{ env.CHERRYPICK_LABEL }}" \ | |
--assignee "${PR_AUTHOR},${{ env.DEFAULT_REVIEWER }}" | |
if (($?!=0)) ; then | |
echo "!!!! error, failed to create issue" | |
FINAL_FAILURE=true | |
fi | |
continue | |
fi | |
git fetch origin ${BRANCH}:${BRANCH} || true | |
if ! git checkout ${BRANCH} ; then | |
echo "error, failed to checkout to branch $BRANCH" | |
gh issue create \ | |
--body "reason: failed to get the branch $BRANCH. PR <${PR_URL}> , action <${ACTION_URL}> " \ | |
--title "failed to auto cherry pick PR ${PR_NUMBER} to branch ${BRANCH}" \ | |
--label "${{ env.CHERRYPICK_LABEL }}" \ | |
--assignee "${PR_AUTHOR},${{ env.DEFAULT_REVIEWER }}" | |
if (($?!=0)) ; then | |
echo "!!!! error, failed to create issue" | |
FINAL_FAILURE=true | |
fi | |
continue | |
fi | |
PR_BRANCH=robot/cherrypick/pr${PR_NUMBER}/${BRANCH} | |
git checkout -b ${PR_BRANCH} | |
git branch --show-current | |
FAIL=false | |
UPDATE=false | |
ERROR_MESSAGE="" | |
for COMMIT in $PR_COMMITS; do | |
if ! ERROR_MESSAGE=`git cherry-pick -m 1 $COMMIT 2>&1` ; then | |
echo ">>>>>>>>>>>> fail when cherry pick $COMMIT to branch $BRANCH " | |
echo "$ERROR_MESSAGE" | |
echo "---- failuire detail" | |
git status | |
git diff | |
echo "<<<<<<<<<<<<<" | |
if git diff --exit-code --quiet ; then | |
echo "no changes happen, ignore cherry pick $COMMIT " | |
git cherry-pick --abort || true | |
git reset --hard HEAD || true | |
continue | |
else | |
FAIL=true | |
echo "error, failed to cherry pick $COMMIT " | |
git cherry-pick --abort || true | |
git reset --hard HEAD || true | |
break | |
fi | |
else | |
UPDATE=true | |
echo "succeed to cherry pick $COMMIT to branch $BRANCH " | |
fi | |
done | |
if [ "$FAIL" == "true" ] ; then | |
echo "failed to cherry pick to branch $BRANCH " | |
FINAL_FAILURE=true | |
echo -e "commits $PR_COMMITS conflict when merging to branch $BRANCH, please manually cherry pick it by yourself. \n PR <${PR_URL}> , action <${ACTION_URL}> \n\n \`\`\`\n${ERROR_MESSAGE}\n\`\`\` " | \ | |
gh issue create \ | |
--title "failed to auto cherry pick PR ${PR_NUMBER} to branch ${BRANCH}" \ | |
--label "${{ env.CHERRYPICK_LABEL }}" \ | |
--assignee "${PR_AUTHOR},${{ env.DEFAULT_REVIEWER }}" \ | |
--body-file - | |
fi | |
if [ "$UPDATE" == "true" ] ; then | |
echo "succeeded to cherry pick to branch $BRANCH " | |
# create a pr | |
git push origin ${PR_BRANCH}:${PR_BRANCH} -f | |
gh pr create --title "${PR_TITLE}" \ | |
--assignee "${PR_AUTHOR},${{ env.DEFAULT_REVIEWER }}" \ | |
--label ${{ env.CHERRYPICK_LABEL }} \ | |
--body "robot cherry pick pr <${PR_URL}> to branch ${BRANCH}, action <${ACTION_URL}> , commits $PR_COMMITS " \ | |
--base ${BRANCH} | |
else | |
echo "no changes happened for commits $PR_COMMITS, ignore create pr" | |
fi | |
done | |
echo "=========== check result ============" | |
if [ "$FINAL_FAILURE" == "true" ] ; then | |
# if failed to create issue or pr, fails | |
echo "error, failuire happened" | |
else | |
echo "all done" | |
fi |