Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Empty file.
7 changes: 4 additions & 3 deletions src/commands/StartingResourcesLogStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { LocationListStep, type ILocationWizardContext } from "@microsoft/vscode
import { ActivityChildItem, ActivityChildType, activityInfoIcon, AzureWizardPromptStep, createContextValue, type ExecuteActivityContext, type IActionContext } from "@microsoft/vscode-azext-utils";
import { activityInfoContext } from "../constants";
import { ext } from "../extensionVariables";
import { prependOrInsertAfterLastInfoChild } from "../utils/activityUtils";
import { localize } from "../utils/localize";

type StartingResourcesLogContext = IActionContext & Partial<ExecuteActivityContext> & ILocationWizardContext & {
Expand Down Expand Up @@ -50,7 +51,7 @@ export class StartingResourcesLogStep<T extends StartingResourcesLogContext> ext

protected async logStartingResources(context: T): Promise<void> {
if (context.resourceGroup) {
context.activityChildren?.push(
prependOrInsertAfterLastInfoChild(context,
new ActivityChildItem({
contextValue: createContextValue([startingResourcesContext, activityInfoContext]),
label: localize('useResourceGroup', 'Use resource group "{0}"', context.resourceGroup.name),
Expand All @@ -62,7 +63,7 @@ export class StartingResourcesLogStep<T extends StartingResourcesLogContext> ext
}

if (context.managedEnvironment) {
context.activityChildren?.push(
prependOrInsertAfterLastInfoChild(context,
new ActivityChildItem({
label: localize('useManagedEnvironment', 'Use managed environment "{0}"', context.managedEnvironment.name),
contextValue: createContextValue([startingResourcesContext, activityInfoContext]),
Expand All @@ -74,7 +75,7 @@ export class StartingResourcesLogStep<T extends StartingResourcesLogContext> ext
}

if (context.containerApp) {
context.activityChildren?.push(
prependOrInsertAfterLastInfoChild(context,
new ActivityChildItem({
label: localize('useContainerApp', 'Use container app "{0}"', context.containerApp.name),
contextValue: createContextValue([startingResourcesContext, activityInfoContext]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ export abstract class AzureResourceVerifyStepBase<T extends WorkspaceDeploymentC
};
}

// Todo: Verify if we need progress output

public createFailOutput(context: T): ExecuteActivityOutput {
return {
item: new ActivityChildItem({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ActivityChildItem, ActivityChildType, AzureWizard, activityInfoContext,
import { ProgressLocation, window } from "vscode";
import { appProvider, managedEnvironmentsId } from "../../../constants";
import { ext } from "../../../extensionVariables";
import { createActivityContext } from "../../../utils/activityUtils";
import { createActivityContext, prependOrInsertAfterLastInfoChild } from "../../../utils/activityUtils";
import { getVerifyProvidersStep } from "../../../utils/getVerifyProvidersStep";
import { localize } from "../../../utils/localize";
import { ContainerAppCreateStep } from "../../createContainerApp/ContainerAppCreateStep";
Expand Down Expand Up @@ -69,8 +69,7 @@ export async function deployWorkspaceProjectInternal(
if (options.suppressActivity) {
activityContext = { suppressNotification: true };
} else {
activityContext = await createActivityContext();
activityContext.activityChildren = [];
activityContext = await createActivityContext({ withChildren: true });
}

// Show loading indicator while we configure starting values
Expand Down Expand Up @@ -114,7 +113,7 @@ export async function deployWorkspaceProjectInternal(

const resourceGroupName: string = nonNullValueAndProp(wizardContext.resourceGroup, 'name');

wizardContext.activityChildren?.push(
prependOrInsertAfterLastInfoChild(wizardContext,
new ActivityChildItem({
label: localize('useResourceGroup', 'Use resource group "{0}"', resourceGroupName),
activityType: ActivityChildType.Info,
Expand All @@ -136,7 +135,7 @@ export async function deployWorkspaceProjectInternal(

const managedEnvironmentName: string = nonNullValueAndProp(wizardContext.managedEnvironment, 'name');

wizardContext.activityChildren?.push(
prependOrInsertAfterLastInfoChild(wizardContext,
new ActivityChildItem({
label: localize('useManagedEnvironment', 'Use container apps environment "{0}"', managedEnvironmentName),
activityType: ActivityChildType.Info,
Expand Down Expand Up @@ -165,9 +164,9 @@ export async function deployWorkspaceProjectInternal(

const registryName: string = nonNullValueAndProp(wizardContext.registry, 'name');

wizardContext.activityChildren?.push(
prependOrInsertAfterLastInfoChild(wizardContext,
new ActivityChildItem({
label: localize('useAcr', 'Using container registry "{0}"', registryName),
label: localize('useAcr', 'Use container registry "{0}"', registryName),
activityType: ActivityChildType.Info,
contextValue: activityInfoContext,
iconPath: activityInfoIcon
Expand All @@ -188,9 +187,9 @@ export async function deployWorkspaceProjectInternal(

executeSteps.push(new ContainerAppUpdateStep());

wizardContext.activityChildren?.push(
prependOrInsertAfterLastInfoChild(wizardContext,
new ActivityChildItem({
label: localize('useContainerApp', 'Using container app "{0}"', containerAppName),
label: localize('useContainerApp', 'Use container app "{0}"', containerAppName),
activityType: ActivityChildType.Info,
contextValue: activityInfoContext,
iconPath: activityInfoIcon
Expand Down
27 changes: 21 additions & 6 deletions src/commands/editContainer/RegistryAndSecretsUpdateStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { type RegistryCredentials, type Secret } from "@azure/arm-appcontainers";
import { AzureWizardExecuteStep, nonNullProp } from "@microsoft/vscode-azext-utils";
import { AzureWizardExecuteStepWithActivityOutput, nonNullProp } from "@microsoft/vscode-azext-utils";
import * as deepEqual from "deep-eql";
import { type Progress } from "vscode";
import { ext } from "../../extensionVariables";
Expand All @@ -13,22 +13,37 @@ import { localize } from "../../utils/localize";
import { updateContainerApp } from "../updateContainerApp";
import { type ContainerEditContext } from "./ContainerEditContext";

export class RegistryAndSecretsUpdateStep<T extends ContainerEditContext> extends AzureWizardExecuteStep<T> {
export class RegistryAndSecretsUpdateStep<T extends ContainerEditContext> extends AzureWizardExecuteStepWithActivityOutput<T> {
public priority: number = 580;
public stepName: string = 'registryAndSecretsUpdateStep';
protected getOutputLogSuccess = (context: T) => localize('updateRegistryCredentialsSuccess', 'Successfully updated new registry credentials and secrets for container app "{0}".', context.containerApp?.name);
protected getOutputLogFail = (context: T) => localize('updateRegistryCredentialsFail', 'Failed to update new registry credentials and secrets for container app "{0}".', context.containerApp?.name);
protected getTreeItemLabel = () => localize('updateRegistryCredentialsLabel', 'Update registry credentials and secrets');

public async execute(context: T, progress: Progress<{ message?: string | undefined; increment?: number | undefined }>): Promise<void> {
private skipRegistryCredentialUpdate: boolean;

public async configureBeforeExecute(context: T): Promise<void> {
const containerApp: ContainerAppModel = nonNullProp(context, 'containerApp');
const containerAppEnvelope = await getContainerEnvelopeWithSecrets(context, context.subscription, containerApp);

// If the credentials have not changed, we can skip this update
if (
context.secrets && context.registryCredentials &&
this.areSecretsDeepEqual(containerAppEnvelope.configuration.secrets, context.secrets) &&
this.areRegistriesDeepEqual(containerAppEnvelope.configuration.registries, context.registryCredentials)
) {
this.skipRegistryCredentialUpdate = true;
context.telemetry.properties.skippedRegistryCredentialUpdate = 'true';
return;
ext.outputChannel.appendLog(localize('skippingCredentialUpdate', 'Verified existing registry credentials are up to date.'));
} else {
this.skipRegistryCredentialUpdate = false;
context.telemetry.properties.skippedRegistryCredentialUpdate = 'false';
}
context.telemetry.properties.skippedRegistryCredentialUpdate = 'false';
}

public async execute(context: T, progress: Progress<{ message?: string | undefined; increment?: number | undefined }>): Promise<void> {
const containerApp: ContainerAppModel = nonNullProp(context, 'containerApp');
const containerAppEnvelope = await getContainerEnvelopeWithSecrets(context, context.subscription, containerApp);

progress.report({ message: localize('configuringSecrets', 'Configuring registry secrets...') });
containerAppEnvelope.configuration.secrets = context.secrets;
Expand All @@ -39,7 +54,7 @@ export class RegistryAndSecretsUpdateStep<T extends ContainerEditContext> extend
}

public shouldExecute(context: T): boolean {
return !!context.registryCredentials && !!context.secrets;
return !!context.registryCredentials && !!context.secrets && !this.skipRegistryCredentialUpdate;
}

private areSecretsDeepEqual(originalSecrets: Secret[] | undefined, newSecrets: Secret[] | undefined): boolean {
Expand Down
14 changes: 7 additions & 7 deletions src/commands/image/imageSource/EnvFileListStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
*--------------------------------------------------------------------------------------------*/

import { type EnvironmentVar } from "@azure/arm-appcontainers";
import { ActivityChildItem, ActivityChildType, AzExtFsExtra, AzureWizardPromptStep, activitySuccessContext, activitySuccessIcon, createContextValue } from "@microsoft/vscode-azext-utils";
import { ActivityChildItem, ActivityChildType, AzExtFsExtra, AzureWizardPromptStep, activityInfoContext, activityInfoIcon, activitySuccessContext, activitySuccessIcon, createContextValue } from "@microsoft/vscode-azext-utils";
import { parse, type DotenvParseOutput } from "dotenv";
import { RelativePattern, workspace, type Uri, type WorkspaceFolder } from "vscode";
import { ImageSource, envFileGlobPattern } from "../../../constants";
import { ext } from "../../../extensionVariables";
import { type EnvironmentVariableTelemetryProps as TelemetryProps } from "../../../telemetry/ImageSourceTelemetryProps";
import { type SetTelemetryProps } from "../../../telemetry/SetTelemetryProps";
import { prependOrInsertAfterLastInfoChild } from "../../../utils/activityUtils";
import { localize } from "../../../utils/localize";
import { selectWorkspaceFile } from "../../../utils/workspaceUtils";
import { type EnvironmentVariablesContext } from "../../environmentVariables/EnvironmentVariablesContext";
Expand Down Expand Up @@ -146,7 +147,7 @@ export class EnvFileListStep<T extends EnvFileListContext> extends AzureWizardPr
} else if (setEnvironmentVariableOption === SetEnvironmentVariableOption.ProvideFile) {
context.activityChildren?.push(
new ActivityChildItem({
label: localize('saveEnvVarsFileLabel', 'Save environment variables using provided .env file'),
label: localize('saveEnvVarsFileLabel', 'Save environment variables from provided .env file'),
description: '0s',
contextValue: createContextValue([envFileListStepContext, activitySuccessContext]),
activityType: ActivityChildType.Success,
Expand All @@ -155,13 +156,12 @@ export class EnvFileListStep<T extends EnvFileListContext> extends AzureWizardPr
);
ext.outputChannel.appendLog(localize('savedEnvVarsFileMessage', 'Saved environment variables using provided .env file "{0}".', context.envPath));
} else if (setEnvironmentVariableOption === SetEnvironmentVariableOption.UseExisting) {
context.activityChildren?.push(
prependOrInsertAfterLastInfoChild(context,
new ActivityChildItem({
label: localize('useExistingEnvVarsLabel', 'Use existing environment variable configuration'),
description: '0s',
contextValue: createContextValue([envFileListStepContext, activitySuccessContext]),
activityType: ActivityChildType.Success,
iconPath: activitySuccessIcon,
contextValue: createContextValue([envFileListStepContext, activityInfoContext]),
activityType: ActivityChildType.Info,
iconPath: activityInfoIcon,
})
);
ext.outputChannel.appendLog(localize('useExistingEnvVarsMessage', 'Used existing environment variable configuration.'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { ActivityChildItem, ActivityChildType, activitySuccessContext, activitySuccessIcon, AzureWizardPromptStep, createContextValue, nonNullProp, type AzureWizardExecuteStep, type IAzureQuickPickItem, type IWizardOptions } from "@microsoft/vscode-azext-utils";
import { acrDomain, type SupportedRegistries } from "../../constants";
import { ActivityChildItem, ActivityChildType, activityInfoIcon, AzureWizardPromptStep, createContextValue, nonNullProp, type AzureWizardExecuteStep, type IAzureQuickPickItem, type IWizardOptions } from "@microsoft/vscode-azext-utils";
import { acrDomain, activityInfoContext, type SupportedRegistries } from "../../constants";
import { ext } from "../../extensionVariables";
import { prependOrInsertAfterLastInfoChild } from "../../utils/activityUtils";
import { getRegistryDomainFromContext } from "../../utils/imageNameUtils";
import { localize } from "../../utils/localize";
import { AcrEnableAdminUserConfirmStep } from "./dockerLogin/AcrEnableAdminUserConfirmStep";
Expand Down Expand Up @@ -92,13 +93,12 @@ export class RegistryCredentialsAddConfigurationListStep extends AzureWizardProm
break;
default:
context.telemetry.properties.newRegistryCredentialType = 'useExisting';
context.activityChildren?.push(
prependOrInsertAfterLastInfoChild(context,
new ActivityChildItem({
label: localize('useExistingRegistryCredentials', 'Use existing registry credential'),
contextValue: createContextValue(['registryCredentialsAddConfigurationListStepItem', activitySuccessContext]),
description: '0s',
activityType: ActivityChildType.Success,
iconPath: activitySuccessIcon,
label: localize('useExistingRegistryCredentials', 'Use existing registry credentials'),
contextValue: createContextValue(['registryCredentialsAddConfigurationListStepItem', activityInfoContext]),
activityType: ActivityChildType.Info,
iconPath: activityInfoIcon,
})
);
ext.outputChannel.appendLog(localize('usingRegistryCredentials', 'Using existing registry credentials.'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export abstract class RevisionDraftUpdateBaseStep<T extends RevisionDraftContext
ext.revisionDraftFileSystem.updateRevisionDraftWithTemplate(this.baseItem, this.revisionDraftTemplate);

if (context.shouldDeployRevisionDraft) {
await this.deployRevisionDraftTemplate(context);
void this.deployRevisionDraftTemplate(context);
}
}

Expand Down
23 changes: 22 additions & 1 deletion src/utils/activityUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { type ExecuteActivityContext } from "@microsoft/vscode-azext-utils";
import { ActivityChildType, type ActivityChildItemBase, type ExecuteActivityContext } from "@microsoft/vscode-azext-utils";
import { type AzureResourcesExtensionApiWithActivity } from "@microsoft/vscode-azext-utils/activity";
import { ext } from "../extensionVariables";
import { settingUtils } from "./settingUtils";
Expand All @@ -15,3 +15,24 @@ export async function createActivityContext(options?: { withChildren?: boolean }
activityChildren: options?.withChildren ? [] : undefined,
};
}

/**
* Adds a new activity child after the last info child in the `activityChildren` array.
* If no info child already exists, the new child is prepended to the front of the array.
* (This utility function is useful for keeping the info children grouped at the front of the list)
*/
export function prependOrInsertAfterLastInfoChild(context: Partial<ExecuteActivityContext>, infoChild: ActivityChildItemBase): void {
if (!context.activityChildren) {
return;
}

const idx: number = context.activityChildren
.map(child => child.activityType)
.lastIndexOf(ActivityChildType.Info);

if (idx === -1) {
context.activityChildren.unshift(infoChild);
} else {
context.activityChildren.splice(idx + 1, 0, infoChild);
}
}