diff --git a/.github/actions/deploy-to-gh-pages/action.yml b/.github/actions/deploy-to-gh-pages/action.yml new file mode 100644 index 0000000..b59bc99 --- /dev/null +++ b/.github/actions/deploy-to-gh-pages/action.yml @@ -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 diff --git a/.github/workflows/docs-pr-cleanup.yml b/.github/workflows/docs-pr-cleanup.yml new file mode 100644 index 0000000..1dc43c7 --- /dev/null +++ b/.github/workflows/docs-pr-cleanup.yml @@ -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 diff --git a/.github/workflows/docs-pr-preview.yml b/.github/workflows/docs-pr-preview.yml new file mode 100644 index 0000000..3afb6fd --- /dev/null +++ b/.github/workflows/docs-pr-preview.yml @@ -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 = ''; + 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, + }); + } diff --git a/.github/workflows/docs-release.yml b/.github/workflows/docs-release.yml new file mode 100644 index 0000000..37ff5f9 --- /dev/null +++ b/.github/workflows/docs-release.yml @@ -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 '' + echo "