WIP: Longer builds, more reproducible

This commit is contained in:
Alex Pyrgiotis 2025-02-25 17:31:32 +02:00
parent da6a52bfbc
commit 1d8026e333
No known key found for this signature in database
GPG key ID: B6C15EBA0357C9AA
2 changed files with 91 additions and 84 deletions

View file

@ -54,19 +54,19 @@ jobs:
- prepare - prepare
strategy: strategy:
fail-fast: false fail-fast: false
matrix: #matrix:
platform: # platform:
- suffix: "" # - suffix: ""
name: "linux/amd64" # name: "linux/amd64"
- suffix: "-arm" # - suffix: "-arm"
name: "linux/arm64" # name: "linux/arm64"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Prepare #- name: Prepare
run: | # run: |
platform=${{ matrix.platform.name }} # platform=${{ matrix.platform.name }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV # echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Login to GHCR - name: Login to GHCR
uses: docker/login-action@v3 uses: docker/login-action@v3
@ -80,7 +80,7 @@ jobs:
with: with:
driver-opts: image=${{ env.BUILDKIT_IMAGE }} driver-opts: image=${{ env.BUILDKIT_IMAGE }}
- name: Build and push by digest - name: Build and push
id: build id: build
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
@ -92,71 +92,71 @@ jobs:
# Remove potentially incorrect Docker provenance that cannot be # Remove potentially incorrect Docker provenance that cannot be
# reproduced. # reproduced.
provenance: false provenance: false
platforms: ${{ matrix.platform.name }} platforms: linux/amd64,linux/arm64
outputs: type=image,"name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}",rewrite-timestamp=true,push-by-digest=true,name-canonical=true,push=true outputs: type=registry,"name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}",rewrite-timestamp=true,name-canonical=true
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
- name: Export digest #- name: Export digest
run: | # run: |
mkdir -p ${{ runner.temp }}/digests # mkdir -p ${{ runner.temp }}/digests
digest="${{ steps.build.outputs.digest }}" # digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${digest#sha256:}" # touch "${{ runner.temp }}/digests/${digest#sha256:}"
echo "Image digest is: ${digest}" # echo "Image digest is: ${digest}"
- name: Upload digest #- name: Upload digest
uses: actions/upload-artifact@v4 # uses: actions/upload-artifact@v4
with: # with:
name: digests-${{ env.PLATFORM_PAIR }} # name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/* # path: ${{ runner.temp }}/digests/*
if-no-files-found: error # if-no-files-found: error
retention-days: 1 # retention-days: 1
merge: #merge:
runs-on: ubuntu-latest # runs-on: ubuntu-latest
needs: # needs:
- prepare # - prepare
- build # - build
outputs: # outputs:
digest: ${{ steps.image.outputs.digest }} # digest: ${{ steps.image.outputs.digest }}
image: ${{ steps.image.outputs.image }} # image: ${{ steps.image.outputs.image }}
steps: # steps:
- uses: actions/checkout@v4 # - uses: actions/checkout@v4
with: # with:
fetch-depth: 0 # fetch-depth: 0
- name: Compute image tag # - name: Compute image tag
id: tag # id: tag
run: | # run: |
DEBIAN_ARCHIVE_DATE=${{ needs.prepare.outputs.debian_archive_date }} # DEBIAN_ARCHIVE_DATE=${{ needs.prepare.outputs.debian_archive_date }}
TAG=$(git describe --long --first-parent | tail -c +2) # TAG=$(git describe --long --first-parent | tail -c +2)
echo "tag=${DEBIAN_ARCHIVE_DATE}-${TAG}" >> $GITHUB_OUTPUT # echo "tag=${DEBIAN_ARCHIVE_DATE}-${TAG}" >> $GITHUB_OUTPUT
- name: Download digests # - name: Download digests
uses: actions/download-artifact@v4 # uses: actions/download-artifact@v4
with: # with:
path: ${{ runner.temp }}/digests # path: ${{ runner.temp }}/digests
pattern: digests-* # pattern: digests-*
merge-multiple: true # merge-multiple: true
- name: Login to GHCR # - name: Login to GHCR
uses: docker/login-action@v3 # uses: docker/login-action@v3
with: # with:
registry: ghcr.io # registry: ghcr.io
username: ${{ github.repository_owner }} # username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }} # password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx # - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 # uses: docker/setup-buildx-action@v3
with: # with:
driver-opts: image=${{ env.BUILDKIT_IMAGE }} # driver-opts: image=${{ env.BUILDKIT_IMAGE }}
- name: Create manifest list and push # - name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests # working-directory: ${{ runner.temp }}/digests
run: | # run: |
IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }} # IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }}
DIGESTS=$(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) # DIGESTS=$(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
docker buildx imagetools create -t ${IMAGE} ${DIGESTS} # docker buildx imagetools create -t ${IMAGE} ${DIGESTS}
- name: Inspect image - name: Inspect image
id: image id: image
@ -173,15 +173,15 @@ jobs:
# the container registry. # the container registry.
provenance: provenance:
needs: needs:
- merge - build
permissions: permissions:
actions: read # for detecting the Github Actions environment. actions: read # for detecting the Github Actions environment.
id-token: write # for creating OIDC tokens for signing. id-token: write # for creating OIDC tokens for signing.
packages: write # for uploading attestations. packages: write # for uploading attestations.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0 uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
with: with:
digest: ${{ needs.merge.outputs.digest }} digest: ${{ needs.build.outputs.digest }}
image: ${{ needs.merge.outputs.image }} image: ${{ needs.build.outputs.image }}
registry-username: ${{ github.actor }} registry-username: ${{ github.actor }}
secrets: secrets:
registry-password: ${{ secrets.GITHUB_TOKEN }} registry-password: ${{ secrets.GITHUB_TOKEN }}
@ -190,7 +190,7 @@ jobs:
check-reproducibility: check-reproducibility:
needs: needs:
- prepare - prepare
- merge - build
runs-on: ubuntu-24.04${{ matrix.platform.suffix }} runs-on: ubuntu-24.04${{ matrix.platform.suffix }}
strategy: strategy:
fail-fast: false fail-fast: false
@ -209,5 +209,5 @@ jobs:
run: | run: |
./dev_scripts/reproduce-image.py \ ./dev_scripts/reproduce-image.py \
--debian-archive-date ${{ needs.build.prepare.debian_archive_date }} \ --debian-archive-date ${{ needs.build.prepare.debian_archive_date }} \
--source ${{ needs.merge.outputs.image }}@${{ needs.merge.outputs.digest }} \ --source ${{ needs.build.outputs.image }}@${{ needs.build.outputs.digest }} \
--platform ${{ matrix.platform.name }} --platform ${{ matrix.platform.name }}

View file

@ -4,6 +4,7 @@ import argparse
import hashlib import hashlib
import logging import logging
import pathlib import pathlib
import platform
import stat import stat
import subprocess import subprocess
import sys import sys
@ -85,16 +86,20 @@ def diffoci_download():
DIFFOCI_PATH.chmod(DIFFOCI_PATH.stat().st_mode | stat.S_IEXEC) DIFFOCI_PATH.chmod(DIFFOCI_PATH.stat().st_mode | stat.S_IEXEC)
def diffoci_diff(runtime, source, local_target, platform=None): def diffoci_diff(runtime, source, target, platform=None):
"""Diff the source image against the recently built target image using diffoci.""" """Diff the source image against the recently built target image using diffoci."""
target = f"{runtime}://{local_target}"
platform_args = [] if not platform else ["--platform", platform] platform_args = [] if not platform else ["--platform", platform]
logger.info(f"Loading image tarball in diffoci")
with open("share/container.tar") as f:
subprocess.run([str(DIFFOCI_PATH), "load"], stdin=f, check=True)
logger.info(f"Performing a strict diff between the two images")
try: try:
return run( return run(
str(DIFFOCI_PATH), str(DIFFOCI_PATH),
"diff", "diff",
source, source,
target, target,
# "--semantic",
"--verbose", "--verbose",
*platform_args, *platform_args,
) )
@ -116,17 +121,19 @@ def build_image(
platform_args = [] if not platform else ["--platform", platform] platform_args = [] if not platform else ["--platform", platform]
runtime_args = [] if not runtime else ["--runtime", runtime] runtime_args = [] if not runtime else ["--runtime", runtime]
date_args = [] if not date else ["--debian-archive-date", date] date_args = [] if not date else ["--debian-archive-date", date]
run( subprocess.run(
"python3", [
"./install/common/build-image.py", "python3",
"--no-save", "./install/common/build-image.py",
"--use-cache", "--use-cache",
str(use_cache), str(use_cache),
*date_args, *date_args,
*platform_args, *platform_args,
*runtime_args, *runtime_args,
"--tag", "--tag",
tag, tag,
],
check=True,
) )