Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/.test-bake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -547,3 +547,17 @@ jobs:
- registry: registry-1-stage.docker.io
username: ${{ vars.DOCKERHUB_STAGE_USERNAME }}
password: ${{ secrets.DOCKERHUB_STAGE_TOKEN }}

bake-namedcontexts:
uses: ./.github/workflows/bake.yml
permissions:
contents: read
id-token: write
with:
artifact-name: bake-namedcontexts-output
artifact-upload: true
context: test
output: local
sbom: true
sign: ${{ github.event_name != 'pull_request' }}
target: go-cross-with-contexts
83 changes: 47 additions & 36 deletions .github/workflows/bake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -335,11 +335,46 @@ jobs:
if (!def) {
throw new Error('Bake definition not set');
}
const targets = Object.keys(def.target);
if (targets.length > 1) {
throw new Error(`Only one target can be built at once, found: ${targets.join(', ')}`);
const targetDefs = def.target || {};
const targets = Object.keys(targetDefs);
if (targets.length === 0) {
throw new Error('Bake definition does not contain any targets');
}
const parseContextTarget = value => {
if (typeof value !== 'string') {
return undefined;
}
const match = value.match(/^target:(.+)$/);
return match ? match[1] : undefined;
};
const resolveTarget = () => {
if (targetDefs[inpTarget]) {
return inpTarget;
}
throw new Error(`Unable to resolve ${inpTarget} target, found: ${targets.join(', ')}`);
};
target = resolveTarget();
const allowedTargets = new Set([target]);
const stack = [target];
while (stack.length > 0) {
const current = stack.pop();
const contexts = targetDefs[current]?.contexts || {};
for (const contextValue of Object.values(contexts)) {
const dependencyTarget = parseContextTarget(contextValue);
if (!dependencyTarget || allowedTargets.has(dependencyTarget)) {
continue;
}
if (!targetDefs[dependencyTarget]) {
throw new Error(`Target ${current} uses unknown named context target ${dependencyTarget}`);
}
allowedTargets.add(dependencyTarget);
stack.push(dependencyTarget);
}
}
const unsupportedTargets = targets.filter(name => !allowedTargets.has(name));
if (unsupportedTargets.length > 0) {
throw new Error(`Only one target can be built at once, found unsupported targets: ${unsupportedTargets.join(', ')}`);
}
target = targets[0];
});
} catch (error) {
core.setFailed(error);
Expand Down Expand Up @@ -581,7 +616,6 @@ jobs:
with:
script: |
const os = require('os');
const { Bake } = require('@docker/actions-toolkit/lib/buildx/bake');
const { Build } = require('@docker/actions-toolkit/lib/buildx/build');
const { GitHub } = require('@docker/actions-toolkit/lib/github');
const { Util } = require('@docker/actions-toolkit/lib/util');
Expand Down Expand Up @@ -613,11 +647,16 @@ jobs:
const inpGitHubToken = core.getInput('github-token');

const bakeSource = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}.git#${process.env.GITHUB_REF}:${inpContext}`;
await core.group(`Set bake source`, async () => {
await core.group(`Set source output`, async () => {
core.info(bakeSource);
core.setOutput('source', bakeSource);
});

await core.group(`Set target output`, async () => {
core.info(inpTarget);
core.setOutput('target', inpTarget);
});

const sbom = inpSbom ? `generator=${inpSbomImage}` : 'false';
await core.group(`Set sbom`, async () => {
core.info(sbom);
Expand All @@ -642,34 +681,6 @@ jobs:
core.setOutput('envs', JSON.stringify(envs));
});

let target;
try {
await core.group(`Validating definition`, async () => {
const bake = new Bake();
const def = await bake.getDefinition({
files: inpFiles,
overrides: inpSet,
sbom: sbom,
source: bakeSource,
targets: [inpTarget]
}, {
env: Object.keys(envs).length > 0 ? envs : undefined
});
if (!def) {
throw new Error('Bake definition not set');
}
const targets = Object.keys(def.target);
if (targets.length > 1) {
throw new Error(`Only one target can be built at once, found: ${targets.join(', ')}`);
}
target = targets[0];
core.setOutput('target', target);
});
} catch (error) {
core.setFailed(error);
return;
}

let bakeFiles = inpFiles;
await core.group(`Set bake files`, async () => {
if (bakeFiles.length === 0) {
Expand Down Expand Up @@ -719,8 +730,8 @@ jobs:
bakeOverrides.push(`*.platform=${inpPlatform}`);
}
if (inpCache) {
bakeOverrides.push(`*.cache-from=type=gha,scope=${inpCacheScope || target}${platformPairSuffix}`);
bakeOverrides.push(`*.cache-to=type=gha,ignore-error=true,scope=${inpCacheScope || target}${platformPairSuffix},mode=${inpCacheMode}`);
bakeOverrides.push(`*.cache-from=type=gha,scope=${inpCacheScope || inpTarget}${platformPairSuffix}`);
bakeOverrides.push(`*.cache-to=type=gha,ignore-error=true,scope=${inpCacheScope || inpTarget}${platformPairSuffix},mode=${inpCacheMode}`);
}
core.info(JSON.stringify(bakeOverrides, null, 2));
core.setOutput('overrides', bakeOverrides.join(os.EOL));
Expand Down
30 changes: 30 additions & 0 deletions test/docker-bake.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,33 @@ target "hello-cross" {
inherits = ["hello"]
platforms = ["linux/amd64", "linux/arm64"]
}

target "go-cross-with-contexts" {
inherits = ["go-cross"]
contexts = {
gen = "target:generated-files"
}
}

target "generated-files" {
contexts = {
generated-hello1 = "target:generated-hello1"
generated-hello2 = "target:generated-hello2"
}
dockerfile-inline = <<-EOT
FROM scratch AS generated-files
COPY --from=generated-hello1 / /hello1
COPY --from=generated-hello2 / /hello2
EOT
output = ["type=cacheonly"]
}

target "generated-hello1" {
dockerfile = "hello.Dockerfile"
output = ["type=cacheonly"]
}

target "generated-hello2" {
dockerfile = "hello.Dockerfile"
output = ["type=cacheonly"]
}
3 changes: 3 additions & 0 deletions test/go.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ ARG XX_VERSION="1.7.0"
# xx is a helper for cross-compilation
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx

FROM scratch AS gen

FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS base
COPY --from=xx / /
RUN apk add --no-cache file git
Expand All @@ -14,6 +16,7 @@ WORKDIR /src

FROM base AS build
ARG TARGETPLATFORM
COPY --from=gen / /out
RUN --mount=type=bind,target=. \
--mount=target=/root/.cache,type=cache \
xx-go build -trimpath -o /out/myapp . \
Expand Down
Loading