Skip to content

Spike: Running Squad's gh-aw workflows on self-hosted / custom runners #1840

Closed

Description

@bradygaster

Question

Can GitHub Agentic Workflows (gh-aw) run on a custom/self-hosted runner, and if so, can Squad's gh-aw integration (workflows/squad.md, workflows/squad-implement-worker.md, workflows/shared/squad.md) run there too?

Answer

Yes to both — but Squad's shared bootstrap component has real gaps that need work before it's supported.


Part 1 — gh-aw supports custom runners

Confirmed against githubnext/gh-aw → docs/src/content/docs/reference/self-hosted-runners.md and docs/src/content/docs/reference/frontmatter.md.

runs-on: accepts all three GitHub Actions forms:

  • String — runs-on: self-hosted
  • Array — runs-on: [self-hosted, linux, x64] (runner must match all labels)
  • Object — runs-on: { group: my-runner-group, labels: [linux, x64] }

Runner scope knobs

Field Controls Default
runs-on: main agent job only ubuntu-latest
runs-on-slim: all framework jobs (activation, pre-activation, safe-outputs, unlock, APM, cache memory) ubuntu-slim
safe-outputs.runs-on: safe-output jobs (takes precedence over runs-on-slim) inherits
safe-outputs.threat-detection.runs-on: threat-detection job agent job's runner
aw.json → maintenance.runs_on every job in generated agentics-maintenance.yml ubuntu-slim

Hard requirements

  • Linux only. macos-* ❌ (no nested virtualization for Docker), windows-* ❌.
  • Working Docker daemon. MCP gateway and sandbox run as containers. Runner user must be in the docker group or the socket must be world-readable.
  • Node.js on PATH for framework scripts. gh-aw auto-emits actions/setup-node (Node 24) when it detects a non-standard runner; pin explicitly with runtimes: { node: { version: '24' } }.
  • Egress to api.githubcopilot.com, github.com, ghcr.io, plus anything in network.allowed.
  • ARC/Kubernetes: requires containerMode.type="dind" (type="kubernetes" is unsupported) plus runner.topology: arc-dind in frontmatter. Split-daemon topologies may need GH_AW_DOCKER_SOCK_PATH / GH_AW_DOCKER_SOCK_GID.
  • Rootless pods: if the cluster enforces allowPrivilegeEscalation: false, the Copilot CLI install script needs --rootless so it installs to ~/.local/bin instead of /usr/local/bin.

Air-gapped / private cloud

.github/workflows/aw.json supports action_pins (remap owner/repo@ref → internal mirror) and container_pins (remap image + digest). Applied at compile time and baked into .lock.yml, so workflows never reach public registries at runtime. Neither is available in per-workflow frontmatter.


Part 2 — Squad-specific gaps

Four issues found in Squad's current gh-aw integration:

1. runs-on is not merged from imports

Per gh-aw's imports reference: "runs-on must be set in each workflow — it is not merged from imports."

Squad ships as imports: - shared/squad.md, so runs-on cannot be added to workflows/shared/squad.md. It has to live in each top-level workflow (workflows/squad.md, workflows/squad-implement-worker.md) or in a consumer-authored wrapper.

2. Bootstrap runs on the activation job, not the agent job

workflows/shared/squad.md runs npx --yes @bradygaster/squad-cli@$SQUAD_CLI_VERSION init inside jobs.activation.pre-steps — deliberately, so the npm install happens outside the agent's network firewall.

But activation is a framework job, so it obeys runs-on-slim, not runs-on. Setting runs-on: self-hosted alone leaves the Squad install running on a GitHub-hosted runner. Full isolation requires runs-on-slim: as well — and then the self-hosted runner needs Node on PATH and egress to registry.npmjs.org.

3. Hardcoded artifact action versions break GHES

workflows/shared/squad.md pins actions/upload-artifact@v7.0.1 and actions/download-artifact@v8.0.1 directly in its pre-steps / steps.

gh-aw's GHES compatibility mode ({"ghes": true} in aw.json, or gh aw compile --ghes) downgrades its own artifact steps to upload-artifact@v3.2.2 / download-artifact@v3.1.0, but it does not rewrite action references that Squad hardcoded. On GHES those v4+ actions fail with GHESNotSupportedError, so Squad's squad-state artifact handoff breaks — the agent job never receives .squad/ or .github/agents/squad.agent.md.

This is the most consequential gap and likely needs a fix in the shared component (e.g. aw.json action_pins, or version-selectable artifact steps).

4. Customizations get clobbered on update

gh aw add bradygaster/squad/workflows/squad.md@latest rewrites the source .md, so a hand-added runs-on: is lost on the next update. Consumers need a wrapper workflow instead.


Proposed consumer pattern

A thin wrapper in the consumer repo that remote-imports Squad's shared component, keeping runner config out of the file that gh aw add overwrites:

---
name: Squad
on:
  slash_command:
    name: squad
runs-on: [self-hosted, linux, x64]
runs-on-slim: [self-hosted, linux, x64]
runtimes:
  node:
    version: '24'
imports:
  - bradygaster/squad/workflows/shared/squad.md@<40-char-sha>
safe-outputs:
  runs-on: [self-hosted, linux, x64]
---

Air-gapped consumers additionally add action_pins + container_pins to .github/workflows/aw.json to mirror ghcr.io/github/gh-aw-firewall and the actions/* dependencies.


Validation status

Findings are documentation- and source-validated, not runtime-validated:

  • ✅ gh-aw runner support verified against upstream docs (self-hosted-runners.md, frontmatter.md, imports.md)
  • ✅ Squad's activation-job bootstrap and hardcoded artifact pins read directly from workflows/shared/squad.md
  • ✅ Import-merge limitation confirmed in gh-aw's imports reference
  • ❌ Wrapper workflow has not been compiled with gh aw compile
  • ❌ Nothing executed on an actual self-hosted runner or ARC cluster

Follow-up work

  • Prototype the wrapper workflow and verify it compiles cleanly with gh aw compile
  • Fix the GHES artifact-version gap in workflows/shared/squad.md (blocks GHES/air-gapped adoption)
  • Decide whether Squad's top-level workflows should expose runs-on / runs-on-slim as documented extension points
  • Add a self-hosted-runner section to docs/src/content/docs/guide/gh-aw.md
  • Smoke-test on a real self-hosted Linux runner with Docker (and, separately, on ARC DinD)

References

Activity

  1. github-actions commented on Aug 23, 2026

    @github-actions
    Contributor

    📋 Assigned to Booster (CI/CD Engineer)

    Issue: #1840 — Spike: Running Squad's gh-aw workflows on self-hosted / custom runners

    Booster will pick this up in the next Copilot session.

    For Copilot coding agent: If enabled, this issue will be worked automatically.
    Otherwise, start a Copilot session and say:
    Booster, work on issue #1840

  2. added
    squadSquad triage inbox — Lead will assign to a member
    on Aug 23, 2026
  3. added
    gh-awGitHub Agentic Workflows integration
    triagedIssue has been triaged
    wave:3-laterWave 3 — backlog, future
    on Aug 24, 2026
  4. bradygaster commented on Aug 30, 2026

    @bradygaster
    CollaboratorAuthor

    Spike research is complete. Actionable findings (custom runner support requires configurable
    uns-on, and bootstrap dependencies must be declared or pre-installed) are consolidated into #1502. Closing as completed; no follow-up issues needed — #1502 is the implementation tracker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    gh-awGitHub Agentic Workflows integrationpriority:p2Next sprintsquadSquad triage inbox — Lead will assign to a membertriagedIssue has been triagedtype:spikeResearch/investigation — produces a plan, not codewave:3-laterWave 3 — backlog, future

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions