Contributing
Thank you for your interest in contributing to Finupdate and the Bluefin utility app ecosystem!
Development Setupβ
Finupdate is designed for Bluefin and other immutable Fedora-based desktops. The recommended workflow uses toolbox for fast Rust iteration and flatpak-builder (via Flatpak) for full integration testing. This matches how GNOME apps are developed upstream.
1. Create a toolbox (one-time)β
toolbox create finupdate
toolbox enter finupdate
Inside the toolbox, install build dependencies:
sudo dnf install -y \
cargo rust \
gtk4-devel libadwaita-devel \
meson ninja-build \
pkg-config
2. Install Flatpak build tools (on host, one-time)β
flatpak install flathub org.flatpak.Builder
flatpak install flathub org.gnome.Sdk//50 org.gnome.Platform//50
Quick Build & Test Cycleβ
# Fast cargo iteration β run inside toolbox:
toolbox run --container finupdate cargo build
toolbox run --container finupdate cargo check
# Full Flatpak build + install β run on host:
flatpak run org.flatpak.Builder --user --install --force-clean _flatpak \
build-aux/org.tunaos.finupdate.Devel.json
# Run the Flatpak:
flatpak run org.tunaos.finupdate.Devel
Or use the just recipes (see justfile):
just build # cargo check inside toolbox
just flatpak # full Flatpak build + install
just run # run the installed Flatpak
Notesβ
- Keep
cargo buildandflatpak-builderoutput directories separate: toolbox builds go to./target/, Flatpak builds go to./_flatpak/. They don't conflict. flatpak-builderalways builds inside the SDK sandbox β the toolbox is only for fast iteration.- If you switch between the two, no cleanup is needed.
Architecture Overviewβ
Read PATTERNS.md for the full architecture. Key principles:
- One component per file β each relm4 component lives in its own
.rsfile - Messages over callbacks β all state changes happen through the relm4 message system
- Separate worker thread β async I/O (subprocess, network) runs on tokio in a background thread
- State machine at app level β the
AppStateenum drives all UI transitions
Code Styleβ
Rustβ
- Follow standard
rustfmtformatting (default config) - Use
tracingmacros (tracing::info!,tracing::error!) notprintln! - All public items need doc comments (
///) - Module-level doc comments (
//!) explain the pattern, not just what the code does - Prefer explicit error messages over
.unwrap()in production paths
GTK/Adwaitaβ
- No hardcoded pixel values for spacing β use CSS classes (
margin-12, etc.) or Adwaita defaults - No custom colors β rely on Adwaita style classes (
suggested-action,destructive-action,dim-label) - Symbolic icons only β always use
name-symbolicsuffix - AdwStatusPage for states β idle, error, success, and empty states
- AdwToast for transient feedback β "copied to clipboard", "update complete"
Accessibilityβ
- Every icon-only button must have
set_tooltip_textANDset_accessible_label - Keyboard navigation must work for all interactive elements
- Test in both light and dark mode
Making Changesβ
Adding a New Featureβ
- Identify which component owns the feature (app.rs, status_view.rs, or new component)
- Add message variants to the appropriate
Input/Outputenum - Implement the handler in
update() - Update the view! macro or init() if new widgets are needed
- Update PATTERNS.md if the feature introduces a new pattern
Adding a New Componentβ
# Create the file:
touch src/ui/my_component.rs
# Add to src/ui/mod.rs:
pub mod my_component;
Then implement using the #[relm4::component(pub)] macro. See log_view.rs for the simplest example or status_view.rs for a complex one.
Modifying the Flatpak Manifestβ
The manifest is at build-aux/org.tunaos.finupdate.Devel.json. Key things:
- New D-Bus permissions: add to
finish-argsβ--talk-name=... - New system access: add to
finish-argsβ--filesystem=... - SDK version changes: update both
runtime-versionandsdk-extensionsversion
Data Filesβ
All data files use Meson templates (.in suffix) with placeholder substitution:
@APP_ID@β the full application ID (includes.Develsuffix in dev builds)@ICON@β the icon name (matches APP_ID)
If you add a new data file, register it in data/meson.build.
Commit Messagesβ
Follow conventional commits:
feat: add feature description
fix: what was broken and how it's fixed
build: build system changes
docs: documentation only
refactor: code changes that don't add features or fix bugs
Include the Co-authored-by trailer for AI-assisted commits.
Before Submitting a PRβ
Run through the HIG compliance checklist in PATTERNS.md.
Quick sanity checks:
-
toolbox run --container finupdate cargo buildcompiles cleanly with no warnings -
toolbox run --container finupdate cargo clippypasses - App launches and the new feature works visually
- Dark mode looks correct
- Keyboard navigation works
- No hardcoded colors or pixel values
File Mapβ
| File | Purpose |
|---|---|
justfile | just recipes for common dev tasks |
Cargo.toml | Rust dependencies and metadata |
meson.build | Top-level Meson build (deps, subdirs) |
meson_options.txt | Build profile option (development/release) |
src/main.rs | Entry point (logging, app launch) |
src/config.rs | Build-time constants |
src/config.rs.in | Meson template for config.rs |
src/app.rs | Main window component + state machine |
src/update_worker.rs | Async subprocess worker (tokio) |
src/ui/mod.rs | UI module declarations |
src/ui/status_view.rs | State-driven content area (Stack) |
src/ui/log_view.rs | Scrollable log output |
src/ui/update_list.rs | Per-module update cards with Nerd Mode |
src/ui/preferences.rs | Preferences dialog |
src/settings.rs | Settings persistence (XDG JSON) |
src/meson.build | Cargo build integration |
data/meson.build | Install desktop/metainfo/icons |
data/*.desktop.in | Desktop entry template |
data/*.metainfo.xml.in | AppStream metadata template |
data/icons/*.svg | App icons (regular + symbolic) |
build-aux/*.json | Flatpak manifests (Devel + release) |
build-aux/dist-vendor.sh | Vendor cargo deps for meson dist |
PATTERNS.md | Reusable patterns for Bluefin apps |
CONTRIBUTING.md | This file |
Getting Helpβ
- Open an issue at https://github.com/castrojo/finupdate/issues
- Reference the GNOME Developer Documentation
- Reference the relm4 book
- Reference the gtk4-rs docs