Skip to content

feat: Linux support — platform abstraction, systemd autostart, Secret Service keyring, CI matrix#1

Open
daviirodrig wants to merge 2 commits into
ctresb:mainfrom
daviirodrig:main
Open

feat: Linux support — platform abstraction, systemd autostart, Secret Service keyring, CI matrix#1
daviirodrig wants to merge 2 commits into
ctresb:mainfrom
daviirodrig:main

Conversation

@daviirodrig

Copy link
Copy Markdown

Overview

Makes the server and desktop build/run properly on Linux without touching the polished macOS flow. macOS behavior is identical to before.


What changed

Backend — platform abstraction (crates/server/src/platform/)

Replaced scattered #[cfg(target_os = "macos")] blocks with a proper platform module:

  • platform/mod.rs — pure TargetOs enum + PlatformLabels struct + platform_labels(os) function (fully testable without a host OS). Exposes autostart_info / install / restart that delegate to the right platform impl.
  • platform/macos.rs — existing LaunchAgent logic, now isolated behind #[cfg(target_os = "macos")] mod macos. No Linux compiler warnings.
  • platform/linux.rs — systemd user service: install writes ~/.config/systemd/user/projectus.service, runs systemctl --user enable --now; restart delegates to systemctl --user restart; status checks is-active --quiet. Suggests loginctl enable-linger but never calls it automatically. No sudo.

daemon.rs

DaemonStatus gains:

field purpose
plataforma "macOS" / "Linux" / "sistema atual"
autostart_nome "LaunchAgent" / "systemd user service"
service_path replaces plist; absolute path to the service file
instalacao_manual hint script path for manual install

status(), install(), restart() now fully delegate — no cfg in daemon.rs.

Cargo deps

[target.'cfg(target_os = "macos")'.dependencies]
keyring = { version = "3", features = ["apple-native"] }
libc = "0.2"

[target.'cfg(target_os = "linux")'.dependencies]
keyring = { version = "3", features = ["sync-secret-service"] }

Eliminates unused-import warnings on Linux. Linux uses DBus Secret Service (GNOME Keyring / KWallet).

domain.rs + storage.rs

  • BackupCredentialStatus gains store_nome ("Keychain" / "Secret Service")
  • ApiCapabilities gains data_root (absolute path) and data_root_label (~-expanded path), filled by storage.bootstrap()

UI

All hardcoded macOS strings replaced by API data:

Before After
"Salva no Keychain do macOS" "Salva no {credentialStore}"
"fixar credenciais no Keychain" "fixar credenciais no {credentialStore}"
"autostart instalado no macOS" "autostart instalado via {daemon.autostart_nome}"
"execute ./scripts/instalar-autostart.sh" "use o botão instalar ou {daemon.instalacao_manual}"
~/Documents/PROJECTUS (hardcoded) capacidades.data_root_label (real path, ~-expanded)

Scripts

script behavior
instalar-autostart.sh bash dispatcher → *-macos.sh or *-linux.sh
remover-autostart.sh bash dispatcher → *-macos.sh or *-linux.sh
instalar-autostart-macos.sh original zsh LaunchAgent logic, unchanged
remover-autostart-macos.sh original zsh logic, unchanged
instalar-autostart-linux.sh systemctl --user, no sudo
remover-autostart-linux.sh disable + rm + daemon-reload
instalar.sh early exit on Linux with helpful message
build-linux.sh pnpm build + cargo release + tauri deb,appimage
check-tauri-linux-deps.sh pkg-config probe; prints Arch/Debian install commands on failure

CI (.github/workflows/ci.yml)

Three jobs on every push/PR to main:

  • web (Ubuntu): typecheck + test + build
  • rust-linux (Ubuntu): libdbus-1-dev, cargo test --workspace, release build
  • rust-macos (macOS): cargo test --workspace, release build

Tests

4 new unit tests in platform/mod.rs:

  • daemon_status_on_linux_reports_systemd_user_service
  • daemon_status_on_macos_reports_launch_agent
  • credential_store_label_matches_platform
  • manual_install_message_mentions_correct_script

All tests pass (cargo test --workspace: 16 passed, pnpm test --run: 16 passed).


Linux quick start (server only)

pnpm install
pnpm build
cargo build --release -p projectus-server
PROJECTUS_WEB_DIST="$PWD/apps/web/dist" ./target/release/projectus-server
# → http://127.0.0.1:4387

Autostart:

./scripts/instalar-autostart.sh
systemctl --user status projectus.service

Secret Service (R2 credentials): requires GNOME Keyring or KWallet running. Headless environments get a clear error, no panic.

…ential store

Adds a platform abstraction layer so macOS and Linux each get correct
labels, paths, and behavior without scattering cfg blocks everywhere.

- platform/: mod.rs with pure TargetOs/PlatformLabels (testable without
  a real OS), macos.rs wrapping the existing LaunchAgent logic, linux.rs
  implementing systemd --user install/restart/remove
- daemon.rs: DaemonStatus gains plataforma, autostart_nome, service_path,
  instalacao_manual; delegates fully to platform module (no more cfg in daemon)
- Cargo.toml: target-specific keyring (apple-native / sync-secret-service)
  and libc (macOS only); eliminates unused-import warnings on Linux
- secrets.rs: error messages and BackupCredentialStatus.store_nome use the
  platform label ("Keychain" / "Secret Service")
- domain.rs: ApiCapabilities gains data_root + data_root_label; filled by
  storage.bootstrap() with the real filesystem path (~-expanded)
- UI: SettingsView, Shell, BackupView all drive text from API data instead
  of hardcoded macOS strings; App.tsx forwards data_root_label
- 4 platform unit tests covering label correctness per OS
…CI matrix

Scripts:
- instalar-autostart.sh / remover-autostart.sh become bash dispatchers
  (Darwin → macos, Linux → linux, else error); old zsh logic moved to
  *-macos.sh variants intact
- instalar-autostart-linux.sh: writes ~/.config/systemd/user/projectus.service,
  runs systemctl --user enable --now; hints about loginctl enable-linger
- remover-autostart-linux.sh: systemctl disable --now + rm + daemon-reload
- instalar.sh: early exit on Linux with a useful message pointing to build:linux
- build-linux.sh: pnpm build + cargo release + tauri deb,appimage
- check-tauri-linux-deps.sh: pkg-config probe for webkit2gtk-4.1 / gtk+-3.0 /
  openssl; prints Arch and Debian/Ubuntu install commands on failure; macOS no-op

package.json: adds build:linux, instalar:macos, desktop:check scripts

CI (.github/workflows/ci.yml):
- web job on ubuntu-latest: typecheck, test, build
- rust-linux on ubuntu-latest: libdbus-1-dev, cargo test + release build
- rust-macos on macos-latest: cargo test + release build
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