Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ name: Docs

# Builds Sphinx documentation on every push and PR that touches docs/, src/, or
# this workflow. On pushes to main the rendered site is published to GitHub
# Pages. PRs only build to verify the docs still compile.
# Pages only after deployment is explicitly enabled. PRs only build to verify
# the docs still compile.
#
# One-time setup: in the repository's Settings -> Pages, set Source to
# "GitHub Actions". Without this, the first run of the deploy job fails on
# actions/deploy-pages with "Get Pages site failed". This cannot be configured
# from a workflow. See README.md "Deploying API documentation".
# "GitHub Actions", then set the DEPLOY_GITHUB_PAGES repository variable to
# "true". Without the variable, deployment is skipped with a notice. Without
# Pages configured, actions/deploy-pages fails with "Get Pages site failed".
# See README.md "Deploying API documentation".

on:
push:
Expand Down Expand Up @@ -64,20 +66,24 @@ jobs:
path: _site
if-no-files-found: error

- name: Report skipped GitHub Pages deployment
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && vars.DEPLOY_GITHUB_PAGES != 'true'
run: echo "::notice::Skipping GitHub Pages deployment. To enable publishing, set Settings -> Pages -> Source = GitHub Actions, then add repository variable DEPLOY_GITHUB_PAGES=true."

- name: Configure GitHub Pages
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && vars.DEPLOY_GITHUB_PAGES == 'true'
uses: actions/configure-pages@v6

- name: Upload GitHub Pages artifact
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && vars.DEPLOY_GITHUB_PAGES == 'true'
uses: actions/upload-pages-artifact@v5
with:
path: _site

deploy:
name: Deploy to GitHub Pages
needs: [build]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && vars.DEPLOY_GITHUB_PAGES == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
environment:
Expand Down
33 changes: 19 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ A comprehensive template for AI-driven Python development with full CI/CD pipeli
- **CI/CD pipeline**: GitHub Actions CI/CD with Python 3.13
- **Changelog management**: Scriv for conflict-free changelog (like Changesets in JS)
- **Release automation**: Automatic PyPI publishing and GitHub releases
- **API documentation**: Sphinx + GitHub Pages deploy on push to `main`
- **API documentation**: Sphinx + opt-in GitHub Pages deploy on push to `main`

## Quick Start

Expand Down Expand Up @@ -88,7 +88,7 @@ ruff check . && ruff format --check . && mypy src/ && python scripts/check_file_
.
├── .github/
│ └── workflows/
│ ├── docs.yml # Sphinx build + GitHub Pages deploy
│ ├── docs.yml # Sphinx build + opt-in GitHub Pages deploy
│ └── release.yml # CI checks + release automation (PyPI + GitHub)
├── changelog.d/ # Changelog fragments (like .changeset/)
│ ├── README.md # Fragment instructions
Expand Down Expand Up @@ -189,9 +189,9 @@ The GitHub Actions workflow provides:

### API Documentation

API documentation is built with [Sphinx](https://www.sphinx-doc.org/) and deployed
to GitHub Pages on every push to `main`. Pull requests build the docs (without
deploying) to catch regressions before they merge.
API documentation is built with [Sphinx](https://www.sphinx-doc.org/) and can be
deployed to GitHub Pages on pushes to `main`. Pull requests build the docs
(without deploying) to catch regressions before they merge.

```bash
# Install docs dependencies
Expand All @@ -213,15 +213,20 @@ this template, update `project`, `author`, and the autosummary target in
#### Deploying API documentation

The `Docs` workflow (`.github/workflows/docs.yml`) builds on every push and
pull request, and deploys to GitHub Pages only on `push` to `main` (matching
the JS and Rust template patterns; see
[link-foundation/relative-meta-logic#170](https://github.com/link-foundation/relative-meta-logic/pull/170)
for the bug this guards against).

**One-time setup per repository**: open `Settings → Pages` and set
`Source = GitHub Actions`. Without this, the first deploy run fails on
`actions/deploy-pages` with `Get Pages site failed`. This cannot be configured
from a workflow.
pull request. On `push` to `main`, it deploys to GitHub Pages only when the
repository variable `DEPLOY_GITHUB_PAGES` is set to `true`. This keeps fresh
repositories green while still validating their docs before Pages is configured.

**One-time setup per repository**:

1. Open `Settings -> Pages` and set `Source = GitHub Actions`.
2. Open `Settings -> Secrets and variables -> Actions -> Variables`, then add
repository variable `DEPLOY_GITHUB_PAGES` with value `true`.

Without the variable, the workflow logs a notice and skips deployment without
failing. Without the Pages source setting, an opted-in deploy fails on
`actions/deploy-pages` with `Get Pages site failed`. The Pages source setting
cannot be configured from a workflow.

### Preview regeneration parity

Expand Down
3 changes: 3 additions & 0 deletions changelog.d/20260703_issue_26_docs_pages_opt_in.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Fixed

- GitHub Pages deployment in the docs workflow is now opt-in via the `DEPLOY_GITHUB_PAGES` repository variable, so fresh repositories still validate docs without failing on unconfigured Pages.
29 changes: 29 additions & 0 deletions tests/test_workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,32 @@ def test_docs_workflow_action_versions_are_current() -> None:
assert_action_pin_absent(docs_workflow, "actions/configure-pages", "v5")
assert_action_pin_absent(docs_workflow, "actions/upload-pages-artifact", "v3")
assert_action_pin_absent(docs_workflow, "actions/deploy-pages", "v4")


def test_docs_workflow_deploys_pages_only_when_opted_in() -> None:
"""Fresh repositories should build docs without failing Pages deployment."""
workflow = read_workflow("docs.yml")
build_job = workflow_job_block(workflow, "build")
deploy_job = workflow_job_block(workflow, "deploy")
configure_step = workflow_step_block(build_job, "Configure GitHub Pages")
upload_step = workflow_step_block(build_job, "Upload GitHub Pages artifact")
skip_step = workflow_step_block(build_job, "Report skipped GitHub Pages deployment")

deploy_condition = (
"github.event_name == 'push' && "
"github.ref == 'refs/heads/main' && "
"vars.DEPLOY_GITHUB_PAGES == 'true'"
)
skip_condition = (
"github.event_name == 'push' && "
"github.ref == 'refs/heads/main' && "
"vars.DEPLOY_GITHUB_PAGES != 'true'"
)

assert f"if: {deploy_condition}" in configure_step
assert f"if: {deploy_condition}" in upload_step
assert f"if: {deploy_condition}" in deploy_job
assert f"if: {skip_condition}" in skip_step
assert "::notice::" in skip_step
assert "DEPLOY_GITHUB_PAGES=true" in skip_step
assert "Settings -> Pages" in skip_step
Loading