Skip to content

Commit eb89b94

Browse files
adding label for the devcontainer cli
1 parent 58e0a47 commit eb89b94

7 files changed

Lines changed: 34 additions & 7 deletions

File tree

.vscode/launch.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,24 @@
3030
"-r",
3131
"ts-node/register",
3232
"--exit",
33-
"src/test/*.test.ts"
33+
"src/test/cli.build.test.ts"
3434
],
3535
"env": {
3636
"TS_NODE_PROJECT": "src/test/tsconfig.json"
3737
},
3838
"console": "integratedTerminal",
39+
},
40+
{
41+
"type": "node",
42+
"request": "launch",
43+
"name": "Launch Help",
44+
"program": "${workspaceFolder}/src/spec-node/devContainersSpecCLI.ts",
45+
"cwd": "${workspaceFolder}",
46+
"args": [
47+
"build",
48+
"--help"
49+
],
50+
"console": "integratedTerminal",
3951
}
4052
]
4153
}

src/spec-node/containerFeatures.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export const getSafeId = (str: string) => str
2828
.replace(/^[\d_]+/g, '_')
2929
.toUpperCase();
3030

31-
export async function extendImage(params: DockerResolverParameters, config: SubstitutedConfig<DevContainerConfig>, imageName: string, additionalImageNames: string[], additionalFeatures: Record<string, string | boolean | Record<string, string | boolean>>, canAddLabelsToContainer: boolean) {
31+
export async function extendImage(params: DockerResolverParameters, config: SubstitutedConfig<DevContainerConfig>, imageName: string, additionalImageNames: string[], imageLabels: string[], additionalFeatures: Record<string, string | boolean | Record<string, string | boolean>>, canAddLabelsToContainer: boolean) {
3232
const { common } = params;
3333
const { cliHost, output } = common;
3434

@@ -113,6 +113,7 @@ export async function extendImage(params: DockerResolverParameters, config: Subs
113113
'--target', featureBuildInfo.overrideTarget,
114114
'-f', dockerfilePath,
115115
...additionalImageNames.length > 0 ? additionalImageNames.map(name => ['-t', name]).flat() : ['-t', updatedImageName],
116+
...imageLabels.length > 0 ? imageLabels.map(name => ['-t', name]).flat() : ['-t', imageLabels],
116117
emptyTempDir
117118
);
118119

src/spec-node/devContainers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export interface ProvisionOptions {
5252
omitLoggerHeader?: boolean | undefined;
5353
buildxPlatform: string | undefined;
5454
buildxPush: boolean;
55+
buildxLabel: string | undefined;
5556
buildxOutput: string | undefined;
5657
buildxCacheTo: string | undefined;
5758
additionalFeatures?: Record<string, string | boolean | Record<string, string | boolean>>;
@@ -146,6 +147,7 @@ export async function createDockerParams(options: ProvisionOptions, disposables:
146147
secretsP,
147148
buildxPlatform: options.buildxPlatform,
148149
buildxPush: options.buildxPush,
150+
buildxLabel: options.buildxLabel,
149151
buildxOutput: options.buildxOutput,
150152
buildxCacheTo: options.buildxCacheTo,
151153
skipFeatureAutoMapping: options.skipFeatureAutoMapping,
@@ -227,6 +229,7 @@ export async function createDockerParams(options: ProvisionOptions, disposables:
227229
experimentalFrozenLockfile,
228230
buildxPlatform: common.buildxPlatform,
229231
buildxPush: common.buildxPush,
232+
buildxLabel: options.buildxLabel,
230233
buildxOutput: common.buildxOutput,
231234
buildxCacheTo: common.buildxCacheTo,
232235
platformInfo

src/spec-node/devContainersSpecCLI.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ async function provision({
267267
useBuildKit: buildkit,
268268
buildxPlatform: undefined,
269269
buildxPush: false,
270+
buildxLabel: undefined,
270271
buildxOutput: undefined,
271272
buildxCacheTo: addCacheTo,
272273
additionalFeatures,
@@ -431,6 +432,7 @@ async function doSetUp({
431432
useBuildKit: 'auto',
432433
buildxPlatform: undefined,
433434
buildxPush: false,
435+
buildxLabel: undefined,
434436
buildxOutput: undefined,
435437
buildxCacheTo: undefined,
436438
skipFeatureAutoMapping: false,
@@ -508,6 +510,7 @@ function buildOptions(y: Argv) {
508510
'buildkit': { choices: ['auto' as 'auto', 'never' as 'never'], default: 'auto' as 'auto', description: 'Control whether BuildKit should be used' },
509511
'platform': { type: 'string', description: 'Set target platforms.' },
510512
'push': { type: 'boolean', default: false, description: 'Push to a container registry.' },
513+
'label': { type: 'string', description: 'Provide key and value for the metadata of the container. (<key1>=<value1> <key2>=<value2> )' },
511514
'output': { type: 'string', description: 'Overrides the default behavior to load built images into the local docker registry. Valid options are the same ones provided to the --output option of docker buildx build.' },
512515
'additional-features': { type: 'string', description: 'Additional features to apply to the dev container (JSON as per "features" section in devcontainer.json)' },
513516
'skip-feature-auto-mapping': { type: 'boolean', default: false, hidden: true, description: 'Temporary option for testing.' },
@@ -546,6 +549,7 @@ async function doBuild({
546549
'buildkit': buildkit,
547550
'platform': buildxPlatform,
548551
'push': buildxPush,
552+
'label': buildxLabel,
549553
'output': buildxOutput,
550554
'cache-to': buildxCacheTo,
551555
'additional-features': additionalFeaturesJson,
@@ -593,6 +597,7 @@ async function doBuild({
593597
useBuildKit: buildkit,
594598
buildxPlatform,
595599
buildxPush,
600+
buildxLabel,
596601
buildxOutput,
597602
buildxCacheTo,
598603
skipFeatureAutoMapping,
@@ -629,10 +634,13 @@ async function doBuild({
629634
// Support multiple use of `--image-name`
630635
const imageNames = (argImageName && (Array.isArray(argImageName) ? argImageName : [argImageName]) as string[]) || undefined;
631636

637+
// Support multiple use of `--label`
638+
const imageLabels = (buildxLabel && (Array.isArray(buildxLabel) ? buildxLabel : [buildxLabel]) as string[]) || undefined;
639+
632640
if (isDockerFileConfig(config)) {
633641

634642
// Build the base image and extend with features etc.
635-
let { updatedImageName } = await buildNamedImageAndExtend(params, configWithRaw as SubstitutedConfig<DevContainerFromDockerfileConfig>, additionalFeatures, false, imageNames);
643+
let { updatedImageName } = await buildNamedImageAndExtend(params, configWithRaw as SubstitutedConfig<DevContainerFromDockerfileConfig>, additionalFeatures, false, imageNames, imageLabels);
636644

637645
if (imageNames) {
638646
imageNameResult = imageNames;
@@ -695,7 +703,7 @@ async function doBuild({
695703
}
696704

697705
await inspectDockerImage(params, config.image, true);
698-
const { updatedImageName } = await extendImage(params, configWithRaw, config.image, imageNames || [], additionalFeatures, false);
706+
const { updatedImageName } = await extendImage(params, configWithRaw, config.image, imageNames || [], imageLabels || [], additionalFeatures, false);
699707

700708
if (imageNames) {
701709
imageNameResult = imageNames;
@@ -858,6 +866,7 @@ async function doRunUserCommands({
858866
useBuildKit: 'auto',
859867
buildxPlatform: undefined,
860868
buildxPush: false,
869+
buildxLabel: undefined,
861870
buildxOutput: undefined,
862871
buildxCacheTo: undefined,
863872
skipFeatureAutoMapping,
@@ -1306,6 +1315,7 @@ export async function doExec({
13061315
omitLoggerHeader: true,
13071316
buildxPlatform: undefined,
13081317
buildxPush: false,
1318+
buildxLabel: undefined,
13091319
buildxCacheTo: undefined,
13101320
skipFeatureAutoMapping,
13111321
buildxOutput: undefined,

src/spec-node/singleContainer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,15 @@ async function setupContainer(container: ContainerDetails, params: DockerResolve
119119
function getDefaultName(config: DevContainerFromDockerfileConfig | DevContainerFromImageConfig, params: DockerResolverParameters) {
120120
return 'image' in config && config.image ? config.image : getFolderImageName(params.common);
121121
}
122-
export async function buildNamedImageAndExtend(params: DockerResolverParameters, configWithRaw: SubstitutedConfig<DevContainerFromDockerfileConfig | DevContainerFromImageConfig>, additionalFeatures: Record<string, string | boolean | Record<string, string | boolean>>, canAddLabelsToContainer: boolean, argImageNames?: string[]): Promise<{ updatedImageName: string[]; imageMetadata: SubstitutedConfig<ImageMetadataEntry[]>; imageDetails: () => Promise<ImageDetails>; labels?: Record<string, string> }> {
122+
export async function buildNamedImageAndExtend(params: DockerResolverParameters, configWithRaw: SubstitutedConfig<DevContainerFromDockerfileConfig | DevContainerFromImageConfig>, additionalFeatures: Record<string, string | boolean | Record<string, string | boolean>>, canAddLabelsToContainer: boolean, argImageNames?: string[], imageLabels?: string[]): Promise<{ updatedImageName: string[]; imageMetadata: SubstitutedConfig<ImageMetadataEntry[]>; imageDetails: () => Promise<ImageDetails>; labels?: Record<string, string> }> {
123123
const { config } = configWithRaw;
124124
const imageNames = argImageNames ?? [getDefaultName(config, params)];
125125
params.common.progress(ResolverProgress.BuildingImage);
126126
if (isDockerFileConfig(config)) {
127127
return await buildAndExtendImage(params, configWithRaw as SubstitutedConfig<DevContainerFromDockerfileConfig>, imageNames, params.buildNoCache ?? false, additionalFeatures);
128128
}
129129
// image-based dev container - extend
130-
return await extendImage(params, configWithRaw, imageNames[0], argImageNames || [], additionalFeatures, canAddLabelsToContainer);
130+
return await extendImage(params, configWithRaw, imageNames[0], argImageNames || [], imageLabels || [], additionalFeatures, canAddLabelsToContainer);
131131
}
132132

133133
async function buildAndExtendImage(buildParams: DockerResolverParameters, configWithRaw: SubstitutedConfig<DevContainerFromDockerfileConfig>, baseImageNames: string[], noCache: boolean, additionalFeatures: Record<string, string | boolean | Record<string, string | boolean>>) {

src/spec-node/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ export interface DockerResolverParameters {
116116
experimentalFrozenLockfile?: boolean;
117117
buildxPlatform: string | undefined;
118118
buildxPush: boolean;
119+
buildxLabel: string | undefined;
119120
buildxOutput: string | undefined;
120121
buildxCacheTo: string | undefined;
121122
platformInfo: PlatformInfo;

src/test/cli.build.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ describe('Dev Containers CLI', function () {
4141
it('should correctly configure the image name to push from --image-name with --push true', async () => {
4242
const testFolder = `${__dirname}/configs/example`;
4343
try {
44-
await shellExec(`${cli} build --workspace-folder ${testFolder} --image-name demo:v1`);
44+
await shellExec(`${cli} build --workspace-folder ${testFolder} --image-name demo:v1 --label "name=prathamesh"`);
4545
const tags = await shellExec(`docker images --format "{{.Tag}}" demo`);
4646
const imageTags = tags.stdout.trim().split('\n').filter(tag => tag !== '<none>');
4747
assert.equal(imageTags.length, 1, 'There should be only one tag for demo:v1');

0 commit comments

Comments
 (0)