From b5c378621cab2a7c920c34b0db18a50da51bd4f2 Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Mon, 20 Feb 2023 22:32:55 +0100 Subject: [PATCH] switch to actions-toolkit implementation Signed-off-by: CrazyMax --- __tests__/context.test.ts | 215 ++++++++++---------------------------- __tests__/flavor.test.ts | 1 + __tests__/github.test.ts | 14 --- __tests__/image.test.ts | 1 + __tests__/meta.test.ts | 50 +++++---- __tests__/tag.test.ts | 1 + dev.Dockerfile | 32 +++--- jest.config.ts | 18 ++++ package.json | 1 + src/context.ts | 58 +--------- src/github.ts | 16 --- src/main.ts | 106 ++++++++++--------- src/meta.ts | 16 +-- tsconfig.json | 7 +- yarn.lock | 73 ++++++++++++- 15 files changed, 260 insertions(+), 349 deletions(-) delete mode 100644 __tests__/github.test.ts delete mode 100644 src/github.ts diff --git a/__tests__/context.test.ts b/__tests__/context.test.ts index 51c29d9..e7622b5 100644 --- a/__tests__/context.test.ts +++ b/__tests__/context.test.ts @@ -1,168 +1,63 @@ -import {describe, expect, it, jest} from '@jest/globals'; -import * as fs from 'fs'; -import * as path from 'path'; +import {beforeEach, describe, expect, test} from '@jest/globals'; import * as context from '../src/context'; -jest.spyOn(context, 'tmpDir').mockImplementation((): string => { - const tmpDir = path.join('/tmp/.docker-metadata-action-jest').split(path.sep).join(path.posix.sep); - if (!fs.existsSync(tmpDir)) { - fs.mkdirSync(tmpDir, {recursive: true}); - } - return tmpDir; -}); - -describe('getInputList', () => { - it('single line correctly', async () => { - await setInput('foo', 'bar'); - const res = context.getInputList('foo'); - expect(res).toEqual(['bar']); +describe('getInputs', () => { + beforeEach(() => { + process.env = Object.keys(process.env).reduce((object, key) => { + if (!key.startsWith('INPUT_')) { + object[key] = process.env[key]; + } + return object; + }, {}); }); - it('multiline correctly', async () => { - setInput('foo', 'bar\nbaz'); - const res = context.getInputList('foo'); - expect(res).toEqual(['bar', 'baz']); - }); - - it('empty lines correctly', async () => { - setInput('foo', 'bar\n\nbaz'); - const res = context.getInputList('foo'); - expect(res).toEqual(['bar', 'baz']); - }); - - it('comment correctly', async () => { - setInput('foo', 'bar\n#com\n"#taken"\nhello#comment\nbaz'); - const res = context.getInputList('foo'); - expect(res).toEqual(['bar', '#taken', 'hello', 'baz']); - }); - - it('comma correctly', async () => { - setInput('foo', 'bar,baz'); - const res = context.getInputList('foo'); - expect(res).toEqual(['bar', 'baz']); - }); - - it('empty result correctly', async () => { - setInput('foo', 'bar,baz,'); - const res = context.getInputList('foo'); - expect(res).toEqual(['bar', 'baz']); - }); - - it('different new lines correctly', async () => { - setInput('foo', 'bar\r\nbaz'); - const res = context.getInputList('foo'); - expect(res).toEqual(['bar', 'baz']); - }); - - it('different new lines and comma correctly', async () => { - setInput('foo', 'bar\r\nbaz,bat'); - const res = context.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 = context.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 = context.getInputList('cache-from', true); - expect(res).toEqual(['user/app:cache', 'type=local,src=path/to/dir']); - }); - - it('multiline values', async () => { - setInput( - 'secrets', - `GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789 -"MYSECRET=aaaaaaaa -bbbbbbb -ccccccccc" -FOO=bar` - ); - const res = context.getInputList('secrets', true); - expect(res).toEqual([ - 'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', - `MYSECRET=aaaaaaaa -bbbbbbb -ccccccccc`, - 'FOO=bar' - ]); - }); - - it('multiline values with empty lines', async () => { - setInput( - 'secrets', - `GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789 -"MYSECRET=aaaaaaaa -bbbbbbb -ccccccccc" -FOO=bar -"EMPTYLINE=aaaa - -bbbb -ccc"` - ); - const res = context.getInputList('secrets', true); - expect(res).toEqual([ - 'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', - `MYSECRET=aaaaaaaa -bbbbbbb -ccccccccc`, - 'FOO=bar', - `EMPTYLINE=aaaa - -bbbb -ccc` - ]); - }); - - it('multiline values without quotes', async () => { - setInput( - 'secrets', - `GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789 -MYSECRET=aaaaaaaa -bbbbbbb -ccccccccc -FOO=bar` - ); - const res = context.getInputList('secrets', true); - expect(res).toEqual(['GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', 'MYSECRET=aaaaaaaa', 'bbbbbbb', 'ccccccccc', 'FOO=bar']); - }); - - it('multiline values escape quotes', async () => { - setInput( - 'secrets', - `GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789 -"MYSECRET=aaaaaaaa -bbbb""bbb -ccccccccc" -FOO=bar` - ); - const res = context.getInputList('secrets', true); - expect(res).toEqual([ - 'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', - `MYSECRET=aaaaaaaa -bbbb"bbb -ccccccccc`, - 'FOO=bar' - ]); - }); -}); - -describe('asyncForEach', () => { - it('executes async tasks sequentially', async () => { - const testValues = [1, 2, 3, 4, 5]; - const results: number[] = []; - - await context.asyncForEach(testValues, async value => { - results.push(value); - }); - - expect(results).toEqual(testValues); - }); + // prettier-ignore + test.each([ + [ + 0, + new Map([ + ['images', 'moby/buildkit\nghcr.io/moby/mbuildkit'], + ]), + { + bakeTarget: 'docker-metadata-action', + flavor: [], + githubToken: '', + images: ['moby/buildkit', 'ghcr.io/moby/mbuildkit'], + labels: [], + sepLabels: '\n', + sepTags: '\n', + tags: [], + } as context.Inputs + ], + [ + 1, + new Map([ + ['bake-target', 'metadata'], + ['images', 'moby/buildkit'], + ['sep-labels', ','], + ['sep-tags', ','], + ]), + { + bakeTarget: 'metadata', + flavor: [], + githubToken: '', + images: ['moby/buildkit'], + labels: [], + sepLabels: ',', + sepTags: ',', + tags: [], + } as context.Inputs + ] + ])( + '[%d] given %p as inputs, returns %p', + async (num: number, inputs: Map, expected: context.Inputs) => { + inputs.forEach((value: string, name: string) => { + setInput(name, value); + }); + expect(await context.getInputs()).toEqual(expected); + } + ); }); // See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67 diff --git a/__tests__/flavor.test.ts b/__tests__/flavor.test.ts index e016258..137e7e7 100644 --- a/__tests__/flavor.test.ts +++ b/__tests__/flavor.test.ts @@ -1,4 +1,5 @@ import {describe, expect, test} from '@jest/globals'; + import {Flavor, Transform} from '../src/flavor'; describe('transform', () => { diff --git a/__tests__/github.test.ts b/__tests__/github.test.ts deleted file mode 100644 index 591a867..0000000 --- a/__tests__/github.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import {describe, expect, jest, it} from '@jest/globals'; -import * as github from '../src/github'; - -import * as repoFixture from './fixtures/repo.json'; -jest.spyOn(github, 'repo').mockImplementation((): Promise => { - return >(repoFixture as unknown); -}); - -describe('repo', () => { - it('returns GitHub repository', async () => { - const repo = await github.repo(process.env.GITHUB_TOKEN || ''); - expect(repo.name).not.toBeNull(); - }); -}); diff --git a/__tests__/image.test.ts b/__tests__/image.test.ts index e885b13..0e82d81 100644 --- a/__tests__/image.test.ts +++ b/__tests__/image.test.ts @@ -1,4 +1,5 @@ import {describe, expect, test} from '@jest/globals'; + import {Transform, Image} from '../src/image'; describe('transform', () => { diff --git a/__tests__/meta.test.ts b/__tests__/meta.test.ts index d909414..e38dc70 100644 --- a/__tests__/meta.test.ts +++ b/__tests__/meta.test.ts @@ -2,19 +2,17 @@ import {beforeEach, describe, expect, jest, test} from '@jest/globals'; import * as fs from 'fs'; import * as path from 'path'; import * as dotenv from 'dotenv'; -import moment from 'moment-timezone'; -import {getInputs, Inputs} from '../src/context'; -import * as github from '../src/github'; -import {Meta, Version} from '../src/meta'; import {Context} from '@actions/github/lib/context'; +import {GitHub} from '@docker/actions-toolkit/lib/github'; +import {Toolkit} from '@docker/actions-toolkit/lib/toolkit'; +import {GitHubRepo} from '@docker/actions-toolkit/lib/types/github'; -import * as repoFixture from './fixtures/repo.json'; -jest.spyOn(github, 'repo').mockImplementation((): Promise => { - return >(repoFixture as unknown); -}); +import {getInputs, Inputs} from '../src/context'; +import {Meta, Version} from '../src/meta'; -jest.spyOn(github, 'context').mockImplementation((): Context => { - return new Context(); +import repoFixture from './fixtures/repo.json'; +jest.spyOn(GitHub.prototype, 'repoData').mockImplementation((): Promise => { + return >(repoFixture as unknown); }); jest.spyOn(global.Date.prototype, 'toISOString').mockImplementation(() => { @@ -26,6 +24,7 @@ jest.mock('moment-timezone', () => { }); beforeEach(() => { + jest.clearAllMocks(); Object.keys(process.env).forEach(function (key) { if (key !== 'GITHUB_TOKEN' && key.startsWith('GITHUB_')) { delete process.env[key]; @@ -48,10 +47,9 @@ describe('isRawStatement', () => { const tagsLabelsTest = async (name: string, envFile: string, inputs: Inputs, exVersion: Version, exTags: Array, exLabels: Array) => { process.env = dotenv.parse(fs.readFileSync(path.join(__dirname, 'fixtures', envFile))); - const context = github.context(); - - const repo = await github.repo(process.env.GITHUB_TOKEN || ''); - const meta = new Meta({...getInputs(), ...inputs}, context, repo); + const toolkit = new Toolkit(); + const repo = await toolkit.github.repoData(); + const meta = new Meta({...getInputs(), ...inputs}, new Context(), repo); const version = meta.version; expect(version).toEqual(exVersion); @@ -2765,10 +2763,10 @@ describe('pr-head-sha', () => { ])('given %p with %p event', async (name: string, envFile: string, inputs: Inputs, exVersion: Version, exTags: Array, exLabels: Array) => { process.env = dotenv.parse(fs.readFileSync(path.join(__dirname, 'fixtures', envFile))); process.env.DOCKER_METADATA_PR_HEAD_SHA = 'true'; - const context = github.context(); - const repo = await github.repo(process.env.GITHUB_TOKEN || ''); - const meta = new Meta({...getInputs(), ...inputs}, context, repo); + const toolkit = new Toolkit(); + const repo = await toolkit.github.repoData(); + const meta = new Meta({...getInputs(), ...inputs}, new Context(), repo); const version = meta.version; expect(version).toEqual(exVersion); @@ -3707,10 +3705,10 @@ describe('json', () => { ] ])('given %p with %p event', async (name: string, envFile: string, inputs: Inputs, exJSON: unknown) => { process.env = dotenv.parse(fs.readFileSync(path.join(__dirname, 'fixtures', envFile))); - const context = github.context(); - const repo = await github.repo(process.env.GITHUB_TOKEN || ''); - const meta = new Meta({...getInputs(), ...inputs}, context, repo); + const toolkit = new Toolkit(); + const repo = await toolkit.github.repoData(); + const meta = new Meta({...getInputs(), ...inputs}, new Context(), repo); const jsonOutput = meta.getJSON(); expect(jsonOutput).toEqual(exJSON); @@ -4013,10 +4011,10 @@ describe('bake', () => { ] ])('given %p with %p event', async (name: string, envFile: string, inputs: Inputs, exBakeDefinition: unknown) => { process.env = dotenv.parse(fs.readFileSync(path.join(__dirname, 'fixtures', envFile))); - const context = github.context(); - const repo = await github.repo(process.env.GITHUB_TOKEN || ''); - const meta = new Meta({...getInputs(), ...inputs}, context, repo); + const toolkit = new Toolkit(); + const repo = await toolkit.github.repoData(); + const meta = new Meta({...getInputs(), ...inputs}, new Context(), repo); const bakeFile = meta.getBakeFile(); expect(JSON.parse(fs.readFileSync(bakeFile, 'utf8'))).toEqual(exBakeDefinition); @@ -4059,10 +4057,10 @@ describe('sepTags', () => { ] ])('given %p with %p event', async (name: string, envFile: string, inputs: Inputs, expTags: string) => { process.env = dotenv.parse(fs.readFileSync(path.join(__dirname, 'fixtures', envFile))); - const context = github.context(); - const repo = await github.repo(process.env.GITHUB_TOKEN || ''); - const meta = new Meta({...getInputs(), ...inputs}, context, repo); + const toolkit = new Toolkit(); + const repo = await toolkit.github.repoData(); + const meta = new Meta({...getInputs(), ...inputs}, new Context(), repo); expect(meta.getTags().join(inputs.sepTags)).toEqual(expTags); }); diff --git a/__tests__/tag.test.ts b/__tests__/tag.test.ts index 962c858..3828e4f 100644 --- a/__tests__/tag.test.ts +++ b/__tests__/tag.test.ts @@ -1,4 +1,5 @@ import {describe, expect, test} from '@jest/globals'; + import {Transform, Parse, Tag, Type, RefEvent, ShaFormat, DefaultPriorities} from '../src/tag'; describe('transform', () => { diff --git a/dev.Dockerfile b/dev.Dockerfile index 682994c..33b4aca 100644 --- a/dev.Dockerfile +++ b/dev.Dockerfile @@ -16,14 +16,14 @@ COPY --from=deps /vendor / FROM deps AS vendor-validate RUN --mount=type=bind,target=.,rw <&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor-update"' - git status --porcelain -- yarn.lock - exit 1 -fi + set -e + git add -A + cp -rf /vendor/* . + if [ -n "$(git status --porcelain -- yarn.lock)" ]; then + echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor-update"' + git status --porcelain -- yarn.lock + exit 1 + fi EOT FROM deps AS build @@ -36,14 +36,14 @@ COPY --from=build /out / FROM build AS build-validate RUN --mount=type=bind,target=.,rw <&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"' - git status --porcelain -- dist - exit 1 -fi + set -e + git add -A + cp -rf /out/* . + if [ -n "$(git status --porcelain -- dist)" ]; then + echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"' + git status --porcelain -- dist + exit 1 + fi EOT FROM deps AS format diff --git a/jest.config.ts b/jest.config.ts index 7ff4e46..2973e9d 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,5 +1,21 @@ +import fs from 'fs'; +import os from 'os'; +import path from 'path'; + +const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-metadata-action-')); + +process.env = Object.assign({}, process.env, { + TEMP: tmpDir, + GITHUB_REPOSITORY: 'docker/metadata-action', + RUNNER_TEMP: path.join(tmpDir, 'runner-temp'), + RUNNER_TOOL_CACHE: path.join(tmpDir, 'runner-tool-cache') +}) as { + [key: string]: string; +}; + module.exports = { clearMocks: true, + testEnvironment: 'node', moduleFileExtensions: ['js', 'ts'], setupFiles: ['dotenv/config'], testMatch: ['**/*.test.ts'], @@ -9,5 +25,7 @@ module.exports = { moduleNameMapper: { '^csv-parse/sync': '/node_modules/csv-parse/dist/cjs/sync.cjs' }, + collectCoverageFrom: ['src/**/{!(main.ts),}.ts'], + coveragePathIgnorePatterns: ['lib/', 'node_modules/', '__mocks__/', '__tests__/'], verbose: true }; diff --git a/package.json b/package.json index 16a11a4..7098afb 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^5.1.1", + "@docker/actions-toolkit": "^0.1.0-beta.14", "@renovate/pep440": "^1.0.0", "csv-parse": "^5.3.3", "handlebars": "^4.7.7", diff --git a/src/context.ts b/src/context.ts index bb9c494..3738b23 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,10 +1,5 @@ -import * as fs from 'fs'; -import * as os from 'os'; -import * as path from 'path'; import * as core from '@actions/core'; -import {parse} from 'csv-parse/sync'; - -let _tmpDir: string; +import {Util} from '@docker/actions-toolkit/lib/util'; export interface Inputs { images: string[]; @@ -17,58 +12,15 @@ export interface Inputs { githubToken: string; } -export function tmpDir(): string { - if (!_tmpDir) { - _tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-metadata-action-')).split(path.sep).join(path.posix.sep); - } - return _tmpDir; -} - export function getInputs(): Inputs { return { - images: getInputList('images', true), - tags: getInputList('tags', true), - flavor: getInputList('flavor', true), - labels: getInputList('labels', true), + images: Util.getInputList('images', {ignoreComma: true}), + tags: Util.getInputList('tags', {ignoreComma: true}), + flavor: Util.getInputList('flavor', {ignoreComma: true}), + labels: Util.getInputList('labels', {ignoreComma: true}), sepTags: core.getInput('sep-tags', {trimWhitespace: false}) || `\n`, sepLabels: core.getInput('sep-labels', {trimWhitespace: false}) || `\n`, bakeTarget: core.getInput('bake-target') || `docker-metadata-action`, githubToken: core.getInput('github-token') }; } - -export function getInputList(name: string, ignoreComma?: boolean): string[] { - const res: Array = []; - - const items = core.getInput(name); - if (items == '') { - return res; - } - - const records = parse(items, { - columns: false, - relaxQuotes: true, - comment: '#', - relaxColumnCount: true, - skipEmptyLines: true - }); - - for (const record of records as Array) { - if (record.length == 1) { - res.push(record[0]); - continue; - } else if (!ignoreComma) { - res.push(...record); - continue; - } - res.push(record.join(',')); - } - - return res.filter(item => item).map(pat => pat.trim()); -} - -export const asyncForEach = async (array, callback) => { - for (let index = 0; index < array.length; index++) { - await callback(array[index], index, array); - } -}; diff --git a/src/github.ts b/src/github.ts deleted file mode 100644 index a5aed0f..0000000 --- a/src/github.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as github from '@actions/github'; -import {Context} from '@actions/github/lib/context'; -import {components as OctoOpenApiTypes} from '@octokit/openapi-types'; - -export type ReposGetResponseData = OctoOpenApiTypes['schemas']['repository']; - -export function context(): Context { - return github.context; -} - -export async function repo(token: string): Promise { - return github - .getOctokit(token) - .rest.repos.get({...github.context.repo}) - .then(response => response.data as ReposGetResponseData); -} diff --git a/src/main.ts b/src/main.ts index c2b70e3..f7bce9e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,34 +1,45 @@ import * as fs from 'fs'; -import {getInputs, Inputs} from './context'; -import * as github from './github'; -import {Meta, Version} from './meta'; import * as core from '@actions/core'; +import * as actionsToolkit from '@docker/actions-toolkit'; import {Context} from '@actions/github/lib/context'; +import {GitHub} from '@docker/actions-toolkit/lib/github'; +import {Toolkit} from '@docker/actions-toolkit/lib/toolkit'; -async function run() { - try { +import {getInputs, Inputs} from './context'; +import {Meta, Version} from './meta'; + +function setOutput(name: string, value: string) { + core.setOutput(name, value); + core.exportVariable(`DOCKER_METADATA_OUTPUT_${name.replace(/\W/g, '_').toUpperCase()}`, value); +} + +actionsToolkit.run( + // main + async () => { const inputs: Inputs = await getInputs(); if (inputs.images.length == 0) { throw new Error(`images input required`); } - const context: Context = github.context(); - const repo: github.ReposGetResponseData = await github.repo(inputs.githubToken); - core.startGroup(`Context info`); - core.info(`eventName: ${context.eventName}`); - core.info(`sha: ${context.sha}`); - core.info(`ref: ${context.ref}`); - core.info(`workflow: ${context.workflow}`); - core.info(`action: ${context.action}`); - core.info(`actor: ${context.actor}`); - core.info(`runNumber: ${context.runNumber}`); - core.info(`runId: ${context.runId}`); - core.endGroup(); + const toolkit = new Toolkit({githubToken: inputs.githubToken}); + const context: Context = GitHub.context; + const repo = await toolkit.github.repoData(); + + await core.group(`Context info`, async () => { + core.info(`eventName: ${context.eventName}`); + core.info(`sha: ${context.sha}`); + core.info(`ref: ${context.ref}`); + core.info(`workflow: ${context.workflow}`); + core.info(`action: ${context.action}`); + core.info(`actor: ${context.actor}`); + core.info(`runNumber: ${context.runNumber}`); + core.info(`runId: ${context.runId}`); + }); if (core.isDebug()) { - core.startGroup(`Webhook payload`); - core.info(JSON.stringify(context.payload, null, 2)); - core.endGroup(); + await core.group(`Webhook payload`, async () => { + core.info(JSON.stringify(context.payload, null, 2)); + }); } const meta: Meta = new Meta(inputs, context, repo); @@ -37,9 +48,9 @@ async function run() { if (meta.version.main == undefined || meta.version.main.length == 0) { core.warning(`No Docker image version has been generated. Check tags input.`); } else { - core.startGroup(`Docker image version`); - core.info(version.main || ''); - core.endGroup(); + await core.group(`Docker image version`, async () => { + core.info(version.main || ''); + }); } setOutput('version', version.main || ''); @@ -48,44 +59,35 @@ async function run() { if (tags.length == 0) { core.warning('No Docker tag has been generated. Check tags input.'); } else { - core.startGroup(`Docker tags`); - for (const tag of tags) { - core.info(tag); - } - core.endGroup(); + await core.group(`Docker tags`, async () => { + for (const tag of tags) { + core.info(tag); + } + }); } setOutput('tags', tags.join(inputs.sepTags)); // Docker labels const labels: Array = meta.getLabels(); - core.startGroup(`Docker labels`); - for (const label of labels) { - core.info(label); - } - core.endGroup(); - setOutput('labels', labels.join(inputs.sepLabels)); + await core.group(`Docker labels`, async () => { + for (const label of labels) { + core.info(label); + } + setOutput('labels', labels.join(inputs.sepLabels)); + }); // JSON const jsonOutput = meta.getJSON(); - core.startGroup(`JSON output`); - core.info(JSON.stringify(jsonOutput, null, 2)); - core.endGroup(); - setOutput('json', JSON.stringify(jsonOutput)); + await core.group(`JSON output`, async () => { + core.info(JSON.stringify(jsonOutput, null, 2)); + setOutput('json', JSON.stringify(jsonOutput)); + }); // Bake file definition const bakeFile: string = meta.getBakeFile(); - core.startGroup(`Bake file definition`); - core.info(fs.readFileSync(bakeFile, 'utf8')); - core.endGroup(); - setOutput('bake-file', bakeFile); - } catch (error) { - core.setFailed(error.message); + await core.group(`Bake file definition`, async () => { + core.info(fs.readFileSync(bakeFile, 'utf8')); + setOutput('bake-file', bakeFile); + }); } -} - -function setOutput(name: string, value: string) { - core.setOutput(name, value); - core.exportVariable(`DOCKER_METADATA_OUTPUT_${name.replace(/\W/g, '_').toUpperCase()}`, value); -} - -run(); +); diff --git a/src/meta.ts b/src/meta.ts index 4b45bc6..47d39e0 100644 --- a/src/meta.ts +++ b/src/meta.ts @@ -4,13 +4,15 @@ import * as path from 'path'; import moment from 'moment-timezone'; import * as pep440 from '@renovate/pep440'; import * as semver from 'semver'; -import {Inputs, tmpDir} from './context'; -import {ReposGetResponseData} from './github'; +import * as core from '@actions/core'; +import {Context} from '@actions/github/lib/context'; +import {Context as ToolkitContext} from '@docker/actions-toolkit/lib/context'; +import {GitHubRepo} from '@docker/actions-toolkit/lib/types/github'; + +import {Inputs} from './context'; import * as icl from './image'; import * as tcl from './tag'; import * as fcl from './flavor'; -import * as core from '@actions/core'; -import {Context} from '@actions/github/lib/context'; export interface Version { main: string | undefined; @@ -23,13 +25,13 @@ export class Meta { private readonly inputs: Inputs; private readonly context: Context; - private readonly repo: ReposGetResponseData; + private readonly repo: GitHubRepo; private readonly images: icl.Image[]; private readonly tags: tcl.Tag[]; private readonly flavor: fcl.Flavor; private readonly date: Date; - constructor(inputs: Inputs, context: Context, repo: ReposGetResponseData) { + constructor(inputs: Inputs, context: Context, repo: GitHubRepo) { // Needs to override Git reference with pr ref instead of upstream branch ref // for pull_request_target event // https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target @@ -498,7 +500,7 @@ export class Meta { } public getBakeFile(): string { - const bakeFile = path.join(tmpDir(), 'docker-metadata-action-bake.json').split(path.sep).join(path.posix.sep); + const bakeFile = path.join(ToolkitContext.tmpDir(), 'docker-metadata-action-bake.json'); fs.writeFileSync( bakeFile, JSON.stringify( diff --git a/tsconfig.json b/tsconfig.json index 47183d4..04c6783 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,20 +1,21 @@ { "compilerOptions": { + "esModuleInterop": true, "target": "es6", "module": "commonjs", + "strict": true, "newLine": "lf", "outDir": "./lib", "rootDir": "./src", - "esModuleInterop": true, "forceConsistentCasingInFileNames": true, - "strict": true, "noImplicitAny": false, "resolveJsonModule": true, "useUnknownInCatchVariables": false, }, "exclude": [ + "./__tests__/**/*", + "./lib/**/*", "node_modules", - "**/*.test.ts", "jest.config.ts" ] } diff --git a/yarn.lock b/yarn.lock index 6a26bfc..5947970 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@actions/core@^1.10.0": +"@actions/core@^1.10.0", "@actions/core@^1.2.6": version "1.10.0" resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.0.tgz#44551c3c71163949a2f06e94d9ca2157a0cfac4f" integrity sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug== @@ -10,6 +10,13 @@ "@actions/http-client" "^2.0.1" uuid "^8.3.2" +"@actions/exec@^1.0.0", "@actions/exec@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@actions/exec/-/exec-1.1.1.tgz#2e43f28c54022537172819a7cf886c844221a611" + integrity sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w== + dependencies: + "@actions/io" "^1.0.1" + "@actions/github@^5.1.1": version "5.1.1" resolved "https://registry.yarnpkg.com/@actions/github/-/github-5.1.1.tgz#40b9b9e1323a5efcf4ff7dadd33d8ea51651bbcb" @@ -27,6 +34,23 @@ dependencies: tunnel "^0.0.6" +"@actions/io@^1.0.1", "@actions/io@^1.1.1", "@actions/io@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.2.tgz#766ac09674a289ce0f1550ffe0a6eac9261a8ea9" + integrity sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw== + +"@actions/tool-cache@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@actions/tool-cache/-/tool-cache-2.0.1.tgz#8a649b9c07838d9d750c9864814e66a7660ab720" + integrity sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA== + dependencies: + "@actions/core" "^1.2.6" + "@actions/exec" "^1.0.0" + "@actions/http-client" "^2.0.1" + "@actions/io" "^1.1.1" + semver "^6.1.0" + uuid "^3.3.2" + "@ampproject/remapping@^2.1.0": version "2.1.2" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" @@ -542,6 +566,22 @@ dependencies: "@cspotcode/source-map-consumer" "0.8.0" +"@docker/actions-toolkit@^0.1.0-beta.14": + version "0.1.0-beta.14" + resolved "https://registry.yarnpkg.com/@docker/actions-toolkit/-/actions-toolkit-0.1.0-beta.14.tgz#82fa8a6b9802a7f770fde3ddcef1cf591739a80b" + integrity sha512-N+aqiO0E2ygoaBORN8fx4K7j/CzJ2nCSgOewtDm0gdzrch8qZmTU14e3oNAbZlP8Q34Lk45KKefm5wDfLipRqg== + dependencies: + "@actions/core" "^1.10.0" + "@actions/exec" "^1.1.1" + "@actions/github" "^5.1.1" + "@actions/http-client" "^2.0.1" + "@actions/io" "^1.1.2" + "@actions/tool-cache" "^2.0.1" + csv-parse "^5.3.5" + jwt-decode "^3.1.2" + semver "^7.3.8" + tmp "^0.2.1" + "@eslint/eslintrc@^1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.1.tgz#8b5e1c49f4077235516bc9ec7d41378c0f69b8c6" @@ -1610,6 +1650,11 @@ csv-parse@*, csv-parse@^5.3.3: resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-5.3.3.tgz#3b75d2279e2edb550cbc54c65b25cbbf3d0033ad" integrity sha512-kEWkAPleNEdhFNkHQpFHu9RYPogsFj3dx6bCxL847fsiLgidzWg0z/O0B1kVWMJUc5ky64zGp18LX2T3DQrOfw== +csv-parse@^5.3.5: + version "5.3.5" + resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-5.3.5.tgz#9924bbba9f7056122f06b7af18edc1a7f022ce99" + integrity sha512-8O5KTIRtwmtD3+EVfW6BCgbwZqJbhTYsQZry12F1TP5RUp0sD9tp1UnCWic3n0mLOhzeocYaCZNYxOGSg3dmmQ== + data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -2826,6 +2871,11 @@ json5@2.x, json5@^2.1.2: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jwt-decode@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59" + integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A== + kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -3292,11 +3342,18 @@ semver@7.x, semver@^7.3.2, semver@^7.3.5, semver@^7.3.7: dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.8: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -3476,6 +3533,13 @@ throat@^6.0.1: resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== +tmp@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + tmpl@1.0.x: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -3627,6 +3691,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"