Building the Astro site in GitHub Actions

Why Astro fits a static engineering blog, what the repository must contain for CI to work, and why the workflow installs dependencies with npm ci.

Why Astro?

Astro is particularly suitable for a documentation or engineering blog because the majority of the content can be generated as static HTML.

The source project might contain:

src/
├── components/
├── layouts/
├── pages/
└── content/

After running:

npm run build

Astro generates a production-ready static website:

dist/
├── index.html
├── about/
│   └── index.html
├── projects/
│   └── index.html
├── blog/
│   └── ...
└── assets/
    └── ...

This means I don’t need a continuously running application server just to serve the blog.

The generated files can be stored in object storage and distributed through a CDN.

The repository

The project is stored in GitHub.

A typical structure looks like:

Local development, the lockfile and the CI install Local development npm install package-lock.json Git commit GitHub Actions npm ci
npm ci installs exactly what the lockfile pins, so a green local build and a green CI run agree.

The important part for CI/CD is that the repository contains:

Local development, the lockfile and the CI install Local development npm install package-lock.json Git commit GitHub Actions npm ci
npm ci installs exactly what the lockfile pins, so a green local build and a green CI run agree.

The lock file is especially important because GitHub Actions will use:

npm ci

to install dependencies.

npm install vs npm ci

For local development, I can use:

npm install

This can create or update:

The lock file should then be committed:

For CI, I use:

npm ci

instead.