name: Release multi-arch container image on: workflow_dispatch: push: branches: - main - "test/**" schedule: - cron: "0 0 * * *" # Run every day at 00:00 UTC. env: REGISTRY: ghcr.io/${{ github.repository_owner }} REGISTRY_USER: ${{ github.actor }} REGISTRY_PASSWORD: ${{ github.token }} IMAGE_NAME: dangerzone/dangerzone BUILDKIT_IMAGE: "docker.io/moby/buildkit:v19.0@sha256:14aa1b4dd92ea0a4cd03a54d0c6079046ea98cd0c0ae6176bdd7036ba370cbbe" jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install dev. dependencies run: |- sudo apt-get update sudo apt-get install -y git python3-poetry --no-install-recommends poetry install --only package - name: Verify that the Dockerfile matches the commited template and params run: |- cp Dockerfile Dockerfile.orig make Dockerfile diff Dockerfile.orig Dockerfile prepare: runs-on: ubuntu-latest outputs: debian_archive_date: ${{ steps.date.outputs.debian_archive_date }} source_date_epoch: ${{ steps.date.outputs.source_date_epoch }} steps: - name: Get current date id: date run: | DEBIAN_ARCHIVE_DATE=$(date -u +'%Y%m%d') SOURCE_DATE_EPOCH=$(date -u -d ${DEBIAN_ARCHIVE_DATE} +"%s") echo "debian_archive_date=${DEBIAN_ARCHIVE_DATE}" >> $GITHUB_OUTPUT echo "source_date_epoch=${SOURCE_DATE_EPOCH}" >> $GITHUB_OUTPUT build: runs-on: ubuntu-24.04${{ matrix.platform.suffix }} needs: - prepare strategy: fail-fast: false #matrix: # platform: # - suffix: "" # name: "linux/amd64" # - suffix: "-arm" # name: "linux/arm64" steps: - uses: actions/checkout@v4 #- name: Prepare # run: | # platform=${{ matrix.platform.name }} # echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - name: Login to GHCR uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: driver-opts: image=${{ env.BUILDKIT_IMAGE }} - name: Build and push id: build uses: docker/build-push-action@v6 with: context: ./dangerzone/ file: Dockerfile build-args: | DEBIAN_ARCHIVE_DATE=${{ needs.prepare.outputs.debian_archive_date }} SOURCE_DATE_EPOCH=${{ needs.prepare.outputs.source_date_epoch }} # Remove potentially incorrect Docker provenance that cannot be # reproduced. provenance: false platforms: linux/amd64,linux/arm64 outputs: type=registry,"name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}",rewrite-timestamp=true,name-canonical=true cache-from: type=gha cache-to: type=gha,mode=max #- name: Export digest # run: | # mkdir -p ${{ runner.temp }}/digests # digest="${{ steps.build.outputs.digest }}" # touch "${{ runner.temp }}/digests/${digest#sha256:}" # echo "Image digest is: ${digest}" #- 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 #merge: # runs-on: ubuntu-latest # needs: # - prepare # - build # outputs: # digest: ${{ steps.image.outputs.digest }} # image: ${{ steps.image.outputs.image }} # steps: # - uses: actions/checkout@v4 # with: # fetch-depth: 0 # - name: Compute image tag # id: tag # run: | # DEBIAN_ARCHIVE_DATE=${{ needs.prepare.outputs.debian_archive_date }} # TAG=$(git describe --long --first-parent | tail -c +2) # echo "tag=${DEBIAN_ARCHIVE_DATE}-${TAG}" >> $GITHUB_OUTPUT # - name: Download digests # uses: actions/download-artifact@v4 # with: # path: ${{ runner.temp }}/digests # pattern: digests-* # merge-multiple: true # - name: Login to GHCR # uses: docker/login-action@v3 # with: # registry: ghcr.io # username: ${{ github.repository_owner }} # password: ${{ secrets.GITHUB_TOKEN }} # - name: Set up Docker Buildx # uses: docker/setup-buildx-action@v3 # with: # driver-opts: image=${{ env.BUILDKIT_IMAGE }} # - name: Create manifest list and push # working-directory: ${{ runner.temp }}/digests # run: | # IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }} # DIGESTS=$(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) # docker buildx imagetools create -t ${IMAGE} ${DIGESTS} - name: Inspect image id: image run: | # NOTE: Set the image as an output because the `env` context is not # available to the inputs of a reusable workflow call. image_name="${REGISTRY}/${IMAGE_NAME}" echo "image=$image_name" >> "$GITHUB_OUTPUT" docker buildx imagetools inspect ${image_name}:${{ steps.tag.outputs.tag }} digest=$(docker buildx imagetools inspect ${image_name}:${{ steps.tag.outputs.tag }} --format "{{json .Manifest}}" | jq -r '.digest') echo "digest=$digest" >> "$GITHUB_OUTPUT" # This step calls the container workflow to generate provenance and push it to # the container registry. provenance: needs: - build permissions: actions: read # for detecting the Github Actions environment. id-token: write # for creating OIDC tokens for signing. packages: write # for uploading attestations. uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0 with: digest: ${{ needs.build.outputs.digest }} image: ${{ needs.build.outputs.image }} registry-username: ${{ github.actor }} secrets: registry-password: ${{ secrets.GITHUB_TOKEN }} # This step ensures that the image is reproducible check-reproducibility: needs: - prepare - build runs-on: ubuntu-24.04${{ matrix.platform.suffix }} strategy: fail-fast: false matrix: platform: - suffix: "" name: "linux/amd64" - suffix: "-arm" name: "linux/arm64" steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Reproduce the same container image run: | ./dev_scripts/reproduce-image.py \ --debian-archive-date ${{ needs.build.prepare.debian_archive_date }} \ --source ${{ needs.build.outputs.image }}@${{ needs.build.outputs.digest }} \ --platform ${{ matrix.platform.name }}