Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/desktop-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ jobs:
${{ runner.os }}-sccache-linux-
${{ runner.os }}-sccache-

# Ubuntu 24.04 restricts unprivileged user namespaces by default; linuxdeploy/AppImage
# packaging uses bubblewrap and otherwise fails with "bwrap: setting up uid map: Permission denied".
- name: Allow bubblewrap user namespaces
run: |
set -euo pipefail
if [ -e /proc/sys/kernel/apparmor_restrict_unprivileged_userns ]; then
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
fi
if [ -e /proc/sys/kernel/unprivileged_userns_clone ]; then
sudo sysctl -w kernel.unprivileged_userns_clone=1
fi

- name: Build Tauri App (Linux, signed updater)
run: nix develop .#ci -c ./scripts/ci/desktop-release.sh
env:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/mobile-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ jobs:
ios-release-artifacts.sha256 \
frontend/src-tauri/target/reproducibility/ios-release-final.sha256 \
frontend/src-tauri/target/reproducibility/ios-release-*.sha256 \
frontend/src-tauri/target/reproducibility/ios-release-*.txt \
frontend/src-tauri/target/reproducibility/ios-onnxruntime-*.sha256
cat ios-release-artifacts.sha256

Expand All @@ -99,6 +100,7 @@ jobs:
path: |
frontend/src-tauri/gen/apple/build/arm64/*.ipa
frontend/src-tauri/target/reproducibility/*.sha256
frontend/src-tauri/target/reproducibility/*.txt
retention-days: 5

verify-ios-artifacts:
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,19 @@ jobs:
${{ runner.os }}-sccache-release-
${{ runner.os }}-sccache-

# Ubuntu 24.04 restricts unprivileged user namespaces by default; linuxdeploy/AppImage
# packaging uses bubblewrap and otherwise fails with "bwrap: setting up uid map: Permission denied".
- name: Allow bubblewrap user namespaces
if: matrix.platform == 'ubuntu-latest-8-cores'
run: |
set -euo pipefail
if [ -e /proc/sys/kernel/apparmor_restrict_unprivileged_userns ]; then
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
fi
if [ -e /proc/sys/kernel/unprivileged_userns_clone ]; then
sudo sysctl -w kernel.unprivileged_userns_clone=1
fi

- name: Build Tauri desktop app
run: nix develop .#${{ matrix.nix_shell }} -c ./scripts/ci/desktop-release.sh
env:
Expand Down Expand Up @@ -321,6 +334,7 @@ jobs:
ios-release-artifacts.sha256 \
frontend/src-tauri/target/reproducibility/ios-release-final.sha256 \
frontend/src-tauri/target/reproducibility/ios-release-*.sha256 \
frontend/src-tauri/target/reproducibility/ios-release-*.txt \
frontend/src-tauri/target/reproducibility/ios-onnxruntime-*.sha256
cat ios-release-artifacts.sha256

Expand All @@ -341,6 +355,7 @@ jobs:
done < <(find frontend/src-tauri -type f \( \
-name '*.ipa' -o \
-path '*/reproducibility/ios-release-*.sha256' -o \
-path '*/reproducibility/ios-release-*.txt' -o \
-path '*/reproducibility/ios-onnxruntime-*.sha256' \
\) -print0 | LC_ALL=C sort -z)

Expand Down
40 changes: 37 additions & 3 deletions scripts/ci/ios-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,27 @@ find_ios_release_app() {
done
}

write_ios_canonical_app_file_manifest() {
local app="$1"
local out="$2"

python3 "${REPO_ROOT}/scripts/ci/canonical-ios-app-hash.py" --manifest "${app}" > "${out}"
}

write_ios_canonical_app_manifest_diff() {
local unsigned_manifest="$1"
local signed_manifest="$2"
local out="$3"
local unsigned_by_path signed_by_path

unsigned_by_path="$(mktemp)"
signed_by_path="$(mktemp)"
sed -E 's/^([0-9a-f]{64}) (.*)$/\2 \1/' "${unsigned_manifest}" | LC_ALL=C sort > "${unsigned_by_path}"
sed -E 's/^([0-9a-f]{64}) (.*)$/\2 \1/' "${signed_manifest}" | LC_ALL=C sort > "${signed_by_path}"
comm -3 "${unsigned_by_path}" "${signed_by_path}" > "${out}"
rm -f "${unsigned_by_path}" "${signed_by_path}"
}

remove_ios_release_outputs
build_ios_release --no-sign --archive-only

Expand All @@ -117,6 +138,7 @@ if [ -z "${unsigned_app}" ]; then
fi
unsigned_app_canonical_hash="$(print_canonical_ios_app_hash "${unsigned_app}" "$(repo_relative_path "${unsigned_app}")" | tee "${repro_dir}/ios-release-unsigned-app-canonical.sha256" | awk '{ print $2 }')"
cat "${repro_dir}/ios-release-unsigned-app-canonical.sha256"
write_ios_canonical_app_file_manifest "${unsigned_app}" "${repro_dir}/ios-release-unsigned-app-canonical-files.sha256"

remove_ios_release_outputs
build_ios_release --export-method app-store-connect
Expand All @@ -128,14 +150,26 @@ if [ -z "${signed_app}" ]; then
fi
signed_app_canonical_hash="$(print_canonical_ios_app_hash "${signed_app}" "$(repo_relative_path "${signed_app}")" | tee "${repro_dir}/ios-release-signed-app-canonical.sha256" | awk '{ print $2 }')"
cat "${repro_dir}/ios-release-signed-app-canonical.sha256"
write_ios_canonical_app_file_manifest "${signed_app}" "${repro_dir}/ios-release-signed-app-canonical-files.sha256"
write_ios_canonical_app_manifest_diff \
"${repro_dir}/ios-release-unsigned-app-canonical-files.sha256" \
"${repro_dir}/ios-release-signed-app-canonical-files.sha256" \
"${repro_dir}/ios-release-signed-vs-unsigned-canonical.diff.txt"

if [ "${signed_app_canonical_hash}" != "${unsigned_app_canonical_hash}" ]; then
echo "Signed iOS app does not strip back to the unsigned app tree." >&2
echo "warning-ios-signed-app-canonical-mismatch signed iOS app does not strip back to the unsigned app tree." >&2
echo "unsigned=${unsigned_app_canonical_hash}" >&2
echo "signed_canonical=${signed_app_canonical_hash}" >&2
exit 1
if [ -s "${repro_dir}/ios-release-signed-vs-unsigned-canonical.diff.txt" ]; then
echo "First canonical iOS file manifest differences:" >&2
sed -n '1,80p' "${repro_dir}/ios-release-signed-vs-unsigned-canonical.diff.txt" >&2
fi
if [ "${MAPLE_ENFORCE_IOS_SIGNED_REPRODUCIBILITY:-0}" = "1" ]; then
exit 1
fi
else
printf 'verified-ios-signed-app %s %s\n' "${signed_app_canonical_hash}" "$(repo_relative_path "${signed_app}")"
fi
printf 'verified-ios-signed-app %s %s\n' "${signed_app_canonical_hash}" "$(repo_relative_path "${signed_app}")"

ios_artifacts=()
while IFS= read -r -d '' file; do
Expand Down
17 changes: 14 additions & 3 deletions scripts/ci/verify-release-artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -465,13 +465,24 @@ verify_ios() {

unsigned_digest="$(manifest_single_digest "${unsigned_manifest}")"
signed_digest="$(manifest_single_digest "${signed_manifest}")"
if [ -z "${unsigned_digest}" ] || [ "${unsigned_digest}" != "${signed_digest}" ]; then
echo "iOS signed app canonical proof does not match unsigned proof." >&2
if [ -z "${unsigned_digest}" ] || [ -z "${signed_digest}" ]; then
echo "iOS signed app canonical proof is missing." >&2
echo "unsigned=${unsigned_digest:-missing}" >&2
echo "signed=${signed_digest:-missing}" >&2
return 1
fi
printf 'verified-ios-signed-app-proof %s\n' "${signed_digest}"

if [ "${unsigned_digest}" != "${signed_digest}" ]; then
echo "iOS signed app canonical proof does not match unsigned proof." >&2
echo "unsigned=${unsigned_digest:-missing}" >&2
echo "signed=${signed_digest:-missing}" >&2
if [ "${MAPLE_ENFORCE_IOS_SIGNED_REPRODUCIBILITY:-0}" = "1" ]; then
return 1
fi
printf 'warning-ios-signed-app-proof-mismatch unsigned=%s signed=%s\n' "${unsigned_digest}" "${signed_digest}"
else
printf 'verified-ios-signed-app-proof %s\n' "${signed_digest}"
fi

verify_canonical_apple_manifest "${payload_manifest}" "${signed_digest}"
verify_ios_signatures
Expand Down
Loading