11# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
2- name : Build
2+ name : CI
33
44on :
55 push :
@@ -473,7 +473,8 @@ jobs:
473473 outputs :
474474 application_name : ${{ steps.variables.outputs.application_name }}
475475 description : ${{ steps.variables.outputs.description }}
476- full_image_name : ${{ steps.variables.outputs.full_image_name }}
476+ full_image_name_remote_registry : ${{ steps.variables.outputs.full_image_name_remote_registry }}
477+ full_image_name_local_registry : ${{ steps.variables.outputs.full_image_name_local_registry }}
477478 registry : ${{ steps.variables.outputs.registry }}
478479 unique_tag : ${{ steps.variables.outputs.unique_tag }}
479480 runs-on : ${{ matrix.runs-on }}
@@ -585,10 +586,15 @@ jobs:
585586 registry=${registry,,}
586587 echo "registry=${registry}" >> ${GITHUB_OUTPUT}
587588
588- # The full image name, which is the registry, the owner and the repo name
589+ # The final full image name, which is the registry, the owner and the repo name
589590 image_name=${{ env.IMAGE_NAME }}
590591 image_name=${image_name,,}
591- echo "full_image_name=${registry}/${image_name}" >> ${GITHUB_OUTPUT}
592+ echo "full_image_name_remote_registry=${registry}/${image_name}" >> ${GITHUB_OUTPUT}
593+
594+ # The local registry to which we'll push
595+ local_registry=localhost:5000
596+ local_registry=${local_registry,,}
597+ echo "full_image_name_local_registry=${local_registry}/${image_name}" >> ${GITHUB_OUTPUT}
592598
593599 # The application's description, from Cargo.toml
594600 description=$(cargo get package.description)
@@ -605,7 +611,7 @@ jobs:
605611 org.opencontainers.image.revision=${{ github.event.pull_request.base.sha }}-${{ github.event.pull_request.head.sha }}
606612 org.opencontainers.image.source=${{ github.event.pull_request.html_url }}
607613 org.opencontainers.image.version=pr-${{ github.event.number }}
608- images : ${{ steps.variables.outputs.full_image_name }}
614+ images : ${{ steps.variables.outputs.full_image_name_local_registry }}
609615 tags : |
610616 type=raw,value=${{ steps.variables.outputs.unique_tag_arch }}
611617
@@ -624,16 +630,14 @@ jobs:
624630
625631 - name : Build Docker image
626632 uses : docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
627- env :
628- BUILDX_NO_DEFAULT_ATTESTATIONS : true
629633 with :
630634 build-args : |
631635 APPLICATION_NAME=${{ steps.variables.outputs.application_name }}
632636 context : .
633637 # this container is THE PR's artifact, and we will re-tag it
634638 # once the PR has been accepted
635- cache-from : type=registry,ref=${{ steps.variables.outputs.full_image_name }}:buildcache-${{ runner.arch }}-${{ steps.variables.outputs.application_name }}-${{ matrix.platform }}
636- cache-to : type=registry,ref=${{ steps.variables.outputs.full_image_name }}:buildcache-${{ runner.arch }}-${{ steps.variables.outputs.application_name }}-${{ matrix.platform }},mode=max
639+ cache-from : type=registry,ref=${{ steps.variables.outputs.full_image_name_remote_registry }}:buildcache-${{ runner.arch }}-${{ steps.variables.outputs.application_name }}-${{ matrix.platform }}
640+ cache-to : type=registry,ref=${{ steps.variables.outputs.full_image_name_remote_registry }}:buildcache-${{ runner.arch }}-${{ steps.variables.outputs.application_name }}-${{ matrix.platform }},mode=max
637641 labels : ${{ steps.meta.outputs.labels }}
638642 outputs : type=oci,dest=/tmp/${{ steps.variables.outputs.unique_tag_arch }}.tar
639643 platforms : linux/${{ matrix.platform }}
@@ -652,7 +656,14 @@ jobs:
652656 docker-publish :
653657 name : Publish Docker container
654658 runs-on : ubuntu-latest
659+ services :
660+ registry :
661+ image : registry:3
662+ ports :
663+ - 5000:5000
655664 permissions :
665+ attestations : write
666+ id-token : write
656667 packages : write
657668 needs :
658669 - cargo-build
@@ -691,12 +702,12 @@ jobs:
691702 org.opencontainers.image.revision=${{ github.event.pull_request.base.sha }}-${{ github.event.pull_request.head.sha }}
692703 org.opencontainers.image.source=${{ github.event.pull_request.html_url }}
693704 org.opencontainers.image.version=pr-${{ github.event.number }}
694- images : ${{ needs.docker-build.outputs.full_image_name }}
705+ images : ${{ needs.docker-build.outputs.full_image_name_local_registry }}
695706 tags : |
696707 type=raw,value=${{ needs.docker-build.outputs.unique_tag }}
697708 type=ref,event=pr,suffix=-latest
698709
699- - name : Download artifact
710+ - name : Download artifacts
700711 uses : actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
701712 id : artifact
702713 with :
@@ -709,30 +720,32 @@ jobs:
709720 working-directory : ${{ steps.artifact.outputs.download-path }}
710721 run : |
711722 docker load --input ./${{ needs.docker-build.outputs.unique_tag }}-amd64.tar
712- docker push ${{ needs.docker-build.outputs.full_image_name }}:${{ needs.docker-build.outputs.unique_tag }}-amd64
723+ echo "Pushing amd64:"
724+ docker push ${{ needs.docker-build.outputs.full_image_name_local_registry }}:${{ needs.docker-build.outputs.unique_tag }}-amd64
713725
714726 docker load --input ./${{ needs.docker-build.outputs.unique_tag }}-arm64.tar
715- docker push ${{ needs.docker-build.outputs.full_image_name }}:${{ needs.docker-build.outputs.unique_tag }}-arm64
727+ echo "Pushing arm64:"
728+ docker push ${{ needs.docker-build.outputs.full_image_name_local_registry }}:${{ needs.docker-build.outputs.unique_tag }}-arm64
716729
717730 - name : Create multiplatform image
718731 shell : bash
719732 run : |
720- new_labels=()
721- while IFS= read -r label; do
722- new_labels+=(--annotation)
723- new_labels+=("index:${label}")
724- done <<< "${{ steps.meta.outputs.labels }}"
725-
726733 new_tags=()
727734 while IFS= read -r tag; do
728735 new_tags+=(--tag)
729736 new_tags+=(${tag})
730737 done <<< "${{ steps.meta.outputs.tags }}"
731738
739+ new_labels=()
740+ while IFS= read -r label; do
741+ new_labels+=(--annotation)
742+ new_labels+=("index:${label}")
743+ done <<< "${{ steps.meta.outputs.labels }}"
744+
732745 # merge the amd64 and arm64 containers in a new multiplatform one
733746 docker buildx imagetools create "${new_tags[@]}" "${new_labels[@]}" \
734- ${{ needs.docker-build.outputs.full_image_name }}:${{ needs.docker-build.outputs.unique_tag }}-amd64 \
735- ${{ needs.docker-build.outputs.full_image_name }}:${{ needs.docker-build.outputs.unique_tag }}-arm64
747+ ${{ needs.docker-build.outputs.full_image_name_local_registry }}:${{ needs.docker-build.outputs.unique_tag }}-amd64 \
748+ ${{ needs.docker-build.outputs.full_image_name_local_registry }}:${{ needs.docker-build.outputs.unique_tag }}-arm64
736749
737750 for new_tag in $(echo "${{ join(steps.meta.outputs.tags, ' ') }}"); do
738751 echo "${new_tag}:"
@@ -741,6 +754,33 @@ jobs:
741754 echo ""
742755 done
743756
757+ - name : Get digest of multiplatform image in our local registry
758+ shell : bash
759+ id : multiplatform_image
760+ run : |
761+ digest=$(docker buildx imagetools inspect ${{ needs.docker-build.outputs.full_image_name_local_registry }}:${{ needs.docker-build.outputs.unique_tag }} --format "{{json .}}" | jq --raw-output ".manifest.digest")
762+
763+ echo "digest=${digest}" >> ${GITHUB_OUTPUT}
764+
765+ - name : Publish to the actual repo
766+ shell : bash
767+ run : |
768+ docker buildx imagetools create \
769+ --tag ${{ needs.docker-build.outputs.full_image_name_remote_registry }}:${{ needs.docker-build.outputs.unique_tag }} \
770+ ${{ needs.docker-build.outputs.full_image_name_local_registry }}:${{ needs.docker-build.outputs.unique_tag }}
771+
772+ # note that we use the digest of the local image
773+ # these digests don't change after pushing, but
774+ # since we deal with tags (mutable), and the way to get a digest is to use the tag, I prefer
775+ # sourcing the digest from the local registry we just spun up (trusted)
776+ - name : Generate artifact attestation
777+ uses : actions/attest-build-provenance@v2
778+ id : attestation
779+ with :
780+ subject-name : ${{ needs.docker-build.outputs.full_image_name_remote_registry }}
781+ subject-digest : ${{ steps.multiplatform_image.outputs.digest }}
782+ push-to-registry : true
783+
744784 all-done :
745785 name : All done
746786 # this is the job that should be marked as required on GitHub. It's the only one that'll reliably trigger
0 commit comments