diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000000..d013edd4bd --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,38 @@ +# Github actions README +This is an introduction about auto-cherry-pick workflow. +take 202205 branch for example: +1. pr_cherrypick_prestep: +```mermaid +graph +Start(Origin PR) --> A{merged?} +A -- NO --> STOP +A -- YES --> A1{Approved
for 202205
Branch?} +A1 -- NO --> STOP +A1 -- YES --> A2(pr_cherrypick_prestep) +B(pr_cherrypick_prestep) +B --> B1{cherry pick
conflict?} +B1 -- YES --> B2(Add tag:
Cherry Pick Confclit_202205) --> B3(Add comment:
refer author code conflict) --> STOP1(STOP) +B1 -- NO --> B4(Create New PR) -- success --> B5(New PR add tag:
automerge) --> B6(New PR add comment:
Origin PR link) --> B7(Origin PR add tag:
Created PR to 202205 Branch) --> B8(Origin PR add comment:
New PR link) +B4 -- fail --> STOP1 +``` + +2. automerge: +```mermaid +graph +Start(PR azp finished successfully) --> A{author:
mssonicbld?} +A -- NO --> STOP +A -- YES --> B{tag:
automerge?} -- YES --> C(Merge PR) +B -- NO --> STOP +``` + +3. pr_cherrypick_poststep: +```mermaid +graph +A(PR is Merged) --> B{tag:
automerge?} +B -- YES --> B1{author:
mssonicbld?} +B1 -- YES --> B2{"title starts:
[action] [PR:123]"} +B2 -- YES --> C(Origin PR remove tag:
Created PR to 202205 Branch) --> D(Origin PR add tag:
Included in 202205 Branch) +B -- NO --> STOP +B1 -- NO --> STOP +B2 -- NO --> STOP +``` diff --git a/.github/workflows/pr_cherrypick_poststep.yml b/.github/workflows/pr_cherrypick_poststep.yml new file mode 100644 index 0000000000..1e9e497075 --- /dev/null +++ b/.github/workflows/pr_cherrypick_poststep.yml @@ -0,0 +1,49 @@ +name: PostCherryPick +on: + pull_request_target: + types: + - closed + branches: + - '20*' + +jobs: + post_cherry_pick: + if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'automerge') && github.event.pull_request.head.user.login == 'mssonicbld' && startsWith(github.event.pull_request.title, '[action]') + runs-on: ubuntu-latest + steps: + - name: Debug + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo $GITHUB_CONTEXT | jq + - name: Checkout + uses: actions/checkout@v3 + with: + persist-credentials: false + - name: Main + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + TOKEN: ${{ secrets.TOKEN }} + run: | + set -e + pr_url=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request._links.html.href") + pr_id=$(echo $GITHUB_CONTEXT | jq -r ".event.number") + base_ref=$(echo $GITHUB_CONTEXT | jq -r ".base_ref") + echo ${TOKEN} | gh auth login --with-token + title=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request.title") + origin_pr_id=$(echo $title | grep -Eo "\[action\] \[PR:[0-9]*\]" | grep -Eo "[0-9]*") + origin_pr_url=$(echo $pr_url | sed "s/$pr_id/$origin_pr_id/") + echo ============================= + echo pr_url: $pr_url + echo pr_id: $pr_id + echo base_ref: $base_ref + echo title: $title + echo origin_pr_id: $origin_pr_id + echo origin_pr_url: $origin_pr_url + echo ============================= + # Add label + if [[ "$origin_pr_id" == "" ]];then + echo "original PR didn't found." + exit 1 + fi + gh pr edit $origin_pr_url --add-label "Included in ${base_ref} Branch" + gh pr edit $origin_pr_url --remove-label "Created PR to ${base_ref} Branch,Request for ${base_ref} Branch,Approved for ${base_ref} Branch" diff --git a/.github/workflows/pr_cherrypick_prestep.yml b/.github/workflows/pr_cherrypick_prestep.yml new file mode 100644 index 0000000000..3caf3f9408 --- /dev/null +++ b/.github/workflows/pr_cherrypick_prestep.yml @@ -0,0 +1,136 @@ +name: PreCherryPick +on: + pull_request_target: + types: + - labeled + - closed + branches: + - master-test + +jobs: + pre_cherry_pick: + if: github.event.pull_request.merged == true && ( (github.event.action == 'closed' && contains(join(github.event.pull_request.labels.*.name, ','), 'Approved for 20')) || (github.event.action == 'labeled' && startsWith(github.event.label.name, 'Approved for 20')) ) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + persist-credentials: false + - name: Debug + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo $GITHUB_CONTEXT | jq + - name: Main + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + TOKEN: ${{ secrets.TOKEN }} + run: | + set -e + + sha=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request.merge_commit_sha") + pr_id=$(echo $GITHUB_CONTEXT | jq -r ".event.number") + pr_url=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request._links.html.href") + repository=$(echo $GITHUB_CONTEXT | jq -r ".repository") + labels=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request.labels[].name") + author=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request.base.user.login") + branches=$(git branch -a --list 'origin/20????' | awk -F/ '{print$3}' | grep -E "202[0-9]{3}") + if [[ $(echo $GITHUB_CONTEXT | jq -r ".event.action") == "labeled" ]];then + labels=$(echo $GITHUB_CONTEXT | jq -r ".event.label.name") + fi + title=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request.title") + echo ============================= + echo SHA: $sha + echo PRID: $pr_id + echo pr_url: $pr_url + echo repository: $repository + echo branches: $branches + echo labels: + echo "$labels" + echo ${TOKEN} | gh auth login --with-token + echo author: $author + echo title: $title + echo ============================= + + git config user.name mssonicbld + git config user.email sonicbld@microsoft.com + git config credential.https://github.com.username mssonicbld + git remote add mssonicbld https://mssonicbld:${TOKEN}@github.com/mssonicbld/sonic-buildimage + git fetch mssonicbld + git remote -vv + + cherry_pick(){ + set -e + local create_pr='' + while read label + do + echo label: $label + if [[ "$label" == "Approved for $branch Branch" ]];then + create_pr=1 + fi + if [[ "$label" == "Created PR to $branch Branch" ]];then + echo "already has tag: Created PR to $branch Branch, return" + return 0 + fi + if [[ "$label" == "Included in $branch Branch" ]];then + echo "already has tag: Included in $branch Branch, return" + return 0 + fi + if [[ "$label" == "Cherry Pick Conflict_$branch" ]];then + echo "already has tag: Cherry Pick Conflict_$branch, return" + return 0 + fi + done <<< "$labels" + + if [[ "$create_pr" != "1" ]];then + echo "Didn't find 'Approved for $branch Branch' tag." + return 0 + fi + # Begin to cherry-pick PR + git cherry-pick --abort 2>/dev/null || true + git clean -xdff 2>/dev/null || true + git reset HEAD --hard || true + git checkout -b $branch --track origin/$branch + git status | grep "working tree clean" + + if ! git cherry-pick $sha;then + echo 'cherry-pick failed.' + git cherry-pick --abort + git status | grep "working tree clean" + # Add label + gh pr edit $pr_url --add-label "Cherry Pick Conflict_$branch" + echo 'Add label "Cherry Pick Conflict_$branch" success' + gh pr comment $pr_url --body "@${author} PR conflicts with $branch branch" + echo 'Add commnet "@${author} PR conflicts with $branch branch"' + else + # Create PR to release branch + git push mssonicbld HEAD:$branch-${pr_id} -f + result=$(gh pr create -R ${repository} -H mssonicbld:$branch-${pr_id} -B $branch -t "[action] [PR:$pr_id] $title" -b '' 2>&1) + echo $result | grep "already exists" && { echo $result; return 0; } + echo $result | grep github.com || { echo $result; return 1; } + new_pr_rul=$(echo $result | grep github.com) + echo new_pr_rul: $new_pr_rul + + # Add label to old PR + gh pr edit $pr_url --add-label "Created PR to $branch Branch" + echo Add label Created PR to $branch Branch + # Add comment to old PR + gh pr comment $pr_url --body "Cherry-pick PR to $branch: ${new_pr_rul}" + echo Add comment to old PR + + # Add label to new PR + gh pr edit $new_pr_rul --add-label "automerge" + echo Add label automerge to new PR + # Add comment to new PR + gh pr comment $new_pr_rul --body "Original PR: ${pr_url}" + echo Add comment to new PR + fi + } + + for branch in $branches + do + echo ------------------------------------------- + echo Begin to parse Branch: $branch + cherry_pick + done +