CI/CD for Astro with GitHub Actions
Build and ship your content-first Astro site automatically.
Astro produces a static site by default, which makes its pipeline lean: validate, build, deploy. This recipe uses the official Astro check for type and content validation and publishes the dist/ output to GitHub Pages.
What the pipeline does
- install deps with npm ci
- run astro check for types and content
- build with astro build
- upload the dist output
- deploy to GitHub Pages
The workflow
astro check validates frontmatter and TypeScript. The build emits dist/, which is uploaded as a Pages artifact.
name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npx astro check
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: dist
deploy:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment:
name: github-pages
steps:
- uses: actions/deploy-pages@v4Caching and speed
cache: npm restores installs. Content-heavy Astro sites spend build time fetching and processing Markdown and images; cache node_modules/.astro and any image-optimization output to speed reruns. For sites with hundreds of pages, faster managed runners like Latchkey cut the build minute count.
Deploying
Set the site and base options in astro.config.mjs to match your Pages URL so links and assets resolve. dist/ also deploys cleanly to Netlify, Cloudflare Pages, or S3+CloudFront. If you enable SSR with an adapter, deploy the server output to that adapter target instead.
Making this reliable in CI
- Pin every tool version. An unpinned toolchain turns a runner image update into a build break on unchanged code.
- Cache what is expensive to produce, and key the cache to the tool version so a restore across a version boundary cannot poison the build.
- Assert on the produced artifact rather than on the command succeeding.
- Set an explicit timeout so a hung step fails fast instead of consuming the whole job budget.
Key takeaways
- Run astro check to validate content collections and types.
- Set site and base in astro.config.mjs for Pages.
- Default output is a static dist/ that any host can serve.