From 42f641f0e59cfabc97164390eec99f622e5041d2 Mon Sep 17 00:00:00 2001 From: Bob Callaway Date: Sat, 13 Dec 2025 09:44:25 -0500 Subject: [PATCH 1/3] pass args by array, tighten regex used in verification Signed-off-by: Bob Callaway --- .github/workflows/bake.yml | 27 +++++++++++++++++---------- .github/workflows/build.yml | 27 +++++++++++++++++---------- .github/workflows/verify.yml | 5 +++-- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index f456185..f476a46 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -577,18 +577,21 @@ jobs: }); const verifyResults = await sigstore.verifySignedManifests( - { certificateIdentityRegexp: `^https://github.com/docker/github-builder-experimental/.github/workflows/bake.yml.*$` }, + { certificateIdentityRegexp: `^https://github\.com/docker/github-builder-experimental/\.github/workflows/bake\.yml@.*$` }, signResults ); await core.group(`Verify commands`, async () => { const verifyCommands = []; for (const [attestationRef, verifyResult] of Object.entries(verifyResults)) { - const cmd = `cosign ${verifyResult.cosignArgs.join(' ')} ${attestationRef}`; - core.info(cmd); + const cmd = { + executable: 'cosign', + args: [...verifyResult.cosignArgs, attestationRef] + }; + core.info(`${cmd.executable} ${cmd.args.join(' ')}`); verifyCommands.push(cmd); } - core.setOutput('verify-commands', verifyCommands.join('\n')); + core.setOutput('verify-commands', JSON.stringify(verifyCommands)); }); - name: Signing local artifacts @@ -609,18 +612,21 @@ jobs: }); const verifyResults = await sigstore.verifySignedArtifacts( - { certificateIdentityRegexp: `^https://github.com/docker/github-builder-experimental/.github/workflows/bake.yml.*$` }, + { certificateIdentityRegexp: `^https://github\.com/docker/github-builder-experimental/\.github/workflows/bake\.yml@.*$` }, signResults ); await core.group(`Verify commands`, async () => { const verifyCommands = []; for (const [artifactPath, verifyResult] of Object.entries(verifyResults)) { - const cmd = `cosign ${verifyResult.cosignArgs.join(' ')} --bundle ${path.relative(inplocalExportDir, verifyResult.bundlePath)} ${path.relative(inplocalExportDir, artifactPath)}`; - core.info(cmd); + const cmd = { + executable: 'cosign', + args: [...verifyResult.cosignArgs, '--bundle', path.relative(inplocalExportDir, verifyResult.bundlePath), path.relative(inplocalExportDir, artifactPath)] + }; + core.info(`cosign ${verifyResult.cosignArgs.join(' ')} --bundle ${path.relative(inplocalExportDir, verifyResult.bundlePath)} ${path.relative(inplocalExportDir, artifactPath)}`); verifyCommands.push(cmd); } - core.setOutput('verify-commands', verifyCommands.join('\n')); + core.setOutput('verify-commands', JSON.stringify(verifyCommands)); }); - name: List local output @@ -759,7 +765,8 @@ jobs: for (const key of Object.keys(inpBuildOutputs)) { const output = JSON.parse(inpBuildOutputs[key]); if (output.verifyCommands) { - verifyCommands.push(output.verifyCommands); + const commands = JSON.parse(output.verifyCommands); + verifyCommands.push(...commands); } } - core.setOutput('cosign-verify-commands', verifyCommands.join('\n')); + core.setOutput('cosign-verify-commands', JSON.stringify(verifyCommands)); diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ffe7e1..7aa135b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -471,18 +471,21 @@ jobs: }); const verifyResults = await sigstore.verifySignedManifests( - { certificateIdentityRegexp: `^https://github.com/docker/github-builder-experimental/.github/workflows/build.yml.*$` }, + { certificateIdentityRegexp: `^https://github\.com/docker/github-builder-experimental/\.github/workflows/build\.yml@.*$` }, signResults ); await core.group(`Verify commands`, async () => { const verifyCommands = []; for (const [attestationRef, verifyResult] of Object.entries(verifyResults)) { - const cmd = `cosign ${verifyResult.cosignArgs.join(' ')} ${attestationRef}`; - core.info(cmd); + const cmd = { + executable: 'cosign', + args: [...verifyResult.cosignArgs, attestationRef] + }; + core.info(`${cmd.executable} ${cmd.args.join(' ')}`); verifyCommands.push(cmd); } - core.setOutput('verify-commands', verifyCommands.join('\n')); + core.setOutput('verify-commands', JSON.stringify(verifyCommands)); }); - name: Signing local artifacts @@ -503,18 +506,21 @@ jobs: }); const verifyResults = await sigstore.verifySignedArtifacts( - { certificateIdentityRegexp: `^https://github.com/docker/github-builder-experimental/.github/workflows/build.yml.*$` }, + { certificateIdentityRegexp: `^https://github\.com/docker/github-builder-experimental/\.github/workflows/build\.yml@.*$` }, signResults ); await core.group(`Verify commands`, async () => { const verifyCommands = []; for (const [artifactPath, verifyResult] of Object.entries(verifyResults)) { - const cmd = `cosign ${verifyResult.cosignArgs.join(' ')} --bundle ${path.relative(inplocalExportDir, verifyResult.bundlePath)} ${path.relative(inplocalExportDir, artifactPath)}`; - core.info(cmd); + const cmd = { + executable: 'cosign', + args: [...verifyResult.cosignArgs, '--bundle', path.relative(inplocalExportDir, verifyResult.bundlePath), path.relative(inplocalExportDir, artifactPath)] + }; + core.info(`${cmd.executable} ${cmd.args.join(' ')}`); verifyCommands.push(cmd); } - core.setOutput('verify-commands', verifyCommands.join('\n')); + core.setOutput('verify-commands', JSON.stringify(verifyCommands)); }); - name: List local output @@ -652,7 +658,8 @@ jobs: for (const key of Object.keys(inpBuildOutputs)) { const output = JSON.parse(inpBuildOutputs[key]); if (output.verifyCommands) { - verifyCommands.push(output.verifyCommands); + const commands = JSON.parse(output.verifyCommands); + verifyCommands.push(...commands); } } - core.setOutput('cosign-verify-commands', verifyCommands.join('\n')); + core.setOutput('cosign-verify-commands', JSON.stringify(verifyCommands)); diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index b787d9d..aad8ef7 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -64,6 +64,7 @@ jobs: INPUT_COSIGN-VERIFY-COMMANDS: ${{ steps.vars.outputs.cosign-verify-commands }} with: script: | - for (const cmd of core.getMultilineInput('cosign-verify-commands')) { - await exec.exec(cmd); + const commands = JSON.parse(core.getInput('cosign-verify-commands')); + for (const cmd of commands) { + await exec.exec(cmd.executable, cmd.args); } From e2fe06e6216da0cedb19aea5a1f9aa5afe006b42 Mon Sep 17 00:00:00 2001 From: Bob Callaway Date: Sat, 13 Dec 2025 10:24:52 -0500 Subject: [PATCH 2/3] be consistent about writing out command from intermediate obj Signed-off-by: Bob Callaway --- .github/workflows/bake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index f476a46..97d09d5 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -623,7 +623,7 @@ jobs: executable: 'cosign', args: [...verifyResult.cosignArgs, '--bundle', path.relative(inplocalExportDir, verifyResult.bundlePath), path.relative(inplocalExportDir, artifactPath)] }; - core.info(`cosign ${verifyResult.cosignArgs.join(' ')} --bundle ${path.relative(inplocalExportDir, verifyResult.bundlePath)} ${path.relative(inplocalExportDir, artifactPath)}`); + core.info(`${cmd.executable} ${cmd.args.join(' ')}`); verifyCommands.push(cmd); } core.setOutput('verify-commands', JSON.stringify(verifyCommands)); From b373e258ca8d314ca6730b700c39a30576ddb6f7 Mon Sep 17 00:00:00 2001 From: Bob Callaway Date: Sat, 13 Dec 2025 10:47:50 -0500 Subject: [PATCH 3/3] return empty array if there are no verifyCommands Signed-off-by: Bob Callaway --- .github/workflows/bake.yml | 2 +- .github/workflows/build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index 97d09d5..19f4c44 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -658,7 +658,7 @@ jobs: const inpArtifactName = core.getInput('artifact-name'); const result = { - verifyCommands: inpVerifyCommands, + verifyCommands: inpVerifyCommands || '[]', imageDigest: inpImageDigest, artifactName: inpArtifactName } diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7aa135b..8d8f7fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -552,7 +552,7 @@ jobs: const inpArtifactName = core.getInput('artifact-name'); const result = { - verifyCommands: inpVerifyCommands, + verifyCommands: inpVerifyCommands || '[]', imageDigest: inpImageDigest, artifactName: inpArtifactName }