Now that we have covered the fundamentals of GitHub Actions, it is time to explore real-world examples! You can use these examples right as they are, modify them to fit your needs, or use them as a starting point for your own workflows.
Each recipe is designed to showcase a specific use case, providing detailed explanations, code snippets, and best practices to help you get started quickly.

Who is Bas Steins?
Bas is a software developer and technology trainer based in the triangle between the Netherlands, Germany, and Belgium. For almost two decades, he has been helping people turn their ideas into software and helping other developers write better code. This series is based on his mini-guide "Automate Your Code with GitHub Actions".
Pre-Build DevContainers
Devcontainers are a great way to ensure that your development environment is consistent across all developers. This is especially useful when you have a large team or when you have a complex development environment.
In essence, a devcontainer is a container that contains all the tools and dependencies required to build and run your project. This includes the programming language, libraries, tools, and extensions that you need to develop your project.
The definition of a devcontainer lives in a directory called .devcontainer in the root of your project. This directory contains a devcontainer.json file that specifies the configuration of the devcontainer.
However, building complex devcontainers can be time-consuming and error-prone. To simplify this process, you can pre-build devcontainers for your team in a GitHub Action.
For each commit to the main branch, we're going to update the pre-built devcontainer image. This way, your team can pull the latest devcontainer image and start developing without having to build the devcontainer themselves.
What you'll learn
- Using a GitHub Action on the
pushevent - Setting up QEMU to enable cross-platform builds
- Building a Docker image in a GitHub Action using the
devcontainers/ciaction - Pushing the Docker image to GitHub Container Registry
Here is the workflow that we're going to create:
name: Pre-build Devcontainer
on:
workflow_dispatch:
push:
branches:
- main
jobs:
build_devcontainer:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
version: v0.16.1
platforms: linux/amd64,linux/arm64
install: true
use: true
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Pre-build dev container image
uses: devcontainers/ci@v0.3
with:
imageName: ghcr.io/bascodes/prebuild-devcontainer-gha
# cacheTo: type=inline # This is the default value.
runCmd: sleep 1
push: always
platform: linux/amd64,linux/arm64
In order for this to work, we need a dev container configuration file in .devcontainer/devcontainer.json.
This file looks like this:
{
"name": "devcontainers-ci",
"build": {
"dockerfile": "./Dockerfile",
"context": ".",
"cacheFrom": "type=registry,ref=ghcr.io/bascodes/prebuild-devcontainer-gha:latest"
},
"remoteUser": "root",
"features": {
"ghcr.io/devcontainers/features/github-cli:1": "latest"
}
}
☝️ When setting up your repository with a devcontainer.json file and a GitHub Actions workflow, please remove the cacheFrom argument from the devcontainer.json file at first. On the first run, there is no image to cache from. Once your workflow ran once successfully, you can add the cacheFrom argument to the devcontainer.json file.
Seeing it in action
Once you open your project in VSCode, you will be prompted to open the project in a dev container. The dev container will be pulled from the GitHub Container Registry and set up in your local environment.
You can verify that the build process actually used the cache by checking the logs of the GitHub Actions workflow. All the layers should be marked with CACHED.
Series: "Automate Your Code with GitHub Actions"
This is part 5 of our series titled "Automate Your Code with GitHub Actions", based on the mini-guide by Bas Steins. Be sure to check out the rest of the series:
- Fundamentals of GitHub Actions
- Events and Triggers in GitHub Actions
- Jobs, Actions, and the Marketplace
- Creating Custom GitHub Actions
- Examples: DevContainers, GitHub Pages, and Cloudflare Workers ← you are here!
- Examples: Data Automation, Linting, and Package Publishing (soon!)
- Repository Splitting and Quick Reference (soon!)
Sign up for our newsletter to get notified about the next episode!
Publishing a Static Website to GitHub Pages
GitHub Pages is a static site hosting service that allows you to publish websites directly from a GitHub repository. You can use GitHub Pages to host project documentation, personal blogs, or any other static content that you want to share with the world.
In this recipe, we will create a GitHub Actions workflow that automatically builds and deploys a static website to GitHub Pages whenever changes are pushed to the main branch. This workflow will use a Node.js-based static site generator called Hugo to build the website and deploy it to GitHub Pages.
What you'll learn
- Using a GitHub Action on the
pushevent - Setting up Hugo to build a static website
- Deploying the website to GitHub Pages
- Using the
CNAMEfile to configure a custom domain
Setting Up the Repository With Hugo
Before we create the GitHub Actions workflow, we need to set up our repository with a static website project using Hugo. If you already have a Hugo project, you can skip this step.
- Create a new Hugo site by running the following command in your terminal:
hugo new site my-hugo-site
- Change into the newly created directory:
cd my-hugo-site
-
Add a theme to your Hugo site. You can choose from a variety of themes available on the Hugo Themes website.
-
Create a new content page by running:
hugo new posts/my-first-post.md
-
Edit the content of the
my-first-post.mdfile to add some sample content. -
Start the Hugo server to preview your site:
hugo server -D
- Open your browser and navigate to
http://localhost:1313to view your Hugo site.
Fine. Now it runs on localhost. How do we deploy it to GitHub Pages?
Creating the GitHub Actions Workflow
To deploy our Hugo site to GitHub Pages automatically, we will create a GitHub Actions workflow that builds the site and deploys it to the gh-pages branch. This workflow will run whenever changes are pushed to the main branch.
- Create a new directory named
.github/workflowsin the root of your repository. - Inside the
.github/workflowsdirectory, create a new YAML file nameddeploy.yml. - Add the following workflow configuration to the
deploy.ymlfile:
name: Deploy to GitHub Pages
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: 'latest'
- name: Build site
run: hugo --minify
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
personal_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
publish_branch: gh-pages
cname: mydomain.com
- Replace
mydomain.comwith your custom domain if you have one. If you don't have a custom domain, you can remove thecnamefield from the workflow configuration. - Commit the changes to your repository.
Configuring GitHub Pages
To enable GitHub Pages for your repository and configure it to use the gh-pages branch, follow these steps:
- Go to your repository on GitHub.
- Click on the Settings tab.
- Scroll down to the GitHub Pages section.
- In the Source drop-down menu, select the
gh-pagesbranch. - Click Save.
- GitHub Pages will now be enabled for your repository, and your Hugo site will be published at
https://<username>.github.io/<repository>. - If you have a custom domain, you can add a
CNAMEfile to your repository with your domain name.
That's it! Your Hugo site is now automatically built and deployed to GitHub Pages whenever changes are pushed to the main branch.
Setting up a Custom Domain
If you have a custom domain that you want to use with your GitHub Pages site, follow these steps to configure it:
- Create a new file named
CNAMEin the root of your repository. - Add your custom domain to the
CNAMEfile:
mydomain.com
- Commit the changes to your repository.
- Update the
cnamefield in the GitHub Actions workflow configuration to match your custom domain. - Go to your domain registrar and configure the DNS settings to point to
username.github.io.
After configuring your custom domain, your Hugo site will be accessible at https://mydomain.com.
Using Wrangler to Deploy to Cloudflare Workers
Cloudflare Workers is a serverless platform that allows you to deploy code to Cloudflare's edge network. This enables you to run code closer to your users, reducing latency and improving performance.
In this example, we will use GitHub Actions to deploy a Cloudflare Worker using the wrangler CLI. We will set up a workflow that automatically deploys the worker on every push to the main branch.
What you'll learn
- Using a GitHub Action on the
pushevent - Setting up
wranglerto deploy a Cloudflare Worker - Using secrets to store sensitive information
- Deploying a Cloudflare Worker on every push
Setting up a Hono App
Before we create the GitHub Actions workflow, we need to set up a Cloudflare Workers project using wrangler. If you already have a project set up, you can skip this step.
- Install the
wranglerCLI by running the following command in your terminal:
npm install -g @cloudflare/wrangler
- Create a new Cloudflare Workers project by running:
wrangler generate my-worker
- Change into the newly created directory:
cd my-worker
-
Edit the
wrangler.tomlfile to configure your project settings. You will need to set theaccount_idandzone_idfields. -
Write your Cloudflare Worker code in the
srcdirectory. You can create a new JavaScript file or modify the existingindex.jsfile. -
Test your Cloudflare Worker locally by running:
wrangler dev
- Open your browser and navigate to
http://localhost:8787to test your worker.
Great! Now you have a Cloudflare Workers project set up.
Creating the GitHub Actions Workflow
To automate the deployment of your Cloudflare Worker using GitHub Actions, we will create a workflow that runs the wrangler publish command on every push to the main branch.
- Create a new directory named
.github/workflowsin the root of your repository. - Inside the
.github/workflowsdirectory, create a new YAML file nameddeploy.yml. - Add the following workflow configuration to the
deploy.ymlfile:
name: Deploy Cloudflare Worker
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install wrangler
run: npm install -g @cloudflare/wrangler
- name: Build and deploy worker
run: wrangler publish
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
- Save the
deploy.ymlfile. - Set up your Cloudflare API token as a secret in your repository. Go to your repository on GitHub, navigate to Settings > Secrets, and add a new secret named
CF_API_TOKENwith your Cloudflare API token as the value. - Commit and push the changes to your repository.
In the next article, we'll continue with more real-world recipes — including data automation with issue templates, web scraping on a schedule, and publishing Python packages. See you there!