Skip to content

Commit 6a1cfbc

Browse files
authored
Merge pull request #60 from docker/gha-cache-sign
sign github actions cache blobs
2 parents 328daf0 + ff3b622 commit 6a1cfbc

File tree

5 files changed

+291
-50
lines changed

5 files changed

+291
-50
lines changed

.github/workflows/.test-bake.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ jobs:
3131
contents: read
3232
id-token: write
3333
with:
34+
cache: true
35+
cache-scope: bake-aws-single
3436
context: test
3537
output: image
3638
push: ${{ github.event_name != 'pull_request' }}
@@ -80,6 +82,8 @@ jobs:
8082
contents: read
8183
id-token: write
8284
with:
85+
cache: true
86+
cache-scope: bake-aws
8387
context: test
8488
output: image
8589
push: ${{ github.event_name != 'pull_request' }}
@@ -129,6 +133,8 @@ jobs:
129133
contents: read
130134
id-token: write
131135
with:
136+
cache: true
137+
cache-scope: bake-aws-nosign
132138
context: test
133139
output: image
134140
push: ${{ github.event_name != 'pull_request' }}

.github/workflows/.test-build.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ jobs:
3131
contents: read
3232
id-token: write
3333
with:
34+
cache: true
35+
cache-scope: build-aws-single
3436
file: test/hello.Dockerfile
3537
output: image
3638
push: ${{ github.event_name != 'pull_request' }}
@@ -80,6 +82,8 @@ jobs:
8082
contents: read
8183
id-token: write
8284
with:
85+
cache: true
86+
cache-scope: build-aws
8387
file: test/hello.Dockerfile
8488
output: image
8589
platforms: linux/amd64,linux/arm64
@@ -129,6 +133,8 @@ jobs:
129133
contents: read
130134
id-token: write
131135
with:
136+
cache: true
137+
cache-scope: build-aws-nosign
132138
file: test/hello.Dockerfile
133139
output: image
134140
platforms: linux/amd64,linux/arm64

.github/workflows/bake.yml

Lines changed: 132 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@ on:
2323
description: "Upload build output GitHub artifact (for local output)"
2424
required: false
2525
default: false
26+
cache:
27+
type: boolean
28+
description: "Enable cache to GitHub Actions cache backend"
29+
required: false
30+
default: false
31+
cache-scope:
32+
type: string
33+
description: "Which scope cache object belongs to if cache enabled (defaults to target name)"
34+
required: false
35+
cache-mode:
36+
type: string
37+
description: "Cache layers to export if cache enabled (min or max)"
38+
required: false
39+
default: 'min'
2640
context:
2741
type: string
2842
description: "Context to build from in the Git working tree"
@@ -124,7 +138,7 @@ on:
124138

125139
env:
126140
BUILDX_VERSION: "v0.30.1"
127-
BUILDKIT_IMAGE: "moby/buildkit:v0.26.2"
141+
BUILDKIT_IMAGE: "moby/buildkit:master@sha256:bdefeba47634c596286beabe68219708ed364c4f1a5e4e9a2e160274712a0e89" # TODO: pin to a specific version when signed gha cache feature is available
128142
DOCKER_ACTIONS_TOOLKIT_MODULE: "@docker/[email protected]"
129143
COSIGN_VERSION: "v3.0.2"
130144
LOCAL_EXPORT_DIR: "/tmp/buildx-output"
@@ -136,6 +150,7 @@ jobs:
136150
outputs:
137151
includes: ${{ steps.set.outputs.includes }}
138152
sign: ${{ steps.set.outputs.sign }}
153+
privateRepo: ${{ steps.set.outputs.privateRepo }}
139154
steps:
140155
-
141156
name: Install @docker/actions-toolkit
@@ -247,6 +262,11 @@ jobs:
247262
}
248263
249264
const privateRepo = GitHub.context.payload.repository?.private ?? false;
265+
await core.group(`Set privateRepo output`, async () => {
266+
core.info(`privateRepo: ${privateRepo}`);
267+
core.setOutput('privateRepo', privateRepo);
268+
});
269+
250270
await core.group(`Set includes output`, async () => {
251271
let includes = [];
252272
if (platforms.length === 0) {
@@ -329,21 +349,123 @@ jobs:
329349
if: ${{ inputs.setup-qemu }}
330350
with:
331351
cache-image: false
352+
-
353+
name: Expose GitHub Runtime
354+
uses: crazy-max/ghaction-github-runtime@3cb05d89e1f492524af3d41a1c98c83bc3025124 # v3.1.0
332355
-
333356
name: Set up Docker Buildx
357+
id: buildx
334358
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
335359
with:
336360
version: ${{ env.BUILDX_VERSION }}
337-
buildkitd-flags: --debug
338-
driver-opts: image=${{ env.BUILDKIT_IMAGE }}
339361
cache-binary: false
362+
buildkitd-flags: --debug
363+
driver-opts: |
364+
image=${{ env.BUILDKIT_IMAGE }}
365+
env.ACTIONS_ID_TOKEN_REQUEST_TOKEN=${{ env.ACTIONS_ID_TOKEN_REQUEST_TOKEN }}
366+
env.ACTIONS_ID_TOKEN_REQUEST_URL=${{ env.ACTIONS_ID_TOKEN_REQUEST_URL }}
367+
buildkitd-config-inline: |
368+
[cache]
369+
[cache.gha]
370+
[cache.gha.sign]
371+
command = ["ghacache-sign-script.sh"]
372+
[cache.gha.verify]
373+
required = true
374+
[cache.gha.verify.policy]
375+
timestampThreshold = 1
376+
tlogThreshold = ${{ matrix.privateRepo == 'true' && '0' || '1' }}
377+
subjectAlternativeName = "https://github.com/docker/github-builder-experimental/.github/workflows/bake.yml*"
378+
githubWorkflowRepository = "docker/github-builder-experimental"
379+
issuer = "https://token.actions.githubusercontent.com"
380+
runnerEnvironment = "github-hosted"
381+
sourceRepositoryURI = "${{ github.server_url }}/${{ github.repository }}"
382+
sourceRepositoryRef = "${{ github.event_name != 'pull_request' && github.ref || '' }}"
383+
-
384+
name: Install Cosign
385+
if: ${{ needs.prepare.outputs.sign == 'true' || inputs.cache }}
386+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
387+
env:
388+
INPUT_COSIGN-VERSION: ${{ env.COSIGN_VERSION }}
389+
INPUT_BUILDER-NAME: ${{ steps.buildx.outputs.name }}
390+
INPUT_GHA-CACHE-SIGN-SCRIPT: |
391+
#!/bin/sh
392+
set -e
393+
394+
# Create temporary files
395+
out_file=$(mktemp)
396+
in_file=$(mktemp)
397+
trap 'rm -f "$in_file" "$out_file"' EXIT
398+
cat > "$in_file"
399+
400+
set -x
401+
402+
# Sign with cosign
403+
cosign sign-blob \
404+
--yes \
405+
--oidc-provider github-actions \
406+
--new-bundle-format \
407+
--use-signing-config \
408+
--bundle "$out_file" \
409+
--tlog-upload=${{ matrix.privateRepo == 'false' }} \
410+
"$in_file"
411+
412+
# Output bundle to stdout
413+
cat "$out_file"
414+
with:
415+
script: |
416+
const fs = require('fs');
417+
const os = require('os');
418+
const path = require('path');
419+
420+
const { Buildx } = require('@docker/actions-toolkit/lib/buildx/buildx');
421+
const { Cosign } = require('@docker/actions-toolkit/lib/cosign/cosign');
422+
const { Install } = require('@docker/actions-toolkit/lib/cosign/install');
423+
424+
const inpCosignVersion = core.getInput('cosign-version');
425+
const inpBuilderName = core.getInput('builder-name');
426+
const inpGHACacheSignScript = core.getInput('gha-cache-sign-script');
427+
428+
const cosignInstall = new Install();
429+
const cosignBinPath = await cosignInstall.download({
430+
version: core.getInput('cosign-version'),
431+
ghaNoCache: true,
432+
skipState: true,
433+
verifySignature: true
434+
});
435+
const cosignPath = await cosignInstall.install(cosignBinPath);
436+
437+
const cosign = new Cosign();
438+
await cosign.printVersion();
439+
440+
const containerName = `${Buildx.containerNamePrefix}${inpBuilderName}0`;
441+
442+
const ghaCacheSignScriptPath = path.join(os.tmpdir(), `ghacache-sign-script.sh`);
443+
core.info(`Writing GitHub Actions cache sign script to ${ghaCacheSignScriptPath}`);
444+
await fs.writeFileSync(ghaCacheSignScriptPath, inpGHACacheSignScript, {mode: 0o700});
445+
446+
core.info(`Copying GitHub Actions cache sign script to BuildKit container ${containerName}`);
447+
await exec.exec('docker', [
448+
'cp',
449+
ghaCacheSignScriptPath,
450+
`${containerName}:/usr/bin/ghacache-sign-script.sh`
451+
]);
452+
453+
core.info(`Copying cosign binary to BuildKit container ${containerName}`);
454+
await exec.exec('docker', [
455+
'cp',
456+
cosignPath,
457+
`${containerName}:/usr/bin/cosign`
458+
]);
340459
-
341460
name: Prepare
342461
id: prepare
343462
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
344463
env:
345464
INPUT_PLATFORM: ${{ matrix.platform }}
346465
INPUT_LOCAL-EXPORT-DIR: ${{ env.LOCAL_EXPORT_DIR }}
466+
INPUT_CACHE: ${{ inputs.cache }}
467+
INPUT_CACHE-SCOPE: ${{ inputs.cache-scope }}
468+
INPUT_CACHE-MODE: ${{ inputs.cache-mode }}
347469
INPUT_CONTEXT: ${{ inputs.context }}
348470
INPUT_FILES: ${{ inputs.files }}
349471
INPUT_OUTPUT: ${{ inputs.output }}
@@ -371,6 +493,9 @@ jobs:
371493
372494
const inpLocalExportDir = core.getInput('local-export-dir');
373495
496+
const inpCache = core.getBooleanInput('cache');
497+
const inpCacheScope = core.getInput('cache-scope');
498+
const inpCacheMode = core.getInput('cache-mode');
374499
const inpContext = core.getInput('context');
375500
const inpFiles = Util.getInputList('files');
376501
const inpOutput = core.getInput('output');
@@ -468,6 +593,10 @@ jobs:
468593
if (inpPlatform) {
469594
bakeOverrides.push(`*.platform=${inpPlatform}`);
470595
}
596+
if (inpCache) {
597+
bakeOverrides.push(`*.cache-from=type=gha,scope=${inpCacheScope || target}${platformPairSuffix}`);
598+
bakeOverrides.push(`*.cache-to=type=gha,scope=${inpCacheScope || target}${platformPairSuffix},mode=${inpCacheMode}`);
599+
}
471600
core.info(JSON.stringify(bakeOverrides, null, 2));
472601
core.setOutput('overrides', bakeOverrides.join(os.EOL));
473602
});
@@ -505,28 +634,6 @@ jobs:
505634
const imageDigest = inpMetadata[inpTarget]['containerimage.digest'];
506635
core.info(imageDigest);
507636
core.setOutput('digest', imageDigest);
508-
-
509-
name: Install Cosign
510-
if: ${{ needs.prepare.outputs.sign == 'true' }}
511-
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
512-
env:
513-
INPUT_COSIGN-VERSION: ${{ env.COSIGN_VERSION }}
514-
with:
515-
script: |
516-
const { Cosign } = require('@docker/actions-toolkit/lib/cosign/cosign');
517-
const { Install } = require('@docker/actions-toolkit/lib/cosign/install');
518-
519-
const cosignInstall = new Install();
520-
const cosignBinPath = await cosignInstall.download({
521-
version: core.getInput('cosign-version'),
522-
ghaNoCache: true,
523-
skipState: true,
524-
verifySignature: true
525-
});
526-
await cosignInstall.install(cosignBinPath);
527-
528-
const cosign = new Cosign();
529-
await cosign.printVersion();
530637
-
531638
name: Signing attestation manifests
532639
id: signing-attestation-manifests

0 commit comments

Comments
 (0)