GitHub Actions Guides
Practical guides to build speed, cost, caching, queue times, and debugging on GitHub Actions.
- Alerting on GitHub Actions Build Time RegressionsGitHub Actions has no build time regression alert. Baseline duration P90 for a week in the WarpBuild Jobs report, then run a scheduled check on the drift.
- Moving GitHub Actions Builds to Native ARM64Build ARM64 artifacts natively in GitHub Actions by removing the QEMU emulation step and sending the job to a WarpBuild native ARM64 runner label.
- An ARM64 Migration ChecklistMigrate GitHub Actions jobs to ARM64 with a four category checklist: downloaded binaries, native modules, container base images, and hardcoded runner paths.
- Node Native Modules on ARM64 RunnersA .node addon compiled for x64 fails on ARM64 with invalid ELF header. Install on the aarch64 machine, key caches on runner.arch, rebuild what has no prebuild.
- Building ARM64 Python WheelsBuilding aarch64 wheels on an x64 GitHub Actions runner puts every compile under QEMU. Move the aarch64 leg of the cibuildwheel matrix to a native runner.
- Automating Base Image Updates on GitHub ActionsA scheduled job resolves the new base image digest, opens a pull request, and lets your checks prove the update before the rebuild hits a feature branch.
- Bazel Disk Cache on GitHub Actions RunnersBazel's --disk_cache is deleted with the GitHub Actions runner. Carry it forward with a keyed cache action and a size cap, or boot from a snapshot runner.
- Bazel Remote Execution from GitHub ActionsPoint Bazel at a remote execution endpoint from GitHub Actions, keep loading and analysis on the runner, and size the runner for the work that remains.
- Publishing Build Artifacts from GitHub ActionsUpload build output once with actions/upload-artifact, consume it by name in later jobs, and set retention-days to the cadence you actually roll back to.
- Sharing a Build Cache Across RepositoriesA GitHub Actions cache entry is addressed inside one repository, so reuse across repositories runs through a registry. Patterns, permissions, and rates.
- Build Once, Deploy Many with GitHub ActionsOne build job publishes the image and emits its digest, and the test and deploy jobs pull that digest. The YAML, the wiring table, and the cost math.
- Choosing a Buildx Cache Backend on GitHub ActionsInline cache, registry cache, and a remote builder profile fail in different ways on GitHub Actions. How to pick a buildx cache backend, with rates.
- Cloud Quotas for BYOC GitHub Actions RunnersOn BYOC, cloud quotas cap concurrent GitHub Actions jobs. Size EC2, EBS, elastic IP, and NAT quotas in your stack region against your job concurrency.
- Using ccache for C and C++ Builds on GitHub Actionsccache returns nothing on GitHub Actions until CCACHE_DIR survives the job. Wire the compiler launcher, cap the size, restore and save it, price the result.
- Working Out CI Cost per Pull RequestCost per pull request is jobs triggered times billed minutes times the rate for each runner label, times attempts. Build it from billing rows, then cut it.
- Setting Build Time Budgets for GitHub ActionsA build time budget is a p50 and p95 target per workflow class. Set the targets from measured percentiles, enforce a ceiling with timeouts, price the fix.
- Running Concurrent Docker Builds Against One CacheSeveral GitHub Actions jobs can build on one WarpBuild builder profile at once. What the shared layer cache does under load, how to size it, what it bills.
- Cutting Container Image Size in GitHub ActionsMost of a container image is base layers and build tooling. Move the toolchain into a stage that never ships, land on a slim runtime base, and pull less.
- Running Jobs Inside a ContainerThe container key runs every step inside your image, so paths, permissions, and tooling change. Here is the setup that keeps caches and services working.
- Cross Compiling or Native ARM64 BuildsCross compile ARM64 artifacts on an x64 runner when the build links no native code and tests can stay on x64. Build natively when cgo or ARM64 tests run.
- Triggering Workflows Across RepositoriesTwo ways to trigger a workflow in another repository: a repository dispatch event or a workflow dispatch API call. Token permissions, refs, and cost.
- Custom Runner Images for GitHub ActionsBake your toolchain into a cloud VM image, register it on a WarpBuild BYOC stack, and route GitHub Actions jobs to it with a warp-custom- runner label.
- How to Debug Failed GitHub Actions JobsDebug a failed GitHub Actions job by classifying the failure, reading per-instance runner metrics, then opening an SSH session on the runner itself.
- Dependency Update Jobs on GitHub ActionsDependabot and Renovate pull requests trigger the same workflows a human one does. Scope the update check, group the updates, and price the weekly batch.
- Deployment Jobs on GitHub ActionsA deploy job needs one environment, a fixed concurrency group with cancel-in-progress off, an OIDC credential exchange, and an artifact pinned by digest.
- Passing Secrets into Docker Builds SafelyA --build-arg token lands in the image history. Mount it with RUN --mount=type=secret in GitHub Actions instead, then prove it is absent from every layer.
- Configuring Remote Docker Builder ProfilesA builder profile pins a name, vCPU size, architecture, and disk to one Docker builder VM. Field settings, the API calls that manage it, and session costs.
- Why Your Docker Layer Cache Misses Every RunA Docker layer cache misses every run when an early layer changes: a whole-context COPY, a build arg consumed too early, lockfile churn, or a reset builder.
- Docker Layer Caching on GitHub ActionsDocker layer caches miss on GitHub Actions because every job builds on a fresh buildx instance. Move the cache onto a builder that outlives the job.
- Dockerfile Changes That Cut Build TimeMost Dockerfile build time on GitHub Actions is rebuilt work. Order instructions by change frequency, add BuildKit cache mounts, keep the cache on a builder.
- Parallel .NET Test Runs on Windows Runnersdotnet test runs assemblies one at a time by default and leaves in-assembly parallelism to the framework. Turn on both levels, then size the Windows label.
- What Pulling Images from ECR Costs Your PipelinePulls from ECR bill your AWS account rather than the GitHub invoice. Where registry charges land in a deploy pipeline, plus a worked monthly model.
- Speeding Up Git Checkout in GitHub ActionsGit checkout is slow in GitHub Actions when every job clones the whole repository from GitHub. WarpBuilds/checkout@v7 seeds the tree from a cached mirror.
- Speeding Up Windows Builds on GitHub ActionsWindows GitHub Actions jobs stall on file-heavy checkouts, Defender scans, and NuGet restores. Diagnose each cause, then size the WarpBuild runner.
- Finding the Slow Step in a GitHub Actions WorkflowFind the slow step in a GitHub Actions workflow by splitting queue wait from execution, ranking step timestamps from the job log, then reading runner metrics.
- Finding and Fixing Flaky GitHub Actions JobsA flaky GitHub Actions job passes and fails on one commit. Rank jobs by success rate, read CPU and memory percentiles, then confirm on the runner.
- Speeding Up Git LFS Checkouts in GitHub ActionsGit LFS is slow in GitHub Actions because lfs true pulls every object the ref points at. Fetch only the paths the job reads and price the difference.
- Tracking Build Duration Percentiles on GitHub ActionsGitHub Actions gives you one duration per run and no percentiles. The WarpBuild Jobs report shows duration P75 and P90 per repository, workflow, and job.
- The GitHub Actions Cache Size Limit, ExplainedGitHub Actions caps all caches in a repository at 10 GB by default and evicts least recently used entries first. How the ceiling works, how to remove it.
- Removing Cold Starts from GitHub Actions JobsA GitHub Actions cold start is the setup time before your first real step runs. Split it into five parts, then cut it with standby disks and snapshots.
- GitHub Actions Concurrency Limits, ExplainedGitHub Actions concurrency limits come from the workflow concurrency key, plan-level job ceilings, and runner pool capacity. Match the symptom to the limit.
- Attributing GitHub Actions Cost per Repository and TeamGitHub Actions bills minutes as account level SKU totals. Attribute cost per repository and team with per job billing rows, runner labels and BYOC tags.
- GitHub Actions Egress Costs, ExplainedEgress charges from GitHub Actions land on your cloud bill instead of GitHub's invoice. Where they come from, how to cut them, and a worked AWS model.
- Running Managed Runners on Open Source ProjectsManaged runners reach public repositories once the Default runner group allows them. Enablement steps, fork pull request controls, and per-minute costs.
- What GitHub Actions Larger Runners CostGitHub Actions larger runners bill $0.012 to $0.252 per minute on Linux x64. See the full rate ladder, break-even math, and WarpBuild rates per size.
- What macOS Runners Cost on GitHub ActionsGitHub-hosted macOS runners list at $0.062 to $0.102 per minute. WarpBuild macOS runners are $0.08 per minute for 6 vCPU and $0.16 for 12 vCPU.
- Building a GitHub Actions Matrix That ScalesA GitHub Actions build matrix turns one job into one job per combination. Size the fan-out to runner capacity, shard the suite, and price every cell.
- When a Matrix Grows Too WideA GitHub Actions matrix multiplies every dimension into jobs. Price the width, prune the pull request grid with exclude and a computed matrix, run it nightly.
- Querying GitHub Actions Data with an MCP ServerWarpBuild runs an MCP server at https://mcp.warpbuild.com/mcp so an agent can query your GitHub Actions runner fleet, create runners, and build images.
- Pulling GitHub Actions Metrics Through the APIPull GitHub Actions metrics from the WarpBuild API: CI billing, jobs, queue timings and daywise costs, with a wkey- key on the ci scope and CSV export.
- Setting a Minutes Budget for GitHub ActionsA GitHub Actions minutes budget is jobs per month times billed minutes per job times the rate per label, bounded by labels, timeouts, concurrency, and paths.
- Network Timeouts in GitHub Actions JobsA GitHub Actions job that times out downloading dependencies is hitting a registry rate limit, a DNS failure, or a slow mirror. Read the log signature first.
- When a GitHub Actions Job Runs Out of MemoryExit code 137 means the kernel out-of-memory killer stopped the job. Read the log signature, cap workers and heaps, then price the runner memory ladder.
- GitHub Actions Queue Times and How to Fix ThemGitHub Actions queue time is the wait between a job being queued and a runner claiming it. Trace it to concurrency caps, labels, or pool capacity.
- Hitting API Rate Limits Inside WorkflowsGitHub API rate limits inside GitHub Actions: which token owns the hourly budget, how to read the x-ratelimit headers, back off safely, and cut calls.
- Using Runner Groups with GitHub ActionsA runner group decides which repositories and workflows may use a set of runners. Jobs that never start are usually blocked by group access, rarely by capacity.
- Runner Level Metrics for GitHub Actions JobsGitHub Actions reports job duration and nothing about the machine. Read per instance CPU, memory, disk and queue metrics in WarpBuild, then right size.
- No Space Left on Device in GitHub ActionsA no space left on device failure means the runner volume filled mid-job. Print usage at three points to name the consumer, then apply one of three fixes.
- Running GitHub Actions Runners in Your Own VPCRun GitHub Actions runners in your own VPC as ephemeral EC2 instances. The network shape AWS needs, the outbound allowlist, the IAM split, and the cost.
- Managing Secrets in GitHub Actions WorkflowsStore every GitHub Actions secret at the narrowest scope that works, hand it to one step rather than one job, and delete the cloud keys OIDC replaces.
- Scaling Self-Hosted Runners Without Owning the ClusterScaling self-hosted GitHub Actions runners means owning registration, autoscaling, image rebuilds, and cleanup. The managed and BYOC paths, priced.
- Gradle Configuration Cache on GitHub ActionsEnable the Gradle configuration cache and the build cache on GitHub Actions, persist both directories across jobs, and key entries by Gradle version.
- Building for Graviton Targets on GitHub ActionsRun the GitHub Actions build and test jobs that produce your Graviton artifacts on native ARM64 runner labels, so architecture faults surface in the pipeline.
- Choosing Between Hosted and BYOC RunnersHosted WarpBuild runners bill one per-minute rate. BYOC runners bill $0.002 per minute plus your own cloud spend. How to choose, with a worked cost model.
- Idle Time Inside GitHub Actions JobsIdle minutes inside a GitHub Actions job bill like busy ones. Spot them from low CPU against a long duration, name the four sources, and price the fix.
- Incremental Builds on GitHub ActionsIncremental builds fail on GitHub Actions because each job gets a clean VM. Boot from a WarpBuild snapshot so build outputs and compiler state survive.
- Code Signing iOS Builds on GitHub ActionsCreate a temporary keychain in the job, import the certificate from repository secrets, install the profile, then archive on a warp-macos runner label.
- Running iOS Simulator Tests on GitHub ActionsRun iOS simulator tests on GitHub Actions with xcodebuild on a macOS runner. Pin the image that carries your runtime, then shard the suite at $0.08 per minute.
- Caching Jest Runs on GitHub ActionsJest re-transforms every module on a fresh GitHub Actions runner. Pin cacheDirectory, restore it with a key that survives dependency bumps, and size maxWorkers.
- Large Artifact Uploads on GitHub ActionsArtifact uploads run slow because upload-artifact zips the whole path at compression level 6 before any byte moves. Cut the file count, bytes, and minutes.
- GitHub Actions on Large RepositoriesLarge repositories run slow on GitHub Actions because every job rebuilds a cold working set. Measure the setup phases, then keep the tree warm.
- Long Running Jobs on GitHub ActionsA GitHub Actions job that runs for hours meets three ceilings. Find the one that ended yours, split the work into checkpointed stages, and price both shapes.
- Notarizing macOS Apps in GitHub Actionsnotarytool submits a signed archive to Apple, waits for a verdict, then staples the ticket. Here is the split-job workflow and what the wait costs.
- Freeing Disk Space on macOS RunnersA macOS Xcode job fills the runner volume with DerivedData, archives and simulator data. Measure the budget, clean up in order, then price the larger label.
- Sharding Test Suites Across a MatrixPut a shard index in the GitHub Actions matrix, pass it to the test command, and merge the shard reports in one job. Workflow YAML and cost arithmetic.
- Caching Toolchains Installed with misemise reinstalls every pinned tool on a fresh GitHub Actions runner. Cache the mise data directory, key it on the config files, and verify versions first.
- Building Several Images from One MonorepoA monorepo that rebuilds every image on every commit pays for images nobody touched. Detect the changed paths, bake only the affected targets, price both paths.
- MSBuild Caching on GitHub Actions Windows RunnersMSBuild rebuilds every project on GitHub Actions because runners are ephemeral. Cache NuGet, keep incremental output inside one job, and skip idle analyzers.
- Multi Platform Docker Images on Native RunnersMulti arch Docker builds crawl on one x64 runner because the arm64 stage runs under QEMU. Build each architecture natively and join them with a manifest.
- Publishing One Image to Several RegistriesBuild the image once, push it to a primary registry, then copy it by digest into every other target. The workflow YAML, the wiring, and the transfer math.
- Multi Stage Docker Builds and Layer ReuseMulti stage Docker builds reuse layers one stage at a time, and GitHub Actions throws that away every job. Keep the stages on a builder that outlives the job.
- Nightly Build Jobs on GitHub ActionsA nightly build runs the work that is too slow or too broad for a pull request check. Pick what belongs there, route failures to a person, and price the matrix.
- Caching NuGet Packages on GitHub ActionsCache the NuGet global packages folder, which dies with the runner on every GitHub Actions run. Use WarpBuilds/setup-dotnet on Linux, actions/cache on Windows.
- OpenTelemetry Metrics from GitHub Actions RunnersGitHub Actions reports run duration and nothing about the machine. The WarpBuild agent emits runner metrics over OpenTelemetry, grouped per job and instance.
- Running Many iOS Jobs in Parallel on GitHub ActionsFanning many iOS jobs out on GitHub Actions clears three limits: the workflow concurrency key, account job ceilings, and the macOS fleet quota.
- Persistent Caches for GitHub Actions RunsA GitHub Actions runner is destroyed after every job. Persist state with a cache action for files, or with a snapshot runner for whole machine state.
- Preview Environments from Pull RequestsPreview environments on GitHub Actions run on three transitions: create on open, update on push, destroy on close. Workflow YAML, concurrency, and cost.
- Sharding pytest Suites Across Runnerspytest runs parallel in GitHub Actions two ways: xdist worker processes inside one job and matrix shards across jobs. Size both levers and merge results.
- Moving ARM64 Docker Builds Off QEMUA buildx arm64 build on an x64 GitHub Actions runner is slow because QEMU translates every instruction. Move it to a native ARM64 runner or builder.
- Cutting GitHub Actions Costs Without RewritesCut GitHub Actions spend by right-sizing runners, ending re-run waste, and fixing cache misses. WarpBuild Linux runners start at $0.004 per minute.
- Release Build Workflows on GitHub ActionsA release workflow fires on a tag, builds each target once, tests those exact files, and publishes them. Here is the YAML, the runner sizing, and the cost.
- Remote Docker Builders for GitHub ActionsA remote Docker builder runs docker build on a dedicated VM with a persistent layer cache outside your GitHub Actions runner. Setup, YAML, and costs.
- Re-run Storms and What They CostA re-run storm bills the same commit twice or three times over. Price the re-run rate against monthly minutes, then cut it with cancellation and retries.
- Running Reusable Workflows Across Many RepositoriesA shared workflow holds up across fifty repositories on three things: a tagged version contract, a runner label input per caller, and a staged rollout.
- A Runner Label Strategy for a Growing OrgMap every workload class to one runner label, pass that label into workflows as an input, and migrate one class at a time. Catalog rows, YAML, and arithmetic.
- Right Sizing GitHub Actions RunnersGitHub Actions reports job duration and nothing about the machine. Right size runners from peak CPU, peak memory and the per job recommendation endpoint.
- Rust Incremental Compilation in GitHub ActionsCargo incremental state lives in target and dies with the runner. Set CARGO_INCREMENTAL=0 on stateless GitHub Actions jobs, or keep the target directory warm.
- Modeling S3 Transfer Costs for GitHub ActionsS3 charges for GitHub Actions land on your AWS bill as artifact reads, fixture pulls, and deploy bundles. A worked monthly model with published AWS rates.
- Using sccache on GitHub Actions Runnerssccache turns repeat compilations into cache fetches, but only when the cache directory outlives the job. Wire it up, persist it, and read the hit counts.
- Security Scanning Jobs Without the WaitScan jobs run long because image pulls, database refreshes, and full-tree analysis repeat on every pull request. Split the work and cache the database.
- What Self-Hosted Runners Actually CostSelf-hosted GitHub Actions runners bill idle instance hours plus image, autoscaling, upgrade and on-call work. A worked monthly model with the arithmetic.
- Service Containers for Integration TestsGitHub Actions service containers start and end with the job. Gate the first step on a real health check, then size the runner for services and test workers.
- Sharing Data Between GitHub Actions JobsThree mechanisms move data between GitHub Actions jobs: job outputs for strings, artifacts for files, and cache or snapshot for runner state.
- Sharing a Docker Layer Cache Across JobsTwo GitHub Actions jobs share a Docker layer cache only when both build on one persistent builder. Point every job at the same WarpBuild builder profile.
- Sizing Runners for Android BuildsSize an Android runner by subtracting the emulator first: it holds guest cores and RAM all job. Sizing table, warp- labels, the KVM label, and cost math.
- Sizing Runners and Builders for Docker BuildsSize the job runner for checkout and waiting, then size the remote Docker builder for the layer cache. Two size ladders, a decision rule, and the arithmetic.
- Sizing Runners for Java and Gradle BuildsSize a Gradle runner from the memory budget first: daemon heap plus forked test heaps must fit under RAM. Sizing table, warp- labels, rates, and cost math.
- Sizing Runners for Node.js Test SuitesNode test workers each hold their own heap, so memory per worker sets the runner size. Measure peak CPU and memory, then pick the warp- Linux label to match.
- Sizing Runners for Python Test SuitesTwo limits decide the runner size for a Python suite: memory per pytest worker and the shared service ceiling. Size both against the Linux x64 ladder.
- Sizing Runners for Rust BuildsSize Rust jobs by how wide the cargo dependency graph stays. 4 vCPU for check jobs, 8 to 16 vCPU for tests, and the point where extra cores stop paying.
- How to Speed Up GitHub Actions BuildsFaster GitHub Actions builds come from more vCPUs, warm caches, and shorter queues. Swap ubuntu-latest for a WarpBuild warp- label and see the cost math.
- Spot Instances for GitHub Actions RunnersSpot instances for GitHub Actions runners come from WarpBuild BYOC in your own AWS, GCP, or Azure account, at a flat $0.002 per runner minute fee.
- Static IPs for GitHub Actions RunnersStatic egress IPs for GitHub Actions runners are a BYOC capability on AWS, GCP, and Azure. Here is the setup, the address math, and the per-GB cost.
- Running Only the Tests a Change AffectsPick the tests a change actually affects with path filters, dependency graph selection, or coverage maps. Detection job YAML, matrix fan-out, and cost math.
- TestFlight Uploads from GitHub ActionsArchive and export on a macOS runner, write an App Store Connect API key into the runner temp directory, then upload the IPA with xcrun altool on a tag.
- Caching vcpkg and Conan Packages on GitHub Actionsvcpkg and Conan rebuild from source on GitHub Actions until the binary cache outlives the job. Restore the archives, key them safely, and ban source builds.
- Visual Studio Build Tools on GitHub ActionsWindows runner images already ship Visual Studio Enterprise. Initialize the developer environment with vswhere and VsDevCmd, and pick images by component ID.
- A Weekly CI Health Report for GitHub ActionsAssemble billed minutes by runner label, p95 duration, queue wait and cache hit rate into one scheduled GitHub Actions job that writes a job summary.
- Code Signing Windows Binaries in GitHub Actionssigntool needs a certificate, a password, and a timestamp authority on a runner that starts with none of them. Here is the tag-only signing job and its cost.
- Cutting Xcode Build Times on GitHub ActionsXcode jobs run long on GitHub Actions because DerivedData and SwiftPM start cold. Measure by phase, restore both caches, then size the macOS runner.
- Caching Xcode DerivedData in GitHub ActionsWhich DerivedData subdirectories restore safely on GitHub Actions, how to key and prune the archive so it fits the cache allowance, and the minutes it returns.
- Pinning an Xcode Version in GitHub ActionsPin the macOS runner label, set DEVELOPER_DIR, and assert the resolved toolchain in the job log so a moving alias or an image update cannot change Xcode.
Start with $10 in free credits
Change the runner label in your workflow and keep the rest of your GitHub Actions setup. Runner time is billed per minute.