Skip to content

updated

updated #697

Workflow file for this run

name: Build
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
matrix:
os: [ubuntu-20.04, windows-latest, macOS-12]
python_version: [3.9]
node_version: [20]
skip_rust: [false]
skip_webui: [false]
experimental: [false]
#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 RELEASE
run: |
echo "RELEASE=${{ startsWith(github.ref_name, 'v') || github.ref_name == 'master' }}" >> $GITHUB_ENV
- name: Set up Python
if: runner.os != 'macOS'
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'
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: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.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: ${{ runner.os }}-${{ env.cache-name }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.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 \
appstream \
qt5-default \
qtwayland5 \
libqt5x11extras5 \
libfontconfig1 \
libxcb1 \
libfontconfig1-dev \
libfreetype6-dev \
libx11-dev \
libxcursor-dev \
libxext-dev \
libxfixes-dev \
libxft-dev \
libxi-dev \
libxrandr-dev \
libxrender-dev
- 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: Run tests
run: |
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-${{ runner.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