mirror of
https://github.com/podman-desktop/podman-desktop
synced 2026-04-21 17:47:22 +00:00
feat(extension/podman): switch to podman msi installer (#15441)
* feat(extension/podman): switch to podman msi installer Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com> * revert: unnecessary change to package.json Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com> --------- Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com>
This commit is contained in:
parent
640cb36a64
commit
76ec5159cd
9 changed files with 89 additions and 44 deletions
|
|
@ -157,11 +157,11 @@ const config = {
|
|||
});
|
||||
// add podman installer
|
||||
if (context.arch === Arch.x64) {
|
||||
context.packager.config.extraResources.push(`${PODMAN_EXTENSION_ASSETS}/podman-installer-windows-amd64.exe`);
|
||||
context.packager.config.extraResources.push(`${PODMAN_EXTENSION_ASSETS}/podman-installer-windows-amd64.msi`);
|
||||
context.packager.config.extraResources.push(`${PODMAN_EXTENSION_ASSETS}/podman-image-x64.zst`);
|
||||
}
|
||||
if (context.arch === Arch.arm64) {
|
||||
context.packager.config.extraResources.push(`${PODMAN_EXTENSION_ASSETS}/podman-installer-windows-arm64.exe`);
|
||||
context.packager.config.extraResources.push(`${PODMAN_EXTENSION_ASSETS}/podman-installer-windows-arm64.msi`);
|
||||
context.packager.config.extraResources.push(`${PODMAN_EXTENSION_ASSETS}/podman-image-arm64.zst`);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,10 +33,10 @@ const mockedPodman5 = {
|
|||
version: 'v5.0.0',
|
||||
arch: {
|
||||
x64: {
|
||||
fileName: 'podman-installer-windows-amd64.exe',
|
||||
fileName: 'podman-installer-windows-amd64.msi',
|
||||
},
|
||||
arm64: {
|
||||
fileName: 'podman-installer-windows-arm64.exe',
|
||||
fileName: 'podman-installer-windows-arm64.msi',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -231,13 +231,13 @@ describe('windows platform', () => {
|
|||
// check called with the correct parameters
|
||||
expect(downloadAndCheckShaSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining(`v${podman5JSON.version}`),
|
||||
expect.stringContaining('podman-installer-windows-amd64.exe'),
|
||||
'podman-installer-windows-amd64.exe',
|
||||
expect.stringContaining('podman-installer-windows-amd64.msi'),
|
||||
'podman-installer-windows-amd64.msi',
|
||||
);
|
||||
expect(downloadAndCheckShaSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining(`v${podman5JSON.version}`),
|
||||
expect.stringContaining('podman-installer-windows-arm64.exe'),
|
||||
'podman-installer-windows-arm64.exe',
|
||||
expect.stringContaining('podman-installer-windows-arm64.msi'),
|
||||
'podman-installer-windows-arm64.msi',
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -262,16 +262,16 @@ describe('windows platform', () => {
|
|||
expect(downloadAndCheckShaSpy).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'v5.0.0',
|
||||
'podman-installer-windows-amd64.exe',
|
||||
'podman-installer-windows-amd64.exe',
|
||||
'podman-installer-windows-amd64.msi',
|
||||
'podman-installer-windows-amd64.msi',
|
||||
);
|
||||
|
||||
// check called with the correct parameters for arm64 installer
|
||||
expect(downloadAndCheckShaSpy).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
'v5.0.0',
|
||||
'podman-installer-windows-arm64.exe',
|
||||
'podman-installer-windows-arm64.exe',
|
||||
'podman-installer-windows-arm64.msi',
|
||||
'podman-installer-windows-arm64.msi',
|
||||
);
|
||||
|
||||
// check no airgap download
|
||||
|
|
|
|||
|
|
@ -105,13 +105,13 @@ export class PodmanDownload {
|
|||
this.#artifactsToDownload.push({
|
||||
version: tagVersion,
|
||||
downloadName: downloadNameAmd64,
|
||||
artifactName: 'podman-installer-windows-amd64.exe',
|
||||
artifactName: 'podman-installer-windows-amd64.msi',
|
||||
});
|
||||
const downloadNameArm64 = podmanJSON.platform.win32.arch.arm64.fileName;
|
||||
this.#artifactsToDownload.push({
|
||||
version: tagVersion,
|
||||
downloadName: downloadNameArm64,
|
||||
artifactName: 'podman-installer-windows-arm64.exe',
|
||||
artifactName: 'podman-installer-windows-arm64.msi',
|
||||
});
|
||||
} else if (this.#platform === 'darwin') {
|
||||
const tagVersion = podmanJSON.platform.darwin.version;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*********************************************************************
|
||||
* Copyright (C) 2025 Red Hat, Inc.
|
||||
* Copyright (C) 2025-2026 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -28,7 +28,7 @@ import { getAssetsFolder } from '/@/utils/util';
|
|||
|
||||
import { WinInstaller } from './win-installer';
|
||||
|
||||
vi.mock('node:fs');
|
||||
vi.mock(import('node:fs'));
|
||||
|
||||
const extensionContext = {
|
||||
subscriptions: [],
|
||||
|
|
@ -41,7 +41,10 @@ const progress = {
|
|||
|
||||
const mockTelemetryLogger = {} as TelemetryLogger;
|
||||
const mockWinPlatform = {} as WinPlatform;
|
||||
const legacyInstaller = {} as PodmanWindowsLegacyInstaller;
|
||||
const legacyInstaller = {
|
||||
isInstalled: vi.fn(),
|
||||
uninstall: vi.fn(),
|
||||
} as unknown as PodmanWindowsLegacyInstaller;
|
||||
|
||||
vi.mock(import('/@/utils/util'), () => ({
|
||||
getAssetsFolder: vi.fn(),
|
||||
|
|
@ -101,3 +104,15 @@ test('expect update on windows to throw error if non zero exit code', async () =
|
|||
expect(result).toBeFalsy();
|
||||
expect(extensionApi.window.showErrorMessage).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('expect update to uninstall legacy installer if detected', async () => {
|
||||
vi.mocked(legacyInstaller.isInstalled).mockResolvedValue(true);
|
||||
|
||||
vi.mocked(existsSync).mockReturnValue(true);
|
||||
vi.mocked(readdirSync).mockReturnValue([]);
|
||||
|
||||
const result = await installer.update();
|
||||
expect(result).toBeTruthy();
|
||||
|
||||
expect(legacyInstaller.uninstall).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -62,7 +62,11 @@ export class WinInstaller extends BaseInstaller {
|
|||
return this.winPlatform.getPreflightChecks();
|
||||
}
|
||||
|
||||
update(): Promise<boolean> {
|
||||
async update(): Promise<boolean> {
|
||||
if (await this.legacyPodmanInstaller.isInstalled()) {
|
||||
await this.legacyPodmanInstaller.uninstall();
|
||||
}
|
||||
|
||||
return this.install();
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +81,8 @@ export class WinInstaller extends BaseInstaller {
|
|||
try {
|
||||
if (fs.existsSync(setupPath)) {
|
||||
try {
|
||||
await processAPI.exec(setupPath, ['/install', '/norestart']);
|
||||
progress.report({ message: `Installing ${fileName}` });
|
||||
await processAPI.exec('msiexec', ['/package', setupPath]);
|
||||
progress.report({ increment: 80 });
|
||||
window.showNotification({ body: 'Podman is successfully installed.' });
|
||||
} catch (err) {
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
"version": "v5.7.1",
|
||||
"arch": {
|
||||
"x64": {
|
||||
"fileName": "podman-installer-windows-amd64.exe"
|
||||
"fileName": "podman-installer-windows-amd64.msi"
|
||||
},
|
||||
"arm64": {
|
||||
"fileName": "podman-installer-windows-arm64.exe"
|
||||
"fileName": "podman-installer-windows-arm64.msi"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
import type { ChildProcess, ChildProcessWithoutNullStreams } from 'node:child_process';
|
||||
import { spawn } from 'node:child_process';
|
||||
import { homedir, platform } from 'node:os';
|
||||
import { delimiter, join } from 'node:path';
|
||||
import type { Readable } from 'node:stream';
|
||||
|
||||
import * as sudo from '@expo/sudo-prompt';
|
||||
|
|
@ -577,35 +579,52 @@ describe('getInstallationPath', () => {
|
|||
process.env['PATH'] = originalPath;
|
||||
});
|
||||
|
||||
test('should return the installation path for Windows', () => {
|
||||
vi.spyOn(util, 'isWindows').mockImplementation(() => true);
|
||||
vi.spyOn(util, 'isMac').mockImplementation(() => false);
|
||||
process.env['PATH'] = '';
|
||||
describe(
|
||||
'windows',
|
||||
{
|
||||
// as the getInstallationPath is using `node:path` and it is platform specific
|
||||
// we cannot assert on non-windows platforms properly
|
||||
skip: platform() !== 'win32',
|
||||
},
|
||||
() => {
|
||||
beforeEach(() => {
|
||||
vi.spyOn(util, 'isWindows').mockImplementation(() => true);
|
||||
vi.spyOn(util, 'isMac').mockImplementation(() => false);
|
||||
});
|
||||
|
||||
const path = getInstallationPath();
|
||||
test('should return the installation paths for Windows', () => {
|
||||
process.env['PATH'] = '';
|
||||
|
||||
expect(path).toBe('c:\\Program Files\\RedHat\\Podman;');
|
||||
});
|
||||
const path = getInstallationPath();
|
||||
|
||||
test('should return the installation path for Windows with pre-filled PATH', () => {
|
||||
vi.spyOn(util, 'isWindows').mockImplementation(() => true);
|
||||
vi.spyOn(util, 'isMac').mockImplementation(() => false);
|
||||
process.env['PATH'] = 'c:\\Local';
|
||||
const parts = path.split(delimiter);
|
||||
expect(parts).toContain(join(homedir(), 'AppData', 'Local', 'Programs', 'Podman'));
|
||||
expect(parts).toContain('c:\\Program Files\\RedHat\\Podman');
|
||||
});
|
||||
|
||||
const path = getInstallationPath();
|
||||
test('should return the installation paths for Windows with pre-filled PATH', () => {
|
||||
process.env['PATH'] = 'c:\\Local';
|
||||
|
||||
expect(path).toBe('c:\\Program Files\\RedHat\\Podman;c:\\Local');
|
||||
});
|
||||
const path = getInstallationPath();
|
||||
|
||||
test('should return the installation path for Windows with defined param', () => {
|
||||
vi.spyOn(util, 'isWindows').mockImplementation(() => true);
|
||||
vi.spyOn(util, 'isMac').mockImplementation(() => false);
|
||||
process.env['PATH'] = 'c:\\Local';
|
||||
const parts = path.split(delimiter);
|
||||
expect(parts).toContain(join(homedir(), 'AppData', 'Local', 'Programs', 'Podman'));
|
||||
expect(parts).toContain('c:\\Program Files\\RedHat\\Podman');
|
||||
expect(parts).toContain('c:\\Local');
|
||||
});
|
||||
|
||||
const path = getInstallationPath('c:\\Directory');
|
||||
test('should return the installation paths for Windows with defined param', () => {
|
||||
process.env['PATH'] = 'c:\\Local';
|
||||
|
||||
expect(path).toBe('c:\\Program Files\\RedHat\\Podman;c:\\Directory');
|
||||
});
|
||||
const path = getInstallationPath('c:\\Directory');
|
||||
|
||||
const parts = path.split(delimiter);
|
||||
expect(parts).toContain(join(homedir(), 'AppData', 'Local', 'Programs', 'Podman'));
|
||||
expect(parts).toContain('c:\\Program Files\\RedHat\\Podman');
|
||||
expect(parts).toContain('c:\\Directory');
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test('should return the installation path for macOS', () => {
|
||||
vi.spyOn(util, 'isWindows').mockImplementation(() => false);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
import type { ChildProcessWithoutNullStreams } from 'node:child_process';
|
||||
import { spawn } from 'node:child_process';
|
||||
import { homedir } from 'node:os';
|
||||
import { delimiter, join } from 'node:path';
|
||||
|
||||
import * as sudo from '@expo/sudo-prompt';
|
||||
import type { RunError, RunOptions, RunResult } from '@podman-desktop/api';
|
||||
|
|
@ -248,7 +250,11 @@ export function getInstallationPath(envPATH?: string): string {
|
|||
envPATH ??= process.env['PATH'];
|
||||
|
||||
if (isWindows()) {
|
||||
return `c:\\Program Files\\RedHat\\Podman;${envPATH}`;
|
||||
return [
|
||||
join(homedir(), 'AppData', 'Local', 'Programs', 'Podman'),
|
||||
'c:\\Program Files\\RedHat\\Podman',
|
||||
envPATH ?? '',
|
||||
].join(delimiter);
|
||||
} else if (isMac()) {
|
||||
if (!envPATH) {
|
||||
return macosExtraPath;
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ test.describe.serial('Podman installer integration in Podman Desktop', { tag: '@
|
|||
await playExpect(podmanCliNotFoundText).toBeVisible();
|
||||
});
|
||||
test('Podman installer artifacts are present in local assets storage', async ({ runner }) => {
|
||||
const fileFormatRegexp = isWindows ? 'exe' : 'pkg';
|
||||
const fileFormatRegexp = isWindows ? 'msi' : 'pkg';
|
||||
// x64 = amd64 for both windows and mac, arm64 = arm64 for win, and aarch64 for mac
|
||||
const archPart = process.arch === 'x64' ? 'amd64' : process.arch === 'arm64' ? (isMac ? 'aarch64' : 'arm64') : null;
|
||||
playExpect(archPart, { message: `Unsupported architecture: ${process.arch}` }).not.toBeNull();
|
||||
|
|
|
|||
Loading…
Reference in a new issue