A local Raspberry Pi build light for GitHub Actions. One container runs
PowerShell and GitHub CLI (gh) using your personal access
token. No server, database, website or device pairing.
Copy this repository to your Pi, then run from its directory:
sudo bash setup-pi.shThe setup script installs/enables Docker, prompts for your PAT,
workflow settings and optional GPIO pins, builds the container, checks GitHub
access and starts it automatically after reboot. Run it again to change settings
or rotate the PAT. Settings are saved in /etc/build-light/container.env with
root-only permissions. The script must be saved beside the Dockerfile and
PowerShell script, not pasted directly into a terminal.
Supports 32-bit Pi OS on ARMv7 or newer, ARM64 and AMD64. Pi 1 and the original Pi Zero (ARMv6) are not supported.
sudo docker logs -f build-light
sudo docker stop build-light
sudo docker start build-lightCreate a fine-grained GitHub PAT with Actions: Read-only for the repository.
Organization approval/SSO authorization may be required. Prefer a fine-grained
token over a classic PAT, which needs broader repo access for private repositories.
Copy .env.example to .env and edit the placeholders:
cp .env.example .env
chmod 600 .env
docker build -t build-light-local .
docker run --rm --env-file .env build-light-local -Once
docker run -d --name build-light --restart unless-stopped --env-file .env build-light-localConsole output is the default. Keep .env private and never put a real PAT in the
example file. Private environment files are excluded from git and image builds;
trusted container administrators can still inspect container environment variables.
Recreate the container after changing settings.
| Variable | Meaning |
|---|---|
GH_TOKEN |
Required PAT. |
GH_REPO |
Required owner/repository; one repository per container. |
BUILD_LIGHT_WORKFLOWS |
Required comma-separated workflow filenames or IDs, e.g. ci.yml,release.yml; up to 20. |
BUILD_LIGHT_BRANCH |
Required exact branch name, e.g. main. |
BUILD_LIGHT_EVENT |
push (default), pull_request, schedule, workflow_dispatch or release. |
BUILD_LIGHT_POLL_SECONDS |
30-300 seconds between cycles; default 60. |
BUILD_LIGHT_OUTPUT |
console (default) or gpio. |
PI_RED, PI_GREEN, PI_BLUE |
Required in GPIO mode; distinct BCM pins 0-27. Template/setup use the original HAT values: red 1, green 3, blue 5. |
PI_GPIO_CHIP |
GPIO chip number, default 0; inspect your Pi/OS first. |
PI_ACTIVE_HIGH |
true (default, common-cathode) or false (common-anode). |
All selected workflows share the branch/event filter. The newest matching run determines each workflow's state; older failures do not override newer successes. Use another container for a different repository.
| State | Colour |
|---|---|
| Starting | White |
| API/auth/network error, malformed response or disabled workflow | Purple |
| Failed or timed out | Red |
| No matching runs or unknown status | Cyan |
| Waiting, cancelled, skipped, neutral or action required | Yellow |
| Queued, pending or running | Blue |
| All selected workflows successful | Green |
Errors immediately show purple; otherwise priority is red, cyan, yellow, blue,
green. Requests time out after 15 seconds and failures retry next cycle.
Each cycle makes two API calls per workflow; increase the interval or reduce
selections if rate-limited. -Once exits 1 for collection/configuration errors,
otherwise 0, including a failed build. Status is not saved to disk.
Use current-limiting resistors and appropriate drive hardware. BCM 0-27 is a
validation range, not a recommendation to use reserved pins.
The original HAT values above are GPIO/BCM offsets, not physical header pin numbers;
verify your wiring before enabling GPIO.
Inspect /dev/gpiochip*; Pi 5 chip numbers vary by kernel/OS. The setup script adds the
selected device and its group automatically.
For manual GPIO launch, first set output, pins and polarity in .env:
CHIP=0 # Replace with the correct chip for your board/OS.
docker run -d --name build-light --restart unless-stopped \
--env-file .env -e PI_GPIO_CHIP="$CHIP" \
--device "/dev/gpiochip${CHIP}:/dev/gpiochip${CHIP}:rw" \
--group-add "$(stat -c '%g' "/dev/gpiochip${CHIP}")" \
build-light-localNo privileged mode, inbound ports or data volume is needed. PowerShell uses libgpiod v1, keeps GPIO lines claimed while running and sets them off on clean shutdown. After release/crash, hardware determines idle state; use suitable pull resistors. Container build/run and physical GPIO still need checking on your Pi.
Install PowerShell 7.6+ and gh, export the settings above, then run:
pwsh -NoLogo -NoProfile -File .\build-light.ps1 -Once
pwsh -NoLogo -NoProfile -File .\build-light.ps1The script does not load .env automatically. Native GPIO requires Linux with
libgpiod v1 (libgpiod2 on Debian 12); use the container to avoid host API differences.
The Dockerfile pins PowerShell 7.6.7 and verifies official archive
checksums. Version tags (v*) publish the multiarchitecture image to
ghcr.io/codify/build-light:VERSION. Make the package public explicitly for
unauthenticated pulls.