Skip to content

Commit c382f71

Browse files
authored
Merge pull request #1120 from crazy-max/build-summary
export build record and generate summary
2 parents 86c2bd0 + 5a5b70d commit c382f71

File tree

8 files changed

+142
-5
lines changed

8 files changed

+142
-5
lines changed

.github/workflows/ci.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,3 +1344,26 @@ jobs:
13441344
name: Check docker
13451345
run: |
13461346
docker image inspect localhost:5000/name/app:latest
1347+
1348+
disable-summary:
1349+
runs-on: ubuntu-latest
1350+
steps:
1351+
-
1352+
name: Checkout
1353+
uses: actions/checkout@v4
1354+
with:
1355+
path: action
1356+
-
1357+
name: Set up Docker Buildx
1358+
uses: docker/setup-buildx-action@v3
1359+
with:
1360+
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
1361+
driver-opts: |
1362+
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
1363+
-
1364+
name: Build
1365+
uses: ./action
1366+
with:
1367+
file: ./test/Dockerfile
1368+
env:
1369+
DOCKER_BUILD_NO_SUMMARY: true

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ ___
3737
* [Customizing](#customizing)
3838
* [inputs](#inputs)
3939
* [outputs](#outputs)
40+
* [environment variables](#environment-variables)
4041
* [Troubleshooting](#troubleshooting)
4142
* [Contributing](#contributing)
4243

@@ -256,6 +257,12 @@ The following outputs are available:
256257
| `digest` | String | Image digest |
257258
| `metadata` | JSON | Build result metadata |
258259

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

261268
See [TROUBLESHOOTING.md](TROUBLESHOOTING.md)

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.

dist/licenses.txt

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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,25 @@ export async function getInputs(): Promise<Inputs> {
7979
};
8080
}
8181

82+
export function sanitizeInputs(inputs: Inputs) {
83+
const res = {};
84+
for (const key of Object.keys(inputs)) {
85+
if (key === 'github-token') {
86+
continue;
87+
}
88+
const value: string | string[] | boolean = inputs[key];
89+
if (typeof value === 'boolean' && value === false) {
90+
continue;
91+
} else if (Array.isArray(value) && value.length === 0) {
92+
continue;
93+
} else if (!value) {
94+
continue;
95+
}
96+
res[key] = value;
97+
}
98+
return res;
99+
}
100+
82101
export async function getArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> {
83102
const context = handlebars.compile(inputs.context)({
84103
defaultContext: Context.gitContext()

src/main.ts

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import * as stateHelper from './state-helper';
44
import * as core from '@actions/core';
55
import * as actionsToolkit from '@docker/actions-toolkit';
66

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

1316
import {ConfigFile} from '@docker/actions-toolkit/lib/types/docker/docker';
1417

@@ -17,8 +20,10 @@ import * as context from './context';
1720
actionsToolkit.run(
1821
// main
1922
async () => {
23+
const startedTime = new Date();
2024
const inputs: context.Inputs = await context.getInputs();
2125
core.debug(`inputs: ${JSON.stringify(inputs)}`);
26+
stateHelper.setInputs(inputs);
2227

2328
const toolkit = new Toolkit();
2429

@@ -78,6 +83,7 @@ actionsToolkit.run(
7883
await core.group(`Builder info`, async () => {
7984
const builder = await toolkit.builder.inspect(inputs.builder);
8085
core.info(JSON.stringify(builder, null, 2));
86+
stateHelper.setBuilder(builder);
8187
});
8288

8389
const args: string[] = await context.getArgs(inputs, toolkit);
@@ -87,11 +93,12 @@ actionsToolkit.run(
8793
core.debug(`buildCmd.command: ${buildCmd.command}`);
8894
core.debug(`buildCmd.args: ${JSON.stringify(buildCmd.args)}`);
8995

96+
let err: Error | undefined;
9097
await Exec.getExecOutput(buildCmd.command, buildCmd.args, {
9198
ignoreReturnCode: true
9299
}).then(res => {
93100
if (res.stderr.length > 0 && res.exitCode != 0) {
94-
throw new Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
101+
err = Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
95102
}
96103
});
97104

@@ -118,13 +125,75 @@ actionsToolkit.run(
118125
core.setOutput('metadata', metadatadt);
119126
});
120127
}
128+
await core.group(`Reference`, async () => {
129+
const ref = await buildRef(toolkit, startedTime, inputs.builder);
130+
if (ref) {
131+
core.info(ref);
132+
stateHelper.setBuildRef(ref);
133+
} else {
134+
core.warning('No build ref found');
135+
}
136+
});
137+
if (err) {
138+
throw err;
139+
}
121140
},
122141
// post
123142
async () => {
143+
if (stateHelper.buildRef.length > 0) {
144+
await core.group(`Generating build summary`, async () => {
145+
if (process.env.DOCKER_BUILD_NO_SUMMARY && Util.parseBool(process.env.DOCKER_BUILD_NO_SUMMARY)) {
146+
core.info('Summary disabled');
147+
return;
148+
}
149+
if (stateHelper.builder && stateHelper.builder.driver === 'cloud') {
150+
core.info('Summary is not yet supported with Docker Build Cloud');
151+
return;
152+
}
153+
try {
154+
const buildxHistory = new BuildxHistory();
155+
const exportRes = await buildxHistory.export({
156+
refs: [stateHelper.buildRef]
157+
});
158+
core.info(`Build record exported to ${exportRes.dockerbuildFilename} (${Util.formatFileSize(exportRes.dockerbuildSize)})`);
159+
const uploadRes = await GitHub.uploadArtifact({
160+
filename: exportRes.dockerbuildFilename,
161+
mimeType: 'application/gzip',
162+
retentionDays: 90
163+
});
164+
await GitHub.writeBuildSummary({
165+
exportRes: exportRes,
166+
uploadRes: uploadRes,
167+
inputs: stateHelper.inputs
168+
});
169+
} catch (e) {
170+
core.warning(e.message);
171+
}
172+
});
173+
}
124174
if (stateHelper.tmpDir.length > 0) {
125175
await core.group(`Removing temp folder ${stateHelper.tmpDir}`, async () => {
126176
fs.rmSync(stateHelper.tmpDir, {recursive: true});
127177
});
128178
}
129179
}
130180
);
181+
182+
async function buildRef(toolkit: Toolkit, since: Date, builder?: string): Promise<string> {
183+
// get ref from metadata file
184+
const ref = toolkit.buildxBuild.resolveRef();
185+
if (ref) {
186+
return ref;
187+
}
188+
// otherwise, look for the very first build ref since the build has started
189+
if (!builder) {
190+
const currentBuilder = await toolkit.builder.inspect();
191+
builder = currentBuilder.name;
192+
}
193+
const refs = Buildx.refs({
194+
dir: Buildx.refsDir,
195+
builderName: builder,
196+
since: since
197+
});
198+
return Object.keys(refs).length > 0 ? Object.keys(refs)[0] : '';
199+
}

src/state-helper.ts

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

3+
import {BuilderInfo} from '@docker/actions-toolkit/lib/types/buildx/builder';
4+
5+
import {Inputs, sanitizeInputs} from './context';
6+
37
export const tmpDir = process.env['STATE_tmpDir'] || '';
8+
export const inputs = process.env['STATE_inputs'] ? JSON.parse(process.env['STATE_inputs']) : undefined;
9+
export const builder = process.env['STATE_builder'] ? <BuilderInfo>JSON.parse(process.env['STATE_builder']) : undefined;
10+
export const buildRef = process.env['STATE_buildRef'] || '';
411

512
export function setTmpDir(tmpDir: string) {
613
core.saveState('tmpDir', tmpDir);
714
}
15+
16+
export function setInputs(inputs: Inputs) {
17+
core.saveState('inputs', JSON.stringify(sanitizeInputs(inputs)));
18+
}
19+
20+
export function setBuilder(builder: BuilderInfo) {
21+
core.saveState('builder', JSON.stringify(builder));
22+
}
23+
24+
export function setBuildRef(buildRef: string) {
25+
core.saveState('buildRef', buildRef);
26+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy