This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This repository contains Docker images for GitHub Actions self-hosted runners with additional tools pre-installed. The main image is based on the official GitHub Actions runner image and includes a comprehensive suite of development and operations tools including Python, PowerShell, Node.js, .NET SDK, Azure CLI, AzCopy, Ansible, Kubernetes tools, network utilities, and more.
- Base Image: Built on
ghcr.io/actions/actions-runner:2.327.1 - Additional Tools: Multiple tools installed via a YAML-driven setup system
- Setup System: Uses
setup.yamlto define installation steps withsetup.shorchestrator - Multi-Architecture Support: Supports both AMD64 and ARM64 architectures
- CI/CD: Uses GitHub Actions for automated building and releasing
The setup system reads src/setup.yaml and executes installation steps sequentially. Each step can either:
- Execute a script file from
src/scripts/directory - Run inline commands directly
The orchestrator (setup.sh) provides:
- Colored logging with timestamps
- Step execution tracking
- Error handling with proper exit codes
- Support for both
scriptandcommandstep types
# Build locally
docker build -t github-actions-runner -f src/Dockerfile src/
# Build with specific platform
docker buildx build --platform linux/amd64 -t github-actions-runner -f src/Dockerfile src/
# Build multi-platform image
docker buildx build --platform linux/amd64,linux/arm64 -t github-actions-runner -f src/Dockerfile src/
# Build and load into local Docker (single platform only)
docker buildx build --platform linux/amd64 --load -t github-actions-runner -f src/Dockerfile src/
# Run the built image
docker run --rm -it github-actions-runner bash
# Test specific tools
docker run --rm github-actions-runner python3 --version
docker run --rm github-actions-runner pwsh --version
docker run --rm github-actions-runner az --version
To add a new tool to the image:
-
For complex installations, create a script in
src/scripts/:# src/scripts/install-newtool.sh #!/bin/bash set -euo pipefail # Architecture detection if needed ARCH=$(uname -m) case ${ARCH} in x86_64) ARCH_SUFFIX="amd64" ;; aarch64) ARCH_SUFFIX="arm64" ;; esac # Installation logic here -
Add the step to
src/setup.yaml:- name: "Install New Tool" script: "scripts/install-newtool.sh" description: "Description of what this installs" -
For simple installations, use inline commands:
- name: "Install New Tool" command: "apt-get update && apt-get install -y newtool" description: "Description of what this installs" -
Make the script executable:
chmod +x src/scripts/install-newtool.sh
The repository uses GitVersion for semantic versioning. The pipeline is triggered on:
- Push to any branch
- Pull requests
- Manual workflow dispatch
src/Dockerfile: Main Dockerfile that builds the runner imagesrc/setup.yaml: YAML configuration defining all installation stepssrc/setup.sh: Main orchestrator that reads setup.yaml and executes stepssrc/scripts/: Installation scripts for various toolsinstall-coreutils.sh: Verifies GNU coreutils (pre-installed)install-file-tools.sh: Installs file utilities (file, tree, time)install-archive-tools.sh: Installs compression tools (p7zip, zip)install-python.sh: Installs pip and Python development toolsinstall-powershell.sh: Installs PowerShell Coreinstall-nodejs.sh: Installs Node.js and npminstall-azure-cli.sh: Installs Azure CLIinstall-azcopy.sh: Installs AzCopy with architecture detectioninstall-ansible.sh: Installs Ansible via pipinstall-docker-tools.sh: Installs Docker Compose plugininstall-json-tools.sh: Verifies jq and yq toolsinstall-kubernetes-tools.sh: Installs kubectl, helm, kustomizeinstall-yamllint.sh: Installs yamllintinstall-github-cli.sh: Installs GitHub CLIinstall-dotnet-sdk.sh: Installs .NET SDK (LTS and latest)install-network-tools.sh: Installs comprehensive network utilities
.github/workflows/pipeline.yaml: Main CI/CD pipelineGitVersion.yaml: Semantic versioning configuration
The project uses GitVersion with:
- Main branch: Continuous deployment mode
- Develop branch: Minor version increments
- Release branches: RC pre-releases
- Feature branches: Named pre-releases
- Commit messages control version bumps (+semver:major/minor/patch)
Images are published to:
- Docker Hub:
emberstack/github-actions-runner - GitHub Container Registry:
ghcr.io/emberstack/github-actions-runner
Both registries receive multi-architecture manifests supporting AMD64 and ARM64.
- Modify installation scripts: Edit files in
src/scripts/for tool-specific changes - Update setup configuration: Modify
src/setup.yamlto add/remove/reorder steps - Test locally: Build and run the image to verify changes
- Commit with semantic versioning: Use commit messages like:
feat: add new tool(minor version bump)fix: correct installation issue(patch version bump)feat!: breaking changeor+semver:major(major version bump)
The runner supports ephemeral mode through the GITHUB_RUNNER_EPHEMERAL environment variable:
- When set to
"true", the runner will be configured with the--ephemeralflag - Each runner will process only one job before automatically deregistering
- This provides clean, isolated environments for each workflow run
- Ideal for autoscaling scenarios and enhanced security requirements
- No job state or secrets persist between runs
The pipeline (pipeline.yaml) consists of:
- Discovery: Determines version and whether to build/release
- Build: Parallel builds for each architecture
- Manifest: Creates multi-arch manifests
- Release: Creates GitHub releases (main branch only)
When debugging tool installations:
- Check the colored output from
setup.shfor the specific failing step - Run the Docker build with
--progress=plainfor detailed output - Test scripts individually inside a running container
- Verify architecture-specific logic for ARM64 vs AMD64
The base GitHub Actions runner image already includes many common tools. Before adding new tools, check if they're pre-installed:
- Core utilities: curl, wget, git, tar, unzip, sudo
- Python 3: Python interpreter (but not pip)
- Docker: Docker engine with Docker Buildx
- JSON processing: jq
- SSH tools: ssh, scp, openssh-client
- Build essentials: gcc, make, build-essential
Some scripts only verify pre-installed tools rather than installing them:
install-coreutils.sh: Verifies GNU coreutilsinstall-json-tools.sh: Verifies jq (pre-installed) and yq (installed in Dockerfile)
- Always check if a tool is pre-installed before adding installation logic
- Use verification-only scripts for pre-installed tools
- Group related tools in single installation scripts
- Minimize apt-get update calls by grouping installations
- Clean package caches after installation to reduce image size