import {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'; const tmpNameSync = path.join('/tmp/.docker-actions-toolkit-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep); const imageID = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9'; 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); if (!fs.existsSync(tmpDir)) { fs.mkdirSync(tmpDir, {recursive: true}); } return tmpDir; }); jest.spyOn(util, 'tmpNameSync').mockImplementation((): string => { return tmpNameSync; }); describe('getImageID', () => { it('matches', async () => { const imageIDFile = await buildx.getImageIDFile(); await fs.writeFileSync(imageIDFile, imageID); const expected = await buildx.getImageID(); expect(expected).toEqual(imageID); }); }); describe('getMetadata', () => { it('matches', async () => { const metadataFile = await buildx.getMetadataFile(); await fs.writeFileSync(metadataFile, metadata); const expected = await buildx.getMetadata(); expect(expected).toEqual(metadata); }); }); describe('getDigest', () => { it('matches', async () => { const metadataFile = await buildx.getMetadataFile(); await fs.writeFileSync(metadataFile, metadata); const expected = await buildx.getDigest(metadata); expect(expected).toEqual('sha256:b09b9482c72371486bb2c1d2c2a2633ed1d0b8389e12c8d52b9e052725c0c83c'); }); }); describe('hasLocalOrTarExporter', () => { test.each([ [['type=registry,ref=user/app'], false], [['type=docker'], false], [['type=local,dest=./release-out'], true], [['type=tar,dest=/tmp/image.tar'], true], [['type=docker', 'type=tar,dest=/tmp/image.tar'], true], [['"type=tar","dest=/tmp/image.tar"'], true], [['" type= local" , dest=./release-out'], true], [['.'], true] ])('given %p returns %p', async (outputs: Array, expected: boolean) => { expect(buildx.hasLocalOrTarExporter(outputs)).toEqual(expected); }); }); describe('isAvailable', () => { it('docker cli', async () => { const execSpy = jest.spyOn(exec, 'getExecOutput'); await buildx.isAvailable(); // eslint-disable-next-line jest/no-standalone-expect expect(execSpy).toHaveBeenCalledWith(`docker`, ['buildx'], { silent: true, ignoreReturnCode: true }); }); it('standalone', async () => { const execSpy = jest.spyOn(exec, 'getExecOutput'); await buildx.isAvailable(true); // eslint-disable-next-line jest/no-standalone-expect expect(execSpy).toHaveBeenCalledWith(`buildx`, [], { silent: true, ignoreReturnCode: true }); }); }); 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 version = await buildx.getVersion(); expect(semver.valid(version)).not.toBeNull(); }); }); describe('parseVersion', () => { test.each([ ['github.com/docker/buildx 0.4.1+azure bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'], ['github.com/docker/buildx v0.4.1 bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'], ['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); }); }); describe('satisfies', () => { 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); }); }); describe('getSecret', () => { 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) => { try { let secret: string; if (file) { secret = await buildx.getSecretFile(kvp); } else { secret = await buildx.getSecretString(kvp); } expect(true).toBe(!invalid); expect(secret).toEqual(`id=${exKey},src=${tmpNameSync}`); expect(fs.readFileSync(tmpNameSync, 'utf-8')).toEqual(exValue); } catch (err) { // eslint-disable-next-line jest/no-conditional-expect expect(true).toBe(invalid); } }); });