-
Notifications
You must be signed in to change notification settings - Fork 69
147 lines (138 loc) · 6.11 KB
/
Copy pathpages.yml
File metadata and controls
147 lines (138 loc) · 6.11 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
name: Site
on:
push:
branches: ["main"]
paths:
- "docs/**"
- ".github/workflows/pages.yml"
# Unfiltered on purpose, unlike the push above. A required check has to be
# able to report on every pull request: a path filter skips the whole
# workflow, the status never arrives, and a branch rule waiting on it would
# block every pull request that did not touch the site. Making it optional
# instead was the other way out, and it is worse — a red build merges.
# The build costs 15-35s, which is not a price worth designing around.
pull_request:
# The install commands name the released version, which is resolved at build
# time — without this the site keeps advertising the previous release until
# something else under docs/ happens to change.
release:
types: [published]
workflow_dispatch:
# Read-only at the top: a job that runs on a pull request must not hold the
# credentials that can publish. Pages write and OIDC are granted to the deploy
# job alone, which never runs from a pull request.
permissions:
contents: read
# One deployment at a time. Queued runs collapse, but a run already
# publishing is never cancelled.
# Production deploys share one lane whatever triggered them. Keying the group
# on the ref put a main push and a release run in different lanes, so they
# could publish concurrently and land out of order. Pull requests keep their
# own lanes; they never deploy.
concurrency:
group: ${{ github.event_name == 'pull_request' && format('pages-pr-{0}', github.ref) || 'pages-production' }}
cancel-in-progress: false
jobs:
# A release run's ref is the tag, and the github-pages environment admits
# only main — the deploy job would be refused at the gate. Dispatch the same
# workflow against main instead, which enters the environment normally and
# rebuilds the install commands with the new version.
redispatch:
if: github.event_name == 'release'
runs-on: ubuntu-latest
permissions:
actions: write
steps:
- run: gh workflow run pages.yml --repo "$GITHUB_REPOSITORY" --ref main
env:
GH_TOKEN: ${{ github.token }}
# Builds on every pull request, so a broken Liquid tag or a dead link is
# caught in review rather than by a deploy that fails after the merge and
# leaves the site quietly serving the previous version.
#
# ruby/setup-ruby with the checked-in Gemfile rather than
# actions/jekyll-build-pages. That action pins the github-pages gem, which
# pins Jekyll 3.10 and — through commonmarker — Ruby < 4.0. On a machine
# running Ruby 4 the gem cannot be installed at all, so nobody could
# reproduce the CI build locally; a failure would first appear after a
# deploy. The cost of building it ourselves is this lockfile, which is why
# it is committed and carries the runner's platform.
build:
# Named, because this is a required check and "build" as a bare context in
# a branch rule says nothing about which workflow owns it.
name: The site builds
# The release event only redispatches; the dispatched run does the work.
if: github.event_name != 'release'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: "3.3"
bundler-cache: true
working-directory: docs
# No configure-pages step: its only useful output is base_url, and the
# site's url/baseurl come from _config.yml. Dropping it keeps the build
# job on contents:read with nothing to grant it.
# The released version is resolved here rather than kept in _config.yml,
# so nobody has to remember to bump it: the install commands and the
# pre-JavaScript header pill name the real latest release on every build.
# The pill is corrected again from the API at view time, which covers a
# release published between deploys.
- name: Resolve the released version
working-directory: docs
run: |
tag=$(curl -fsSL -H 'Accept: application/vnd.github+json' \
-H "Authorization: Bearer $GITHUB_TOKEN" \
"https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/latest" \
| sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
if [ -n "$tag" ]; then
echo "sdns_version: $tag" > _config.release.yml
echo "building with sdns_version=$tag"
else
echo "sdns_version: ${FALLBACK}" > _config.release.yml
echo "::warning::could not resolve the latest release; keeping the checked-in value"
fi
env:
GITHUB_TOKEN: ${{ github.token }}
FALLBACK: ""
- name: Build
working-directory: docs
env:
JEKYLL_ENV: production
run: |
cfg=_config.yml
if [ -s _config.release.yml ] && grep -q 'sdns_version: .' _config.release.yml; then
cfg="_config.yml,_config.release.yml"
fi
bundle exec jekyll build --config "$cfg" --destination ../_site --trace
- name: Check internal links resolve
run: |
fail=0
# Every href into /docs/ must have a generated page behind it.
grep -rhoE 'href="/docs/[a-z0-9/-]*"' _site --include='*.html' \
| sed 's/href="//;s/"//' | sort -u | while read -r u; do
if [ ! -f "_site${u}index.html" ]; then
echo "broken internal link: $u"; exit 1
fi
done || fail=1
test "$fail" -eq 0
- uses: actions/upload-pages-artifact@v3
if: github.event_name != 'pull_request'
deploy:
needs: build
permissions:
pages: write
id-token: write
# Never from a pull request, and never from a branch other than main —
# the environment's branch policy is the backstop, not the only gate.
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4