Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ export class DeployWorkspaceProjectConfirmStep extends OverwriteConfirmStepBase<
resourcesToCreate.join(', ')
);
} else {
confirmMessage = localize('overwriteConfirm', 'The latest deployment of container app "{0}" and the latest image of registry "{1}" will be overwritten.', context.containerApp?.name, context.registry?.name);
outputMessage = localize('overwriteConfirmed', 'User confirmed overwrite of container app "{0}" and the latest image of registry "{1}".', context.containerApp?.name, context.registry?.name);
confirmMessage = localize('overwriteConfirm', 'The latest deployment of container app "{0}" will be overwritten.', context.containerApp?.name);
outputMessage = localize('overwriteConfirmed', 'User confirmed overwrite of container app "{0}".', context.containerApp?.name);
}

if (this.hasUnsupportedFeatures(context)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { SetTelemetryProps } from "../../telemetry/SetTelemetryProps";
import type { DeployWorkspaceProjectTelemetryProps as TelemetryProps } from "../../telemetry/commandTelemetryProps";
import type { CreateContainerAppBaseContext } from "../createContainerApp/CreateContainerAppContext";
import type { IManagedEnvironmentContext } from "../createManagedEnvironment/IManagedEnvironmentContext";
import { BuildImageInAzureImageSourceBaseContext } from "../image/imageSource/buildImageInAzure/BuildImageInAzureContext";
import { BuildImageInAzureImageSourceBaseContext } from "../image/imageSource/buildImageInAzure/BuildImageInAzureImageSourceContext";
import type { CreateAcrContext } from "../image/imageSource/containerRegistry/acr/createAcr/CreateAcrContext";

// Use intersection typing instead of an interface here to bypass some minor (relatively trivial) type mismatch issues introduced by having to use the 'Partial' utility
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { localize } from "../../../utils/localize";
import { validateUtils } from "../../../utils/validateUtils";
import { ContainerAppNameStep } from "../../createContainerApp/ContainerAppNameStep";
import { ManagedEnvironmentNameStep } from "../../createManagedEnvironment/ManagedEnvironmentNameStep";
import { ImageNameStep } from "../../image/imageSource/buildImageInAzure/ImageNameStep";
import { RegistryNameStep } from "../../image/imageSource/containerRegistry/acr/createAcr/RegistryNameStep";
import type { DeployWorkspaceProjectContext } from "../DeployWorkspaceProjectContext";

Expand All @@ -32,7 +33,7 @@ export class DefaultResourcesNameStep extends AzureWizardPromptStep<DeployWorksp
!context.resourceGroup && (context.newResourceGroupName = resourceBaseName);
!context.managedEnvironment && (context.newManagedEnvironmentName = resourceBaseName);
!context.containerApp && (context.newContainerAppName = resourceBaseName);
context.imageName = `${resourceBaseName}:latest`;
context.imageName = ImageNameStep.getTimestampedImageName(context.containerApp?.name || resourceBaseName);
}

public async configureBeforePrompt(context: DeployWorkspaceProjectContext): Promise<void> {
Expand All @@ -55,7 +56,7 @@ export class DefaultResourcesNameStep extends AzureWizardPromptStep<DeployWorksp
!context.managedEnvironment && (context.newManagedEnvironmentName = workspaceName);
!context.registry && (context.newRegistryName = await RegistryNameStep.tryGenerateRelatedName(context, workspaceName));
!context.containerApp && (context.newContainerAppName = workspaceName);
context.imageName = `${context.containerApp?.name || workspaceName}:latest`;
context.imageName = ImageNameStep.getTimestampedImageName(context.containerApp?.name || workspaceName);
}

public shouldPrompt(context: DeployWorkspaceProjectContext): boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
*--------------------------------------------------------------------------------------------*/

import type { Registry } from "@azure/arm-containerregistry";
import type { ISubscriptionActionContext } from "@microsoft/vscode-azext-utils";
import { nonNullProp, type ISubscriptionActionContext } from "@microsoft/vscode-azext-utils";
import { ext } from "../../../extensionVariables";
import type { ContainerAppItem } from "../../../tree/ContainerAppItem";
import type { ManagedEnvironmentItem } from "../../../tree/ManagedEnvironmentItem";
import { localize } from "../../../utils/localize";
import { ImageNameStep } from "../../image/imageSource/buildImageInAzure/ImageNameStep";
import { AcrListStep } from "../../image/imageSource/containerRegistry/acr/AcrListStep";
import { DeployWorkspaceProjectSettings } from "../deployWorkspaceProjectSettings";
import { triggerSettingsOverride } from "./getDefaultContextValues";
Expand Down Expand Up @@ -36,7 +37,7 @@ export async function getDefaultAcrResources(
ext.outputChannel.appendLog(localize('foundResourceMatch', 'Used saved workspace settings and found an existing container registry.'));
return {
registry: savedRegistry,
imageName: `${settings.containerAppName || savedRegistry.name}:latest`
imageName: ImageNameStep.getTimestampedImageName(settings.containerAppName || nonNullProp(savedRegistry, 'name'))
};
} else {
ext.outputChannel.appendLog(localize('noResourceMatch', 'Used saved workspace settings to search for Azure Container Registry "{0}" but found no match.', settings.containerRegistryName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { acrDomain, activityFailContext, activityFailIcon, activitySuccessContex
import { ExecuteActivityOutput, ExecuteActivityOutputStepBase } from "../../../../utils/activity/ExecuteActivityOutputStepBase";
import { createActivityChildContext } from "../../../../utils/activity/activityUtils";
import { localize } from "../../../../utils/localize";
import { BuildImageInAzureImageSourceContext } from "./BuildImageInAzureContext";
import { BuildImageInAzureImageSourceContext } from "./BuildImageInAzureImageSourceContext";
import { buildImageInAzure } from "./buildImageInAzure";

export class BuildImageStep extends ExecuteActivityOutputStepBase<BuildImageInAzureImageSourceContext> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { AzureWizardPromptStep, nonNullValue } from '@microsoft/vscode-azext-utils';
import { dockerFilePick, dockerfileGlobPattern } from "../../../../constants";
import { selectWorkspaceFile } from "../../../../utils/workspaceUtils";
import { BuildImageInAzureImageSourceContext } from './BuildImageInAzureContext';
import { BuildImageInAzureImageSourceContext } from './BuildImageInAzureImageSourceContext';

export class DockerFileItemStep extends AzureWizardPromptStep<BuildImageInAzureImageSourceContext> {
public async prompt(context: BuildImageInAzureImageSourceContext): Promise<void> {
Expand Down
38 changes: 23 additions & 15 deletions src/commands/image/imageSource/buildImageInAzure/ImageNameStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@
*--------------------------------------------------------------------------------------------*/

import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils";
import { URI, Utils } from "vscode-uri";
import { localize } from "../../../../utils/localize";
import { validateUtils } from "../../../../utils/validateUtils";
import { BuildImageInAzureImageSourceContext } from "./BuildImageInAzureContext";
import { CreateContainerAppContext } from "../../../createContainerApp/CreateContainerAppContext";
import type { BuildImageInAzureImageSourceContext } from "./BuildImageInAzureImageSourceContext";

const maxImageNameLength: number = 46;

export class ImageNameStep extends AzureWizardPromptStep<BuildImageInAzureImageSourceContext> {
public async prompt(context: BuildImageInAzureImageSourceContext): Promise<void> {
const suggestedImageName = await getSuggestedName(context, context.rootFolder.name);
const suggestedImageName = ImageNameStep.getTimestampedImageName(
context.containerApp?.name ||
// Step is also technically reachable from the `createContainerApp` entry point
(context as CreateContainerAppContext).newContainerAppName ||
'hello-world'
Comment thread
MicroFish91 marked this conversation as resolved.
Outdated
);

context.imageName = (await context.ui.showInputBox({
prompt: localize('imageNamePrompt', 'Enter a name for the image'),
Expand All @@ -35,19 +40,22 @@ export class ImageNameStep extends AzureWizardPromptStep<BuildImageInAzureImageS

return undefined;
}
}

async function getSuggestedName(context: BuildImageInAzureImageSourceContext, dockerFilePath: string): Promise<string | undefined> {
let suggestedImageName: string | undefined;
suggestedImageName = Utils.dirname(URI.parse(dockerFilePath)).path.split('/').pop();
if (suggestedImageName === '') {
if (context.rootFolder) {
suggestedImageName = Utils.basename(context.rootFolder.uri).toLowerCase().replace(/\s/g, '');
}
static getTimestampedImageName(repositoryName: string): string {
const tag: string = getTimestampTag();
return repositoryName.slice(0, maxImageNameLength - (tag.length + 1)) + ':' + tag;
Comment thread
MicroFish91 marked this conversation as resolved.
}
}

function getTimestampTag(): string {
const now = new Date();

const year = now.getFullYear();
const month = (now.getMonth() + 1).toString().padStart(2, '0'); // Months start at 0, so add 1
const day = now.getDate().toString().padStart(2, '0');
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
const seconds = now.getSeconds().toString().padStart(2, '0');

const colonTag: string = ':latest';
suggestedImageName = suggestedImageName?.slice(0, maxImageNameLength - colonTag.length);
suggestedImageName += colonTag;
return suggestedImageName;
return `${year}-${month}-${day}_${hours}${minutes}${seconds}`;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { AzureWizardPromptStep, IAzureQuickPickItem } from "@microsoft/vscode-azext-utils";
import { localize } from "../../../../utils/localize";
import { BuildImageInAzureImageSourceContext } from "./BuildImageInAzureContext";
import { BuildImageInAzureImageSourceContext } from "./BuildImageInAzureImageSourceContext";

export enum AcrBuildSupportedOS {
Windows = 'Windows',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { AzureWizardPromptStep, UserCancelledError } from '@microsoft/vscode-aze
import * as vscode from 'vscode';
import { isAzdWorkspaceProject } from '../../../../utils/azdUtils';
import { localize } from '../../../../utils/localize';
import { BuildImageInAzureImageSourceContext } from './BuildImageInAzureContext';
import { BuildImageInAzureImageSourceContext } from './BuildImageInAzureImageSourceContext';

export class RootFolderStep extends AzureWizardPromptStep<BuildImageInAzureImageSourceContext> {
public async prompt(context: BuildImageInAzureImageSourceContext): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { activityFailContext, activityFailIcon } from "../../../../constants";
import { ExecuteActivityOutput, ExecuteActivityOutputStepBase } from "../../../../utils/activity/ExecuteActivityOutputStepBase";
import { createActivityChildContext } from "../../../../utils/activity/activityUtils";
import { localize } from "../../../../utils/localize";
import { BuildImageInAzureImageSourceContext } from "./BuildImageInAzureContext";
import { BuildImageInAzureImageSourceContext } from "./BuildImageInAzureImageSourceContext";

export class RunStep extends ExecuteActivityOutputStepBase<BuildImageInAzureImageSourceContext> {
public priority: number = 440;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils";
import * as os from 'os';
import { URI, Utils } from "vscode-uri";
import { BuildImageInAzureImageSourceContext } from "./BuildImageInAzureContext";
import { BuildImageInAzureImageSourceContext } from "./BuildImageInAzureImageSourceContext";

const idPrecision = 6;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { ExecuteActivityOutput, ExecuteActivityOutputStepBase } from '../../../.
import { createActivityChildContext } from '../../../../utils/activity/activityUtils';
import { createContainerRegistryManagementClient } from '../../../../utils/azureClients';
import { localize } from '../../../../utils/localize';
import { BuildImageInAzureImageSourceContext } from './BuildImageInAzureContext';
import { BuildImageInAzureImageSourceContext } from './BuildImageInAzureImageSourceContext';

const vcsIgnoreList = ['.git', '.gitignore', '.bzr', 'bzrignore', '.hg', '.hgignore', '.svn'];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { Run as AcrRun } from '@azure/arm-containerregistry';
import { KnownRunStatus } from '@azure/arm-containerregistry';
import { nonNullValue } from '@microsoft/vscode-azext-utils';
import { delay } from '../../../../utils/delay';
import { BuildImageInAzureImageSourceContext } from './BuildImageInAzureContext';
import { BuildImageInAzureImageSourceContext } from './BuildImageInAzureImageSourceContext';

const WAIT_MS = 5000;

Expand Down
5 changes: 2 additions & 3 deletions src/commands/image/updateImage/UpdateImageDraftStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import type { Revision } from "@azure/arm-appcontainers";
import { nonNullProp, randomUtils } from "@microsoft/vscode-azext-utils";
import { nonNullProp } from "@microsoft/vscode-azext-utils";
import type { Progress } from "vscode";
import { ext } from "../../../extensionVariables";
import type { ContainerAppItem, ContainerAppModel } from "../../../tree/ContainerAppItem";
Expand All @@ -29,8 +29,7 @@ export class UpdateImageDraftStep<T extends UpdateImageContext> extends Revision
this.revisionDraftTemplate.containers.push({
env: context.environmentVariables,
image: context.image,
// We need the revision draft to always show up as having unsaved changes, we can ensure this by adding a unique ID at end of the container name
name: getContainerNameForImage(nonNullProp(context, 'image')) + `-${randomUtils.getRandomHexString(5)}`,
name: getContainerNameForImage(nonNullProp(context, 'image')),
Comment thread
MicroFish91 marked this conversation as resolved.
});

await this.updateRevisionDraftWithTemplate(context);
Expand Down
2 changes: 1 addition & 1 deletion src/utils/pickItem/pickContainerApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { getPickEnvironmentSteps } from "./pickEnvironment";
export function getPickContainerAppStep(containerAppName?: string | RegExp): AzureWizardPromptStep<AzureResourceQuickPickWizardContext> {
let containerAppFilter: RegExp | undefined;
if (containerAppName) {
containerAppFilter = containerAppName instanceof RegExp ? containerAppName : new RegExp(containerAppName);
containerAppFilter = containerAppName instanceof RegExp ? containerAppName : new RegExp(`^${containerAppName}$`);
Comment thread
MicroFish91 marked this conversation as resolved.
} else {
containerAppFilter = ContainerAppItem.contextValueRegExp;
}
Expand Down
2 changes: 1 addition & 1 deletion src/utils/pickItem/pickEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function getPickEnvironmentSteps(skipIfOne: boolean = false, environmentN

let environmentFilter: RegExp | undefined;
if (environmentName) {
environmentFilter = environmentName instanceof RegExp ? environmentName : new RegExp(environmentName);
environmentFilter = environmentName instanceof RegExp ? environmentName : new RegExp(`^${environmentName}$`);
} else {
environmentFilter = ManagedEnvironmentItem.contextValueRegExp;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ suite('DefaultResourcesNameStep', async () => {
newResourceGroupName: 'workspace-name',
newManagedEnvironmentName: 'workspace-name',
newContainerAppName: 'workspace-name',
imageName: 'workspace-name:latest'
} as MockDefaultResourcesNameStepContext,
getMockResultContext(wizardContext)
);
Expand Down Expand Up @@ -93,7 +92,6 @@ suite('DefaultResourcesNameStep', async () => {
newResourceGroupName: 'user-name',
newManagedEnvironmentName: 'user-name',
newContainerAppName: 'user-name',
imageName: 'user-name:latest'
} as MockDefaultResourcesNameStepContext,
getMockResultContext(wizardContext)
);
Expand Down Expand Up @@ -124,7 +122,6 @@ suite('DefaultResourcesNameStep', async () => {
newResourceGroupName: undefined,
newManagedEnvironmentName: undefined,
newContainerAppName: 'workspace-name',
imageName: 'workspace-name:latest'
} as MockDefaultResourcesNameStepContext,
getMockResultContext(wizardContext)
);
Expand Down Expand Up @@ -155,7 +152,6 @@ suite('DefaultResourcesNameStep', async () => {
newResourceGroupName: undefined,
newManagedEnvironmentName: undefined,
newContainerAppName: 'user-name',
imageName: 'user-name:latest'
} as MockDefaultResourcesNameStepContext,
getMockResultContext(wizardContext)
);
Expand Down Expand Up @@ -188,7 +184,6 @@ suite('DefaultResourcesNameStep', async () => {
newResourceGroupName: undefined,
newManagedEnvironmentName: undefined,
newContainerAppName: undefined,
imageName: 'acr-build-1:latest'
} as MockDefaultResourcesNameStepContext,
getMockResultContext(wizardContext)
);
Expand Down Expand Up @@ -216,6 +211,5 @@ function getMockResultContext(context: MockDefaultResourcesNameStepContext): Moc
newResourceGroupName: context.newResourceGroupName,
newManagedEnvironmentName: context.newManagedEnvironmentName,
newContainerAppName: context.newContainerAppName,
imageName: context.imageName
};
}