DEV Community

Picoable
Picoable

Posted on • Originally published at devops.picoable.com

Automate Your Astro Blog with GitHub Actions

While Cloudflare's default Git integration is brilliantly simple, as we covered in our first guide, sometimes you need more power. When you want to add unit tests, linting, or other custom checks to your build process, you need to own the pipeline.

This guide shows you how. We'll build a robust, fully-customizable CI/CD workflow using only GitHub Actions to bootstrap and deploy an Astro blog, giving you complete command over your entire process.

Prerequisites: Setting the Stage

Before we dive in, this guide assumes you have a foundational setup. You'll need:

  1. A New, Empty GitHub Repository: Create a new repository on GitHub. This will be the home for your workflows and your blog's code.
  2. Cloudflare Account: You’ll need a free Cloudflare account.
  3. Initial Workflow Files: You must create the .github/workflows/bootstrap.yml and .github/workflows/deploy.yml files locally and commit them to your new repository. GitHub Actions only run after they've been added to your repository.

With that initial setup complete, you're ready to automate.

Part 1: The Bootstrapper - A Blog Generator on Demand

Imagine you want to start a new blog, or your team needs to spin up new projects from a standard template. Instead of manually running npm create and copying files, you can create a "blog generator" right in your repository. This is infrastructure-as-code for your starting point.

We'll build a reusable workflow that, with a single click, populates our repository with a fresh, ready-to-go Astro blog.

Deconstructing the Bootstrap Workflow

Create a file at .github/workflows/bootstrap.yml with the following content.

# .github/workflows/bootstrap.yml

name: Bootstrap Astro Blog
on:
  workflow_dispatch: # Allows us to run this workflow manually from the Actions tab

permissions:
  contents: write # Important: This allows the action to commit files back to the repo

jobs:
  bootstrap:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Create and Bootstrap Astro Project
        run: |
          mkdir blog
          cd blog
          # We're using the minimal, fast Astro Micro theme
          npm create astro@latest . -- --template trevortylerlee/astro-micro --yes

      - name: Remove template's git history
        run: rm -rf blog/.git

      - name: Commit new blog files
        run: |
          git config --global user.name 'GitHub Actions Bot'
          git config --global user.email 'actions-bot@github.com'
          git add blog/
          if git diff --staged --quiet; then
            echo "No changes to commit."
          else
            git commit -m "feat: Bootstrap Astro Micro blog"
            git push
          fi
Enter fullscreen mode Exit fullscreen mode

How It Works:

  1. on: workflow_dispatch: This makes the workflow manually triggerable from the GitHub "Actions" tab.
  2. permissions: contents: write: This grants the Action permission to push commits to your repository. Without it, the git push command will fail.
  3. npm create astro@latest ...: We use the --yes flag and --template argument to run the Astro CLI non-interactively, using the excellent, minimal Astro Micro theme.
  4. git commit ...: The Action acts like a developer, staging the new blog/ directory and pushing it to the repository.

Once you've committed this file, go to your repository's "Actions" tab, select "Bootstrap Astro Blog," and run it. Your repository will be populated with a brand new, ready-to-configure Astro blog.

Part 2: The Continuous Deployment Pipeline

Now that we have a blog, let's build the engine that deploys it. We'll create a separate workflow that takes over the build and deploy process from Cloudflare.

The key to this is Wrangler, and we'll use the cloudflare/wrangler-action to run it.

Securely Storing Your Credentials

First, you need to give GitHub Actions the credentials to act on your behalf. Create these two secrets in your repository's Settings > Secrets and variables > Actions:

  1. CLOUDFLARE_API_TOKEN: Create a new API token in your Cloudflare dashboard with the "Edit Cloudflare Pages" permission.
  2. CLOUDFLARE_ACCOUNT_ID: You can find this on the main overview page of your Cloudflare account.

Deconstructing the Deployment Workflow

Now, create a new file at .github/workflows/deploy.yml. This workflow will build the site and then deploy it using Wrangler.

# .github/workflows/deploy.yml

name: Build and Deploy to Cloudflare Pages

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        working-directory: ./blog
        run: npm ci

      - name: Build
        working-directory: ./blog
        run: npm run build

      - name: Upload artifact
        uses: actions/upload-artifact@v3
        with:
          name: astro-build-output
          path: blog/dist

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download artifact
        uses: actions/download-artifact@v3
        with:
          name: astro-build-output
          path: ./dist

      - name: Deploy to Cloudflare Pages
        uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          # Make the project name dynamic based on the repo name
          projectName: ${{ github.event.repository.name }}
          branch: ${{ github.ref_name }}
          directory: './dist'
Enter fullscreen mode Exit fullscreen mode

How It Works:

  1. Two-Stage Process: The workflow is split into build and deploy jobs. The deploy job only runs if the build job succeeds.
  2. Artifacts: The build job uploads the blog/dist directory as an "artifact." The deploy job downloads it, ensuring the exact same output is deployed.
  3. Dynamic Project Name: We've set projectName: ${{ github.event.repository.name }}. This is a robust way to ensure the deployment targets a Cloudflare Pages project with the same name as your GitHub repository, making the workflow portable and reusable.
  4. Dynamic Branch Deployment: branch: ${{ github.ref_name }} is the magic key. When the workflow runs on a pull request, this value is the feature branch name, telling Cloudflare to create a preview deployment. When it runs on a push to main, the value is main, and Cloudflare deploys to production.

This single, elegant workflow handles both preview and production deployments, all within your control.

Conclusion: You Are the Pipeline

By building these two workflows, you've taken ownership of your entire development lifecycle. Your GitHub repository is now a self-contained factory for both creating and deploying your website.

Your new, empowered workflow looks like this:

  1. Click a button to bootstrap a fresh Astro blog into a new repository.
  2. Create a branch, make your changes, and open a pull request.
  3. Your custom deploy.yml action builds the site and deploys a preview, posting the link directly to your PR.
  4. Once everything looks perfect, you merge to main, and the same action automatically deploys to your production domain.

All logs, all steps, all in one place. You have achieved CI/CD nirvana.

Next Steps: Full Automation

As an exercise, consider how you could take this one step further. Could you use the GitHub CLI or a tool like Terraform to automate the very first step—the creation of the repository itself? The power is all yours.

Top comments (0)