mirror of
https://github.com/docker/build-push-action
synced 2024-11-22 18:31:40 +00:00
Add metadata
output
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
parent
ad1d2e93be
commit
c0b121fe44
9 changed files with 104 additions and 47 deletions
24
.github/workflows/ci.yml
vendored
24
.github/workflows/ci.yml
vendored
|
@ -70,9 +70,6 @@ jobs:
|
||||||
name: Inspect
|
name: Inspect
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
||||||
-
|
|
||||||
name: Image digest
|
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
|
||||||
-
|
-
|
||||||
name: Check digest
|
name: Check digest
|
||||||
run: |
|
run: |
|
||||||
|
@ -133,9 +130,6 @@ jobs:
|
||||||
name: Inspect
|
name: Inspect
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
||||||
-
|
|
||||||
name: Image digest
|
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
|
||||||
-
|
-
|
||||||
name: Check digest
|
name: Check digest
|
||||||
run: |
|
run: |
|
||||||
|
@ -191,9 +185,6 @@ jobs:
|
||||||
name: Inspect
|
name: Inspect
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
||||||
-
|
|
||||||
name: Image digest
|
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
|
||||||
-
|
-
|
||||||
name: Check digest
|
name: Check digest
|
||||||
run: |
|
run: |
|
||||||
|
@ -392,9 +383,6 @@ jobs:
|
||||||
name: Inspect
|
name: Inspect
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
||||||
-
|
|
||||||
name: Image digest
|
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
|
||||||
-
|
-
|
||||||
name: Check digest
|
name: Check digest
|
||||||
run: |
|
run: |
|
||||||
|
@ -447,9 +435,6 @@ jobs:
|
||||||
name: Inspect (1)
|
name: Inspect (1)
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect localhost:5000/name/app:latest
|
docker buildx imagetools inspect localhost:5000/name/app:latest
|
||||||
-
|
|
||||||
name: Image digest (1)
|
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
|
||||||
-
|
-
|
||||||
name: Check digest (1)
|
name: Check digest (1)
|
||||||
run: |
|
run: |
|
||||||
|
@ -480,9 +465,6 @@ jobs:
|
||||||
name: Inspect (2)
|
name: Inspect (2)
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect localhost:5000/name/app:latest
|
docker buildx imagetools inspect localhost:5000/name/app:latest
|
||||||
-
|
|
||||||
name: Image digest (2)
|
|
||||||
run: echo ${{ steps.docker_build2.outputs.digest }}
|
|
||||||
-
|
-
|
||||||
name: Check digest (2)
|
name: Check digest (2)
|
||||||
run: |
|
run: |
|
||||||
|
@ -557,9 +539,6 @@ jobs:
|
||||||
name: Inspect
|
name: Inspect
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
||||||
-
|
|
||||||
name: Image digest
|
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
|
||||||
-
|
-
|
||||||
name: Check digest
|
name: Check digest
|
||||||
run: |
|
run: |
|
||||||
|
@ -622,9 +601,6 @@ jobs:
|
||||||
name: Inspect
|
name: Inspect
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
|
||||||
-
|
|
||||||
name: Image digest
|
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
|
||||||
-
|
-
|
||||||
name: Check digest
|
name: Check digest
|
||||||
run: |
|
run: |
|
||||||
|
|
10
README.md
10
README.md
|
@ -100,9 +100,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
push: true
|
push: true
|
||||||
tags: user/app:latest
|
tags: user/app:latest
|
||||||
-
|
|
||||||
name: Image digest
|
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Building from the current repository automatically uses the [GitHub Token](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token)
|
Building from the current repository automatically uses the [GitHub Token](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token)
|
||||||
|
@ -223,9 +220,10 @@ Following inputs can be used as `step.with` keys
|
||||||
|
|
||||||
Following outputs are available
|
Following outputs are available
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
|---------------|---------|---------------------------------------|
|
|-------------------|---------|---------------------------------------|
|
||||||
| `digest` | String | Image content-addressable identifier also called a digest |
|
| `digest` | String | Image content-addressable identifier also called a digest |
|
||||||
|
| `metadata` | JSON | Build result metadata |
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,10 @@ import * as context from '../src/context';
|
||||||
|
|
||||||
const tmpNameSync = path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
|
const tmpNameSync = path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
|
||||||
const digest = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9';
|
const digest = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9';
|
||||||
|
const metadata = `{
|
||||||
|
"containerimage.config.digest": "sha256:059b68a595b22564a1cbc167af369349fdc2ecc1f7bc092c2235cbf601a795fd",
|
||||||
|
"containerimage.digest": "sha256:b09b9482c72371486bb2c1d2c2a2633ed1d0b8389e12c8d52b9e052725c0c83c"
|
||||||
|
}`;
|
||||||
|
|
||||||
jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
|
jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
|
||||||
const tmpDir = path.join('/tmp/.docker-build-push-jest').split(path.sep).join(path.posix.sep);
|
const tmpDir = path.join('/tmp/.docker-build-push-jest').split(path.sep).join(path.posix.sep);
|
||||||
|
@ -32,6 +36,17 @@ describe('getImageID', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getMetadata', () => {
|
||||||
|
it('matches', async () => {
|
||||||
|
const metadataFile = await buildx.getMetadataFile();
|
||||||
|
console.log(`metadataFile: ${metadataFile}`);
|
||||||
|
await fs.writeFileSync(metadataFile, metadata);
|
||||||
|
const expected = await buildx.getMetadata();
|
||||||
|
console.log(`metadata: ${expected}`);
|
||||||
|
expect(expected).toEqual(metadata);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('isLocalOrTarExporter', () => {
|
describe('isLocalOrTarExporter', () => {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
test.each([
|
test.each([
|
||||||
|
|
|
@ -425,7 +425,30 @@ ccc`],
|
||||||
'--output', 'type=local,dest=./release-out',
|
'--output', 'type=local,dest=./release-out',
|
||||||
'.'
|
'.'
|
||||||
]
|
]
|
||||||
]
|
],
|
||||||
|
[
|
||||||
|
'0.6.0',
|
||||||
|
new Map<string, string>([
|
||||||
|
['context', '.'],
|
||||||
|
['tag', 'localhost:5000/name/app:latest'],
|
||||||
|
['file', './test/Dockerfile'],
|
||||||
|
['network', 'host'],
|
||||||
|
['load', 'false'],
|
||||||
|
['no-cache', 'false'],
|
||||||
|
['push', 'true'],
|
||||||
|
['pull', 'false']
|
||||||
|
]),
|
||||||
|
[
|
||||||
|
'buildx',
|
||||||
|
'build',
|
||||||
|
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||||
|
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||||
|
'--file', './test/Dockerfile',
|
||||||
|
'--network', 'host',
|
||||||
|
'--push',
|
||||||
|
'.'
|
||||||
|
]
|
||||||
|
],
|
||||||
])(
|
])(
|
||||||
'given %p with %p as inputs, returns %p',
|
'given %p with %p as inputs, returns %p',
|
||||||
async (buildxVersion: string, inputs: Map<string, any>, expected: Array<string>) => {
|
async (buildxVersion: string, inputs: Map<string, any>, expected: Array<string>) => {
|
||||||
|
|
|
@ -79,6 +79,8 @@ inputs:
|
||||||
outputs:
|
outputs:
|
||||||
digest:
|
digest:
|
||||||
description: 'Image content-addressable identifier also called a digest'
|
description: 'Image content-addressable identifier also called a digest'
|
||||||
|
metadata:
|
||||||
|
description: 'Build result metadata'
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: 'node12'
|
using: 'node12'
|
||||||
|
|
40
dist/index.js
generated
vendored
40
dist/index.js
generated
vendored
|
@ -38,7 +38,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.satisfies = exports.parseVersion = exports.getVersion = exports.isAvailable = exports.hasGitAuthToken = exports.isLocalOrTarExporter = exports.getSecret = exports.getSecretFile = exports.getSecretString = exports.getImageID = exports.getImageIDFile = void 0;
|
exports.satisfies = exports.parseVersion = exports.getVersion = exports.isAvailable = exports.hasGitAuthToken = exports.isLocalOrTarExporter = exports.getSecret = exports.getSecretFile = exports.getSecretString = exports.getMetadata = exports.getMetadataFile = exports.getImageID = exports.getImageIDFile = void 0;
|
||||||
const sync_1 = __importDefault(__nccwpck_require__(8750));
|
const sync_1 = __importDefault(__nccwpck_require__(8750));
|
||||||
const fs_1 = __importDefault(__nccwpck_require__(5747));
|
const fs_1 = __importDefault(__nccwpck_require__(5747));
|
||||||
const path_1 = __importDefault(__nccwpck_require__(5622));
|
const path_1 = __importDefault(__nccwpck_require__(5622));
|
||||||
|
@ -61,6 +61,22 @@ function getImageID() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.getImageID = getImageID;
|
exports.getImageID = getImageID;
|
||||||
|
function getMetadataFile() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
return path_1.default.join(context.tmpDir(), 'metadata-file').split(path_1.default.sep).join(path_1.default.posix.sep);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.getMetadataFile = getMetadataFile;
|
||||||
|
function getMetadata() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const metadataFile = yield getMetadataFile();
|
||||||
|
if (!fs_1.default.existsSync(metadataFile)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return fs_1.default.readFileSync(metadataFile, { encoding: 'utf-8' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.getMetadata = getMetadata;
|
||||||
function getSecretString(kvp) {
|
function getSecretString(kvp) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return getSecret(kvp, false);
|
return getSecret(kvp, false);
|
||||||
|
@ -311,6 +327,9 @@ function getBuildArgs(inputs, defaultContext, buildxVersion) {
|
||||||
if (!buildx.isLocalOrTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || buildx.satisfies(buildxVersion, '>=0.4.2'))) {
|
if (!buildx.isLocalOrTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || buildx.satisfies(buildxVersion, '>=0.4.2'))) {
|
||||||
args.push('--iidfile', yield buildx.getImageIDFile());
|
args.push('--iidfile', yield buildx.getImageIDFile());
|
||||||
}
|
}
|
||||||
|
if (buildx.satisfies(buildxVersion, '>=0.6.0')) {
|
||||||
|
args.push('--metadata-file', yield buildx.getMetadataFile());
|
||||||
|
}
|
||||||
yield exports.asyncForEach(inputs.cacheFrom, (cacheFrom) => __awaiter(this, void 0, void 0, function* () {
|
yield exports.asyncForEach(inputs.cacheFrom, (cacheFrom) => __awaiter(this, void 0, void 0, function* () {
|
||||||
args.push('--cache-from', cacheFrom);
|
args.push('--cache-from', cacheFrom);
|
||||||
}));
|
}));
|
||||||
|
@ -476,13 +495,18 @@ function run() {
|
||||||
throw new Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)[0].trim()}`);
|
throw new Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)[0].trim()}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const imageID = yield buildx.getImageID();
|
yield core.group(`Setting outputs`, () => __awaiter(this, void 0, void 0, function* () {
|
||||||
if (imageID) {
|
const imageID = yield buildx.getImageID();
|
||||||
core.startGroup(`Extracting digest`);
|
const metadata = yield buildx.getMetadata();
|
||||||
core.info(`${imageID}`);
|
if (imageID) {
|
||||||
context.setOutput('digest', imageID);
|
core.info(`digest=${imageID}`);
|
||||||
core.endGroup();
|
context.setOutput('digest', imageID);
|
||||||
}
|
}
|
||||||
|
if (metadata) {
|
||||||
|
core.info(`metadata=${metadata}`);
|
||||||
|
context.setOutput('metadata', metadata);
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
|
|
|
@ -18,6 +18,18 @@ export async function getImageID(): Promise<string | undefined> {
|
||||||
return fs.readFileSync(iidFile, {encoding: 'utf-8'});
|
return fs.readFileSync(iidFile, {encoding: 'utf-8'});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getMetadataFile(): Promise<string> {
|
||||||
|
return path.join(context.tmpDir(), 'metadata-file').split(path.sep).join(path.posix.sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getMetadata(): Promise<string | undefined> {
|
||||||
|
const metadataFile = await getMetadataFile();
|
||||||
|
if (!fs.existsSync(metadataFile)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return fs.readFileSync(metadataFile, {encoding: 'utf-8'});
|
||||||
|
}
|
||||||
|
|
||||||
export async function getSecretString(kvp: string): Promise<string> {
|
export async function getSecretString(kvp: string): Promise<string> {
|
||||||
return getSecret(kvp, false);
|
return getSecret(kvp, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import csvparse from 'csv-parse/lib/sync';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as semver from 'semver';
|
|
||||||
import * as tmp from 'tmp';
|
import * as tmp from 'tmp';
|
||||||
|
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
|
@ -122,6 +121,9 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, buildxVersio
|
||||||
if (!buildx.isLocalOrTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || buildx.satisfies(buildxVersion, '>=0.4.2'))) {
|
if (!buildx.isLocalOrTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || buildx.satisfies(buildxVersion, '>=0.4.2'))) {
|
||||||
args.push('--iidfile', await buildx.getImageIDFile());
|
args.push('--iidfile', await buildx.getImageIDFile());
|
||||||
}
|
}
|
||||||
|
if (buildx.satisfies(buildxVersion, '>=0.6.0')) {
|
||||||
|
args.push('--metadata-file', await buildx.getMetadataFile());
|
||||||
|
}
|
||||||
await asyncForEach(inputs.cacheFrom, async cacheFrom => {
|
await asyncForEach(inputs.cacheFrom, async cacheFrom => {
|
||||||
args.push('--cache-from', cacheFrom);
|
args.push('--cache-from', cacheFrom);
|
||||||
});
|
});
|
||||||
|
|
19
src/main.ts
19
src/main.ts
|
@ -33,13 +33,18 @@ async function run(): Promise<void> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const imageID = await buildx.getImageID();
|
await core.group(`Setting outputs`, async () => {
|
||||||
if (imageID) {
|
const imageID = await buildx.getImageID();
|
||||||
core.startGroup(`Extracting digest`);
|
const metadata = await buildx.getMetadata();
|
||||||
core.info(`${imageID}`);
|
if (imageID) {
|
||||||
context.setOutput('digest', imageID);
|
core.info(`digest=${imageID}`);
|
||||||
core.endGroup();
|
context.setOutput('digest', imageID);
|
||||||
}
|
}
|
||||||
|
if (metadata) {
|
||||||
|
core.info(`metadata=${metadata}`);
|
||||||
|
context.setOutput('metadata', metadata);
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue