1111 schedule :
1212 - cron : ' 55 2 * * 1'
1313 workflow_dispatch :
14+ inputs :
15+ no_automatic_merge :
16+ type : boolean
17+ description : ' No automatic merge'
18+ default : false
1419
1520env :
1621 UPDATE_BRANCH : update-from-template
22+ UPDATE_BRANCH_MERGED : update-from-template-merged
1723 REMOTE_URL : https://github.com/xdev-software/java-template.git
1824 REMOTE_BRANCH : master
1925
@@ -36,31 +42,34 @@ jobs:
3642
3743 - name : Init Git
3844 run : |
39- git config --global user.email "actions@ github.com"
40- git config --global user.name "GitHub Actions "
45+ git config --global user.email "[email protected] . github.com" 46+ git config --global user.name "XDEV Bot "
4147
42- - name : Main workflow
43- id : main
48+ - name : Manage branches
49+ id : manage-branches
4450 run : |
4551 echo "Adding remote template-repo"
4652 git remote add template ${{ env.REMOTE_URL }}
4753
4854 echo "Fetching remote template repo"
4955 git fetch template
5056
51- echo "Deleting local branch that will contain the updates - if present"
57+ echo "Deleting local branches that will contain the updates - if present"
5258 git branch -D ${{ env.UPDATE_BRANCH }} || true
59+ git branch -D ${{ env.UPDATE_BRANCH_MERGED }} || true
5360
5461 echo "Checking if the remote template repo has new commits"
5562 git rev-list ..template/${{ env.REMOTE_BRANCH }}
5663
5764 if [ $(git rev-list --count ..template/${{ env.REMOTE_BRANCH }}) -eq 0 ]; then
5865 echo "There are no commits new commits on the template repo"
5966
60- echo "Deleting origin branch that contains the updates - if present"
67+ echo "Deleting origin branch(es) that contain the updates - if present"
6168 git push -f origin --delete ${{ env.UPDATE_BRANCH }} || true
69+ git push -f origin --delete ${{ env.UPDATE_BRANCH_MERGED }} || true
6270
63- echo "abort=1" >> $GITHUB_OUTPUT
71+ echo "create_update_branch_pr=0" >> $GITHUB_OUTPUT
72+ echo "create_update_branch_merged_pr=0" >> $GITHUB_OUTPUT
6473 exit 0
6574 fi
6675
@@ -73,21 +82,189 @@ jobs:
7382 echo "Pushing update branch"
7483 git push -f -u origin ${{ env.UPDATE_BRANCH }}
7584
76- echo "Getting current branch"
77- current_branch =$(git branch --show-current)
78- echo "Current branch is $current_branch "
79- echo "current_branch=$current_branch " >> $GITHUB_OUTPUT
85+ echo "Getting base branch"
86+ base_branch =$(git branch --show-current)
87+ echo "Base branch is $base_branch "
88+ echo "base_branch=$base_branch " >> $GITHUB_OUTPUT
8089
81- echo "abort=0" >> $GITHUB_OUTPUT
90+ echo "Trying to create auto-merged branch ${{ env.UPDATE_BRANCH_MERGED }}"
91+ git branch ${{ env.UPDATE_BRANCH_MERGED }} ${{ env.UPDATE_BRANCH }}
92+ git checkout ${{ env.UPDATE_BRANCH_MERGED }}
8293
83- - name : pull-request
84- if : steps.main.outputs.abort == 0
94+ echo "Merging branch $base_branch into ${{ env.UPDATE_BRANCH_MERGED }}"
95+ git merge $base_branch && merge_exit_code=$? || merge_exit_code=$?
96+ if [ $merge_exit_code -ne 0 ]; then
97+ echo "Auto merge failed! Manual merge required"
98+ echo "::notice ::Auto merge failed - Manual merge required"
99+
100+ echo "Cleaning up failed merge"
101+ git merge --abort
102+ git checkout $base_branch
103+ git branch -D ${{ env.UPDATE_BRANCH_MERGED }} || true
104+
105+ echo "Deleting auto-merge branch - if present"
106+ git push -f origin --delete ${{ env.UPDATE_BRANCH_MERGED }} || true
107+
108+ echo "create_update_branch_pr=1" >> $GITHUB_OUTPUT
109+ echo "create_update_branch_merged_pr=0" >> $GITHUB_OUTPUT
110+ exit 0
111+ fi
112+
113+ echo "Post processing: Trying to automatically fill in template variables"
114+ find . -type f \
115+ -not -path "./.git/**" \
116+ -not -path "./.github/workflows/update-from-template.yml" -print0 \
117+ | xargs -0 sed -i "s/template-placeholder/${GITHUB_REPOSITORY#*/}/g"
118+
119+ git status
120+ git add --all
121+
122+ if [[ "$(git status --porcelain)" != "" ]]; then
123+ echo "Filled in template; Committing"
124+
125+ git commit -m "Fill in template"
126+ fi
127+
128+ echo "Pushing auto-merged branch"
129+ git push -f -u origin ${{ env.UPDATE_BRANCH_MERGED }}
130+
131+ echo "update_branch_merged_commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
132+
133+ echo "Restoring base branch $base_branch"
134+ git checkout $base_branch
135+
136+ echo "create_update_branch_pr=0" >> $GITHUB_OUTPUT
137+ echo "create_update_branch_merged_pr=1" >> $GITHUB_OUTPUT
138+
139+ - name : PR update_branch
140+ if : steps.manage-branches.outputs.create_update_branch_pr == 1
85141 env :
86- GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
142+ GH_TOKEN : ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
87143 run : |
88144 gh_pr_up() {
89145 gh pr create -H "${{ env.UPDATE_BRANCH }}" "$@" || (git checkout "${{ env.UPDATE_BRANCH }}" && gh pr edit "$@")
90146 }
91- gh_pr_up -B "${{ steps.main .outputs.current_branch }}" \
147+ gh_pr_up -B "${{ steps.manage-branches .outputs.base_branch }}" \
92148 --title "Update from template" \
93149 --body "An automated PR to sync changes from the template into this repo"
150+
151+ - name : PR update_branch_merged
152+ if : steps.manage-branches.outputs.create_update_branch_merged_pr == 1
153+ env :
154+ GH_TOKEN : ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
155+ run : |
156+ gh_pr_up() {
157+ gh pr create -H "${{ env.UPDATE_BRANCH_MERGED }}" "$@" || (git checkout "${{ env.UPDATE_BRANCH_MERGED }}" && gh pr edit "$@")
158+ }
159+ gh_pr_up -B "${{ steps.manage-branches.outputs.base_branch }}" \
160+ --title "Update from template (auto-merged)" \
161+ --body "An automated PR to sync changes from the template into this repo"
162+
163+ - name : Checking if auto-merge for PR update_branch_merged can be done
164+ id : auto-merge-check
165+ if : steps.manage-branches.outputs.create_update_branch_merged_pr == 1
166+ env :
167+ GH_TOKEN : ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
168+ run : |
169+ not_failed_conclusion="skipped|neutral|success"
170+ not_relevant_app_slug="dependabot"
171+
172+ echo "Waiting for workflows to start..."
173+ sleep 60s
174+
175+ for i in {1..15}; do
176+ echo "Checking if PR can be auto-merged. Try: $i"
177+
178+ echo "Fetching checks"
179+ cs_response=$(curl -sL \
180+ --fail-with-body \
181+ --connect-timeout 60 \
182+ --max-time 120 \
183+ -H "Accept: application/vnd.github+json" \
184+ -H "Authorization: Bearer $GH_TOKEN" \
185+ -H "X-GitHub-Api-Version: 2022-11-28" \
186+ https://api.github.com/repos/${{ github.repository }}/commits/${{ steps.manage-branches.outputs.update_branch_merged_commit }}/check-suites)
187+
188+ cs_data=$(echo $cs_response | jq '.check_suites[] | { conclusion: .conclusion, slug: .app.slug, check_runs_url: .check_runs_url }')
189+ echo $cs_data
190+
191+ if [[ -z "$cs_data" ]]; then
192+ echo "No check suite data - Assuming that there are no checks to run"
193+
194+ echo "perform=1" >> $GITHUB_OUTPUT
195+ exit 0
196+ fi
197+
198+ cs_failed=$(echo $cs_data | jq --arg x "$not_failed_conclusion" 'select ((.conclusion == null or (.conclusion | test($x))) | not)')
199+ if [[ -z "$cs_failed" ]]; then
200+ echo "No check failed so far; Checking if relevant checks are still running"
201+
202+ cs_relevant_still_running=$(echo $cs_data | jq --arg x "$not_relevant_app_slug" 'select (.conclusion == null and (.slug | test($x) | not))')
203+ if [[ -z $cs_relevant_still_running ]]; then
204+ echo "All relevant checks finished - PR can be merged"
205+
206+ echo "perform=1" >> $GITHUB_OUTPUT
207+ exit 0
208+ else
209+ echo "Relevant checks are still running"
210+ echo $cs_relevant_still_running
211+ fi
212+ else
213+ echo "Detected failed check"
214+ echo $cs_failed
215+
216+ echo "perform=0" >> $GITHUB_OUTPUT
217+ exit 0
218+ fi
219+
220+ echo "Waiting before next run..."
221+ sleep 60s
222+ done
223+
224+ echo "Timed out"
225+ echo "perform=0" >> $GITHUB_OUTPUT
226+
227+ - name : Auto-merge update_branch_merged
228+ if : steps.auto-merge-check.outputs.perform == 1
229+ run : |
230+ base_branch="${{ steps.manage-branches.outputs.base_branch }}"
231+ echo "Restoring base branch $base_branch"
232+ git checkout $base_branch
233+
234+ echo "Fetching..."
235+ git fetch
236+
237+ expected_commit="${{ steps.manage-branches.outputs.update_branch_merged_commit }}"
238+ actual_commit=$(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }})
239+ if [[ "$expected_commit" != "$actual_commit" ]]; then
240+ echo "Branch ${{ env.UPDATE_BRANCH_MERGED }} contains unexpected commit $actual_commit"
241+ echo "Expected: $expected_commit"
242+
243+ exit 0
244+ fi
245+
246+ echo "Ensuring that current branch $base_branch is up-to-date"
247+ git pull
248+
249+ echo "Merging ${{ env.UPDATE_BRANCH_MERGED }} into $base_branch"
250+ git merge ${{ env.UPDATE_BRANCH_MERGED }} && merge_exit_code=$? || merge_exit_code=$?
251+ if [ $merge_exit_code -ne 0 ]; then
252+ echo "Unexpected merge failure $merge_exit_code - Requires manual resolution"
253+
254+ exit 0
255+ fi
256+
257+ if [[ "${{ inputs.no_automatic_merge }}" == "true" ]]; then
258+ echo "Exiting due no_automatic_merge"
259+
260+ exit 0
261+ fi
262+
263+ echo "Pushing"
264+ git push
265+
266+ echo "Cleaning up"
267+ git branch -D ${{ env.UPDATE_BRANCH }} || true
268+ git branch -D ${{ env.UPDATE_BRANCH_MERGED }} || true
269+ git push -f origin --delete ${{ env.UPDATE_BRANCH }} || true
270+ git push -f origin --delete ${{ env.UPDATE_BRANCH_MERGED }} || true
0 commit comments