name: Build and Publish Docker Image on: workflow_call: permissions: contents: read packages: write actions: read env: REGISTRY: ghcr.io # This would be easier if we could just build all platforms in one job, but # building the ARM version on x86 is very slow due to the pre-compile step we do # in the Dockerfile. # # See also https://github.com/docker/build-push-action/issues/671 and especially the linked solution # https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners # for more details on how this produces a single image with multiple architectures from different runners. jobs: build-docker: name: Package Docker Image strategy: matrix: include: - runner: [k8s-runners-amd64] rust_target: x86_64-unknown-linux-gnu docker_arch: amd64 docker_platform: linux/amd64 - runner: [k8s-runners-arm64] rust_target: aarch64-unknown-linux-gnu docker_arch: arm64 docker_platform: linux/arm64 runs-on: ${{ matrix.runner }} container: image: ghcr.io/feldera/feldera-dev:sha-a5ab793b8d261068867b9fdfad3f04157b2536fc steps: - name: Show Kubernetes node if: always() run: | echo "K8S node: ${K8S_NODE_NAME}" - name: Checkout Repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 fetch-tags: true persist-credentials: false - name: Download fda id: binaries uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 with: name: fda-${{ matrix.rust_target }} path: build - name: Download pipeline-manager uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 with: name: pipeline-manager-${{ matrix.rust_target }} path: build - name: Download Compiler Binaries uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 with: name: feldera-sql-compiler path: build # Remove if https://github.com/actions/upload-artifact/issues/38 ever gets fixed - name: Make binaries executable run: | chmod +x ${{ steps.binaries.outputs.download-path }}/* ls -la ${{ steps.binaries.outputs.download-path }} - name: Prepare Platform Environment Variable shell: bash run: | platform=${{ matrix.docker_platform }} echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - name: Docker meta id: meta uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 with: images: | ${{ vars.FELDERA_IMAGE_NAME }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 with: version: latest - name: Login to GHCR uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push by digest id: build uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 with: # `context` is somehow important to set, otherwise the build will use it's own git checkout instead of the one # checkout out earlier that also has the artifacts (!?) context: . file: deploy/Dockerfile platforms: ${{ matrix.docker_platform }} labels: ${{ steps.meta.outputs.labels }} tags: ${{ vars.FELDERA_IMAGE_NAME }} outputs: type=image,push-by-digest=true,name-canonical=true,push=true cache-from: type=gha cache-to: type=gha,mode=max # If you wonder why this needs to be $RUNNER_TEMP here # and not ${{ runner.temp }}: https://github.com/actions/runner/issues/2498 - name: Export digest run: | rm -rf $RUNNER_TEMP/digests mkdir -p $RUNNER_TEMP/digests digest="${{ steps.build.outputs.digest }}" touch "$RUNNER_TEMP/digests/${digest#sha256:}" - name: Upload digest uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: digests-${{ env.PLATFORM_PAIR }} path: ${{ runner.temp }}/digests/* if-no-files-found: error retention-days: 7 # One problem with this workflow is the unknown/unknown architecture # it adds in the github UI. It's a github bug: # https://github.com/orgs/community/discussions/45969 merge-manifests: name: Merge Docker Manifests runs-on: ubuntu-latest-amd64 needs: build-docker steps: - name: Download digests uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 with: path: ${{ runner.temp }}/digests pattern: digests-* merge-multiple: true - name: Login to GHCR uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 with: version: latest - name: Docker meta id: meta uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 with: images: ${{ vars.FELDERA_IMAGE_NAME }} tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha,format=long - name: Create manifest list and push working-directory: ${{ runner.temp }}/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ $(printf '${{ vars.FELDERA_IMAGE_NAME }}@sha256:%s ' *) - name: Inspect image run: | docker buildx imagetools inspect ${{ vars.FELDERA_IMAGE_NAME }}:${{ steps.meta.outputs.version }} - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 1 - name: Wait for image run: | ./.github/scripts/wait_for_images_ghcr.sh \ "${{ vars.FELDERA_IMAGE_NAME }}" \ "${{ steps.meta.outputs.version }}" \ "amd64,arm64" # Upload after the image is verified so check-prior-build knows the # sha-{sha} tag actually exists in GHCR (not just that digests were pushed). - name: Signal docker image ready run: echo "${{ steps.meta.outputs.version }}" > /tmp/docker-image-ready.txt - name: Upload docker-image-ready artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: docker-image-ready path: /tmp/docker-image-ready.txt retention-days: 7