Skip to content

build(tauri): stage watcher modules before Linux Tauri build - #1498

Closed
TimeToBuildBob wants to merge 4 commits into
ActivityWatch:masterfrom
TimeToBuildBob:feat/stage-tauri-modules
Closed

TimeToBuildBob wants to merge 4 commits into
ActivityWatch:masterfrom
TimeToBuildBob:feat/stage-tauri-modules

Conversation

@TimeToBuildBob

Copy link
Copy Markdown
Contributor

Problem

Linux standalone bundles (AppImage/deb/rpm) from make package TAURI_BUILD=true shipped without watchers. The aw-tauri Makefile already supports injecting a src-tauri/modules/ directory into the Tauri bundle via bundle.resources (commit 931e56d — conditional on $(wildcard src-tauri/modules/aw-*) being non-empty), but nothing in the activitywatch build was staging anything there.

Fix

Restructure the package target to:

  1. Build all non-aw-tauri PACKAGEABLES first (watchers + aw-core + aw-client)
  2. On Linux: copy aw-watcher-afk/, aw-watcher-window/, and aw-sync into aw-tauri/src-tauri/modules/
  3. Build aw-tauri explicitly after staging — aw-tauri's Makefile detects the populated modules/ directory and injects it into the bundle

macOS is unchanged: the staging block is ifeq ($(shell uname),Linux) only, since macOS bundles watchers differently (native window tracker, .app bundle structure).

Test plan

  • make package TAURI_BUILD=true on Linux — verify dist/activitywatch/aw-tauri/*.AppImage contains aw-watcher-afk, aw-watcher-window, and aw-sync under Resources/modules/
  • CI Linux Tauri build leg passes
  • make package (non-TAURI_BUILD) unchanged — aw-qt flow unaffected

@greptile-apps

greptile-apps Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[High risk] Restructures the build and package workflow for the desktop app.

Fix the Linux source-build regression before merging.

Findings

  1. P1 Source builds skip the desktop ▶

Summary

The PR stages Linux watchers and aw-sync before building Tauri bundles. It also clears old bundles, retries packaging, and passes updater signing keys to the packaging step.

  • Linux source builds now skip the Tauri desktop unless packaging also runs.
  • The previously reported missing awatcher is addressed by its staging copy.
  • TimeToBuildBob deferred the earlier release-version export, Python test compatibility, and upgrade smoke-test findings because they were pre-existing and would be fixed separately.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  B["make build: Linux Tauri"] --> C["Build other components"]
  C --> S["Skip aw-tauri"]
  P["make package"] --> W["Package watchers"]
  W --> M["Stage watchers and aw-sync"]
  M --> R["Remove old bundles"]
  R --> T["Build and package aw-tauri"]
  T --> O["Linux standalone bundles"]
Loading

Reviews (4) · Last reviewed commit: "fix(tauri): build Linux bundles once aft..."

Comment thread .github/workflows/release.yml
Comment thread scripts/tests/test_patch_research_edition_config.py
Comment thread .github/workflows/windows-upgrade-smoke.yml Outdated
On Linux, copy aw-watcher-afk, aw-watcher-window, and aw-sync into
aw-tauri/src-tauri/modules/ before building the Tauri package. The
aw-tauri Makefile (commit 931e56d) already detects the presence of
src-tauri/modules/aw-* and injects them into the AppImage/deb/rpm via
bundle.resources — but nothing was staging them there before this change,
so standalone Linux bundles shipped without watchers.

Restructure the package loop to build all non-aw-tauri PACKAGEABLES first,
then stage modules on Linux, then build aw-tauri explicitly. On macOS the
staging block is skipped (watchers are bundled differently there).

Git-Session-Id: f6b4
@TimeToBuildBob
TimeToBuildBob force-pushed the feat/stage-tauri-modules branch from 123fb7c to 14ffe5c Compare October 6, 2026 14:59
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

Rebased onto upstream master (14ffe5c). The upstream had added APP_BUNDLE variable, update-submodules/sync-tauri-server targets, test-query-parity, and fixed the aw-qt rename in the package else branch — all non-overlapping with our Tauri staging changes, so the cherry-pick applied cleanly with no conflicts.

The original code staged modules then called `make --directory=aw-tauri
package`, but aw-tauri's Makefile evaluates TAURI_BUILD_ARGS at parse
time: the `bundle.resources` config is only injected when
src-tauri/modules/aw-* already exists when make starts.

Staging after the top-level `make build` (which already ran `make
--directory=aw-tauri build`) meant the tauri build ran without modules,
and `make package` only copies the already-built bundles — so the deb/
rpm/AppImage were built without the watcher binaries embedded.

Fix: on Linux, call `make --directory=aw-tauri build package` after
staging, so tauri re-runs its build step with modules present and
TAURI_BUILD_ARGS correctly includes `bundle.resources`. On non-Linux
platforms the staging block doesn't run, so `make --directory=aw-tauri
package` is unchanged.

Git-Session-Id: 791dd535-5e0b-57e7-a6c3-b1653fe4976e
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

Root cause found and fixed in d1fb5c8.

The CI failure (cp: target 'aw-tauri.deb': No such file or directory) stems from a sequencing issue:

  1. make build runs the SUBMODULES loop including make --directory=aw-tauri build. At this point src-tauri/modules/aw-* doesn't exist yet, so aw-tauri's Makefile sets TAURI_BUILD_ARGS without bundle.resources — the tauri build runs and produces a deb without bundled watchers.

  2. make package (original code) staged the watcher binaries into src-tauri/modules/, then called make --directory=aw-tauri package — which only copies the already-built bundles. It doesn't re-run tauri build, so the staged modules are never seen by the bundler. The copy then fails because the expected deb path doesn't match (aw-tauri's package target expects the deb to contain the correct arch suffix, which may differ between build/package steps), or more precisely the bundle doesn't contain the modules paths it expected.

Fix: on Linux, after staging modules, call make --directory=aw-tauri build package instead of just package. This re-runs tauri build with the staged src-tauri/modules/aw-* present, so TAURI_BUILD_ARGS correctly picks up --config '{"bundle":{"resources":{"modules/":"modules/"}}}'. Rust's incremental compilation means only the bundle step re-runs in practice. On non-Linux the staging block is skipped and behavior is unchanged.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

@greptileai review

Comment thread Makefile
awatcher is included as a PACKAGEABLE on Linux (alongside aw-watcher-afk
and aw-watcher-window) but was missing from the src-tauri/modules/ staging
block, so standalone Linux Tauri bundles shipped without the Wayland-
compatible window watcher.

Git-Session-Id: dc4bba9d-ca43-5116-848c-3f8e863d5efe
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

@greptileai review

The previous package-time `make --directory=aw-tauri build package`
re-ran tauri build after the top-level `make build` had already
bundled aw-tauri without modules. That caused two CI failures:

- ubuntu-24.04: second linuxdeploy (AppImage) failed with
  "failed to run linuxdeploy". Build already retried that flake
  twice; Package had no retry.
- ubuntu-24.04-arm: `cp bundle/deb/*.deb .../aw-tauri.deb` failed
  because leftover .deb files from the first bundle made GNU cp
  treat the dest as a directory.

Skip the Linux aw-tauri build until modules are staged, wipe any
leftover bundle dir, and retry Package with the same signing env
as Build so the one remaining tauri build can produce updater
artifacts.

Git-Session-Id: bob-monitor-3650578
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

The Package failures on 0c56018 were a second-order effect of rebuilding aw-tauri twice:

  • ubuntu-24.04: first tauri build (no modules) already retried linuxdeploy twice on Connection reset by peer, then succeeded. Package ran tauri build again with modules; linuxdeploy failed (failed to run linuxdeploy) and Package had no retry.
  • ubuntu-24.04-arm: the second build succeeded (deb/rpm/AppImage all produced) but cp src-tauri/target/release/bundle/deb/*.deb target/package/aw-tauri/aw-tauri.deb failed. Leftover .deb files from the first bundle made GNU cp treat the dest as a directory.

Research-edition Linux passed because that job's extra rebuild left a single .deb for the glob.

Fix in c0a8853:

  1. Skip the Linux aw-tauri build during make build when TAURI_BUILD=true — watchers are staged first, then one tauri build.
  2. Wipe src-tauri/target/{release,debug}/bundle before that build.
  3. Retry the Tauri Package step (same nick-fields/retry as Build) and pass the signing env so the one remaining build can still emit updater artifacts.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

@greptileai review

Comment thread Makefile
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

Status on c0a8853: the 4/5 rests only on the "Source builds skip the desktop" P1, and Greptile withdrew it at 18:26 after the design rationale. The summary score was computed before that. All 5 review threads are resolved. The two release.yml/test findings are pre-existing, and the VERSION_NO_V export is already on master.

No code change this round, so I'm not re-triggering a review. CI on c0a8853 is still running (the Tauri Linux legs are the ones that matter). Leaving this for human review and merge once those are green.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

On c0a8853, all three Tauri Linux legs passed: ubuntu-24.04, ubuntu-24.04-arm and research. The ubuntu-24.04 log shows the fix doing what it should:

  • make build skips aw-tauri on Linux ("watcher modules must be staged first").
  • package stages aw-watcher-afk, aw-watcher-window, awatcher and aw-sync into aw-tauri/src-tauri/modules/, clears leftover bundles, then runs one tauri build.
  • That one build produces the .deb, .rpm and .AppImage, and the .deb and .AppImage end up in the release zip. The double build and the aw-tauri.deb cp failure are gone.

The macOS legs are still queued for runners. This change is gated to Linux, so they don't exercise it. Ready for review and merge.

@TimeToBuildBob

TimeToBuildBob commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 AI code review

The PR restructures the Makefile package target so that on Linux Tauri builds, watcher binaries and aw-sync are staged into aw-tauri/src-tauri/modules/ before aw-tauri is built and packaged, making Linux standalone bundles self-contained. It also wraps the CI Package step in a retry action and passes Tauri signing environment variables to that step.

Needs a look — P2 only

Confidence 4/5

ℹ️ Consensus was degraded on this run: 1 of 3 passes answered, so findings were filtered at 1-of-1 agreement rather than 2-of-3 — less filtered than usual; 1 of 3 fan-out jobs answered, so the findings above were filtered against less evidence than the threshold assumes.

2 findings · ⚠️ 2 P2

⚠️ P2 medium — .github/workflows/release.yml:1482

The CI workflow's Package step now uses nick-fields/retry with max_attempts: 3 and timeout_minutes: 60. The command runs make package SKIP_SERVER_RUST=${{ matrix.skip_rust }}. On Linux Tauri builds, this make package now runs tauri build (via make --directory=aw-tauri build package), which can take a long time. The retry action will retry the entire make package if it times out or fails. However, make package starts with rm -rf dist and rebuilds everything from scratch. If the first attempt fails after 60 minutes, the retry will start over, potentially wasting another 60 minutes. More importantly, the retry action's timeout_minutes applies to each attempt, but the make package on Linux Tauri may exceed 60 minutes, causing the retry to fail and then retry again, potentially hitting the overall job timeout. The previous Package step was a plain run without a timeout, so it could run as long as needed. Adding a 60-minute timeout may cause the build to fail on slower runners or when the cargo cache is cold. This is a potential regression in CI reliability.

How this was verified: Checked the diff: the Package step was changed from a plain run to a retry with timeout_minutes: 60. The Linux Tauri build now happens inside this step, and a full Tauri build can take longer than 60 minutes, especially on the first run without cache. The retry will restart the entire step, which is wasteful and may still time out.

⚠️ P2 medium — Makefile:74

The Makefile's build target now skips aw-tauri on Linux when TAURI_BUILD=true, with the comment that watcher modules must be staged first. However, the build target is also used by the CI Build step, which runs make build SKIP_WEBUI=... SKIP_SERVER_RUST=.... On Linux Tauri builds, this now skips building aw-tauri entirely, meaning the aw-tauri frontend (if any) and Rust code are not compiled during the Build step. They are compiled later during make package (in the Package step). This means the Build step no longer catches compile errors in aw-tauri on Linux; they only surface during Package, which is now wrapped in a retry with a 60-minute timeout. If aw-tauri fails to compile, the Package step will retry three times, each time re-running the full make package (including rebuilding all watchers and aw-tauri), wasting significant CI time before failing. This is a regression in CI feedback speed and could mask errors until the packaging stage.

How this was verified: Checked the Makefile build target lines 70-79. The new elif skips aw-tauri on Linux Tauri builds. The CI Build step runs make build, so aw-tauri is not built there. The Package step later runs make package, which on Linux runs make --directory=aw-tauri build package. So aw-tauri compilation is deferred to the Package step.

Files changed (2) — the diff as I read it
  • .github/workflows/release.yml — Wraps the Package step in nick-fields/retry and adds TAURI_SIGNING_PRIVATE_KEY and TAURI_SIGNING_PRIVATE_KEY_PASSWORD env vars to it.
  • Makefile — Skips aw-tauri build on Linux during make build, filters aw-tauri out of the package loop, and adds a Linux-only staging block that copies watcher modules and aw-sync into aw-tauri/src-tauri/modules before building and packaging aw-tauri.

Reviewed c0a88538a2fa · openrouter/deepseek/deepseek-v4-flash-0731 · llm engine · 1215s · about this reviewer

Maintainer commands

@TimeToBuildBob review (own line) — fresh review · @TimeToBuildBob fix — a worker acts on the findings. Once per comment; 👀 = received.

make package SKIP_SERVER_RUST=${{ matrix.skip_rust }}
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4
with:
timeout_minutes: 60

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

⚠️ P2 — The CI workflow's Package step now uses nick-fields/retry with max_attempts: 3 and timeout_minutes: 60. The command runs make package SKIP_SERVER_RUST=${{ matrix.skip_rust }}. On Linux Tauri builds, this make package now runs tauri build (via make --directory=aw-tauri build package), which can take a long time. The retry action will retry the entire make package if it times out or fails. However, make package starts with rm -rf dist and rebuilds everything from scratch. If the first attempt fails after 60 minutes, the retry will start over, potentially wasting another 60 minutes. More importantly, the retry action's timeout_minutes applies to each attempt, but the make package on Linux Tauri may exceed 60 minutes, causing the retry to fail and then retry again, potentially hitting the overall job timeout. The previous Package step was a plain run without a timeout, so it could run as long as needed. Adding a 60-minute timeout may cause the build to fail on slower runners or when the cargo cache is cold. This is a potential regression in CI reliability.

Comment thread Makefile
echo "Building $$module"; \
if [ "$$module" = "aw-server-rust" ] && [ "$(TAURI_BUILD)" = "true" ]; then \
make --directory=$$module aw-sync SKIP_WEBUI=$(SKIP_WEBUI) || { echo "Error in $$module aw-sync"; exit 2; }; \
elif [ "$$module" = "aw-tauri" ] && [ "$(TAURI_BUILD)" = "true" ] && [ "$(OS)" = "Linux" ]; then \

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

⚠️ P2 — The Makefile's build target now skips aw-tauri on Linux when TAURI_BUILD=true, with the comment that watcher modules must be staged first. However, the build target is also used by the CI Build step, which runs make build SKIP_WEBUI=... SKIP_SERVER_RUST=.... On Linux Tauri builds, this now skips building aw-tauri entirely, meaning the aw-tauri frontend (if any) and Rust code are not compiled during the Build step. They are compiled later during make package (in the Package step). This means the Build step no longer catches compile errors in aw-tauri on Linux; they only surface during Package, which is now wrapped in a retry with a 60-minute timeout. If aw-tauri fails to compile, the Package step will retry three times, each time re-running the full make package (including rebuilding all watchers and aw-tauri), wasting significant CI time before failing. This is a regression in CI feedback speed and could mask errors until the packaging stage.

@ErikBjare

Copy link
Copy Markdown
Member

Closing in favour of #1499, which fixes the same problem in the Makefile only. One issue here, for the record: this copies dist/activitywatch/awatcher/ in as a directory named awatcher, but aw-tauri's module discovery only descends into aw-* directories, so aw-awatcher wouldn't be found. On Wayland that leaves nothing tracking. #1499 stages flat aw-awatcher and aw-sync executables instead, and the Python watchers aren't needed when awatcher is present.

@ErikBjare ErikBjare closed this Oct 7, 2026
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