First the repository's Pages source is set to GitHub Actions 29 (Settings > Pages, or the REST API):
gh api -X POST repos/{owner}/{repo}/pages -f build_type=workflow \
--jq '{html_url, build_type, source}'{"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:
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@v5The 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.