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:
- A New, Empty GitHub Repository: Create a new repository on GitHub. This will be the home for your workflows and your blog's code.
- Cloudflare Account: You’ll need a free Cloudflare account.
- Initial Workflow Files: You must create the
.github/workflows/bootstrap.ymland.github/workflows/deploy.ymlfiles 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
How It Works:
-
on: workflow_dispatch: This makes the workflow manually triggerable from the GitHub "Actions" tab. -
permissions: contents: write: This grants the Action permission to push commits to your repository. Without it, thegit pushcommand will fail. -
npm create astro@latest ...: We use the--yesflag and--templateargument to run the Astro CLI non-interactively, using the excellent, minimal Astro Micro theme. -
git commit ...: The Action acts like a developer, staging the newblog/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:
-
CLOUDFLARE_API_TOKEN: Create a new API token in your Cloudflare dashboard with the "Edit Cloudflare Pages" permission. -
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'
How It Works:
- Two-Stage Process: The workflow is split into
buildanddeployjobs. Thedeployjob only runs if thebuildjob succeeds. - Artifacts: The
buildjob uploads theblog/distdirectory as an "artifact." Thedeployjob downloads it, ensuring the exact same output is deployed. - 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. - 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 tomain, the value ismain, 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:
- Click a button to bootstrap a fresh Astro blog into a new repository.
- Create a branch, make your changes, and open a pull request.
- Your custom
deploy.ymlaction builds the site and deploys a preview, posting the link directly to your PR. - 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)