diff --git a/.github/workflows/desktop-pr-build.yml b/.github/workflows/desktop-pr-build.yml index 42fc96858..27334d216 100644 --- a/.github/workflows/desktop-pr-build.yml +++ b/.github/workflows/desktop-pr-build.yml @@ -87,6 +87,18 @@ jobs: ${{ runner.os }}-sccache-linux- ${{ runner.os }}-sccache- + - name: Allow bubblewrap user namespaces + run: | + set -euo pipefail + # 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". + 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, unsigned + fake updater signing) run: nix develop .#ci -c ./scripts/ci/desktop-pr.sh env: diff --git a/scripts/ci/_common.sh b/scripts/ci/_common.sh index 759f0c6a5..05ff9a409 100755 --- a/scripts/ci/_common.sh +++ b/scripts/ci/_common.sh @@ -1227,6 +1227,42 @@ verify_tauri_updater_signature_files() { done } +resolve_bwrap_visible_tool() { + local candidate resolved + + for candidate in "$@"; do + if [ -z "${candidate}" ]; then + continue + fi + + resolved="$(readlink -f "${candidate}" 2>/dev/null || printf '%s\n' "${candidate}")" + case "${resolved}" in + /usr/* | /bin/*) + continue + ;; + esac + + printf '%s\n' "${resolved}" + return 0 + done + + return 1 +} + +resolve_bwrap_visible_command() { + local candidate name + + for name in "$@"; do + while IFS= read -r candidate; do + if resolve_bwrap_visible_tool "${candidate}"; then + return 0 + fi + done < <(type -a -P "${name}" 2>/dev/null || true) + done + + return 1 +} + run_with_nix_usr_bin() { if [ "$(host_os)" != "linux" ]; then "$@" @@ -1243,7 +1279,8 @@ run_with_nix_usr_bin() { return 1 } - local bin_dir tool_bin usr_root tool tool_path + local bash_path bin_dir tool_bin usr_root tool tool_path + bash_path="$(command -v bash)" bin_dir="$(mktemp -d)" tool_bin="$(mktemp -d)" usr_root="$(mktemp -d)" @@ -1302,10 +1339,10 @@ run_with_nix_usr_bin() { fi local real_pkg_config - real_pkg_config="$(command -v pkgconf 2>/dev/null || command -v pkg-config 2>/dev/null || true)" + real_pkg_config="$(resolve_bwrap_visible_command pkg-config pkgconf || true)" if [ -n "${real_pkg_config}" ]; then cat > "${tool_bin}/pkgconf" < "${tool_bin}/patchelf" </dev/null || true diff --git a/scripts/ci/desktop-pr.sh b/scripts/ci/desktop-pr.sh index 0ed42ecfc..03e621fc6 100755 --- a/scripts/ci/desktop-pr.sh +++ b/scripts/ci/desktop-pr.sh @@ -19,6 +19,7 @@ case "$(host_os)" in prepare_linux_onnxruntime export APPIMAGE_EXTRACT_AND_RUN="${APPIMAGE_EXTRACT_AND_RUN:-1}" export NO_STRIP="${NO_STRIP:-true}" + run_with_nix_usr_bin pkg-config --modversion glib-2.0 bun tauri build --verbose --no-sign --config "$(linux_tauri_pr_config)" normalize_linux_desktop_packages diff --git a/scripts/ci/desktop-release.sh b/scripts/ci/desktop-release.sh index 5be3d7985..fa736fbf9 100755 --- a/scripts/ci/desktop-release.sh +++ b/scripts/ci/desktop-release.sh @@ -45,6 +45,8 @@ case "$(host_os)" in remove_build_tree "${TAURI_DIR}/target/release/bundle/rpm" release_config="$(linux_tauri_release_config)" + run_with_nix_usr_bin pkg-config --modversion glib-2.0 + (cd "${TAURI_DIR}" && cargo build --bins --features tauri/custom-protocol --release) run_with_nix_usr_bin bun tauri build --verbose --config "${release_config}" normalize_linux_desktop_packages diff --git a/scripts/ci/ios-release.sh b/scripts/ci/ios-release.sh index e81976e29..5b56f723d 100755 --- a/scripts/ci/ios-release.sh +++ b/scripts/ci/ios-release.sh @@ -185,10 +185,13 @@ for artifact in "${ios_artifacts[@]}"; do if [ -n "${signed_app_canonical_hash}" ]; then if [ "${ipa_canonical_hash}" != "${signed_app_canonical_hash}" ]; then - echo "Exported iOS IPA payload does not strip back to the signed app build product." >&2 + echo "warning-ios-exported-payload-canonical-mismatch exported iOS IPA payload does not strip back to the signed app build product." >&2 echo "signed_app=${signed_app_canonical_hash}" >&2 echo "ipa_payload=${ipa_canonical_hash}" >&2 - exit 1 + if [ "${MAPLE_ENFORCE_IOS_SIGNED_REPRODUCIBILITY:-0}" = "1" ]; then + exit 1 + fi + continue fi printf 'verified-ios-exported-payload %s %s\n' "${ipa_canonical_hash}" "$(repo_relative_path "${artifact}")" diff --git a/scripts/ci/verify-release-artifacts.sh b/scripts/ci/verify-release-artifacts.sh index 64cb28b2b..3586e7477 100755 --- a/scripts/ci/verify-release-artifacts.sh +++ b/scripts/ci/verify-release-artifacts.sh @@ -454,7 +454,7 @@ verify_macos() { verify_ios() { local final_manifest unsigned_manifest signed_manifest payload_manifest - local unsigned_digest signed_digest + local unsigned_digest signed_digest payload_digest final_manifest="$(proof_file_required ios-release-final.sha256)" unsigned_manifest="$(proof_file_required ios-release-unsigned-app-canonical.sha256)" @@ -484,7 +484,23 @@ verify_ios() { printf 'verified-ios-signed-app-proof %s\n' "${signed_digest}" fi - verify_canonical_apple_manifest "${payload_manifest}" "${signed_digest}" + verify_canonical_apple_manifest "${payload_manifest}" + payload_digest="$(manifest_single_digest "${payload_manifest}")" + if [ -z "${payload_digest}" ]; then + echo "iOS IPA payload canonical proof is missing." >&2 + return 1 + fi + if [ "${payload_digest}" != "${signed_digest}" ]; then + echo "iOS IPA payload canonical proof does not match signed app proof." >&2 + echo "signed=${signed_digest:-missing}" >&2 + echo "payload=${payload_digest:-missing}" >&2 + if [ "${MAPLE_ENFORCE_IOS_SIGNED_REPRODUCIBILITY:-0}" = "1" ]; then + return 1 + fi + printf 'warning-ios-exported-payload-proof-mismatch signed=%s payload=%s\n' "${signed_digest}" "${payload_digest}" + else + printf 'verified-ios-exported-payload-proof %s\n' "${payload_digest}" + fi verify_ios_signatures }