Any program can be a GitHub Actions shell
Using Arbitrary “Shells” in GitHub Actions
- Main insight: any executable can be used as the “shell” for a
run:block, with the script materialized to a temp file and passed as{0}. - People note you can already “become anything” via
exec, but this makes it more explicit and lets you drive CI in languages like Go, C, Elisp, or via tools likegoevalornix develop. - Some see it primarily as a neat, under-documented capability that’s useful for debugging and understanding the runner, not something to lean on heavily.
Centralized Workflows & repository_dispatch
- One org shares an undocumented trick: matching
repository_dispatchevents with wildcards (security_scan::*) to centralize release workflows while leaving builds per-repo. - This helps identify product/version in the Actions UI.
- Discussion notes limitations around private vs public action repos and gaps in GitHub’s story for reacting to CI events across repos.
Debugging Shell, set -e, pipefail
- Several commenters use custom shells (e.g., forcing
bash -x) to improve debuggability. - Long subthread debates
set -o pipefailand-e:- One side:
pipefailis a misunderstood anti-pattern that can obscure which part of a pipeline failed and leave corrupted partial outputs. - Others: this is no worse than other shell footguns;
-xand tools likePIPESTATUSprovide enough context if used correctly.
- One side:
Nix, Performance, and Caching
- People consider combining this trick with
nix develop, but report GitHub’s default runners are slow for Nix-heavy workflows, even with binary caches. - Suggestions: self‑hosted runners, pre-baked container images, or careful caching; but GitHub’s cache size, ownership, and per-repo limitations are pain points.
YAML, Discipline, and “Do Less in Actions”
- Strong sentiment that complex logic in YAML (and in Actions generally) is brittle and hard to debug.
- Recommended practices:
- Put almost all logic in scripts or real build systems (Make, Bazel, Nix, custom CLIs).
- Use Actions as thin glue: checkout, call scripts, handle triggers, fan-out/fan-in, and UI integration.
- Prefer locally runnable setups; avoid dummy commits to debug CI.
- Debate over “compile to YAML” approaches (e.g., Dhall): some advocate them; others argue they add tooling complexity and training burden.
CI Portability, Lock‑In, and Security
- Advantages of GHA YAML vs a single
pipeline.sh: rich UI, marketplace actions, parallelism, cross-platform matrices, automatic tokens, and integration with PR annotations and caches. - Counterpoint: heavy use of marketplace actions and expressions increases lock-in and makes migration harder, though many steps are conceptually portable.
- Security angle: this trick doesn’t introduce fundamentally new risks, but reinforces that in Actions, write access is effectively execute access, especially with third‑party triggers and self-hosted runners.