Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions src/compose-generator.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { generateDockerCompose } from './compose-generator';
import { getRealUserHome } from './host-identity';
import { ACT_PRESET_BASE_IMAGE } from './host-identity';
import { logger } from './logger';
import { WrapperConfig } from './types';
Expand Down Expand Up @@ -496,24 +497,42 @@ describe('generateDockerCompose', () => {
expect(result.volumes).toEqual({ sysroot: {} });
});

it('filters out workDir-based and home-based bind mounts on split-fs', () => {
it('filters out workDir and home dot-directory bind mounts on split-fs', () => {
const config = {
...mockConfig,
runnerTopology: 'arc-dind' as const,
workDir: '/tmp/awf-12345',
};
const result = generateDockerCompose(config, mockNetworkConfig);
const volumes = result.services.agent.volumes as string[];
const workspaceDir = process.env.GITHUB_WORKSPACE || process.cwd();

// workDir-based mounts should be dropped
expect(volumes.some(v => v.startsWith('/tmp/awf-12345'))).toBe(false);

// Home-based mounts targeting /host/home should be dropped
const homeTargets = volumes.filter(v => {
// Home dot-directory mounts should be dropped, but workspace mounts under home should remain.
const homeTargets = volumes
.filter(v => {
const target = v.split(':')[1];
return target.startsWith('/host/home') && !v.startsWith('/dev/null');
})
.map(v => v.split(':')[1]);

expect(homeTargets).toContain(`/host${workspaceDir}`);
expect(homeTargets.some(target => target.startsWith('/host/home/runner/.'))).toBe(false);

// Home root mounts (including trailing slash source) should be dropped.
const effectiveHome = getRealUserHome();
const configWithHomeRootMount = {
...config,
volumeMounts: [`${effectiveHome}/:/host${effectiveHome}:rw`],
};
const resultWithHomeRootMount = generateDockerCompose(configWithHomeRootMount, mockNetworkConfig);
const homeRootMounts = (resultWithHomeRootMount.services.agent.volumes as string[]).filter(v => {
const target = v.split(':')[1];
return target.startsWith('/host/home') && !v.startsWith('/dev/null');
return target === `/host${effectiveHome}` || target === `/host${effectiveHome}/`;
});
expect(homeTargets).toHaveLength(0);
expect(homeRootMounts).toHaveLength(0);

// Should still have /tmp:/tmp, /sys, /dev, sysroot volume
expect(volumes).toContain('/tmp:/tmp:rw');
Expand Down
10 changes: 8 additions & 2 deletions src/compose-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,14 @@ export function generateDockerCompose(
// Drop mounts sourced from AWF workDir (runner's unshared /tmp/awf-*)
if (source.startsWith(workDirPrefix)) return false;

// Drop home directory mounts targeting /host/home/... — sysroot provides them
if (source.startsWith(effectiveHome) && target.startsWith(hostHomeMountPrefix)) return false;
// Drop home dot-directory mounts (e.g. .cache, .config) — sysroot provides them.
// Keep workspace/work paths (e.g. _work/_temp/gh-aw) since those are user-supplied
// custom mounts or tool-cache mounts that the sysroot doesn't provide.
if (source.startsWith(effectiveHome) && target.startsWith(hostHomeMountPrefix)) {
const normalizedSource = source.replace(/\/+$/, '') || '/';
const relPath = normalizedSource.slice(effectiveHome.length);
if (relPath.startsWith('/.') || relPath === '') return false;
}
Comment on lines +152 to +159

return true;
});
Expand Down
Loading