diff --git a/__tests__/fixtures/hello-err.Dockerfile b/__tests__/fixtures/hello-err.Dockerfile new file mode 100644 index 0000000..5bc7b36 --- /dev/null +++ b/__tests__/fixtures/hello-err.Dockerfile @@ -0,0 +1,19 @@ +# syntax=docker/dockerfile:1 + +# Copyright 2024 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. + +FROM busybox:latest +ARGGG NAME=foo +RUN echo "hello $NAME" diff --git a/__tests__/github.test.itg.ts b/__tests__/github.test.itg.ts index 2163a76..12ce561 100644 --- a/__tests__/github.test.itg.ts +++ b/__tests__/github.test.itg.ts @@ -118,29 +118,20 @@ maybe('writeBuildSummary', () => { test.each([ [ 'single', - [ - 'bake', - '-f', path.join(fixturesDir, 'hello-bake.hcl'), - 'hello' - ], + path.join(fixturesDir, 'hello-bake.hcl'), + 'hello' ], [ 'group', - [ - 'bake', - '-f', path.join(fixturesDir, 'hello-bake.hcl'), - 'hello-all' - ], + path.join(fixturesDir, 'hello-bake.hcl'), + 'hello-all' ], [ 'matrix', - [ - 'bake', - '-f', path.join(fixturesDir, 'hello-bake.hcl'), - 'hello-matrix' - ], + path.join(fixturesDir, 'hello-bake.hcl'), + 'hello-matrix' ] - ])('write bake summary %p', async (_, bargs) => { + ])('write bake summary %p', async (_, file, target) => { const buildx = new Buildx(); const bake = new Bake({buildx: buildx}); @@ -150,7 +141,9 @@ maybe('writeBuildSummary', () => { // prettier-ignore const buildCmd = await buildx.getCommand([ '--builder', process.env.CTN_BUILDER_NAME ?? 'default', - ...bargs, + 'bake', + '-f', file, + target, '--metadata-file', bake.getMetadataFilePath() ]); await Exec.exec(buildCmd.command, buildCmd.args, { @@ -159,6 +152,16 @@ maybe('writeBuildSummary', () => { })() ).resolves.not.toThrow(); + const definition = await bake.getDefinition( + { + files: [file], + targets: [target], + }, + { + cwd: fixturesDir + } + ); + const metadata = bake.resolveMetadata(); expect(metadata).toBeDefined(); const buildRefs = bake.resolveRefs(metadata); @@ -186,6 +189,62 @@ maybe('writeBuildSummary', () => { uploadRes: uploadRes, inputs: { files: path.join(fixturesDir, 'hello-bake.hcl') + }, + bakeDefinition: definition + }); + }); + + it('fails with dockerfile syntax issue', async () => { + const startedTime = new Date(); + const buildx = new Buildx(); + const build = new Build({buildx: buildx}); + + fs.mkdirSync(tmpDir, {recursive: true}); + await expect( + (async () => { + // prettier-ignore + const buildCmd = await buildx.getCommand([ + '--builder', process.env.CTN_BUILDER_NAME ?? 'default', + 'build', + '-f', path.join(fixturesDir, 'hello-err.Dockerfile'), + fixturesDir, + '--metadata-file', build.getMetadataFilePath() + ]); + await Exec.exec(buildCmd.command, buildCmd.args); + })() + ).rejects.toThrow(); + + const refs = Buildx.refs({ + dir: Buildx.refsDir, + builderName: process.env.CTN_BUILDER_NAME ?? 'default', + since: startedTime + }); + expect(refs).toBeDefined(); + expect(Object.keys(refs).length).toBeGreaterThan(0); + + const history = new History({buildx: buildx}); + const exportRes = await history.export({ + refs: [Object.keys(refs)[0] ?? ''] + }); + expect(exportRes).toBeDefined(); + expect(exportRes?.dockerbuildFilename).toBeDefined(); + expect(exportRes?.dockerbuildSize).toBeDefined(); + expect(exportRes?.summaries).toBeDefined(); + + const uploadRes = await GitHub.uploadArtifact({ + filename: exportRes?.dockerbuildFilename, + mimeType: 'application/gzip', + retentionDays: 1 + }); + expect(uploadRes).toBeDefined(); + expect(uploadRes?.url).toBeDefined(); + + await GitHub.writeBuildSummary({ + exportRes: exportRes, + uploadRes: uploadRes, + inputs: { + context: fixturesDir, + file: path.join(fixturesDir, 'hello-err.Dockerfile') } }); }); diff --git a/__tests__/util.test.ts b/__tests__/util.test.ts index 9305a93..6889c1b 100644 --- a/__tests__/util.test.ts +++ b/__tests__/util.test.ts @@ -380,6 +380,42 @@ describe('stringToUnicodeEntities', () => { }); }); +describe('countLines', () => { + it('counts total number of lines correctly', () => { + const text = `This + +is +a +sample + +text +with +multiple +lines`; + + const result = Util.countLines(text); + expect(result).toEqual(10); // Including empty lines + }); + it('handles edge case with empty string', () => { + const text = ''; + + const result = Util.countLines(text); + expect(result).toEqual(1); // Empty string should have 1 line + }); + it('handles edge case with single line', () => { + const text = 'Single line text'; + + const result = Util.countLines(text); + expect(result).toEqual(1); // Single line should have 1 line + }); + it('handles multiple types of line breaks', () => { + const text = `Line 1\r\nLine 2\rLine 3\nLine 4`; + + const result = Util.countLines(text); + expect(result).toEqual(4); // Different line break types should be counted correctly + }); +}); + // See: https://github.com/actions/toolkit/blob/a1b068ec31a042ff1e10a522d8fdf0b8869d53ca/packages/core/src/core.ts#L89 function getInputName(name: string): string { return `INPUT_${name.replace(/ /g, '_').toUpperCase()}`; diff --git a/src/github.ts b/src/github.ts index 5fd1d5a..a087fb5 100644 --- a/src/github.ts +++ b/src/github.ts @@ -229,7 +229,7 @@ export class GitHub { // prettier-ignore const sum = core.summary - .addHeading('Docker Build summary', 1) + .addHeading('Docker Build summary', 2) .addRaw(`
`) .addRaw(`For a detailed look at the build, download the following build record archive and import it into Docker Desktop's Builds view. `) .addBreak() @@ -246,8 +246,8 @@ export class GitHub { .addRaw(addLink('Let us know', 'https://docs.docker.com/feedback/gha-build-summary')) .addRaw('
'); - sum.addHeading('Preview', 2); - + // Preview + sum.addRaw(`Preview`).addBreak().addRaw('');
const summaryTableData: Array
`); + if (Util.countLines(buildError) > 10) { + // prettier-ignore + sum + .addRaw(``); } + // Build inputs if (opts.inputs) { - sum.addHeading('Build inputs', 2).addCodeBlock( - jsyaml.dump(opts.inputs, { - indent: 2, - lineWidth: -1 - }), - 'yaml' - ); + // prettier-ignore + sum.addRaw(``); + } else { + // prettier-ignore + sum + .addRaw(`Error`) + .addBreak() + .addRaw(`Error
`) + .addCodeBlock(buildError, 'text') + .addRaw(``) + .addCodeBlock(buildError, 'text') + .addRaw(`
`); + } + sum.addRaw(`