feat: add runner.topology arc-dind support for ARC/DinD rootless execution#42371
Conversation
…ution
Add runner.topology configuration to enable ARC/DinD runner topology
detection and rootless agent job execution:
- Add runner.topology field to frontmatter schema and AWF config schema
- Emit {"runner":{"topology":"arc-dind"}} in AWF config JSON
- Add RunnerConfig type with parsing from frontmatter
- Redirect RUNNER_TOOL_CACHE to /tmp/gh-aw/tool-cache on ARC/DinD
- Validate no sudo/apt-get in generated steps when topology is arc-dind
- Add comprehensive tests for all new functionality
The runner.topology key is the single stable contract between gh-aw and
AWF for runner environment detection — AWF resolves all internal details
(network isolation, sysroot image, path-prefix probes, tool cache
validation) from this signal.
Closes #42368
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds explicit runner.topology: arc-dind support to gh-aw so compiled workflows can (a) emit a single runner-topology signal into the AWF config JSON, (b) apply ARC/DinD-specific workflow wiring (tool-cache redirection), and (c) validate user-authored step blocks for root-required commands in ARC/DinD mode.
Changes:
- Introduces
RunnerConfig(runner.topology) in frontmatter parsing +WorkflowData, with validation for supported topology values. - Emits an AWF config
runnersection containingtopologywhen set. - Adds ARC/DinD rootless validation and an ARC/DinD tool-cache redirection step in the main job.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/frontmatter_types.go | Adds RunnerConfig type and RunnerTopologyArcDind constant; wires runner config into parsed frontmatter struct. |
| pkg/workflow/runner_config.go | Extracts runner.topology from frontmatter and validates allowed topology values. |
| pkg/workflow/runner_config_test.go | Unit tests for runner config extraction/validation and topology helpers. |
| pkg/workflow/workflow_builder.go | Plumbs extracted runner config into initial WorkflowData. |
| pkg/workflow/compiler_types.go | Extends WorkflowData with RunnerConfig. |
| pkg/workflow/compiler.go | Wires runner topology validation into the compiler validation pipeline. |
| pkg/workflow/runner_topology_validation.go | Adds ARC/DinD rootless validation (sudo/apt install detection) for user-authored step blocks. |
| pkg/workflow/runner_topology_validation_test.go | Unit tests for ARC/DinD rootless validation helpers. |
| pkg/workflow/compiler_yaml_main_job.go | Adds an ARC/DinD tool-cache redirection step to the generated main job. |
| pkg/workflow/awf_config.go | Adds runner section to AWF config JSON emission, and helper functions for topology detection. |
| pkg/workflow/awf_config_test.go | Tests that runner.topology is emitted (or omitted) in AWF config JSON. |
| pkg/parser/schemas/main_workflow_schema.json | Updates main workflow frontmatter schema to allow runner.topology: arc-dind. |
| pkg/workflow/schemas/awf-config.schema.json | Updates AWF config schema to allow runner.topology: arc-dind. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 13/13 changed files
- Comments generated: 2
- Review effort level: Low
| // containsSudoCommand checks if a line contains a sudo invocation. | ||
| // Matches "sudo " at word boundaries but not inside comments or strings mentioning sudo. | ||
| func containsSudoCommand(line string) bool { | ||
| // Look for sudo as a command (not in a YAML key or comment) | ||
| trimmed := strings.TrimSpace(line) | ||
| if strings.HasPrefix(trimmed, "#") { | ||
| return false | ||
| } | ||
| // Check for sudo at start of a command or after common shell operators | ||
| for _, prefix := range []string{"sudo ", "sudo\t"} { | ||
| if strings.Contains(trimmed, prefix) { | ||
| return true | ||
| } | ||
| } | ||
| return false | ||
| } | ||
|
|
||
| // containsAptGetInstall checks if a line contains apt-get install. | ||
| func containsAptGetInstall(line string) bool { | ||
| trimmed := strings.TrimSpace(line) | ||
| if strings.HasPrefix(trimmed, "#") { | ||
| return false | ||
| } | ||
| return strings.Contains(trimmed, "apt-get install") || strings.Contains(trimmed, "apt install") | ||
| } |
| // Redirect tool cache for ARC/DinD runners. | ||
| // On ARC, the standard RUNNER_TOOL_CACHE=/opt/hostedtoolcache is invisible to the DinD | ||
| // daemon's filesystem. Redirecting to /tmp/gh-aw/tool-cache (a shared emptyDir volume) | ||
| // ensures setup-* actions install to a path visible to both runner and DinD containers. | ||
| if isArcDindTopology(data) { |
|
@copilot run pr-finisher skill |
…e redirection - Fix containsSudoCommand false positives: only flag sudo when it appears as a command invocation (at line start, as inline run: value, or after a shell operator). YAML metadata lines like "- name: avoid sudo" no longer cause false positive compilation failures. - Add isYAMLKey/hasSudoInvocation helpers to make the logic clear and auditable. - Move ARC/DinD tool cache redirection step to before runtime setup steps so setup-* actions (setup-go, setup-node, etc.) see the redirected RUNNER_TOOL_CACHE path. Add mkdir -p to create the directory before it is referenced. - Add/extend tests: TestContainsSudoCommand covers command-start, inline run:, shell operators, and false-positive cases; updated TestValidateArcDindRootless covers step-name false positive; apply require.Error per testifylint; use strings.SplitSeq per modernize. Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Done. Two issues fixed in commit
Tool cache redirection step ordering — The ARC/DinD |
|
✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟 |
|
🚀 Smoke Antigravity MISSION COMPLETE! Antigravity has spoken. ✨ |
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ |
|
✅ All tools validated successfully! Agent Container Smoke Test confirms agent container is ready. |
|
📰 BREAKING: Smoke Copilot - AOAI (Entra) is now investigating this pull request. Sources say the story is developing... |
|
🚀 Smoke Pi MISSION COMPLETE! Pi delivered. 🥧 |
|
📰 BREAKING: Smoke Copilot - AOAI (apikey) is now investigating this pull request. Sources say the story is developing... |
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
|
🚀 Smoke Gemini MISSION COMPLETE! Gemini has spoken. ✨ Testing |
Agent Container Tool Check
Result: 12/12 tools available ✅ Overall Status: PASS Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
Smoke Test: Gemini Results
Overall status: FAIL Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "localhost"See Network Configuration for more information.
|
Comment MemoryNote This comment is managed by comment memory.It stores persistent context for this thread in the code block at the top of this comment. Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
🧪 Smoke Test: Claude — Run 28412908793Core #1-12: ✅ all passed Overall: PASS ✅ Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
There was a problem hiding this comment.
💥 Automated smoke test review - all systems nominal!
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
💥 [THE END] — Illustrated by Smoke Claude · 52.9 AIC · ⌖ 25.6 AIC · ⊞ 8.7K
Comment /smoke-claude to run again
| var runnerConfigLog = logger.New("workflow:runner_config") | ||
|
|
||
| // extractRunnerConfig extracts runner topology configuration from frontmatter. | ||
| // Returns nil when no runner configuration is present. |
There was a problem hiding this comment.
Consider documenting the expected frontmatter shape for runner here so callers know which keys are read.
| return nil | ||
| } | ||
|
|
||
| config := &RunnerConfig{} |
There was a problem hiding this comment.
Nice—returning nil on empty topology keeps the zero-config path clean. A brief comment on why empty topology means no config could help future readers.
|
Caution agentic threat detected DetailsThe threat detection engine failed to produce results. Review the workflow run logs for details. Pull request created: #42386
|
There was a problem hiding this comment.
Smoke review tools work. Me leave tiny notes.
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
📰 BREAKING: Report filed by Smoke Copilot · 333.1 AIC · ⌖ 22.4 AIC · ⊞ 19.1K
Comment /smoke-copilot to run again
Add label smoke to run again
|
@lpcox Tests results:
|
|
Smoke Test Results: 1✅ 2❌ 3❌ 4✅ 5❌ 6✅ 7❌ 8✅ Overall: FAIL @lpcox
|
|
🎉 This pull request is included in a new release. Release: |
"body": "### Summary\n\nAdds
runner.topology: arc-dindas a first-class frontmatter configuration