|
19 | 19 | repository_dispatch: |
20 | 20 | types: [cherry-pick-command] |
21 | 21 |
|
22 | | -permissions: |
23 | | - contents: write |
24 | | - pull-requests: write |
25 | | - issues: write |
26 | | - |
27 | 22 | jobs: |
28 | | - prepare: |
29 | | - runs-on: ubuntu-latest |
30 | | - outputs: |
31 | | - branches: ${{ steps.parse-args.outputs.branches }} |
32 | | - error: ${{ steps.parse-args.outputs.error }} |
33 | | - message: ${{ steps.parse-args.outputs.message }} |
34 | | - steps: |
35 | | - - name: Add reaction to trigger comment |
36 | | - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 |
37 | | - with: |
38 | | - token: ${{ secrets.CHATOPS_TOKEN }} |
39 | | - repository: ${{ github.event.client_payload.github.payload.repository.full_name }} |
40 | | - comment-id: ${{ github.event.client_payload.github.payload.comment.id }} |
41 | | - reactions: "+1" |
42 | | - |
43 | | - - name: Get target branches from command args |
44 | | - id: parse-args |
45 | | - run: | |
46 | | - # Parse all unnamed arguments from the slash command |
47 | | - ARGS_JSON='${{ toJson(github.event.client_payload.slash_command.args.unnamed) }}' |
48 | | -
|
49 | | - # Extract branch names from the JSON object, filtering out "all" field if present |
50 | | - # The unnamed args come as {arg1: "branch1", arg2: "branch2", ...} |
51 | | - BRANCHES=$(echo "$ARGS_JSON" | jq -r '[to_entries[] | select(.key | startswith("arg")) | .value | select(. != null and . != "")] | @json') |
52 | | -
|
53 | | - echo "Parsed branches: $BRANCHES" |
54 | | -
|
55 | | - if [ "$BRANCHES" = "[]" ] || [ -z "$BRANCHES" ]; then |
56 | | - echo "error=true" >> $GITHUB_OUTPUT |
57 | | - echo "message=Missing target branch(es). Usage: /cherry-pick <target-branch> [<target-branch2> ...]" >> $GITHUB_OUTPUT |
58 | | - else |
59 | | - echo "branches=$BRANCHES" >> $GITHUB_OUTPUT |
60 | | - echo "error=false" >> $GITHUB_OUTPUT |
61 | | - fi |
62 | | -
|
63 | | - - name: Comment on error |
64 | | - if: steps.parse-args.outputs.error == 'true' |
65 | | - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 |
66 | | - with: |
67 | | - token: ${{ secrets.CHATOPS_TOKEN }} |
68 | | - repository: ${{ github.event.client_payload.github.payload.repository.full_name }} |
69 | | - issue-number: ${{ github.event.client_payload.github.payload.issue.number }} |
70 | | - body: | |
71 | | - ❌ **Cherry-pick failed**: ${{ steps.parse-args.outputs.message }} |
72 | | -
|
73 | | - **Usage**: `/cherry-pick <target-branch> [<target-branch2> ...]` |
74 | | - **Examples**: |
75 | | - - `/cherry-pick release-v1.0` |
76 | | - - `/cherry-pick release-v1.0 release-v1.1 release-v2.0` |
77 | | -
|
78 | 23 | cherry-pick: |
79 | | - needs: prepare |
80 | | - if: needs.prepare.outputs.error == 'false' |
81 | | - runs-on: ubuntu-latest |
82 | | - strategy: |
83 | | - fail-fast: false |
84 | | - matrix: |
85 | | - branch: ${{ fromJson(needs.prepare.outputs.branches) }} |
86 | | - steps: |
87 | | - - name: Checkout repository |
88 | | - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 |
89 | | - with: |
90 | | - token: ${{ secrets.CHATOPS_TOKEN }} |
91 | | - fetch-depth: 0 |
92 | | - |
93 | | - - name: Perform cherry-pick |
94 | | - id: cherry-pick |
95 | | - continue-on-error: true |
96 | | - env: |
97 | | - GH_TOKEN: ${{ secrets.CHATOPS_TOKEN }} |
98 | | - TARGET_BRANCH: ${{ matrix.branch }} |
99 | | - PR_NUMBER: ${{ github.event.client_payload.pull_request.number }} |
100 | | - run: | |
101 | | - set +e # Don't exit on error, we want to capture it |
102 | | -
|
103 | | - # Capture all output |
104 | | - OUTPUT_FILE=$(mktemp) |
105 | | -
|
106 | | - { |
107 | | - echo "🤖 Starting cherry-pick process..." |
108 | | -
|
109 | | - git config user.name "Tekton Bot" |
110 | | - git config user.email "tekton-bot@users.noreply.github.com" |
111 | | -
|
112 | | - # Get PR information |
113 | | - echo "Fetching PR #$PR_NUMBER information..." |
114 | | - PR_DATA=$(gh pr view $PR_NUMBER --repo ${{ github.repository }} --json state,mergeCommit,mergedAt,title,body) |
115 | | -
|
116 | | - # Check if PR is merged |
117 | | - PR_STATE=$(echo "$PR_DATA" | jq -r '.state') |
118 | | - MERGED_AT=$(echo "$PR_DATA" | jq -r '.mergedAt') |
119 | | - if [ "$PR_STATE" != "MERGED" ] || [ "$MERGED_AT" = "null" ]; then |
120 | | - echo "❌ ERROR: PR #$PR_NUMBER is not merged yet (state: $PR_STATE). Cherry-pick requires merged PRs." |
121 | | - exit 1 |
122 | | - fi |
123 | | -
|
124 | | - MERGE_COMMIT=$(echo "$PR_DATA" | jq -r '.mergeCommit.oid') |
125 | | - PR_TITLE=$(echo "$PR_DATA" | jq -r '.title') |
126 | | - PR_BODY=$(echo "$PR_DATA" | jq -r '.body') |
127 | | - echo "Found merge commit: $MERGE_COMMIT" |
128 | | - echo "PR title: $PR_TITLE" |
129 | | -
|
130 | | - # Fetch target branch |
131 | | - echo "Fetching target branch: $TARGET_BRANCH..." |
132 | | - if ! git fetch origin "$TARGET_BRANCH" 2>&1; then |
133 | | - echo "❌ ERROR: Target branch '$TARGET_BRANCH' does not exist or cannot be fetched." |
134 | | - exit 1 |
135 | | - fi |
136 | | -
|
137 | | - # Check if a cherry-pick PR already exists |
138 | | - CHERRY_PICK_BRANCH="cherry-pick-$PR_NUMBER-to-$TARGET_BRANCH" |
139 | | - echo "Checking for existing cherry-pick PR..." |
140 | | - EXISTING_PR=$(gh pr list \ |
141 | | - --repo ${{ github.repository }} \ |
142 | | - --head "$CHERRY_PICK_BRANCH" \ |
143 | | - --base "$TARGET_BRANCH" \ |
144 | | - --json number,url \ |
145 | | - --jq '.[0] | select(. != null)') |
146 | | -
|
147 | | - if [ -n "$EXISTING_PR" ]; then |
148 | | - PR_URL=$(echo "$EXISTING_PR" | jq -r '.url') |
149 | | - PR_NUM=$(echo "$EXISTING_PR" | jq -r '.number') |
150 | | - echo "ℹ️ Cherry-pick PR already exists: #$PR_NUM" |
151 | | - echo "URL: $PR_URL" |
152 | | - echo "existing_pr_url=$PR_URL" >> $GITHUB_OUTPUT |
153 | | - echo "existing_pr_number=$PR_NUM" >> $GITHUB_OUTPUT |
154 | | - exit 0 |
155 | | - fi |
156 | | -
|
157 | | - # Create new branch for cherry-pick |
158 | | - echo "Creating cherry-pick branch: $CHERRY_PICK_BRANCH..." |
159 | | - git checkout -b "$CHERRY_PICK_BRANCH" "origin/$TARGET_BRANCH" |
160 | | -
|
161 | | - # Perform cherry-pick |
162 | | - echo "Cherry-picking commit $MERGE_COMMIT..." |
163 | | - if ! git cherry-pick -m 1 "$MERGE_COMMIT" 2>&1; then |
164 | | - echo "❌ ERROR: Cherry-pick failed due to conflicts or other errors." |
165 | | - git cherry-pick --abort 2>/dev/null || true |
166 | | - exit 1 |
167 | | - fi |
168 | | -
|
169 | | - # Push the new branch |
170 | | - echo "Pushing cherry-pick branch..." |
171 | | - git push origin "$CHERRY_PICK_BRANCH" |
172 | | -
|
173 | | - # Create pull request |
174 | | - echo "Creating pull request..." |
175 | | -
|
176 | | - # Prepare PR body file |
177 | | - { |
178 | | - echo "This is a cherry-pick of #$PR_NUMBER" |
179 | | - echo "" |
180 | | - echo "---" |
181 | | - echo "" |
182 | | - echo "$PR_BODY" |
183 | | - } > /tmp/pr-body.md |
184 | | -
|
185 | | - # Create pull request with original PR content |
186 | | - gh pr create \ |
187 | | - --repo ${{ github.repository }} \ |
188 | | - --base "$TARGET_BRANCH" \ |
189 | | - --head "$CHERRY_PICK_BRANCH" \ |
190 | | - --title "[cherry-pick: $TARGET_BRANCH] $PR_TITLE" \ |
191 | | - --body-file /tmp/pr-body.md |
192 | | -
|
193 | | - echo "✅ Cherry-pick completed successfully!" |
194 | | - } 2>&1 | tee "$OUTPUT_FILE" |
195 | | -
|
196 | | - EXIT_CODE=${PIPESTATUS[0]} |
197 | | -
|
198 | | - # Save output for use in comments |
199 | | - EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) |
200 | | - echo "output<<$EOF" >> $GITHUB_OUTPUT |
201 | | - cat "$OUTPUT_FILE" >> $GITHUB_OUTPUT |
202 | | - echo "$EOF" >> $GITHUB_OUTPUT |
203 | | -
|
204 | | - rm -f "$OUTPUT_FILE" |
205 | | - exit $EXIT_CODE |
206 | | -
|
207 | | - - name: Comment on existing PR |
208 | | - if: steps.cherry-pick.outcome == 'success' && steps.cherry-pick.outputs.existing_pr_url != '' |
209 | | - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 |
210 | | - with: |
211 | | - token: ${{ secrets.CHATOPS_TOKEN }} |
212 | | - repository: ${{ github.event.client_payload.github.payload.repository.full_name }} |
213 | | - issue-number: ${{ github.event.client_payload.github.payload.issue.number }} |
214 | | - body: | |
215 | | - ℹ️ **Cherry-pick to `${{ matrix.branch }}` already exists!** |
216 | | -
|
217 | | - A pull request for this cherry-pick already exists: #${{ steps.cherry-pick.outputs.existing_pr_number }} |
218 | | -
|
219 | | - **PR**: ${{ steps.cherry-pick.outputs.existing_pr_url }} |
220 | | -
|
221 | | - - name: Comment on success |
222 | | - if: steps.cherry-pick.outcome == 'success' && steps.cherry-pick.outputs.existing_pr_url == '' |
223 | | - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 |
224 | | - with: |
225 | | - token: ${{ secrets.CHATOPS_TOKEN }} |
226 | | - repository: ${{ github.event.client_payload.github.payload.repository.full_name }} |
227 | | - issue-number: ${{ github.event.client_payload.github.payload.issue.number }} |
228 | | - body: | |
229 | | - ✅ **Cherry-pick to `${{ matrix.branch }}` successful!** |
230 | | -
|
231 | | - A new pull request has been created to cherry-pick this change to `${{ matrix.branch }}`. |
232 | | -
|
233 | | - Please review and merge the cherry-pick PR. |
234 | | -
|
235 | | - - name: Comment on failure |
236 | | - if: steps.cherry-pick.outcome == 'failure' |
237 | | - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 |
238 | | - with: |
239 | | - token: ${{ secrets.CHATOPS_TOKEN }} |
240 | | - repository: ${{ github.event.client_payload.github.payload.repository.full_name }} |
241 | | - issue-number: ${{ github.event.client_payload.github.payload.issue.number }} |
242 | | - body: | |
243 | | - ❌ **Cherry-pick to `${{ matrix.branch }}` failed!** |
244 | | -
|
245 | | - The automatic cherry-pick to `${{ matrix.branch }}` failed. |
246 | | -
|
247 | | - **Output:** |
248 | | - ``` |
249 | | - ${{ steps.cherry-pick.outputs.output }} |
250 | | - ``` |
251 | | -
|
252 | | - **Next steps:** |
253 | | - - Check the [action logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for complete details |
254 | | - - If the PR is not merged, merge it first and try again |
255 | | - - If there are conflicts, you'll need to manually cherry-pick this PR |
| 24 | + name: Cherry Pick Actions |
| 25 | + uses: tektoncd/plumbing/.github/workflows/_cherry-pick-command.yaml@4b57443b85569e5bb7d9ee440bf5cae99cb642cb |
| 26 | + secrets: |
| 27 | + CHATOPS_TOKEN: ${{ secrets.CHATOPS_TOKEN }} |
0 commit comments