Skip to content

Fix chunked reconstruction losing windows over nanosecond times (#261) #48

Fix chunked reconstruction losing windows over nanosecond times (#261)

Fix chunked reconstruction losing windows over nanosecond times (#261) #48

Workflow file for this run

name: Build documentation
on:
push:
branches:
- main
release:
types:
- published
workflow_dispatch:
inputs:
ref:
description: "Git ref (tag) to build the docs from; empty builds the ref the workflow runs on"
required: false
type: string
default: ""
version:
description: "Docs version to deploy (e.g. 0.3, or rc for the rolling pre-release docs)"
required: true
type: string
latest:
description: "Point the 'latest' alias (public default) at this version"
required: false
type: boolean
default: false
defaults:
run:
shell: bash
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
# Rolling targets (dev, rc) are newest-wins; stable releases queue in
# publish order. The groups must stay separate: cancel-in-progress is
# evaluated per incoming run, so a shared group would let an arriving
# pre-release cancel a running stable build
concurrency:
group: docs-build-${{ github.event_name == 'push' && 'dev' || ((github.event_name == 'release' && (github.event.release.prerelease || (contains(github.event.release.tag_name, '-') && !contains(github.event.release.tag_name, '+')))) || (github.event_name == 'workflow_dispatch' && inputs.version == 'rc')) && 'rc' || github.event_name == 'release' && 'stable' || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'push' || (github.event_name == 'release' && (github.event.release.prerelease || (contains(github.event.release.tag_name, '-') && !contains(github.event.release.tag_name, '+')))) || (github.event_name == 'workflow_dispatch' && inputs.version == 'rc') }}
steps:
# Dispatch builds a tag via the ref input; dispatching from a tag
# would use that tag's workflow definition, which lacks this trigger
- uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ inputs.ref }}
- name: Install uv
uses: astral-sh/setup-uv@v5
# Tags predating the versioning setup lack the provider key, and
# their docs would build without the version selector
- name: Ensure version provider on backfill builds
if: github.event_name == 'workflow_dispatch' && inputs.ref != ''
run: |
if ! grep -q 'provider = "mike"' zensical.toml; then
printf '\n[project.extra.version]\nprovider = "mike"\n' >> zensical.toml
fi
- name: Configure git identity
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Resolve docs version
id: docs
env:
EVENT_NAME: ${{ github.event_name }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
RELEASE_PRERELEASE: ${{ github.event.release.prerelease }}
INPUT_VERSION: ${{ inputs.version }}
INPUT_LATEST: ${{ inputs.latest }}
INPUT_REF: ${{ inputs.ref }}
run: |
if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then
# Only MAJOR.MINOR or the rolling 'rc' target; in particular
# this rejects the 'latest' alias and the auto-managed 'dev'
if [[ ! "$INPUT_VERSION" =~ ^([0-9]+\.[0-9]+|rc)$ ]]; then
echo "Invalid docs version '$INPUT_VERSION'; expected MAJOR.MINOR (e.g. 0.3) or rc" >&2
exit 1
fi
if [[ "$INPUT_VERSION" == "rc" && "$INPUT_LATEST" == "true" ]]; then
echo "The public default cannot point at the rolling rc version" >&2
exit 1
fi
version="$INPUT_VERSION"
latest="$INPUT_LATEST"
# An rc rebuild keeps its tag-derived title instead of 'rc'
if [[ "$INPUT_VERSION" == "rc" && -n "$INPUT_REF" ]]; then
title="${INPUT_REF#v}"
fi
elif [[ "$EVENT_NAME" == "release" ]]; then
if [[ ! "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([-+].*)?$ ]]; then
echo "Tag '$RELEASE_TAG' is not vMAJOR.MINOR.PATCH; refusing to deploy docs" >&2
exit 1
fi
# The tag's own pre-release suffix counts even when the GitHub
# pre-release checkbox was forgotten: a '-' right after the
# patch number, not a hyphen inside '+' build metadata
if [[ "$RELEASE_PRERELEASE" == "true" || "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+- ]]; then
# Pre-releases go to a rolling 'rc' version so they can never
# overwrite the stable X.Y that 'latest' may already point to
version="rc"
title="${RELEASE_TAG#v}"
latest="false"
else
# v0.4.0 -> 0.4
version="$(echo "${RELEASE_TAG#v}" | cut -d. -f1,2)"
latest="true"
fi
else
version="dev"
latest="false"
fi
echo "version=${version}" >> "$GITHUB_OUTPUT"
echo "title=${title:-${version}}" >> "$GITHUB_OUTPUT"
echo "latest=${latest}" >> "$GITHUB_OUTPUT"
- name: Deploy documentation version
env:
VERSION: ${{ steps.docs.outputs.version }}
TITLE: ${{ steps.docs.outputs.title }}
LATEST: ${{ steps.docs.outputs.latest }}
GUARD_LATEST: ${{ github.event_name == 'release' }}
run: |
# The zensical fork of mike is GitHub-only (no PyPI releases), so
# pin it to a commit; this job holds contents: write
mike() {
uvx --from "git+https://github.com/squidfunk/mike.git@2d4ad799442f4592db8ad53b179bfb33db8c69ac" \
--with "mkdocstrings[python]" mike "$@"
}
# A maintenance release for an older line (e.g. v0.3.4 after
# v0.4.0) must not move 'latest' backward; re-checked against
# fresh gh-pages state on every attempt since release builds are
# not serialized. Dispatches honor the explicit input.
# Returns 0 = may move, 1 = older line, 2 = could not verify —
# fail closed, except for a confirmed-absent gh-pages (bootstrap)
may_move_latest() {
[[ "$GUARD_LATEST" == "true" ]] || return 0
if ! git fetch --quiet origin gh-pages 2>/dev/null; then
rc=0
git ls-remote --exit-code origin refs/heads/gh-pages >/dev/null 2>&1 || rc=$?
[[ "$rc" -eq 2 ]] && return 0
echo "Cannot verify the current latest target; failing this attempt" >&2
return 2
fi
current="$(git show FETCH_HEAD:versions.json 2>/dev/null \
| jq -r '.[] | select(.aliases | index("latest")) | .version')" || {
echo "Cannot read versions.json from gh-pages; failing this attempt" >&2
return 2
}
if [[ -n "$current" ]] && \
[[ "$(printf '%s\n%s\n' "$current" "$VERSION" | sort -V | tail -1)" != "$VERSION" ]]; then
echo "Line ${VERSION} is older than current latest (${current}); not moving the alias" >&2
return 1
fi
}
deploy() {
if [[ "$LATEST" != "true" ]]; then
mike deploy --push --title "$TITLE" "$VERSION"
return
fi
rc=0
may_move_latest || rc=$?
case "$rc" in
0) mike deploy --push --update-aliases --title "$TITLE" "$VERSION" latest &&
mike set-default --push latest ;;
1) mike deploy --push --title "$TITLE" "$VERSION" ;;
*) return 2 ;;
esac
}
# Concurrent runs race on the gh-pages push; the local branch must
# be reset to the remote before rerunning, or every retry replays
# the same non-fast-forward rejection
retry() {
for attempt in 1 2; do
"$@" && return 0
echo "attempt ${attempt} failed; retrying" >&2
sleep 15
git fetch --force origin gh-pages:gh-pages 2>/dev/null || true
done
"$@"
}
retry deploy
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
pages: write
id-token: write
# Serialize Pages publishes only; every build job must run so no mike
# deploy is lost. gh-pages state is cumulative, so a pending deploy
# superseded in this queue is covered by the newer one that replaced it
concurrency:
group: "pages"
cancel-in-progress: false
steps:
- uses: actions/checkout@v6
with:
ref: gh-pages
- name: Check a default version exists
id: bootstrapped
run: |
# The root redirect only exists once a stable version has been
# deployed and set as default; until then, keep serving the
# previously published site instead of a broken root
if [[ -f index.html ]]; then
echo "ok=true" >> "$GITHUB_OUTPUT"
else
echo "ok=false" >> "$GITHUB_OUTPUT"
echo "No default docs version set yet; skipping Pages publish" >&2
fi
- name: Upload artifact
if: steps.bootstrapped.outputs.ok == 'true'
uses: actions/upload-pages-artifact@v4
with:
path: .
- name: Deploy to GitHub Pages
if: steps.bootstrapped.outputs.ok == 'true'
id: deployment
uses: actions/deploy-pages@v5