Skip to content

Commit 2f231a0

Browse files
authored
Merge branch 'main' into feat/stop-and-down-commands
2 parents d8b1910 + b4651df commit 2f231a0

File tree

23 files changed

+473
-314
lines changed

23 files changed

+473
-314
lines changed

.github/workflows/dev-containers.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ jobs:
1313
name: CLI
1414
runs-on: ubuntu-latest
1515
steps:
16-
- uses: actions/checkout@v4
17-
- uses: actions/setup-node@v4
16+
- uses: actions/checkout@v6
17+
- uses: actions/setup-node@v5
1818
with:
1919
node-version: '18.x'
2020
registry-url: 'https://npm.pkg.github.com'
@@ -33,7 +33,7 @@ jobs:
3333
echo "TGZ=devcontainers-cli-${VERSION}.tgz" | tee -a $GITHUB_ENV
3434
echo "TGZ_UPLOAD=devcontainers-cli-${VERSION}-${GITHUB_SHA:0:8}.tgz" | tee -a $GITHUB_ENV
3535
- name: Store TGZ
36-
uses: actions/upload-artifact@v4
36+
uses: actions/upload-artifact@v5
3737
with:
3838
name: ${{ env.TGZ_UPLOAD }}
3939
path: ${{ env.TGZ }}
@@ -62,9 +62,9 @@ jobs:
6262
]
6363
steps:
6464
- name: Checkout
65-
uses: actions/checkout@v4
65+
uses: actions/checkout@v6
6666
- name: Setup Node.js
67-
uses: actions/setup-node@v4
67+
uses: actions/setup-node@v5
6868
with:
6969
node-version: '18.x'
7070
registry-url: 'https://npm.pkg.github.com'
@@ -95,9 +95,9 @@ jobs:
9595
runs-on: ubuntu-latest
9696
steps:
9797
- name: Checkout
98-
uses: actions/checkout@v4
98+
uses: actions/checkout@v6
9999
- name: Setup Node.js
100-
uses: actions/setup-node@v4
100+
uses: actions/setup-node@v5
101101
with:
102102
node-version: '18.x'
103103
registry-url: 'https://npm.pkg.github.com'

.github/workflows/publish-dev-containers.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- name: Checkout
13-
uses: actions/checkout@v4
13+
uses: actions/checkout@v6
1414
- name: Setup Node.js
15-
uses: actions/setup-node@v4
15+
uses: actions/setup-node@v5
1616
with:
1717
node-version: '18.x'
1818
registry-url: 'https://registry.npmjs.org'
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Docker v20 Tests for dockerfile frontend test
2+
3+
on:
4+
push:
5+
branches: ['main', 'directive-syntax-further-changes']
6+
pull_request:
7+
branches: ['main']
8+
9+
jobs:
10+
test-docker-v20:
11+
name: Docker v20.10 Compatibility
12+
runs-on: ubuntu-22.04
13+
14+
steps:
15+
- uses: actions/checkout@v6
16+
17+
- uses: actions/setup-node@v5
18+
with:
19+
node-version: '18.x'
20+
21+
- name: Install Docker v20.10
22+
run: |
23+
sudo apt-get remove -y docker-ce docker-ce-cli containerd.io || true
24+
sudo apt-get update
25+
sudo apt-get install -y \
26+
ca-certificates \
27+
curl \
28+
gnupg \
29+
lsb-release
30+
sudo mkdir -p /etc/apt/keyrings
31+
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
32+
echo \
33+
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
34+
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
35+
sudo apt-get update
36+
sudo apt-get install -y docker-ce=5:20.10.* docker-ce-cli=5:20.10.* containerd.io
37+
sudo systemctl restart docker
38+
39+
- name: Verify Docker version, Install and Test
40+
run: |
41+
# Verify
42+
docker version
43+
DOCKER_VERSION=$(docker version --format '{{.Server.Version}}')
44+
if [[ ! "$DOCKER_VERSION" =~ ^20\.10\. ]]; then
45+
echo "ERROR: Expected Docker v20.10.x but got $DOCKER_VERSION"
46+
exit 1
47+
fi
48+
yarn install --frozen-lockfile
49+
yarn type-check
50+
yarn package
51+
yarn test-matrix --forbid-only src/test/cli.up.test.ts
52+
env:
53+
CI: true
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Docker v29 Tests
2+
3+
on:
4+
push:
5+
branches: ['main', 'docker-v29-issue-old']
6+
pull_request:
7+
branches: ['main']
8+
9+
jobs:
10+
test-docker-v29:
11+
name: Docker v29.0.0 Compatibility
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v6
16+
17+
- uses: actions/setup-node@v5
18+
with:
19+
node-version: '18.x'
20+
21+
- name: Install Docker v29.0.0
22+
run: |
23+
sudo apt-get remove -y docker-ce docker-ce-cli containerd.io || true
24+
curl -fsSL https://get.docker.com -o get-docker.sh
25+
sudo VERSION=29.0.0 sh get-docker.sh
26+
sudo systemctl restart docker
27+
28+
- name: Verify Docker version, Install and Test
29+
run: |
30+
# Verify
31+
docker version
32+
DOCKER_VERSION=$(docker version --format '{{.Server.Version}}')
33+
if [[ ! "$DOCKER_VERSION" =~ ^29\. ]]; then
34+
echo "ERROR: Expected Docker v29.x but got $DOCKER_VERSION"
35+
exit 1
36+
fi
37+
yarn install --frozen-lockfile
38+
yarn type-check
39+
yarn package
40+
yarn test-matrix --forbid-only src/test/cli.up.test.ts
41+
env:
42+
CI: true
43+

.github/workflows/test-plan-item-validator.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
steps:
1010
- name: Checkout Actions
1111
if: contains(github.event.issue.labels.*.name, 'testplan-item') || contains(github.event.issue.labels.*.name, 'invalid-testplan-item')
12-
uses: actions/checkout@v4
12+
uses: actions/checkout@v6
1313
with:
1414
repository: 'microsoft/vscode-github-triage-actions'
1515
ref: stable

.github/workflows/test-windows.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ jobs:
4646
]
4747
steps:
4848
- name: Checkout
49-
uses: actions/checkout@v4
49+
uses: actions/checkout@v6
5050
- name: Setup Node.js
51-
uses: actions/setup-node@v4
51+
uses: actions/setup-node@v5
5252
with:
5353
node-version: '18.x'
5454
registry-url: 'https://npm.pkg.github.com'

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33
Notable changes.
44

5+
## December 2025
6+
7+
### [0.80.3]
8+
- Fix: Skip download and injection of `dockerfile:1.4` syntax for Docker Engine versions [>=23.0.0](https://docs.docker.com/engine/release-notes/23.0/#2300)) - `dockerfile:1.4` or a subsequent version is already used by the docker engine package. (https://github.com/devcontainers/cli/pull/1113)
9+
10+
## November 2025
11+
12+
### [0.80.2]
13+
- Fix: Docker container event 'start' dropped deprecated fields in Docker v29.0.0 (https://github.com/devcontainers/cli/pull/1103)
14+
15+
## September 2025
16+
17+
### [0.80.1]
18+
- Fix: debian:latest dropped adduser / addgroup (https://github.com/devcontainers/cli/pull/1060)
19+
520
## July 2025
621

722
### [0.80.0]

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@devcontainers/cli",
33
"description": "Dev Containers CLI",
4-
"version": "0.80.0",
4+
"version": "0.80.3",
55
"bin": {
66
"devcontainer": "devcontainer.js"
77
},
@@ -61,7 +61,7 @@
6161
"@types/js-yaml": "^4.0.9",
6262
"@types/mocha": "^10.0.10",
6363
"@types/ncp": "^2.0.8",
64-
"@types/node": "^18.19.75",
64+
"@types/node": "^18.19.127",
6565
"@types/pull-stream": "^3.6.7",
6666
"@types/recursive-readdir": "^2.2.4",
6767
"@types/semver": "^7.5.8",
@@ -74,7 +74,7 @@
7474
"@typescript-eslint/parser": "^8.26.0",
7575
"chai": "^4.5.0",
7676
"copyfiles": "^2.4.1",
77-
"esbuild": "^0.25.0",
77+
"esbuild": "^0.27.0",
7878
"eslint": "^8.57.0",
7979
"event-stream": "^4.0.1",
8080
"gulp-eslint": "^6.0.0",

src/spec-node/containerFeatures.ts

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export async function getExtendImageBuildInfo(params: DockerResolverParameters,
154154
}
155155
};
156156
}
157-
return { featureBuildInfo: getImageBuildOptions(params, config, dstFolder, baseName, imageBuildInfo) };
157+
return { featureBuildInfo: await getImageBuildOptions(params, config, dstFolder, baseName, imageBuildInfo) };
158158
}
159159

160160
// Generates the end configuration.
@@ -193,24 +193,24 @@ export interface ImageBuildOptions {
193193
securityOpts: string[];
194194
}
195195

196-
function getImageBuildOptions(params: DockerResolverParameters, config: SubstitutedConfig<DevContainerConfig>, dstFolder: string, baseName: string, imageBuildInfo: ImageBuildInfo): ImageBuildOptions {
197-
const syntax = imageBuildInfo.dockerfile?.preamble.directives.syntax;
198-
return {
199-
dstFolder,
200-
dockerfileContent: `
196+
async function getImageBuildOptions(params: DockerResolverParameters, config: SubstitutedConfig<DevContainerConfig>, dstFolder: string, baseName: string, imageBuildInfo: ImageBuildInfo): Promise<ImageBuildOptions> {
197+
const syntax = imageBuildInfo.dockerfile?.preamble.directives.syntax;
198+
return {
199+
dstFolder,
200+
dockerfileContent: `
201201
FROM $_DEV_CONTAINERS_BASE_IMAGE AS dev_containers_target_stage
202202
${getDevcontainerMetadataLabel(getDevcontainerMetadata(imageBuildInfo.metadata, config, { featureSets: [] }, [], getOmitDevcontainerPropertyOverride(params.common)))}
203203
`,
204-
overrideTarget: 'dev_containers_target_stage',
205-
dockerfilePrefixContent: `${syntax ? `# syntax=${syntax}` : ''}
206-
ARG _DEV_CONTAINERS_BASE_IMAGE=placeholder
204+
overrideTarget: 'dev_containers_target_stage',
205+
dockerfilePrefixContent: `${syntax ? `# syntax=${syntax}` : ''}
206+
ARG _DEV_CONTAINERS_BASE_IMAGE=placeholder
207207
`,
208-
buildArgs: {
209-
_DEV_CONTAINERS_BASE_IMAGE: baseName,
210-
} as Record<string, string>,
211-
buildKitContexts: {} as Record<string, string>,
212-
securityOpts: [],
213-
};
208+
buildArgs: {
209+
_DEV_CONTAINERS_BASE_IMAGE: baseName,
210+
} as Record<string, string>,
211+
buildKitContexts: {} as Record<string, string>,
212+
securityOpts: [],
213+
};
214214
}
215215

216216
function getOmitDevcontainerPropertyOverride(resolverParams: { omitConfigRemotEnvFromMetadata?: boolean }): (keyof DevContainerConfig & keyof ImageMetadataEntry)[] {
@@ -241,7 +241,10 @@ async function getFeaturesBuildOptions(params: DockerResolverParameters, devCont
241241
const useBuildKitBuildContexts = buildKitVersionParsed ? !isEarlierVersion(buildKitVersionParsed, minRequiredVersion) : false;
242242
const buildContentImageName = 'dev_container_feature_content_temp';
243243
const disableSELinuxLabels = useBuildKitBuildContexts && await isUsingSELinuxLabels(params);
244-
244+
// Access Docker engine version
245+
const dockerEngineVersionParsed = params.dockerEngineVersion?.versionMatch ? parseVersion(params.dockerEngineVersion.versionMatch) : undefined;
246+
const minDockerEngineVersion = [23, 0, 0];
247+
const skipDefaultSyntax = dockerEngineVersionParsed ? !isEarlierVersion(dockerEngineVersionParsed, minDockerEngineVersion) : false;
245248
const omitPropertyOverride = params.common.skipPersistingCustomizationsFromFeatures ? ['customizations'] : [];
246249
const imageMetadata = getDevcontainerMetadata(imageBuildInfo.metadata, devContainerConfig, featuresConfig, omitPropertyOverride, getOmitDevcontainerPropertyOverride(params.common));
247250
const { containerUser, remoteUser } = findContainerUsers(imageMetadata, composeServiceUser, imageBuildInfo.user);
@@ -262,11 +265,12 @@ async function getFeaturesBuildOptions(params: DockerResolverParameters, devCont
262265
.replace('#{devcontainerMetadata}', getDevcontainerMetadataLabel(imageMetadata))
263266
.replace('#{containerEnvMetadata}', generateContainerEnvs(devContainerConfig.config.containerEnv, true))
264267
;
265-
const syntax = imageBuildInfo.dockerfile?.preamble.directives.syntax;
266-
const omitSyntaxDirective = common.omitSyntaxDirective; // Can be removed when https://github.com/moby/buildkit/issues/4556 is fixed
267-
const dockerfilePrefixContent = `${omitSyntaxDirective ? '' :
268-
useBuildKitBuildContexts && !(imageBuildInfo.dockerfile && supportsBuildContexts(imageBuildInfo.dockerfile)) ? '# syntax=docker/dockerfile:1.4' :
269-
syntax ? `# syntax=${syntax}` : ''}
268+
const syntax = imageBuildInfo.dockerfile?.preamble.directives.syntax;
269+
const omitSyntaxDirective = common.omitSyntaxDirective; // Can be removed when https://github.com/moby/buildkit/issues/4556 is fixed
270+
const dockerfilePrefixContent = `${omitSyntaxDirective ? '' :
271+
skipDefaultSyntax ? (syntax ? `# syntax=${syntax}` : '') :
272+
useBuildKitBuildContexts && !(imageBuildInfo.dockerfile && supportsBuildContexts(imageBuildInfo.dockerfile)) ? '# syntax=docker/dockerfile:1.4' :
273+
syntax ? `# syntax=${syntax}` : ''}
270274
ARG _DEV_CONTAINERS_BASE_IMAGE=placeholder
271275
`;
272276

src/spec-node/devContainers.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { LogLevel, LogDimensions, toErrorText, createCombinedLog, createTerminal
1717
import { dockerComposeCLIConfig } from './dockerCompose';
1818
import { Mount } from '../spec-configuration/containerFeaturesConfiguration';
1919
import { getPackageConfig, PackageConfiguration } from '../spec-utils/product';
20-
import { dockerBuildKitVersion, isPodman } from '../spec-shutdown/dockerUtils';
20+
import { dockerBuildKitVersion, dockerEngineVersion, isPodman } from '../spec-shutdown/dockerUtils';
2121
import { Event } from '../spec-utils/event';
2222

2323

@@ -205,6 +205,16 @@ export async function createDockerParams(options: ProvisionOptions, disposables:
205205
output,
206206
platformInfo
207207
}));
208+
209+
const dockerEngineVer = await dockerEngineVersion({
210+
cliHost,
211+
dockerCLI: dockerPath,
212+
dockerComposeCLI,
213+
env: cliHost.env,
214+
output,
215+
platformInfo
216+
});
217+
208218
return {
209219
common,
210220
parsedAuthority,
@@ -225,6 +235,7 @@ export async function createDockerParams(options: ProvisionOptions, disposables:
225235
updateRemoteUserUIDDefault,
226236
additionalCacheFroms: options.additionalCacheFroms,
227237
buildKitVersion,
238+
dockerEngineVersion: dockerEngineVer,
228239
isTTY: process.stdout.isTTY || options.logFormat === 'json',
229240
experimentalLockfile,
230241
experimentalFrozenLockfile,

0 commit comments

Comments
 (0)