From 8b70087931acb45baf9580bb2a8f20e26fdcf4de Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 11:26:53 +0000 Subject: [PATCH 01/33] Try multiarch native build --- .github/workflows/ci-pipeline.yml | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 4f5b840..d2c2b21 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -11,8 +11,8 @@ on: ####### Uncomment this to test the CI pipeline in a PR ####### You'll also need to comment the rules containing {{branch}} ####### in the `Extract Docker metadata` step -# pull_request: -# branches: [ "main" ] + pull_request: + branches: [ "main" ] env: # Use docker.io for Docker Hub if empty @@ -52,8 +52,8 @@ jobs: run: | docker run --rm ${{ env.TEST_TAG }} make ci-test - build: - runs-on: ubuntu-latest + build-arch: + runs-on: ${{ matrix.arch.runner }} needs: test permissions: contents: read @@ -63,11 +63,18 @@ jobs: id-token: write strategy: matrix: + arch: + - platform: "amd64" + runner: ubuntu-latest + - platform: "arm64" + # There is no latest for ARM yet + # https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources + runner: ubuntu-24.04-arm docker_target: - - migrations +# - migrations - http - - socketio - - dramatiq +# - socketio +# - dramatiq steps: # GitHub gives only repository complete in / format. # Need some manual sheanigans @@ -79,9 +86,6 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - # Install the cosign tool # https://github.com/sigstore/cosign-installer - name: Install cosign @@ -111,9 +115,7 @@ jobs: ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} # generate Docker tags based on the following events/attributes tags: | - type=sha - type=raw,value={{branch}}-latest - type=raw,value={{branch}}-{{date 'YYYYMMDDHHmmss'}} + type=sha-${{ matrix.arch.platform }} # Build and push Docker image with Buildx # https://github.com/docker/build-push-action @@ -123,7 +125,7 @@ jobs: with: context: . target: ${{ matrix.docker_target }} - platforms: linux/amd64,linux/arm64 + platforms: linux/${{ matrix.arch.platform }} push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} From cb63f8b22f66725cff69bd138a0f0f6aae518dbf Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 11:34:04 +0000 Subject: [PATCH 02/33] Make tag suffix --- .github/workflows/ci-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index d2c2b21..e0d7867 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -115,7 +115,7 @@ jobs: ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} # generate Docker tags based on the following events/attributes tags: | - type=sha-${{ matrix.arch.platform }} + type=sha,suffix=${{ matrix.arch.platform }} # Build and push Docker image with Buildx # https://github.com/docker/build-push-action From a0ae0ccc3c67dfb95d8dc3f875c84a1bb548c1ae Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:10:42 +0000 Subject: [PATCH 03/33] Try digest approach from Docker docs --- .github/workflows/ci-pipeline.yml | 111 ++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index e0d7867..5d90429 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -52,6 +52,7 @@ jobs: run: | docker run --rm ${{ env.TEST_TAG }} make ci-test + # Inspired to https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners build-arch: runs-on: ${{ matrix.arch.runner }} needs: test @@ -64,9 +65,9 @@ jobs: strategy: matrix: arch: - - platform: "amd64" + - platform: linux/amd64 runner: ubuntu-latest - - platform: "arm64" + - platform: linux/arm64 # There is no latest for ARM yet # https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources runner: ubuntu-24.04-arm @@ -77,11 +78,14 @@ jobs: # - dramatiq steps: # GitHub gives only repository complete in / format. - # Need some manual sheanigans + # Need some manual shenanigans # Set IMAGE_NAME so we can push to // + # Transform os/arch to os-arch for suffix target - name: Set ENV variables run: | echo "IMAGE_NAME=${GITHUB_REPOSITORY#$GITHUB_REPOSITORY_OWNER/}" >> $GITHUB_ENV + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - name: Checkout repository uses: actions/checkout@v4 @@ -115,9 +119,9 @@ jobs: ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} # generate Docker tags based on the following events/attributes tags: | - type=sha,suffix=${{ matrix.arch.platform }} + type=sha,suffix=-${{ env.PLATFORM_PAIR }} - # Build and push Docker image with Buildx + # Build and push Docker image with Buildx by digest # https://github.com/docker/build-push-action - name: Build and push production image id: build-and-push @@ -125,13 +129,106 @@ jobs: with: context: . target: ${{ matrix.docker_target }} - platforms: linux/${{ matrix.arch.platform }} - push: true + platforms: ${{ matrix.arch.platform }} + outputs: type=image,push-by-digest=true,name-canonical=true,push=true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max + - name: Export digest + run: | + mkdir -p ${{ runner.temp }}/digests/${{ matrix.docker_target }} + digest="${{ steps.build.outputs.digest }}" + touch "${{ runner.temp }}/digests/${{ matrix.docker_target }}/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digests-${{ env.PLATFORM_PAIR }} + path: ${{ runner.temp }}/digests/* + if-no-files-found: error + retention-days: 1 + + + aggregate-manifests: + runs-on: ubuntu-latest + needs: build-arch + permissions: + contents: read + packages: write + # This is used to complete the identity challenge + # with sigstore/fulcio when running outside of PRs. + id-token: write + strategy: + matrix: + docker_target: + # - migrations + - http + # - socketio + # - dramatiq + + steps: + # GitHub gives only repository complete in / format. + # Need some manual sheanigans + # Set IMAGE_NAME so we can push to // + - name: Set ENV variables + run: | + echo "IMAGE_NAME=${GITHUB_REPOSITORY#$GITHUB_REPOSITORY_OWNER/}" >> $GITHUB_ENV + + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: ${{ runner.temp }}/digests/${{ matrix.docker_target }} + pattern: digests-* + merge-multiple: true + + - name: Checkout repository + uses: actions/checkout@v4 + + # Install the cosign tool + # https://github.com/sigstore/cosign-installer + - name: Install cosign + uses: sigstore/cosign-installer@v3.8.1 + + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v3.10.0 + + # Login against a Docker registry + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + uses: docker/login-action@v3.3.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5.7.0 + with: + # list of Docker images to use as base name for tags + # //- + images: | + ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} + # generate Docker tags based on the following events/attributes + tags: | + type=sha + type=raw,value={{branch}}-latest + type=raw,value={{branch}}-{{date 'YYYYMMDDHHmmss'}} + + - 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 '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) + + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} + #TODO: Implement signature using generated key: https://docs.sigstore.dev/signing/quickstart/#signing-with-a-generated-key # Sign the resulting Docker image digest except on PRs. From 0365ac2f0deaa32ef76ce638ed79c59081acef0e Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:18:51 +0000 Subject: [PATCH 04/33] Fix platform pari --- .github/workflows/ci-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 5d90429..5bc923b 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -84,7 +84,7 @@ jobs: - name: Set ENV variables run: | echo "IMAGE_NAME=${GITHUB_REPOSITORY#$GITHUB_REPOSITORY_OWNER/}" >> $GITHUB_ENV - platform=${{ matrix.platform }} + platform=${{ matrix.arch.platform }} echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - name: Checkout repository From 6f30a44592f648111cbe8b263918e6bd951bd299 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:30:19 +0000 Subject: [PATCH 05/33] Push image without tags --- .github/workflows/ci-pipeline.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 5bc923b..cf87945 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -107,8 +107,7 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # Extract metadata (tags, labels) for Docker - # https://github.com/docker/metadata-action + # We extract metadata without tags for single image - name: Extract Docker metadata id: meta uses: docker/metadata-action@v5.7.0 @@ -117,12 +116,8 @@ jobs: # //- images: | ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} - # generate Docker tags based on the following events/attributes - tags: | - type=sha,suffix=-${{ env.PLATFORM_PAIR }} - # Build and push Docker image with Buildx by digest - # https://github.com/docker/build-push-action + # This build an image WITHOUT tags and outputs the digests, so that we can aggragate them later - name: Build and push production image id: build-and-push uses: docker/build-push-action@v6.15.0 @@ -131,7 +126,7 @@ jobs: target: ${{ matrix.docker_target }} platforms: ${{ matrix.arch.platform }} outputs: type=image,push-by-digest=true,name-canonical=true,push=true - tags: ${{ steps.meta.outputs.tags }} + tags: ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max From a4c962b2b21aa7c10dec60cbb6f4e07c21eacc91 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:32:49 +0000 Subject: [PATCH 06/33] Fix digest upload --- .github/workflows/ci-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index cf87945..4044691 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -141,7 +141,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: digests-${{ env.PLATFORM_PAIR }} - path: ${{ runner.temp }}/digests/* + path: ${{ runner.temp }}/digests/${{ matrix.docker_target }}/* if-no-files-found: error retention-days: 1 From 3f9dcdb4cc393fd5ba2cb0b6f95f6d3cad5b257c Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:38:37 +0000 Subject: [PATCH 07/33] Fix digest output --- .github/workflows/ci-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 4044691..d2a73ef 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -134,7 +134,7 @@ jobs: - name: Export digest run: | mkdir -p ${{ runner.temp }}/digests/${{ matrix.docker_target }} - digest="${{ steps.build.outputs.digest }}" + digest="${{ steps.build-and-push.outputs.digest }}" touch "${{ runner.temp }}/digests/${{ matrix.docker_target }}/${digest#sha256:}" - name: Upload digest From 476db9eca5c981e194d2779a6c06e963299c0734 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:47:27 +0000 Subject: [PATCH 08/33] Fix image name --- .github/workflows/ci-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index d2a73ef..2c103ec 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -218,7 +218,7 @@ jobs: working-directory: ${{ runner.temp }}/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) + $(printf '${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }}@sha256:%s ' *) - name: Inspect image run: | From a58b020707c371e91945062cd0f72ffd2da0e93a Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:48:07 +0000 Subject: [PATCH 09/33] Disable branch tags --- .github/workflows/ci-pipeline.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 2c103ec..6590588 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -211,8 +211,8 @@ jobs: # generate Docker tags based on the following events/attributes tags: | type=sha - type=raw,value={{branch}}-latest - type=raw,value={{branch}}-{{date 'YYYYMMDDHHmmss'}} +# type=raw,value={{branch}}-latest +# type=raw,value={{branch}}-{{date 'YYYYMMDDHHmmss'}} - name: Create manifest list and push working-directory: ${{ runner.temp }}/digests From 2bd852f36d4f4a7980c5112f803698a5b747ee11 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 13:07:13 +0000 Subject: [PATCH 10/33] Comment out cosign and fix paths --- .github/workflows/ci-pipeline.yml | 49 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 6590588..bec08d9 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -178,9 +178,6 @@ jobs: pattern: digests-* merge-multiple: true - - name: Checkout repository - uses: actions/checkout@v4 - # Install the cosign tool # https://github.com/sigstore/cosign-installer - name: Install cosign @@ -215,32 +212,32 @@ jobs: # type=raw,value={{branch}}-{{date 'YYYYMMDDHHmmss'}} - name: Create manifest list and push - working-directory: ${{ runner.temp }}/digests + working-directory: ${{ runner.temp }}/digests/${{ matrix.docker_target }} run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ $(printf '${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }}@sha256:%s ' *) - name: Inspect image run: | - docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} - - #TODO: Implement signature using generated key: https://docs.sigstore.dev/signing/quickstart/#signing-with-a-generated-key - - # Sign the resulting Docker image digest except on PRs. - # This will only write to the public Rekor transparency log when the Docker - # repository is public to avoid leaking data. If you would like to publish - # transparency data even for private images, pass --force to cosign below. - # https://github.com/sigstore/cosign - - name: Sign the published Docker image using GitHub OIDC Token - env: - # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable - TAGS: ${{ steps.meta.outputs.tags }} - DIGEST: ${{ steps.build-and-push.outputs.digest }} - # This step uses the identity token to provision an ephemeral certificate - # against the sigstore community Fulcio instance. - run: | - images="" - for tag in ${TAGS}; do - images+="${tag}@${DIGEST} " - done - cosign sign --yes ${images} + docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }}:${{ steps.meta.outputs.version }} + +# #TODO: Implement signature using generated key: https://docs.sigstore.dev/signing/quickstart/#signing-with-a-generated-key +# +# # Sign the resulting Docker image digest except on PRs. +# # This will only write to the public Rekor transparency log when the Docker +# # repository is public to avoid leaking data. If you would like to publish +# # transparency data even for private images, pass --force to cosign below. +# # https://github.com/sigstore/cosign +# - name: Sign the published Docker image using GitHub OIDC Token +# env: +# # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable +# TAGS: ${{ steps.meta.outputs.tags }} +# DIGEST: ${{ steps.build-and-push.outputs.digest }} +# # This step uses the identity token to provision an ephemeral certificate +# # against the sigstore community Fulcio instance. +# run: | +# images="" +# for tag in ${TAGS}; do +# images+="${tag}@${DIGEST} " +# done +# cosign sign --yes ${images} From e5b6734405d9bc0e38c7224dc3c8478372521783 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 13:45:51 +0000 Subject: [PATCH 11/33] Enable build caching to optimize Docker image layer reuse This change introduces build cache mounts for both APT package management and UV commands in the Dockerfile. These updates reduce redundant downloads and improve build performance by leveraging cached data across builds. The new configuration enhances efficiency while maintaining current behavior. --- Dockerfile | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5af24f8..d93d3fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,10 +14,11 @@ RUN mkdir /venv && chown nonroot:nonroot /venv ENV PATH="/venv/bin:$PATH" # Install necessary runtime libraries (e.g. libmysql) -RUN apt-get update \ +RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,id=apt-lib,target=/var/lib/apt,sharing=locked \ + apt-get update \ && apt-get install -y --no-install-recommends \ - make \ - && rm -rf /var/lib/apt/lists/* + make FROM base AS base_builder ENV UV_PROJECT_ENVIRONMENT=/venv @@ -26,10 +27,11 @@ ENV UV_COMPILE_BYTECODE=1 # Install build system requirements (gcc, library headers, etc.) # for compiled Python requirements like psycopg2 -RUN apt-get update \ +RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,id=apt-lib,target=/var/lib/apt,sharing=locked \ + apt-get update \ && apt-get install -y --no-install-recommends \ - build-essential gcc git \ - && rm -rf /var/lib/apt/lists/* + build-essential gcc git COPY --from=ghcr.io/astral-sh/uv:0.6.3 /uv /uvx /bin/ @@ -44,7 +46,7 @@ COPY --chown=nonroot:nonroot Makefile . # Dev image, contains all files and dependencies FROM base_builder AS dev COPY --chown=nonroot:nonroot . . -RUN --mount=type=cache,target=~/.cache/uv \ +RUN --mount=type=cache,id=uv,target=~/.cache/uv,sharing=locked \ make dev-dependencies # Note that opentelemetry doesn't play well together with uvicorn reloader @@ -53,22 +55,22 @@ CMD ["uvicorn", "http_app:create_app", "--host", "0.0.0.0", "--port", "8000", "- # Installs requirements to run production dramatiq application FROM base_builder AS dramatiq_builder -RUN --mount=type=cache,target=~/.cache/uv \ +RUN --mount=type=cache,id=uv,target=~/.cache/uv,sharing=locked \ uv sync --no-dev --no-install-project --frozen --no-editable # Installs requirements to run production http application FROM base_builder AS http_builder -RUN --mount=type=cache,target=~/.cache/uv \ +RUN --mount=type=cache,id=uv,target=~/.cache/uv,sharing=locked \ uv sync --no-dev --group http --no-install-project --frozen --no-editable # Installs requirements to run production socketio application FROM base_builder AS socketio_builder -RUN --mount=type=cache,target=~/.cache/uv \ +RUN --mount=type=cache,id=uv,target=~/.cache/uv,sharing=locked \ uv sync --no-dev --group socketio --no-install-project --frozen --no-editable # Installs requirements to run production migrations application FROM base_builder AS migrations_builder -RUN --mount=type=cache,target=~/.cache/uv \ +RUN --mount=type=cache,target=~/.cache/uv,sharing=locked \ uv sync --no-dev --group migrations --no-install-project --frozen --no-editable # Create the base app with the common python packages From 865df565f693511dfeee46f08d22956fe40e52d9 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:06:41 +0000 Subject: [PATCH 12/33] Add caching steps for UV and APT in CI pipeline Introduce caching for UV and APT files to optimize Docker builds. Use `actions/cache` for storing cache and `buildkit-cache-dance` for injecting caches into the build process. This reduces redundant downloads, improving CI efficiency and build speeds. --- .github/workflows/ci-pipeline.yml | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index bec08d9..93c6934 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -117,6 +117,42 @@ jobs: images: | ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} + - name: UV Build Caches for Docker + id: docker-build-uv-cache + uses: actions/cache@v4 + with: + path: | + home-nonroot-cache-uv + key: cache-uv-${{ hashFiles('uv.lock') }} + + - name: APT Build Caches for Docker APT + id: docker-build-apt-cache + uses: actions/cache@v4 + with: + path: | + var-cache-apt + var-lib-apt + key: cache-apt-${{ hashFiles('Dockerfile') }} + + - name: Inject UV cache in docker + uses: reproducible-containers/buildkit-cache-dance@v3.1.2 + with: + cache-map: | + { + "home-nonroot-cache-uv": "/home/nonroot/.cache/uv" + } + skip-extraction: ${{ steps.docker-build-uv-cache.outputs.cache-hit }} + + - name: Inject APT cache in docker + uses: reproducible-containers/buildkit-cache-dance@v3.1.2 + with: + cache-map: | + { + "var-cache-apt": "/var/cache/apt", + "var-lib-apt": "/var/lib/apt", + } + skip-extraction: ${{ steps.docker-build-apt-cache.outputs.cache-hit }} + # This build an image WITHOUT tags and outputs the digests, so that we can aggragate them later - name: Build and push production image id: build-and-push From 25f769d320b62acb5b3c8bd518b9a506d8b7c4d4 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:10:26 +0000 Subject: [PATCH 13/33] Add cache to the test step --- .github/workflows/ci-pipeline.yml | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 93c6934..d05c1b5 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -33,6 +33,42 @@ jobs: - name: Setup Docker buildx uses: docker/setup-buildx-action@v3.10.0 + - name: UV Build Caches for Docker + id: docker-build-uv-cache + uses: actions/cache@v4 + with: + path: | + home-nonroot-cache-uv + key: cache-uv-${{ hashFiles('uv.lock') }} + + - name: APT Build Caches for Docker APT + id: docker-build-apt-cache + uses: actions/cache@v4 + with: + path: | + var-cache-apt + var-lib-apt + key: cache-apt-${{ hashFiles('Dockerfile') }} + + - name: Inject UV cache in docker + uses: reproducible-containers/buildkit-cache-dance@v3.1.2 + with: + cache-map: | + { + "home-nonroot-cache-uv": "/home/nonroot/.cache/uv" + } + skip-extraction: ${{ steps.docker-build-uv-cache.outputs.cache-hit }} + + - name: Inject APT cache in docker + uses: reproducible-containers/buildkit-cache-dance@v3.1.2 + with: + cache-map: | + { + "var-cache-apt": "/var/cache/apt", + "var-lib-apt": "/var/lib/apt", + } + skip-extraction: ${{ steps.docker-build-apt-cache.outputs.cache-hit }} + # Build but don't push Docker image with Buildx # https://github.com/docker/build-push-action - name: Build test image From 44b14593dae0a6d707721e75a97d76152c2f36a1 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:12:20 +0000 Subject: [PATCH 14/33] Trailing commas --- .github/workflows/ci-pipeline.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index d05c1b5..eeb3532 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -65,7 +65,7 @@ jobs: cache-map: | { "var-cache-apt": "/var/cache/apt", - "var-lib-apt": "/var/lib/apt", + "var-lib-apt": "/var/lib/apt" } skip-extraction: ${{ steps.docker-build-apt-cache.outputs.cache-hit }} @@ -185,7 +185,7 @@ jobs: cache-map: | { "var-cache-apt": "/var/cache/apt", - "var-lib-apt": "/var/lib/apt", + "var-lib-apt": "/var/lib/apt" } skip-extraction: ${{ steps.docker-build-apt-cache.outputs.cache-hit }} From 5d06facebc38ded39ee936b56abfbb1ceace65ba Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:21:33 +0000 Subject: [PATCH 15/33] Use absolute path for uv cache --- Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index d93d3fb..5a74727 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,7 +46,7 @@ COPY --chown=nonroot:nonroot Makefile . # Dev image, contains all files and dependencies FROM base_builder AS dev COPY --chown=nonroot:nonroot . . -RUN --mount=type=cache,id=uv,target=~/.cache/uv,sharing=locked \ +RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked \ make dev-dependencies # Note that opentelemetry doesn't play well together with uvicorn reloader @@ -55,22 +55,22 @@ CMD ["uvicorn", "http_app:create_app", "--host", "0.0.0.0", "--port", "8000", "- # Installs requirements to run production dramatiq application FROM base_builder AS dramatiq_builder -RUN --mount=type=cache,id=uv,target=~/.cache/uv,sharing=locked \ +RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked \ uv sync --no-dev --no-install-project --frozen --no-editable # Installs requirements to run production http application FROM base_builder AS http_builder -RUN --mount=type=cache,id=uv,target=~/.cache/uv,sharing=locked \ +RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked \ uv sync --no-dev --group http --no-install-project --frozen --no-editable # Installs requirements to run production socketio application FROM base_builder AS socketio_builder -RUN --mount=type=cache,id=uv,target=~/.cache/uv,sharing=locked \ +RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked \ uv sync --no-dev --group socketio --no-install-project --frozen --no-editable # Installs requirements to run production migrations application FROM base_builder AS migrations_builder -RUN --mount=type=cache,target=~/.cache/uv,sharing=locked \ +RUN --mount=type=cache,target=/home/nonroot/.cache/uv,sharing=locked \ uv sync --no-dev --group migrations --no-install-project --frozen --no-editable # Create the base app with the common python packages From 6f28ad944f7a567e822f2f46bfb4fc673c9c4535 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:22:16 +0000 Subject: [PATCH 16/33] Add ENV UV_LINK_MODE=copy --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 5a74727..a75f19a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,6 +24,7 @@ FROM base AS base_builder ENV UV_PROJECT_ENVIRONMENT=/venv # Enable bytecode compilation ENV UV_COMPILE_BYTECODE=1 +ENV UV_LINK_MODE=copy # Install build system requirements (gcc, library headers, etc.) # for compiled Python requirements like psycopg2 From a626316bdd89949f036ae200b2a43fbeb90cd621 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:36:05 +0000 Subject: [PATCH 17/33] Add uid and gid options to cache mounts in Dockerfile This ensures proper user and group ownership for cache directories when mounting during build steps. It improves compatibility with non-root users and prevents potential permission issues in CI/CD pipelines or local development environments. --- Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index a75f19a..dd456d7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,7 @@ COPY --chown=nonroot:nonroot Makefile . # Dev image, contains all files and dependencies FROM base_builder AS dev COPY --chown=nonroot:nonroot . . -RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked \ +RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ make dev-dependencies # Note that opentelemetry doesn't play well together with uvicorn reloader @@ -56,22 +56,22 @@ CMD ["uvicorn", "http_app:create_app", "--host", "0.0.0.0", "--port", "8000", "- # Installs requirements to run production dramatiq application FROM base_builder AS dramatiq_builder -RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked \ +RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ uv sync --no-dev --no-install-project --frozen --no-editable # Installs requirements to run production http application FROM base_builder AS http_builder -RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked \ +RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ uv sync --no-dev --group http --no-install-project --frozen --no-editable # Installs requirements to run production socketio application FROM base_builder AS socketio_builder -RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked \ +RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ uv sync --no-dev --group socketio --no-install-project --frozen --no-editable # Installs requirements to run production migrations application FROM base_builder AS migrations_builder -RUN --mount=type=cache,target=/home/nonroot/.cache/uv,sharing=locked \ +RUN --mount=type=cache,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ uv sync --no-dev --group migrations --no-install-project --frozen --no-editable # Create the base app with the common python packages From 970b5edc49a38e2cd00dbdcd3a881b3b7acde2f3 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:55:49 +0000 Subject: [PATCH 18/33] Remove cache ids --- Dockerfile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index dd456d7..129c64f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,8 +14,8 @@ RUN mkdir /venv && chown nonroot:nonroot /venv ENV PATH="/venv/bin:$PATH" # Install necessary runtime libraries (e.g. libmysql) -RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,id=apt-lib,target=/var/lib/apt,sharing=locked \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ apt-get update \ && apt-get install -y --no-install-recommends \ make @@ -28,8 +28,8 @@ ENV UV_LINK_MODE=copy # Install build system requirements (gcc, library headers, etc.) # for compiled Python requirements like psycopg2 -RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,id=apt-lib,target=/var/lib/apt,sharing=locked \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ apt-get update \ && apt-get install -y --no-install-recommends \ build-essential gcc git @@ -47,7 +47,7 @@ COPY --chown=nonroot:nonroot Makefile . # Dev image, contains all files and dependencies FROM base_builder AS dev COPY --chown=nonroot:nonroot . . -RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ +RUN --mount=type=cache,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ make dev-dependencies # Note that opentelemetry doesn't play well together with uvicorn reloader @@ -56,17 +56,17 @@ CMD ["uvicorn", "http_app:create_app", "--host", "0.0.0.0", "--port", "8000", "- # Installs requirements to run production dramatiq application FROM base_builder AS dramatiq_builder -RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ +RUN --mount=type=cache,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ uv sync --no-dev --no-install-project --frozen --no-editable # Installs requirements to run production http application FROM base_builder AS http_builder -RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ +RUN --mount=type=cache,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ uv sync --no-dev --group http --no-install-project --frozen --no-editable # Installs requirements to run production socketio application FROM base_builder AS socketio_builder -RUN --mount=type=cache,id=uv,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ +RUN --mount=type=cache,target=/home/nonroot/.cache/uv,sharing=locked,uid=$UID,gid=$GID \ uv sync --no-dev --group socketio --no-install-project --frozen --no-editable # Installs requirements to run production migrations application From 78d15864d6056e6d9368d269977b11bea898265b Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 15:03:56 +0000 Subject: [PATCH 19/33] Separate caches for architecture, extract always --- .github/workflows/ci-pipeline.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index eeb3532..4f4efa3 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -39,7 +39,7 @@ jobs: with: path: | home-nonroot-cache-uv - key: cache-uv-${{ hashFiles('uv.lock') }} + key: cache-uv-linux-amd64-${{ hashFiles('uv.lock') }} - name: APT Build Caches for Docker APT id: docker-build-apt-cache @@ -48,7 +48,7 @@ jobs: path: | var-cache-apt var-lib-apt - key: cache-apt-${{ hashFiles('Dockerfile') }} + key: cache-apt-linux-amd64-${{ hashFiles('Dockerfile') }} - name: Inject UV cache in docker uses: reproducible-containers/buildkit-cache-dance@v3.1.2 @@ -57,7 +57,6 @@ jobs: { "home-nonroot-cache-uv": "/home/nonroot/.cache/uv" } - skip-extraction: ${{ steps.docker-build-uv-cache.outputs.cache-hit }} - name: Inject APT cache in docker uses: reproducible-containers/buildkit-cache-dance@v3.1.2 @@ -67,7 +66,6 @@ jobs: "var-cache-apt": "/var/cache/apt", "var-lib-apt": "/var/lib/apt" } - skip-extraction: ${{ steps.docker-build-apt-cache.outputs.cache-hit }} # Build but don't push Docker image with Buildx # https://github.com/docker/build-push-action @@ -159,7 +157,7 @@ jobs: with: path: | home-nonroot-cache-uv - key: cache-uv-${{ hashFiles('uv.lock') }} + key: cache-uv-${{ env.PLATFORM_PAIR }}-${{ hashFiles('uv.lock') }} - name: APT Build Caches for Docker APT id: docker-build-apt-cache @@ -168,7 +166,7 @@ jobs: path: | var-cache-apt var-lib-apt - key: cache-apt-${{ hashFiles('Dockerfile') }} + key: cache-apt-${{ env.PLATFORM_PAIR }}-${{ hashFiles('Dockerfile') }} - name: Inject UV cache in docker uses: reproducible-containers/buildkit-cache-dance@v3.1.2 @@ -177,7 +175,6 @@ jobs: { "home-nonroot-cache-uv": "/home/nonroot/.cache/uv" } - skip-extraction: ${{ steps.docker-build-uv-cache.outputs.cache-hit }} - name: Inject APT cache in docker uses: reproducible-containers/buildkit-cache-dance@v3.1.2 @@ -187,7 +184,6 @@ jobs: "var-cache-apt": "/var/cache/apt", "var-lib-apt": "/var/lib/apt" } - skip-extraction: ${{ steps.docker-build-apt-cache.outputs.cache-hit }} # This build an image WITHOUT tags and outputs the digests, so that we can aggragate them later - name: Build and push production image From f40f4f310443d1ccd58a0fa0cbbcccb6400d33c4 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 15:26:32 +0000 Subject: [PATCH 20/33] Try adding options to cache-map --- .github/workflows/ci-pipeline.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 4f4efa3..f9727fe 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -55,7 +55,12 @@ jobs: with: cache-map: | { - "home-nonroot-cache-uv": "/home/nonroot/.cache/uv" + "home-nonroot-cache-uv": { + "target": "/home/nonroot/.cache/uv", + "sharing": "locked", + "uid": "2000", + "gid": "2000" + } } - name: Inject APT cache in docker @@ -173,7 +178,12 @@ jobs: with: cache-map: | { - "home-nonroot-cache-uv": "/home/nonroot/.cache/uv" + "home-nonroot-cache-uv": { + "target": "/home/nonroot/.cache/uv", + "sharing": "locked", + "uid": "2000", + "gid": "2000" + } } - name: Inject APT cache in docker From 3d21c8d09e90e66246760126c0764a9ee0867c99 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 15:31:58 +0000 Subject: [PATCH 21/33] Do not skip extraction --- .github/workflows/ci-pipeline.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index f9727fe..8785a96 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -53,6 +53,7 @@ jobs: - name: Inject UV cache in docker uses: reproducible-containers/buildkit-cache-dance@v3.1.2 with: + skip-extraction: false cache-map: | { "home-nonroot-cache-uv": { @@ -66,6 +67,7 @@ jobs: - name: Inject APT cache in docker uses: reproducible-containers/buildkit-cache-dance@v3.1.2 with: + skip-extraction: false cache-map: | { "var-cache-apt": "/var/cache/apt", @@ -176,6 +178,7 @@ jobs: - name: Inject UV cache in docker uses: reproducible-containers/buildkit-cache-dance@v3.1.2 with: + skip-extraction: false cache-map: | { "home-nonroot-cache-uv": { @@ -189,6 +192,7 @@ jobs: - name: Inject APT cache in docker uses: reproducible-containers/buildkit-cache-dance@v3.1.2 with: + skip-extraction: false cache-map: | { "var-cache-apt": "/var/cache/apt", From fe48a0b2d440d02f6c8c00b3d81cce5eb7832355 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 15:54:16 +0000 Subject: [PATCH 22/33] Remove gha shenanigans --- .github/workflows/ci-pipeline.yml | 73 ------------------------------- 1 file changed, 73 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 8785a96..924f1c3 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -41,39 +41,6 @@ jobs: home-nonroot-cache-uv key: cache-uv-linux-amd64-${{ hashFiles('uv.lock') }} - - name: APT Build Caches for Docker APT - id: docker-build-apt-cache - uses: actions/cache@v4 - with: - path: | - var-cache-apt - var-lib-apt - key: cache-apt-linux-amd64-${{ hashFiles('Dockerfile') }} - - - name: Inject UV cache in docker - uses: reproducible-containers/buildkit-cache-dance@v3.1.2 - with: - skip-extraction: false - cache-map: | - { - "home-nonroot-cache-uv": { - "target": "/home/nonroot/.cache/uv", - "sharing": "locked", - "uid": "2000", - "gid": "2000" - } - } - - - name: Inject APT cache in docker - uses: reproducible-containers/buildkit-cache-dance@v3.1.2 - with: - skip-extraction: false - cache-map: | - { - "var-cache-apt": "/var/cache/apt", - "var-lib-apt": "/var/lib/apt" - } - # Build but don't push Docker image with Buildx # https://github.com/docker/build-push-action - name: Build test image @@ -158,46 +125,6 @@ jobs: images: | ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} - - name: UV Build Caches for Docker - id: docker-build-uv-cache - uses: actions/cache@v4 - with: - path: | - home-nonroot-cache-uv - key: cache-uv-${{ env.PLATFORM_PAIR }}-${{ hashFiles('uv.lock') }} - - - name: APT Build Caches for Docker APT - id: docker-build-apt-cache - uses: actions/cache@v4 - with: - path: | - var-cache-apt - var-lib-apt - key: cache-apt-${{ env.PLATFORM_PAIR }}-${{ hashFiles('Dockerfile') }} - - - name: Inject UV cache in docker - uses: reproducible-containers/buildkit-cache-dance@v3.1.2 - with: - skip-extraction: false - cache-map: | - { - "home-nonroot-cache-uv": { - "target": "/home/nonroot/.cache/uv", - "sharing": "locked", - "uid": "2000", - "gid": "2000" - } - } - - - name: Inject APT cache in docker - uses: reproducible-containers/buildkit-cache-dance@v3.1.2 - with: - skip-extraction: false - cache-map: | - { - "var-cache-apt": "/var/cache/apt", - "var-lib-apt": "/var/lib/apt" - } # This build an image WITHOUT tags and outputs the digests, so that we can aggragate them later - name: Build and push production image From 380565f20d31686bfc5e1d67657968a64aace84b Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 15:59:49 +0000 Subject: [PATCH 23/33] Use registry cache --- .github/workflows/ci-pipeline.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 924f1c3..bf3410e 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -51,8 +51,8 @@ jobs: load: true target: dev tags: ${{ env.TEST_TAG }} - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:buildcache + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:buildcache,mode=max # This is a barrier check to make sure we push a functional # docker image, we can avoid linting @@ -137,8 +137,8 @@ jobs: outputs: type=image,push-by-digest=true,name-canonical=true,push=true tags: ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:buildcache + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:buildcache,mode=max - name: Export digest run: | From 11030173e52890237796d5b172d0101fc100ae30 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 16:03:49 +0000 Subject: [PATCH 24/33] Add missing env var --- .github/workflows/ci-pipeline.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index bf3410e..d73e838 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -25,6 +25,14 @@ jobs: test: runs-on: ubuntu-latest steps: + # GitHub gives only repository complete in / format. + # Need some manual shenanigans + # Set IMAGE_NAME so we can push to // + # Transform os/arch to os-arch for suffix target + - name: Set ENV variables + run: | + echo "IMAGE_NAME=${GITHUB_REPOSITORY#$GITHUB_REPOSITORY_OWNER/}" >> $GITHUB_ENV + - name: Checkout repository uses: actions/checkout@v4 From a2e25012971d85a27ed7d8233adc2222e3ade2c8 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 16:07:23 +0000 Subject: [PATCH 25/33] Login into registry --- .github/workflows/ci-pipeline.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index d73e838..ea52f7d 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -36,6 +36,15 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + # Login against a Docker registry + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + uses: docker/login-action@v3.3.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + # This might be unnecessary as tests are not # multiplatform - name: Setup Docker buildx From ba5991737f076ce245aad22dbd7bf9cdbd9e134b Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 16:14:43 +0000 Subject: [PATCH 26/33] Permissions --- .github/workflows/ci-pipeline.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index ea52f7d..30daca7 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -24,6 +24,9 @@ env: jobs: test: runs-on: ubuntu-latest + permissions: + contents: read + packages: write steps: # GitHub gives only repository complete in / format. # Need some manual shenanigans From c65fedeb6605555bd73416233a8342387be95866 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 16:25:05 +0000 Subject: [PATCH 27/33] Split image caches --- .github/workflows/ci-pipeline.yml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 30daca7..9a79628 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -53,14 +53,6 @@ jobs: - name: Setup Docker buildx uses: docker/setup-buildx-action@v3.10.0 - - name: UV Build Caches for Docker - id: docker-build-uv-cache - uses: actions/cache@v4 - with: - path: | - home-nonroot-cache-uv - key: cache-uv-linux-amd64-${{ hashFiles('uv.lock') }} - # Build but don't push Docker image with Buildx # https://github.com/docker/build-push-action - name: Build test image @@ -71,8 +63,8 @@ jobs: load: true target: dev tags: ${{ env.TEST_TAG }} - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:buildcache - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:buildcache,mode=max + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:tests + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:tests,mode=max # This is a barrier check to make sure we push a functional # docker image, we can avoid linting @@ -157,8 +149,8 @@ jobs: outputs: type=image,push-by-digest=true,name-canonical=true,push=true tags: ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:buildcache - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:buildcache,mode=max + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }}:buildcache + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }}:buildcache,mode=max - name: Export digest run: | From ae47571da68e36afb2e55271b4b0a67c60a6c4fb Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 16:27:45 +0000 Subject: [PATCH 28/33] Split caches --- .github/workflows/ci-pipeline.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 9a79628..9df41a0 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -149,8 +149,8 @@ jobs: outputs: type=image,push-by-digest=true,name-canonical=true,push=true tags: ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }}:buildcache - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }}:buildcache,mode=max + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:buildcache-${{ matrix.docker_target }}-${{ env.PLATFORM_PAIR }} + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-cache:buildcache-${{ matrix.docker_target }}-${{ env.PLATFORM_PAIR }},mode=max - name: Export digest run: | From df7b9501a8ce9d82e3e174e9e8c075d9a8877eb0 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 16:47:57 +0000 Subject: [PATCH 29/33] Enable cosign and test multiple tags --- .github/workflows/ci-pipeline.yml | 41 ++++++++++++++++--------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 9df41a0..9dfb572 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -229,6 +229,7 @@ jobs: # generate Docker tags based on the following events/attributes tags: | type=sha + type=sha,suffix=-test # type=raw,value={{branch}}-latest # type=raw,value={{branch}}-{{date 'YYYYMMDDHHmmss'}} @@ -242,23 +243,23 @@ jobs: run: | docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}/${{ env.IMAGE_NAME }}-${{ matrix.docker_target }}:${{ steps.meta.outputs.version }} -# #TODO: Implement signature using generated key: https://docs.sigstore.dev/signing/quickstart/#signing-with-a-generated-key -# -# # Sign the resulting Docker image digest except on PRs. -# # This will only write to the public Rekor transparency log when the Docker -# # repository is public to avoid leaking data. If you would like to publish -# # transparency data even for private images, pass --force to cosign below. -# # https://github.com/sigstore/cosign -# - name: Sign the published Docker image using GitHub OIDC Token -# env: -# # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable -# TAGS: ${{ steps.meta.outputs.tags }} -# DIGEST: ${{ steps.build-and-push.outputs.digest }} -# # This step uses the identity token to provision an ephemeral certificate -# # against the sigstore community Fulcio instance. -# run: | -# images="" -# for tag in ${TAGS}; do -# images+="${tag}@${DIGEST} " -# done -# cosign sign --yes ${images} + #TODO: Implement signature using generated key: https://docs.sigstore.dev/signing/quickstart/#signing-with-a-generated-key + + # Sign the resulting Docker image digest except on PRs. + # This will only write to the public Rekor transparency log when the Docker + # repository is public to avoid leaking data. If you would like to publish + # transparency data even for private images, pass --force to cosign below. + # https://github.com/sigstore/cosign + - name: Sign the published Docker image using GitHub OIDC Token + env: + # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable + TAGS: ${{ steps.meta.outputs.tags }} + DIGEST: ${{ steps.build-and-push.outputs.digest }} + # This step uses the identity token to provision an ephemeral certificate + # against the sigstore community Fulcio instance. + run: | + images="" + for tag in ${TAGS}; do + images+="${tag}@${DIGEST} " + done + cosign sign --yes ${images} From 18f8ac1c0aca32367d464a0beb193ccfa7578f8e Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 17:22:40 +0000 Subject: [PATCH 30/33] Try fixing cosign --- .github/workflows/ci-pipeline.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 9dfb572..f24630b 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -254,12 +254,11 @@ jobs: env: # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable TAGS: ${{ steps.meta.outputs.tags }} - DIGEST: ${{ steps.build-and-push.outputs.digest }} # This step uses the identity token to provision an ephemeral certificate # against the sigstore community Fulcio instance. run: | images="" for tag in ${TAGS}; do - images+="${tag}@${DIGEST} " + images+="${tag}@sha256:$(docker buildx imagetools inspect --format '{{.Digest}}' ${tag}) " done cosign sign --yes ${images} From f21ebf60e0c5bf62b2d297abb22b82590b7cbdf2 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 17:48:11 +0000 Subject: [PATCH 31/33] Fix digest inspectin command --- .github/workflows/ci-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index f24630b..1938596 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -259,6 +259,6 @@ jobs: run: | images="" for tag in ${TAGS}; do - images+="${tag}@sha256:$(docker buildx imagetools inspect --format '{{.Digest}}' ${tag}) " + images+="${tag}@sha256:$(docker buildx imagetools inspect --format '{{json .Manifest.Digest}}' ${tag} | xargs) " done cosign sign --yes ${images} From a0946b002fe9bcf1299745c2197aa28cb6432756 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 17:59:07 +0000 Subject: [PATCH 32/33] Remove double `sha256:` --- .github/workflows/ci-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 1938596..56e1d04 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -259,6 +259,6 @@ jobs: run: | images="" for tag in ${TAGS}; do - images+="${tag}@sha256:$(docker buildx imagetools inspect --format '{{json .Manifest.Digest}}' ${tag} | xargs) " + images+="${tag}@$(docker buildx imagetools inspect --format '{{json .Manifest.Digest}}' ${tag} | xargs) " done cosign sign --yes ${images} From 3840e4574febdcf395456aa2c1780913cbb652f9 Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Thu, 6 Mar 2025 18:03:41 +0000 Subject: [PATCH 33/33] Disable build on PR, restore all docker targets, make ready for merging --- .github/workflows/ci-pipeline.yml | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 56e1d04..d911017 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -11,8 +11,8 @@ on: ####### Uncomment this to test the CI pipeline in a PR ####### You'll also need to comment the rules containing {{branch}} ####### in the `Extract Docker metadata` step - pull_request: - branches: [ "main" ] +# pull_request: +# branches: [ "main" ] env: # Use docker.io for Docker Hub if empty @@ -92,10 +92,10 @@ jobs: # https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources runner: ubuntu-24.04-arm docker_target: -# - migrations + - migrations - http -# - socketio -# - dramatiq + - socketio + - dramatiq steps: # GitHub gives only repository complete in / format. # Need some manual shenanigans @@ -179,10 +179,10 @@ jobs: strategy: matrix: docker_target: - # - migrations + - migrations - http - # - socketio - # - dramatiq + - socketio + - dramatiq steps: # GitHub gives only repository complete in / format. @@ -229,9 +229,8 @@ jobs: # generate Docker tags based on the following events/attributes tags: | type=sha - type=sha,suffix=-test -# type=raw,value={{branch}}-latest -# type=raw,value={{branch}}-{{date 'YYYYMMDDHHmmss'}} + type=raw,value={{branch}}-latest + type=raw,value={{branch}}-{{date 'YYYYMMDDHHmmss'}} - name: Create manifest list and push working-directory: ${{ runner.temp }}/digests/${{ matrix.docker_target }}