Skip to content

Commit 27f4a30

Browse files
committed
Feat: Enable support to submit single commits
Each commit in the pull request are processed individually as a single commit before submitting to Gerrit repository. This option allows you to preserve git history. This requires `inputs.SUBMIT_SINGLE_COMMITS` to be set to 'true' from the caller. Remove extra inputs. Gerrit server and port and project has be read from .gitreview file. Composite actions have a limitation on the number of the inputs that can be passed to 10. Update doc example with new feat options. Signed-off-by: Anil Belur <[email protected]>
1 parent 4bdafe2 commit 27f4a30

File tree

4 files changed

+277
-139
lines changed

4 files changed

+277
-139
lines changed

.github/workflows/call-g2g-composite-action.yaml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,8 @@ jobs:
2828
id: gerrit-upload
2929
uses: lfit/github2gerrit@main
3030
with:
31-
USE_PR_AS_COMMIT: false
32-
FETCH_DEPTH: 10
33-
GERRIT_KNOWN_HOSTS: ${{ vars.GERRIT_KNOWN_HOSTS }}
34-
GERRIT_SERVER: ${{ vars.GERRIT_SERVER }}
35-
GERRIT_SERVER_PORT: "29418"
31+
SUBMIT_SINGLE_COMMITS: "true"
32+
USE_PR_AS_COMMIT: "false"
3633
GERRIT_SSH_PRIVKEY_G2G: ${{ secrets.GERRIT_SSH_PRIVKEY_G2G }}
3734
GERRIT_SSH_USER_G2G: ${{ vars.GERRIT_SSH_USER_G2G }}
3835
GERRIT_SSH_USER_G2G_EMAIL: ${{ vars.GERRIT_SSH_USER_G2G_EMAIL }}

.github/workflows/github2gerrit.yaml

Lines changed: 114 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ name: github2gerrit-reusable-workflow
77
on:
88
workflow_call:
99
inputs:
10+
SUBMIT_SINGLE_COMMITS:
11+
description: "Submit one commit at a time to the Gerrit repository"
12+
required: false
13+
default: false
14+
type: boolean
1015
USE_PR_AS_COMMIT:
1116
description: "Use PR body and tittle as commit message"
1217
required: false
@@ -73,6 +78,14 @@ jobs:
7378
with:
7479
python-version: "3.11"
7580

81+
- name: Validate workflow inputs
82+
if: ${{ (inputs.USE_PR_AS_COMMIT == true) && (inputs.SUBMIT_SINGLE_COMMITS == true) }}
83+
shell: bash
84+
# yamllint disable rule:line-length
85+
run: |
86+
echo "Error: USE_PR_AS_COMMIT and SUBMIT_SINGLE_COMMITS cannot be enabled at the same time"
87+
exit 1
88+
7689
- name: "Install required dependencies: git-review,jq"
7790
shell: bash
7891
run: |
@@ -212,9 +225,37 @@ jobs:
212225
env:
213226
GH_TOKEN: ${{ github.token }}
214227

228+
- name: Prepare commits to submit one at a time
229+
shell: bash
230+
if: ${{ (env.PR_COMMITS > 0) && (inputs.SUBMIT_SINGLE_COMMITS == true) }}
231+
# yamllint disable rule:line-length
232+
run: |
233+
set -x
234+
commit_shas=$(gh pr view ${{ env.PR_NUMBER }} --json commits --jq '.commits[] | .oid')
235+
git checkout -b tmp_branch ${{ github.event.pull_request.base.sha }}
236+
237+
# Cherry-pick the commits into diff branch and amend to add change-Id
238+
for csha in ${commit_shas}; do
239+
git checkout tmp_branch
240+
git cherry-pick "${csha}"
241+
git commit -s -v --no-edit --amend
242+
change_id="$(git log --format="%(trailers:key=Change-Id,valueonly,separator=%x2C)" -n1)"
243+
if [ -n "${change_id}" ]; then
244+
# Capture the newly created change-Id
245+
echo "$change_id" >> change-Id.txt
246+
else
247+
echo "FAIL: Change-Id not created, exit job!"
248+
exit 1
249+
fi
250+
git checkout ${{ env.GERRIT_BRANCH }}
251+
done
252+
git log -n3
253+
env:
254+
GH_TOKEN: ${{ github.token }}
255+
215256
- name: Squash commits into a single commit
216257
shell: bash
217-
if: ${{ (env.PR_COMMITS > 0) }}
258+
if: ${{ (env.PR_COMMITS > 0) && (inputs.SUBMIT_SINGLE_COMMITS == false) }}
218259
# yamllint disable rule:line-length
219260
run: |
220261
set -x
@@ -251,7 +292,7 @@ jobs:
251292
git log -n2
252293
253294
- name: Overwrite commit message with PR tittle and body
254-
if: ${{ (github.event_name == 'pull_request_target') && (env.PR_COMMITS > 0) && (inputs.USE_PR_AS_COMMIT == true) }}
295+
if: ${{ (github.event_name == 'pull_request_target') && (env.PR_COMMITS > 0) && (inputs.USE_PR_AS_COMMIT == true) && (inputs.SUBMIT_SINGLE_COMMITS == false) }}
255296
shell: bash
256297
# yamllint disable rule:line-length
257298
run: |
@@ -285,6 +326,10 @@ jobs:
285326
run: |
286327
set -x
287328
329+
if ${{ inputs.SUBMIT_SINGLE_COMMITS == true }}; then
330+
git checkout tmp_branch
331+
fi
332+
288333
reviewers_emails_list="${{ inputs.REVIEWERS_EMAIL }}"
289334
# If the reviewers email is unset/empty then use a default
290335
reviewers=${reviewers_emails_list:-"${{ inputs.GERRIT_SSH_USER_G2G_EMAIL }}"}
@@ -293,35 +338,68 @@ jobs:
293338
echo "git review .... inprogress"
294339
git review --yes -t "$topic" --reviewers "$reviewers"
295340
296-
# retrive change-id from the submitted PR
297-
gerrit_change_id=$(git show HEAD --format=%B -s | grep Change-Id: | cut -d " " -f2;)
298-
299-
if [[ "$gerrit_change_id" != '' ]]; then
300-
echo "GERRIT_CHANGE_ID=${gerrit_change_id}" >> "$GITHUB_ENV"
301-
fi
302-
303-
- name: Retrive the Gerrit change number from Change-ID
304-
if: env.GERRIT_CHANGE_ID != ''
341+
- name: Validate Change-ID and retrive the Gerrit change number
305342
id: change_num
306343
shell: bash
307344
# yamllint disable rule:line-length
308345
run: |
309346
set -x
310347
311-
# Query for a pre-existing gerrit review to retrive Change-Id
312-
ssh -v -p 29418 "${{ inputs.GERRIT_SSH_USER_G2G }}@${{ env.GERRIT_SERVER }}" \
313-
gerrit query limit:1 owner:self is:open \
314-
project:"${{ env.PROJECT_REPO_GERRIT }}" \
315-
--current-patch-set --format=JSON \
316-
"${{ env.GERRIT_CHANGE_ID }}" > query_result.txt
348+
if [[ ! -s change-Id.txt ]]; then
349+
# retrive change-id from the submitted PR
350+
gerrit_change_id=$(git show HEAD --format=%B -s | grep Change-Id: | cut -d " " -f2;)
351+
if [[ "$gerrit_change_id" == '' ]]; then
352+
echo "GERRIT_CHANGE_ID: null"; exit 1
353+
fi
354+
echo "$gerrit_change_id" >> change-Id.txt
355+
fi
317356
318-
query_result_url=$(jq -r '.url | select( . != null )' query_result.txt)
319-
query_result_number=$(jq -r '.number | select( . != null )' query_result.txt)
320-
query_result_commit_sha=$(jq -r '.currentPatchSet.revision | select( . != null )' query_result.txt)
357+
if [[ -s change-Id.txt ]]; then
358+
GERRIT_CHANGE_ID_VALUES="$(<change-Id.txt)"
359+
{
360+
echo 'GERRIT_CHANGE_ID<<EOF'
361+
echo "${GERRIT_CHANGE_ID_VALUES}"
362+
echo EOF
363+
} >> "$GITHUB_ENV"
364+
fi
321365
322-
echo "GERRIT_CHANGE_REQUEST_URL=${query_result_url}" >> "$GITHUB_ENV"
323-
echo "GERRIT_CHANGE_REQUEST_NUMBER=${query_result_number}" >> "$GITHUB_ENV"
324-
echo "GERRIT_COMMIT_SHA=${query_result_commit_sha}" >> "$GITHUB_ENV"
366+
while IFS="" read -r cid; do
367+
# Query for a pre-existing gerrit review to retrive Change-Id
368+
ssh -v -n -p 29418 "${{ inputs.GERRIT_SSH_USER_G2G }}@${{ env.GERRIT_SERVER }}" \
369+
"gerrit query limit:1 owner:self is:open" \
370+
"project:${{ env.PROJECT_REPO_GERRIT }}" \
371+
--current-patch-set --format=JSON \
372+
"$cid" > query_result.txt
373+
374+
query_result_url=$(jq -r '.url | select( . != null )' query_result.txt)
375+
query_result_number=$(jq -r '.number | select( . != null )' query_result.txt)
376+
query_result_commit_sha=$(jq -r '.currentPatchSet.revision | select( . != null )' query_result.txt)
377+
378+
echo "${query_result_url}" >> change-url.txt
379+
echo "${query_result_commit_sha}" >> commit-sha.txt
380+
echo "${query_result_number}" >> change-request-number.txt
381+
done < change-Id.txt
382+
383+
GERRIT_CHANGE_REQUEST_URL_VALUES="$(<change-url.txt)"
384+
{
385+
echo 'GERRIT_CHANGE_REQUEST_URL<<EOF'
386+
echo "${GERRIT_CHANGE_REQUEST_URL_VALUES}"
387+
echo EOF
388+
} >> "$GITHUB_ENV"
389+
390+
GERRIT_COMMIT_SHA_VALUES="$(<commit-sha.txt)"
391+
{
392+
echo 'GERRIT_COMMIT_SHA<<EOF'
393+
echo "${GERRIT_COMMIT_SHA_VALUES}"
394+
echo EOF
395+
} >> "$GITHUB_ENV"
396+
397+
GERRIT_CHANGE_REQUEST_NUM_VALUES="$(<change-request-number.txt)"
398+
{
399+
echo 'GERRIT_CHANGE_REQUEST_NUM<<EOF'
400+
echo "${GERRIT_CHANGE_REQUEST_NUM_VALUES}"
401+
echo EOF
402+
} >> "$GITHUB_ENV"
325403
326404
- name: Add source of Github PR URL as a gerrit comment
327405
if: env.GERRIT_CHANGE_ID != ''
@@ -334,22 +412,26 @@ jobs:
334412
pr_path="${{ github.server_url }}/${{ github.repository }}/pull/${{ env.PR_NUMBER }}"
335413
message="$(printf 'GHPR: %s\nAcition-Run: %s\n' "${pr_path}" "${run_url}")"
336414
337-
# Add a comment on the change was create from Github.
338-
ssh -v -p 29418 "${{ inputs.GERRIT_SSH_USER_G2G }}@${{ env.GERRIT_SERVER }}" \
339-
gerrit review -m "'""${message}""'" \
340-
--branch ${{ env.GERRIT_BRANCH }} --project "${{ env.PROJECT_REPO_GERRIT }}" \
341-
"${{ env.GERRIT_COMMIT_SHA }}"
342-
343-
- name: PR Comment update CR number
344-
if: env.GERRIT_CHANGE_REQUEST_URL != ''
415+
# Add comment backref change request to Github PR and workflow job.
416+
while IFS="" read -r csha; do
417+
ssh -v -n -p 29418 "${{ inputs.GERRIT_SSH_USER_G2G }}@${{ env.GERRIT_SERVER }}" \
418+
gerrit review -m "'""${message}""'" \
419+
--branch ${{ env.GERRIT_BRANCH }} --project "${{ env.PROJECT_REPO_GERRIT }}" \
420+
"$csha"
421+
done < commit-sha.txt
422+
423+
- name: Add comment to refrence the change-request on the pull-request
424+
if: |
425+
hashFiles('commit-sha.txt') != '' ||
426+
(! startsWith(env.GERRIT_CHANGE_REQUEST_URL, ''))
345427
uses: actions/github-script@v7
346428
with:
347429
result-encoding: string
348430
retries: 3
349431
retry-exempt-status-codes: 400,401
350432
script: |
351433
const output = `The pull-request PR-${{ env.PR_NUMBER }} is submitted to Gerrit [${{ inputs.ORGANIZATION }}](https://${{ env.GERRIT_SERVER }})! \n
352-
To follow up on the change visit: [${{ env.GERRIT_CHANGE_REQUEST_NUMBER }}](${{ env.GERRIT_CHANGE_REQUEST_URL }}) \n \n
434+
To follow up on the change visit: \n \n ${{ env.GERRIT_CHANGE_REQUEST_URL }} \n \n
353435
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.`
354436
github.rest.issues.createComment({
355437
issue_number: context.issue.number,

README.md

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,41 @@ The action extracts the commits from a GitHub pull-request and submits them to a
1414
The action and workflow are written with bash scripts using well known Git SCM tools, gh, jq and git-review.
1515

1616
1. The action is triggered when a new pull request is created on a GitHub repository configured with the action.
17-
2. Squash all the commits in the pull request into a single commit.
17+
2. One of the below options can be used depending on the workflow followed by the community.
18+
19+
- Squash all the commits in the pull request into a single commit and use consolidate the commit titles and body into a single commit (Default).
20+
- Squash all the commits in the pull request into a single commit and using the pull request title and body as the commit title and body (USE_PR_AS_COMMIT).
21+
- Submit each commit as a separate single commit preserving the git history (SUBMIT_SINGLE_COMMITS).
22+
1823
3. Check for a Change-Id line in the pull request commit message. If it is not present, add the Change-Id to the commit. If the Change-Id is found in any of the commits, it will be reused along with the patch.
19-
4. Create a Gerrit patch with the Change-Id, squashing all PR changes into a single commit.
20-
5. Add a pull-request reference as a comment on the Gerrit change for committers or reviewers to refer to the source of change request.
21-
6. Close the pull request once the Gerrit patch is submitted. A comment is added to the pull request with the URL to the change. Any updates will require the pull request to be reopened. Updates to the pull request are done with a force push, which triggers the workflows to ensure the change is resubmitted.
24+
4. Add the Change-Id (and optionally squash changes into a single commit if required).
25+
5. Add a pull-request and workflow run reference link as a comment on the Gerrit change that was created for committers or reviewers to back reference to the source of change request.
26+
6. Add a comment to the pull request with the URL to the change. Any updates will require the pull request to be reopened and updates to the pull request must be done with a force push, which triggers the workflows to ensure the change is resubmitted.
27+
7. Close the pull request once the Gerrit patch is submitted successfully.
2228

2329
## Features
2430

25-
### Use pull-request a commit message
31+
### Use pull-request as a single squashed commit message
32+
33+
- Commits in a pull request are squashed into a single commit before submitting the change request to Gerrit. This is the default behavior shown in the caller workflow examples.
34+
- Merge commits get filtered out.
35+
- Here `inputs.SUBMIT_SINGLE_COMMITS` is set to 'false' by default.
36+
37+
### Use pull-request body and title in the commit message
2638

27-
- Commits in a pull request are squashed into a single commit before submitting the change request to Gerrit.
39+
- The commit message title and body is extracted from the pull request body and title along with the change-Id and Signed-off-by lines. Commits are still squashed and while only the commit body and title are discarded.
40+
- Requires setting `inputs.USE_PR_AS_COMMIT` to 'true'.
41+
- This option is exclusive with `inputs.SUBMIT_SINGLE_COMMITS` and cannot be used together.
2842

29-
### Use pull-request a commit message
43+
### Submit each commit as a separate single commit
3044

31-
- Set the commit message as pull request body and title along with the change-Id and Signed-off-by lines. Commit message are squashed and the commit body and tittle are discarded.
45+
- Each commit in the pull request are processed individually as a single commit before submitting to Gerrit repository. This option allows you to preserve git history.
46+
- Requires `inputs.SUBMIT_SINGLE_COMMITS` to be set to 'true' in the caller.
3247

3348
## Caveats - Future Improvements
3449

35-
- Commits in a pull request are submitted as independent change requests to Gerrit under the same topic.
36-
- Code review comments on Gerrit will not be updated back on the pull request, requiring developers to follow up on the Gerrit change request URL.
50+
- `inputs.SUBMIT_SINGLE_COMMITS` has not be tested extensively for handling large pull requests.
51+
- Code review comments on Gerrit are not synchronized back to the pull request comment, therefore requires developers to follow up on the Gerrit change request URL. Rework through the recommended changes can be done by reopening the pull request and updating to the commits through a force push.
3752

3853
## Required Inputs
3954

@@ -44,7 +59,8 @@ The action and workflow are written with bash scripts using well known Git SCM t
4459

4560
## Optional Inputs
4661

47-
- `USE_PR_AS_COMMIT`: Use commit body and tittle from pull-request (Default: false)
62+
- `SUBMIT_SINGLE_COMMITS`: Submit one commit at a time to the Gerrit repository (Default: false)
63+
- `USE_PR_AS_COMMIT`: Use commit body and title from pull-request (Default: false)
4864
- `FETCH_DEPTH`: fetch-depth of the clone repo. (Default: 10)
4965
- `GERRIT_PROJECT`: Gerrit project repository (Default read from .gitreview).
5066
- `GERRIT_SERVER`: Gerrit server FQDN (Default read from .gitreview).
@@ -55,6 +71,7 @@ The action and workflow are written with bash scripts using well known Git SCM t
5571
## Full Example Usage with Composite Action
5672

5773
Use the composite action as a step in the workflow for further processing.
74+
Example workflow does not enable `SUBMIT_SINGLE_COMMITS` and `USE_PR_AS_COMMIT`
5875

5976
```yaml
6077
---
@@ -85,10 +102,10 @@ jobs:
85102
id: gerrit-upload
86103
uses: lfit/github2gerrit@main
87104
with:
105+
SUBMIT_SINGLE_COMMITS: "false"
106+
USE_PR_AS_COMMIT: "false"
88107
FETCH_DEPTH: 10
89108
GERRIT_KNOWN_HOSTS: ${{ vars.GERRIT_KNOWN_HOSTS }}
90-
GERRIT_SERVER: ${{ vars.GERRIT_SERVER }}
91-
GERRIT_SERVER_PORT: "29418"
92109
GERRIT_SSH_PRIVKEY_G2G: ${{ secrets.GERRIT_SSH_PRIVKEY_G2G }}
93110
GERRIT_SSH_USER_G2G: ${{ vars.GERRIT_SSH_USER_G2G }}
94111
GERRIT_SSH_USER_G2G_EMAIL: ${{ vars.GERRIT_SSH_USER_G2G_EMAIL }}

0 commit comments

Comments
 (0)