Skip to content

Documentation site · schedule #1434

Documentation site · schedule

Documentation site · schedule #1434

Workflow file for this run

name: GitHub Pages Documentation
run-name: Documentation site · ${{ github.event_name }}
on:
schedule:
- cron: "17 * * * *"
push:
branches:
- main
paths:
- ".github/scripts/build_pages_site.py"
- ".github/scripts/build_download_stats.py"
- ".github/scripts/release_recovery_state.py"
- ".github/scripts/test_pages_release_deploy_contract.py"
- ".github/workflows/github-pages.yml"
- ".github/workflows/release-recovery.yml"
- ".github/release-settings.json"
- "docs/site-data.json"
- "docs/site-assets/**"
- "docs/SITE.md"
- "docs/media/**"
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.event_name == 'pull_request' && format('toolkit-pages-pr-{0}', github.event.pull_request.number) || 'toolkit-pages-production' }}
cancel-in-progress: true
jobs:
validate:
name: Build and validate documentation site
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: ${{ github.sha }}
persist-credentials: false
- name: Overlay authoritative release-state status
shell: bash
run: |
set -euo pipefail
git fetch --no-tags --depth=1 origin \
+refs/heads/release-state:refs/remotes/origin/release-state
git restore --source=refs/remotes/origin/release-state -- \
status/release-dashboard.json \
status/README.md \
status/update-manifest.json \
status/release-speed-history.json \
status/RELEASE_SPEED.md
- name: Validate source syntax
run: |
python3 -m py_compile .github/scripts/build_pages_site.py
python3 -m py_compile .github/scripts/build_download_stats.py
python3 .github/scripts/build_download_stats.py --self-test
python3 -m py_compile .github/scripts/test_pages_release_deploy_contract.py
python3 .github/scripts/test_pages_release_deploy_contract.py
node --check docs/site-assets/site.js
python3 -m json.tool docs/site-data.json > /dev/null
- name: Build static documentation
run: |
python3 .github/scripts/build_pages_site.py \
--output _site \
--base-path /missionchief-toolkit-assets/ \
| tee pages-build-report.json
- name: Enforce deterministic static-site limits
run: |
python3 - <<'PY'
from pathlib import Path
root = Path('_site')
files = [path for path in root.rglob('*') if path.is_file()]
total_bytes = sum(path.stat().st_size for path in files)
required = [
'index.html',
'features/index.html',
'themes/index.html',
'docs/index.html',
'changelog/index.html',
'status/index.html',
'404.html',
'assets/site.css',
'assets/site.js',
'data/status.json',
]
missing = [name for name in required if not (root / name).is_file()]
empty = [name for name in required if (root / name).is_file() and (root / name).stat().st_size == 0]
diagnostic = [
f'file_count={len(files)}',
f'total_bytes={total_bytes}',
'missing=' + ','.join(missing),
'empty=' + ','.join(empty),
*[f'{path.relative_to(root)}={path.stat().st_size}' for path in sorted(files)],
]
Path('pages-limits-diagnostic.txt').write_text('\n'.join(diagnostic) + '\n', encoding='utf-8')
if missing:
raise SystemExit('Missing Pages outputs: ' + ', '.join(missing))
if empty:
raise SystemExit('Empty Pages outputs: ' + ', '.join(empty))
if not 10 <= len(files) <= 250:
raise SystemExit(f'Pages file-count limit failed: {len(files)}')
if total_bytes > 25_000_000:
raise SystemExit(f'Pages byte limit failed: {total_bytes}')
print(f'Pages output: {len(files)} files, {total_bytes} bytes.')
PY
- name: Upload Pages preview and diagnostics
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: missionchief-toolkit-pages-preview
path: |
_site/
pages-build-report.json
pages-limits-diagnostic.txt
if-no-files-found: error
retention-days: 14
deploy:
name: Deploy verified site to GitHub Pages
if: github.event_name != 'pull_request'
needs: validate
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Check out current production source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: main
fetch-depth: 1
persist-credentials: false
- name: Resolve verified production source
id: production
env:
EXPECTED_TAG: ${{ github.event_name == 'release' && github.event.release.tag_name || '' }}
shell: bash
run: |
set -euo pipefail
EXPECTED_VERSION="${EXPECTED_TAG#v}"
for ATTEMPT in $(seq 1 40); do
git fetch --no-tags --depth=1 origin \
+refs/heads/main:refs/remotes/origin/main \
+refs/heads/release-state:refs/remotes/origin/release-state
git reset --hard origin/main
git restore --source=refs/remotes/origin/release-state -- \
status/release-dashboard.json \
status/README.md \
status/update-manifest.json \
status/release-speed-history.json \
status/RELEASE_SPEED.md
DASHBOARD_VERSION="$(jq -r '.latestRelease.version // empty' status/release-dashboard.json)"
RELEASE_STATE="$(jq -r '.status.githubRelease // empty' status/release-dashboard.json)"
DISTRIBUTION_STATE="$(jq -r '.status.tkbDistribution // empty' status/release-dashboard.json)"
if [[ -z "$EXPECTED_VERSION" ]]; then
EXPECTED_VERSION="$DASHBOARD_VERSION"
fi
if [[ -n "$EXPECTED_VERSION" && "$DASHBOARD_VERSION" == "$EXPECTED_VERSION" && "$RELEASE_STATE" == "published" && "$DISTRIBUTION_STATE" == "verified" ]]; then
SOURCE_SHA="$(git rev-parse HEAD)"
RELEASE_STATE_SHA="$(git rev-parse refs/remotes/origin/release-state)"
echo "release_version=$EXPECTED_VERSION" >> "$GITHUB_OUTPUT"
echo "source_sha=$SOURCE_SHA" >> "$GITHUB_OUTPUT"
echo "release_state_sha=$RELEASE_STATE_SHA" >> "$GITHUB_OUTPUT"
echo "Deploying verified Toolkit ${EXPECTED_VERSION} from main ${SOURCE_SHA} with release-state ${RELEASE_STATE_SHA}."
exit 0
fi
echo "Waiting for verified production state ${EXPECTED_VERSION:-unknown}; dashboard=${DASHBOARD_VERSION:-missing}, GitHub=${RELEASE_STATE:-missing}, TKB distribution=${DISTRIBUTION_STATE:-missing}."
sleep 15
done
echo "::error::Verified production state ${EXPECTED_VERSION:-unknown} was not available within 10 minutes."
exit 1
- name: Configure GitHub Pages
id: pages
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
- name: Build deployment site
env:
PAGES_BASE_PATH: ${{ steps.pages.outputs.base_path }}
shell: bash
run: |
set -euo pipefail
BASE_PATH="${PAGES_BASE_PATH:-/missionchief-toolkit-assets}"
python3 .github/scripts/build_pages_site.py \
--output _site \
--base-path "$BASE_PATH"
grep -Fq "${{ steps.production.outputs.release_version }}" _site/index.html
echo "Pages source: ${{ steps.production.outputs.source_sha }}" >> "$GITHUB_STEP_SUMMARY"
echo "Pages release-state: ${{ steps.production.outputs.release_state_sha }}" >> "$GITHUB_STEP_SUMMARY"
echo "Pages release: ${{ steps.production.outputs.release_version }}" >> "$GITHUB_STEP_SUMMARY"
- name: Build public TKB download statistics
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail
gh api --paginate "repos/${GITHUB_REPOSITORY}/releases?per_page=100" --slurp > release-pages.json
python3 .github/scripts/build_download_stats.py \
--releases release-pages.json \
--output _site/data/download-stats.json
jq -e '.schemaVersion == 1 and (.newInstalls | type == "number") and (.successfulUpdates | type == "number")' \
_site/data/download-stats.json > /dev/null
echo "TKB download statistics feed generated." >> "$GITHUB_STEP_SUMMARY"
- name: Upload GitHub Pages artifact
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: _site/
- name: Deploy GitHub Pages
id: deployment
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0