-
Notifications
You must be signed in to change notification settings - Fork 3
/
action.yaml
406 lines (351 loc) · 15 KB
/
action.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
---
# SPDX-License-Identifier: Apache-2.0
# Copyright 2024 The Linux Foundation <abelur@linux.com>
name: github2gerrit-composite-action
description: "Submit a Githib pull-request to Gerrit repository"
inputs:
SUBMIT_SINGLE_COMMITS:
description: "Submit one commit at a time to the Gerrit repository"
required: false
default: "false"
USE_PR_AS_COMMIT:
description: "Use PR body and tittle as commit message"
required: false
default: "false"
FETCH_DEPTH:
description: "fetch-depth for the clone."
required: false
default: "10"
GERRIT_KNOWN_HOSTS:
description: "known hosts"
required: true
GERRIT_SSH_PRIVKEY_G2G:
description: "SSH Private key"
required: true
GERRIT_SSH_USER_G2G:
description: "Gerrit user-id for SSH"
required: true
GERRIT_SSH_USER_G2G_EMAIL:
description: "Email of the SSH user"
required: true
ORGANIZATION:
description: "Orginazation name ex: OpendayLight.org"
required: true
default: "OpendayLight.org"
REVIEWERS_EMAIL:
description: "Committers email list (comma separated) to notify on code-reviews"
required: false
default: ""
outputs:
url:
description: "URL of the change-request submitted"
value: ${{ steps.change_num.outputs.GERRIT_CHANGE_REQUEST_URL }}
change_number:
description: "Change number"
value: ${{ steps.change_num.outputs.GERRIT_CHANGE_REQUEST_NUMBER }}
runs:
using: "composite"
steps:
- name: Install python
uses: actions/setup-python@v5
id: setup-python
with:
python-version: "3.11"
- name: Validate workflow inputs
if: ${{ (inputs.USE_PR_AS_COMMIT == 'true') && (inputs.SUBMIT_SINGLE_COMMITS == 'true') }}
shell: bash
# yamllint disable rule:line-length
run: |
echo "Error: USE_PR_AS_COMMIT and SUBMIT_SINGLE_COMMITS cannot be set at the same time!"
exit 1
- name: "Install required dependencies: git-review,jq"
shell: bash
run: |
python -m pip install --upgrade pip
pip install "git-review==2.3.1" jq
git review --version
jq --version
- name: Clone Github repo where the PR is submitted
uses: actions/checkout@v4
with:
fetch-depth: ${{ inputs.FETCH_DEPTH }}
ref: ${{ github.event.pull_request.head.sha }}
- name: "Report error when .gitreview is undefined"
if: "${{ hashFiles('.gitreview') == '' }}"
shell: bash
run: |
set -x
echo "Error: .gitreview file is required for the composite action to run"
echo "Gerrit <server:port> not supported as inputs for composite action"
exit 1
- name: Read .gitreview to set PROJECT_REPO_GERRIT & PROJECT_REPO_GITHUB
if: "${{ hashFiles('.gitreview') != '' }}"
shell: bash
# yamllint disable rule:line-length
run: |
set -x
project_repo_gerrit_git=$(grep -E "project" .gitreview | cut -d "=" -f2)
# strip .git suffix
project_repo_gerrit="${project_repo_gerrit_git//.*}"
# change any '/' to '-' nested repos are not available on Github
project_repo_github="${project_repo_gerrit////-}"
echo "PROJECT_REPO_GERRIT=${project_repo_gerrit}" >> "$GITHUB_ENV"
echo "PROJECT_REPO_GITHUB=${project_repo_github}" >> "$GITHUB_ENV"
- name: Read .gitreview and set env GERRIT_SERVER and GERRIT_PORT
if: "${{ hashFiles('.gitreview') != '' }}"
shell: bash
# yamllint disable rule:line-length
run: |
set -x
gerrit_server=$(grep -E "host" .gitreview | cut -d "=" -f2)
gerrit_server_port=$(grep -E "port" .gitreview | cut -d "=" -f2)
echo "GERRIT_SERVER=${gerrit_server}" >> "$GITHUB_ENV"
echo "GERRIT_SERVER_PORT=${gerrit_server_port}" >> "$GITHUB_ENV"
- name: Set env GITHUB branch in env
shell: bash
run: |
gerrit_branch="${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}"
echo "GERRIT_BRANCH=${gerrit_branch}" >> "$GITHUB_ENV"
- name: Print last X commits in the git log
if: env.ACT == 'true'
shell: bash
# yamllint disable rule:line-length
run: |
set -x
git --no-pager log --graph --all --decorate --pretty=oneline -n5
- name: Install SSH Key
uses: shimataro/ssh-key-action@d4fffb50872869abe2d9a9098a6d9c5aa7d16be4 # v2.7.0
with:
key: ${{ inputs.GERRIT_SSH_PRIVKEY_G2G }}
name: "id_rsa"
known_hosts: ${{ inputs.GERRIT_KNOWN_HOSTS }}
config: |
Host ${{ env.GERRIT_SERVER }}
User ${{ inputs.GERRIT_SSH_USER_G2G }}
Port 29418
PubkeyAcceptedKeyTypes +ssh-rsa
IdentityFile ~/.ssh/id_rsa
- name: Setup Gerrit remote
if: env.PROJECT_REPO_GERRIT != ''
shell: bash
# yamllint disable rule:line-length
run: |
set -x
# Setup global git config required by git-review
git config --global gitreview.username ${{ inputs.GERRIT_SSH_USER_G2G }}
git config --global user.name ${{ inputs.GERRIT_SSH_USER_G2G }}
git config --global user.email ${{ inputs.GERRIT_SSH_USER_G2G_EMAIL }}
# Workaround for git-review failing to copy the commit-msg hook to submodules
git config core.hooksPath "$(git rev-parse --show-toplevel)/.git/hooks"
# Init gerrit repo
git review -s -v
# print remote settings
git remote -v
- name: Extract the pull-request number
shell: bash
# yamllint disable rule:line-length
run: |
set -x
export PR_NUMBER="${{ github.event.pull_request.number || github.event.issue.number }}"
echo "PR_NUMBER=$PR_NUMBER" >> "$GITHUB_ENV"
- name: Get the number of commits in the pull-request
if: ${{ github.event_name == 'pull_request_target' }}
shell: bash
# yamllint disable rule:line-length
run: |
set -x
num_commits="$(gh pr view ${{ env.PR_NUMBER }} --json commits | jq '.[] | length')"
echo "PR_COMMITS=$num_commits" >> "$GITHUB_ENV"
env:
GH_TOKEN: ${{ github.token }}
- name: Prepare commits to submit one at a time
if: "${{ (env.PR_COMMITS > 0) && (inputs.SUBMIT_SINGLE_COMMITS == 'true') }}"
shell: bash
# yamllint disable rule:line-length
run: |
set -x
commit_shas=$(gh pr view ${{ env.PR_NUMBER }} --json commits --jq '.commits[] | .oid')
git checkout -b tmp_branch ${{ github.event.pull_request.base.sha }}
# Cherry-pick the commits into diff branch and amend to add change-Id
for csha in ${commit_shas}; do
git checkout tmp_branch
git cherry-pick "${csha}"
git commit -s -v --no-edit --amend
change_id="$(git log --format="%(trailers:key=Change-Id,valueonly,separator=%x2C)" -n1)"
if [ -n "${change_id}" ]; then
# Capture the newly created change-Id
echo "$change_id" >> change-Id.txt
else
echo "FAIL: Change-Id not created, exit job!"
exit 1
fi
git checkout "origin/${{ env.GERRIT_BRANCH }}"
done
git log -n3 tmp_branch
env:
GH_TOKEN: ${{ github.token }}
- name: Squash commits into a single commit
if: ${{ (env.PR_COMMITS > 0) && (inputs.SUBMIT_SINGLE_COMMITS == 'false') }}
shell: bash
# yamllint disable rule:line-length
run: |
set -x
git --no-pager log --graph --all --decorate --pretty=oneline -n"${{ env.PR_COMMITS }}"
# Create a Change-id from all the PR
# Squash all commits in pull-request into a single commit
git reset --soft "${{ github.sha }}"
# Check if change-id is present in each commit and use the first one
# Capture and check for signed-of-by and Change-Id
git log -v --format=%B --reverse "HEAD..HEAD@{1}" | grep -E "^(Change-Id)" > change-Id.txt || true
git log -v --format=%B --reverse "HEAD..HEAD@{1}" | grep -E "^(Signed-off-by)" > signed-off-by.txt || true
git log -v --format=%B --reverse "HEAD..HEAD@{1}" | grep -Ev "^(Signed-off-by|Change-Id)" > commit-msg.txt
if [[ -f commit-msg.txt ]]; then
commit_message="${commit_message:-commit-msg.txt}"
fi
if [[ -f change-Id.txt ]]; then
commit_message+=' '
commit_message+="change-Id.txt"
fi
if [[ -f signed-off-by.txt ]]; then
sort -u signed-off-by.txt -o signed-off-by-final.txt
commit_message+=' '
commit_message+="signed-off-by-final.txt"
fi
git commit -s -v --no-edit -m "$(cat $commit_message)"
git log -n2
- name: Overwrite commit message with PR tittle and body
if: ${{ (github.event_name == 'pull_request_target') && (env.PR_COMMITS > 0) && (inputs.USE_PR_AS_COMMIT == 'true') && (inputs.SUBMIT_SINGLE_COMMITS == 'false') }}
shell: bash
# yamllint disable rule:line-length
run: |
set -x
pr_tittle_length="$(gh pr view ${{ env.PR_NUMBER }} --json title | jq '.[] | length')"
pr_body_length="$(gh pr view ${{ env.PR_NUMBER }} --json body | jq '.[] | length')"
gh pr view ${{ env.PR_NUMBER }} --json title | jq -r '.title | select( . != null )' > pr_title.txt
# add blank line between title and body
echo "" >> pr_title.txt
gh pr view ${{ env.PR_NUMBER }} --json body | jq -r '.body | select( . != null )' >> pr_body.txt
# Note: its upto the dev to ensure the 50/72 rule
cat pr_title.txt pr_body.txt > pr_commit.txt
echo "" >> pr_commit.txt
cat signed-off-by-final.txt >> pr_commit.txt
if [[ -f pr_commit.txt ]] && [[ ($pr_body_length -gt 0) ]] && [[ ($pr_tittle_length -gt 0) ]]; then
git commit -s -v --amend --no-edit -F "pr_commit.txt"
git log -n2
fi
env:
GH_TOKEN: ${{ github.token }}
- name: Submit the change to Gerrit repository
id: submit
if: env.PR_NUMBER != ''
shell: bash
# yamllint disable rule:line-length
run: |
set -x
if ${{ inputs.SUBMIT_SINGLE_COMMITS == 'true' }}; then
git checkout tmp_branch
fi
reviewers_emails_list="${{ inputs.REVIEWERS_EMAIL }}"
# If the reviewers email is unset/empty then use a default
reviewers=${reviewers_emails_list:-"${{ inputs.GERRIT_SSH_USER_G2G_EMAIL }}"}
topic="GH-${{ env.PROJECT_REPO_GITHUB }}-${{ env.PR_NUMBER }}"
echo "git review .... inprogress"
git review --yes -t "$topic" --reviewers "$reviewers"
- name: Validate Change-ID and retrive the Gerrit change number
id: change_num
shell: bash
# yamllint disable rule:line-length
run: |
set -x
if [[ ! -s change-Id.txt ]]; then
# retrive change-id from the submitted PR
gerrit_change_id=$(git show HEAD --format=%B -s | grep Change-Id: | cut -d " " -f2;)
if [[ "$gerrit_change_id" == '' ]]; then
echo "GERRIT_CHANGE_ID: null"; exit 1
fi
echo "$gerrit_change_id" >> change-Id.txt
fi
if [[ -s change-Id.txt ]]; then
GERRIT_CHANGE_ID_VALUES="$(<change-Id.txt)"
{
echo 'GERRIT_CHANGE_ID<<EOF'
echo "${GERRIT_CHANGE_ID_VALUES}"
echo EOF
} >> "$GITHUB_ENV"
fi
while IFS="" read -r cid; do
# Query for a pre-existing gerrit review to retrive Change-Id
ssh -v -n -p 29418 "${{ inputs.GERRIT_SSH_USER_G2G }}@${{ env.GERRIT_SERVER }}" \
"gerrit query limit:1 owner:self is:open" \
"project:${{ env.PROJECT_REPO_GERRIT }}" \
--current-patch-set --format=JSON \
"$cid" > query_result.txt
query_result_url=$(jq -r '.url | select( . != null )' query_result.txt)
query_result_number=$(jq -r '.number | select( . != null )' query_result.txt)
query_result_commit_sha=$(jq -r '.currentPatchSet.revision | select( . != null )' query_result.txt)
echo "${query_result_url}" >> change-url.txt
echo "${query_result_commit_sha}" >> commit-sha.txt
echo "${query_result_number}" >> change-request-number.txt
done < change-Id.txt
GERRIT_CHANGE_REQUEST_URL_VALUES="$(<change-url.txt)"
{
echo 'GERRIT_CHANGE_REQUEST_URL<<EOF'
echo "${GERRIT_CHANGE_REQUEST_URL_VALUES}"
echo EOF
} >> "$GITHUB_ENV"
GERRIT_COMMIT_SHA_VALUES="$(<commit-sha.txt)"
{
echo 'GERRIT_COMMIT_SHA<<EOF'
echo "${GERRIT_COMMIT_SHA_VALUES}"
echo EOF
} >> "$GITHUB_ENV"
GERRIT_CHANGE_REQUEST_NUM_VALUES="$(<change-request-number.txt)"
{
echo 'GERRIT_CHANGE_REQUEST_NUM<<EOF'
echo "${GERRIT_CHANGE_REQUEST_NUM_VALUES}"
echo EOF
} >> "$GITHUB_ENV"
- name: Add source of Github PR URL as a gerrit comment
if: env.GERRIT_CHANGE_ID != ''
shell: bash
# yamllint disable rule:line-length
run: |
set -x
run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
pr_path="${{ github.server_url }}/${{ github.repository }}/pull/${{ env.PR_NUMBER }}"
message="$(printf 'GHPR: %s\nAction-Run: %s\n' "${pr_path}" "${run_url}")"
# Add comment backref change request to Github PR and workflow job.
while IFS="" read -r csha; do
ssh -v -n -p 29418 "${{ inputs.GERRIT_SSH_USER_G2G }}@${{ env.GERRIT_SERVER }}" \
gerrit review -m "'""${message}""'" \
--branch ${{ env.GERRIT_BRANCH }} --project "${{ env.PROJECT_REPO_GERRIT }}" \
"$csha"
done < commit-sha.txt
- name: Add comment to refrence the change-request on the pull-request
if: |
hashFiles('commit-sha.txt') != '' ||
(! startsWith(env.GERRIT_CHANGE_REQUEST_URL, ''))
uses: actions/github-script@v7
with:
result-encoding: string
retries: 3
retry-exempt-status-codes: 400,401
script: |
const output = `The pull-request PR-${{ env.PR_NUMBER }} is submitted to Gerrit [${{ inputs.ORGANIZATION }}](https://${{ env.GERRIT_SERVER }})! \n
To follow up on the change visit: \n \n ${{ env.GERRIT_CHANGE_REQUEST_URL }} \n \n
NOTE: The pull-request PR-${{ env.PR_NUMBER }} will be closed, re-opening the pull-request will not update the same commit and may result in duplicate changes on Gerrit.`
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
- name: Close pull-request
if: ${{ github.event_name == 'pull_request_target' }}
shell: bash
# yamllint disable rule:line-length
run: |
set -x
gh pr close --comment "Auto-closing pull request" --delete-branch "${{ env.PR_NUMBER }}"
env:
GH_TOKEN: ${{ github.token }}