Skip to content

docs(corekit): sixth whole-repo pass over corekit, const and vendor (#1103) #5964

docs(corekit): sixth whole-repo pass over corekit, const and vendor (#1103)

docs(corekit): sixth whole-repo pass over corekit, const and vendor (#1103) #5964

Workflow file for this run

name: GitHub Pages
on:
# No `push` trigger: chaining off `Unit Tests`' completion reuses its verdict
# instead of running the gate a second time for the same tree (#715).
# `workflow_run` fires for any completion, PR or push, so `deploy-pages`
# filters on the event itself.
workflow_run:
workflows: ["Unit Tests"]
types: [completed]
# #1967: GitHub Pages, Vendor Update and Conda Update run eight hours apart
# on Saturdays, so each runs `head`'s test gate alone and `vendor-update` and
# `conda-update` do not queue on `repository-maintenance` together. Conda
# Update comes last so its upload finds the release Create Release made after
# Vendor Update (#1634). workflows.rst gives the evidence.
schedule:
- cron: '0 2 * * 6' # Saturdays at 02:00 UTC
pull_request:
branches: [main]
# A build-only run of the dispatched ref: `head`'s test gate and the Sphinx
# build, whose site is kept as the `pages-html` artifact. Nothing is
# published to gh-pages and no report is posted.
workflow_dispatch:
permissions:
contents: read
# Keyed on the ref, unlike the validation workflows: this publishes a latest
# state, not a verdict, so a pending build a newer push supersedes is rightly
# dropped, and Pages permits only one live deployment anyway.
#
# A `workflow_run` keys on the commit `Unit Tests` verified instead (#1643):
# one whose verdict is for an older commit only runs `head` and skips, and in a
# shared group would cancel a pending run whose verdict matches. Coalescing
# then happens in `deploy-pages`' own `ci-` group, which only a run whose
# verdict covers its checkout reaches. A manual run publishes nothing, so it is
# keyed on itself here and in that group, and never displaces a pending run.
concurrency:
group: pages-${{ github.event_name == 'workflow_dispatch' && github.run_id || github.event.workflow_run.head_sha || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
# #2030: one Discussions category holds every report with no pull request to
# comment on, one thread per job.
env:
REPORT_CATEGORY: CI reports
jobs:
# #1967: the test gate on the schedule and the `verdict` on a `workflow_run`,
# shared with Conda Update and Vendor Update; cron-head.yml says when each
# runs. On a pull request both skip.
head:
name: Docs gate
permissions:
contents: read
uses: ./.github/workflows/cron-head.yml
deploy-pages:
needs: [ head ]
# A job of `head` skips on every path, so this must not inherit a skip;
# `!cancelled()` rather than `always()` so cancelling the run still cancels
# the build. The `workflow_run` clause is the real gate for a push to main:
# `head`'s `verified` says whether the verdict covers the commit checked out
# below (#1643), and without `.event == 'push'` and `.head_branch == 'main'`
# a green PR would publish docs from that PR's tree.
if: >-
!cancelled() && needs.head.result != 'failure' &&
(github.event_name != 'workflow_run' || (
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_branch == 'main' &&
needs.head.outputs.verified == 'true'
))
concurrency: ci-${{ github.event_name == 'workflow_dispatch' && github.run_id || github.ref }} # Recommended if you intend to make multiple deployments in quick succession.
runs-on: macos-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# The default `github.sha` (main's tip), not
# `github.event.workflow_run.head_sha`, which CodeQL flagged as
# "checkout of untrusted code in a privileged context": on a pull
# request's `Unit Tests` run it is a fork's commit. A trusted ref
# removes the pattern rather than relying on the `if:` guard, and
# main's tip is the right commit for docs anyway. Whether the verdict
# covers it is `head`'s question (#1643).
persist-credentials: false
# #1660: `latest` from .github/python-versions.toml, read with the
# runner's own python3.
- name: Read the Python versions
id: python-versions
run: python3 util/python_versions.py --github-output
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ steps.python-versions.outputs.latest }}
# `PCAPKIT_SPHINX` makes the `if SPHINX_TYPE_CHECKING:` TypedDicts visible
# to autodoc; `PCAPKIT_DEVMODE` logs at DEBUG with untrimmed tracebacks,
# so an autodoc import failure is legible. Both are read at import time,
# so they are exported before anything imports `pcapkit`. `.[all,dev]`
# because autodoc imports the engine wrappers too, which need #910's
# `dev` extra, as in Lint.
- name: Install and Build 🔧
run: |
set -x
export PCAPKIT_SPHINX=1
export PCAPKIT_DEVMODE=1
python -m pip install -U pip setuptools wheel
python -m pip install -r docs/requirements.txt
python -m pip install -e '.[all,dev]'
rm -rf docs/build
make -C docs html
# disable Jekyll
touch docs/build/html/.nojekyll
# `.nojekyll` is hidden, and upload-artifact leaves hidden files out unless
# told otherwise.
- name: Upload the built site
if: ${{ github.event_name != 'pull_request' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: pages-html
path: docs/build/html
include-hidden-files: true
retention-days: 1
# #1968: the push to `gh-pages`, split out so that the job running the tree's
# own code, a pull request's included, holds only `contents: read`. This one
# runs no project code, and never on a pull request or a manual run.
# `deploy-pages`' result is checked explicitly under `!cancelled()`: a skip
# anywhere in the chain skips a job left with the implicit `success()` (#1632).
publish-pages:
name: Publish to gh-pages
needs: [ deploy-pages ]
if: >-
!cancelled() && needs.deploy-pages.result == 'success' &&
github.event_name != 'pull_request' && github.event_name != 'workflow_dispatch'
concurrency:
group: publish-pages-${{ github.ref }}
cancel-in-progress: false
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
actions: read
contents: write
steps:
# The deploy action pushes from a checkout of this repository.
- name: Checkout 🛎️
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Download the built site
env:
GH_TOKEN: ${{ github.token }}
run: >-
gh run download "$GITHUB_RUN_ID" --repo "$GITHUB_REPOSITORY" --name pages-html
--dir docs/build/html
# Builds finish in any order, and a concurrency group cannot order them (a
# job joining one cancels the one pending there). So each deploy names its
# commit, and this skips only when `gh-pages` holds a build this run's
# commit is behind on main; anything else, an API error included,
# publishes. Comparing heads alone would also skip when the newer commit's
# run never publishes, a red one, leaving the docs older than this build.
- name: Check gh-pages holds no newer build
id: fresh
env:
GH_TOKEN: ${{ github.token }}
run: |
published="$(gh api "repos/$GITHUB_REPOSITORY/commits/gh-pages" --jq .commit.message |
sed -n 's/^Publish the documentation of \([0-9a-f]\{40\}\)$/\1/p' | head -n 1)"
if [ -n "$published" ] && [ "$published" != "$GITHUB_SHA" ]; then
status="$(gh api "repos/$GITHUB_REPOSITORY/compare/$published...$GITHUB_SHA" --jq .status || true)"
if [ "$status" = behind ]; then
echo "::notice title=Newer documentation already published::gh-pages holds the build of $published, which $GITHUB_SHA is behind on main, so this older build is not published"
echo "publish=false" >> "$GITHUB_OUTPUT"
exit 0
fi
fi
echo "publish=true" >> "$GITHUB_OUTPUT"
- name: Deploy 🚀
if: steps.fresh.outputs.publish == 'true'
uses: JamesIves/github-pages-deploy-action@fa24774553152dd7873cd16ebd8d959b010c5445 # v4.9.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: gh-pages # The branch the action should deploy to.
folder: docs/build/html # The folder the action should deploy.
clean: true # Automatically remove deleted files from the deploy branch
# Read back by the step above; keep the two in step.
commit-message: Publish the documentation of ${{ github.sha }}
# #2030: the run's report, the gate's, the build's and the publish's results,
# posted to the thread `deploy-pages: documentation build report`. As
# cron-vendor.yml's `discussion` job: a `workflow_run` follows a push to
# main, so it posts as a push run, only when it failed and once more on the
# next green run, and the schedule posts every run. It runs where
# `deploy-pages` ran or `head`'s gate failed, so never on a pull request's
# run or a verdict for another commit,
# which skip `deploy-pages` deliberately, nor on a manual run, which the
# thread would read as a real one. It reads no artifact, and checks
# out the script and util/_actions.py, which it imports (#2047), alone. The
# job and its step are `continue-on-error`;
# util/discussion_report.py writes a warning rather than failing.
discussion:
name: Post the Pages report
needs: [ head, deploy-pages, publish-pages ]
if: >-
${{ always() && github.event_name != 'pull_request' && github.event_name != 'workflow_dispatch' &&
(needs.deploy-pages.result != 'skipped' ||
needs.head.result == 'failure' || needs.head.result == 'cancelled') }}
runs-on: ubuntu-latest
timeout-minutes: 10
continue-on-error: true
permissions:
contents: read
discussions: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
sparse-checkout: |
util/_actions.py
util/discussion_report.py
sparse-checkout-cone-mode: false
persist-credentials: false
# A skipped `deploy-pages` reports the gate's result; a skipped
# `publish-pages` after a green build, the skip.
- name: Post the report to Discussions
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
MODE: ${{ github.event_name == 'workflow_run' && 'push' || 'scheduled' }}
HEAD_RESULT: ${{ needs.head.result }}
BUILD_RESULT: ${{ needs.deploy-pages.result }}
PUBLISH_RESULT: ${{ needs.publish-pages.result }}
run: |
if [ "$BUILD_RESULT" = skipped ]; then
status="$HEAD_RESULT"
elif [ "$BUILD_RESULT" != success ]; then
status="$BUILD_RESULT"
else
status="$PUBLISH_RESULT"
fi
mkdir -p report
{
echo '### GitHub Pages'
echo
echo "- Gate: $HEAD_RESULT"
echo "- Build: $BUILD_RESULT"
echo "- Publish: $PUBLISH_RESULT"
} > report/pages-report.md
python3 util/discussion_report.py --category "$REPORT_CATEGORY" \
--title 'deploy-pages: documentation build report' --report report/pages-report.md \
--mode "$MODE" --status "$status"