diff --git a/.github/workflows/.test.yml b/.github/workflows/.test.yml index b175ad8..10487bb 100644 --- a/.github/workflows/.test.yml +++ b/.github/workflows/.test.yml @@ -39,6 +39,19 @@ jobs: username: ${{ secrets.AWS_ACCESS_KEY_ID }} password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + build-aws-single-verify: + uses: ./.github/workflows/verify.yml + if: ${{ github.event_name != 'pull_request' }} + needs: + - build-aws-single + with: + builder-outputs: ${{ toJSON(needs.build-aws-single.outputs) }} + secrets: + registry-auths: | + - registry: public.ecr.aws + username: ${{ secrets.AWS_ACCESS_KEY_ID }} + password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + build-aws: uses: ./.github/workflows/build.yml permissions: @@ -63,37 +76,17 @@ jobs: password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} build-aws-verify: - runs-on: ubuntu-latest + uses: ./.github/workflows/verify.yml if: ${{ github.event_name != 'pull_request' }} needs: - build-aws - steps: - - - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - with: - cosign-release: ${{ needs.build-aws.outputs.cosign-version }} - - - name: Login to registry - uses: docker/login-action@v3 - with: - registry: public.ecr.aws + with: + builder-outputs: ${{ toJSON(needs.build-aws.outputs) }} + secrets: + registry-auths: | + - registry: public.ecr.aws username: ${{ secrets.AWS_ACCESS_KEY_ID }} password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - - - name: Verify signatures - uses: actions/github-script@v8 - env: - INPUT_COSIGN-VERSION: ${{ needs.build-aws.outputs.cosign-version }} - INPUT_COSIGN-VERIFY-COMMANDS: ${{ needs.build-aws.outputs.cosign-verify-commands }} - with: - script: | - const cosignVersion = core.getInput('cosign-version'); - core.info(`Cosign version used by Docker GitHub Builder: ${cosignVersion}`); - const cosignVerifyCommands = core.getMultilineInput('cosign-verify-commands'); - for (const cmd of cosignVerifyCommands) { - await exec.exec(cmd); - } build-ghcr: uses: ./.github/workflows/build.yml @@ -115,6 +108,19 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + build-ghcr-verify: + uses: ./.github/workflows/verify.yml + if: ${{ github.event_name != 'pull_request' }} + needs: + - build-ghcr + with: + builder-outputs: ${{ toJSON(needs.build-ghcr.outputs) }} + secrets: + registry-auths: | + - registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + build-dockerhub-stage: uses: ./.github/workflows/build.yml permissions: @@ -135,6 +141,19 @@ jobs: username: ${{ vars.DOCKERHUB_STAGE_USERNAME }} password: ${{ secrets.DOCKERHUB_STAGE_TOKEN }} + build-dockerhub-stage-verify: + uses: ./.github/workflows/verify.yml + if: ${{ github.event_name != 'pull_request' }} + needs: + - build-dockerhub-stage + with: + builder-outputs: ${{ toJSON(needs.build-dockerhub-stage.outputs) }} + secrets: + registry-auths: | + - registry: registry-1-stage.docker.io + username: ${{ vars.DOCKERHUB_STAGE_USERNAME }} + password: ${{ secrets.DOCKERHUB_STAGE_TOKEN }} + build-dockerhub-stage-oidc: uses: ./.github/workflows/build.yml permissions: @@ -154,6 +173,21 @@ jobs: - registry: registry-1-stage.docker.io username: docker:cdeb5882-30b7-4076-be92-bfdceb258e9c + build-dockerhub-stage-oidc-verify: + uses: ./.github/workflows/verify.yml + if: ${{ github.event_name != 'pull_request' }} + permissions: + contents: read + id-token: write + needs: + - build-dockerhub-stage-oidc + with: + builder-outputs: ${{ toJSON(needs.build-dockerhub-stage-oidc.outputs) }} + secrets: + registry-auths: | + - registry: registry-1-stage.docker.io + username: docker:cdeb5882-30b7-4076-be92-bfdceb258e9c + build-ghcr-and-aws: uses: ./.github/workflows/build.yml permissions: @@ -179,6 +213,22 @@ jobs: username: ${{ secrets.AWS_ACCESS_KEY_ID }} password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + build-ghcr-and-aws-verify: + uses: ./.github/workflows/verify.yml + if: ${{ github.event_name != 'pull_request' }} + needs: + - build-ghcr-and-aws + with: + builder-outputs: ${{ toJSON(needs.build-ghcr-and-aws.outputs) }} + secrets: + registry-auths: | + - registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - registry: public.ecr.aws + username: ${{ secrets.AWS_ACCESS_KEY_ID }} + password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + build-local: uses: ./.github/workflows/build.yml permissions: @@ -193,35 +243,12 @@ jobs: build-platforms: linux/amd64,linux/arm64 build-local-verify: - runs-on: ubuntu-latest + uses: ./.github/workflows/verify.yml if: ${{ github.event_name != 'pull_request' }} needs: - build-local - steps: - - - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - with: - cosign-release: ${{ needs.build-local.outputs.cosign-version }} - - - name: Download artifact - uses: actions/download-artifact@v5 - with: - name: ${{ needs.build-local.outputs.artifact-name }} - - - name: Verify signatures - uses: actions/github-script@v8 - env: - INPUT_COSIGN-VERSION: ${{ needs.build-local.outputs.cosign-version }} - INPUT_COSIGN-VERIFY-COMMANDS: ${{ needs.build-local.outputs.cosign-verify-commands }} - with: - script: | - const cosignVersion = core.getInput('cosign-version'); - core.info(`Cosign version used by Docker GitHub Builder: ${cosignVersion}`); - const cosignVerifyCommands = core.getMultilineInput('cosign-verify-commands'); - for (const cmd of cosignVerifyCommands) { - await exec.exec(cmd); - } + with: + builder-outputs: ${{ toJSON(needs.build-local.outputs) }} build-local-single: uses: ./.github/workflows/build.yml @@ -235,6 +262,50 @@ jobs: build-file: test/hello.Dockerfile build-sbom: true + build-local-single-verify: + uses: ./.github/workflows/verify.yml + if: ${{ github.event_name != 'pull_request' }} + needs: + - build-local-single + with: + builder-outputs: ${{ toJSON(needs.build-local-single.outputs) }} + + bake-aws-single: + uses: ./.github/workflows/bake.yml + permissions: + contents: read + packages: write + id-token: write + with: + context: test + target: hello + output: ${{ github.event_name != 'pull_request' && 'registry' || 'cacheonly' }} + cache: true + cache-scope: bake-aws + meta-images: | + public.ecr.aws/q3b5f1u4/test-docker-action + meta-tags: | + type=raw,value=bake-ghbuilder-single-${{ github.run_id }} + bake-sbom: true + secrets: + registry-auths: | + - registry: public.ecr.aws + username: ${{ secrets.AWS_ACCESS_KEY_ID }} + password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + bake-aws-single-verify: + uses: ./.github/workflows/verify.yml + if: ${{ github.event_name != 'pull_request' }} + needs: + - bake-aws-single + with: + builder-outputs: ${{ toJSON(needs.bake-aws-single.outputs) }} + secrets: + registry-auths: | + - registry: public.ecr.aws + username: ${{ secrets.AWS_ACCESS_KEY_ID }} + password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + bake-aws: uses: ./.github/workflows/bake.yml permissions: @@ -259,37 +330,17 @@ jobs: password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} bake-aws-verify: - runs-on: ubuntu-latest + uses: ./.github/workflows/verify.yml if: ${{ github.event_name != 'pull_request' }} needs: - bake-aws - steps: - - - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - with: - cosign-release: ${{ needs.bake-aws.outputs.cosign-version }} - - - name: Login to registry - uses: docker/login-action@v3 - with: - registry: public.ecr.aws + with: + builder-outputs: ${{ toJSON(needs.bake-aws.outputs) }} + secrets: + registry-auths: | + - registry: public.ecr.aws username: ${{ secrets.AWS_ACCESS_KEY_ID }} password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - - - name: Verify signatures - uses: actions/github-script@v8 - env: - INPUT_COSIGN-VERSION: ${{ needs.bake-aws.outputs.cosign-version }} - INPUT_COSIGN-VERIFY-COMMANDS: ${{ needs.bake-aws.outputs.cosign-verify-commands }} - with: - script: | - const cosignVersion = core.getInput('cosign-version'); - core.info(`Cosign version used by Docker GitHub Builder: ${cosignVersion}`); - const cosignVerifyCommands = core.getMultilineInput('cosign-verify-commands'); - for (const cmd of cosignVerifyCommands) { - await exec.exec(cmd); - } bake-ghcr-and-aws: uses: ./.github/workflows/bake.yml @@ -319,37 +370,20 @@ jobs: password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} bake-ghcr-and-aws-verify: - runs-on: ubuntu-latest + uses: ./.github/workflows/verify.yml if: ${{ github.event_name != 'pull_request' }} needs: - bake-ghcr-and-aws - steps: - - - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - with: - cosign-release: ${{ needs.bake-ghcr-and-aws.outputs.cosign-version }} - - - name: Login to registry - uses: docker/login-action@v3 - with: - registry: public.ecr.aws + with: + builder-outputs: ${{ toJSON(needs.bake-ghcr-and-aws.outputs) }} + secrets: + registry-auths: | + - registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - registry: public.ecr.aws username: ${{ secrets.AWS_ACCESS_KEY_ID }} password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - - - name: Verify signatures - uses: actions/github-script@v8 - env: - INPUT_COSIGN-VERSION: ${{ needs.bake-ghcr-and-aws.outputs.cosign-version }} - INPUT_COSIGN-VERIFY-COMMANDS: ${{ needs.bake-ghcr-and-aws.outputs.cosign-verify-commands }} - with: - script: | - const cosignVersion = core.getInput('cosign-version'); - core.info(`Cosign version used by Docker GitHub Builder: ${cosignVersion}`); - const cosignVerifyCommands = core.getMultilineInput('cosign-verify-commands'); - for (const cmd of cosignVerifyCommands) { - await exec.exec(cmd); - } bake-local: uses: ./.github/workflows/bake.yml @@ -366,36 +400,12 @@ jobs: bake-sbom: true bake-local-verify: - runs-on: ubuntu-latest + uses: ./.github/workflows/verify.yml if: ${{ github.event_name != 'pull_request' }} needs: - bake-local - steps: - - - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - with: - cosign-release: ${{ needs.bake-local.outputs.cosign-version }} - - - name: Download artifacts - uses: actions/download-artifact@v5 - with: - pattern: ${{ needs.bake-local.outputs.artifact-name }}* - merge-multiple: true - - - name: Verify signatures - uses: actions/github-script@v8 - env: - INPUT_COSIGN-VERSION: ${{ needs.bake-local.outputs.cosign-version }} - INPUT_COSIGN-VERIFY-COMMANDS: ${{ needs.bake-local.outputs.cosign-verify-commands }} - with: - script: | - const cosignVersion = core.getInput('cosign-version'); - core.info(`Cosign version used by Docker GitHub Builder: ${cosignVersion}`); - const cosignVerifyCommands = core.getMultilineInput('cosign-verify-commands'); - for (const cmd of cosignVerifyCommands) { - await exec.exec(cmd); - } + with: + builder-outputs: ${{ toJSON(needs.bake-local.outputs) }} bake-local-single: uses: ./.github/workflows/bake.yml @@ -410,3 +420,11 @@ jobs: cache: true artifact-name: bake-output-single bake-sbom: true + + bake-local-single-verify: + uses: ./.github/workflows/verify.yml + if: ${{ github.event_name != 'pull_request' }} + needs: + - bake-local-single + with: + builder-outputs: ${{ toJSON(needs.bake-local-single.outputs) }} diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index 9a3a7e3..aa70851 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -129,6 +129,9 @@ on: artifact-name: description: Name of the uploaded artifact (for local output) value: ${{ jobs.finalize.outputs.artifact-name }} + output-type: + description: Build output type + value: ${{ jobs.finalize.outputs.output-type }} env: DOCKER_ACTIONS_TOOLKIT_MODULE: "@docker/actions-toolkit@0.67.0" @@ -635,6 +638,7 @@ jobs: cosign-version: ${{ env.COSIGN_VERSION }} cosign-verify-commands: ${{ steps.set.outputs.cosign-verify-commands }} artifact-name: ${{ inputs.artifact-name }} + output-type: ${{ inputs.output }} needs: - build steps: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6fa628f..ce31df5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -127,6 +127,9 @@ on: artifact-name: description: Name of the uploaded artifact (for local output) value: ${{ jobs.build.outputs.artifact-name }} + output-type: + description: Build output type + value: ${{ jobs.build.outputs.output-type }} env: DOCKER_ACTIONS_TOOLKIT_MODULE: "@docker/actions-toolkit@0.67.0" @@ -140,6 +143,7 @@ jobs: cosign-version: ${{ env.COSIGN_VERSION }} cosign-verify-commands: ${{ steps.signing-attestation-manifests.outputs.verify-commands || steps.signing-local-artifacts.outputs.verify-commands }} artifact-name: ${{ inputs.artifact-name }} + output-type: ${{ inputs.output }} permissions: contents: read id-token: write # for signing attestation manifests with GitHub OIDC Token diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml new file mode 100644 index 0000000..1290564 --- /dev/null +++ b/.github/workflows/verify.yml @@ -0,0 +1,70 @@ +name: verify + +on: + workflow_call: + inputs: + builder-outputs: + type: string + description: "JSON build outputs from Docker GitHub Builder reusable workflows" + required: true + secrets: + registry-auths: + description: "Registry authentication details as YAML objects" + required: false + +jobs: + verify: + runs-on: ubuntu-latest + steps: + - + name: Extract builder outputs + id: vars + uses: actions/github-script@v8 + env: + INPUT_BUILDER-OUTPUTS: ${{ inputs.builder-outputs }} + with: + script: | + const builderOutputs = JSON.parse(core.getInput('builder-outputs')); + core.info(JSON.stringify(builderOutputs, null, 2)); + + const cosignVersion = builderOutputs['cosign-version']; + const cosignVerifyCommands = builderOutputs['cosign-verify-commands']; + const artifactName = builderOutputs['artifact-name']; + const outputType = builderOutputs['output-type']; + if (!cosignVersion || !cosignVerifyCommands || !artifactName || !outputType) { + throw new Error('Missing required build outputs for verification'); + } + + core.setOutput('cosign-version', cosignVersion); + core.setOutput('cosign-verify-commands', cosignVerifyCommands); + core.setOutput('artifact-name', artifactName); + core.setOutput('output-type', outputType); + - + name: Install Cosign + uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 + with: + cosign-release: ${{ steps.vars.outputs.cosign-version }} + - + name: Login to registry + if: ${{ steps.vars.outputs.output-type == 'registry' }} + # TODO: switch to docker/login-action when OIDC is supported + uses: crazy-max/docker-login-action@dockerhub-oidc + with: + registry-auth: ${{ secrets.registry-auths }} + - + name: Download artifact + if: ${{ steps.vars.outputs.output-type == 'local' }} + uses: actions/download-artifact@v5 + with: + pattern: ${{ steps.vars.outputs.artifact-name }}* + merge-multiple: true + - + name: Verify signatures + uses: actions/github-script@v8 + env: + 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); + } diff --git a/README.md b/README.md index ac74601..6c8980c 100644 --- a/README.md +++ b/README.md @@ -52,34 +52,21 @@ on: username: ${{ vars.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + # Optional job to verify the pushed images' signatures. This is already done + # in the `build` job and can be omitted. It's provided here as an example of + # how to use the `verify.yml` reusable workflow. build-verify: - runs-on: ubuntu-latest + uses: docker/github-builder-experimental/.github/workflows/verify.yml@main if: ${{ github.event_name != 'pull_request' }} needs: - build - steps: - - - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - with: - cosign-release: ${{ needs.build.outputs.cosign-version }} - - - name: Login to registry - uses: docker/login-action@v3 - with: - registry: docker.io + with: + builder-outputs: ${{ toJSON(needs.build.outputs) }} + secrets: + registry-auths: | + - registry: docker.io username: ${{ vars.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Verify signatures - uses: actions/github-script@v8 - env: - INPUT_COSIGN-VERIFY-COMMANDS: ${{ needs.build.outputs.cosign-verify-commands }} - with: - script: | - for (const cmd of core.getMultilineInput('cosign-verify-commands')) { - await exec.exec(cmd); - } ``` You can find the list of available inputs in [`.github/workflows/build.yml`](.github/workflows/build.yml). @@ -119,34 +106,21 @@ on: username: ${{ vars.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + # Optional job to verify the pushed images' signatures. This is already done + # in the `bake` job and can be omitted. It's provided here as an example of + # how to use the `verify.yml` reusable workflow. bake-verify: - runs-on: ubuntu-latest + uses: docker/github-builder-experimental/.github/workflows/verify.yml@main if: ${{ github.event_name != 'pull_request' }} needs: - bake - steps: - - - name: Install Cosign - uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 - with: - cosign-release: ${{ needs.bake.outputs.cosign-version }} - - - name: Login to registry - uses: docker/login-action@v3 - with: - registry: docker.io + with: + builder-outputs: ${{ toJSON(needs.bake.outputs) }} + secrets: + registry-auths: | + - registry: docker.io username: ${{ vars.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Verify signatures - uses: actions/github-script@v8 - env: - INPUT_COSIGN-VERIFY-COMMANDS: ${{ needs.bake.outputs.cosign-verify-commands }} - with: - script: | - for (const cmd of core.getMultilineInput('cosign-verify-commands')) { - await exec.exec(cmd); - } ``` You can find the list of available inputs in [`.github/workflows/bake.yml`](.github/workflows/bake.yml).