feat(worker): exec-as-user, stdin input, chown + userns plumbing

This commit is contained in:
Gabriel Brown
2026-07-13 09:52:45 -04:00
parent 78cb3d90c2
commit 37a82098c2
4 changed files with 156 additions and 19 deletions
@@ -44,6 +44,65 @@ describe('Docker runtime', () => {
);
});
test('boxUsernsArgs maps the host user onto the box uid under podman', async () => {
process.env.SPOON_AGENT_CONTAINER_RUNTIME = 'podman';
const { boxUsernsArgs } = await loadVolumeSpec();
expect(boxUsernsArgs()).toEqual(['--userns=keep-id:uid=1000,gid=1000']);
});
test('boxUsernsArgs adds nothing under docker', async () => {
process.env.SPOON_AGENT_CONTAINER_RUNTIME = 'docker';
const { boxUsernsArgs } = await loadVolumeSpec();
expect(boxUsernsArgs()).toEqual([]);
});
test('SPOON_AGENT_BOX_USERNS overrides: value passes through, empty disables', async () => {
process.env.SPOON_AGENT_CONTAINER_RUNTIME = 'podman';
process.env.SPOON_AGENT_BOX_USERNS = 'host';
let { boxUsernsArgs } = await loadVolumeSpec();
expect(boxUsernsArgs()).toEqual(['--userns=host']);
process.env.SPOON_AGENT_BOX_USERNS = '';
({ boxUsernsArgs } = await loadVolumeSpec());
expect(boxUsernsArgs()).toEqual([]);
delete process.env.SPOON_AGENT_BOX_USERNS;
});
test('execArgv places -u after the workdir and before the container name', async () => {
const { execArgv } = await loadVolumeSpec();
expect(
execArgv({
containerName: 'spoon-box-gabriel',
command: ['ls', '-la'],
environment: { HOME: '/home/gabriel' },
containerCwd: '/home/gabriel',
user: 'gabriel',
}),
).toEqual([
'exec',
'-e',
'HOME=/home/gabriel',
'-w',
'/home/gabriel',
'-u',
'gabriel',
'spoon-box-gabriel',
'ls',
'-la',
]);
});
test('execArgv omits -u when no user is given', async () => {
const { execArgv } = await loadVolumeSpec();
const argv = execArgv({
containerName: 'c',
command: ['true'],
environment: {},
containerCwd: '/',
});
expect(argv).not.toContain('-u');
});
test('treats a spawn failure (no exitCode) as a non-zero exit, not empty success', async () => {
const { normalizeRunResult } = await loadVolumeSpec();
// This is what execa returns with `reject: false` when the runtime binary is