From fca51501a9c142cb39fcb710059b44a713d65416 Mon Sep 17 00:00:00 2001 From: Landon Cox Date: Tue, 30 Jun 2026 12:36:43 -0700 Subject: [PATCH] fix: escape $d as $$d in sysroot-stage compose command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docker Compose interprets $d in the sysroot-stage shell command as a Compose variable (warns: 'The "d" variable is not set') and replaces it with an empty string. This causes the for-loop to execute 'cp -a "/" /sysroot/' — copying the entire container root filesystem instead of individual directories — which eventually fails with exit code 1 after ~3.5 minutes. Fix: use $$d which Docker Compose passes through as literal $d to the shell interpreter. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/services/sysroot-service.test.ts | 11 +++++++++++ src/services/sysroot-service.ts | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/services/sysroot-service.test.ts b/src/services/sysroot-service.test.ts index 908c15656..9bf25a21a 100644 --- a/src/services/sysroot-service.test.ts +++ b/src/services/sysroot-service.test.ts @@ -125,6 +125,17 @@ describe('buildSysrootStageService', () => { expect(service.command[0]).toContain('.awf-sysroot-ready'); }); + it('escapes $d as $$d for Docker Compose variable interpolation', () => { + const service = buildSysrootStageService({ + config: makeConfig({ runnerTopology: 'arc-dind' }), + registry: 'ghcr.io/github/gh-aw-firewall', + imageTag: 'latest', + }); + // Docker Compose treats $var as variable interpolation; $$ escapes to literal $ + expect(service.command[0]).toContain('/$$d'); + expect(service.command[0]).not.toMatch(/\/\$d[^$]/); + }); + it('uses network_mode none (no network needed for copy)', () => { const service = buildSysrootStageService({ config: makeConfig({ runnerTopology: 'arc-dind' }), diff --git a/src/services/sysroot-service.ts b/src/services/sysroot-service.ts index 528ac8cc8..45e2f9b3a 100644 --- a/src/services/sysroot-service.ts +++ b/src/services/sysroot-service.ts @@ -44,7 +44,9 @@ export function buildSysrootStageService(params: SysrootServiceParams): any { 'fi; ' + 'echo "Copying sysroot filesystem..."; ' + 'for d in usr lib bin sbin etc; do ' + - ' [ -d "/$d" ] && cp -a "/$d" /sysroot/; ' + + // Use $$ to escape Docker Compose variable interpolation — Compose + // treats bare $d as a variable reference and replaces it with "". + ' [ -d "/$$d" ] && cp -a "/$$d" /sysroot/; ' + 'done; ' + 'if [ -d /lib64 ]; then cp -a /lib64 /sysroot/; fi; ' + 'touch /sysroot/.awf-sysroot-ready; ' +