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
|
---
# --------------------( LICENSE )--------------------
# Copyright (c) 2014-2025 Beartype authors.
# See "LICENSE" for further details.
#
# --------------------( SYNOPSIS )--------------------
# GitHub-specific static site generation configuration, enabling automated
# deployment of the MkDocs-driven documentation for this project to the GitHub
# Pages-hosted site associated with this repository on each push of a commit to
# the "main" branch of this repository.
#
# This workflow intentionally avoids an intermediate "gh-pages" branch housing
# web-specific output files generated by the "mkDocs build" command in favour of
# directly pushing those files to the GitHub Pages service. Doing so
# dramatically decreases both the size of this GitHub-hosted repository and the
# time for this workflow to complete.
#
# --------------------( CAVEATS )--------------------
# There currently exist *NO* best practices for publishing Mkdocs-driven
# documentation to a GitHub Pages-hosted site. Several alternatives exist, each
# with concomitant advantages and disadvantages:
# * Well-maintained blog article originally authored in 2022 but since actively
# updated for the past several years. Although unofficial, this article is
# the best approximation of "best practices":
# https://group.miletic.net/en/blog/2022-11-01-publishing-material-for-mkdocs-website-to-github-pages-using-custom-actions-workflow
# * GitHub Actions-based workflow officially promoted by Material for MkDocs:
# https://squidfunk.github.io/mkdocs-material/publishing-your-site
# ....................{ METADATA }....................
# Non-human-readable (i.e., machine-readable) label associated with this
# GitHub Actions workflow.
name: docs
# ....................{ TRIGGER }....................
# Confine deployment to only...
on:
# Pushes to the main branch. Pushes to other branches are assumed to be
# developer-specific and thus already deployed locally by that developer.
push:
branches:
- 'main'
# Allow only one concurrent run of this workflow while:
# * Skipping runs accidentally queued between the current in-progress run and
# the most recently queued run.
# * Avoiding cancelling the current in-progress run.
concurrency:
group: 'pages'
cancel-in-progress: false
# ....................{ PERMISSIONS }....................
# Default job security model applied by default to all jobs performed below.
permissions:
# Permit third-party GitHub Actions to read the contents of this repository's
# ".git/" subdirectory (e.g., to list all git commits). This is the safest
# explicit permission that a GitHub workflow can currently grant to
# third-party GitHub Actions. Ideally, this permission would be the default.
# According to the CodeQL code scanner, however, this is *NOT* the case.
# CodeQL security alerts document that:
# If a GitHub Actions job or workflow has no explicit permissions set,
# then the repository permissions are used. Repositories created under
# organizations inherit the organization permissions. The organizations or
# repositories created before February 2023 have the default permissions
# set to read-write. Often these permissions do not adhere to the
# principle of least privilege and can be reduced to read-only, leaving
# the write permission only to a specific types as issues: write or
# pull-requests: write.
#
# Explicitly granting this permission elides both this CodeQL security alert
# and the underlying insecurity described by this alert.
contents: read
# Permit third-party GitHub Actions to both read and write the dynamically
# generated ${GITHUB_TOKEN} supplied by the GitHub Actions API.
id-token: write
# Permit third-party GitHub Actions to both read and write the GitHub Pages
# associated with this repository.
pages: write
# ....................{ MAIN }....................
jobs:
# ...................{ BUILD }...................
# Job generating a new MkDocs-driven static site.
build:
name: "Create static site with Mkdocs"
runs-on: ubuntu-latest
steps:
# ..................{ SETUP }..................
- name: "Checking out repository..."
uses: 'actions/checkout@v6'
- name: "Preparing GitHub Pages..."
uses: 'actions/configure-pages@v5'
- name: "Installing Python..."
uses: 'actions/setup-python@v6'
with:
python-version: '3.x'
- name: 'Installing uv...'
uses: 'astral-sh/setup-uv@v7'
with:
# Temporarily cache third-party packages subsequently installed by
# "uv pip" below. This action intelligently defines the cache key to
# be hashed against the top-level "pyproject.toml" file and thus
# silently clears this cache on each change to that file. See also:
# https://github.com/actions/setup-python?tab=readme-ov-file#caching-packages-dependencies
enable-cache: true
cache-dependency-glob: 'pyproject.toml'
- name: 'Displaying Python metadata...'
run: |
python3 -VV
python3 -m site
# Print either:
# * For free-threading Python builds:
# Py_GIL_DISABLED: 1
# * For GIL-encumbered Python builds:
# Py_GIL_DISABLED: 0
python3 -c "import sysconfig; print('Py_GIL_DISABLED:', sysconfig.get_config_var('Py_GIL_DISABLED'))"
# ..................{ VALIDATE }..................
#FIXME: Consider uncommenting if we ever run into serious snags with
#MkDocs-specific configuration files or Markdown. Note that we'll also
#need to additionally define a "yamllint" configuration. See the
#quasi-authoritative blog article linked above. *sigh*
# - name: Install yamllint
# run: pip install yamllint
# - name: Check MkDocs YAML configuration
# run: yamllint ./mkdocs.yml
# continue-on-error: true
# - name: Check Markdown files
# uses: DavidAnson/markdownlint-cli2-action@v19
# with:
# globs: '**/*.md'
# continue-on-error: true
# ..................{ CACHE }..................
#FIXME: The quasi-authoritative blog article linked above advises *NOT*
#doing this, as:
# "Removed caching as (Material for) MkDocs version is not pinned and
# therefore the site builds are not reproducible."
# # Define a new "${CACHE_ID}" environment variable whose value is the
# # current 0-based number of the current week with respect to the entire
# # year. This number is guaranteed to be in the range [0, 53].
# - name: "Setting caching environment variables..."
# run: |
# set -xe
# echo "CACHE_ID=$(date --utc '+%V')" >> $GITHUB_ENV
#
# # Restore all MkDocs assets previously cached for the current week by the
# # most recent run of this workflow. This cache is tied to the week and
# # thus automatically expires on the Sunday of each new week.
# - name: "Restoring cached MkDocs assets..."
# uses: actions/cache@v4
# with:
# key: "mkdocs-material-${{ env.CACHE_ID }}"
# path: ".cache"
# restore-keys: |
# mkdocs-material-
# ..................{ INSTALL }..................
# Install "pip"-based Python dependencies. Note that:
# * This command *MUST* be platform-agnostic by running under both:
# * POSIX-compliant platforms (e.g., Linux, macOS).
# * POSIX-noncompliant platforms (e.g., Windows).
# In particular, commands that assume a POSIX-compliant shell (e.g.,
# Bash) *MUST* be avoided.
# * Packaging dependencies (e.g., "pip") are upgraded *BEFORE* all
# remaining dependencies (e.g., "tox").
- name: "Upgrading packager dependencies..."
run: |
set -xe
uv pip install --quiet --system --upgrade pip hatch wheel
# Install all documentation-time dependencies required to generate
# documentation for this project. Technically, this also uselessly
# installs this package and all runtime dependencies required to use this
# package, all of which is irrelevant to documentation generation.
# Pragmatically, this approach nonetheless enjoys the overwhelming
# advantage of centralizing all documentation-time dependencies in the
# top-level "pyproject.toml" file for this project -- preserving Don't
# Repeat Yourself (DRY) that would otherwise require us to manually list
# these dependencies here. In short, this is the least bad approach.
- name: "Installing package dependencies..."
run: |
set -xe
uv pip install --quiet --system -e .[doc-ghp]
# ..................{ DOCUMENTATION }..................
# Generate the MkDocs-driven static site for this repository in the local
# Jekyll-specific "_site/" subdirectory (for compatibility with Jekyll,
# which most GitHub Pages infrastructure still assumes). See also:
# # Further options for this MkDocs subcommand.
# mkdocs build --help
- name: "Building static site..."
env:
# Notify the "mkdocs build" subcommand run below that it is running
# under a GitHub Actions-based continuous integration (CI) workflow by
# defining the quasi-standard "${CI}" environment variable.
CI: true
run: |
set -xe
mkdocs build --config-file ./mkdocs.yml --strict --site-dir ./_site
- name: "Preparing static site for deployment..."
uses: actions/upload-pages-artifact@v4
with:
path: '_site'
# ...................{ DEPLOY }...................
# Job deploying the previously generated MkDocs-driven static site to GitHub
# Pages -- silently overwriting the prior GitHub Pages-hosted site.
deploy:
name: "Deploy static site to GitHub Pages"
runs-on: ubuntu-latest
# Perform this job *ONLY* if the prior job succeeded.
needs: build
# GitHub Environment associated with this job. Note that the third-party
# "deploy-pages" Action run below *STRONGLY* recommends this exact
# environment name and associated URL.
environment:
# "deploy-pages"-specific name of this environment.
name: github-pages
# "deploy-pages"-specific URL associated with this environment.
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: "Deploying static site to GitHub Pages..."
uses: 'actions/deploy-pages@v4'
id: deployment
|