Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add compose service startup CodeLenses, update vscode-docker-registries #4432

Merged
merged 4 commits into from
Dec 18, 2024
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
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3008,13 +3008,13 @@
"@azure/arm-authorization": "^9.0.0",
"@azure/arm-containerregistry": "^10.1.0",
"@azure/storage-blob": "^12.14.0",
"@microsoft/compose-language-service": "^0.2.0",
"@microsoft/compose-language-service": "^0.3.0",
"@microsoft/vscode-azext-azureappservice": "~3.3.0",
"@microsoft/vscode-azext-azureauth": "^2.4.1",
"@microsoft/vscode-azext-azureutils": "^3.0.1",
"@microsoft/vscode-azext-utils": "^2.5.1",
"@microsoft/vscode-container-client": "^0.1.2",
"@microsoft/vscode-docker-registries": "^0.1.12",
"@microsoft/vscode-docker-registries": "^0.1.13",
"dayjs": "^1.11.7",
"dockerfile-language-server-nodejs": "^0.13.0",
"fs-extra": "^11.1.1",
Expand Down
25 changes: 16 additions & 9 deletions src/commands/compose/compose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ import { quickPickWorkspaceFolder } from '../../utils/quickPickWorkspaceFolder';
import { selectComposeCommand } from '../selectCommandTemplate';
import { getComposeProfileList, getComposeProfilesOrServices, getComposeServiceList } from './getComposeSubsetList';

async function compose(context: IActionContext, commands: ('up' | 'down' | 'upSubset')[], message: string, dockerComposeFileUri?: vscode.Uri, selectedComposeFileUris?: vscode.Uri[]): Promise<void> {
async function compose(context: IActionContext, commands: ('up' | 'down' | 'upSubset')[], message: string, dockerComposeFileUri?: vscode.Uri | string, selectedComposeFileUris?: vscode.Uri[], preselectedServices?: string[], preselectedProfiles?: string[]): Promise<void> {
if (!vscode.workspace.isTrusted) {
throw new UserCancelledError('enforceTrust');
}

if (typeof dockerComposeFileUri === 'string') {
dockerComposeFileUri = vscode.Uri.parse(dockerComposeFileUri);
}

// If a file is chosen, get its workspace folder, otherwise, require the user to choose
// If a file is chosen that is not in a workspace, it will automatically fall back to quickPickWorkspaceFolder
const folder: vscode.WorkspaceFolder = (dockerComposeFileUri ? vscode.workspace.getWorkspaceFolder(dockerComposeFileUri) : undefined) ||
Expand Down Expand Up @@ -59,7 +63,7 @@ async function compose(context: IActionContext, commands: ('up' | 'down' | 'upSu
);

// Add the service list if needed
terminalCommand.command = await addServicesOrProfilesIfNeeded(context, folder, terminalCommand.command);
terminalCommand.command = await addServicesOrProfilesIfNeeded(context, folder, terminalCommand.command, preselectedServices, preselectedProfiles);

const client = await ext.orchestratorManager.getClient();
const taskCRF = new TaskCommandRunnerFactory({
Expand All @@ -72,12 +76,14 @@ async function compose(context: IActionContext, commands: ('up' | 'down' | 'upSu
}
}

export async function composeUp(context: IActionContext, dockerComposeFileUri?: vscode.Uri, selectedComposeFileUris?: vscode.Uri[]): Promise<void> {
// The parameters of this function should not be changed without updating the compose language service which uses this command
export async function composeUp(context: IActionContext, dockerComposeFileUri?: vscode.Uri | string, selectedComposeFileUris?: vscode.Uri[]): Promise<void> {
return await compose(context, ['up'], vscode.l10n.t('Choose Docker Compose file to bring up'), dockerComposeFileUri, selectedComposeFileUris);
}

export async function composeUpSubset(context: IActionContext, dockerComposeFileUri?: vscode.Uri, selectedComposeFileUris?: vscode.Uri[]): Promise<void> {
return await compose(context, ['upSubset'], vscode.l10n.t('Choose Docker Compose file to bring up'), dockerComposeFileUri, selectedComposeFileUris);
// The parameters of this function should not be changed without updating the compose language service which uses this command
export async function composeUpSubset(context: IActionContext, dockerComposeFileUri?: vscode.Uri | string, selectedComposeFileUris?: vscode.Uri[], preselectedServices?: string[], preselectedProfiles?: string[]): Promise<void> {
return await compose(context, ['upSubset'], vscode.l10n.t('Choose Docker Compose file to bring up'), dockerComposeFileUri, selectedComposeFileUris, preselectedServices, preselectedProfiles);
}

export async function composeDown(context: IActionContext, dockerComposeFileUri?: vscode.Uri, selectedComposeFileUris?: vscode.Uri[]): Promise<void> {
Expand All @@ -90,18 +96,19 @@ export async function composeRestart(context: IActionContext, dockerComposeFileU

const serviceListPlaceholder = /\${serviceList}/i;
const profileListPlaceholder = /\${profileList}/i;
async function addServicesOrProfilesIfNeeded(context: IActionContext, workspaceFolder: vscode.WorkspaceFolder, command: string): Promise<string> {
async function addServicesOrProfilesIfNeeded(context: IActionContext, workspaceFolder: vscode.WorkspaceFolder, command: string, preselectedServices: string[], preselectedProfiles: string[]): Promise<string> {
const commandWithoutPlaceholders = command.replace(serviceListPlaceholder, '').replace(profileListPlaceholder, '');

if (serviceListPlaceholder.test(command) && profileListPlaceholder.test(command)) {
// If both are present, need to ask
const { services, profiles } = await getComposeProfilesOrServices(context, workspaceFolder, commandWithoutPlaceholders);
const { services, profiles } = await getComposeProfilesOrServices(context, workspaceFolder, commandWithoutPlaceholders, preselectedServices, preselectedProfiles);
return command
.replace(serviceListPlaceholder, services)
.replace(profileListPlaceholder, profiles);
} else if (serviceListPlaceholder.test(command)) {
return command.replace(serviceListPlaceholder, await getComposeServiceList(context, workspaceFolder, commandWithoutPlaceholders));
return command.replace(serviceListPlaceholder, await getComposeServiceList(context, workspaceFolder, commandWithoutPlaceholders, preselectedServices));
} else if (profileListPlaceholder.test(command)) {
return command.replace(profileListPlaceholder, await getComposeProfileList(context, workspaceFolder, commandWithoutPlaceholders));
return command.replace(profileListPlaceholder, await getComposeProfileList(context, workspaceFolder, commandWithoutPlaceholders, preselectedProfiles));
} else {
return command;
}
Expand Down
24 changes: 16 additions & 8 deletions src/commands/compose/getComposeSubsetList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,21 @@ const composeCommandReplaceRegex = /(\b(up|down)\b).*$/i;

type SubsetType = 'services' | 'profiles';

export async function getComposeProfilesOrServices(context: IActionContext, workspaceFolder: vscode.WorkspaceFolder, composeCommand: string): Promise<{ services: string | undefined, profiles: string | undefined }> {
export async function getComposeProfilesOrServices(context: IActionContext, workspaceFolder: vscode.WorkspaceFolder, composeCommand: string, preselectedServices?: string[], preselectedProfiles?: string[]): Promise<{ services: string | undefined, profiles: string | undefined }> {
const profiles = await getServiceSubsets(workspaceFolder, composeCommand, 'profiles');

if (preselectedServices?.length && preselectedProfiles?.length) {
throw new Error(vscode.l10n.t('Cannot specify both services and profiles to start. Please choose one or the other.'));
}

// If there any profiles, we need to ask the user whether they want profiles or services, since they are mutually exclusive to use
// Otherwise, if there are no profiles, we'll automatically assume services
let useProfiles = false;
if (profiles?.length) {
if (preselectedProfiles?.length) {
useProfiles = true;
} else if (preselectedServices?.length) {
useProfiles = false;
} else if (profiles?.length) {
const profilesOrServices: IAzureQuickPickItem<SubsetType>[] = [
{
label: vscode.l10n.t('Services'),
Expand All @@ -35,12 +43,12 @@ export async function getComposeProfilesOrServices(context: IActionContext, work
}

return {
profiles: useProfiles ? await getComposeProfileList(context, workspaceFolder, composeCommand, profiles) : '',
services: !useProfiles ? await getComposeServiceList(context, workspaceFolder, composeCommand) : '',
profiles: useProfiles ? await getComposeProfileList(context, workspaceFolder, composeCommand, profiles, preselectedProfiles) : '',
services: !useProfiles ? await getComposeServiceList(context, workspaceFolder, composeCommand, preselectedServices) : '',
};
}

export async function getComposeProfileList(context: IActionContext, workspaceFolder: vscode.WorkspaceFolder, composeCommand: string, prefetchedProfiles?: string[]): Promise<string> {
export async function getComposeProfileList(context: IActionContext, workspaceFolder: vscode.WorkspaceFolder, composeCommand: string, prefetchedProfiles?: string[], preselectedProfiles?: string[]): Promise<string> {
const profiles = prefetchedProfiles ?? await getServiceSubsets(workspaceFolder, composeCommand, 'profiles');

if (!profiles?.length) {
Expand All @@ -51,15 +59,15 @@ export async function getComposeProfileList(context: IActionContext, workspaceFo
// Fetch the previously chosen profiles list. By default, all will be selected.
const workspaceProfileListKey = `vscode-docker.composeProfiles.${workspaceFolder.name}`;
const previousChoices = ext.context.workspaceState.get<string[]>(workspaceProfileListKey, profiles);
const result = await pickSubsets(context, 'profiles', profiles, previousChoices);
const result = preselectedProfiles?.length ? preselectedProfiles : await pickSubsets(context, 'profiles', profiles, previousChoices);

// Update the cache
await ext.context.workspaceState.update(workspaceProfileListKey, result);

return result.map(p => `--profile ${p}`).join(' ');
}

export async function getComposeServiceList(context: IActionContext, workspaceFolder: vscode.WorkspaceFolder, composeCommand: string): Promise<string> {
export async function getComposeServiceList(context: IActionContext, workspaceFolder: vscode.WorkspaceFolder, composeCommand: string, preselectedServices?: string[]): Promise<string> {
const services = await getServiceSubsets(workspaceFolder, composeCommand, 'services');

if (!services?.length) {
Expand All @@ -70,7 +78,7 @@ export async function getComposeServiceList(context: IActionContext, workspaceFo
// Fetch the previously chosen services list. By default, all will be selected.
const workspaceServiceListKey = `vscode-docker.composeServices.${workspaceFolder.name}`;
const previousChoices = ext.context.workspaceState.get<string[]>(workspaceServiceListKey, services);
const result = await pickSubsets(context, 'services', services, previousChoices);
const result = preselectedServices?.length ? preselectedServices : await pickSubsets(context, 'services', services, previousChoices);

// Update the cache
await ext.context.workspaceState.update(workspaceServiceListKey, result);
Expand Down
1 change: 1 addition & 0 deletions src/utils/AlternateYamlLanguageServiceClientFeature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export class AlternateYamlLanguageServiceClientFeature implements StaticFeature,
advancedCompletions: false, // YAML extension does not have advanced completions for compose docs
hover: false, // YAML extension provides hover, but the compose spec lacks descriptions -- https://github.com/compose-spec/compose-spec/issues/138
imageLinks: false, // YAML extension does not have image hyperlinks for compose docs
serviceStartupCodeLens: false, // YAML extension does not have service startup code lens for compose docs
formatting: true,
};

Expand Down
Loading