|
32 | 32 | required: false |
33 | 33 | default: docs-site |
34 | 34 | type: string |
| 35 | + checkout_ref: |
| 36 | + description: Optional Git ref to check out when building documentation |
| 37 | + required: false |
| 38 | + default: '' |
| 39 | + type: string |
35 | 40 | deploy_github_pages: |
36 | 41 | description: Deploy the rendered site to GitHub Pages |
37 | 42 | required: false |
38 | 43 | default: false |
39 | 44 | type: boolean |
| 45 | + docs_version: |
| 46 | + description: Version identifier used for a GitHub Pages deployment |
| 47 | + required: false |
| 48 | + default: dev |
| 49 | + type: string |
| 50 | + docs_version_title: |
| 51 | + description: Optional display title for the documentation version |
| 52 | + required: false |
| 53 | + default: '' |
| 54 | + type: string |
| 55 | + docs_aliases: |
| 56 | + description: JSON array of aliases assigned to the documentation version |
| 57 | + required: false |
| 58 | + default: '[]' |
| 59 | + type: string |
| 60 | + docs_default_version: |
| 61 | + description: Optional version or alias used as the documentation site root |
| 62 | + required: false |
| 63 | + default: '' |
| 64 | + type: string |
| 65 | + docs_versions_branch: |
| 66 | + description: Git branch that stores assembled versioned documentation |
| 67 | + required: false |
| 68 | + default: gh-pages |
| 69 | + type: string |
40 | 70 | publish_cloudflare: |
41 | 71 | description: Publish an internal pull request to Cloudflare Pages |
42 | 72 | required: false |
|
74 | 104 | description: Stable Cloudflare Pages branch alias when a preview was published |
75 | 105 | value: ${{ jobs.build.outputs.preview_url }} |
76 | 106 |
|
| 107 | +concurrency: |
| 108 | + group: >- |
| 109 | + ${{ inputs.deploy_github_pages && |
| 110 | + format('versioned-docs-{0}-{1}', github.repository, inputs.docs_versions_branch) || |
| 111 | + format('docs-build-{0}', github.run_id) }} |
| 112 | + cancel-in-progress: false |
| 113 | + |
77 | 114 | jobs: |
78 | 115 | build: |
79 | 116 | name: Build documentation |
80 | 117 | runs-on: ubuntu-latest |
81 | 118 | permissions: |
82 | | - contents: read |
| 119 | + contents: write |
83 | 120 | deployments: write |
84 | 121 | pages: write |
85 | 122 | outputs: |
86 | 123 | preview_url: ${{ steps.preview_url.outputs.url }} |
87 | 124 | steps: |
88 | 125 | - name: Checkout repository |
89 | 126 | uses: actions/checkout@v7 |
| 127 | + with: |
| 128 | + fetch-depth: 0 |
| 129 | + ref: ${{ inputs.checkout_ref }} |
90 | 130 |
|
91 | 131 | - name: Set up Python ${{ inputs.python_version }} |
92 | 132 | uses: actions/setup-python@v7 |
@@ -131,6 +171,95 @@ jobs: |
131 | 171 | path: ${{ inputs.site_path }}/ |
132 | 172 | if-no-files-found: error |
133 | 173 |
|
| 174 | + - name: Validate versioned documentation configuration |
| 175 | + if: inputs.deploy_github_pages |
| 176 | + env: |
| 177 | + DOCS_ALIASES: ${{ inputs.docs_aliases }} |
| 178 | + DOCS_DEFAULT_VERSION: ${{ inputs.docs_default_version }} |
| 179 | + DOCS_VERSION: ${{ inputs.docs_version }} |
| 180 | + DOCS_VERSION_TITLE: ${{ inputs.docs_version_title }} |
| 181 | + DOCS_VERSIONS_BRANCH: ${{ inputs.docs_versions_branch }} |
| 182 | + run: | |
| 183 | + identifier_pattern='^[A-Za-z0-9][A-Za-z0-9._-]*$' |
| 184 | + if [[ ! "$DOCS_VERSION" =~ $identifier_pattern ]]; then |
| 185 | + echo "Invalid documentation version: $DOCS_VERSION" >&2 |
| 186 | + exit 2 |
| 187 | + fi |
| 188 | + if [[ "$DOCS_VERSION_TITLE" == *$'\n'* || "$DOCS_VERSION_TITLE" == *$'\r'* ]]; then |
| 189 | + echo 'Documentation version titles cannot contain newlines.' >&2 |
| 190 | + exit 2 |
| 191 | + fi |
| 192 | + if [[ -n "$DOCS_DEFAULT_VERSION" && ! "$DOCS_DEFAULT_VERSION" =~ $identifier_pattern ]]; then |
| 193 | + echo "Invalid default documentation version: $DOCS_DEFAULT_VERSION" >&2 |
| 194 | + exit 2 |
| 195 | + fi |
| 196 | + if ! git check-ref-format "refs/heads/$DOCS_VERSIONS_BRANCH"; then |
| 197 | + echo "Invalid documentation versions branch: $DOCS_VERSIONS_BRANCH" >&2 |
| 198 | + exit 2 |
| 199 | + fi |
| 200 | + if ! jq --exit-status \ |
| 201 | + --arg pattern "$identifier_pattern" \ |
| 202 | + 'type == "array" and all(.[]; type == "string" and test($pattern))' \ |
| 203 | + <<< "$DOCS_ALIASES" > /dev/null; then |
| 204 | + echo 'Documentation aliases must be a JSON array of valid identifiers.' >&2 |
| 205 | + exit 2 |
| 206 | + fi |
| 207 | +
|
| 208 | + - name: Install versioned documentation support |
| 209 | + if: inputs.deploy_github_pages |
| 210 | + env: |
| 211 | + MIKE_PACKAGE: mike @ git+https://github.com/squidfunk/mike.git@2d4ad799442f4592db8ad53b179bfb33db8c69ac |
| 212 | + run: uv pip install "$MIKE_PACKAGE" |
| 213 | + |
| 214 | + - name: Assemble versioned documentation |
| 215 | + if: inputs.deploy_github_pages |
| 216 | + env: |
| 217 | + DOCS_ALIASES: ${{ inputs.docs_aliases }} |
| 218 | + DOCS_DEFAULT_VERSION: ${{ inputs.docs_default_version }} |
| 219 | + DOCS_VERSION: ${{ inputs.docs_version }} |
| 220 | + DOCS_VERSION_TITLE: ${{ inputs.docs_version_title }} |
| 221 | + DOCS_VERSIONS_BRANCH: ${{ inputs.docs_versions_branch }} |
| 222 | + SITE_PATH: ${{ inputs.site_path }} |
| 223 | + run: | |
| 224 | + git config user.name 'github-actions[bot]' |
| 225 | + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' |
| 226 | +
|
| 227 | + args=( |
| 228 | + deploy |
| 229 | + --branch "$DOCS_VERSIONS_BRANCH" |
| 230 | + --alias-type redirect |
| 231 | + --update-aliases |
| 232 | + ) |
| 233 | + if [[ -n "$DOCS_VERSION_TITLE" ]]; then |
| 234 | + args+=(--title "$DOCS_VERSION_TITLE") |
| 235 | + fi |
| 236 | + args+=("$DOCS_VERSION") |
| 237 | + mapfile -t aliases < <(jq --raw-output '.[]' <<< "$DOCS_ALIASES") |
| 238 | + args+=("${aliases[@]}") |
| 239 | + uv run --no-sync mike "${args[@]}" |
| 240 | +
|
| 241 | + if ! grep --recursive --include='*.html' --extended-regexp --quiet \ |
| 242 | + '"provider"[[:space:]]*:[[:space:]]*"mike"' \ |
| 243 | + "$SITE_PATH"; then |
| 244 | + echo 'The versioned build does not enable the mike version selector.' >&2 |
| 245 | + exit 2 |
| 246 | + fi |
| 247 | +
|
| 248 | + if [[ -n "$DOCS_DEFAULT_VERSION" ]]; then |
| 249 | + uv run --no-sync mike set-default \ |
| 250 | + --branch "$DOCS_VERSIONS_BRANCH" \ |
| 251 | + "$DOCS_DEFAULT_VERSION" |
| 252 | + elif ! git cat-file --exit-code \ |
| 253 | + "$DOCS_VERSIONS_BRANCH:index.html" > /dev/null 2>&1; then |
| 254 | + uv run --no-sync mike set-default \ |
| 255 | + --branch "$DOCS_VERSIONS_BRANCH" \ |
| 256 | + "$DOCS_VERSION" |
| 257 | + fi |
| 258 | + git push -- origin "$DOCS_VERSIONS_BRANCH" |
| 259 | +
|
| 260 | + mkdir versioned-site |
| 261 | + git archive "$DOCS_VERSIONS_BRANCH" | tar --extract --directory versioned-site |
| 262 | +
|
134 | 263 | - name: Validate Cloudflare preview configuration |
135 | 264 | if: inputs.publish_cloudflare |
136 | 265 | env: |
@@ -343,11 +472,11 @@ jobs: |
343 | 472 | if: inputs.deploy_github_pages |
344 | 473 | uses: actions/configure-pages@v6 |
345 | 474 |
|
346 | | - - name: Upload GitHub Pages artifact |
| 475 | + - name: Upload versioned GitHub Pages artifact |
347 | 476 | if: inputs.deploy_github_pages |
348 | 477 | uses: actions/upload-pages-artifact@v5 |
349 | 478 | with: |
350 | | - path: ${{ inputs.site_path }}/ |
| 479 | + path: versioned-site/ |
351 | 480 |
|
352 | 481 | deploy: |
353 | 482 | name: Deploy documentation |
|
0 commit comments