From e24d7ea914975f474af6eb6198e3ae521cc6f305 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Mon, 17 Aug 2026 10:26:57 +0200 Subject: [PATCH 1/2] Run hosted Podman Feature tests rootfully Retain the Docker-in-Docker Feature workload while avoiding the hosted runner's rootless Podman 5.8 APT sandbox regression. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/test/cli.podman.test.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/test/cli.podman.test.ts b/src/test/cli.podman.test.ts index 932d9a358..77ea367c5 100644 --- a/src/test/cli.podman.test.ts +++ b/src/test/cli.podman.test.ts @@ -5,6 +5,7 @@ import * as assert from 'assert'; import * as path from 'path'; +import { chmod, writeFile } from 'fs/promises'; import { shellExec } from './testUtils'; const pkg = require('../../package.json'); @@ -14,31 +15,39 @@ describe('Dev Containers CLI using Podman', function () { const tmp = path.relative(process.cwd(), path.join(__dirname, 'tmp')); const cli = `npx --prefix ${tmp} devcontainer`; + const podman = process.env.GITHUB_ACTIONS === 'true' ? path.join(process.cwd(), tmp, 'podman-rootful') : 'podman'; before('Install', async () => { await shellExec(`rm -rf ${tmp}/node_modules`); await shellExec(`mkdir -p ${tmp}`); + if (process.env.GITHUB_ACTIONS === 'true') { + // The hosted runner's rootless Podman 5.8 build fails when APT drops + // privileges to _apt, so retain the full Feature coverage rootfully. + const podmanExecutable = (await shellExec('command -v podman')).stdout.trim(); + await writeFile(podman, `#!/bin/sh\nexec sudo -- ${podmanExecutable} "$@"\n`); + await chmod(podman, 0o755); + } await shellExec(`npm --prefix ${tmp} install devcontainers-cli-${pkg.version}.tgz`); }); describe('Command up using Podman', () => { it('should execute successfully with valid config with features', async () => { - const res = await shellExec(`${cli} up --docker-path podman --workspace-folder ${__dirname}/configs/image-with-features`); + const res = await shellExec(`${cli} up --docker-path ${podman} --workspace-folder ${__dirname}/configs/image-with-features`); const response = JSON.parse(res.stdout); assert.equal(response.outcome, 'success'); const containerId: string = response.containerId; assert.ok(containerId, 'Container id not found.'); - await shellExec(`podman rm -f ${containerId}`); + await shellExec(`${podman} rm -f ${containerId}`); }); it('should execute successfully with valid config with features', async () => { - const res = await shellExec(`${cli} up --docker-path podman --workspace-folder ${__dirname}/configs/dockerfile-with-features`); + const res = await shellExec(`${cli} up --docker-path ${podman} --workspace-folder ${__dirname}/configs/dockerfile-with-features`); const response = JSON.parse(res.stdout); assert.equal(response.outcome, 'success'); const containerId: string = response.containerId; assert.ok(containerId, 'Container id not found.'); - await shellExec(`podman rm -f ${containerId}`); + await shellExec(`${podman} rm -f ${containerId}`); }); }); -}); \ No newline at end of file +}); From 76a621f835a913dae7daf636a9f6c573ed9cdb6a Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Tue, 18 Aug 2026 11:44:25 +0200 Subject: [PATCH 2/2] Keep hosted Podman tests rootless Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/test/cli.podman.test.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/test/cli.podman.test.ts b/src/test/cli.podman.test.ts index 77ea367c5..4541eadb9 100644 --- a/src/test/cli.podman.test.ts +++ b/src/test/cli.podman.test.ts @@ -5,7 +5,6 @@ import * as assert from 'assert'; import * as path from 'path'; -import { chmod, writeFile } from 'fs/promises'; import { shellExec } from './testUtils'; const pkg = require('../../package.json'); @@ -15,25 +14,22 @@ describe('Dev Containers CLI using Podman', function () { const tmp = path.relative(process.cwd(), path.join(__dirname, 'tmp')); const cli = `npx --prefix ${tmp} devcontainer`; - const podman = process.env.GITHUB_ACTIONS === 'true' ? path.join(process.cwd(), tmp, 'podman-rootful') : 'podman'; + const podman = 'podman'; + // Buildah 1.42+ can reset /tmp permissions after RUN --mount when layers are enabled. + const cliEnvironment = process.env.GITHUB_ACTIONS === 'true' + ? { ...process.env, BUILDAH_LAYERS: 'false' } + : process.env; before('Install', async () => { await shellExec(`rm -rf ${tmp}/node_modules`); await shellExec(`mkdir -p ${tmp}`); - if (process.env.GITHUB_ACTIONS === 'true') { - // The hosted runner's rootless Podman 5.8 build fails when APT drops - // privileges to _apt, so retain the full Feature coverage rootfully. - const podmanExecutable = (await shellExec('command -v podman')).stdout.trim(); - await writeFile(podman, `#!/bin/sh\nexec sudo -- ${podmanExecutable} "$@"\n`); - await chmod(podman, 0o755); - } await shellExec(`npm --prefix ${tmp} install devcontainers-cli-${pkg.version}.tgz`); }); describe('Command up using Podman', () => { it('should execute successfully with valid config with features', async () => { - const res = await shellExec(`${cli} up --docker-path ${podman} --workspace-folder ${__dirname}/configs/image-with-features`); + const res = await shellExec(`${cli} up --docker-path ${podman} --workspace-folder ${__dirname}/configs/image-with-features`, { env: cliEnvironment }); const response = JSON.parse(res.stdout); assert.equal(response.outcome, 'success'); const containerId: string = response.containerId; @@ -42,7 +38,7 @@ describe('Dev Containers CLI using Podman', function () { }); it('should execute successfully with valid config with features', async () => { - const res = await shellExec(`${cli} up --docker-path ${podman} --workspace-folder ${__dirname}/configs/dockerfile-with-features`); + const res = await shellExec(`${cli} up --docker-path ${podman} --workspace-folder ${__dirname}/configs/dockerfile-with-features`, { env: cliEnvironment }); const response = JSON.parse(res.stdout); assert.equal(response.outcome, 'success'); const containerId: string = response.containerId;