Skip to content

[IMP] odoo-setup: Add support for windows packaging#1242

Closed
d-fence wants to merge 10 commits intoActivityWatch:masterfrom
odoo:master-windows-builder-moc
Closed

[IMP] odoo-setup: Add support for windows packaging#1242
d-fence wants to merge 10 commits intoActivityWatch:masterfrom
odoo:master-windows-builder-moc

Conversation

@d-fence
Copy link
Copy Markdown

@d-fence d-fence commented Apr 3, 2026

No description provided.

Xavier-Do and others added 10 commits March 25, 2026 09:07
- Add `buildpackage.sh` script to build the tool and package it as a Debian
  package. By default, it builds the `noble` package. To build the `jammy`
  package, pass `jammy` as the first argument (e.g., `./buildpackage.sh jammy`).

- Add Dockerfiles for Ubuntu Jammy and Noble. They differ mainly in the
  `rustup` and `poetry` setup.

- Add `aw-systray-odoo.py` as a replacement for `aw-qt`. It starts the Rust
  server, the `awatcher` module, and the GNOME extension needed for Wayland
  setups.
The script needs a previously crafted Windows qemu/kmv virtual machine
with at least the following requirements:
- Ssh server and MingGW in order to intrument the build through ssh
- A valid ssh public key to use when  building
- python3
- Poetry
- the rustup nightly toolchain
- Node.js 20
- gnuwin32
- innosetup

Details can be found here:
https://docs.activitywatch.net/en/latest/installing-from-source.html#checking-dependencies
When building windows package, we exclude aw-qt and the python server
from the Windows installer.

This is done through the environment variable ODOO_WINDOWS_BUILD
Adapt the script to work on Windows by using pystray instead of gi when
building for Windows platform.

While pystray is cross platform, we need to keep gi as python3-pystray
package is not available on Ubuntu Jammy.

So the script is now able to conditionaly use one or another.
Add a .spec file used by pyinstaller to build aw-systray-odoo for
windows platform.
@d-fence d-fence closed this Apr 3, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 3, 2026

Greptile Summary

This PR adds Odoo-specific Windows and Debian packaging support to ActivityWatch, including a new cross-platform system tray app (aw-systray-odoo), Docker-based Linux build environments, a KVM-based Windows build orchestrator, and Inno Setup packaging changes. While the new odoo-setup/ directory additions are largely self-contained, several changes to core shared files introduce critical regressions for standard (non-Odoo) builds.

Critical issues:

  • .gitmodules: The upstream aw-server and aw-server-rust submodule URLs have been replaced with SSH-based Odoo fork URLs (git@github.com:odoo/...). This breaks git submodule update --init for all contributors who do not have SSH access to the Odoo GitHub org, and changes the canonical source of these critical submodules for the entire project.
  • Makefile: The step that moves aw-qt contents to the dist/ root for non-Tauri builds was removed entirely (not preserved alongside the new ODOO_WINDOWS_BUILD branch), causing a regression in all standard Linux/macOS package builds.
  • scripts/package/activitywatch-setup.iss: The Windows Inno Setup installer unconditionally replaces aw-qt.exe with aw-systray-odoo.exe and removes the aw-qt.exe file entry, breaking the standard Windows installer for any non-Odoo build.

Other notable issues:

  • aw.spec still unconditionally builds the aw_server_a PyInstaller analysis even when SKIP_SERVER_PYTHON=true, which will fail if the aw-server submodule is absent.
  • odoo-setup/awbuilder.py contains a hardcoded developer-specific remote path (/Users/moc/) that will fail for other VM users.
  • aw-systray-odoo.py duplicate-instance detection always returns False on Windows.
  • Minor: duplicate package entries in both Dockerfiles, hardcoded version in debian/control.

Confidence Score: 1/5

Not safe to merge — three critical regressions break standard (non-Odoo) builds for all contributors.

Three P0 issues affect shared infrastructure: (1) .gitmodules replaces upstream ActivityWatch submodule URLs with SSH Odoo forks; (2) Makefile regression removes aw-qt dist relocation for all non-Tauri builds; (3) activitywatch-setup.iss unconditionally changes the Windows installer entrypoint, breaking all standard Windows packaging.

.gitmodules, Makefile, and scripts/package/activitywatch-setup.iss all require immediate attention before merge.

Important Files Changed

Filename Overview
.gitmodules Critical: submodule URLs for aw-server and aw-server-rust changed from upstream ActivityWatch HTTPS URLs to SSH-based Odoo private forks, breaking the repo for all non-Odoo contributors.
Makefile Regression: the aw-qt dist relocation step (needed for all non-Tauri builds) was removed entirely and replaced with an ODOO_WINDOWS_BUILD-only branch, breaking standard builds; also has space/tab indentation inconsistency.
scripts/package/activitywatch-setup.iss Critical: main app executable unconditionally changed to aw-systray-odoo.exe and aw-qt.exe removed, breaking standard (non-Odoo) Windows installer builds.
aw.spec aw_server_a PyInstaller analysis is still unconditionally executed even when SKIP_SERVER_PYTHON=true, wasting work and potentially failing if the submodule isn't present.
odoo-setup/awbuilder.py New VM-based Windows build orchestrator using KVM+SSH; contains a hardcoded developer-specific remote path (/Users/moc/) that will break for other VM login users.
odoo-setup/aw-systray-odoo.py New cross-platform system tray application; duplicate-instance check always returns False on Windows, allowing multiple simultaneous instances.
odoo-setup/debian/control New Debian package control file; version is hardcoded to 0.13.2-1 and will need manual updates with each release.
odoo-setup/Dockerfile_jammy New Docker build environment for Ubuntu Jammy; curl is listed twice in the apt-get install command.
odoo-setup/Dockerfile_noble New Docker build environment for Ubuntu Noble; curl and rustup are each listed twice in apt-get install; poetry strategy differs from Jammy Dockerfile.
odoo-setup/aw-systray-odoo.spec PyInstaller spec for building the Windows systray EXE; correctly excludes Linux-only imports.
odoo-setup/buildpackage.sh New shell script to build the Debian package inside Docker; straightforward and functional.
odoo-setup/activitywatch-odoo.desktop New Linux desktop/autostart entry for the Odoo systray app; no issues.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Build Triggered] --> B{TAURI_BUILD?}
    B -- yes --> C[Tauri build path]
    B -- no --> D{ODOO_WINDOWS_BUILD?}
    D -- yes --> E[pip install pystray/pillow/pywin32]
    E --> F[pyinstaller aw-systray-odoo.spec]
    F --> G[cp aw-systray-odoo.exe to dist/activitywatch/]
    D -- no --> H[⚠️ aw-qt relocation step MISSING - regression for standard builds]

    A2[Windows Packaging] --> I{ODOO_WINDOWS_BUILD?}
    I -- yes --> J[awbuilder.py: start KVM VM]
    J --> K[SSH into VM]
    K --> L[Upload activitywatch sources via SCP]
    L --> M[Run make build + make package on VM]
    M --> N[Download .exe artifact]
    N --> O{--pesign?}
    O -- yes --> P[Sign with HSM]
    O -- no --> Q[Output to destdir]
    P --> Q

    A3[Linux Packaging] --> R[buildpackage.sh]
    R --> S[docker build Dockerfile_jammy/noble]
    S --> T[docker run: make build + make package]
    T --> U[unzip Linux build into Debian pkg structure]
    U --> V[Add GNOME extension zip]
    V --> W[dpkg-deb build .deb]
Loading

Comments Outside Diff (3)

  1. Makefile, line 56-68 (link)

    P0 Removal of aw-qt dist relocation breaks standard (non-Odoo) builds

    The original code unconditionally moved aw-qt contents to the dist root for all non-Tauri builds:

    # Move aw-qt to the root of the dist folder
        mv dist/activitywatch/aw-qt aw-qt-tmp
        mv aw-qt-tmp/* dist/activitywatch
        rmdir aw-qt-tmp

    This entire block has been deleted and replaced with only the ODOO_WINDOWS_BUILD branch. For any standard build where TAURI_BUILD != true and ODOO_WINDOWS_BUILD != true, the aw-qt directory is no longer moved to the dist root. This is a regression that will break standard Linux/macOS package builds that rely on aw-qt.exe/aw-qt being at the top level of the dist/activitywatch/ directory.

    The ODOO_WINDOWS_BUILD block should be an additional branch alongside the existing aw-qt relocation, not a replacement for it.

  2. odoo-setup/awbuilder.py, line 683 (link)

    P1 Hardcoded developer-specific remote path

    The remote upload path is hardcoded to a specific developer's home directory:

    remote_path = '/Users/moc/activitywatch.tar.gz'

    /Users/moc/ is a macOS-style home directory for a specific user (moc). This will fail for any other VM login user. It should use the self.login attribute or a more portable approach:

    remote_path = f'/Users/{self.login}/activitywatch.tar.gz'

    or simply:

    remote_path = '~/activitywatch.tar.gz'
  3. odoo-setup/aw-systray-odoo.py, line 357-361 (link)

    P1 Duplicate-instance check always returns False on Windows

    The systray_already_running() function unconditionally returns False on Windows:

    def systray_already_running():
        if IS_WINDOWS:
            return False
        else:
            return len([p for p in psutil.process_iter(...)]) > 1

    This means on Windows, multiple instances of the systray can be started simultaneously — for example, if a user double-clicks the executable or it's triggered again at login. The Linux branch uses psutil to detect this, but psutil is also listed as an excludes in aw-systray-odoo.spec. Consider implementing a Windows-specific single-instance check (e.g., using a named mutex via ctypes/win32event) or at minimum adding a comment that multiple instances are intentionally allowed on Windows.

Reviews (1): Last reviewed commit: "[IMP] aw-server-rust: update aw-server-r..." | Re-trigger Greptile

Comment on lines +9 to 10
url = git@github.com:odoo/aw-server.git
[submodule "aw-watcher-afk"]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P0 Submodule URLs point to Odoo SSH forks instead of upstream ActivityWatch repos

Both aw-server and aw-server-rust submodule URLs have been changed from the official ActivityWatch HTTPS URLs to SSH-based Odoo org forks:

url = git@github.com:odoo/aw-server.git
url = git@github.com:odoo/aw-server-rust.git

This has two significant problems:

  1. SSH vs HTTPS protocol: The upstream repo used HTTPS URLs, which work for anyone. SSH URLs require a properly configured SSH key with access to GitHub. Any contributor cloning this repo without GitHub SSH credentials configured will fail on git submodule update --init.

  2. Odoo-specific forks in the public repo: These point to odoo/aw-server and odoo/aw-server-rust, which are Odoo internal forks. If those repos are private, every contributor to the ActivityWatch project will be unable to fetch the submodules. Even if they are public, they replace the canonical ActivityWatch source, which is unexpected for a community project.

The same issue appears at line 19 for aw-server-rust.

These should either revert to the upstream ActivityWatch HTTPS URLs, or the Odoo-specific overrides should be kept out-of-tree (e.g., via a local .gitconfig override or a separate odoo-specific manifest).

#define MyAppPublisher "ActivityWatch Contributors"
#define MyAppURL "https://activitywatch.net/"
#define MyAppExeName "aw-qt.exe"
#define MyAppExeName "aw-systray-odoo.exe"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P0 Inno Setup script unconditionally switched to aw-systray-odoo.exe

MyAppExeName is now set to aw-systray-odoo.exe unconditionally:

#define MyAppExeName "aw-systray-odoo.exe"

This file is the standard Windows installer script for ActivityWatch. Changing the main app executable to aw-systray-odoo.exe means that any standard (non-Odoo) Windows build will produce a broken installer — it will reference an executable that doesn't exist in the standard package. The original aw-qt.exe entry was also removed from [Files].

This change should be conditionalized (e.g., using Inno Setup preprocessor #ifdef ODOO_BUILD) or kept in a separate, Odoo-specific .iss file that doesn't modify the upstream installer.

Comment on lines +121 to 123
],
)
aw_server_a = build_analysis(
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 aw_server_a analysis is always built even when skip_aw_server_python=True

When SKIP_SERVER_PYTHON=true, the script sets skip_aw_server_python = True and skips creating aws_coll, but the aw_server_a analysis on line 121 is still unconditionally executed:

aw_server_a = build_analysis(
    "aw-server",
    aws_location,
    ...
)

This means PyInstaller still performs the full dependency analysis of the Python server even in the SKIP_SERVER_PYTHON=true case, which defeats the purpose of the flag. If the aw-server Python source is not present (e.g., when building without that submodule), this will also fail with a FileNotFoundError.

The build_analysis call should also be guarded:

if not skip_aw_server_python:
    aw_server_a = build_analysis(
        "aw-server",
        aws_location,
        ...
    )

Comment on lines +9 to +10
python3 python3-dev python3-pip python3-venv curl \
pkgconf libssl-dev libxkbcommon-dev libglib2.0-0 && \
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Duplicate curl package in apt-get install

curl appears twice in the same apt-get install command:

apt-get install -y --no-install-recommends ca-certificates apt-transport-https adduser \
        build-essential zip unzip git curl \
        python3 python3-dev python3-pip python3-venv curl \

While this doesn't cause a build failure, it's a leftover from copy-paste and should be cleaned up.

RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates apt-transport-https adduser \
build-essential zip unzip git curl rustup \
python3 python3-dev python3-pip python3-venv python3-poetry curl rustup \
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Duplicate curl and rustup packages in apt-get install

Both curl and rustup appear twice in the same apt-get install line. Additionally, Dockerfile_noble installs python3-poetry via apt-get but the venv is created manually without using it, while Dockerfile_jammy installs poetry via pip. Consider making them consistent.

Maintainer: Christophe Monniez <moc@odoo.com>
Homepage: https://nightly.odoo.com/aw
Package: activitywatch-odoo
Version: 0.13.2-1
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Hardcoded package version will get out of sync

The version is hardcoded as 0.13.2-1. This will need to be manually updated with every release and will silently drift out of sync with the actual ActivityWatch version. Consider generating this field dynamically in buildpackage.sh using sed or a template mechanism driven by the git tag/version.

Comment on lines +32 to 38
SUBMODULES := $(filter-out aw-server,$(SUBMODULES))
endif
# Odoo-specific Windows build: replaces aw-qt with aw-systray-odoo
ifeq ($(ODOO_WINDOWS_BUILD),true)
SUBMODULES := $(filter-out aw-qt,$(SUBMODULES))
endif
# Include extras if AW_EXTRAS is true
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Inconsistent indentation in new ifeq blocks (spaces vs tabs)

The existing ifeq blocks in this Makefile use tab indentation for commands inside them, but the two new blocks use 4-space indentation. Please align with the file's existing style.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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