diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index b0eac80..90cac66 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,8 +1,9 @@ -name: Deploy to GitHub Pages +name: Docs on: push: branches: [main] + tags: ["v*"] pull_request: branches: [main] workflow_dispatch: @@ -10,13 +11,9 @@ on: # Deny by default; each job grants only what it needs. permissions: {} -concurrency: - group: "pages" - cancel-in-progress: true - jobs: build: - name: Build docs + name: Build docs (strict) runs-on: ubuntu-latest permissions: contents: read # checkout the repo @@ -30,7 +27,9 @@ jobs: - name: Install a specific version of uv uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: - enable-cache: true + # Caching is disabled: this workflow can publish (tag trigger), and a + # cache poisoned by a lower-privilege run could taint the built docs. + enable-cache: false version: "0.5.x" - name: Install dependencies @@ -39,27 +38,66 @@ jobs: - name: Build docs run: uv run -- mkdocs build --strict - - name: Upload artifact - id: deployment - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 - with: - path: ./site - retention-days: 1 - deploy: - name: Deploy to GitHub Pages - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest + name: Deploy versioned docs (mike) needs: build + # Publish for branch/tag pushes and manual runs, never for pull requests. + if: github.event_name != 'pull_request' + runs-on: ubuntu-latest permissions: - pages: write # publish the Pages deployment - id-token: write # OIDC token for actions/deploy-pages + contents: write # mike commits the built site to the gh-pages branch + # Never cancel an in-flight deploy: mike pushes to gh-pages, and a + # half-finished push would leave the branch inconsistent. + concurrency: + group: mike-deploy + cancel-in-progress: false steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 - timeout-minutes: 10 + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + # Full history is needed so mike can fetch and update gh-pages. + fetch-depth: 0 + # Don't persist the token to .git/config. The repo is public, so mike + # fetches gh-pages anonymously; only the push needs auth, supplied + # transiently via gh below — so the token never touches disk. + persist-credentials: false + + - name: Install a specific version of uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + with: + # Caching is disabled: this workflow can publish (tag trigger), and a + # cache poisoned by a lower-privilege run could taint the built docs. + enable-cache: false + version: "0.5.x" + + - name: Install dependencies + run: uv sync + + - name: Configure git for mike + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + # Use gh as git's credential helper: it reads the token from GH_TOKEN + # at push time, so only the helper command (no token) is written to + # git config and nothing sensitive appears in the logs. + gh auth setup-git + + # Push to main rolls the `latest` version — the default readers land on. + - name: Deploy latest (main) + if: github.ref == 'refs/heads/main' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: uv run -- mike deploy --push latest + + # A vX.Y.Z tag publishes an immutable major.minor snapshot. `latest` is + # left untouched, so released versions stay browsable alongside it. + - name: Deploy release snapshot (tag) + if: startsWith(github.ref, 'refs/tags/v') + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + VERSION="${GITHUB_REF_NAME#v}" # v1.0.0 -> 1.0.0 + VERSION="${VERSION%.*}" # 1.0.0 -> 1.0 + uv run -- mike deploy --push "$VERSION" diff --git a/mkdocs.yml b/mkdocs.yml index 89c6839..dbeeb42 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -7,6 +7,16 @@ docs_dir: docs site_url: "https://developmentseed.org/datacube-guide/" use_directory_urls: false +# Keep non-published files out of the built site/, and therefore out of the +# gh-pages branch mike deploys. mkdocs copies every non-page file in docs_dir +# into site/ verbatim, so the Graphviz .dot sources (kept in the repo as the +# source for the rendered .svg diagrams) and macOS Finder .DS_Store files would +# otherwise be published. The repo .gitignore can't cover this: it governs the +# source repo, but mike commits the built site/ to gh-pages bypassing it. +exclude_docs: | + .DS_Store + *.dot + extra: version: alias: true