We’ve all been there: you push a tiny CSS tweak, and then you sit… and wait… and watch the GitHub Actions logs spin.
My Hugo site was taking nearly a minute to deploy. Not “slow” by 2010 standards, but for a modern static site? That’s an eternity. I dug into the logs, found the bottlenecks, and trimmed the fat. Here’s how I optimized my CI/CD pipeline.
1. The Problem: The “Wrangler Tax”
Looking at my logs, I saw a massive yellow wall of text. Every single time I deployed, GitHub was:
Installing an ancient version of Wrangler (v2).
Realizing it was outdated.
Delegating to a newer version (v4).
This “version dance” was eating up about 20-30 seconds per build for absolutely no reason. Plus, I was using the deprecated pages-action@v1.
2. The Fix: Modernizing the Stack
I swapped out the old pages-action@v1 for the modern cloudflare/wrangler-action@v3. This is built to use the latest Wrangler engine by default. No more “delegation” and no more warnings.
3. The Pro Move: Preview Deploys
Why wait until you merge to main to see your changes? I updated the script to handle Preview Branches. Now, if I push to a branch called feature-cool-stuff, Cloudflare gives me a private link to check it out first.
The “Final Form” Workflow
Here is the optimized .github/workflows/deploy.yml:
YAML
name: Deploy Hugo
on:
push:
branches:
- main
- '*' # This triggers the build for ANY branch!
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: 'latest'
extended: true
- name: Cache Hugo resources
uses: actions/cache@v4
with:
path: resources
key: ${{ runner.os }}-hugo-resources-${{ hashFiles('content/**', 'assets/**') }}
- name: Build
run: pnpm install && hugo --gc --minify
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}
# DYNAMIC BRANCHING: This detects if it's main or a preview
command: pages deploy ./public --project-name=olimiah --branch=${{ github.ref_name }}
The Results
Clean Logs: No more “Deprecated” warnings.
Speed: We skip the overhead of installing multiple Wrangler versions.
Confidence: With Preview Deploys, I can test risky changes on a separate branch without touching my live site.
Stop using pages-action@v1. Switch to wrangler-action@v3, use the pages deploy command with dynamic branching, and cache your resources.
