Skip to content

Use flake for PR build workflows#533

Merged
AnthonyRonning merged 1 commit into
masterfrom
codex/reproducible-flake-builds
May 23, 2026
Merged

Use flake for PR build workflows#533
AnthonyRonning merged 1 commit into
masterfrom
codex/reproducible-flake-builds

Conversation

@AnthonyRonning
Copy link
Copy Markdown
Contributor

@AnthonyRonning AnthonyRonning commented May 22, 2026

Summary

  • expands the Nix flake into pinned CI/dev shells for frontend, Rust, desktop, iOS, and Android PR builds
  • moves PR workflow logic into scripts/ci entrypoints run through nix develop
  • pins and verifies Linux ONNX Runtime downloads, Xcode selection, iOS simulator runtime requirements, Android SDK/NDK versions, and GitHub Actions SHAs

Local verification

  • nix flake check --print-build-logs
  • nix flake check --all-systems --no-build
  • nix develop .#ci -c ./scripts/ci/frontend.sh
  • nix develop .#ci -c ./scripts/ci/rust.sh
  • nix develop .#ci -c ./scripts/ci/desktop-pr.sh
  • mac zsh -lc 'cd /Users/tony/Dev/OpenSecret/maple && nix develop .#ci -c ./scripts/ci/desktop-pr.sh'
  • mac zsh -lc 'cd /Users/tony/Dev/OpenSecret/maple && nix develop .#apple -c ./scripts/ci/ios-pr.sh'

Android is flake-evaluated and guarded locally; the full Android PR build requires x86_64-linux because Google Linux NDK tools in this SDK package are x86_64-only.


Open in Devin Review

Summary by CodeRabbit

  • Chores

    • CI consolidated onto a Nix-driven pipeline with centralized dev shells and standardized entrypoint scripts for desktop, mobile, Android, iOS, frontend, and Rust; macOS Xcode target updated to 26.5.
    • Added shared CI utilities for deterministic builds, artifact hashing, and sccache reporting; APK upload preserved; Desktop artifact uploads now only .deb/.rpm.
  • Bug Fixes / Improvements

    • Improved cross‑platform ONNX Runtime handling (including Linux aarch64) with architecture-aware provisioning, pinned hashes, manifest verification, and reproducible outputs.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR migrates CI workflows to Nix-driven dev shells, expands flake.nix to provide multi-environment devShells/checks/apps, adds a shared Bash CI helper library, implements platform-specific CI entrypoint scripts (android/desktop/ios/frontend/rust), and standardizes ONNX runtime provisioning and deterministic artifact hashing.

Changes

Nix-Based CI Infrastructure and Script Modernization

Layer / File(s) Summary
Flake multi-environment infrastructure
flake.nix
flake.nix now centralizes toolchain/version constants, a rustup shim, conditional Rust targets, grouped package sets, host-aware shell hooks, checks outputs, and apps that wrap CI scripts via nix develop (adds devShells.ci, conditional devShells.android/devShells.apple, and CI apps).
GitHub Actions workflow updates
.github/workflows/*.yml
All PR workflows (Android, Desktop, Mobile/iOS, Frontend tests, Rust tests) now install Nix and invoke nix-driven CI scripts (e.g., nix develop .#ci -c ./scripts/ci/*); many prior explicit tool-install and build steps removed; sccache stats run via Nix with if: always().
Shared CI utilities library
scripts/ci/_common.sh
New shared Bash CI helpers: frontend dep installer, configure_sccache(), PR env defaults, reproducible-build metadata, Xcode developer/toolchain utilities, iOS simulator validator, Linux ONNX provisioning helpers, deterministic file/tree hashing, iOS xcframework manifest handling, and Tauri PR bundling JSON generator.
ONNX Runtime multi-architecture support
frontend/src-tauri/scripts/onnxruntime-pins.sh, frontend/src-tauri/scripts/provide-linux-onnxruntime.sh
Added architecture-specific SHA256 pin helpers for Linux aarch64 and updated provider to select ORT_ARCH by uname -m, wiring archive/dylib names, URLs, and expected SHA256 values.
iOS ONNX Runtime build and caching
frontend/src-tauri/scripts/build-ios-onnxruntime-all.sh, scripts/ci/ios-onnxruntime.sh
CMake extra defines converted to arrays; header discovery hardened; ios-onnxruntime.sh implements cached fast-path, rebuild-on-mismatch, builds 1.22.2, writes/verifies a sorted .sha256 manifest, and prints artifact hashes.
iOS Cargo config and simulator setup
frontend/src-tauri/scripts/setup-ios-cargo-config.sh, scripts/ci/ios-pr.sh
Generated iOS Cargo config now links c++; ios-pr.sh enforces macOS, selects Xcode toolchain, validates/install simulator runtime (optional), snapshots/restores generated iOS build state, verifies ONNX Runtime manifest, configures env, and runs Tauri iOS simulator debug build, then prints deterministic hashes.
Android CI entrypoint
scripts/ci/android-pr.sh
android-pr.sh enforces Linux x86_64, discovers NDK/LLVM prebuilt, creates llvm-ranlib symlinks, exports per-target AR/CC/CXX/RANLIB and default Rust linker flags, generates gen/android/app/tauri.properties, runs bun tauri android build --debug --apk, and prints deterministic artifact hashes.
Desktop CI entrypoint
scripts/ci/desktop-pr.sh
desktop-pr.sh sources helpers and dispatches by host OS: Linux prepares ONNX Runtime and builds deb/rpm bundles; macOS selects Xcode toolchain, configures SDK/sysroot and RUSTFLAGS, and runs universal Tauri build with signing/updater disabled; artifacts and tree hashes are printed.
Frontend and Rust CI scripts
scripts/ci/frontend.sh, scripts/ci/rust.sh
frontend.sh installs frontend deps and runs Bun format/lint/typecheck/tests; rust.sh configures sccache, prepares Linux ONNX Runtime, and runs cargo test --all-targets in the Tauri workspace.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • OpenSecretCloud/Maple#525: Both PRs touch ONNX Runtime pinning/provisioning scripts and related download/verification logic.
  • OpenSecretCloud/Maple#490: Related Linux ONNX provisioning and ORT_SKIP_DOWNLOAD/ORT_LIB_LOCATION env wiring used by CI.
  • OpenSecretCloud/Maple#526: Overlapping workflow refactor affecting sccache and PR build workflow steps consolidated here under Nix-driven scripts.

Poem

🐰 In a nixy burrow I tidy shells and pins,

Scripts hop together, neat as violin strings.
Builds now march from one gentle command,
Artifacts hashed and bundled by my pawed hand.
CI hums softly — hop, test, ship, and grin.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Use flake for PR build workflows' directly and clearly summarizes the main change: converting PR build workflows to use Nix flakes and associated CI scripts.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/reproducible-flake-builds

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 22, 2026

Deploying maple with  Cloudflare Pages  Cloudflare Pages

Latest commit: a002114
Status: ✅  Deploy successful!
Preview URL: https://3f87441d.maple-ca8.pages.dev
Branch Preview URL: https://codex-reproducible-flake-bui.maple-ca8.pages.dev

View logs

@AnthonyRonning AnthonyRonning force-pushed the codex/reproducible-flake-builds branch from f4bca39 to 343abb1 Compare May 22, 2026 03:16
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/ci/ios-pr.sh`:
- Around line 43-47: The script copies iOS files into a temp dir without
checking for their existence which can fail before the trap is installed; set up
ios_project_state_dir and install the trap (trap restore_ios_build_state EXIT)
before attempting any copies, and guard each cp of
"${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" and
"${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" with existence checks
(e.g. [ -f ... ] or similar) so the script continues gracefully when those files
are absent, optionally emitting a warning when a file is missing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 13b9d476-beee-4574-a178-6e394a447bc3

📥 Commits

Reviewing files that changed from the base of the PR and between 6c7fb8f and f4bca39.

📒 Files selected for processing (15)
  • .github/workflows/android-pr-build.yml
  • .github/workflows/desktop-pr-build.yml
  • .github/workflows/frontend-tests.yml
  • .github/workflows/mobile-pr-build.yml
  • .github/workflows/rust-tests.yml
  • flake.nix
  • frontend/src-tauri/scripts/onnxruntime-pins.sh
  • frontend/src-tauri/scripts/provide-linux-onnxruntime.sh
  • frontend/src-tauri/scripts/setup-ios-cargo-config.sh
  • scripts/ci/_common.sh
  • scripts/ci/android-pr.sh
  • scripts/ci/desktop-pr.sh
  • scripts/ci/frontend.sh
  • scripts/ci/ios-pr.sh
  • scripts/ci/rust.sh

Comment thread scripts/ci/ios-pr.sh
Comment on lines +43 to +47
cd "${TAURI_DIR}"
ios_project_state_dir="$(mktemp -d)"
cp "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" "${ios_project_state_dir}/Info.plist"
cp "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" "${ios_project_state_dir}/maple_iOS.entitlements"
trap restore_ios_build_state EXIT
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

State preservation may fail if iOS project files don't exist.

Lines 45-46 copy files without checking if they exist first. On a fresh checkout where bun tauri ios init hasn't been run yet, these files may not exist and the script will fail before the trap is set.

Consider adding existence checks or letting these operations fail gracefully:

Proposed fix
 cd "${TAURI_DIR}"
 ios_project_state_dir="$(mktemp -d)"
-cp "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" "${ios_project_state_dir}/Info.plist"
-cp "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" "${ios_project_state_dir}/maple_iOS.entitlements"
+if [ -f "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" ]; then
+  cp "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" "${ios_project_state_dir}/Info.plist"
+fi
+if [ -f "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" ]; then
+  cp "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" "${ios_project_state_dir}/maple_iOS.entitlements"
+fi
 trap restore_ios_build_state EXIT
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cd "${TAURI_DIR}"
ios_project_state_dir="$(mktemp -d)"
cp "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" "${ios_project_state_dir}/Info.plist"
cp "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" "${ios_project_state_dir}/maple_iOS.entitlements"
trap restore_ios_build_state EXIT
cd "${TAURI_DIR}"
ios_project_state_dir="$(mktemp -d)"
if [ -f "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" ]; then
cp "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" "${ios_project_state_dir}/Info.plist"
fi
if [ -f "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" ]; then
cp "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" "${ios_project_state_dir}/maple_iOS.entitlements"
fi
trap restore_ios_build_state EXIT
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/ios-pr.sh` around lines 43 - 47, The script copies iOS files into
a temp dir without checking for their existence which can fail before the trap
is installed; set up ios_project_state_dir and install the trap (trap
restore_ios_build_state EXIT) before attempting any copies, and guard each cp of
"${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" and
"${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" with existence checks
(e.g. [ -f ... ] or similar) so the script continues gracefully when those files
are absent, optionally emitting a warning when a file is missing.

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
scripts/ci/ios-pr.sh (1)

44-47: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Install the EXIT trap before copying state files, and guard missing files.

Line 45 and Line 46 can fail before trap restore_ios_build_state EXIT is active, which skips cleanup/setup recovery on missing generated iOS files.

Suggested patch
 cd "${TAURI_DIR}"
 ios_project_state_dir="$(mktemp -d)"
-cp "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" "${ios_project_state_dir}/Info.plist"
-cp "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" "${ios_project_state_dir}/maple_iOS.entitlements"
 trap restore_ios_build_state EXIT
+if [ -f "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" ]; then
+  cp "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" "${ios_project_state_dir}/Info.plist"
+fi
+if [ -f "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" ]; then
+  cp "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" "${ios_project_state_dir}/maple_iOS.entitlements"
+fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/ios-pr.sh` around lines 44 - 47, Install the EXIT trap before
performing any file operations so restore_ios_build_state will run on early
failures; move the trap restore_ios_build_state EXIT line above the cp commands
that copy into ios_project_state_dir and add existence checks for
"${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" and
"${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" (or bail with an
error) to guard against missing generated iOS files before copying into
ios_project_state_dir.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/ci/android-pr.sh`:
- Around line 43-44: Add a guard after computing toolchain_prebuilt to fail fast
when no prebuilt directory was found: check if the variable toolchain_prebuilt
is empty or unset, and if so print a clear error to stderr (e.g., printf 'Error:
no prebuilt toolchain found in %s\n' "$NDK_HOME/toolchains/llvm/prebuilt" >&2)
and exit with a non‑zero status; otherwise continue to export PATH as before.
Ensure you reference the existing toolchain_prebuilt variable in the check so
the invalid PATH is never exported.

---

Duplicate comments:
In `@scripts/ci/ios-pr.sh`:
- Around line 44-47: Install the EXIT trap before performing any file operations
so restore_ios_build_state will run on early failures; move the trap
restore_ios_build_state EXIT line above the cp commands that copy into
ios_project_state_dir and add existence checks for
"${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" and
"${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" (or bail with an
error) to guard against missing generated iOS files before copying into
ios_project_state_dir.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 04a4cefe-9ce3-4ba8-87fc-49dfcfbc911e

📥 Commits

Reviewing files that changed from the base of the PR and between f4bca39 and 343abb1.

📒 Files selected for processing (15)
  • .github/workflows/android-pr-build.yml
  • .github/workflows/desktop-pr-build.yml
  • .github/workflows/frontend-tests.yml
  • .github/workflows/mobile-pr-build.yml
  • .github/workflows/rust-tests.yml
  • flake.nix
  • frontend/src-tauri/scripts/onnxruntime-pins.sh
  • frontend/src-tauri/scripts/provide-linux-onnxruntime.sh
  • frontend/src-tauri/scripts/setup-ios-cargo-config.sh
  • scripts/ci/_common.sh
  • scripts/ci/android-pr.sh
  • scripts/ci/desktop-pr.sh
  • scripts/ci/frontend.sh
  • scripts/ci/ios-pr.sh
  • scripts/ci/rust.sh

Comment thread scripts/ci/android-pr.sh
Comment on lines +43 to +44
toolchain_prebuilt="$(find "${NDK_HOME}/toolchains/llvm/prebuilt" -mindepth 1 -maxdepth 1 -type d | sort | head -n 1)"
export PATH="${toolchain_prebuilt}/bin:${PATH}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add an explicit guard for empty toolchain_prebuilt.

If find returns no child prebuilt directory, Line 44 exports an invalid toolchain path and failures happen later with poor diagnostics. Fail fast here.

Suggested patch
-toolchain_prebuilt="$(find "${NDK_HOME}/toolchains/llvm/prebuilt" -mindepth 1 -maxdepth 1 -type d | sort | head -n 1)"
+toolchain_prebuilt="$(find "${NDK_HOME}/toolchains/llvm/prebuilt" -mindepth 1 -maxdepth 1 -type d | sort | head -n 1 || true)"
+if [ -z "${toolchain_prebuilt}" ] || [ ! -d "${toolchain_prebuilt}/bin" ]; then
+  echo "Could not resolve an NDK LLVM prebuilt toolchain under ${NDK_HOME}/toolchains/llvm/prebuilt" >&2
+  exit 1
+fi
 export PATH="${toolchain_prebuilt}/bin:${PATH}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
toolchain_prebuilt="$(find "${NDK_HOME}/toolchains/llvm/prebuilt" -mindepth 1 -maxdepth 1 -type d | sort | head -n 1)"
export PATH="${toolchain_prebuilt}/bin:${PATH}"
toolchain_prebuilt="$(find "${NDK_HOME}/toolchains/llvm/prebuilt" -mindepth 1 -maxdepth 1 -type d | sort | head -n 1 || true)"
if [ -z "${toolchain_prebuilt}" ] || [ ! -d "${toolchain_prebuilt}/bin" ]; then
echo "Could not resolve an NDK LLVM prebuilt toolchain under ${NDK_HOME}/toolchains/llvm/prebuilt" >&2
exit 1
fi
export PATH="${toolchain_prebuilt}/bin:${PATH}"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/android-pr.sh` around lines 43 - 44, Add a guard after computing
toolchain_prebuilt to fail fast when no prebuilt directory was found: check if
the variable toolchain_prebuilt is empty or unset, and if so print a clear error
to stderr (e.g., printf 'Error: no prebuilt toolchain found in %s\n'
"$NDK_HOME/toolchains/llvm/prebuilt" >&2) and exit with a non‑zero status;
otherwise continue to export PATH as before. Ensure you reference the existing
toolchain_prebuilt variable in the check so the invalid PATH is never exported.

@AnthonyRonning AnthonyRonning force-pushed the codex/reproducible-flake-builds branch from 343abb1 to 0439a4a Compare May 22, 2026 03:43
coderabbitai[bot]

This comment was marked as resolved.

@AnthonyRonning AnthonyRonning force-pushed the codex/reproducible-flake-builds branch 2 times, most recently from 1491d0a to d94bc93 Compare May 22, 2026 05:35
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
scripts/ci/ios-pr.sh (1)

45-48: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Install the restore trap before snapshot copies and guard missing files.

The snapshot cp commands can fail before the EXIT trap is registered. That makes this entrypoint brittle on fresh or partially initialized iOS project state.

Proposed fix
 cd "${TAURI_DIR}"
 ios_project_state_dir="$(mktemp -d)"
-cp "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" "${ios_project_state_dir}/Info.plist"
-cp "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" "${ios_project_state_dir}/maple_iOS.entitlements"
 trap restore_ios_build_state EXIT
+if [ -f "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" ]; then
+  cp "${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" "${ios_project_state_dir}/Info.plist"
+fi
+if [ -f "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" ]; then
+  cp "${TAURI_DIR}/gen/apple/maple_iOS/maple_iOS.entitlements" "${ios_project_state_dir}/maple_iOS.entitlements"
+fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/ios-pr.sh` around lines 45 - 48, The EXIT trap is registered too
late (after the cp calls) and the cp commands assume files exist; move the trap
call (restore_ios_build_state) to immediately after ios_project_state_dir is
created so cleanup is guaranteed, and guard each copy of
"${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" and ".../maple_iOS.entitlements"
by testing file existence (e.g., [ -f ... ]) before running cp, logging or
skipping if missing to avoid hard failures; reference ios_project_state_dir,
restore_ios_build_state, and the two cp lines to locate the changes.
🧹 Nitpick comments (2)
flake.nix (1)

126-139: 💤 Low value

Potential argument parsing issue in target add when using --toolchain flag.

When --toolchain or -t is encountered, shift 2 is used, but if the toolchain value is missing (e.g., --toolchain is the last argument), this will cause an error or skip the next positional argument incorrectly.

🛡️ Safer argument parsing
                      --toolchain | -t)
-                       shift 2
+                       shift
+                       [ "$#" -gt 0 ] && shift
                        ;;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@flake.nix` around lines 126 - 139, The argument parsing loop that handles the
--toolchain/-t case (inside the while ... case block that appends to
requested_targets) currently does an unconditional shift 2 which misbehaves if
--toolchain is the last argument; update the --toolchain|-t branch to validate
that a following value exists before shifting twice (e.g., check that "$#" -gt
1), and if missing emit an error or handle the missing toolchain value safely;
ensure the rest of the case branches and the requested_targets array behavior
remain unchanged.
.github/workflows/desktop-pr-build.yml (1)

18-35: 💤 Low value

Xcode selection logic is duplicated across workflows.

The same Xcode 26.5 selection logic appears in both desktop-pr-build.yml and mobile-pr-build.yml. Consider extracting this into a reusable composite action or a shared script to reduce duplication and ensure consistency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/desktop-pr-build.yml around lines 18 - 35, Extract the
duplicated "Select Xcode 26.5" step logic into a single reusable unit and update
both workflows to call it: create a composite GitHub Action (e.g.,
.github/actions/select-xcode-26-5 with an action.yml) or a shared script (e.g.,
scripts/select_xcode_26_5.sh) that contains the for-loop/xcode-select/xcodebuild
logic currently under the step named "Select Xcode 26.5", then replace the
inline step in desktop-pr-build.yml and mobile-pr-build.yml with a uses:
reference to the new action or a run: invoking the shared script so both
workflows reuse the exact same selection logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/ci/rust.sh`:
- Line 10: The CI Rust test invocation runs cargo test --all-targets without
enforcing the lockfile, allowing Cargo to update Cargo.lock during CI; update
the test command in scripts/ci/rust.sh to run cargo test --all-targets --locked
(i.e., add the --locked flag) so dependency resolution uses the checked-in
Cargo.lock and fails the job if the lockfile would change.

---

Duplicate comments:
In `@scripts/ci/ios-pr.sh`:
- Around line 45-48: The EXIT trap is registered too late (after the cp calls)
and the cp commands assume files exist; move the trap call
(restore_ios_build_state) to immediately after ios_project_state_dir is created
so cleanup is guaranteed, and guard each copy of
"${TAURI_DIR}/gen/apple/maple_iOS/Info.plist" and ".../maple_iOS.entitlements"
by testing file existence (e.g., [ -f ... ]) before running cp, logging or
skipping if missing to avoid hard failures; reference ios_project_state_dir,
restore_ios_build_state, and the two cp lines to locate the changes.

---

Nitpick comments:
In @.github/workflows/desktop-pr-build.yml:
- Around line 18-35: Extract the duplicated "Select Xcode 26.5" step logic into
a single reusable unit and update both workflows to call it: create a composite
GitHub Action (e.g., .github/actions/select-xcode-26-5 with an action.yml) or a
shared script (e.g., scripts/select_xcode_26_5.sh) that contains the
for-loop/xcode-select/xcodebuild logic currently under the step named "Select
Xcode 26.5", then replace the inline step in desktop-pr-build.yml and
mobile-pr-build.yml with a uses: reference to the new action or a run: invoking
the shared script so both workflows reuse the exact same selection logic.

In `@flake.nix`:
- Around line 126-139: The argument parsing loop that handles the --toolchain/-t
case (inside the while ... case block that appends to requested_targets)
currently does an unconditional shift 2 which misbehaves if --toolchain is the
last argument; update the --toolchain|-t branch to validate that a following
value exists before shifting twice (e.g., check that "$#" -gt 1), and if missing
emit an error or handle the missing toolchain value safely; ensure the rest of
the case branches and the requested_targets array behavior remain unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 37977db8-aee3-40bf-b0c3-861923cf4fac

📥 Commits

Reviewing files that changed from the base of the PR and between 1491d0a and d94bc93.

📒 Files selected for processing (17)
  • .github/workflows/android-pr-build.yml
  • .github/workflows/desktop-pr-build.yml
  • .github/workflows/frontend-tests.yml
  • .github/workflows/mobile-pr-build.yml
  • .github/workflows/rust-tests.yml
  • flake.nix
  • frontend/src-tauri/scripts/build-ios-onnxruntime-all.sh
  • frontend/src-tauri/scripts/onnxruntime-pins.sh
  • frontend/src-tauri/scripts/provide-linux-onnxruntime.sh
  • frontend/src-tauri/scripts/setup-ios-cargo-config.sh
  • scripts/ci/_common.sh
  • scripts/ci/android-pr.sh
  • scripts/ci/desktop-pr.sh
  • scripts/ci/frontend.sh
  • scripts/ci/ios-onnxruntime.sh
  • scripts/ci/ios-pr.sh
  • scripts/ci/rust.sh
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/rust-tests.yml

Comment thread scripts/ci/rust.sh
prepare_linux_onnxruntime

cd "${TAURI_DIR}"
cargo test --all-targets
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "Cargo test invocations under CI scripts:"
rg -n --type=sh '\bcargo\s+test\b' scripts/ci

echo
echo "Cargo.lock files present in repository:"
fd -HI '^Cargo.lock$'

Repository: OpenSecretCloud/Maple

Length of output: 273


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "---- scripts/ci/rust.sh (with line numbers) ----"
nl -ba scripts/ci/rust.sh | sed -n '1,120p'

echo
echo "---- Other 'cargo test' invocations under scripts/ci ----"
rg -n --type=sh '\bcargo\s+test\b' scripts/ci

echo
echo "---- Cargo.lock locations ----"
fd -HI '^Cargo.lock$'

Repository: OpenSecretCloud/Maple

Length of output: 175


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "---- scripts/ci/rust.sh (cat -n) ----"
cat -n scripts/ci/rust.sh | sed -n '1,120p'

echo
echo "---- Other 'cargo test' invocations under scripts/ci ----"
rg -n --type=sh '\bcargo\s+test\b' scripts/ci

echo
echo "---- Cargo.lock locations ----"
fd -HI '^Cargo.lock$'

Repository: OpenSecretCloud/Maple

Length of output: 584


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "---- Find TAURI_DIR definition ----"
rg -n --hidden '^\s*(export\s+)?TAURI_DIR=' scripts/ci -S || true
rg -n --hidden 'TAURI_DIR' scripts/ci/_common.sh scripts/ci -S || true

echo
echo "---- Show scripts/ci/_common.sh (first 200 lines) ----"
sed -n '1,200p' scripts/ci/_common.sh

Repository: OpenSecretCloud/Maple

Length of output: 10108


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "---- Search for --locked usage in scripts/ci ----"
rg -n --hidden '\bcargo\s+test\b.*--locked\b|--locked\b' scripts/ci || true

echo
echo "---- Inspect .cargo config generation/usage in scripts/ci/_common.sh ----"
sed -n '380,520p' scripts/ci/_common.sh

echo
echo "---- Show actual frontend/src-tauri/.cargo/config.toml if present ----"
if [ -f "frontend/src-tauri/.cargo/config.toml" ]; then
  sed -n '1,200p' frontend/src-tauri/.cargo/config.toml
else
  echo "frontend/src-tauri/.cargo/config.toml not found"
fi

Repository: OpenSecretCloud/Maple

Length of output: 2386


Enforce lockfile usage in CI Rust tests

scripts/ci/rust.sh runs cargo test --all-targets from frontend/src-tauri (which contains Cargo.lock), but without --locked Cargo can update the lockfile during CI. Add --locked to keep dependency resolution reproducible.

Proposed fix
-cargo test --all-targets
+cargo test --all-targets --locked
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cargo test --all-targets
cargo test --all-targets --locked
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/rust.sh` at line 10, The CI Rust test invocation runs cargo test
--all-targets without enforcing the lockfile, allowing Cargo to update
Cargo.lock during CI; update the test command in scripts/ci/rust.sh to run cargo
test --all-targets --locked (i.e., add the --locked flag) so dependency
resolution uses the checked-in Cargo.lock and fails the job if the lockfile
would change.

@AnthonyRonning AnthonyRonning force-pushed the codex/reproducible-flake-builds branch 4 times, most recently from 180ebcb to 03cf21f Compare May 22, 2026 10:28
devin-ai-integration[bot]

This comment was marked as resolved.

@AnthonyRonning AnthonyRonning force-pushed the codex/reproducible-flake-builds branch 9 times, most recently from fd25dde to d31f784 Compare May 22, 2026 16:55
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 27 additional findings in Devin Review.

Open in Devin Review

Comment thread scripts/ci/latest-json.sh
exit 1
fi

configure_reproducible_build_metadata
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot May 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 pub_date in latest.json hardcoded to 1980-01-01 due to reproducible build epoch

The source_date_rfc3339() function at scripts/ci/_common.sh:251 formats SOURCE_DATE_EPOCH into an RFC 3339 date. configure_reproducible_build_metadata() at scripts/ci/_common.sh:124-126 defaults SOURCE_DATE_EPOCH to 315532800 (1980-01-01T00:00:00Z) when unset. The update-latest-json job in release.yml:419-422 does not set SOURCE_DATE_EPOCH externally, so latest-json.sh:52 calls source_date_rfc3339() which produces 1980-01-01T00:00:00Z. Every release's latest.json auto-updater manifest will report pub_date: "1980-01-01T00:00:00Z" instead of the actual release date. The old workflow used date -u +"%Y-%m-%dT%H:%M:%SZ" to get the real current time.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@AnthonyRonning AnthonyRonning force-pushed the codex/reproducible-flake-builds branch 4 times, most recently from 4f1d8c5 to 12f5d8b Compare May 22, 2026 18:36
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 30 additional findings in Devin Review.

Open in Devin Review

Comment thread scripts/ci/_common.sh
Comment on lines +354 to +355
export CARGO_TARGET_AARCH64_APPLE_DARWIN_RUSTFLAGS="${CARGO_TARGET_AARCH64_APPLE_DARWIN_RUSTFLAGS:+${CARGO_TARGET_AARCH64_APPLE_DARWIN_RUSTFLAGS} }${macos_link_flags}"
export CARGO_TARGET_X86_64_APPLE_DARWIN_RUSTFLAGS="${CARGO_TARGET_X86_64_APPLE_DARWIN_RUSTFLAGS:+${CARGO_TARGET_X86_64_APPLE_DARWIN_RUSTFLAGS} }${macos_link_flags}"
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot May 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 CARGO_TARGET_*_APPLE_DARWIN_RUSTFLAGS overrides RUSTFLAGS, losing --remap-path-prefix reproducibility flags on macOS

In use_xcode_toolchain() (line 354-355), CARGO_TARGET_AARCH64_APPLE_DARWIN_RUSTFLAGS and CARGO_TARGET_X86_64_APPLE_DARWIN_RUSTFLAGS are set with only the -C link-arg=-isysroot linker flags. Per Cargo's documented flag resolution, per-target rustflags (target.<triple>.rustflags) take precedence over global build.rustflags/RUSTFLAGS. Since configure_reproducible_rust_paths() (scripts/ci/_common.sh:189-198) sets --remap-path-prefix flags only in RUSTFLAGS (via append_rustflag_once), these remap flags are effectively ignored for macOS darwin targets when Cargo resolves flags. This means host-specific absolute paths (repo root, cargo home, rustup home) remain embedded in the compiled macOS binaries, undermining the cross-machine reproducibility that the rest of the infrastructure carefully establishes. The same-machine unsigned-vs-signed comparison still passes because both builds use the same environment, so the bug is silent in CI.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@AnthonyRonning AnthonyRonning force-pushed the codex/reproducible-flake-builds branch 2 times, most recently from a9bfd51 to 8919240 Compare May 22, 2026 19:56
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 34 additional findings in Devin Review.

Open in Devin Review

EOF
nix develop .#ci -c ./scripts/ci/attestation-manifest.sh \
latest-json-artifacts.sha256 \
frontend/src-tauri/target/reproducibility/latest-json-final.sha256 \
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot May 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Duplicate file passed to attestation-manifest.sh for latest-json step

The same file frontend/src-tauri/target/reproducibility/latest-json-final.sha256 is passed as both the second argument (final manifest, whose contents are copied to the output) and the third argument (proof file, whose own hash is appended to the output). This causes the attestation manifest to contain the entries from the final manifest plus a redundant self-referential hash entry. All other invocations of attestation-manifest.sh in the PR use distinct glob patterns for the proof files (e.g., android-release-*.sha256), suggesting this is a copy-paste error where the third argument should either be omitted or use a different pattern.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@AnthonyRonning AnthonyRonning force-pushed the codex/reproducible-flake-builds branch 12 times, most recently from b6fec23 to a1c3260 Compare May 23, 2026 03:26
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 39 additional findings in Devin Review.

Open in Devin Review

Comment thread scripts/ci/_common.sh
}

source_date_rfc3339() {
date -u -d "@${SOURCE_DATE_EPOCH:?SOURCE_DATE_EPOCH is required}" +"%Y-%m-%dT%H:%M:%SZ"
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot May 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 source_date_rfc3339() uses GNU-only date -d flag, fails on macOS

source_date_rfc3339() at scripts/ci/_common.sh:251 uses date -u -d "@${SOURCE_DATE_EPOCH}" which is GNU coreutils syntax. On macOS (BSD date), -d means DST adjustment, not date-string parsing. The macOS equivalent is date -u -r "${SOURCE_DATE_EPOCH}". While this function is currently only called from latest-json.sh which runs on Linux in CI (release.yml runs update-latest-json on ubuntu-latest), it is defined in _common.sh and the script is exposed as a flake app (ci-latest-json in flake.nix:473) on all platforms including macOS, making local development/testing broken on macOS.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@AnthonyRonning AnthonyRonning force-pushed the codex/reproducible-flake-builds branch 8 times, most recently from f0173d9 to 5837978 Compare May 23, 2026 07:53
@AnthonyRonning AnthonyRonning force-pushed the codex/reproducible-flake-builds branch from 5837978 to a002114 Compare May 23, 2026 08:46
@AnthonyRonning AnthonyRonning merged commit 2874512 into master May 23, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant