Some improvements

- Use classes
- Split buildx/builder modules
- Additional tests

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax
2023-01-23 10:07:14 +01:00
parent c7dfb4c220
commit aae4a2d7bc
17 changed files with 1045 additions and 712 deletions

158
__tests__/builder.test.ts Normal file
View File

@@ -0,0 +1,158 @@
import {describe, expect, it, test} from '@jest/globals';
import * as fs from 'fs';
import * as path from 'path';
import {Builder} from '../src/builder';
describe('inspect', () => {
it('valid', async () => {
const builder = new Builder();
const builderInfo = await builder.inspect('');
expect(builderInfo).not.toBeUndefined();
expect(builderInfo.name).not.toEqual('');
expect(builderInfo.driver).not.toEqual('');
expect(builderInfo.nodes).not.toEqual({});
}, 100000);
});
describe('parseInspect', () => {
// prettier-ignore
test.each([
[
'inspect1.txt',
{
"name": "builder-5cb467f7-0940-47e1-b94b-d51f54054d62",
"driver": "docker-container",
"nodes": [
{
"name": "builder-5cb467f7-0940-47e1-b94b-d51f54054d620",
"endpoint": "unix:///var/run/docker.sock",
"status": "running",
"buildkitdFlags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"buildkitVersion": "v0.10.4",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/arm64,linux/riscv64,linux/386,linux/arm/v7,linux/arm/v6"
}
]
}
],
[
'inspect2.txt',
{
"name": "builder-5f449644-ff29-48af-8344-abb0292d0673",
"driver": "docker-container",
"nodes": [
{
"name": "builder-5f449644-ff29-48af-8344-abb0292d06730",
"endpoint": "unix:///var/run/docker.sock",
"driverOpts": [
"image=moby/buildkit:latest"
],
"status": "running",
"buildkitdFlags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"buildkitVersion": "v0.10.4",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/386"
}
]
}
],
[
'inspect3.txt',
{
"name": "builder-9929e463-7954-4dc3-89cd-514cca29ff80",
"driver": "docker-container",
"nodes": [
{
"name": "builder-9929e463-7954-4dc3-89cd-514cca29ff800",
"endpoint": "unix:///var/run/docker.sock",
"driverOpts": [
"image=moby/buildkit:master",
"network=host"
],
"status": "running",
"buildkitdFlags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"buildkitVersion": "3fab389",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/386"
}
]
}
],
[
'inspect4.txt',
{
"name": "default",
"driver": "docker",
"nodes": [
{
"name": "default",
"endpoint": "default",
"status": "running",
"buildkitVersion": "20.10.17",
"platforms": "linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6"
}
]
}
],
[
'inspect5.txt',
{
"name": "remote-builder",
"driver": "remote",
"nodes": [
{
"name": "aws_graviton2",
"endpoint": "tcp://1.23.45.67:1234",
"driverOpts": [
"cert=/home/user/.certs/aws_graviton2/cert.pem",
"key=/home/user/.certs/aws_graviton2/key.pem",
"cacert=/home/user/.certs/aws_graviton2/ca.pem"
],
"status": "running",
"platforms": "darwin/arm64,linux/arm64,linux/arm/v5,linux/arm/v6,linux/arm/v7,windows/arm64"
}
]
}
],
[
'inspect6.txt',
{
"nodes": [
{
"name": "builder-17cfff01-48d9-4c3d-9332-9992e308a5100",
"endpoint": "unix:///var/run/docker.sock",
"status": "running",
"buildkitdFlags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/386"
}
],
"name": "builder-17cfff01-48d9-4c3d-9332-9992e308a510",
"driver": "docker-container"
}
],
[
'inspect7.txt',
{
"name": "builder2",
"driver": "docker-container",
"lastActivity": new Date("2023-01-16T09:45:23.000Z"),
"nodes": [
{
"buildkitVersion": "v0.11.0",
"buildkitdFlags": "--debug --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"driverOpts": [
"BUILDKIT_STEP_LOG_MAX_SIZE=10485760",
"BUILDKIT_STEP_LOG_MAX_SPEED=10485760",
"JAEGER_TRACE=localhost:6831",
"image=moby/buildkit:latest",
"network=host"
],
"endpoint": "unix:///var/run/docker.sock",
"name": "builder20",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6",
"status": "running"
}
]
}
]
])('given %p', async (inspectFile, expected) => {
expect(await Builder.parseInspect(fs.readFileSync(path.join(__dirname, 'fixtures', inspectFile)).toString())).toEqual(expected);
});
});

View File

@@ -1,32 +1,40 @@
import {describe, expect, it, jest, test} from '@jest/globals';
import {afterEach, describe, expect, it, jest, test} from '@jest/globals';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as semver from 'semver';
import * as buildkit from '../src/buildkit';
import * as buildx from '../src/buildx';
import * as util from '../src/util';
import rimraf from 'rimraf';
const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-actions-toolkit-')).split(path.sep).join(path.posix.sep);
jest.spyOn(util, 'tmpDir').mockImplementation((): string => {
return tmpdir;
import {BuildKit} from '../src/buildkit';
import {Builder, BuilderInfo} from '../src/builder';
const tmpDir = path.join('/tmp/.docker-actions-toolkit-jest').split(path.sep).join(path.posix.sep);
const tmpName = path.join(tmpDir, '.tmpname-jest').split(path.sep).join(path.posix.sep);
jest.spyOn(BuildKit.prototype as any, 'tmpDir').mockImplementation((): string => {
if (!fs.existsSync(tmpDir)) {
fs.mkdirSync(tmpDir, {recursive: true});
}
return tmpDir;
});
const tmpname = path.join(tmpdir, '.tmpname').split(path.sep).join(path.posix.sep);
jest.spyOn(util, 'tmpNameSync').mockImplementation((): string => {
return tmpname;
jest.spyOn(BuildKit.prototype as any, 'tmpName').mockImplementation((): string => {
return tmpName;
});
jest.spyOn(buildx, 'inspect').mockImplementation(async (): Promise<buildx.Builder> => {
afterEach(() => {
rimraf.sync(tmpDir);
});
jest.spyOn(Builder.prototype, 'inspect').mockImplementation(async (): Promise<BuilderInfo> => {
return {
name: 'builder2',
driver: 'docker-container',
'last-activity': new Date('2023-01-16 09:45:23 +0000 UTC'),
lastActivity: new Date('2023-01-16 09:45:23 +0000 UTC'),
nodes: [
{
buildkit: 'v0.11.0',
'buildkitd-flags': '--debug --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
'driver-opts': ['BUILDKIT_STEP_LOG_MAX_SIZE=10485760', 'BUILDKIT_STEP_LOG_MAX_SPEED=10485760', 'JAEGER_TRACE=localhost:6831', 'image=moby/buildkit:latest', 'network=host'],
buildkitVersion: 'v0.11.0',
buildkitdFlags: '--debug --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
driverOpts: ['BUILDKIT_STEP_LOG_MAX_SIZE=10485760', 'BUILDKIT_STEP_LOG_MAX_SPEED=10485760', 'JAEGER_TRACE=localhost:6831', 'image=moby/buildkit:latest', 'network=host'],
endpoint: 'unix:///var/run/docker.sock',
name: 'builder20',
platforms: 'linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6',
@@ -38,6 +46,7 @@ jest.spyOn(buildx, 'inspect').mockImplementation(async (): Promise<buildx.Builde
describe('getVersion', () => {
it('valid', async () => {
const buildkit = new BuildKit();
const version = await buildkit.getVersion('builder2');
expect(semver.valid(version)).not.toBeNull();
});
@@ -48,14 +57,15 @@ describe('satisfies', () => {
['builder2', '>=0.10.0', true],
['builder2', '>0.11.0', false]
])('given %p', async (builderName, range, expected) => {
expect(await buildkit.satisfies(builderName, range)).toBe(expected);
const buildkit = new BuildKit();
expect(await buildkit.versionSatisfies(builderName, range)).toBe(expected);
});
});
describe('getConfig', () => {
describe('generateConfig', () => {
test.each([
['debug = true', false, 'debug = true', false],
[`notfound.toml`, true, '', true],
['debug = true', false, 'debug = true', null],
[`notfound.toml`, true, '', new Error('config file notfound.toml not found')],
[
`${path.join(__dirname, 'fixtures', 'buildkitd.toml').split(path.sep).join(path.posix.sep)}`,
true,
@@ -63,23 +73,23 @@ describe('getConfig', () => {
[registry."docker.io"]
mirrors = ["mirror.gcr.io"]
`,
false
null
]
])('given %p config', async (val, file, exValue, invalid) => {
])('given %p config', async (val, file, exValue, error: Error) => {
try {
const buildkit = new BuildKit();
let config: string;
if (file) {
config = await buildkit.getConfigFile(val);
config = buildkit.generateConfigFile(val);
} else {
config = await buildkit.getConfigInline(val);
config = buildkit.generateConfigInline(val);
}
expect(true).toBe(!invalid);
expect(config).toEqual(tmpname);
const configValue = fs.readFileSync(tmpname, 'utf-8');
expect(config).toEqual(tmpName);
const configValue = fs.readFileSync(tmpName, 'utf-8');
expect(configValue).toEqual(exValue);
} catch (err) {
} catch (e) {
// eslint-disable-next-line jest/no-conditional-expect
expect(true).toBe(invalid);
expect(e.message).toEqual(error?.message);
}
});
});

View File

@@ -1,53 +1,61 @@
import {describe, expect, it, jest, test} from '@jest/globals';
import {afterEach, describe, expect, it, jest, test} from '@jest/globals';
import * as fs from 'fs';
import * as path from 'path';
import * as semver from 'semver';
import * as exec from '@actions/exec';
import * as buildx from '../src/buildx';
import * as util from '../src/util';
import rimraf from 'rimraf';
const tmpNameSync = path.join('/tmp/.docker-actions-toolkit-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
const imageID = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9';
import {Buildx} from '../src/buildx';
const tmpDir = path.join('/tmp/.docker-actions-toolkit-jest').split(path.sep).join(path.posix.sep);
const tmpName = path.join(tmpDir, '.tmpname-jest').split(path.sep).join(path.posix.sep);
const metadata = `{
"containerimage.config.digest": "sha256:059b68a595b22564a1cbc167af369349fdc2ecc1f7bc092c2235cbf601a795fd",
"containerimage.digest": "sha256:b09b9482c72371486bb2c1d2c2a2633ed1d0b8389e12c8d52b9e052725c0c83c"
}`;
jest.spyOn(util, 'tmpDir').mockImplementation((): string => {
const tmpDir = path.join('/tmp/.docker-actions-toolkit-jest').split(path.sep).join(path.posix.sep);
jest.spyOn(Buildx.prototype as any, 'tmpDir').mockImplementation((): string => {
if (!fs.existsSync(tmpDir)) {
fs.mkdirSync(tmpDir, {recursive: true});
}
return tmpDir;
});
jest.spyOn(util, 'tmpNameSync').mockImplementation((): string => {
return tmpNameSync;
afterEach(() => {
rimraf.sync(tmpDir);
});
describe('getImageID', () => {
jest.spyOn(Buildx.prototype as any, 'tmpName').mockImplementation((): string => {
return tmpName;
});
describe('getBuildImageID', () => {
it('matches', async () => {
const imageIDFile = await buildx.getImageIDFile();
const buildx = new Buildx();
const imageID = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9';
const imageIDFile = buildx.getBuildImageIDFilePath();
await fs.writeFileSync(imageIDFile, imageID);
const expected = await buildx.getImageID();
const expected = buildx.getBuildImageID();
expect(expected).toEqual(imageID);
});
});
describe('getMetadata', () => {
describe('getBuildMetadata', () => {
it('matches', async () => {
const metadataFile = await buildx.getMetadataFile();
const buildx = new Buildx();
const metadataFile = buildx.getBuildMetadataFilePath();
await fs.writeFileSync(metadataFile, metadata);
const expected = await buildx.getMetadata();
const expected = buildx.getBuildMetadata();
expect(expected).toEqual(metadata);
});
});
describe('getDigest', () => {
it('matches', async () => {
const metadataFile = await buildx.getMetadataFile();
const buildx = new Buildx();
const metadataFile = buildx.getBuildMetadataFilePath();
await fs.writeFileSync(metadataFile, metadata);
const expected = await buildx.getDigest(metadata);
const expected = buildx.getDigest();
expect(expected).toEqual('sha256:b09b9482c72371486bb2c1d2c2a2633ed1d0b8389e12c8d52b9e052725c0c83c');
});
});
@@ -62,14 +70,15 @@ describe('hasLocalOrTarExporter', () => {
[['"type=tar","dest=/tmp/image.tar"'], true],
[['" type= local" , dest=./release-out'], true],
[['.'], true]
])('given %p returns %p', async (outputs: Array<string>, expected: boolean) => {
expect(buildx.hasLocalOrTarExporter(outputs)).toEqual(expected);
])('given %p returns %p', async (exporters: Array<string>, expected: boolean) => {
expect(Buildx.hasLocalExporter(exporters) || Buildx.hasTarExporter(exporters)).toEqual(expected);
});
});
describe('isAvailable', () => {
it('docker cli', async () => {
const execSpy = jest.spyOn(exec, 'getExecOutput');
const buildx = new Buildx();
await buildx.isAvailable();
// eslint-disable-next-line jest/no-standalone-expect
expect(execSpy).toHaveBeenCalledWith(`docker`, ['buildx'], {
@@ -79,7 +88,10 @@ describe('isAvailable', () => {
});
it('standalone', async () => {
const execSpy = jest.spyOn(exec, 'getExecOutput');
await buildx.isAvailable(true);
const buildx = new Buildx({
standalone: true
});
await buildx.isAvailable();
// eslint-disable-next-line jest/no-standalone-expect
expect(execSpy).toHaveBeenCalledWith(`buildx`, [], {
silent: true,
@@ -88,161 +100,9 @@ describe('isAvailable', () => {
});
});
describe('inspect', () => {
it('valid', async () => {
const builder = await buildx.inspect('');
expect(builder).not.toBeUndefined();
expect(builder.name).not.toEqual('');
expect(builder.driver).not.toEqual('');
expect(builder.nodes).not.toEqual({});
}, 100000);
});
describe('parseInspect', () => {
// prettier-ignore
test.each([
[
'inspect1.txt',
{
"name": "builder-5cb467f7-0940-47e1-b94b-d51f54054d62",
"driver": "docker-container",
"nodes": [
{
"name": "builder-5cb467f7-0940-47e1-b94b-d51f54054d620",
"endpoint": "unix:///var/run/docker.sock",
"status": "running",
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"buildkit": "v0.10.4",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/arm64,linux/riscv64,linux/386,linux/arm/v7,linux/arm/v6"
}
]
}
],
[
'inspect2.txt',
{
"name": "builder-5f449644-ff29-48af-8344-abb0292d0673",
"driver": "docker-container",
"nodes": [
{
"name": "builder-5f449644-ff29-48af-8344-abb0292d06730",
"endpoint": "unix:///var/run/docker.sock",
"driver-opts": [
"image=moby/buildkit:latest"
],
"status": "running",
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"buildkit": "v0.10.4",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/386"
}
]
}
],
[
'inspect3.txt',
{
"name": "builder-9929e463-7954-4dc3-89cd-514cca29ff80",
"driver": "docker-container",
"nodes": [
{
"name": "builder-9929e463-7954-4dc3-89cd-514cca29ff800",
"endpoint": "unix:///var/run/docker.sock",
"driver-opts": [
"image=moby/buildkit:master",
"network=host"
],
"status": "running",
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"buildkit": "3fab389",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/386"
}
]
}
],
[
'inspect4.txt',
{
"name": "default",
"driver": "docker",
"nodes": [
{
"name": "default",
"endpoint": "default",
"status": "running",
"buildkit": "20.10.17",
"platforms": "linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6"
}
]
}
],
[
'inspect5.txt',
{
"name": "remote-builder",
"driver": "remote",
"nodes": [
{
"name": "aws_graviton2",
"endpoint": "tcp://1.23.45.67:1234",
"driver-opts": [
"cert=/home/user/.certs/aws_graviton2/cert.pem",
"key=/home/user/.certs/aws_graviton2/key.pem",
"cacert=/home/user/.certs/aws_graviton2/ca.pem"
],
"status": "running",
"platforms": "darwin/arm64,linux/arm64,linux/arm/v5,linux/arm/v6,linux/arm/v7,windows/arm64"
}
]
}
],
[
'inspect6.txt',
{
"nodes": [
{
"name": "builder-17cfff01-48d9-4c3d-9332-9992e308a5100",
"endpoint": "unix:///var/run/docker.sock",
"status": "running",
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/386"
}
],
"name": "builder-17cfff01-48d9-4c3d-9332-9992e308a510",
"driver": "docker-container"
}
],
[
'inspect7.txt',
{
"name": "builder2",
"driver": "docker-container",
"last-activity": new Date("2023-01-16T09:45:23.000Z"),
"nodes": [
{
"buildkit": "v0.11.0",
"buildkitd-flags": "--debug --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"driver-opts": [
"BUILDKIT_STEP_LOG_MAX_SIZE=10485760",
"BUILDKIT_STEP_LOG_MAX_SPEED=10485760",
"JAEGER_TRACE=localhost:6831",
"image=moby/buildkit:latest",
"network=host"
],
"endpoint": "unix:///var/run/docker.sock",
"name": "builder20",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6",
"status": "running"
}
]
}
]
])('given %p', async (inspectFile, expected) => {
expect(await buildx.parseInspect(fs.readFileSync(path.join(__dirname, 'fixtures', inspectFile)).toString())).toEqual(expected);
});
});
describe('getVersion', () => {
it('valid', async () => {
const buildx = new Buildx();
const version = await buildx.getVersion();
expect(semver.valid(version)).not.toBeNull();
});
@@ -255,44 +115,54 @@ describe('parseVersion', () => {
['github.com/docker/buildx v0.4.2 fb7b670b764764dc4716df3eba07ffdae4cc47b2', '0.4.2'],
['github.com/docker/buildx f117971 f11797113e5a9b86bd976329c5dbb8a8bfdfadfa', 'f117971']
])('given %p', async (stdout, expected) => {
expect(buildx.parseVersion(stdout)).toEqual(expected);
expect(Buildx.parseVersion(stdout)).toEqual(expected);
});
});
describe('satisfies', () => {
describe('versionSatisfies', () => {
test.each([
['0.4.1', '>=0.3.2', true],
['bda4882a65349ca359216b135896bddc1d92461c', '>0.1.0', false],
['f117971', '>0.6.0', true]
])('given %p', async (version, range, expected) => {
expect(buildx.satisfies(version, range)).toBe(expected);
expect(Buildx.versionSatisfies(version, range)).toBe(expected);
});
});
describe('getSecret', () => {
describe('generateBuildSecret', () => {
test.each([
['A_SECRET=abcdef0123456789', false, 'A_SECRET', 'abcdef0123456789', false],
['GIT_AUTH_TOKEN=abcdefghijklmno=0123456789', false, 'GIT_AUTH_TOKEN', 'abcdefghijklmno=0123456789', false],
['MY_KEY=c3RyaW5nLXdpdGgtZXF1YWxzCg==', false, 'MY_KEY', 'c3RyaW5nLXdpdGgtZXF1YWxzCg==', false],
['aaaaaaaa', false, '', '', true],
['aaaaaaaa=', false, '', '', true],
['=bbbbbbb', false, '', '', true],
[`foo=${path.join(__dirname, 'fixtures', 'secret.txt').split(path.sep).join(path.posix.sep)}`, true, 'foo', 'bar', false],
[`notfound=secret`, true, '', '', true]
])('given %p key and %p secret', async (kvp, file, exKey, exValue, invalid) => {
['A_SECRET=abcdef0123456789', false, 'A_SECRET', 'abcdef0123456789', null],
['GIT_AUTH_TOKEN=abcdefghijklmno=0123456789', false, 'GIT_AUTH_TOKEN', 'abcdefghijklmno=0123456789', null],
['MY_KEY=c3RyaW5nLXdpdGgtZXF1YWxzCg==', false, 'MY_KEY', 'c3RyaW5nLXdpdGgtZXF1YWxzCg==', null],
['aaaaaaaa', false, '', '', new Error('aaaaaaaa is not a valid secret')],
['aaaaaaaa=', false, '', '', new Error('aaaaaaaa= is not a valid secret')],
['=bbbbbbb', false, '', '', new Error('=bbbbbbb is not a valid secret')],
[`foo=${path.join(__dirname, 'fixtures', 'secret.txt').split(path.sep).join(path.posix.sep)}`, true, 'foo', 'bar', null],
[`notfound=secret`, true, '', '', new Error('secret file secret not found')]
])('given %p key and %p secret', async (kvp: string, file: boolean, exKey: string, exValue: string, error: Error) => {
try {
const buildx = new Buildx();
let secret: string;
if (file) {
secret = await buildx.getSecretFile(kvp);
secret = buildx.generateBuildSecretFile(kvp);
} else {
secret = await buildx.getSecretString(kvp);
secret = buildx.generateBuildSecretString(kvp);
}
expect(true).toBe(!invalid);
expect(secret).toEqual(`id=${exKey},src=${tmpNameSync}`);
expect(fs.readFileSync(tmpNameSync, 'utf-8')).toEqual(exValue);
} catch (err) {
expect(secret).toEqual(`id=${exKey},src=${tmpName}`);
expect(fs.readFileSync(tmpName, 'utf-8')).toEqual(exValue);
} catch (e) {
// eslint-disable-next-line jest/no-conditional-expect
expect(true).toBe(invalid);
expect(e.message).toEqual(error?.message);
}
});
});
describe('hasGitAuthTokenSecret', () => {
// prettier-ignore
test.each([
[['A_SECRET=abcdef0123456789'], false],
[['GIT_AUTH_TOKEN=abcdefghijklmno=0123456789'], true],
])('given %p secret', async (kvp: Array<string>, expected: boolean) => {
expect(Buildx.hasGitAuthTokenSecret(kvp)).toBe(expected);
});
});

View File

@@ -1,11 +1,12 @@
import {describe, expect, it, jest} from '@jest/globals';
import * as docker from '../src/docker';
import * as exec from '@actions/exec';
import {Docker} from '../src/docker';
describe('isAvailable', () => {
it('cli', () => {
const execSpy = jest.spyOn(exec, 'getExecOutput');
docker.isAvailable();
Docker.isAvailable();
// eslint-disable-next-line jest/no-standalone-expect
expect(execSpy).toHaveBeenCalledWith(`docker`, undefined, {

View File

@@ -0,0 +1,195 @@
{
"after": "860c1904a1ce19322e91ac35af1ab07466440c37",
"base_ref": null,
"before": "5f3331d7f7044c18ca9f12c77d961c4d7cf3276a",
"commits": [
{
"author": {
"email": "crazy-max@users.noreply.github.com",
"name": "CrazyMax",
"username": "crazy-max"
},
"committer": {
"email": "crazy-max@users.noreply.github.com",
"name": "CrazyMax",
"username": "crazy-max"
},
"distinct": true,
"id": "860c1904a1ce19322e91ac35af1ab07466440c37",
"message": "hello dev",
"timestamp": "2022-04-19T11:27:24+02:00",
"tree_id": "d2c60af597e863787d2d27f569e30495b0b92820",
"url": "https://github.com/docker/test-docker-action/commit/860c1904a1ce19322e91ac35af1ab07466440c37"
}
],
"compare": "https://github.com/docker/test-docker-action/compare/5f3331d7f704...860c1904a1ce",
"created": false,
"deleted": false,
"forced": false,
"head_commit": {
"author": {
"email": "crazy-max@users.noreply.github.com",
"name": "CrazyMax",
"username": "crazy-max"
},
"committer": {
"email": "crazy-max@users.noreply.github.com",
"name": "CrazyMax",
"username": "crazy-max"
},
"distinct": true,
"id": "860c1904a1ce19322e91ac35af1ab07466440c37",
"message": "hello dev",
"timestamp": "2022-04-19T11:27:24+02:00",
"tree_id": "d2c60af597e863787d2d27f569e30495b0b92820",
"url": "https://github.com/docker/test-docker-action/commit/860c1904a1ce19322e91ac35af1ab07466440c37"
},
"organization": {
"avatar_url": "https://avatars.githubusercontent.com/u/5429470?v=4",
"description": "Docker helps developers bring their ideas to life by conquering the complexity of app development.",
"events_url": "https://api.github.com/orgs/docker/events",
"hooks_url": "https://api.github.com/orgs/docker/hooks",
"id": 5429470,
"issues_url": "https://api.github.com/orgs/docker/issues",
"login": "docker",
"members_url": "https://api.github.com/orgs/docker/members{/member}",
"node_id": "MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=",
"public_members_url": "https://api.github.com/orgs/docker/public_members{/member}",
"repos_url": "https://api.github.com/orgs/docker/repos",
"url": "https://api.github.com/orgs/docker"
},
"pusher": {
"email": "github@crazymax.dev",
"name": "crazy-max"
},
"ref": "refs/heads/dev",
"repository": {
"allow_forking": true,
"archive_url": "https://api.github.com/repos/docker/test-docker-action/{archive_format}{/ref}",
"archived": false,
"assignees_url": "https://api.github.com/repos/docker/test-docker-action/assignees{/user}",
"blobs_url": "https://api.github.com/repos/docker/test-docker-action/git/blobs{/sha}",
"branches_url": "https://api.github.com/repos/docker/test-docker-action/branches{/branch}",
"clone_url": "https://github.com/docker/test-docker-action.git",
"collaborators_url": "https://api.github.com/repos/docker/test-docker-action/collaborators{/collaborator}",
"comments_url": "https://api.github.com/repos/docker/test-docker-action/comments{/number}",
"commits_url": "https://api.github.com/repos/docker/test-docker-action/commits{/sha}",
"compare_url": "https://api.github.com/repos/docker/test-docker-action/compare/{base}...{head}",
"contents_url": "https://api.github.com/repos/docker/test-docker-action/contents/{+path}",
"contributors_url": "https://api.github.com/repos/docker/test-docker-action/contributors",
"created_at": 1596792180,
"default_branch": "master",
"deployments_url": "https://api.github.com/repos/docker/test-docker-action/deployments",
"description": "Test \"Docker\" Actions",
"disabled": false,
"downloads_url": "https://api.github.com/repos/docker/test-docker-action/downloads",
"events_url": "https://api.github.com/repos/docker/test-docker-action/events",
"fork": false,
"forks": 1,
"forks_count": 1,
"forks_url": "https://api.github.com/repos/docker/test-docker-action/forks",
"full_name": "docker/test-docker-action",
"git_commits_url": "https://api.github.com/repos/docker/test-docker-action/git/commits{/sha}",
"git_refs_url": "https://api.github.com/repos/docker/test-docker-action/git/refs{/sha}",
"git_tags_url": "https://api.github.com/repos/docker/test-docker-action/git/tags{/sha}",
"git_url": "git://github.com/docker/test-docker-action.git",
"has_downloads": true,
"has_issues": true,
"has_pages": false,
"has_projects": true,
"has_wiki": true,
"homepage": "",
"hooks_url": "https://api.github.com/repos/docker/test-docker-action/hooks",
"html_url": "https://github.com/docker/test-docker-action",
"id": 285789493,
"is_template": false,
"issue_comment_url": "https://api.github.com/repos/docker/test-docker-action/issues/comments{/number}",
"issue_events_url": "https://api.github.com/repos/docker/test-docker-action/issues/events{/number}",
"issues_url": "https://api.github.com/repos/docker/test-docker-action/issues{/number}",
"keys_url": "https://api.github.com/repos/docker/test-docker-action/keys{/key_id}",
"labels_url": "https://api.github.com/repos/docker/test-docker-action/labels{/name}",
"language": "JavaScript",
"languages_url": "https://api.github.com/repos/docker/test-docker-action/languages",
"license": {
"key": "mit",
"name": "MIT License",
"node_id": "MDc6TGljZW5zZTEz",
"spdx_id": "MIT",
"url": "https://api.github.com/licenses/mit"
},
"master_branch": "master",
"merges_url": "https://api.github.com/repos/docker/test-docker-action/merges",
"milestones_url": "https://api.github.com/repos/docker/test-docker-action/milestones{/number}",
"mirror_url": null,
"name": "test-docker-action",
"node_id": "MDEwOlJlcG9zaXRvcnkyODU3ODk0OTM=",
"notifications_url": "https://api.github.com/repos/docker/test-docker-action/notifications{?since,all,participating}",
"open_issues": 6,
"open_issues_count": 6,
"organization": "docker",
"owner": {
"avatar_url": "https://avatars.githubusercontent.com/u/5429470?v=4",
"email": "info@docker.com",
"events_url": "https://api.github.com/users/docker/events{/privacy}",
"followers_url": "https://api.github.com/users/docker/followers",
"following_url": "https://api.github.com/users/docker/following{/other_user}",
"gists_url": "https://api.github.com/users/docker/gists{/gist_id}",
"gravatar_id": "",
"html_url": "https://github.com/docker",
"id": 5429470,
"login": "docker",
"name": "docker",
"node_id": "MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=",
"organizations_url": "https://api.github.com/users/docker/orgs",
"received_events_url": "https://api.github.com/users/docker/received_events",
"repos_url": "https://api.github.com/users/docker/repos",
"site_admin": false,
"starred_url": "https://api.github.com/users/docker/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/docker/subscriptions",
"type": "Organization",
"url": "https://api.github.com/users/docker"
},
"private": true,
"pulls_url": "https://api.github.com/repos/docker/test-docker-action/pulls{/number}",
"pushed_at": 1650360446,
"releases_url": "https://api.github.com/repos/docker/test-docker-action/releases{/id}",
"size": 796,
"ssh_url": "git@github.com:docker/test-docker-action.git",
"stargazers": 0,
"stargazers_count": 0,
"stargazers_url": "https://api.github.com/repos/docker/test-docker-action/stargazers",
"statuses_url": "https://api.github.com/repos/docker/test-docker-action/statuses/{sha}",
"subscribers_url": "https://api.github.com/repos/docker/test-docker-action/subscribers",
"subscription_url": "https://api.github.com/repos/docker/test-docker-action/subscription",
"svn_url": "https://github.com/docker/test-docker-action",
"tags_url": "https://api.github.com/repos/docker/test-docker-action/tags",
"teams_url": "https://api.github.com/repos/docker/test-docker-action/teams",
"topics": [],
"trees_url": "https://api.github.com/repos/docker/test-docker-action/git/trees{/sha}",
"updated_at": "2022-04-19T09:05:09Z",
"url": "https://github.com/docker/test-docker-action",
"visibility": "private",
"watchers": 0,
"watchers_count": 0
},
"sender": {
"avatar_url": "https://avatars.githubusercontent.com/u/1951866?v=4",
"events_url": "https://api.github.com/users/crazy-max/events{/privacy}",
"followers_url": "https://api.github.com/users/crazy-max/followers",
"following_url": "https://api.github.com/users/crazy-max/following{/other_user}",
"gists_url": "https://api.github.com/users/crazy-max/gists{/gist_id}",
"gravatar_id": "",
"html_url": "https://github.com/crazy-max",
"id": 1951866,
"login": "crazy-max",
"node_id": "MDQ6VXNlcjE5NTE4NjY=",
"organizations_url": "https://api.github.com/users/crazy-max/orgs",
"received_events_url": "https://api.github.com/users/crazy-max/received_events",
"repos_url": "https://api.github.com/users/crazy-max/repos",
"site_admin": false,
"starred_url": "https://api.github.com/users/crazy-max/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/crazy-max/subscriptions",
"type": "User",
"url": "https://api.github.com/users/crazy-max"
}
}

View File

@@ -1,14 +1,41 @@
import {describe, expect, jest, it} from '@jest/globals';
import * as github from '../src/github';
import {Context} from '@actions/github/lib/context';
import {GitHub, Payload, ReposGetResponseData} from '../src/github';
jest.spyOn(GitHub.prototype, 'context').mockImplementation((): Context => {
return new Context();
});
import * as repoFixture from './fixtures/repo.json';
jest.spyOn(github, 'repo').mockImplementation((): Promise<github.ReposGetResponseData> => {
return <Promise<github.ReposGetResponseData>>(repoFixture as unknown);
jest.spyOn(GitHub.prototype, 'repo').mockImplementation((): Promise<ReposGetResponseData> => {
return <Promise<ReposGetResponseData>>(repoFixture as unknown);
});
import * as payloadFixture from './fixtures/github-payload.json';
jest.spyOn(GitHub.prototype as any, 'payload').mockImplementation((): Promise<Payload> => {
return <Promise<Payload>>(payloadFixture as unknown);
});
jest.spyOn(GitHub.prototype as any, 'ref').mockImplementation((): string => {
return 'refs/heads/master';
});
describe('gitContext', () => {
it('returns refs/heads/master', async () => {
expect(GitHub.getInstance().gitContext()).toEqual('https://github.com/docker/test-docker-action.git#refs/heads/master');
});
});
describe('repo', () => {
it('returns GitHub repository', async () => {
const repo = await github.repo(process.env.GITHUB_TOKEN || '');
expect(repo.name).not.toBeNull();
const repo = await GitHub.getInstance().repo(process.env.GITHUB_TOKEN || '');
expect(repo.name).toEqual('Hello-World');
});
});
describe('fromPayload', () => {
it('returns repository name from payload', async () => {
const repoName = await GitHub.getInstance().fromPayload('repository.name');
expect(repoName).toEqual('test-docker-action');
});
});

View File

@@ -1,76 +1,61 @@
import {describe, expect, it, jest, test} from '@jest/globals';
import {describe, expect, it, test} from '@jest/globals';
import * as fs from 'fs';
import * as path from 'path';
import * as util from '../src/util';
jest.spyOn(util, 'defaultContext').mockImplementation((): string => {
return 'https://github.com/docker/actions-toolkit.git#refs/heads/test-jest';
});
jest.spyOn(util, 'tmpDir').mockImplementation((): string => {
const tmpDir = path.join('/tmp/.docker-build-push-jest').split(path.sep).join(path.posix.sep);
if (!fs.existsSync(tmpDir)) {
fs.mkdirSync(tmpDir, {recursive: true});
}
return tmpDir;
});
jest.spyOn(util, 'tmpNameSync').mockImplementation((): string => {
return path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
});
import {Util} from '../src/util';
describe('getInputList', () => {
it('single line correctly', async () => {
await setInput('foo', 'bar');
const res = util.getInputList('foo');
const res = Util.getInputList('foo');
expect(res).toEqual(['bar']);
});
it('multiline correctly', async () => {
setInput('foo', 'bar\nbaz');
const res = util.getInputList('foo');
const res = Util.getInputList('foo');
expect(res).toEqual(['bar', 'baz']);
});
it('empty lines correctly', async () => {
setInput('foo', 'bar\n\nbaz');
const res = util.getInputList('foo');
const res = Util.getInputList('foo');
expect(res).toEqual(['bar', 'baz']);
});
it('comma correctly', async () => {
setInput('foo', 'bar,baz');
const res = util.getInputList('foo');
const res = Util.getInputList('foo');
expect(res).toEqual(['bar', 'baz']);
});
it('empty result correctly', async () => {
setInput('foo', 'bar,baz,');
const res = util.getInputList('foo');
const res = Util.getInputList('foo');
expect(res).toEqual(['bar', 'baz']);
});
it('different new lines correctly', async () => {
setInput('foo', 'bar\r\nbaz');
const res = util.getInputList('foo');
const res = Util.getInputList('foo');
expect(res).toEqual(['bar', 'baz']);
});
it('different new lines and comma correctly', async () => {
setInput('foo', 'bar\r\nbaz,bat');
const res = util.getInputList('foo');
const res = Util.getInputList('foo');
expect(res).toEqual(['bar', 'baz', 'bat']);
});
it('multiline and ignoring comma correctly', async () => {
setInput('cache-from', 'user/app:cache\ntype=local,src=path/to/dir');
const res = util.getInputList('cache-from', true);
const res = Util.getInputList('cache-from', true);
expect(res).toEqual(['user/app:cache', 'type=local,src=path/to/dir']);
});
it('different new lines and ignoring comma correctly', async () => {
setInput('cache-from', 'user/app:cache\r\ntype=local,src=path/to/dir');
const res = util.getInputList('cache-from', true);
const res = Util.getInputList('cache-from', true);
expect(res).toEqual(['user/app:cache', 'type=local,src=path/to/dir']);
});
@@ -83,7 +68,7 @@ bbbbbbb
ccccccccc"
FOO=bar`
);
const res = util.getInputList('secrets', true);
const res = Util.getInputList('secrets', true);
expect(res).toEqual([
'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789',
`MYSECRET=aaaaaaaa
@@ -106,7 +91,7 @@ FOO=bar
bbbb
ccc"`
);
const res = util.getInputList('secrets', true);
const res = Util.getInputList('secrets', true);
expect(res).toEqual([
'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789',
`MYSECRET=aaaaaaaa
@@ -129,7 +114,7 @@ bbbbbbb
ccccccccc
FOO=bar`
);
const res = util.getInputList('secrets', true);
const res = Util.getInputList('secrets', true);
expect(res).toEqual(['GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', 'MYSECRET=aaaaaaaa', 'bbbbbbb', 'ccccccccc', 'FOO=bar']);
});
@@ -140,7 +125,7 @@ FOO=bar`
`"GPG_KEY=${pgp}"
FOO=bar`
);
const res = util.getInputList('secrets', true);
const res = Util.getInputList('secrets', true);
expect(res).toEqual([`GPG_KEY=${pgp}`, 'FOO=bar']);
});
@@ -153,7 +138,7 @@ bbbb""bbb
ccccccccc"
FOO=bar`
);
const res = util.getInputList('secrets', true);
const res = Util.getInputList('secrets', true);
expect(res).toEqual([
'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789',
`MYSECRET=aaaaaaaa
@@ -169,7 +154,7 @@ describe('asyncForEach', () => {
const testValues = [1, 2, 3, 4, 5];
const results: number[] = [];
await util.asyncForEach(testValues, async value => {
await Util.asyncForEach(testValues, async value => {
results.push(value);
});
@@ -183,7 +168,7 @@ describe('isValidUrl', () => {
['https://github.com/docker/buildx.git#refs/pull/648/head', true],
['v0.4.1', false]
])('given %p', async (url, expected) => {
expect(util.isValidUrl(url)).toEqual(expected);
expect(Util.isValidUrl(url)).toEqual(expected);
});
});