From 635bbbee882fea516f53739a2cbf8970cea2de2a Mon Sep 17 00:00:00 2001 From: Brayo Date: Mon, 4 Aug 2025 21:18:34 +0300 Subject: [PATCH 01/11] wip --- .github/workflows/build-tauri.yml | 312 +++++++++++++++++++++ .gitmodules | 6 + Makefile | 73 +++-- aw-core | 2 +- aw-notify | 2 +- aw-server-rust | 2 +- aw-tauri | 1 + aw-watcher-afk | 2 +- awatcher | 1 + scripts/changelog_contributors.csv | 2 +- scripts/changelog_contributors_twitter.csv | 2 +- scripts/package/README.txt | 3 + scripts/package/activitywatch-setup.iss | 6 +- scripts/package/build_app.sh | 145 ++++++++++ scripts/package/move-to-aw-modules.sh | 12 + scripts/package/package-all.sh | 5 + scripts/package/package-appimage.sh | 2 +- 17 files changed, 540 insertions(+), 38 deletions(-) create mode 100644 .github/workflows/build-tauri.yml create mode 160000 aw-tauri create mode 160000 awatcher create mode 100644 scripts/package/README.txt create mode 100755 scripts/package/build_app.sh create mode 100644 scripts/package/move-to-aw-modules.sh diff --git a/.github/workflows/build-tauri.yml b/.github/workflows/build-tauri.yml new file mode 100644 index 000000000..f05d838e9 --- /dev/null +++ b/.github/workflows/build-tauri.yml @@ -0,0 +1,312 @@ +name: Build Tauri + +on: + push: + branches: [master] + tags: + - v* + pull_request: + branches: [master] + #release: + # types: [published] + +jobs: + build: + name: ${{ matrix.os }}, py-${{ matrix.python_version }}, node-${{ matrix.node_version }} + runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.experimental }} + env: + # Wether to build and include extras (like aw-notify and aw-watcher-input) + AW_EXTRAS: true + # sets the macOS version target, see: https://users.rust-lang.org/t/compile-rust-binary-for-older-versions-of-mac-osx/38695 + MACOSX_DEPLOYMENT_TARGET: 10.9 + defaults: + run: + shell: bash + strategy: + fail-fast: false + max-parallel: 5 + matrix: + os: + [ + ubuntu-22.04, + ubuntu-22.04-arm, + windows-latest, + macOS-13, + macos-latest, + ] + python_version: [3.9] + node_version: [22] + skip_rust: [false] + skip_webui: [false] + experimental: [false] + tauri_build: [true] + #include: + # - os: ubuntu-latest + # python_version: 3.9 + # node_version: 20 + # experimental: true + + steps: + - uses: actions/checkout@v4 + with: + submodules: "recursive" + fetch-depth: 0 # fetch all branches and tags + + # Build in release mode if: (longer build times) + # - on a tag (release) + # - on the master branch (nightly) + - name: Set environment variables + run: | + echo "RELEASE=${{ startsWith(github.ref_name, 'v') || github.ref_name == 'master' }}" >> $GITHUB_ENV + echo "TAURI_BUILD=${{ matrix.tauri_build }}" >> $GITHUB_ENV + + - name: Set up Python + if: matrix.os != 'macOS-13' + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python_version }} + + # Setup Python version built for older macOS (https://github.com/actions/virtual-environments/issues/1256) + - name: Set up Python for macOS + if: matrix.os == 'macOS-13' + run: | + curl https://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-macosx10.9.pkg -o "python.pkg" + + # Python 3.11+ only has *macos11.pkg, so no more *macosx10.9.pkg + # the 'macos11' naming seems to suggest it only supports macos11 and up, + # but the release page says "for macOS 10.9 and later", + # unclear what the resulting binary compatibility will be. + # + # curl https://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-macos11.pkg -o "python.pkg" + + sudo installer -pkg python.pkg -target / + echo "/Library/Frameworks/Python.framework/Versions/${{ matrix.python_version }}/bin" >> $GITHUB_PATH + "/Applications/Python ${{ matrix.python_version }}/Install Certificates.command" + env: + # Add the patch number to the Python version (for FTP download link) + PYTHON_VERSION: ${{ matrix.python_version }}.13 + + - name: Set up Node + if: ${{ !matrix.skip_webui }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node_version }} + + - name: Set up Rust + if: ${{ !matrix.skip_rust }} + uses: dtolnay/rust-toolchain@master + id: toolchain + with: + toolchain: stable + + - name: Get npm cache dir + id: npm-cache-dir + run: | + echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v4 + name: Cache npm + if: ${{ !matrix.skip_webui }} + env: + cache-name: node + with: + path: ${{ steps.npm-cache-dir.outputs.dir }} + key: ${{ matrix.os }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ matrix.os }}-${{ env.cache-name }}- + + - name: Cache cargo build + uses: actions/cache@v4 + if: ${{ !matrix.skip_rust && (runner.os != 'macOS') }} # cache doesn't seem to behave nicely on macOS, see: https://github.com/ActivityWatch/aw-server-rust/issues/180 + env: + cache-name: cargo-build-target + with: + path: aw-server-rust/target + # key needs to contain rustc_hash due to https://github.com/ActivityWatch/aw-server-rust/issues/180 + key: ${{ matrix.os }}-${{ env.cache-name }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ matrix.os }}-${{ env.cache-name }}-${{ steps.toolchain.outputs.rustc_hash }}- + + - name: Install APT dependencies + if: runner.os == 'Linux' + run: | + sudo apt-get update + # Unsure which of these are actually necessary... + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev \ + libjavascriptcoregtk-4.1-dev libsoup-3.0-dev xdg-utils + + - name: Install dependencies + run: | + if [ "$RUNNER_OS" == "Windows" ]; then + choco install innosetup + fi + pip3 install poetry==1.3.2 + + - name: Build + run: | + python3 -m venv venv + source venv/bin/activate || source venv/Scripts/activate + poetry install + make build SKIP_WEBUI=${{ matrix.skip_webui }} SKIP_SERVER_RUST=${{ matrix.skip_rust }} + pip freeze # output Python packages, useful for debugging dependency versions + + # - name: Build + # uses: nick-fields/retry@v3 + # with: + # timeout_minutes: 60 + # max_attempts: 3 + # shell: bash + # command: | + # python3 -m venv venv + # source venv/bin/activate || source venv/Scripts/activate + # poetry install + # make build SKIP_WEBUI=${{ matrix.skip_webui }} SKIP_SERVER_RUST=${{ matrix.skip_rust }} + # pip freeze # output Python packages, useful for debugging dependency versions + + - name: Run tests + uses: nick-fields/retry@v3 + with: + timeout_minutes: 60 + max_attempts: 3 + shell: bash + command: | + source venv/bin/activate || source venv/Scripts/activate + make test SKIP_SERVER_RUST=${{ matrix.skip_rust }} + + # Don't run integration tests on Windows, doesn't work for some reason + # - name: Run integration tests + # if: runner.os != 'Windows' + # run: | + # source venv/bin/activate || source venv/Scripts/activate + # make test-integration + + - name: Package + run: | + source venv/bin/activate || source venv/Scripts/activate + poetry install # run again to ensure we have the correct version of PyInstaller + make package SKIP_SERVER_RUST=${{ matrix.skip_rust }} + + - name: Package dmg + if: runner.os == 'macOS' + run: | + # Load certificates + # Only load key & sign if env vars for signing exists + if [ -n "$APPLE_EMAIL" ]; then + ./scripts/ci/import-macos-p12.sh + fi + + # Build .app and .dmg + source venv/bin/activate + make dist/ActivityWatch.dmg + + # codesign and notarize + if [ -n "$APPLE_EMAIL" ]; then + codesign --verbose -s ${APPLE_PERSONALID} dist/ActivityWatch.dmg + + # Run prechecks + brew install akeru-inc/tap/xcnotary + xcnotary precheck dist/ActivityWatch.app + xcnotary precheck dist/ActivityWatch.dmg + + # Notarize + make dist/notarize + fi + mv dist/ActivityWatch.dmg dist/activitywatch-$(scripts/package/getversion.sh)-macos-x86_64.dmg + env: + APPLE_EMAIL: ${{ secrets.APPLE_EMAIL }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_PERSONALID: ${{ secrets.APPLE_TEAMID }} # APPLE_PERSONAL_ID == APPLE_TEAM_ID for personal accounts + APPLE_TEAMID: ${{ secrets.APPLE_TEAMID }} + CERTIFICATE_MACOS_P12_BASE64: ${{ secrets.CERTIFICATE_MACOS_P12_BASE64 }} + CERTIFICATE_MACOS_P12_PASSWORD: ${{ secrets.CERTIFICATE_MACOS_P12_PASSWORD }} + + # - name: Package AppImage + # if: startsWith(runner.os, 'linux') + # run: | + # ./scripts/package/package-appimage.sh + + # - name: Package deb + # if: startsWith(runner.os, 'linux') + # run: | + # # The entire process is deferred to a shell file for consistency. + # ./scripts/package/package-deb.sh + + - name: Upload packages + uses: actions/upload-artifact@v4 + with: + name: builds-${{ matrix.os }}-py${{ matrix.python_version }} + path: dist/activitywatch-*.* + + release-notes: + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/v') # only on runs triggered from tag + steps: + - uses: actions/checkout@v4 + with: + submodules: "recursive" + fetch-depth: 0 # fetch all branches and tags + + - uses: ActivityWatch/check-version-format-action@v2 + id: version + with: + prefix: "v" + + - name: Echo version + run: | + echo "${{ steps.version.outputs.full }} (stable: ${{ steps.version.outputs.is_stable }})" + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install deps + run: | + pip install requests + + - name: Generate release notes + run: | + LAST_RELEASE=`STABLE_ONLY=${{ steps.version.output.is_stable }} ./scripts/get_latest_release.sh` + ./scripts/build_changelog.py --range "$LAST_RELEASE...${{ steps.version.outputs.full }}" + + # TODO: Move rename build_changelog and move into there + - name: Rename + run: | + mv changelog.md release_notes.md + + - name: Upload release notes + uses: actions/upload-artifact@v4 + with: + name: release_notes + path: release_notes.md + + release: + needs: [build, release-notes] + if: startsWith(github.ref, 'refs/tags/v') # only run on tag + runs-on: ubuntu-latest + steps: + # Will download all artifacts to path + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + path: dist + + - name: Display structure of downloaded files + run: ls -R + working-directory: dist + + # detect if version tag is stable/beta + - uses: ActivityWatch/check-version-format-action@v2 + id: version + with: + prefix: "v" + + # create a release + - name: Release + uses: softprops/action-gh-release@v1 + with: + draft: true + files: dist/*/activitywatch-*.* + body_path: dist/release_notes/release_notes.md + prerelease: ${{ !(steps.version.outputs.is_stable == 'true') }} # must compare to true, since boolean outputs are actually just strings, and "false" is truthy since it's not empty: https://github.com/actions/runner/issues/1483#issuecomment-994986996 diff --git a/.gitmodules b/.gitmodules index 8e7d1bdaf..aa570caea 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,9 @@ [submodule "aw-watcher-input"] path = aw-watcher-input url = https://github.com/ActivityWatch/aw-watcher-input.git +[submodule "awatcher"] + path = awatcher + url = https://github.com/0xbrayo/awatcher +[submodule "aw-tauri"] + path = aw-tauri + url = https://github.com/activitywatch/aw-tauri diff --git a/Makefile b/Makefile index 67d8fdd27..ef2992d21 100644 --- a/Makefile +++ b/Makefile @@ -11,12 +11,32 @@ SHELL := /usr/bin/env bash -SUBMODULES := aw-core aw-client aw-qt aw-server aw-server-rust aw-watcher-afk aw-watcher-window +OS := $(shell uname -s) + +ifeq ($(TAURI_BUILD),true) + SUBMODULES := aw-core aw-client aw-server aw-server-rust aw-watcher-afk aw-watcher-window aw-tauri +else + SUBMODULES := aw-core aw-client aw-qt aw-server aw-server-rust aw-watcher-afk aw-watcher-window +endif # Exclude aw-server-rust if SKIP_SERVER_RUST is true ifeq ($(SKIP_SERVER_RUST),true) - SUBMODULES := $(filter-out aw-server-rust,$(SUBMODULES)) + SUBMODULES := $(filter-out aw-server-rust,$(SUBMODULES)) endif + +# Build in release mode by default, unless RELEASE=false +ifeq ($(RELEASE), false) + targetdir := debug +else + targetdir := release +endif + + +#Include awatcher on linux +ifeq ($(OS),Linux) + SUBMODULES := $(SUBMODULES) awatcher +endif + # Include extras if AW_EXTRAS is true ifeq ($(AW_EXTRAS),true) SUBMODULES := $(SUBMODULES) aw-notify aw-watcher-input @@ -34,6 +54,10 @@ PACKAGEABLES := $(foreach dir,$(SUBMODULES),$(call has_target,$(dir),package)) LINTABLES := $(foreach dir,$(SUBMODULES),$(call has_target,$(dir),lint)) TYPECHECKABLES := $(foreach dir,$(SUBMODULES),$(call has_target,$(dir),typecheck)) +ifeq ($(TAURI_BUILD),true) + PACKAGEABLES := $(filter-out aw-server-rust aw-server, $(PACKAGEABLES)) +endif + # The `build` target # ------------------ # @@ -44,17 +68,13 @@ build: aw-core/.git # needed due to https://github.com/pypa/setuptools/issues/1963 # would ordinarily be specified in pyproject.toml, but is not respected due to https://github.com/pypa/setuptools/issues/1963 pip install 'setuptools>49.1.1' - @if [ "$(SKIP_SERVER_RUST)" = "false" ]; then \ - if (which cargo); then \ - echo 'Rust found!'; \ - else \ - echo 'ERROR: Rust not found, try running with SKIP_SERVER_RUST=true'; \ - exit 1; \ - fi \ - fi for module in $(SUBMODULES); do \ echo "Building $$module"; \ - make --directory=$$module build SKIP_WEBUI=$(SKIP_WEBUI) || { echo "Error in $$module build"; exit 2; }; \ + 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; }; \ + else \ + make --directory=$$module build SKIP_WEBUI=$(SKIP_WEBUI) || { echo "Error in $$module build"; exit 2; }; \ + fi; \ done # The below is needed due to: https://github.com/ActivityWatch/activitywatch/issues/173 make --directory=aw-client build @@ -62,18 +82,6 @@ build: aw-core/.git # Needed to ensure that the server has the correct version set python -c "import aw_server; print(aw_server.__version__)" - -# Install -# ------- -# -# Installs things like desktop/menu shortcuts. -# Might in the future configure autostart on the system. -install: - make --directory=aw-qt install -# Installation is already happening in the `make build` step currently. -# We might want to change this. -# We should also add some option to install as user (pip3 install --user) - # Update # ------ # @@ -120,15 +128,15 @@ test-integration: # aw-server-python @echo "== Integration testing aw-server ==" @pytest ./scripts/tests/integration_tests.py ./aw-server/tests/ -v - # aw-server-rust - @echo "== Integration testing aw-server-rust ==" - @export PATH=aw-server-rust/target/release:aw-server-rust/target/debug:${PATH}; \ - pytest ./scripts/tests/integration_tests.py ./aw-server/tests/ -v %/.git: git submodule update --init --recursive -ICON := "aw-qt/media/logo/logo.png" +ifeq ($(TAURI_BUILD),true) + ICON := "aw-tauri/aw-webui/media/logo/logo.png" +else + ICON := "aw-tauri/aw-webui/media/logo/logo.png" +endif aw-qt/media/logo/logo.icns: mkdir -p build/MyIcon.iconset @@ -147,7 +155,11 @@ aw-qt/media/logo/logo.icns: mv build/MyIcon.icns aw-qt/media/logo/logo.icns dist/ActivityWatch.app: aw-qt/media/logo/logo.icns +ifeq ($(TAURI_BUILD),true) + scripts/package/build_app.sh +else pyinstaller --clean --noconfirm aw.spec +endif dist/ActivityWatch.dmg: dist/ActivityWatch.app # NOTE: This does not codesign the dmg, that is done in the CI config @@ -164,10 +176,15 @@ package: make --directory=$$dir package; \ cp -r $$dir/dist/$$dir dist/activitywatch; \ done +ifeq ($(TAURI_BUILD),true) + mkdir -p dist/activitywatch/aw-server-rust + cp aw-server-rust/target/$(targetdir)/aw-sync dist/activitywatch/aw-server-rust/aw-sync +else # 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 +endif # Remove problem-causing binaries rm -f dist/activitywatch/libdrm.so.2 # see: https://github.com/ActivityWatch/activitywatch/issues/161 rm -f dist/activitywatch/libharfbuzz.so.0 # see: https://github.com/ActivityWatch/activitywatch/issues/660#issuecomment-959889230 diff --git a/aw-core b/aw-core index 6a58ec59c..e13c33c6d 160000 --- a/aw-core +++ b/aw-core @@ -1 +1 @@ -Subproject commit 6a58ec59c16c57933fce7bad4453449168c83ebd +Subproject commit e13c33c6d7349ae6482c666e267c4d48c475bd79 diff --git a/aw-notify b/aw-notify index 092337a13..bcea3cd1a 160000 --- a/aw-notify +++ b/aw-notify @@ -1 +1 @@ -Subproject commit 092337a1354fdc3da96e08eb5ab87487bc731652 +Subproject commit bcea3cd1a7ffd1ffcb721b952dfa75d11c3bef91 diff --git a/aw-server-rust b/aw-server-rust index a0cdef90c..c6409796f 160000 --- a/aw-server-rust +++ b/aw-server-rust @@ -1 +1 @@ -Subproject commit a0cdef90cf86cd8d2cc89723f5751c1123ae7e2b +Subproject commit c6409796f3859c1c610339682d90e0a03659ccdd diff --git a/aw-tauri b/aw-tauri new file mode 160000 index 000000000..f2ed9e74b --- /dev/null +++ b/aw-tauri @@ -0,0 +1 @@ +Subproject commit f2ed9e74b8ab6726bb589c78758e03649e4942a2 diff --git a/aw-watcher-afk b/aw-watcher-afk index 2dd99ca13..403a331f6 160000 --- a/aw-watcher-afk +++ b/aw-watcher-afk @@ -1 +1 @@ -Subproject commit 2dd99ca13c8ef9b14f891a8ddcc74b123482951e +Subproject commit 403a331f6f626afe18094cf61aeed235b75e537c diff --git a/awatcher b/awatcher new file mode 160000 index 000000000..ac10126be --- /dev/null +++ b/awatcher @@ -0,0 +1 @@ +Subproject commit ac10126be60cba846e01f24fffa454886e5a2d8c diff --git a/scripts/changelog_contributors.csv b/scripts/changelog_contributors.csv index 34efc5543..f268181cd 100644 --- a/scripts/changelog_contributors.csv +++ b/scripts/changelog_contributors.csv @@ -1,3 +1,4 @@ +Oxbrayo vukubrian@gmail.com 2e3s 2e3s19@gmail.com 750 37119951+750@users.noreply.github.com Alwinator 39517491+Alwinator@users.noreply.github.com @@ -25,7 +26,6 @@ aaayushsingh ayush-_-singh@live.com alclary 9044153+alclary@users.noreply.github.com alialamine ali@towbe.com alwinator accounts@alwinschuster.at -brayo-pip 62670517+brayo-pip@users.noreply.github.com chaoky levimanga@gmail.com chengyuhui chengyuhui1@gmail.com davidfraser davidfraser@users.noreply.github.com diff --git a/scripts/changelog_contributors_twitter.csv b/scripts/changelog_contributors_twitter.csv index bbc14c5a2..d0560c107 100644 --- a/scripts/changelog_contributors_twitter.csv +++ b/scripts/changelog_contributors_twitter.csv @@ -1,4 +1,4 @@ -brayo-pip subrupt +0xbrayo subrupt chaoky chaokyer erikbjare erikbjare iloveitaly mike_bianco diff --git a/scripts/package/README.txt b/scripts/package/README.txt new file mode 100644 index 000000000..4a7d64f50 --- /dev/null +++ b/scripts/package/README.txt @@ -0,0 +1,3 @@ +Run move-to-aw-modules.sh to copy all modules except aw-tauri to ~/aw-modules/. Aw-tauri (replaces aw-qt), will use this directory to discover new modules. You can add your own modules and scripts to this directory. The modules should start with the aw- prefix and should not have an extension i.e `.sh`. + +In the aw-tauri folder there is appimage, rpm and deb binaries.Choose the appropriate one for your distro, if in doubt use the appimage works on most linux systems. If you decide on the appimage copy it a permanent folder like ~/bin or /usr/local/bin, since autostart relies on the appimage being in the same location each time. diff --git a/scripts/package/activitywatch-setup.iss b/scripts/package/activitywatch-setup.iss index dc582e597..6177dceaa 100644 --- a/scripts/package/activitywatch-setup.iss +++ b/scripts/package/activitywatch-setup.iss @@ -5,7 +5,7 @@ #define MyAppVersion GetEnv('AW_VERSION') #define MyAppPublisher "ActivityWatch Contributors" #define MyAppURL "https://activitywatch.net/" -#define MyAppExeName "aw-qt.exe" +#define MyAppExeName "aw-tauri.exe" #define RootDir "..\.." #define DistDir "..\..\dist" @@ -30,7 +30,7 @@ PrivilegesRequired=lowest PrivilegesRequiredOverridesAllowed=dialog OutputDir={#DistDir} OutputBaseFilename=activitywatch-setup -SetupIconFile="{#RootDir}\aw-qt\media\logo\logo.ico" +SetupIconFile="{#RootDir}\aw-tauri\src-tauri\icons\icon.ico" UninstallDisplayName={#MyAppName} UninstallDisplayIcon={app}\{#MyAppExeName} Compression=lzma @@ -45,7 +45,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{ Name: "StartMenuEntry" ; Description: "Start ActivityWatch when Windows starts"; GroupDescription: "Windows Startup"; MinVersion: 4,4; [Files] -Source: "{#DistDir}\activitywatch\aw-qt.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "{#DistDir}\activitywatch\aw-tauri.exe"; DestDir: "{app}\aw-tauri"; Flags: ignoreversion Source: "{#DistDir}\activitywatch\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files diff --git a/scripts/package/build_app.sh b/scripts/package/build_app.sh new file mode 100755 index 000000000..d2abf224b --- /dev/null +++ b/scripts/package/build_app.sh @@ -0,0 +1,145 @@ +#!/bin/bash +set -e + +# Configuration +APP_NAME="ActivityWatch" +BUNDLE_ID="net.activitywatch.ActivityWatch" +VERSION="0.1.0" +ICON_PATH="aw-tauri/src-tauri/icons/icon.icns" + +# Check if running on macOS +if [[ "$(uname)" != "Darwin" ]]; then + echo "This script is designed to run on macOS only." + exit 1 +fi + +# Check if dist/activitywatch exists +if [ ! -d "dist/activitywatch" ]; then + echo "Error: dist/activitywatch directory not found. Please build the project first." + exit 1 +fi + +# Check if aw-tauri binary exists +if [ ! -f "dist/activitywatch/aw-tauri" ]; then + echo "Error: aw-tauri binary not found in dist/activitywatch/" + exit 1 +fi + +# Clean previous build +echo "Cleaning previous builds..." +rm -rf "dist/${APP_NAME}.app" +mkdir -p "dist" + +# Create app bundle structure +echo "Creating app bundle structure..." +mkdir -p "dist/${APP_NAME}.app/Contents/"{MacOS,Resources} + +# Copy aw-tauri as the main executable +echo "Copying aw-tauri as main executable..." +cp "dist/activitywatch/aw-tauri" "dist/${APP_NAME}.app/Contents/MacOS/aw-tauri" +chmod +x "dist/${APP_NAME}.app/Contents/MacOS/aw-tauri" + +# Copy all other components to Resources in organized directories +echo "Copying all components to Resources..." +for component in dist/activitywatch/*/; do + if [ -d "$component" ]; then + component_name=$(basename "$component") + echo " Copying $component_name..." + mkdir -p "dist/${APP_NAME}.app/Contents/Resources/$component_name" + cp -r "$component"/* "dist/${APP_NAME}.app/Contents/Resources/$component_name/" + fi +done + +# Make all aw-* executables within Resources executable +echo "Setting executable permissions..." +find "dist/${APP_NAME}.app/Contents/Resources" -type f -name "aw-*" -exec chmod +x {} \; + +# Copy app icon +echo "Copying app icon..." +if [ -f "$ICON_PATH" ]; then + cp "$ICON_PATH" "dist/${APP_NAME}.app/Contents/Resources/icon.icns" +else + echo "Warning: Icon file not found at $ICON_PATH" +fi + +# Create Info.plist +echo "Creating Info.plist..." +cat > "dist/${APP_NAME}.app/Contents/Info.plist" << EOF + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + aw-tauri + CFBundleIconFile + icon.icns + CFBundleIdentifier + ${BUNDLE_ID} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${APP_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + ${VERSION} + CFBundleVersion + ${VERSION} + NSAppleEventsUsageDescription + ActivityWatch needs access to monitor application usage + NSHighResolutionCapable + + NSPrincipalClass + NSApplication + LSMinimumSystemVersion + 10.14 + + +EOF + +# Create PkgInfo file +echo "Creating PkgInfo..." +echo "APPL????" > "dist/${APP_NAME}.app/Contents/PkgInfo" + +# Code signing (if APPLE_PERSONALID is set) +if [ -n "$APPLE_PERSONALID" ]; then + echo "Signing app with identity: $APPLE_PERSONALID" + codesign --deep --force --sign "$APPLE_PERSONALID" "dist/${APP_NAME}.app" + echo "App signing complete." +else + echo "APPLE_PERSONALID environment variable not set. Skipping code signing." +fi + +echo "" +echo "✅ App bundle created successfully at: dist/${APP_NAME}.app" +echo "" +echo "App Bundle Structure:" +echo "├── Contents/" +echo "│ ├── MacOS/" +echo "│ │ └── aw-tauri (main executable)" +echo "│ ├── Resources/" +for dir in "dist/${APP_NAME}.app/Contents/Resources/"*/; do + if [ -d "$dir" ] && [[ $(basename "$dir") == aw-* ]]; then + component_name=$(basename "$dir") + echo "│ │ ├── $component_name/" + # Show the main executable in each component + main_exec=$(find "$dir" -maxdepth 1 -name "aw-*" -type f 2>/dev/null | head -1) + if [ -n "$main_exec" ]; then + exec_name=$(basename "$main_exec") + echo "│ │ │ ├── $exec_name (executable)" + fi + # Show other important files + other_files=$(find "$dir" -maxdepth 2 -name "*.jxa" -o -name "Python" -o -name "*.dylib" 2>/dev/null | wc -l | tr -d ' ') + if [ "$other_files" -gt 0 ]; then + echo "│ │ │ └── ... (+ dependencies & libraries)" + fi + fi +done +echo "│ │ └── icon.icns" +echo "│ ├── Info.plist" +echo "│ └── PkgInfo" +echo "" +echo "All executables are properly packaged and accessible by aw-tauri." +echo "To test the app, run: open dist/${APP_NAME}.app" diff --git a/scripts/package/move-to-aw-modules.sh b/scripts/package/move-to-aw-modules.sh new file mode 100644 index 000000000..178316427 --- /dev/null +++ b/scripts/package/move-to-aw-modules.sh @@ -0,0 +1,12 @@ +#!/usr/bin/bash + +if [[ -n "$XDG_SESSION_TYPE" && "$XDG_SESSION_TYPE" == "wayland" ]]; then + rsync -r . ~/aw-modules/ --exclude=aw-tauri --exclude=aw-server-rust --exclude=awatcher --exclude=move-to-aw-modules.sh --exclude=README.txt + cp ./awatcher/aw-awatcher ~/aw-modules/ + cp aw-server-rust/aw-sync ~/aw-modules/ +else + rsync -r . ~/aw-modules/ --exclude=aw-tauri --exclude=awatcher \ + --exclude=aw-server-rust --exclude=move-to-aw-modules.sh --exclude=README.txt + + cp aw-server-rust/aw-sync ~/aw-modules +fi diff --git a/scripts/package/package-all.sh b/scripts/package/package-all.sh index 967c6a459..32915c774 100755 --- a/scripts/package/package-all.sh +++ b/scripts/package/package-all.sh @@ -41,6 +41,11 @@ function get_arch() { platform=$(get_platform) version=$(get_version) arch=$(get_arch) + +if [[ $platform == "linux" ]]; then + cp scripts/package/README.txt scripts/package/move-to-aw-modules.sh dist/activitywatch +fi + echo "Platform: $platform, arch: $arch, version: $version" function build_zip() { diff --git a/scripts/package/package-appimage.sh b/scripts/package/package-appimage.sh index dd4ece935..32264ecb0 100755 --- a/scripts/package/package-appimage.sh +++ b/scripts/package/package-appimage.sh @@ -18,6 +18,6 @@ DIR="$(dirname "$(readlink -f "${0}")")" chmod a+x ./activitywatch/AppRun # build appimage -./linuxdeploy-x86_64.AppImage --appdir activitywatch --executable ./activitywatch/aw-qt --output appimage --desktop-file ./activitywatch/aw-qt.desktop --icon-file ./activitywatch/media/logo/logo.png --icon-filename activitywatch +./linuxdeploy-x86_64.AppImage --appdir activitywatch --executable ./activitywatch/aw-tauri --output appimage --desktop-file ./activitywatch/aw_tauri/resources/aw_tauri.desktop --icon-file ./activitywatch/aw_tauri/icons/icon.png --icon-filename activitywatch APPIMAGE_FILE=`ls -1 | grep AppImage| grep -i ActivityWatch` cp -v $APPIMAGE_FILE ./dist/activitywatch-linux-x86_64.AppImage From d55cc09fc9664fcf193e87c683e1d39aba33933b Mon Sep 17 00:00:00 2001 From: Brayo Date: Wed, 6 Aug 2025 19:54:49 +0300 Subject: [PATCH 02/11] add arm builds for aw-qt --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e003ca684..d4acb9d08 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-20.04, windows-latest, macOS-13] + os: [ubuntu-20.04, ubuntu-20.04-arm, windows-latest, macOS-13, macos-latest] python_version: [3.9] node_version: [20] skip_rust: [false] @@ -53,14 +53,14 @@ jobs: echo "RELEASE=${{ startsWith(github.ref_name, 'v') || github.ref_name == 'master' }}" >> $GITHUB_ENV - name: Set up Python - if: runner.os != 'macOS' + if: matrix.os != 'macOS-13' uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} # Setup Python version built for older macOS (https://github.com/actions/virtual-environments/issues/1256) - name: Set up Python for macOS - if: runner.os == 'macOS' + if: matrix.os == 'macOS-13' run: | curl https://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-macosx10.9.pkg -o "python.pkg" From 592471d060a8b5cd80d90120e859a3b45c3b7cac Mon Sep 17 00:00:00 2001 From: Brayo Date: Wed, 6 Aug 2025 19:58:29 +0300 Subject: [PATCH 03/11] bump linux runners 20 -> 24 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d4acb9d08..5b06aefdf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-20.04, ubuntu-20.04-arm, windows-latest, macOS-13, macos-latest] + os: [ubuntu-22.04, ubuntu-22.04-arm, windows-latest, macOS-13, macos-latest] python_version: [3.9] node_version: [20] skip_rust: [false] From 6af1c12774ad1400b20408afd16e1226a2218413 Mon Sep 17 00:00:00 2001 From: Brayo Date: Wed, 6 Aug 2025 19:58:48 +0300 Subject: [PATCH 04/11] bump linux runners 20 -> 24 --- .github/workflows/build-tauri.yml | 4 ++-- .github/workflows/build.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-tauri.yml b/.github/workflows/build-tauri.yml index f05d838e9..c5cd02f54 100644 --- a/.github/workflows/build-tauri.yml +++ b/.github/workflows/build-tauri.yml @@ -29,8 +29,8 @@ jobs: matrix: os: [ - ubuntu-22.04, - ubuntu-22.04-arm, + ubuntu-24.04, + ubuntu-24.04-arm, windows-latest, macOS-13, macos-latest, diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5b06aefdf..ab2b4d59b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, ubuntu-22.04-arm, windows-latest, macOS-13, macos-latest] + os: [ubuntu-24.04, ubuntu-24.04-arm, windows-latest, macOS-13, macos-latest] python_version: [3.9] node_version: [20] skip_rust: [false] From f38ba920a3ce38451de4e60636a1c2f1f17c333a Mon Sep 17 00:00:00 2001 From: Brayo Date: Wed, 6 Aug 2025 20:34:30 +0300 Subject: [PATCH 05/11] update qt deps --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ab2b4d59b..f91feea39 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -126,7 +126,8 @@ jobs: # Unsure which of these are actually necessary... sudo apt-get install -y \ appstream \ - qt5-default \ + qt5-qmake \ + qtbase5-dev \ qtwayland5 \ libqt5x11extras5 \ libfontconfig1 \ From 35888f973bade7d25a4d0d1f482eddfde8b11a92 Mon Sep 17 00:00:00 2001 From: Brayo Date: Wed, 6 Aug 2025 21:11:54 +0300 Subject: [PATCH 06/11] unique package names --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f91feea39..7e5c3a88b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -103,9 +103,9 @@ jobs: cache-name: node with: path: ${{ steps.npm-cache-dir.outputs.dir }} - key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + key: ${{ matrix.os }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | - ${{ runner.os }}-${{ env.cache-name }}- + ${{ matrix.os }}-${{ env.cache-name }}- - name: Cache cargo build uses: actions/cache@v4 @@ -224,7 +224,7 @@ jobs: - name: Upload packages uses: actions/upload-artifact@v4 with: - name: builds-${{ runner.os }}-py${{ matrix.python_version }} + name: builds-${{ matrix.os }}-py${{ matrix.python_version }} path: dist/activitywatch-*.* release-notes: From fab02b9e8d972f2765b600ab2bb7112994f7fe6d Mon Sep 17 00:00:00 2001 From: Brayo Date: Thu, 7 Aug 2025 15:06:11 +0300 Subject: [PATCH 07/11] separate builds for tauri and qt --- .github/workflows/build-tauri.yml | 38 +++++------ .github/workflows/build.yml | 4 +- Makefile | 2 +- scripts/package/activitywatch-setup.iss | 6 +- scripts/package/aw-tauri.iss | 63 +++++++++++++++++++ .../{build_app.sh => build_app_tauri.sh} | 0 scripts/package/package-all.sh | 7 ++- scripts/package/package-appimage.sh | 2 +- 8 files changed, 94 insertions(+), 28 deletions(-) create mode 100644 scripts/package/aw-tauri.iss rename scripts/package/{build_app.sh => build_app_tauri.sh} (100%) diff --git a/.github/workflows/build-tauri.yml b/.github/workflows/build-tauri.yml index c5cd02f54..63c56d925 100644 --- a/.github/workflows/build-tauri.yml +++ b/.github/workflows/build-tauri.yml @@ -143,26 +143,26 @@ jobs: fi pip3 install poetry==1.3.2 - - name: Build - run: | - python3 -m venv venv - source venv/bin/activate || source venv/Scripts/activate - poetry install - make build SKIP_WEBUI=${{ matrix.skip_webui }} SKIP_SERVER_RUST=${{ matrix.skip_rust }} - pip freeze # output Python packages, useful for debugging dependency versions - # - name: Build - # uses: nick-fields/retry@v3 - # with: - # timeout_minutes: 60 - # max_attempts: 3 - # shell: bash - # command: | - # python3 -m venv venv - # source venv/bin/activate || source venv/Scripts/activate - # poetry install - # make build SKIP_WEBUI=${{ matrix.skip_webui }} SKIP_SERVER_RUST=${{ matrix.skip_rust }} - # pip freeze # output Python packages, useful for debugging dependency versions + # run: | + # python3 -m venv venv + # source venv/bin/activate || source venv/Scripts/activate + # poetry install + # make build SKIP_WEBUI=${{ matrix.skip_webui }} SKIP_SERVER_RUST=${{ matrix.skip_rust }} + # pip freeze # output Python packages, useful for debugging dependency versions + + - name: Build + uses: nick-fields/retry@v3 + with: + timeout_minutes: 60 + max_attempts: 3 + shell: bash + command: | + python3 -m venv venv + source venv/bin/activate || source venv/Scripts/activate + poetry install + make build SKIP_WEBUI=${{ matrix.skip_webui }} SKIP_SERVER_RUST=${{ matrix.skip_rust }} + pip freeze # output Python packages, useful for debugging dependency versions - name: Run tests uses: nick-fields/retry@v3 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7e5c3a88b..e83e485d8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,9 +26,9 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-24.04, ubuntu-24.04-arm, windows-latest, macOS-13, macos-latest] + os: [ubuntu-24.04, windows-latest, macOS-13, macos-latest] python_version: [3.9] - node_version: [20] + node_version: [22] skip_rust: [false] skip_webui: [false] experimental: [false] diff --git a/Makefile b/Makefile index ef2992d21..8ba0af15d 100644 --- a/Makefile +++ b/Makefile @@ -156,7 +156,7 @@ aw-qt/media/logo/logo.icns: dist/ActivityWatch.app: aw-qt/media/logo/logo.icns ifeq ($(TAURI_BUILD),true) - scripts/package/build_app.sh + scripts/package/build_app_tauri.sh else pyinstaller --clean --noconfirm aw.spec endif diff --git a/scripts/package/activitywatch-setup.iss b/scripts/package/activitywatch-setup.iss index 6177dceaa..dc582e597 100644 --- a/scripts/package/activitywatch-setup.iss +++ b/scripts/package/activitywatch-setup.iss @@ -5,7 +5,7 @@ #define MyAppVersion GetEnv('AW_VERSION') #define MyAppPublisher "ActivityWatch Contributors" #define MyAppURL "https://activitywatch.net/" -#define MyAppExeName "aw-tauri.exe" +#define MyAppExeName "aw-qt.exe" #define RootDir "..\.." #define DistDir "..\..\dist" @@ -30,7 +30,7 @@ PrivilegesRequired=lowest PrivilegesRequiredOverridesAllowed=dialog OutputDir={#DistDir} OutputBaseFilename=activitywatch-setup -SetupIconFile="{#RootDir}\aw-tauri\src-tauri\icons\icon.ico" +SetupIconFile="{#RootDir}\aw-qt\media\logo\logo.ico" UninstallDisplayName={#MyAppName} UninstallDisplayIcon={app}\{#MyAppExeName} Compression=lzma @@ -45,7 +45,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{ Name: "StartMenuEntry" ; Description: "Start ActivityWatch when Windows starts"; GroupDescription: "Windows Startup"; MinVersion: 4,4; [Files] -Source: "{#DistDir}\activitywatch\aw-tauri.exe"; DestDir: "{app}\aw-tauri"; Flags: ignoreversion +Source: "{#DistDir}\activitywatch\aw-qt.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "{#DistDir}\activitywatch\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files diff --git a/scripts/package/aw-tauri.iss b/scripts/package/aw-tauri.iss new file mode 100644 index 000000000..e454883ce --- /dev/null +++ b/scripts/package/aw-tauri.iss @@ -0,0 +1,63 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "ActivityWatch" +#define MyAppVersion GetEnv('AW_VERSION') + "-tauri" +#define MyAppPublisher "ActivityWatch Contributors" +#define MyAppURL "https://activitywatch.net/" +#define MyAppExeName "aw-tauri.exe" +#define RootDir "..\.." +#define DistDir "..\..\dist" + +#pragma verboselevel 9 + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +; NOTE: the double {{ are used to escape the { character (needed for the AppId) +AppId={{983D0855-08C8-46BD-AEFB-3924581C6703} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL="https://github.com/ActivityWatch/activitywatch/issues" +AppUpdatesURL="https://github.com/ActivityWatch/activitywatch/releases" +DefaultDirName={autopf}\{#MyAppName} +DisableProgramGroupPage=yes +; Uncomment the following line to run in non administrative install mode (install for current user only.) +PrivilegesRequired=lowest +PrivilegesRequiredOverridesAllowed=dialog +OutputDir={#DistDir} +OutputBaseFilename=activitywatch-setup +SetupIconFile="{#RootDir}\aw-tauri\src-tauri\icons\icon.ico" +UninstallDisplayName={#MyAppName} +UninstallDisplayIcon={app}\{#MyAppExeName} +Compression=lzma +SolidCompression=yes +WizardStyle=modern + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked +Name: "StartMenuEntry" ; Description: "Start ActivityWatch when Windows starts"; GroupDescription: "Windows Startup"; MinVersion: 4,4; + +[Files] +Source: "{#DistDir}\activitywatch\aw-tauri.exe"; DestDir: "{app}\aw-tauri"; Flags: ignoreversion +Source: "{#DistDir}\activitywatch\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + +[Icons] +Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon +Name: "{userstartup}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: StartMenuEntry; + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent + +; Removes the previously installed version before installing the new one +; NOTE: Doesn't work? And also discouraged by the docs +;[InstallDelete] +;Type: filesandordirs; Name: "{app}\" diff --git a/scripts/package/build_app.sh b/scripts/package/build_app_tauri.sh similarity index 100% rename from scripts/package/build_app.sh rename to scripts/package/build_app_tauri.sh diff --git a/scripts/package/package-all.sh b/scripts/package/package-all.sh index 32915c774..c386b28c3 100755 --- a/scripts/package/package-all.sh +++ b/scripts/package/package-all.sh @@ -75,7 +75,11 @@ function build_setup() { # Windows installer version should not include 'v' prefix, see: https://github.com/microsoft/winget-pkgs/pull/17564 version_no_prefix="$(echo $version | sed -e 's/^v//')" - env AW_VERSION=$version_no_prefix "$innosetupdir/iscc.exe" scripts/package/activitywatch-setup.iss + if [[ $TAURI_BUILD == "true" ]]; then + env AW_VERSION=$version_no_prefix "$innosetupdir/iscc.exe" scripts/package/aw-tauri.iss + else + env AW_VERSION=$version_no_prefix "$innosetupdir/iscc.exe" scripts/package/activitywatch-setup.iss + fi mv dist/activitywatch-setup.exe dist/$filename echo "Setup built!" } @@ -90,4 +94,3 @@ echo "-------------------------------------" echo "Contents of ./dist" ls -l dist echo "-------------------------------------" - diff --git a/scripts/package/package-appimage.sh b/scripts/package/package-appimage.sh index 32264ecb0..dd4ece935 100755 --- a/scripts/package/package-appimage.sh +++ b/scripts/package/package-appimage.sh @@ -18,6 +18,6 @@ DIR="$(dirname "$(readlink -f "${0}")")" chmod a+x ./activitywatch/AppRun # build appimage -./linuxdeploy-x86_64.AppImage --appdir activitywatch --executable ./activitywatch/aw-tauri --output appimage --desktop-file ./activitywatch/aw_tauri/resources/aw_tauri.desktop --icon-file ./activitywatch/aw_tauri/icons/icon.png --icon-filename activitywatch +./linuxdeploy-x86_64.AppImage --appdir activitywatch --executable ./activitywatch/aw-qt --output appimage --desktop-file ./activitywatch/aw-qt.desktop --icon-file ./activitywatch/media/logo/logo.png --icon-filename activitywatch APPIMAGE_FILE=`ls -1 | grep AppImage| grep -i ActivityWatch` cp -v $APPIMAGE_FILE ./dist/activitywatch-linux-x86_64.AppImage From be513525554d3ed8b0cd9af5fb01a5d7623e731c Mon Sep 17 00:00:00 2001 From: Brayo Date: Fri, 8 Aug 2025 09:37:17 +0300 Subject: [PATCH 08/11] try enabling cache on macOS --- .github/workflows/build-tauri.yml | 2 +- .github/workflows/build.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-tauri.yml b/.github/workflows/build-tauri.yml index 63c56d925..62b399f2f 100644 --- a/.github/workflows/build-tauri.yml +++ b/.github/workflows/build-tauri.yml @@ -118,7 +118,7 @@ jobs: - name: Cache cargo build uses: actions/cache@v4 - if: ${{ !matrix.skip_rust && (runner.os != 'macOS') }} # cache doesn't seem to behave nicely on macOS, see: https://github.com/ActivityWatch/aw-server-rust/issues/180 + # if: ${{ !matrix.skip_rust && (runner.os != 'macOS') }} # cache doesn't seem to behave nicely on macOS, see: https://github.com/ActivityWatch/aw-server-rust/issues/180 env: cache-name: cargo-build-target with: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e83e485d8..9f610955d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -109,15 +109,15 @@ jobs: - name: Cache cargo build uses: actions/cache@v4 - if: ${{ !matrix.skip_rust && (runner.os != 'macOS') }} # cache doesn't seem to behave nicely on macOS, see: https://github.com/ActivityWatch/aw-server-rust/issues/180 + # if: ${{ !matrix.skip_rust && (runner.os != 'macOS') }} # cache doesn't seem to behave nicely on macOS, see: https://github.com/ActivityWatch/aw-server-rust/issues/180 env: cache-name: cargo-build-target with: path: aw-server-rust/target # key needs to contain rustc_hash due to https://github.com/ActivityWatch/aw-server-rust/issues/180 - key: ${{ runner.os }}-${{ env.cache-name }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }} + key: ${{ matrix.os }}-${{ env.cache-name }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.cache-name }}-${{ steps.toolchain.outputs.rustc_hash }}- + ${{ matrix.os }}-${{ env.cache-name }}-${{ steps.toolchain.outputs.rustc_hash }}- - name: Install APT dependencies if: runner.os == 'Linux' From 7c07d6dc4a3bd9e896009b76ec0c523ffe615512 Mon Sep 17 00:00:00 2001 From: Brayo Date: Fri, 8 Aug 2025 10:38:03 +0300 Subject: [PATCH 09/11] Update scripts/package/move-to-aw-modules.sh Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> --- Makefile | 8 ++------ scripts/package/README.txt | 2 +- scripts/package/move-to-aw-modules.sh | 2 +- scripts/package/package-all.sh | 2 +- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 8ba0af15d..22d800cb6 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ endif # Exclude aw-server-rust if SKIP_SERVER_RUST is true ifeq ($(SKIP_SERVER_RUST),true) - SUBMODULES := $(filter-out aw-server-rust,$(SUBMODULES)) + SUBMODULES := $(filter-out aw-server-rust,$(SUBMODULES)) endif # Build in release mode by default, unless RELEASE=false @@ -132,11 +132,7 @@ test-integration: %/.git: git submodule update --init --recursive -ifeq ($(TAURI_BUILD),true) - ICON := "aw-tauri/aw-webui/media/logo/logo.png" -else - ICON := "aw-tauri/aw-webui/media/logo/logo.png" -endif +ICON := "aw-qt/media/logo/logo.png" aw-qt/media/logo/logo.icns: mkdir -p build/MyIcon.iconset diff --git a/scripts/package/README.txt b/scripts/package/README.txt index 4a7d64f50..009c78492 100644 --- a/scripts/package/README.txt +++ b/scripts/package/README.txt @@ -1,3 +1,3 @@ Run move-to-aw-modules.sh to copy all modules except aw-tauri to ~/aw-modules/. Aw-tauri (replaces aw-qt), will use this directory to discover new modules. You can add your own modules and scripts to this directory. The modules should start with the aw- prefix and should not have an extension i.e `.sh`. -In the aw-tauri folder there is appimage, rpm and deb binaries.Choose the appropriate one for your distro, if in doubt use the appimage works on most linux systems. If you decide on the appimage copy it a permanent folder like ~/bin or /usr/local/bin, since autostart relies on the appimage being in the same location each time. +In the aw-tauri folder there is appimage, rpm and deb binaries. Choose the appropriate one for your distro, if in doubt use the appimage works on most linux systems. If you decide on the appimage copy it a permanent folder like ~/bin or /usr/local/bin, since autostart relies on the appimage being in the same location each time. diff --git a/scripts/package/move-to-aw-modules.sh b/scripts/package/move-to-aw-modules.sh index 178316427..bae0565d2 100644 --- a/scripts/package/move-to-aw-modules.sh +++ b/scripts/package/move-to-aw-modules.sh @@ -1,7 +1,7 @@ #!/usr/bin/bash if [[ -n "$XDG_SESSION_TYPE" && "$XDG_SESSION_TYPE" == "wayland" ]]; then - rsync -r . ~/aw-modules/ --exclude=aw-tauri --exclude=aw-server-rust --exclude=awatcher --exclude=move-to-aw-modules.sh --exclude=README.txt + rsync -a . ~/aw-modules/ --exclude=aw-tauri --exclude=aw-server-rust --exclude=awatcher --exclude=move-to-aw-modules.sh --exclude=README.txt cp ./awatcher/aw-awatcher ~/aw-modules/ cp aw-server-rust/aw-sync ~/aw-modules/ else diff --git a/scripts/package/package-all.sh b/scripts/package/package-all.sh index c386b28c3..cb949a718 100755 --- a/scripts/package/package-all.sh +++ b/scripts/package/package-all.sh @@ -42,7 +42,7 @@ platform=$(get_platform) version=$(get_version) arch=$(get_arch) -if [[ $platform == "linux" ]]; then +if [[ $platform == "linux" && $TAURI_BUILD == "true" ]]; then cp scripts/package/README.txt scripts/package/move-to-aw-modules.sh dist/activitywatch fi From 771e99ecdbc4c53e7b33da96335e10ec0b6e7796 Mon Sep 17 00:00:00 2001 From: Brayo Date: Sat, 16 Aug 2025 19:49:51 +0300 Subject: [PATCH 10/11] Replace fork of awatcher submodule with the actual repo --- .gitmodules | 6 +++--- awatcher | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index aa570caea..e5e7a8947 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,9 +25,9 @@ [submodule "aw-watcher-input"] path = aw-watcher-input url = https://github.com/ActivityWatch/aw-watcher-input.git -[submodule "awatcher"] - path = awatcher - url = https://github.com/0xbrayo/awatcher [submodule "aw-tauri"] path = aw-tauri url = https://github.com/activitywatch/aw-tauri +[submodule "awatcher"] + path = awatcher + url = https://github.com/2e3s/awatcher diff --git a/awatcher b/awatcher index ac10126be..0cdf79f85 160000 --- a/awatcher +++ b/awatcher @@ -1 +1 @@ -Subproject commit ac10126be60cba846e01f24fffa454886e5a2d8c +Subproject commit 0cdf79f857a65d5f43329c46a7039a166d280d7e From fcd408f4998ab243abd106920f44f8d18fbbf931 Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 20 Feb 2026 16:11:11 +0000 Subject: [PATCH 11/11] fix: address review comments for aw-tauri support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - aw-tauri.iss: rename app to "ActivityWatch Tauri" to avoid collision with aw-qt installer (same DefaultDirName, same AppName previously) - aw-tauri.iss: uncomment AppVerName, use plain version without "-tauri" suffix - Makefile: make aw-qt icon dependency conditional on TAURI_BUILD so the aw-qt icon build step is skipped when building with Tauri - move-to-aw-modules.sh: use consistent rsync -a flags in both Wayland and X11 paths; deduplicate excludes into a shared variable - README.txt: fix typos ("copy it to", "AppImage", "Linux" capitalized) - build-tauri.yml, build.yml: fix typo "Wether" → "Whether" --- .github/workflows/build-tauri.yml | 2 +- .github/workflows/build.yml | 2 +- Makefile | 3 ++- scripts/package/README.txt | 2 +- scripts/package/aw-tauri.iss | 7 ++++--- scripts/package/move-to-aw-modules.sh | 13 ++++++------- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build-tauri.yml b/.github/workflows/build-tauri.yml index 62b399f2f..e6dcea2b9 100644 --- a/.github/workflows/build-tauri.yml +++ b/.github/workflows/build-tauri.yml @@ -16,7 +16,7 @@ jobs: runs-on: ${{ matrix.os }} continue-on-error: ${{ matrix.experimental }} env: - # Wether to build and include extras (like aw-notify and aw-watcher-input) + # Whether to build and include extras (like aw-notify and aw-watcher-input) AW_EXTRAS: true # sets the macOS version target, see: https://users.rust-lang.org/t/compile-rust-binary-for-older-versions-of-mac-osx/38695 MACOSX_DEPLOYMENT_TARGET: 10.9 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9f610955d..f3e59585d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: runs-on: ${{ matrix.os }} continue-on-error: ${{ matrix.experimental }} env: - # Wether to build and include extras (like aw-notify and aw-watcher-input) + # Whether to build and include extras (like aw-notify and aw-watcher-input) AW_EXTRAS: true # sets the macOS version target, see: https://users.rust-lang.org/t/compile-rust-binary-for-older-versions-of-mac-osx/38695 MACOSX_DEPLOYMENT_TARGET: 10.9 diff --git a/Makefile b/Makefile index 22d800cb6..c2c25d22e 100644 --- a/Makefile +++ b/Makefile @@ -150,10 +150,11 @@ aw-qt/media/logo/logo.icns: rm -R build/MyIcon.iconset mv build/MyIcon.icns aw-qt/media/logo/logo.icns -dist/ActivityWatch.app: aw-qt/media/logo/logo.icns ifeq ($(TAURI_BUILD),true) +dist/ActivityWatch.app: scripts/package/build_app_tauri.sh else +dist/ActivityWatch.app: aw-qt/media/logo/logo.icns pyinstaller --clean --noconfirm aw.spec endif diff --git a/scripts/package/README.txt b/scripts/package/README.txt index 009c78492..1b934d2c6 100644 --- a/scripts/package/README.txt +++ b/scripts/package/README.txt @@ -1,3 +1,3 @@ Run move-to-aw-modules.sh to copy all modules except aw-tauri to ~/aw-modules/. Aw-tauri (replaces aw-qt), will use this directory to discover new modules. You can add your own modules and scripts to this directory. The modules should start with the aw- prefix and should not have an extension i.e `.sh`. -In the aw-tauri folder there is appimage, rpm and deb binaries. Choose the appropriate one for your distro, if in doubt use the appimage works on most linux systems. If you decide on the appimage copy it a permanent folder like ~/bin or /usr/local/bin, since autostart relies on the appimage being in the same location each time. +In the aw-tauri folder there are AppImage, RPM, and DEB binaries. Choose the appropriate one for your distro; if in doubt, the AppImage works on most Linux systems. If you decide on the AppImage, copy it to a permanent folder like ~/bin or /usr/local/bin, since autostart relies on the AppImage being in the same location each time. diff --git a/scripts/package/aw-tauri.iss b/scripts/package/aw-tauri.iss index e454883ce..daad157b2 100644 --- a/scripts/package/aw-tauri.iss +++ b/scripts/package/aw-tauri.iss @@ -1,8 +1,8 @@ ; Script generated by the Inno Setup Script Wizard. ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! -#define MyAppName "ActivityWatch" -#define MyAppVersion GetEnv('AW_VERSION') + "-tauri" +#define MyAppName "ActivityWatch Tauri" +#define MyAppVersion GetEnv('AW_VERSION') #define MyAppPublisher "ActivityWatch Contributors" #define MyAppURL "https://activitywatch.net/" #define MyAppExeName "aw-tauri.exe" @@ -18,12 +18,13 @@ AppId={{983D0855-08C8-46BD-AEFB-3924581C6703} AppName={#MyAppName} AppVersion={#MyAppVersion} -;AppVerName={#MyAppName} {#MyAppVersion} +AppVerName={#MyAppName} {#MyAppVersion} AppPublisher={#MyAppPublisher} AppPublisherURL={#MyAppURL} AppSupportURL="https://github.com/ActivityWatch/activitywatch/issues" AppUpdatesURL="https://github.com/ActivityWatch/activitywatch/releases" DefaultDirName={autopf}\{#MyAppName} +DefaultGroupName={#MyAppName} DisableProgramGroupPage=yes ; Uncomment the following line to run in non administrative install mode (install for current user only.) PrivilegesRequired=lowest diff --git a/scripts/package/move-to-aw-modules.sh b/scripts/package/move-to-aw-modules.sh index bae0565d2..9545edec2 100644 --- a/scripts/package/move-to-aw-modules.sh +++ b/scripts/package/move-to-aw-modules.sh @@ -1,12 +1,11 @@ #!/usr/bin/bash +EXCLUDES="--exclude=aw-tauri --exclude=aw-server-rust --exclude=awatcher --exclude=move-to-aw-modules.sh --exclude=README.txt" + if [[ -n "$XDG_SESSION_TYPE" && "$XDG_SESSION_TYPE" == "wayland" ]]; then - rsync -a . ~/aw-modules/ --exclude=aw-tauri --exclude=aw-server-rust --exclude=awatcher --exclude=move-to-aw-modules.sh --exclude=README.txt + rsync -a . ~/aw-modules/ $EXCLUDES cp ./awatcher/aw-awatcher ~/aw-modules/ - cp aw-server-rust/aw-sync ~/aw-modules/ -else - rsync -r . ~/aw-modules/ --exclude=aw-tauri --exclude=awatcher \ - --exclude=aw-server-rust --exclude=move-to-aw-modules.sh --exclude=README.txt - - cp aw-server-rust/aw-sync ~/aw-modules +else + rsync -a . ~/aw-modules/ $EXCLUDES fi +cp aw-server-rust/aw-sync ~/aw-modules/