Skip to content

Conversation

@bongiozzo
Copy link

@bongiozzo bongiozzo commented Jan 14, 2026

PR adds brief instructions to run immichframe on linux arm64 platforms in README.md and provides improvements to the build and release process, especially for Linux ARM64, and updates dependencies and documentation for better clarity and support. The changes include a new workflow for ARM64 builds via a self-hosted runner, enhanced workflow flexibility, dependency updates, and improved Linux autostart instructions.

Build and Release Workflow Improvements:

  • Added a new publish-tauri-linux-arm64 job to .github/workflows/build-and-push.yml for building and releasing Linux ARM64 .deb packages using a self-hosted runner, including setup steps and release upload.
  • Enhanced the main workflow to support manual dispatch with selectable build targets (hosted, arm64, all) and a tag input, improving flexibility for different release scenarios.
  • Refactored the build matrix and job conditions to better separate platform builds and avoid running hosted ARM64 builds when not supported, using a more descriptive matrix and runs-on logic.

Dependency and Version Management:

  • Updated package.json, src-tauri/Cargo.toml, and src-tauri/tauri.conf.json to version 1.0.23 and bumped dependencies to specific versions for improved reproducibility and compatibility. [1] [2] [3] [4]
  • Changed the version bumping process in the workflow to use jq for updating package.json, ensuring consistency with extracted version information.

Linux and ARM64 Support Enhancements:

  • Added comprehensive instructions in README.md for setting up autostart on Linux and for building ARM64 .deb packages using a self-hosted runner, including troubleshooting tips for low-memory boards.

Workflow Tooling and Reliability:

  • Switched to using Yarn via Corepack and locked frontend dependencies with yarn install --frozen-lockfile for more reliable and reproducible builds. [1] [2]
  • Added verification steps for Yarn and Tauri CLI in the workflow to ensure the correct tools are available before building. [1] [2]

Summary by CodeRabbit

  • New Features

    • Persistent URL save/load so the app remembers the last URL.
    • Debug overlay showing Linux memory/resource stats.
    • Optional watchdog: auto-reload and auto-restart timers.
    • Multi-platform release builds (macOS, Linux, Windows) and ARM64 self-hosted builds; DEB artifact publishing.
  • Documentation

    • Linux autostart guide and ARM64 build/run notes.
  • Chores

    • Version bumped to 1.0.3 and updated Tauri/frontend tooling.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings January 14, 2026 13:51
@coderabbitai
Copy link

coderabbitai bot commented Jan 14, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Updated project version to 1.0.3, upgraded Tauri and frontend deps, extended GitHub Actions to multi-target builds including a new self-hosted ARM64 job, added persistent URL I/O and Linux resource monitoring Tauri commands, simplified main startup to use the library runtime, and added Linux autostart and ARM64 self-hosted runner docs.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow
.\.github/workflows/build-and-push.yml
Added workflow_dispatch inputs (tag, build); switched package bump to jq edits; introduced Yarn/Corepack setup and Tauri CLI verification; converted publish pipeline to a multi-target matrix (macOS arm64/x64, Linux x64, Windows) and added a dedicated self-hosted publish-tauri-linux-arm64 job; added macOS Rust targets and adjusted Linux dependency handling; release/tag logic now prefers inputs.tag.
Manifests / Versions
package.json, src-tauri/Cargo.toml, src-tauri/tauri.conf.json
Bumped version to 1.0.3; updated frontend and Tauri dependencies: @tauri-apps/cli ~2.9.6, @tauri-apps/api ~2.9.1, tauri-build ~2.5.3, tauri ~2.9.5.
Tauri runtime / Commands
src-tauri/src/lib.rs
Added persistent settings directory handling and file I/O for Settings.txt; new Tauri commands: save_url_to_file, read_url_from_file, exit_app, restart_app, read_immichframe_env, and get_linux_resource_stats; implemented Linux-specific resource monitoring parsers and LinuxResourceStats struct; registered new commands in the app invoke handler.
Tauri main / Startup
src-tauri/src/main.rs
Removed Tauri command handlers and tauri::Builder-based initialization; replaced app bootstrap with a direct call to immichframe_lib::run() (delegates runtime to library).
Frontend runtime / Debug & Watchdog
src/main.js
Added persistent currentUrl state and load/save handling; utility helpers; debug overlay showing Linux resource stats; optional watchdog features (debug overlay, auto-reload, auto-restart) driven by env; synchronized URL handling when saving/reloading.
Documentation
README.md
Added "Autostart (Linux)" instructions (example ~/.config/autostart/immich.desktop and settings path); added "ARM64 (aarch64) builds via self-hosted runner" section with runner labels, manual workflow usage, swap/zram note, and build steps; added docs link.

Sequence Diagram(s)

sequenceDiagram
  participant Frontend
  participant TauriCmd as Tauri (Rust)
  participant FS as Filesystem
  participant OS as Linux / Proc

  Frontend->>TauriCmd: invoke save_url_to_file(url)
  TauriCmd->>FS: ensure settings dir & write Settings.txt
  FS-->>TauriCmd: write result
  TauriCmd-->>Frontend: return success

  Frontend->>TauriCmd: invoke read_url_from_file()
  TauriCmd->>FS: read Settings.txt
  FS-->>TauriCmd: contents or error
  TauriCmd-->>Frontend: return url or error

  Frontend->>TauriCmd: request get_linux_resource_stats()
  TauriCmd->>OS: read /proc/meminfo, /proc/self/status, ps for WebKit children
  OS-->>TauriCmd: parsed metrics
  TauriCmd-->>Frontend: LinuxResourceStats JSON
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nibbled lines in code and log,
Wove URL crumbs into a file for the fog.
ARM64 runners join the race,
Debug overlays hop in place.
A tiny rabbit cheers the build—go, go, go!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective of the PR: adding documentation and CI/CD support for building ImmichFrame on Linux ARM64 with a self-hosted runner, which aligns with the primary changes across the workflow, README, and source code.
Docstring Coverage ✅ Passed Docstring coverage is 91.67% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds Linux ARM64 build support via self-hosted runners and updates project dependencies to specific pinned versions. The changes enable building ARM64 .deb packages, add Linux autostart documentation, and improve build workflow flexibility through manual dispatch with selectable build targets.

Changes:

  • Version bumped from 1.0.2 to 1.0.23 across all configuration files
  • Added workflow support for ARM64 builds via self-hosted runners with memory-constrained optimizations
  • Switched from npm to Yarn with locked dependencies for reproducible builds

Reviewed changes

Copilot reviewed 5 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
yarn.lock New file adding Yarn lockfile with Tauri 2.9.x dependencies
package.json Updated version to 1.0.23 and pinned Tauri dependencies to ~2.9.x
package-lock.json Removed in favor of yarn.lock
src-tauri/tauri.conf.json Updated version to 1.0.23
src-tauri/Cargo.toml Updated version to 1.0.23 and pinned Tauri build dependencies
src-tauri/Cargo.lock Updated dependencies to match new versions
README.md Added Linux autostart instructions and ARM64 build documentation
.github/workflows/build-and-push.yml Added ARM64 self-hosted job, workflow_dispatch inputs, and Yarn integration

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

publish-tauri:
needs: sync-version
runs-on: ${{ matrix.platform }}
if: ${{ always() && (needs.sync-version.result == 'success' || needs.sync-version.result == 'skipped') && (github.event_name != 'workflow_dispatch' || inputs.build != 'arm64') }}
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The workflow condition checks for needs.sync-version.result == 'skipped' but the sync-version job has no conditions that would cause it to be skipped. This condition may never be true, making the logic more complex than necessary.

Copilot uses AI. Check for mistakes.
Copy link

@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

🤖 Fix all issues with AI agents
In `@README.md`:
- Around line 42-51: Update the README: change the heading phrase "High level
steps" to "High-level steps", capitalize "GitHub" where "github" appears,
replace the outdated example tag `v1.0.2` with a placeholder like `v1.0.x` (or
the current `v1.0.23`) used in the `.github/workflows/build-and-push.yml`
workflow example, and fix the sub-item indentation under step 3 (the dash
listing the release/tag note) so it is properly nested and aligned with the
other list items.
🧹 Nitpick comments (3)
src-tauri/Cargo.toml (1)

17-25: Good version pinning, but tauri-plugin-shell is inconsistent.

The tauri-build and tauri dependencies now use tilde-pinned versions for stability, which is good. However, tauri-plugin-shell = "2" (line 22) still uses a major-only version specifier, which is inconsistent with the pinning strategy applied to the other Tauri dependencies.

♻️ Suggested consistency fix
 [dependencies]
 tauri = { version = "~2.9.5", features = [] }
-tauri-plugin-shell = "2"
+tauri-plugin-shell = "~2.2"
 serde = { version = "1", features = ["derive"] }
 serde_json = "1"
 dirs = "4.0"
.github/workflows/build-and-push.yml (2)

75-75: Complex conditional logic is correct but hard to read.

The condition handles multiple scenarios correctly, but consider adding a comment explaining the logic for future maintainers.

📝 Suggested comment
   publish-tauri:
     needs: sync-version
+    # Run when: (1) sync-version succeeded or was skipped, AND
+    # (2) not a workflow_dispatch with build=arm64 (that's handled by publish-tauri-linux-arm64)
     if: ${{ always() && (needs.sync-version.result == 'success' || needs.sync-version.result == 'skipped') && (github.event_name != 'workflow_dispatch' || inputs.build != 'arm64') }}

242-246: Add Rust target for ARM64 for consistency with macOS job.

The ARM64 job in the build command specifies --target aarch64-unknown-linux-gnu but lacks an explicit rustup target add step. The macOS job (line 129-133) explicitly adds its targets. While the target should be available by default on a native aarch64 runner, adding it explicitly improves consistency and robustness:

      - name: Add Rust target (ARM64)
        run: rustup target add aarch64-unknown-linux-gnu
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05aeef8 and bef5703.

⛔ Files ignored due to path filters (3)
  • package-lock.json is excluded by !**/package-lock.json
  • src-tauri/Cargo.lock is excluded by !**/*.lock
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (5)
  • .github/workflows/build-and-push.yml
  • README.md
  • package.json
  • src-tauri/Cargo.toml
  • src-tauri/tauri.conf.json
🧰 Additional context used
🪛 LanguageTool
README.md

[grammar] ~42-~42: Use a hyphen to join words.
Context: ...64 .deb on a self-hosted runner. High level steps: 1. Provision an Ubuntu aar...

(QB_NEW_EN_HYPHEN)


[uncategorized] ~46-~46: The official name of this software platform is spelled with a capital “H”.
Context: ..., linux, arm64. 3. Run the workflow .github/workflows/build-and-push.yml manually ...

(GITHUB)

🪛 markdownlint-cli2 (0.18.1)
README.md

47-47: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Agent
🔇 Additional comments (9)
src-tauri/tauri.conf.json (1)

4-4: LGTM!

Version bump to 1.0.23 is consistent with the coordinated version updates in package.json and src-tauri/Cargo.toml.

README.md (1)

24-33: Autostart documentation looks good.

The desktop entry example is well-documented with useful notes about Wayland/GLES settings for ARM/Mali setups. The sleep delay and logging approach are practical for debugging startup issues.

.github/workflows/build-and-push.yml (6)

8-21: Well-designed workflow inputs.

The workflow_dispatch inputs provide good flexibility for selective builds. The build choice options (hosted, arm64, all) cleanly separate the build targets.


108-121: Robust Yarn setup via Corepack.

Good use of set -euxo pipefail for strict error handling. Pinning Yarn to 1.22.22 ensures reproducible builds. Installing to $HOME/.local/bin and updating GITHUB_PATH correctly makes the shim available to subsequent steps.


177-184: Good resource management for constrained ARM64 runners.

Setting CARGO_BUILD_JOBS: '1' and timeout-minutes: 180 appropriately addresses memory limitations on low-resource ARM boards. The inline comment at lines 229-231 provides helpful context for future maintainers.


248-260: Release upload configuration looks correct.

Using softprops/action-gh-release@v2 with fail_on_unmatched_files: true ensures the workflow fails if the expected .deb artifact isn't found, providing good build validation.

One consideration: ensure the inputs.tag corresponds to an existing release, as action-gh-release will create a new release if one doesn't exist with that tag.


59-65: Clean approach for version bumping.

Using jq for JSON manipulation is a solid choice—it's readable and handles edge cases better than sed-based approaches.


151-158: Good CI hygiene with lockfile enforcement and verification.

Using yarn install --frozen-lockfile ensures the build uses exact dependency versions from the lockfile. The subsequent yarn tauri --version verification confirms the CLI is properly installed before attempting builds.

package.json (1)

10-13: Good version pinning strategy.

Switching to tilde (~) version ranges provides better stability by limiting updates to patch versions only. This is especially beneficial for CI/CD reliability. The versions are compatible: @tauri-apps/cli 2.9.6 works with @tauri-apps/api 2.9.1 as part of the 2.9.x ecosystem, and the Rust-side tauri dependency (~2.9.5) is also aligned.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@JW-CH JW-CH requested a review from 3rob3 January 14, 2026 16:05
Copy link
Contributor

@3rob3 3rob3 left a comment

Choose a reason for hiding this comment

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

Is this meant for raspberry pi type devices? I just autostart fullscreen chromium on those. Regardless, thanks for the contribution!

@bongiozzo
Copy link
Author

Is this meant for raspberry pi type devices? I just autostart fullscreen chromium on those. Regardless, thanks for the contribution!

Exactly.
But Chromium crashed after 4–5 hours.
That’s why I tried a lightweight Rust app.

But it crashes as well. :-)
Is the problem in the Mali drivers?

logs.txt

Copy link

@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

🤖 Fix all issues with AI agents
In `@src/main.js`:
- Around line 70-72: The click handler that removes the overlay element (el)
must also clear the repeating timer started for update; capture the setInterval
return value in a named variable (e.g., overlayInterval or intervalId) in the
same scope where update is scheduled (the setInterval call around lines 111–112)
and call clearInterval on that variable inside the el.addEventListener("click",
...) before removing the element so the update function stops executing after
the overlay is hidden.
♻️ Duplicate comments (1)
README.md (1)

49-54: Documentation issues flagged previously remain unaddressed.

The static analysis and past review identified:

  1. Line 49: "High level" → "High-level" (hyphenation)
  2. Line 54: Sub-item indentation should use 4 spaces or proper list nesting
  3. Line 54: Example tag v1.0.2 appears outdated given the current version is 1.0.23
📝 Suggested fixes
-High level steps:
+High-level steps:
 
 1. Provision an Ubuntu aarch64 machine (e.g. Khadas VIM3) and install the GitHub Actions runner.
 2. Register the runner for your fork/repo with labels: `self-hosted`, `linux`, `arm64`.
 3. Run the workflow `.github/workflows/build-and-push.yml` manually via `workflow_dispatch` and pick `build=arm64`.
-  - Provide an existing tag (e.g. `v1.0.2`) so the workflow can upload the `.deb` to that release.
+    - Provide an existing tag (e.g. `v1.0.x`) so the workflow can upload the `.deb` to that release.
🧹 Nitpick comments (2)
src-tauri/src/lib.rs (1)

151-226: Solid implementation for tracking WebKit subprocess memory.

The iterative descendant discovery algorithm correctly handles arbitrary process tree depths. Using saturating_add for RSS aggregation (lines 219-220) prevents overflow on systems with many WebKit processes.

One minor style note: the use std::collections::{HashMap, HashSet}; at line 194 is imported inside the function. While valid, module-level imports are more conventional in Rust.

src/main.js (1)

98-101: Minor: Inconsistent spacing in WebKit RSS line.

Line 100 is missing a space after the colon, unlike other stat lines (e.g., lines 93, 95-97).

📝 Suggested fix
-          lines.push(`WebKit RSS:${formatKb(stats.webkit_rss_kb)}${n}`);
+          lines.push(`WebKit RSS: ${formatKb(stats.webkit_rss_kb)}${n}`);
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4930870 and 46e1656.

📒 Files selected for processing (4)
  • README.md
  • src-tauri/src/lib.rs
  • src-tauri/src/main.rs
  • src/main.js
💤 Files with no reviewable changes (1)
  • src-tauri/src/main.rs
🧰 Additional context used
🪛 LanguageTool
README.md

[grammar] ~49-~49: Use a hyphen to join words.
Context: ...64 .deb on a self-hosted runner. High level steps: 1. Provision an Ubuntu aar...

(QB_NEW_EN_HYPHEN)


[uncategorized] ~53-~53: The official name of this software platform is spelled with a capital “H”.
Context: ..., linux, arm64. 3. Run the workflow .github/workflows/build-and-push.yml manually ...

(GITHUB)

🪛 markdownlint-cli2 (0.18.1)
README.md

54-54: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

🔇 Additional comments (14)
src-tauri/src/lib.rs (7)

6-29: LGTM! Cross-platform settings directory resolution is well-structured.

The function correctly handles platform-specific paths and creates the directory if missing. Minor observation: the fallback case (line 21) returns just home_dir() without an "immichFrame" subdirectory, which differs from the explicit OS cases. This is acceptable for unknown platforms but could lead to settings file clutter in the home directory.


31-48: LGTM! Simple and effective file I/O for URL persistence.

The error handling is appropriate, propagating descriptive error messages to the frontend.


50-62: LGTM! Standard patterns for app lifecycle control.

The restart implementation correctly spawns a detached child process before exiting.


64-79: Good security practice restricting environment variable access.

The validation correctly limits frontend access to only IMMICHFRAME_* prefixed variables with alphanumeric/underscore suffixes, preventing arbitrary environment variable disclosure.


96-149: Well-implemented Linux-specific parsing utilities.

The parsing logic correctly handles the format of /proc/meminfo, /proc/self/status, and ps output. The fallback logic for ps variants without header suppression (lines 166-179) and the subsequent header-skip retry (lines 183-186) is a thoughtful touch for compatibility.


228-278: LGTM! Well-structured conditional compilation for Linux-only stats.

The graceful degradation with Option return type and #[cfg(not(target_os = "linux"))] returning None ensures cross-platform compatibility without runtime errors.


284-291: LGTM! All new commands properly registered.

The invoke handler correctly wires up all the new Tauri commands for frontend access.

src/main.js (6)

13-18: LGTM! Clean utility function for parsing positive integers.

The parsePositiveInt function correctly handles edge cases including null/undefined values and non-positive numbers.


20-35: LGTM! Effective hard-reload pattern.

The blank-then-restore approach with a 250ms delay is a reliable way to force a full iframe reload, clearing any cached state.


37-48: LGTM! Well-designed utility helpers.

The formatKb function provides clean human-readable memory formatting, and truthyEnv handles common truthy value patterns robustly.


115-128: LGTM! Proper synchronization of currentUrl state on startup.

The startup logic correctly updates currentUrl in both success and error paths, ensuring the debug overlay and reload functions always reference the correct URL.


130-166: LGTM! Well-designed optional watchdog features.

The environment-driven watchdog configuration with silent fallback (lines 163-165) is appropriate for optional features. The pattern of using parsePositiveInt to guard against invalid values is defensive and clean.


217-219: LGTM! Correct state synchronization on URL save.

Updating currentUrl before setting iframe.src ensures the state remains consistent for subsequent hard-reload operations.

README.md (1)

17-44: Helpful autostart documentation for Linux users.

The .desktop file example with environment variable configuration aligns well with the implemented features. The comments explaining optional watchdog flags are a nice touch for discoverability.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +70 to +72
el.addEventListener("click", () => {
el.remove();
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Interval not cleared when overlay is removed.

When the user clicks to hide the overlay (line 71), the interval created at line 112 continues running. The update function will keep executing every 5 seconds, making Tauri invocations and attempting to update a removed DOM element.

🔧 Proposed fix
+  let intervalId = null;
+
   el.addEventListener("click", () => {
+    if (intervalId) {
+      window.clearInterval(intervalId);
+    }
     el.remove();
   });
   
   // ... later ...
   
   update();
-  window.setInterval(update, 5000);
+  intervalId = window.setInterval(update, 5000);

Also applies to: 111-112

🤖 Prompt for AI Agents
In `@src/main.js` around lines 70 - 72, The click handler that removes the overlay
element (el) must also clear the repeating timer started for update; capture the
setInterval return value in a named variable (e.g., overlayInterval or
intervalId) in the same scope where update is scheduled (the setInterval call
around lines 111–112) and call clearInterval on that variable inside the
el.addEventListener("click", ...) before removing the element so the update
function stops executing after the overlay is hidden.

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.

2 participants