-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
Merge pull request #564 from crazy-max/compose-install
compose install
Showing
8 changed files
with
618 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/** | ||
* Copyright 2025 actions-toolkit authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import {describe, expect, it, jest, test, afterEach} from '@jest/globals'; | ||
import fs from 'fs'; | ||
import os from 'os'; | ||
import path from 'path'; | ||
import * as rimraf from 'rimraf'; | ||
import * as semver from 'semver'; | ||
|
||
import {Context} from '../../src/context'; | ||
import {Exec} from '../../src/exec'; | ||
|
||
import {Compose} from '../../src/compose/compose'; | ||
|
||
const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'compose-compose-')); | ||
const tmpName = path.join(tmpDir, '.tmpname-jest'); | ||
|
||
jest.spyOn(Context, 'tmpDir').mockImplementation((): string => { | ||
fs.mkdirSync(tmpDir, {recursive: true}); | ||
return tmpDir; | ||
}); | ||
|
||
jest.spyOn(Context, 'tmpName').mockImplementation((): string => { | ||
return tmpName; | ||
}); | ||
|
||
afterEach(() => { | ||
rimraf.sync(tmpDir); | ||
}); | ||
|
||
describe('isAvailable', () => { | ||
it('docker cli', async () => { | ||
const execSpy = jest.spyOn(Exec, 'getExecOutput'); | ||
const compose = new Compose({ | ||
standalone: false | ||
}); | ||
await compose.isAvailable(); | ||
// eslint-disable-next-line jest/no-standalone-expect | ||
expect(execSpy).toHaveBeenCalledWith(`docker`, ['compose'], { | ||
silent: true, | ||
ignoreReturnCode: true | ||
}); | ||
}); | ||
it('standalone', async () => { | ||
const execSpy = jest.spyOn(Exec, 'getExecOutput'); | ||
const compose = new Compose({ | ||
standalone: true | ||
}); | ||
await compose.isAvailable(); | ||
// eslint-disable-next-line jest/no-standalone-expect | ||
expect(execSpy).toHaveBeenCalledWith(`compose`, [], { | ||
silent: true, | ||
ignoreReturnCode: true | ||
}); | ||
}); | ||
}); | ||
|
||
describe('printVersion', () => { | ||
it('docker cli', async () => { | ||
const execSpy = jest.spyOn(Exec, 'exec'); | ||
const compose = new Compose({ | ||
standalone: false | ||
}); | ||
await compose.printVersion(); | ||
expect(execSpy).toHaveBeenCalledWith(`docker`, ['compose', 'version'], { | ||
failOnStdErr: false | ||
}); | ||
}); | ||
it('standalone', async () => { | ||
const execSpy = jest.spyOn(Exec, 'exec'); | ||
const compose = new Compose({ | ||
standalone: true | ||
}); | ||
await compose.printVersion(); | ||
expect(execSpy).toHaveBeenCalledWith(`compose`, ['version'], { | ||
failOnStdErr: false | ||
}); | ||
}); | ||
}); | ||
|
||
describe('version', () => { | ||
it('valid', async () => { | ||
const compose = new Compose(); | ||
expect(semver.valid(await compose.version())).not.toBeUndefined(); | ||
}); | ||
}); | ||
|
||
describe('parseVersion', () => { | ||
// prettier-ignore | ||
test.each([ | ||
['Docker Compose version v2.31.0', '2.31.0'], | ||
])('given %p', async (stdout, expected) => { | ||
expect(Compose.parseVersion(stdout)).toEqual(expected); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/** | ||
* Copyright 2025 actions-toolkit authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import {describe, expect, test} from '@jest/globals'; | ||
import * as fs from 'fs'; | ||
|
||
import {Install} from '../../src/compose/install'; | ||
|
||
const maybe = !process.env.GITHUB_ACTIONS || (process.env.GITHUB_ACTIONS === 'true' && process.env.ImageOS && process.env.ImageOS.startsWith('ubuntu')) ? describe : describe.skip; | ||
|
||
maybe('download', () => { | ||
// prettier-ignore | ||
test.each(['latest'])( | ||
'install compose %s', async (version) => { | ||
await expect((async () => { | ||
const install = new Install({ | ||
standalone: true | ||
}); | ||
const toolPath = await install.download(version); | ||
if (!fs.existsSync(toolPath)) { | ||
throw new Error('toolPath does not exist'); | ||
} | ||
const binPath = await install.installStandalone(toolPath); | ||
if (!fs.existsSync(binPath)) { | ||
throw new Error('binPath does not exist'); | ||
} | ||
})()).resolves.not.toThrow(); | ||
}, 60000); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
/** | ||
* Copyright 2025 actions-toolkit authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import {describe, expect, it, jest, test, afterEach} from '@jest/globals'; | ||
import fs from 'fs'; | ||
import os from 'os'; | ||
import path from 'path'; | ||
import * as rimraf from 'rimraf'; | ||
import osm = require('os'); | ||
|
||
import {Install} from '../../src/compose/install'; | ||
|
||
const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'compose-install-')); | ||
|
||
afterEach(function () { | ||
rimraf.sync(tmpDir); | ||
}); | ||
|
||
describe('download', () => { | ||
// prettier-ignore | ||
test.each([ | ||
['v2.31.0', false], | ||
['v2.32.4', true], | ||
['latest', true] | ||
])( | ||
'acquires %p of compose (standalone: %p)', async (version, standalone) => { | ||
const install = new Install({standalone: standalone}); | ||
const toolPath = await install.download(version); | ||
expect(fs.existsSync(toolPath)).toBe(true); | ||
let composeBin: string; | ||
if (standalone) { | ||
composeBin = await install.installStandalone(toolPath, tmpDir); | ||
} else { | ||
composeBin = await install.installPlugin(toolPath, tmpDir); | ||
} | ||
expect(fs.existsSync(composeBin)).toBe(true); | ||
}, | ||
100000 | ||
); | ||
|
||
// prettier-ignore | ||
test.each([ | ||
// following versions are already cached to htc from previous test cases | ||
['v2.31.0'], | ||
['v2.32.4'], | ||
])( | ||
'acquires %p of compose with cache', async (version) => { | ||
const install = new Install({standalone: false}); | ||
const toolPath = await install.download(version); | ||
expect(fs.existsSync(toolPath)).toBe(true); | ||
}); | ||
|
||
// prettier-ignore | ||
test.each([ | ||
['v2.27.1'], | ||
['v2.28.0'], | ||
])( | ||
'acquires %p of compose without cache', async (version) => { | ||
const install = new Install({standalone: false}); | ||
const toolPath = await install.download(version, true); | ||
expect(fs.existsSync(toolPath)).toBe(true); | ||
}); | ||
|
||
// TODO: add tests for arm | ||
// prettier-ignore | ||
test.each([ | ||
['win32', 'x64'], | ||
['win32', 'arm64'], | ||
['darwin', 'x64'], | ||
['darwin', 'arm64'], | ||
['linux', 'x64'], | ||
['linux', 'arm64'], | ||
['linux', 'ppc64'], | ||
['linux', 's390x'], | ||
])( | ||
'acquires compose for %s/%s', async (os, arch) => { | ||
jest.spyOn(osm, 'platform').mockImplementation(() => os as NodeJS.Platform); | ||
jest.spyOn(osm, 'arch').mockImplementation(() => arch); | ||
const install = new Install(); | ||
const composeBin = await install.download('latest'); | ||
expect(fs.existsSync(composeBin)).toBe(true); | ||
}, | ||
100000 | ||
); | ||
}); | ||
|
||
describe('getDownloadVersion', () => { | ||
it('returns latest download version', async () => { | ||
const version = await Install.getDownloadVersion('latest'); | ||
expect(version.version).toEqual('latest'); | ||
expect(version.downloadURL).toEqual('https://github.com/docker/compose/releases/download/v%s/%s'); | ||
expect(version.releasesURL).toEqual('https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/compose-releases.json'); | ||
}); | ||
it('returns v2.24.3 download version', async () => { | ||
const version = await Install.getDownloadVersion('v2.24.3'); | ||
expect(version.version).toEqual('v2.24.3'); | ||
expect(version.downloadURL).toEqual('https://github.com/docker/compose/releases/download/v%s/%s'); | ||
expect(version.releasesURL).toEqual('https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/compose-releases.json'); | ||
}); | ||
}); | ||
|
||
describe('getRelease', () => { | ||
it('returns latest GitHub release', async () => { | ||
const version = await Install.getDownloadVersion('latest'); | ||
const release = await Install.getRelease(version); | ||
expect(release).not.toBeNull(); | ||
expect(release?.tag_name).not.toEqual(''); | ||
}); | ||
it('returns v2.24.3 GitHub release', async () => { | ||
const version = await Install.getDownloadVersion('v2.24.3'); | ||
const release = await Install.getRelease(version); | ||
expect(release).not.toBeNull(); | ||
expect(release?.id).toEqual(138380726); | ||
expect(release?.tag_name).toEqual('v2.24.3'); | ||
expect(release?.html_url).toEqual('https://github.com/docker/compose/releases/tag/v2.24.3'); | ||
}); | ||
it('unknown release', async () => { | ||
const version = await Install.getDownloadVersion('foo'); | ||
await expect(Install.getRelease(version)).rejects.toThrow(new Error('Cannot find Compose release foo in https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/compose-releases.json')); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.