fix: install latest compose as fallback

This commit is contained in:
Joao Pargana 2025-12-08 20:26:21 +00:00 committed by Emilien Escalle
parent bb5664383c
commit c36b7c122a
3 changed files with 165 additions and 17 deletions

23
dist/index.js generated vendored
View File

@ -47949,22 +47949,29 @@ class DockerComposeInstallerService {
this.manualInstallerAdapter = manualInstallerAdapter;
}
async install({ composeVersion, cwd, githubToken }) {
const currentVersion = await this.version({ cwd });
if (!composeVersion) {
const currentVersion = await this.getInstalledVersion(cwd);
const needsInstall = !currentVersion || (composeVersion && composeVersion !== currentVersion);
if (!needsInstall) {
return currentVersion;
}
if (currentVersion === composeVersion) {
return currentVersion;
}
if (composeVersion === COMPOSE_VERSION_LATEST) {
let targetVersion = composeVersion || COMPOSE_VERSION_LATEST;
if (targetVersion === COMPOSE_VERSION_LATEST) {
if (!githubToken) {
throw new Error("GitHub token is required to install the latest version");
}
composeVersion = await this.getLatestVersion(githubToken);
targetVersion = await this.getLatestVersion(githubToken);
}
await this.installVersion(composeVersion);
await this.installVersion(targetVersion);
return this.version({ cwd });
}
async getInstalledVersion(cwd) {
try {
return await this.version({ cwd });
}
catch {
return null;
}
}
async version({ cwd }) {
const result = await (0,dist.version)({
cwd,

View File

@ -30,7 +30,7 @@ describe("DockerComposeInstallerService", () => {
});
afterEach(() => {
jest.clearAllMocks();
jest.resetAllMocks();
});
describe("install", () => {
@ -234,5 +234,139 @@ describe("DockerComposeInstallerService", () => {
expect(manualInstallerAdapterMock.install).not.toHaveBeenCalled();
});
it("should install when version check fails", async () => {
// Arrange: first call to version() doesn't find
versionMock.mockRejectedValueOnce(new Error("version not installed"));
const installedVersion = "2.0.0";
// After installation, version() returns the new version
versionMock.mockResolvedValueOnce({
exitCode: 0,
out: "",
err: "",
data: {
version: installedVersion,
},
});
Object.defineProperty(process, "platform", {
value: "linux",
});
// Act
const result = await service.install({
composeVersion: installedVersion,
cwd: "/path/to/cwd",
githubToken: "token",
});
// Assert
expect(result).toBe(installedVersion);
expect(manualInstallerAdapterMock.install).toHaveBeenCalledWith(installedVersion);
});
it("should install latest version when missing or unspecified", async () => {
// Arrange: first call to version() doesn't find
versionMock.mockRejectedValueOnce(new Error("version check failed"));
// second call finds newly installed version
versionMock.mockResolvedValueOnce({
exitCode: 0,
out: "",
err: "",
data: {
version: "v1.4.0",
},
});
const latestVersion = "v1.4.0";
const mockClient = mockAgent.get("https://api.github.com");
mockClient
.intercept({
path: "/repos/docker/compose/releases/latest",
method: "GET",
})
.reply(
200,
{
tag_name: latestVersion,
},
{
headers: {
"content-type": "application/json",
},
}
);
setGlobalDispatcher(mockClient);
versionMock.mockResolvedValueOnce({
exitCode: 0,
out: "",
err: "",
data: {
version: latestVersion,
},
});
Object.defineProperty(process, "platform", {
value: "linux",
});
Object.defineProperty(globalThis, "fetch", {
value: jest.fn(),
});
// Act
const result = await service.install({
composeVersion: "latest",
cwd: "/path/to/cwd",
githubToken: "token",
});
// Assert
expect(result).toBe(latestVersion);
expect(manualInstallerAdapterMock.install).toHaveBeenCalledWith(latestVersion);
});
it("should throw if Compose is missing and no GitHub token is provided", async () => {
// Arrange: first call to version() doesn't find
versionMock.mockRejectedValueOnce(new Error("version check failed"));
Object.defineProperty(process, "platform", {
value: "linux",
});
await expect(
service.install({
composeVersion: "latest",
cwd: "/path/to/cwd",
githubToken: null,
})
).rejects.toThrow("GitHub token is required to install the latest version");
});
it("should not install when the version is already installed and no version is specified", async () => {
// Arrange
versionMock.mockResolvedValue({
exitCode: 0,
out: "",
err: "",
data: {
version: "1.2.3",
},
});
// Act
const result = await service.install({
composeVersion: "",
cwd: "/path/to/cwd",
githubToken: null,
});
// Assert
expect(result).toBe("1.2.3");
expect(manualInstallerAdapterMock.install).not.toHaveBeenCalled();
});
});
});

View File

@ -17,28 +17,35 @@ export class DockerComposeInstallerService {
constructor(private readonly manualInstallerAdapter: ManualInstallerAdapter) {}
async install({ composeVersion, cwd, githubToken }: InstallInputs): Promise<string> {
const currentVersion = await this.version({ cwd });
const currentVersion = await this.getInstalledVersion(cwd);
if (!composeVersion) {
const needsInstall = !currentVersion || (composeVersion && composeVersion !== currentVersion);
if (!needsInstall) {
return currentVersion;
}
if (currentVersion === composeVersion) {
return currentVersion;
}
let targetVersion = composeVersion || COMPOSE_VERSION_LATEST;
if (composeVersion === COMPOSE_VERSION_LATEST) {
if (targetVersion === COMPOSE_VERSION_LATEST) {
if (!githubToken) {
throw new Error("GitHub token is required to install the latest version");
}
composeVersion = await this.getLatestVersion(githubToken);
targetVersion = await this.getLatestVersion(githubToken);
}
await this.installVersion(composeVersion);
await this.installVersion(targetVersion);
return this.version({ cwd });
}
private async getInstalledVersion(cwd: string): Promise<string | null> {
try {
return await this.version({ cwd });
} catch {
return null;
}
}
private async version({ cwd }: VersionInputs): Promise<string> {
const result = await version({
cwd,