From 4da8133faf23b79cc4b1a45ba00ba2c48c3105a8 Mon Sep 17 00:00:00 2001 From: sh <37271604+shumvgolove@users.noreply.github.com> Date: Thu, 5 Jun 2025 07:26:40 +0000 Subject: [PATCH] ci: add reproducible Linux desktop builds (#5960) * ci: add reproducible Linux desktop builds * ci: move commands from ci to script * scripts: switch appimage tools to simplex-chat forks (stable release) --- .github/workflows/build.yml | 6 ++-- Dockerfile.build | 1 + scripts/desktop/make-appimage-linux.sh | 20 ++++++++++-- scripts/desktop/make-deb-linux.sh | 44 ++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 7 deletions(-) create mode 100755 scripts/desktop/make-deb-linux.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca1bc79510..26979df834 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -234,16 +234,14 @@ jobs: if: startsWith(github.ref, 'refs/tags/v') && matrix.should_run == true shell: docker exec -t builder sh -eu {0} run: | - scripts/desktop/build-lib-linux.sh - cd apps/multiplatform - ./gradlew packageDeb + scripts/desktop/make-deb-linux.sh - name: Prepare Desktop id: linux_desktop_build if: startsWith(github.ref, 'refs/tags/v') && matrix.should_run == true shell: bash run: | - path=$(echo ${{ github.workspace }}/apps/multiplatform/release/main/deb/simplex_*_amd64.deb ) + path=$(echo ${{ github.workspace }}/apps/multiplatform/release/main/deb/simplex_amd64.deb ) echo "package_path=$path" >> $GITHUB_OUTPUT echo "package_hash=$(echo SHA2-256\(${{ matrix.desktop_asset_name }}\)= $(openssl sha256 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT diff --git a/Dockerfile.build b/Dockerfile.build index 76bb1127f2..9b7c38fa87 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -16,6 +16,7 @@ RUN apt-get update && \ apt-get install -y curl \ libpq-dev \ git \ + strip-nondeterminism \ sqlite3 \ libsqlite3-dev \ build-essential \ diff --git a/scripts/desktop/make-appimage-linux.sh b/scripts/desktop/make-appimage-linux.sh index 6cc7aac011..ffd5e13337 100755 --- a/scripts/desktop/make-appimage-linux.sh +++ b/scripts/desktop/make-appimage-linux.sh @@ -37,13 +37,27 @@ cp *imple*.desktop usr/share/applications/ cp $multiplatform_dir/desktop/src/jvmMain/resources/distribute/*.appdata.xml usr/share/metainfo if [ ! -f ../appimagetool-x86_64.AppImage ]; then - wget --secure-protocol=TLSv1_3 https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage -O ../appimagetool-x86_64.AppImage + wget --secure-protocol=TLSv1_3 https://github.com/simplex-chat/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage -O ../appimagetool-x86_64.AppImage chmod +x ../appimagetool-x86_64.AppImage fi if [ ! -f ../runtime-x86_64 ]; then - wget --secure-protocol=TLSv1_3 https://github.com/AppImage/type2-runtime/releases/download/continuous/runtime-x86_64 -O ../runtime-x86_64 + wget --secure-protocol=TLSv1_3 https://github.com/simplex-chat/type2-runtime/releases/download/continuous/runtime-x86_64 -O ../runtime-x86_64 chmod +x ../runtime-x86_64 fi -../appimagetool-x86_64.AppImage --runtime-file ../runtime-x86_64 . +# Determenistic build + +export SOURCE_DATE_EPOCH=1704067200 + +# Delete redundant jar file and modify cfg +rm -f ./usr/lib/app/*skiko-awt-runtime-linux* +sed -i -e '/skiko-awt-runtime-linux/d' ./usr/lib/app/simplex.cfg + +# Set all files to fixed time +find . -exec touch -d "@$SOURCE_DATE_EPOCH" {} + + +../appimagetool-x86_64.AppImage --verbose --no-appstream --runtime-file ../runtime-x86_64 . mv *imple*.AppImage ../../ + +# Just a safeguard +strip-nondeterminism ../../*imple*.AppImage diff --git a/scripts/desktop/make-deb-linux.sh b/scripts/desktop/make-deb-linux.sh new file mode 100755 index 0000000000..6f9de8a1e6 --- /dev/null +++ b/scripts/desktop/make-deb-linux.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env sh + +scripts/desktop/build-lib-linux.sh +cd apps/multiplatform +./gradlew packageDeb + +# Workaround for skiko library +# +# Compose Multiplatform depends on skiko library, that +# handles all of the window managment and graphics drawing. +# +# This skiko library comes with two jar's: +# - platform-agnostic "skiko-awt" +# - and platform-specific "skiko-awt-runtime" +# +# In case of Linux, second jar is called "skiko-awt-runtime-linux-x64". +# Essentially, this jar has the Linux .so library called "libskiko-linux-x64.so" +# that is being unpacked to runtime libs. +# +# Since the jar is nothing more than a zip archive, extracting library +# from "skiko-awt-runtime-linux-x64" modifies it's timestamps +# with current time, which in changes it's hash, which in turn +# makes the whole build unreproducible. +# +# It seems to be there is no way to handle this extraction in our code and +# https://docs.gradle.org/current/userguide/working_with_files.html#sec:reproducible_archives +# unfortunately doesn't solve the issue. +# +# Instead, just modify the deb, removing the redundant skiko library. +# +# Also, it seems this is related to: +# https://youtrack.jetbrains.com/issue/CMP-1971/createDistributable-produces-duplicated-skiko-awt.jar-and-skiko-awt-runtime-windows-x64.jar + +export SOURCE_DATE_EPOCH=1704067200 + +dpkg-deb -R ./release/main/deb/simplex*.deb ./extracted + +rm -f ./extracted/opt/*imple*/lib/app/*skiko-awt-runtime-linux* +sed -i -e '/skiko-awt-runtime-linux/d' ./extracted/opt/*imple*/lib/app/simplex.cfg +find ./extracted/ -exec touch -d "@$SOURCE_DATE_EPOCH" {} + + +dpkg-deb --build --root-owner-group --uniform-compression ./extracted ./release/main/deb/simplex_amd64.deb + +strip-nondeterminism ./release/main/deb/simplex_amd64.deb