Pages from Workflows

Pages Deployments from a Workflow

First the repository's Pages source is set to GitHub Actions 29 (Settings > Pages, or the REST API):

Turning on Pages with a workflow as its sourceShell
gh api -X POST repos/{owner}/{repo}/pages -f build_type=workflow \
  --jq '{html_url, build_type, source}'
Output
{"build_type":"workflow","html_url":"https://binarybehemoth.github.io/booknest/",
"source":{"branch":"main","path":"/"}}

pages.yml runs on pushes to main that touch public/**, db/seed.json or itself, and on workflow_dispatch. It grants pages: write and id-token: write, because actions/deploy-pages proves with an OIDC token (OIDC for Cloud) which run is deploying, and puts runs in a concurrency group with cancel-in-progress: false, so deployments queue instead of dying halfway. The build job assembles _site and uploads it as a special artifact; deploy publishes it:

.github/workflows/pages.yml (the jobs)YAML
jobs:
  build:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v7
      - uses: actions/configure-pages@v6
      - name: Build the site
        run: |
          mkdir -p _site/api
          cp public/* _site/
          node -p "JSON.stringify(require('./db/seed.json').books)" > _site/api/books
      - uses: actions/upload-pages-artifact@v5
  deploy:
    needs: build
    runs-on: ubuntu-24.04
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - id: deployment
        uses: actions/deploy-pages@v5

The github-pages environment, which GitHub 29 creates, records each deployment with its URL. Merging pull request #26 changed public/, so the push started run 36148484049: build took 6 seconds and deploy 8. upload-pages-artifact packs _site into a tar archive kept for one day by default; its path input publishes any other folder, such as a documentation generator's output.