Skip to content

Commit a2006d0

Browse files
Merge branch 'main' into test-timeouts
2 parents ad7e467 + da642b4 commit a2006d0

File tree

7 files changed

+33
-23
lines changed

7 files changed

+33
-23
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
echo "TGZ=devcontainers-cli-${VERSION}.tgz" | tee -a $GITHUB_ENV
3838
echo "TGZ_UPLOAD=devcontainers-cli-${VERSION}-${GITHUB_SHA:0:8}.tgz" | tee -a $GITHUB_ENV
3939
- name: Download TGZ
40-
uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11
40+
uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20
4141
with:
4242
workflow: dev-containers.yml
4343
workflow_conclusion: success

CHANGELOG.md

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

33
Notable changes.
44

5+
## April 2026
6+
7+
### [0.86.0]
8+
- Bump basic-ftp from 5.2.0 to 5.2.2. (https://github.com/devcontainers/cli/pull/1201)
9+
- Always write devcontainer.metadata label as JSON array. (https://github.com/devcontainers/cli/pull/1199)
10+
- Normalize drive letter to lowercase on Windows to match VSCode. (https://github.com/devcontainers/cli/pull/1183)
11+
512
## March 2026
613

714
### [0.85.0]

package.json

Lines changed: 1 addition & 1 deletion
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.85.0",
4+
"version": "0.86.0",
55
"bin": {
66
"devcontainer": "devcontainer.js"
77
},

src/spec-node/imageMetadata.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -497,11 +497,9 @@ export function getDevcontainerMetadataLabel(devContainerMetadata: SubstitutedCo
497497
if (!metadata.length) {
498498
return '';
499499
}
500-
const imageMetadataLabelValue = metadata.length !== 1
501-
? `[${metadata
502-
.map(feature => ` \\\n${toLabelString(feature)}`)
503-
.join(',')} \\\n]`
504-
: toLabelString(metadata[0]);
500+
const imageMetadataLabelValue = `[${metadata
501+
.map(feature => ` \\\n${toLabelString(feature)}`)
502+
.join(',')} \\\n]`;
505503
return `LABEL ${imageMetadataLabel}="${imageMetadataLabelValue}"`;
506504
}
507505

src/spec-node/singleContainer.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ export const configFileLabel = 'devcontainer.config_file';
2020
export async function openDockerfileDevContainer(params: DockerResolverParameters, configWithRaw: SubstitutedConfig<DevContainerFromDockerfileConfig | DevContainerFromImageConfig>, workspaceConfig: WorkspaceConfiguration, idLabels: string[], additionalFeatures: Record<string, string | boolean | Record<string, string | boolean>>): Promise<ResolverResult> {
2121
const { common } = params;
2222
const { config } = configWithRaw;
23-
// let collapsedFeaturesConfig: () => Promise<CollapsedFeaturesConfig | undefined>;
2423

2524
let container: ContainerDetails | undefined;
2625
let containerProperties: ContainerProperties | undefined;
@@ -30,14 +29,7 @@ export async function openDockerfileDevContainer(params: DockerResolverParameter
3029
let imageMetadata: ImageMetadataEntry[];
3130
let mergedConfig: MergedDevContainerConfig;
3231
if (container) {
33-
// let _collapsedFeatureConfig: Promise<CollapsedFeaturesConfig | undefined>;
34-
// collapsedFeaturesConfig = async () => {
35-
// return _collapsedFeatureConfig || (_collapsedFeatureConfig = (async () => {
36-
// const allLabels = container?.Config.Labels || {};
37-
// const featuresConfig = await generateFeaturesConfig(params.common, (await createFeaturesTempFolder(params.common)), config, async () => allLabels, getContainerFeaturesFolder);
38-
// return collapseFeaturesConfig(featuresConfig);
39-
// })());
40-
// };
32+
4133
await startExistingContainer(params, idLabels, container);
4234
imageMetadata = getImageMetadataFromContainer(container, configWithRaw, undefined, idLabels, common.output).config;
4335
mergedConfig = mergeConfiguration(config, imageMetadata);
@@ -47,9 +39,6 @@ export async function openDockerfileDevContainer(params: DockerResolverParameter
4739
mergedConfig = mergeConfiguration(config, imageMetadata);
4840
const { containerUser } = mergedConfig;
4941
const updatedImageName = await updateRemoteUserUID(params, mergedConfig, res.updatedImageName[0], res.imageDetails, findUserArg(config.runArgs) || containerUser);
50-
51-
// collapsedFeaturesConfig = async () => res.collapsedFeaturesConfig;
52-
5342
try {
5443
await spawnDevContainer(params, config, mergedConfig, updatedImageName, idLabels, workspaceConfig.workspaceMount, workspaceConfig.additionalMountString, res.imageDetails, containerUser, res.labels || {});
5544
} finally {
@@ -290,7 +279,7 @@ export function findUserArg(runArgs: string[] = []) {
290279
return runArgs[i + 1];
291280
}
292281
if (runArg.startsWith('-u=') || runArg.startsWith('--user=')) {
293-
return runArg.substr(runArg.indexOf('=') + 1);
282+
return runArg.slice(runArg.indexOf('=') + 1);
294283
}
295284
}
296285
return undefined;

src/test/imageMetadata.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,22 @@ describe('Image Metadata', function () {
432432
assert.strictEqual(label.replace(/ \\\n/g, ''), `LABEL devcontainer.metadata="${JSON.stringify(expected).replace(/"/g, '\\"')}"`);
433433
});
434434

435+
it('should create array label for single metadata entry (docker-compose with Dockerfile, no features)', () => {
436+
// When there is only one metadata entry, the label should still be a JSON array.
437+
// Regression test for https://github.com/devcontainers/cli/issues/1054
438+
const label = getDevcontainerMetadataLabel(configWithRaw([
439+
{
440+
remoteUser: 'testUser',
441+
}
442+
]));
443+
const expected = [
444+
{
445+
remoteUser: 'testUser',
446+
}
447+
];
448+
assert.strictEqual(label.replace(/ \\\n/g, ''), `LABEL devcontainer.metadata="${JSON.stringify(expected).replace(/"/g, '\\"')}"`);
449+
});
450+
435451
it('should merge metadata from devcontainer.json and features', () => {
436452
const merged = mergeConfiguration({
437453
configFilePath: URI.parse('file:///devcontainer.json'),

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -639,9 +639,9 @@ base64-js@^1.3.1:
639639
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
640640

641641
basic-ftp@^5.0.2:
642-
version "5.2.0"
643-
resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.2.0.tgz#7c2dff63c918bde60e6bad1f2ff93dcf5137a40a"
644-
integrity sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==
642+
version "5.2.2"
643+
resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.2.2.tgz#4cb2422deddf432896bdb3c9b8f13b944ad4842c"
644+
integrity sha512-1tDrzKsdCg70WGvbFss/ulVAxupNauGnOlgpyjKzeQxzyllBLS0CGLV7tjIXTK3ZQA9/FBEm9qyFFN1bciA6pw==
645645

646646
bl@^5.0.0:
647647
version "5.1.0"

0 commit comments

Comments
 (0)