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

refactor: updated compose onboarding installation #4479

Merged
merged 1 commit into from Oct 25, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
89 changes: 56 additions & 33 deletions extensions/compose/package.json
Expand Up @@ -21,32 +21,32 @@
"title": "Compose: Checks..."
},
{
"command": "compose.onboarding.checkComposeInstalled",
"title": "Compose: Check Compose installation"
"command": "compose.onboarding.checkComposeDownloaded",
"title": "Compose: Check Compose Downloaded"
},
{
"command": "compose.onboarding.installCompose",
"title": "Compose: Install Compose"
"command": "compose.onboarding.downloadCompose",
"title": "Compose: Download Compose"
}
],
"onboarding": {
"title": "Compose Setup",
"enablement": "!compose.isComposeInstalledSystemWide",
"steps": [
{
"id": "checkComposeInstalled",
"id": "checkComposeDownloaded",
"label": "Check Compose",
"title": "Checking for Compose installation",
"command": "compose.onboarding.checkComposeInstalled",
"command": "compose.onboarding.checkComposeDownloaded",
"completionEvents": [
"onCommand:compose.onboarding.checkComposeInstalled"
"onCommand:compose.onboarding.checkComposeDownloaded"
]
},
{
"id": "startComposeInstallation",
"label": "Compose Installation",
"title": "Compose Installation",
"when": "onboardingContext:composeIsNotInstalled == true",
"id": "startComposeDownload",
"label": "Compose Download",
"title": "Compose Download",
"when": "onboardingContext:composeIsNotDownloaded == true",
"content": [
[
{
Expand All @@ -55,55 +55,78 @@
],
[
{
"value": "#### How to use Compose\nRun `podman compose up` (podman CLI v4.7.0+) in a directory with a `compose.yaml` for Podman to deploy the containers. Podman Desktop will automatically detect the Compose deployment and show it in the container list. \n\n> ℹ️ Note: If you would like to use docker tools such as: `docker compose up` or `docker-compose` with podman. Enable **Docker Compatibility** within Preferences.",
"value": "> ℹ️ Note: Want to use docker CLI tools such as: `docker compose up` or `docker-compose` with podman? Enable **Docker Compatibility** within Preferences.",
"highlight": true
}
],
[
{
"value": "Compose will be installed in the next step (Version ${onboardingContext:composeInstallVersion}). :link[Want to install a different version?]{command=compose.onboarding.promptUserForVersion}",
"when": "!onboardingContext:composeShowCustomInstallDialog"
"value": "Compose will be downloaded in the next step (Version ${onboardingContext:composeDownloadVersion}). :link[Want to download a different version?]{command=compose.onboarding.promptUserForVersion}",
"when": "!onboardingContext:composeShowCustomDownloadDialog"
}
]
]
},
{
"id": "installComposeView",
"title": "Installing Compose ${onboardingContext:composeInstallVersion}",
"description": "Downloading and installing the binary.\n\nOnce installed, we will enable and configure the extension.",
"when": "onboardingContext:composeIsNotInstalled == true",
"command": "compose.onboarding.installCompose",
"id": "downloadComposeView",
"title": "Downloading Compose ${onboardingContext:composeDownloadVersion}",
"description": "Downloading the binary.\n\nOnce downloaded, the next step will install Compose system-wide.",
"when": "onboardingContext:composeIsNotDownloaded == true",
"command": "compose.onboarding.downloadCompose",
"completionEvents": [
"onCommand:compose.onboarding.installCompose"
"onCommand:compose.onboarding.downloadCompose"
]
},
{
"id": "composeFailedInstallation",
"title": "Failed installing Compose",
"when": "onboardingContext:composeIsNotInstalled == true",
"id": "composeFailedDownload",
"title": "Failed Downloading Compose",
"when": "onboardingContext:composeIsNotDownloaded == true",
"state": "failed"
},
{
"id": "composeInstalled",
"title": "Compose successfully installed",
"when": "onboardingContext:composeIsNotInstalled == false",
"id": "composeDownloaded",
"title": "Compose Successfully Downloaded",
"when": "onboardingContext:composeIsNotDownloaded == false",
"state": "succeeded",
"content": [
[
{
"value": "Compose has been successfully installed! However, in order for `podman compose` (podman CLI v4.7.0+) to work correctly, it is required for Compose to be installed system-wide for `podman` to access the binary.",
"when": "!compose.isComposeInstalledSystemWide"
"value": "Compose has been successfully downloaded! In order for `podman compose` (podman CLI v4.7.0+) to work correctly, it is required for Compose to be installed system-wide for `podman` to access the binary.\n\nThe next step will install Compose system-wide. **You will be prompted for system privileges when enabling this.**"
}
],
]
]
},
{
"id": "installComposeSystemWide",
"title": "Install Compose",
"description": "Installing the binary system-wide.\n\n You may be prompted for elevated system privileges.",
"when": "compose.isComposeInstalledSystemWide == false",
"command": "compose.onboarding.installSystemWide",
"completionEvents": [
"onCommand:compose.onboarding.installSystemWide"
]
},
{
"id": "composeFailedInstalledSystemWide",
"title": "Failed Installing Compose",
"when": "compose.isComposeInstalledSystemWide == false",
"state": "failed"
},
{
"id": "composeInstalledSystemWide",
"title": "Compose Successfully Installed",
"when": "compose.isComposeInstalledSystemWide == true",
"state": "succeeded",
"content": [
[
{
"value": "${configuration:compose.binary.installComposeSystemWide}",
"when": "!compose.isComposeInstalledSystemWide"
"value": "Compose has been successfully installed system-wide!"
}
],
[
{
"value": "> ℹ️ Note on `docker`: If you are using docker CLI tools with a podman back-end you must enable **Docker Compatibility** within **Preferences -> Extension: Podman** or set the [DOCKER_HOST](https://podman-desktop.io/docs/migrating-from-docker/using-the-docker_host-environment-variable) environment variable before running `docker compose up` or `docker-compose up`."
"value": "#### How to use Compose\nRun `podman compose up` (podman CLI v4.7.0+) or `docker-compose` in a directory with a `compose.yaml`. Podman Desktop will automatically detect the Compose deployment and show it in the container list.'\n\n`$ podman compose up`",
"highlight": true
}
]
]
Expand All @@ -118,7 +141,7 @@
"default": false,
"scope": ["DEFAULT", "Onboarding"],
"hidden": true,
"description": "Install system-wide instead of just your user directory, so compose can be accessed on the command line. Note: You will be prompted for system privileges when enabling this. "
"description": "Install system-wide instead of just your user directory, so compose can be accessed on the command line. Note: You may be prompted for elevated system privileges when enabling this."
}
}
}
Expand Down
Expand Up @@ -20,7 +20,7 @@ import { afterEach, expect, test, vi } from 'vitest';
import type { ComposeGitHubReleases, ComposeGithubReleaseArtifactMetadata } from './compose-github-releases';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { ComposeInstallation } from './installation';
import { ComposeDownload } from './download';
import * as extensionApi from '@podman-desktop/api';
import { OS } from './os';
import * as utils from './utils';
Expand Down Expand Up @@ -87,8 +87,8 @@ test('expect getLatestVersionAsset to return the first release from a list of re
});

// Expect the test to return the first release from the list (as the function simply returns the first one)
const composeInstallation = new ComposeInstallation(extensionContext, composeGitHubReleasesMock, os);
const result = await composeInstallation.getLatestVersionAsset();
const composeDownload = new ComposeDownload(extensionContext, composeGitHubReleasesMock, os);
const result = await composeDownload.getLatestVersionAsset();
expect(result).toBeDefined();
expect(result).toEqual(releases[0]);
});
Expand All @@ -103,13 +103,13 @@ test('pick the 4th option option in the quickpickmenu and expect it to return th
showQuickPickMock.mockResolvedValue({ id: 86626999, label: 'v2.14.2', tag: 'v2.14.2' } as any);

// Expect the test to return the first release from the list (as the function simply returns the first one)
const composeInstallation = new ComposeInstallation(extensionContext, composeGitHubReleasesMock, os);
const result = await composeInstallation.promptUserForVersion();
const composeDownload = new ComposeDownload(extensionContext, composeGitHubReleasesMock, os);
const result = await composeDownload.promptUserForVersion();
expect(result).toBeDefined();
expect(result).toEqual(releases[3]); // "4th" option was picked
});

test('test installation of compose passes and that mkdir and executable mocks are called', async () => {
test('test download of compose passes and that mkdir and executable mocks are called', async () => {
const makeExecutableMock = vi.spyOn(utils, 'makeExecutable');
const mkdirMock = vi.spyOn(fs.promises, 'mkdir');
const getReleaseAssetIdMock = vi.spyOn(composeGitHubReleasesMock, 'getReleaseAssetId');
Expand All @@ -128,9 +128,9 @@ test('test installation of compose passes and that mkdir and executable mocks ar
getReleaseAssetIdMock.mockResolvedValue(123456789);
downloadReleaseAssetMock.mockResolvedValue(undefined);

// Simply install the first release from the example json list
const composeInstallation = new ComposeInstallation(extensionContext, composeGitHubReleasesMock, os);
await composeInstallation.install(releases[0]);
// Simply download the first release from the example json list
const composeDownload = new ComposeDownload(extensionContext, composeGitHubReleasesMock, os);
await composeDownload.download(releases[0]);

// Expect the mkdir and executables to have been called
expect(mkdirMock).toHaveBeenCalled();
Expand Down
Expand Up @@ -24,7 +24,7 @@ import type { OS } from './os';
import { platform, arch } from 'node:os';
import { makeExecutable } from './utils';

export class ComposeInstallation {
export class ComposeDownload {
constructor(
private readonly extensionContext: extensionApi.ExtensionContext,
private readonly composeGitHubReleases: ComposeGitHubReleases,
Expand All @@ -38,14 +38,14 @@ export class ComposeInstallation {
return latestReleases[0];
}

// Create a "quickpick" prompt to ask the user which version of Compose they want to install
// Create a "quickpick" prompt to ask the user which version of Compose they want to download
async promptUserForVersion(): Promise<ComposeGithubReleaseArtifactMetadata> {
// Get the latest releases
const lastReleasesMetadata = await this.composeGitHubReleases.grabLatestsReleasesMetadata();

// Show the quickpick
const selectedRelease = await extensionApi.window.showQuickPick(lastReleasesMetadata, {
placeHolder: 'Select Compose version to install',
placeHolder: 'Select Compose version to download',
});

if (selectedRelease) {
Expand All @@ -55,12 +55,13 @@ export class ComposeInstallation {
}
}

// Install compose from the artifact metadata: ComposeGithubReleaseArtifactMetadata
async install(release: ComposeGithubReleaseArtifactMetadata): Promise<void> {
// Download compose from the artifact metadata: ComposeGithubReleaseArtifactMetadata
// this will download it to the storage bin folder as well as make it executeable
async download(release: ComposeGithubReleaseArtifactMetadata): Promise<void> {
// Get asset id
const assetId = await this.composeGitHubReleases.getReleaseAssetId(release.id, platform(), arch());

// Get the storage and check to see if it exists before we install Compose
// Get the storage and check to see if it exists before we download Compose
const storageData = this.extensionContext.storagePath;
const storageBinFolder = path.resolve(storageData, 'bin');
if (!existsSync(storageBinFolder)) {
Expand Down