Skip to content
Latchkey

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.

.github/workflows/ci.yml
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@v4

Caching 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.

Frequently asked questions

CI/CD for Astro with GitHub Actions?
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.
The workflow?
astro check validates frontmatter and TypeScript. The build emits dist/, which is uploaded as a Pages artifact.
Caching 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.

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card