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
34 changes: 34 additions & 0 deletions .github/actions/deploy-to-gh-pages/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Deploy to gh-pages
description: Deploy built docs to a subdirectory on gh-pages

inputs:
target:
description: Subdirectory to deploy to
required: true
commit-message:
description: Commit message
required: true

runs:
using: composite
steps:
- shell: bash
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
TARGET="${{ inputs.target }}"
git fetch origin gh-pages 2>/dev/null || true
if git rev-parse --verify origin/gh-pages >/dev/null 2>&1; then
git checkout -B gh-pages origin/gh-pages
else
git checkout --orphan gh-pages
git rm -rf .
git clean -fd
fi
touch .nojekyll
rm -rf "$TARGET"
mkdir -p "$(dirname "$TARGET")"
cp -r /tmp/built-site "$TARGET"
git add .nojekyll "$TARGET"
git diff --cached --quiet || git commit -m "${{ inputs.commit-message }}"
git push origin gh-pages
36 changes: 36 additions & 0 deletions .github/workflows/docs-pr-cleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Documentation (PR Cleanup)

on:
pull_request:
types: [closed]

permissions:
contents: write

concurrency:
group: docs-deploy
cancel-in-progress: false

jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Remove PR preview
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git fetch origin gh-pages 2>/dev/null || true
if ! git rev-parse --verify origin/gh-pages >/dev/null 2>&1; then
echo "gh-pages branch does not exist, nothing to clean up"
exit 0
fi
git checkout -B gh-pages origin/gh-pages
if [ ! -d "pr/${{ github.event.number }}" ]; then
echo "No preview directory found for PR #${{ github.event.number }}"
exit 0
fi
git rm -rf "pr/${{ github.event.number }}"
git commit -m "Remove PR #${{ github.event.number }} preview"
git push origin gh-pages
68 changes: 68 additions & 0 deletions .github/workflows/docs-pr-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Documentation (PR Preview)

on:
pull_request:
types: [opened, synchronize, reopened]

permissions:
contents: write
pull-requests: write

concurrency:
group: docs-deploy
cancel-in-progress: false

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- uses: astral-sh/setup-uv@v7

- name: Build docs
run: |
uv run --group docs python scripts/override_site_url.py "pr/${{ github.event.number }}"
uv run --group docs zensical build --clean --config-file zensical.local.toml
cp -r site /tmp/built-site

- name: Get preview URL
id: preview
run: |
url=$(uv run --group docs python -c "import tomlkit; print(tomlkit.loads(open('zensical.local.toml').read()).get('project', {}).get('site_url', ''))")
echo "url=${url}" >> "$GITHUB_OUTPUT"

- uses: ./.github/actions/deploy-to-gh-pages
with:
target: pr/${{ github.event.number }}
commit-message: Deploy PR #${{ github.event.number }} preview

- name: Post or update PR comment
if: steps.preview.outputs.url != ''
uses: actions/github-script@v7
with:
script: |
const marker = '<!-- docs-preview -->';
const url = '${{ steps.preview.outputs.url }}';
const body = `${marker}\n📖 Docs preview: ${url}`;
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ github.event.number }},
});
const existing = comments.find(c => c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ github.event.number }},
body,
});
}
60 changes: 60 additions & 0 deletions .github/workflows/docs-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Documentation (Release)

on:
push:
tags:
- "v*"

permissions:
contents: write

concurrency:
group: docs-deploy
cancel-in-progress: false

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- uses: astral-sh/setup-uv@v7

- name: Extract version
id: version
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"

- name: Build docs
run: |
uv run --group docs python scripts/override_site_url.py "${{ steps.version.outputs.version }}"
uv run --group docs zensical build --clean --config-file zensical.local.toml
cp -r site /tmp/built-site

- uses: ./.github/actions/deploy-to-gh-pages
with:
target: ${{ steps.version.outputs.version }}
commit-message: Deploy docs for v${{ steps.version.outputs.version }}

- name: Update latest and index.html
run: |
TARGET="${{ steps.version.outputs.version }}"
rm -rf latest
cp -r /tmp/built-site latest
# Generate root index.html
REPO_NAME="${{ github.event.repository.name }}"
{
echo '<!DOCTYPE html>'
echo "<html><head><meta charset=\"utf-8\"><title>${REPO_NAME}</title></head>"
echo "<body><h1>${REPO_NAME} documentation</h1><ul>"
echo '<li><a href="latest/">latest</a></li>'
if [ -d dev ]; then
echo '<li><a href="dev/">dev</a></li>'
fi
for d in $(find . -maxdepth 1 -type d -name '[0-9]*' | sed 's|^\./||' | sort -rV); do
echo "<li><a href=\"$d/\">$d</a></li>"
done
echo '</ul></body></html>'
} > index.html
git add latest index.html
git diff --cached --quiet || git commit -m "Update latest and index.html for v${TARGET}"
git push origin gh-pages
31 changes: 19 additions & 12 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
name: Documentation

on:
push:
branches:
- main

permissions:
contents: read
pages: write
id-token: write
contents: write

concurrency:
group: docs-deploy
cancel-in-progress: false

jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/configure-pages@v5
- uses: actions/checkout@v6

- uses: astral-sh/setup-uv@v7
- run: uv run --group docs zensical build --clean
- uses: actions/upload-pages-artifact@v4

- name: Build docs
run: |
uv run --group docs python scripts/override_site_url.py dev
uv run --group docs zensical build --clean --config-file zensical.local.toml
cp -r site /tmp/built-site

- uses: ./.github/actions/deploy-to-gh-pages
with:
path: site
- uses: actions/deploy-pages@v4
id: deployment
target: dev
commit-message: Deploy dev docs
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ tag_sign = false
check_dirty = false

[dependency-groups]
docs = ["mkdocstrings-python", "zensical"]
docs = ["mkdocstrings-python", "zensical", "tomlkit"]
20 changes: 20 additions & 0 deletions scripts/override_site_url.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'''Override site_url in zensical.toml for subdirectory deployment.'''
import sys
from pathlib import Path
import tomlkit

INPUT_PATH = Path('zensical.toml')
OUTPUT_PATH = Path('zensical.local.toml')


def main():
config = tomlkit.loads(INPUT_PATH.read_text())
url = config.get('project', {}).get('site_url')
if url:
subdir = sys.argv[1]
new_url = url.rstrip('/') + '/' + subdir.strip('/') + '/'
config['project']['site_url'] = new_url
OUTPUT_PATH.write_text(tomlkit.dumps(config))


main()
Loading