diff --git a/.github/workflows/build-and-push-multiarch-image.yaml b/.github/workflows/build-and-push-multiarch-image.yaml new file mode 100644 index 000000000..4f1135e82 --- /dev/null +++ b/.github/workflows/build-and-push-multiarch-image.yaml @@ -0,0 +1,178 @@ +name: Build and push multi-arch image + +on: + workflow_call: + inputs: + ecrRepositoryName: + required: false + type: string + default: ${{ github.event.repository.name }} + dockerfilePath: + required: false + type: string + default: Dockerfile + buildArgs: + required: false + type: string + gitRef: + required: false + type: string + default: ${{ github.sha }} + outputs: + imageTag: + description: "The image tag for the built image" + value: ${{ jobs.build-and-push-image.outputs.imageTag }} + +jobs: + build-and-push-image: + name: Build and push image for ${{ inputs.ecrRepositoryName }} + runs-on: ubuntu-latest + strategy: + matrix: + arch: + - amd64 + - arm64 + outputs: + imageTag: ${{ steps.meta.outputs.version }} + permissions: + id-token: write + contents: read + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.gitRef }} + show-progress: false + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4.0.1 + with: + role-to-assume: "arn:aws:iam::172025368201:role/github_action_ecr_push" + aws-region: eu-west-1 + role-session-name: ecr-push + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + with: + mask-password: 'true' + + - name: Set up QEMU for ${{ matrix.arch }} build + if: ${{ matrix.arch != 'amd64' }} + uses: docker/setup-qemu-action@v3 + with: + platforms: ${{ matrix.arch }} + + - uses: docker/setup-buildx-action@v3 + + - name: Calculate Image Tags + id: calculate-image-tags + run: | + CREATED_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" + echo "createdDate=${CREATED_DATE}" >> $GITHUB_OUTPUT + echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + + - name: Generate Image Metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ${{ steps.login-ecr.outputs.registry }}/${{ inputs.ecrRepositoryName }} + labels: | + org.opencontainers.image.vendor=GDS + org.opencontainers.image.created=${{ steps.calculate-image-tags.outputs.createdDate }} + tags: | + type=raw,priority=500,value=${{ inputs.gitRef }},enable=${{ startsWith(inputs.gitRef, 'v') }} + type=raw,priority=400,value=${{ steps.calculate-image-tags.outputs.sha }},enable=${{ !startsWith(inputs.gitRef, 'v') }} + type=sha,enable=true,format=short + type=sha,enable=true,priority=100,format=long + + - id: build-image + uses: docker/build-push-action@v5 + with: + file: ${{ inputs.dockerfilepath }} + context: . + platforms: "linux/${{ matrix.arch }}" + load: true + provenance: false + build-args: ${{ inputs.buildArgs }} + labels: ${{ steps.meta.outputs.labels }} + outputs: type=image,name=${{ steps.login-ecr.outputs.registry }}/${{ inputs.ecrRepositoryName }},push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=build-${{ matrix.arch}} + cache-to: type=gha,scope=build-${{ matrix.arch}},mode=max + + - id: export-digests + run: | + mkdir -p /tmp/digests + digest="${{steps.build-image.outputs.digest }}" + touch "/tmp/digests/${baseDigest#sha256:}" + + - id: upload-digests + uses: actions/upload-artifact@v4 + with: + name: digests-${{ matrix.arch }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + overwrite: true + + combine_manifests: + name: Create Docker Manifests for Built Images + needs: + - build-and-push-image + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + steps: + - name: Download Digests + uses: actions/download-artifact@v4 + with: + path: /tmp/digests + pattern: digests-* + merge-multiple: true + + - uses: docker/setup-buildx-action@v3 + + - name: Calculate Image Tags + id: calculate-image-tags + run: | + CREATED_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" + echo "createdDate=${CREATED_DATE}" >> $GITHUB_OUTPUT + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4.0.1 + with: + role-to-assume: "arn:aws:iam::172025368201:role/github_action_ecr_push" + aws-region: eu-west-1 + role-session-name: ecr-push + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + with: + mask-password: 'true' + + - name: Generate Image Metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ${{ steps.login-ecr.outputs.registry }}/${{ inputs.ecrRepositoryName }} + labels: | + org.opencontainers.image.vendor=GDS + org.opencontainers.image.created=${{ steps.calculate-image-tags.outputs.createdDate }} + tags: | + type=raw,priority=500,value=${{ inputs.gitRef }},enable=${{ startsWith(inputs.gitRef, 'v') }} + type=raw,priority=400,value=${{ steps.calculate-image-tags.outputs.sha }},enable=${{ !startsWith(inputs.gitRef, 'v') }} + type=sha,enable=true,format=short + type=sha,enable=true,priority=100,format=long + + - name: Create Manifest Lists + working-directory: /tmp/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ steps.login-ecr.outputs.registry }}/${{ inputs.ecrRepositoryName }}@sha256:%s ' *) + + - name: Inspect Images + run: | + docker buildx imagetools inspect ${{ steps.login-ecr.outputs.registry }}/${{ inputs.ecrRepositoryName }}:${{ steps.meta.outputs.version }} \ No newline at end of file