Reproducible Yocto Builds in GitHub Actions
Cache shared state on a self-hosted runner and rebuild firmware images deterministically.
- Runs out of the box: no
- Tests: yes
- CI: yes
- Docs: yes
- Used in production: no
Purpose#
A workflow and runner setup that builds a Yocto image on every merge and nightly. Layers are pinned by commit in a manifest, the shared-state cache lives on the runner's local disk, and a weekly job rebuilds from an empty cache to prove the image is still reproducible.
The repository documents the runner's disk layout and the cleanup policy that keeps the cache from filling the volume.
What you will learn#
- Pin every layer by commit in a manifest checked into the repository
- Configure a shared-state cache on a self-hosted runner and keep it bounded
- Prove reproducibility by comparing image hashes from warm and empty caches
Technologies & features#
- Technologies
- BashYocto ProjectGitHub ActionsDocker
- Features
- CI PipelineDependency PinningLinux Image Build
- Topics
- DevOps & CI/CDprimaryEmbedded/Linux
Lessons learned#
- Worked
A weekly clean-cache rebuild caught a layer that fetched from a moving branch before it ever affected a release.
- Didn’t work
Sharing one cache across parallel builds on the runner caused lock contention. One build per runner with a fast local disk was faster overall.
Try it#
git clone https://git.example.internal/embedded-platforms/yocto-ci.git
cd yocto-ci
./tools/fetch-layers.sh manifest.xml
source layers/poky/oe-init-build-env build
bitbake core-image-minimalCommands come from the owner’s README. Credentials are never stored here.


