-
Notifications
You must be signed in to change notification settings - Fork 1
475 lines (434 loc) · 17.8 KB
/
deploy_to_github_pages.yml
File metadata and controls
475 lines (434 loc) · 17.8 KB
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
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
# =========== IMPORTANT!! READ THIS!! ============ #
# This file can be copied to be used in other websites deployments.
# When you copy this file, make sure to check and modify the fields
# that here are marked with `MODIFY IF NEEDED`.
# Other related files/folders that you will also need to copy:
# - .github/workflows/templates/
# - .github/workflows/delete_pr_preview_comment.yml
# ============================================== #
name: Deploy to GitHub Pages
on:
push: # Action fires anytime there is a push to the following branches
branches:
- main
paths:
- 'documentation/**' # MODIFY IF NEEDED - This should be changed to be DOC_DIR/** based on the env variable DOC_DIR below
pull_request: # Action also fires anytime a PR is (re)opened, closed or synchronized
types:
- opened
- reopened
- synchronize
workflow_dispatch: # Action can also be triggered manually
env:
TZ: Australia/Canberra
DOC_DIR: 'documentation' # MODIFY IF NEEDED - Directory where the mkdocs.yml file is located relative to the repository root
BUILD_DEVELOPMENT_WEBSITE: false # MODIFY IF NEEDED - Set to 'true' to build also the development website from the 'development' branch
BUILD_DIR: ${{ github.workspace }}/website-build
WEBSITE_DIR: ${{ github.workspace }}/full-website
PR_PREVIEWS_DIR: pr-previews
PR_PREVIEW_EXCLUDE_REGEX: ^!no-(pr-)?preview\b # This regex will be considered case insensitive
PR_PREVIEW_COMMENT_LABEL: pr-preview-comment
concurrency:
group: documentation-build-deploy
cancel-in-progress: true
# ========== You should not need to modify anything below this ============ #
jobs:
# The conditionals cannot depend directly from the GitHub environment (e.g., if: env.BUILD_DEVELOPMENT_WEBSITE == 'true')
# so we use a job to set that as an output that can be then used in the other jobs' conditionals
set-development-preview-condition:
name: Set development preview build condition
runs-on: ubuntu-latest
outputs:
build_development_website: ${{ steps.set-condition.outputs.build_development_website }}
steps:
- name: Set condition
id: set-condition
run: echo "build_development_website=${{ env.BUILD_DEVELOPMENT_WEBSITE }}" >> $GITHUB_OUTPUT
# Get the root url to be used at build time to set the READTHEDOCS_CANONICAL_URL env variable
# used in the mkdocs.yml file to construct the website map for links
get-root-url:
name: Set root URL
runs-on: ubuntu-latest
outputs:
root_url: ${{ steps.get-root-url.outputs.root_url }}
env:
GH_TOKEN: ${{ github.token }} # Required for gh usage
steps:
- name: Get root url
id: get-root-url
run: |
root_url=$(gh api repos/${{ github.repository }}/pages --jq '.html_url')
if [[ $? != 0 ]]; then
echo "::error::The repository '${{ github.repository }}' does not seem to gave a GitHub Pages deployment."
exit 1
fi
echo "Root url set to '${root_url}'"
echo "root_url=${root_url}" >> $GITHUB_OUTPUT
# Get the date to be used in the PR preview comments
get-date:
name: Get date
runs-on: ubuntu-latest
# Run this job also if the workflow was skipped for concurrency reasons
if: ${{ always() }}
env:
TZ: Australia/Canberra
outputs:
date: ${{ steps.get-date.outputs.date }}
steps:
- name: Get date
id: get-date
run: echo "date=$(date '+%Y-%m-%d %H:%M %Z')" >> $GITHUB_OUTPUT
# Set up the PR preview comment
pr-preview-setup:
name: PR preview setup
# Run this job also if the workflow was skipped for concurrency reasons but only
# if the action was fired because of a PR
if: ${{ always() && github.event_name == 'pull_request' }}
needs: get-date
runs-on: ubuntu-latest
env:
HEAD: ${{ github.event.pull_request.head.sha }}
HEAD_URL: https://github.com/${{ github.event.pull_request.head.repo.full_name }}/commit/${{ github.event.pull_request.head.sha }}
permissions:
pull-requests: write
steps:
- name: Add PR preview setup comment
if: ${{ github.event.action != 'closed' }}
uses: access-nri/actions/.github/actions/comment@main
with:
message: |
PR Preview
:---:
🛫 The preview of PR head commit [${{ env.HEAD }}](${{ env.HEAD_URL }}) is currently being deployed.<br>The preview URL will be available once the deployment completes.<br>For further details, please check the [Actions](https://github.com/${{ github.repository }}/actions) tab.
${{ needs.get-date.outputs.date }}
label: ${{ env.PR_PREVIEW_COMMENT_LABEL }}
# Build the main website
build-main:
name: Build main website
runs-on: ubuntu-latest
needs: get-root-url
env:
GH_TOKEN: ${{ github.token }} # Required for gh usage
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: main
- name: Check mkdocs.yaml
id: check-mkdocs
working-directory: ${{ env.DOC_DIR }}
run: |
if [[ -f mkdocs.yml ]]; then
echo "mkdocs.yml file found."
else
echo "::warning::No mkdocs.yml file found in '$(git rev-parse --abbrev-ref HEAD)'."
echo "SKIP_STEP=true" >> $GITHUB_ENV
fi
- name: Python setup
uses: actions/setup-python@v5
if: ${{ ! env.SKIP_STEP }}
with:
python-version: 3.11.x
- name: Install dependencies
working-directory: ${{ env.DOC_DIR }}
if: ${{ ! env.SKIP_STEP }}
run: |
pip install -r requirements.txt
- name: Build website
working-directory: ${{ env.DOC_DIR }}
env:
GH_TOKEN: ${{ github.token }} # Required for gh usage
ROOT_URL: ${{ needs.get-root-url.outputs.root_url }}
id: build
if: ${{ ! env.SKIP_STEP }}
run: |
dir=
site_url="${{ env.ROOT_URL }}${dir:+${dir}/}"
command="READTHEDOCS_CANONICAL_URL=${site_url} mkdocs build -f mkdocs.yml -d ${{env.BUILD_DIR}}"
echo "$command"
eval "$command"
- name: Upload artifact
uses: actions/upload-artifact@v4
if: ${{ ! env.SKIP_STEP }}
with:
name: main-website
path: ${{env.BUILD_DIR}}
# Build the development website
build-development:
name: Build development website
runs-on: ubuntu-latest
needs: [set-development-preview-condition,get-root-url]
if: ${{ needs.set-development-preview-condition.outputs.build_development_website == 'true' }}
env:
GH_TOKEN: ${{ github.token }} # Required for gh usage
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: development
- name: Check mkdocs.yaml
id: check-mkdocs
run: |
if [[ -f mkdocs.yml ]]; then
echo "mkdocs.yml file found."
else
echo "::warning::No mkdocs.yml file found in '$(git rev-parse --abbrev-ref HEAD)'."
echo "SKIP_STEP=true" >> $GITHUB_ENV
fi
- name: Python setup
uses: actions/setup-python@v5
if: ${{ ! env.SKIP_STEP }}
with:
python-version: 3.11.x
- name: Install dependencies
working-directory: ${{ env.DOC_DIR }}
if: ${{ ! env.SKIP_STEP }}
run: |
pip install -r requirements.txt
- name: Build website
working-directory: ${{ env.DOC_DIR }}
env:
GH_TOKEN: ${{ github.token }} # Required for gh usage
ROOT_URL: ${{ needs.get-root-url.outputs.root_url }}
id: build
if: ${{ ! env.SKIP_STEP }}
run: |
dir=development-website
site_url="${{ env.ROOT_URL }}${dir:+${dir}/}"
command="READTHEDOCS_CANONICAL_URL=${site_url} mkdocs build -f mkdocs.yml -d ${{env.BUILD_DIR}}"
echo "$command"
eval "$command"
- name: Upload artifact
uses: actions/upload-artifact@v4
if: ${{ ! env.SKIP_STEP }}
with:
name: development-website
path: ${{env.BUILD_DIR}}
# Get information about open PRs to be used to build websites
# for the PR previews and to setup the PR-previews comments
get-prs-info:
name: Get PRs info
runs-on: ubuntu-latest
needs: get-root-url
outputs:
open_prs_info: ${{ steps.get-prs-info.outputs.open_prs_info }}
env:
GH_TOKEN: ${{ github.token }} # Required for gh usage
ROOT_URL: ${{ needs.get-root-url.outputs.root_url }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Get PRs info
id: get-prs-info
working-directory: ${{ env.DOC_DIR }}
run: |
# Include only open PRs, not from forks, and whose head branch is not `main`
open_prs=$(
gh pr list \
--state open \
--json number,title,headRepositoryOwner,headRefOid,body \
--jq 'sort_by(.number) | .[] | select( .headRefName!="main" and .headRepositoryOwner.login=="${{ github.repository_owner }}")' \
)
# If open PRs are found, filter them and output the desired json object
if [[ -n "$open_prs" ]]; then
# Keep only PRs:
# - with a mkdocs.yml file in their head commit
# - whose body doesn't start with a PR_PREVIEW_EXCLUDE_REGEX line
filtered_prs=$(
while IFS= read -r pr; do
sha=$(jq -r '.headRefOid' <<< $pr)
body=$(jq -r '.body' <<< $pr)
if (
gh api repos/${{ github.repository }}/git/trees/${sha}?recursive=1 | \
jq '.tree[].path' | grep 'mkdocs.ya\?ml' > /dev/null
) && (
! grep -qi '${{ env.PR_PREVIEW_EXCLUDE_REGEX }}' <<< "$body"
); then
echo $pr
fi
done <<< "$open_prs"
)
# Define the PR info json object with the following fields:
# - pr_number: the PR number
# - pr_title: the PR title
# - pr_head_sha: the PR head commit sha
# - pr_preview_url: the PR preview URL
open_prs_info=$(
jq -s -c '[.[] | {
pr_number: .number,
pr_title: .title,
pr_head_sha: .headRefOid,
pr_preview_url: ("${{ env.ROOT_URL }}${{ env.PR_PREVIEWS_DIR }}/" + (.number | tostring))
}]' <<< "$filtered_prs"
)
echo "Found the following open PRs:"
jq <<< "$open_prs_info"
else
echo "No open PRs found."
fi
echo "open_prs_info=${open_prs_info}" >> "$GITHUB_OUTPUT"
# Build each pr website with matrix strategy jobs
build-pr:
name: Build PR ${{matrix.pr_number}}
runs-on: ubuntu-latest
needs: [get-root-url, get-prs-info]
# Run this job only if there are open PRs
if: ${{ needs.get-prs-info.outputs.open_prs_info != '' }}
env:
GH_TOKEN: ${{ github.token }} # Required for gh usage
strategy:
fail-fast: true
matrix:
include: ${{ fromJson(needs.get-prs-info.outputs.open_prs_info) }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ matrix.pr_head_sha }}
- name: Python setup
uses: actions/setup-python@v5
with:
python-version: 3.11.x
- name: Install dependencies
working-directory: ${{ env.DOC_DIR }}
run: |
pip install -r requirements.txt
- name: Build website
working-directory: ${{ env.DOC_DIR }}
env:
GH_TOKEN: ${{ github.token }} # Required for gh usage
ROOT_URL: ${{ needs.get-root-url.outputs.root_url }}
id: build
run: |
dir=$(sed 's|^${{ env.ROOT_URL }}||' <<< ${{ matrix.pr_preview_url }})
site_url="${{ env.ROOT_URL }}${dir:+${dir}/}"
command="READTHEDOCS_CANONICAL_URL=${site_url} mkdocs build -f mkdocs.yml -d ${{env.BUILD_DIR}}"
echo "$command"
eval "$command"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.pr_number }}
path: ${{env.BUILD_DIR}}
# Create the pr-previews page with links to all avaiable pr-previews
create-pr-previews-page:
name: Create PR previews list page
runs-on: ubuntu-latest
needs: [get-root-url, get-prs-info]
env:
GH_TOKEN: ${{ github.token }} # Required for gh usage
FILE_NAME: index.html
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Python setup
uses: actions/setup-python@v5
with:
python-version: 3.11.x
- name: Install dependencies
run: pip install jinja-cli==1.2.2
- name: Create PR previews page
run: |
open_prs_json='${{ needs.get-prs-info.outputs.open_prs_info }}'
if [[ -n "$open_prs_json" ]]; then
data_json=$(jq -c -n --argjson data "$open_prs_json" '{"data": $data}')
else
data_json='{}'
fi
jq -c <<< "$data_json" | \
jinja -d - -f json ./.github/workflows/templates/pr_previews_page.html > ${{ env.FILE_NAME }}
echo "Created the pr-previews page through the following html file:"
cat ${{ env.FILE_NAME }}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: '${{ env.PR_PREVIEWS_DIR }}'
path: ${{ env.FILE_NAME }}
# Set the final website structure for the deployment
set-website-structure:
name: Set entire website structure
runs-on: ubuntu-latest
needs: [build-main, build-development, build-pr, create-pr-previews-page]
# Run this job also if build-pr or build-development was skipped (no PR was found or no development build requested)
if: ${{ always() && contains(fromJson('["success","skipped"]'), needs.build-pr.result) && contains(fromJson('["success","skipped"]'), needs.build-development.result) }}
env:
GH_TOKEN: ${{ github.token }} # Required for gh usage
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download all build artifacts
uses: actions/download-artifact@v4
with:
path: ${{ env.WEBSITE_DIR }}
- name: Set website structure
run: |
# Move all PR websites (directories named with only numbers) within the pr-previews directory
# Using '[0-9]*' instead of '[0-9]+' within the regex because I cannot make the plus ('+') sign to be recognised correctly
find ${{ env.WEBSITE_DIR }} -maxdepth 1 -type d -regex '.*/[0-9]*$' -exec mv {} ${{ env.WEBSITE_DIR }}/${{ env.PR_PREVIEWS_DIR }} \;
# Move the main website to the root of the website directory and remove the empty main-website artifact directory
mv ${{ env.WEBSITE_DIR }}/main-website/* ${{ env.WEBSITE_DIR }}
rm -rf ${{ env.WEBSITE_DIR }}/main-website
# Set permissions
chmod -c -R +rX ${{ env.WEBSITE_DIR }}
echo "Website structure set to:"
tree -d -L 2 ${{ env.WEBSITE_DIR }}
- name: Create artifact for deployment to GitHub Pages
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa #v3.0.1
with:
path: ${{ env.WEBSITE_DIR }}
# Deploy the website to GitHub Pages
deploy:
needs: set-website-structure
runs-on: ubuntu-latest
# Need to specify this conition because otherwise this job might be skipped if
# any job needed by this job's needed job(s) is skipped (e.g., if a job needed by set-website-structure is skipped)
# Reference: https://github.com/actions/runner/issues/2205
if: ${{ always() && needs.set-website-structure.result == 'success' }}
permissions:
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source
steps:
- name: Deploy to GitHub Pages
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e #v4.0.5
# Set pr-preview messages
pr-preview:
needs: [get-date, get-prs-info, deploy]
# Run this job only if there are open PRs
if: ${{ always() && needs.deploy.result == 'success' && needs.get-prs-info.outputs.open_prs_info != '' }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.get-prs-info.outputs.open_prs_info) }}
permissions:
pull-requests: write
steps:
- name: Add PR preview setup comment
uses: access-nri/actions/.github/actions/comment@main
with:
message: |
PR Preview
:---:
🚀 Preview of PR head commit ${{ matrix.pr_head_sha }} deployed to ${{ matrix.pr_preview_url }}
${{ needs.get-date.outputs.date }}
Preview generated through the _${{ github.workflow }}_ workflow run [${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}).
number: ${{ matrix.pr_number }}
label: ${{ env.PR_PREVIEW_COMMENT_LABEL }}
failed-preview:
needs: [get-date, pr-preview]
# Run this job if the workflow was triggered because of a pull request and any previou job failed
if: ${{ github.event_name == 'pull_request' && failure() }}
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Add PR preview failure comment
uses: access-nri/actions/.github/actions/comment@main
with:
message: |
PR Preview
:---:
⚠️ There was an error in the pr-preview deployment.
For more information check the [Actions](https://github.com/${{github.repository}}/actions) tab.
${{ needs.get-date.outputs.date }}
label: ${{ env.PR_PREVIEW_COMMENT_LABEL }}