Skip to content

Commit 6460b33

Browse files
authored
Merge pull request #208 from crazy-max/build-summary
export build record and generate summary
2 parents bc96707 + bc3c21b commit 6460b33

File tree

7 files changed

+164
-4
lines changed

7 files changed

+164
-4
lines changed

.github/workflows/ci.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,3 +522,27 @@ jobs:
522522
name: Check docker
523523
run: |
524524
docker image inspect localhost:5000/name/app:latest
525+
526+
disable-summary:
527+
runs-on: ubuntu-latest
528+
steps:
529+
-
530+
name: Checkout
531+
uses: actions/checkout@v4
532+
-
533+
name: Set up Docker Buildx
534+
uses: docker/setup-buildx-action@v3
535+
with:
536+
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
537+
driver-opts: |
538+
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
539+
network=host
540+
-
541+
name: Build
542+
uses: ./
543+
with:
544+
files: |
545+
./test/config.hcl
546+
targets: app
547+
env:
548+
DOCKER_BUILD_NO_SUMMARY: true

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ ___
1919
* [Customizing](#customizing)
2020
* [inputs](#inputs)
2121
* [outputs](#outputs)
22+
* [environment variables](#environment-variables)
2223
* [Subactions](#subactions)
2324
* [`list-targets`](#list-targets)
2425
* [Contributing](#contributing)
@@ -255,6 +256,12 @@ The following outputs are available
255256
|------------|----------|----------------------------|
256257
| `targets` | List/CSV | List of extracted targest |
257258

259+
### environment variables
260+
261+
| Name | Type | Description |
262+
|---------------------------|------|-------------------------------------------------------------------------------------------------------------------|
263+
| `DOCKER_BUILD_NO_SUMMARY` | Bool | If `true`, [build summary](https://docs.docker.com/build/ci/github-actions/build-summary/) generation is disabled |
264+
258265
## Contributing
259266

260267
Want to contribute? Awesome! You can find information about contributing to

dist/index.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/context.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,28 @@ export async function getInputs(): Promise<Inputs> {
4444
};
4545
}
4646

47+
export function sanitizeInputs(inputs: Inputs) {
48+
const res = {};
49+
for (const key of Object.keys(inputs)) {
50+
if (key === 'github-token') {
51+
continue;
52+
}
53+
const value: string | string[] | boolean = inputs[key];
54+
if (typeof value === 'boolean' && value === false) {
55+
continue;
56+
} else if (Array.isArray(value) && value.length === 0) {
57+
continue;
58+
} else if (!value) {
59+
continue;
60+
}
61+
if (key === 'workdir' && value === '.') {
62+
continue;
63+
}
64+
res[key] = value;
65+
}
66+
return res;
67+
}
68+
4769
export async function getArgs(inputs: Inputs, definition: BakeDefinition, toolkit: Toolkit): Promise<Array<string>> {
4870
// prettier-ignore
4971
return [

src/main.ts

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ import * as path from 'path';
33
import * as core from '@actions/core';
44
import * as actionsToolkit from '@docker/actions-toolkit';
55

6+
import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx';
7+
import {History as BuildxHistory} from '@docker/actions-toolkit/lib/buildx/history';
68
import {Context} from '@docker/actions-toolkit/lib/context';
79
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
810
import {Exec} from '@docker/actions-toolkit/lib/exec';
911
import {GitHub} from '@docker/actions-toolkit/lib/github';
1012
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
13+
import {Util} from '@docker/actions-toolkit/lib/util';
1114

1215
import {BakeDefinition} from '@docker/actions-toolkit/lib/types/buildx/bake';
1316
import {ConfigFile} from '@docker/actions-toolkit/lib/types/docker/docker';
@@ -18,7 +21,12 @@ import * as stateHelper from './state-helper';
1821
actionsToolkit.run(
1922
// main
2023
async () => {
24+
const startedTime = new Date();
25+
2126
const inputs: context.Inputs = await context.getInputs();
27+
core.debug(`inputs: ${JSON.stringify(inputs)}`);
28+
stateHelper.setInputs(inputs);
29+
2230
const toolkit = new Toolkit();
2331
const gitAuthToken = process.env.BUILDX_BAKE_GIT_AUTH_TOKEN ?? inputs['github-token'];
2432

@@ -78,6 +86,7 @@ actionsToolkit.run(
7886
await core.group(`Builder info`, async () => {
7987
const builder = await toolkit.builder.inspect(inputs.builder);
8088
core.info(JSON.stringify(builder, null, 2));
89+
stateHelper.setBuilder(builder);
8190
});
8291

8392
let definition: BakeDefinition | undefined;
@@ -103,6 +112,7 @@ actionsToolkit.run(
103112
if (!definition) {
104113
throw new Error('Bake definition not set');
105114
}
115+
stateHelper.setBakeDefinition(definition);
106116

107117
const args: string[] = await context.getArgs(inputs, definition, toolkit);
108118
const buildCmd = await toolkit.buildx.getCommand(args);
@@ -119,13 +129,14 @@ actionsToolkit.run(
119129
});
120130
});
121131

132+
let err: Error | undefined;
122133
await Exec.getExecOutput(buildCmd.command, buildCmd.args, {
123134
cwd: inputs.workdir,
124135
env: buildEnv,
125136
ignoreReturnCode: true
126137
}).then(res => {
127138
if (res.stderr.length > 0 && res.exitCode != 0) {
128-
throw new Error(`buildx bake failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
139+
err = Error(`buildx bake failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
129140
}
130141
});
131142

@@ -137,13 +148,84 @@ actionsToolkit.run(
137148
core.setOutput('metadata', metadatadt);
138149
});
139150
}
151+
await core.group(`Build references`, async () => {
152+
const refs = await buildRefs(toolkit, startedTime, inputs.builder);
153+
if (refs) {
154+
for (const ref of refs) {
155+
core.info(ref);
156+
}
157+
stateHelper.setBuildRefs(refs);
158+
} else {
159+
core.warning('No build refs found');
160+
}
161+
});
162+
if (err) {
163+
throw err;
164+
}
140165
},
141166
// post
142167
async () => {
168+
if (stateHelper.buildRefs.length > 0) {
169+
await core.group(`Generating build summary`, async () => {
170+
if (process.env.DOCKER_BUILD_NO_SUMMARY && Util.parseBool(process.env.DOCKER_BUILD_NO_SUMMARY)) {
171+
core.info('Summary disabled');
172+
return;
173+
}
174+
if (stateHelper.builder && stateHelper.builder.driver === 'cloud') {
175+
core.info('Summary is not yet supported with Docker Build Cloud');
176+
return;
177+
}
178+
try {
179+
const buildxHistory = new BuildxHistory();
180+
const exportRes = await buildxHistory.export({
181+
refs: stateHelper.buildRefs
182+
});
183+
core.info(`Build records exported to ${exportRes.dockerbuildFilename} (${Util.formatFileSize(exportRes.dockerbuildSize)})`);
184+
const uploadRes = await GitHub.uploadArtifact({
185+
filename: exportRes.dockerbuildFilename,
186+
mimeType: 'application/gzip',
187+
retentionDays: 90
188+
});
189+
await GitHub.writeBuildSummary({
190+
exportRes: exportRes,
191+
uploadRes: uploadRes,
192+
inputs: stateHelper.inputs,
193+
bakeDefinition: stateHelper.bakeDefinition
194+
});
195+
} catch (e) {
196+
core.warning(e.message);
197+
}
198+
});
199+
}
143200
if (stateHelper.tmpDir.length > 0) {
144201
await core.group(`Removing temp folder ${stateHelper.tmpDir}`, async () => {
145202
fs.rmSync(stateHelper.tmpDir, {recursive: true});
146203
});
147204
}
148205
}
149206
);
207+
208+
async function buildRefs(toolkit: Toolkit, since: Date, builder?: string): Promise<Array<string>> {
209+
// get refs from metadata file
210+
const metaRefs = toolkit.buildxBake.resolveRefs();
211+
if (metaRefs) {
212+
return metaRefs;
213+
}
214+
// otherwise, look for the very first build ref since the build has started
215+
if (!builder) {
216+
const currentBuilder = await toolkit.builder.inspect();
217+
builder = currentBuilder.name;
218+
}
219+
const res = Buildx.refs({
220+
dir: Buildx.refsDir,
221+
builderName: builder,
222+
since: since
223+
});
224+
const refs: Array<string> = [];
225+
for (const ref in res) {
226+
if (Object.prototype.hasOwnProperty.call(res, ref)) {
227+
refs.push(ref);
228+
}
229+
}
230+
return refs;
231+
}

src/state-helper.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,32 @@
11
import * as core from '@actions/core';
22

3+
import {BakeDefinition} from '@docker/actions-toolkit/lib/types/buildx/bake';
4+
import {BuilderInfo} from '@docker/actions-toolkit/lib/types/buildx/builder';
5+
6+
import {Inputs, sanitizeInputs} from './context';
7+
38
export const tmpDir = process.env['STATE_tmpDir'] || '';
9+
export const inputs = process.env['STATE_inputs'] ? JSON.parse(process.env['STATE_inputs']) : undefined;
10+
export const builder = process.env['STATE_builder'] ? <BuilderInfo>JSON.parse(process.env['STATE_builder']) : undefined;
11+
export const bakeDefinition = process.env['STATE_bakeDefinition'] ? <BakeDefinition>JSON.parse(process.env['STATE_bakeDefinition']) : undefined;
12+
export const buildRefs = process.env['STATE_buildRefs'] ? process.env['STATE_buildRefs'].split(',') : [];
413

514
export function setTmpDir(tmpDir: string) {
615
core.saveState('tmpDir', tmpDir);
716
}
17+
18+
export function setInputs(inputs: Inputs) {
19+
core.saveState('inputs', JSON.stringify(sanitizeInputs(inputs)));
20+
}
21+
22+
export function setBuilder(builder: BuilderInfo) {
23+
core.saveState('builder', JSON.stringify(builder));
24+
}
25+
26+
export function setBakeDefinition(bakeDefinition: BakeDefinition) {
27+
core.saveState('bakeDefinition', JSON.stringify(bakeDefinition));
28+
}
29+
30+
export function setBuildRefs(buildRefs: Array<string>) {
31+
core.saveState('buildRefs', buildRefs.join(','));
32+
}

0 commit comments

Comments
 (0)