External Documentation Deployment Guide
This guide explains how to set up automatic documentation deployment from your project to zircote.github.io.
Overview
The external docs deployment system allows projects to automatically publish their generated documentation (rustdoc, typedoc, sphinx, etc.) and ADR viewers to the website without manual intervention or PR review.
Architecture:
Source Project zircote.github.io
| |
| 1. Build docs (cargo doc, etc.) |
| |
| 2. Upload as artifact |
| |
| 3. Dispatch deploy-docs event --->|
| |
| 4. Validate project in registry
| 5. Download artifact
| 6. Deploy to projects/{id}/docs/
| 7. Trigger Jekyll rebuild
| |
|<-- 8. Docs available at URL |
Prerequisites
Before setting up deployment, ensure:
- Your project is registered in
_data/external_docs.yml - You have a Personal Access Token (PAT) with
reposcope - The PAT is stored as
DOCS_DEPLOY_TOKENin your repository secrets
Setup Steps
1. Register Your Project
Add your project to _data/external_docs.yml in zircote.github.io:
your-project:
name: "Your Project"
description: "Brief description"
repository: "zircote/your-project"
doc_type: "rustdoc" # or typedoc, sphinx, custom
supports_adrs: true
enabled: true
2. Create a Deploy Token
- Go to https://github.com/settings/tokens
- Generate new token (classic)
- Select
reposcope (full control of private repositories) - Copy the token
3. Add Secret to Your Repository
- Go to your repository Settings > Secrets and variables > Actions
- Create new secret:
DOCS_DEPLOY_TOKEN - Paste the PAT value
4. Add Deployment Workflow
Create .github/workflows/deploy-docs.yml in your repository using one of the templates below.
Workflow Templates
Rust Project (cargo doc)
name: Deploy Documentation
on:
push:
branches: [main]
paths:
- "src/**"
- "Cargo.toml"
- ".github/workflows/deploy-docs.yml"
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: "Documentation version label"
required: false
default: "latest"
permissions:
contents: read
actions: write
jobs:
build-and-deploy:
name: Build and Deploy Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Build documentation
run: |
cargo doc --no-deps --all-features
# Create redirect to main crate docs
echo '<meta http-equiv="refresh" content="0; url=YOUR_CRATE_NAME/index.html">' > target/doc/index.html
- name: Determine version
id: version
run: |
if [ "$" == "release" ]; then
echo "version=$" >> "$GITHUB_OUTPUT"
elif [ "$" == "workflow_dispatch" ]; then
echo "version=$" >> "$GITHUB_OUTPUT"
else
echo "version=latest" >> "$GITHUB_OUTPUT"
fi
- name: Deploy documentation
uses: zircote/zircote.github.io/.github/actions/docs-deploy@main
with:
project-id: YOUR_PROJECT_ID
docs-path: target/doc
version: $
env:
DOCS_DEPLOY_TOKEN: $
TypeScript Project (TypeDoc)
name: Deploy Documentation
on:
push:
branches: [main]
paths:
- "src/**"
- "package.json"
- ".github/workflows/deploy-docs.yml"
release:
types: [published]
workflow_dispatch:
permissions:
contents: read
actions: write
jobs:
build-and-deploy:
name: Build and Deploy Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Build documentation
run: npx typedoc src/index.ts --out docs
- name: Determine version
id: version
run: |
if [ "$" == "release" ]; then
echo "version=$" >> "$GITHUB_OUTPUT"
else
echo "version=latest" >> "$GITHUB_OUTPUT"
fi
- name: Deploy documentation
uses: zircote/zircote.github.io/.github/actions/docs-deploy@main
with:
project-id: YOUR_PROJECT_ID
docs-path: docs
version: $
env:
DOCS_DEPLOY_TOKEN: $
Python Project (Sphinx)
name: Deploy Documentation
on:
push:
branches: [main]
paths:
- "src/**"
- "docs/**"
- "pyproject.toml"
- ".github/workflows/deploy-docs.yml"
release:
types: [published]
workflow_dispatch:
permissions:
contents: read
actions: write
jobs:
build-and-deploy:
name: Build and Deploy Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: |
pip install -e ".[docs]"
# Or: pip install sphinx sphinx-rtd-theme
- name: Build documentation
run: sphinx-build -b html docs/source docs/_build/html
- name: Determine version
id: version
run: |
if [ "$" == "release" ]; then
echo "version=$" >> "$GITHUB_OUTPUT"
else
echo "version=latest" >> "$GITHUB_OUTPUT"
fi
- name: Deploy documentation
uses: zircote/zircote.github.io/.github/actions/docs-deploy@main
with:
project-id: YOUR_PROJECT_ID
docs-path: docs/_build/html
version: $
env:
DOCS_DEPLOY_TOKEN: $
With ADR Viewer (using adrscope)
name: Deploy Documentation
on:
push:
branches: [main]
paths:
- "src/**"
- "docs/decisions/**"
- "Cargo.toml"
release:
types: [published]
workflow_dispatch:
permissions:
contents: read
actions: write
jobs:
build-and-deploy:
name: Build and Deploy Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Build documentation
run: |
cargo doc --no-deps --all-features
echo '<meta http-equiv="refresh" content="0; url=YOUR_CRATE_NAME/index.html">' > target/doc/index.html
- name: Generate ADR viewer
uses: zircote/adrscope/.github/actions/adrscope@v0
with:
command: generate
input-dir: docs/decisions
output: adr-viewer.html
theme: system
- name: Determine version
id: version
run: |
if [ "$" == "release" ]; then
echo "version=$" >> "$GITHUB_OUTPUT"
else
echo "version=latest" >> "$GITHUB_OUTPUT"
fi
- name: Deploy documentation
uses: zircote/zircote.github.io/.github/actions/docs-deploy@main
with:
project-id: YOUR_PROJECT_ID
docs-path: target/doc
version: $
include-adrs: adr-viewer.html
env:
DOCS_DEPLOY_TOKEN: $
Action Reference
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
project-id |
Yes | - | Project identifier (must match registry) |
docs-path |
Yes | - | Path to generated documentation directory |
version |
Yes | - | Documentation version label |
include-adrs |
No | "" |
Path to ADR viewer HTML file |
target-repo |
No | zircote/zircote.github.io |
Target repository |
dry-run |
No | false |
Validate without deploying |
Outputs
| Output | Description |
|---|---|
deployed-url |
URL of the deployed documentation |
artifact-name |
Name of the uploaded artifact |
Environment Variables
| Variable | Required | Description |
|---|---|---|
DOCS_DEPLOY_TOKEN |
Yes | PAT with repo scope |
URL Structure
After deployment, documentation is available at:
- API Docs:
https://www.zircote.com/projects/{project-id}/docs/ - ADR Viewer:
https://www.zircote.com/projects/{project-id}/adrs.html
Troubleshooting
“Project not found in registry”
Your project is not registered in _data/external_docs.yml. Submit a PR to add it or contact the repository owner.
“Source repository mismatch”
The workflow is running from a repository that does not match the registered repository for this project ID. Check that the repository field in the registry matches your repository.
“Failed to dispatch deployment”
Common causes:
- Invalid or expired
DOCS_DEPLOY_TOKEN - Token does not have
reposcope - Network issues
“No index.html found”
Your documentation output must include an index.html file at the root. For Rust projects, you may need to create a redirect file:
echo '<meta http-equiv="refresh" content="0; url=crate_name/index.html">' > target/doc/index.html
Rollback
If a deployment causes issues, you can rollback to a previous version:
# List available backups
git tag --list 'backup/docs-PROJECT_ID-*'
# Restore from specific backup
git checkout backup/docs-PROJECT_ID-TIMESTAMP -- projects/PROJECT_ID/docs/
# Commit the restoration
git commit -m "revert(PROJECT_ID): rollback docs to previous version"
git push origin main
Security
- The
DOCS_DEPLOY_TOKENshould have minimal scope (justrepoaccess to zircote.github.io) - Projects must be explicitly registered in the registry
- Artifacts are scanned for forbidden file types before deployment
- Each deployment creates a backup tag for rollback capability
Adding a New Project
To add a new project to the deployment system:
- Add entry to
_data/external_docs.yml - Add entry to
keep_filesin_config.yml - Create PAT and add as secret in source repository
- Add deployment workflow to source repository
- Test with
dry-run: truefirst