refactor(ci): unify release workflows (#1313) #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Unified release/build pipeline for ActivityWatch. | |
| # | |
| # Triggers: | |
| # - schedule / workflow_dispatch: decide whether to create a new dev prerelease tag | |
| # - push / pull_request: run the normal build matrices | |
| # - tag push: run both build matrices, generate release notes, and publish one draft release | |
| on: | |
| schedule: | |
| - cron: '0 12 * * 4' | |
| workflow_dispatch: | |
| inputs: | |
| release_line: | |
| description: 'Release line to prerelease from' | |
| required: true | |
| default: patch | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| push: | |
| branches: [master] | |
| tags: | |
| - v* | |
| pull_request: | |
| branches: [master] | |
| permissions: | |
| contents: write | |
| actions: read | |
| checks: read | |
| jobs: | |
| preflight: | |
| name: Pre-flight checks | |
| if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: dev-release | |
| cancel-in-progress: false | |
| outputs: | |
| should_release: ${{ steps.preflight.outputs.should_release }} | |
| next_tag: ${{ steps.preflight.outputs.next_tag }} | |
| since_ref: ${{ steps.preflight.outputs.since_ref }} | |
| commits_since_ref: ${{ steps.preflight.outputs.commits_since_ref }} | |
| head_sha: ${{ steps.preflight.outputs.head_sha }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| ref: master | |
| fetch-depth: 0 | |
| - name: Decide whether to create a dev release | |
| id: preflight | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| RELEASE_LINE: ${{ github.event.inputs.release_line || 'patch' }} | |
| run: | | |
| set -euo pipefail | |
| if [ "${GITHUB_EVENT_NAME}" = "schedule" ]; then | |
| ref_epoch=$(date -d "2024-01-04" +%s) | |
| now_epoch=$(date -u +%s) | |
| weeks_since=$(( (now_epoch - ref_epoch) / 604800 )) | |
| if [ $((weeks_since % 2)) -eq 1 ]; then | |
| echo "Skipping this week to keep the cadence biweekly." | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| fi | |
| bump_version() { | |
| local version="$1" release_line="$2" | |
| IFS='.' read -r major minor patch <<< "$version" | |
| if [ "$release_line" = "minor" ]; then | |
| minor=$((minor + 1)) | |
| patch=0 | |
| else | |
| patch=$((patch + 1)) | |
| fi | |
| echo "${major}.${minor}.${patch}" | |
| } | |
| latest_stable=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1 || true) | |
| if [ -z "$latest_stable" ]; then | |
| echo "No stable tag found, refusing to create prerelease tags." | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| next_base=$(bump_version "${latest_stable#v}" "$RELEASE_LINE") | |
| # If a prerelease for a version ahead of next_base already exists, | |
| # continue that release line instead of starting a new one from the | |
| # stable bump. Example: latest_stable=v0.13.2 + patch -> v0.13.3, | |
| # but if v0.14.0b1 exists, produce v0.14.0b2 instead. | |
| highest_prerelease=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+b[0-9]+$' | head -1 || true) | |
| if [ -n "$highest_prerelease" ]; then | |
| hp_base="${highest_prerelease%%b*}" | |
| hp_base="${hp_base#v}" | |
| if [ "$(printf '%s\n%s\n' "$hp_base" "$next_base" | sort -V | tail -1)" = "$hp_base" ] && \ | |
| [ "$hp_base" != "$next_base" ]; then | |
| echo "Existing prerelease $highest_prerelease is ahead of computed v${next_base}; continuing that release line." | |
| next_base="$hp_base" | |
| fi | |
| fi | |
| prerelease_pattern="^v${next_base//./\\.}b[0-9]+$" | |
| last_prerelease=$(git tag --sort=-version:refname | grep -E "$prerelease_pattern" | head -1 || true) | |
| if [ -n "$last_prerelease" ]; then | |
| since_ref="$last_prerelease" | |
| last_prerelease_num=${last_prerelease##*b} | |
| next_tag="v${next_base}b$((last_prerelease_num + 1))" | |
| else | |
| since_ref="$latest_stable" | |
| next_tag="v${next_base}b1" | |
| fi | |
| commits_since_ref=$(git rev-list "${since_ref}..HEAD" --count) | |
| echo "latest_stable=$latest_stable" | |
| echo "last_prerelease=${last_prerelease:-<none>}" | |
| echo "since_ref=$since_ref" | |
| echo "next_tag=$next_tag" | |
| echo "commits_since_ref=$commits_since_ref" | |
| if [ "$commits_since_ref" -eq 0 ]; then | |
| echo "No new commits since $since_ref, skipping dev release." | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| head_sha=$(git rev-parse HEAD) | |
| current_suite_id=$(gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \ | |
| --jq '.check_suite_id' 2>/dev/null || echo "0") | |
| # Auxiliary workflow jobs are not CI signals; exclude them so their | |
| # skipped or failed conclusions do not block the release. | |
| conclusions=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${head_sha}/check-runs" \ | |
| --paginate \ | |
| --slurp 2>/dev/null | jq -r --arg suite "$current_suite_id" ' | |
| [.[].check_runs[]? | |
| | select( | |
| .app.slug == "github-actions" and | |
| ((.check_suite.id | tostring) != $suite) and | |
| (.name | test("^(Dependabot|Auto-merge|greeting|Pre-flight checks|Create dev release tag)$") | not) | |
| ) | |
| | .conclusion] | |
| | unique | |
| | .[] | |
| ' 2>/dev/null || echo unknown) | |
| echo "CI conclusions: $conclusions" | |
| if echo "$conclusions" | grep -qE 'failure|action_required|timed_out|cancelled|startup_failure'; then | |
| echo "CI has failures on HEAD, skipping dev release." | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if echo "$conclusions" | grep -qE 'null|pending'; then | |
| echo "CI is still running on HEAD, skipping dev release." | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if [ -z "$conclusions" ] || [ "$conclusions" = "unknown" ]; then | |
| echo "CI status unavailable on HEAD, skipping dev release." | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if ! echo "$conclusions" | grep -q 'success'; then | |
| echo "No successful CI checks found on HEAD, skipping dev release." | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "should_release=true" >> "$GITHUB_OUTPUT" | |
| echo "next_tag=$next_tag" >> "$GITHUB_OUTPUT" | |
| echo "since_ref=$since_ref" >> "$GITHUB_OUTPUT" | |
| echo "commits_since_ref=$commits_since_ref" >> "$GITHUB_OUTPUT" | |
| echo "head_sha=$head_sha" >> "$GITHUB_OUTPUT" | |
| create-tag: | |
| name: Create dev release tag | |
| needs: preflight | |
| if: needs.preflight.outputs.should_release == 'true' | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: dev-release | |
| cancel-in-progress: false | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.preflight.outputs.head_sha }} | |
| fetch-depth: 1 | |
| token: ${{ secrets.AWBOT_GH_TOKEN }} | |
| - name: Configure git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| - name: Create and push prerelease tag | |
| run: | | |
| set -euo pipefail | |
| tag="${{ needs.preflight.outputs.next_tag }}" | |
| git tag -a "$tag" -m "Development prerelease $tag" | |
| git push origin "$tag" | |
| { | |
| echo "## Dev release created" | |
| echo "" | |
| echo "- Tag: \`$tag\`" | |
| echo "- Changes since: \`${{ needs.preflight.outputs.since_ref }}\`" | |
| echo "- Commits: \`${{ needs.preflight.outputs.commits_since_ref }}\`" | |
| echo "" | |
| echo "The tag-triggered build jobs in this workflow will now build artifacts and create/update the draft prerelease." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| build-qt: | |
| name: Build Qt artifacts | |
| if: github.event_name == 'push' || github.event_name == 'pull_request' | |
| runs-on: ${{ matrix.os }} | |
| continue-on-error: ${{ matrix.experimental }} | |
| env: | |
| AW_EXTRAS: true | |
| MACOSX_DEPLOYMENT_TARGET: 10.9 | |
| defaults: | |
| run: | |
| shell: bash | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-24.04, windows-latest, macos-latest] | |
| python_version: [3.9] | |
| node_version: [22] | |
| skip_rust: [false] | |
| skip_webui: [false] | |
| experimental: [false] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| submodules: 'recursive' | |
| fetch-depth: 0 | |
| - name: Set RELEASE | |
| run: | | |
| echo "RELEASE=${{ startsWith(github.ref_name, 'v') || github.ref_name == 'master' }}" >> "$GITHUB_ENV" | |
| - name: Set tag metadata | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| run: | | |
| echo "VERSION_TAG=${GITHUB_REF_NAME}" >> "$GITHUB_ENV" | |
| - name: Determine and output version | |
| run: | | |
| VERSION_WITH_V=$(bash scripts/package/getversion.sh) | |
| VERSION_NO_V="${VERSION_WITH_V#v}" | |
| echo "VERSION_WITH_V=${VERSION_WITH_V}" >> "$GITHUB_ENV" | |
| echo "========================================" | |
| echo "Build Version Information" | |
| echo "========================================" | |
| echo "GitHub ref: ${{ github.ref }}" | |
| echo "GitHub ref_name: ${{ github.ref_name }}" | |
| echo "Version (with v): ${VERSION_WITH_V}" | |
| echo "Version (no v): ${VERSION_NO_V}" | |
| echo "========================================" | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python_version }} | |
| - name: Set up Node | |
| if: ${{ !matrix.skip_webui }} | |
| uses: actions/setup-node@v6 | |
| 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: Cache node_modules | |
| uses: actions/cache@v5 | |
| if: ${{ !matrix.skip_webui }} | |
| with: | |
| path: aw-server-rust/aw-webui/node_modules | |
| key: ${{ matrix.os }}-node_modules-${{ hashFiles('**/package-lock.json') }} | |
| restore-keys: | | |
| ${{ matrix.os }}-node_modules- | |
| - name: Cache cargo build | |
| uses: actions/cache@v5 | |
| env: | |
| cache-name: cargo-build-target | |
| with: | |
| path: aw-server-rust/target | |
| 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 | |
| sudo apt-get install -y \ | |
| appstream \ | |
| qt5-qmake \ | |
| qtbase5-dev \ | |
| 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.4.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 | |
| - name: Run tests | |
| run: | | |
| source venv/bin/activate || source venv/Scripts/activate | |
| make test SKIP_SERVER_RUST=${{ matrix.skip_rust }} | |
| - 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 | |
| make package SKIP_SERVER_RUST=${{ matrix.skip_rust }} | |
| - name: Package dmg | |
| if: runner.os == 'macOS' | |
| run: | | |
| if [ -n "$APPLE_EMAIL" ]; then | |
| ./scripts/ci/import-macos-p12.sh | |
| fi | |
| source venv/bin/activate | |
| make dist/ActivityWatch.dmg | |
| if [ -n "$APPLE_EMAIL" ]; then | |
| codesign --force --verbose --timestamp -s ${APPLE_PERSONALID} dist/ActivityWatch.dmg | |
| brew install akeru-inc/tap/xcnotary | |
| xcnotary precheck dist/ActivityWatch.app | |
| xcnotary precheck dist/ActivityWatch.dmg | |
| make dist/notarize | |
| fi | |
| mv dist/ActivityWatch.dmg dist/activitywatch-${VERSION_WITH_V}-macos-$(uname -m).dmg | |
| env: | |
| APPLE_EMAIL: ${{ secrets.APPLE_EMAIL }} | |
| APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} | |
| APPLE_PERSONALID: ${{ secrets.APPLE_TEAMID }} | |
| 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: | | |
| ./scripts/package/package-deb.sh | |
| - name: Upload packages | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: builds-${{ matrix.os }}-py${{ matrix.python_version }} | |
| path: dist/activitywatch-*.* | |
| build-tauri: | |
| name: Build Tauri artifacts | |
| if: github.event_name == 'push' || github.event_name == 'pull_request' | |
| runs-on: ${{ matrix.os }} | |
| continue-on-error: ${{ matrix.experimental }} | |
| env: | |
| AW_EXTRAS: true | |
| TAURI_BUILD: true | |
| MACOSX_DEPLOYMENT_TARGET: 10.9 | |
| defaults: | |
| run: | |
| shell: bash | |
| strategy: | |
| fail-fast: false | |
| max-parallel: 5 | |
| matrix: | |
| os: | |
| [ | |
| ubuntu-24.04, | |
| ubuntu-24.04-arm, | |
| windows-latest, | |
| macos-latest, | |
| ] | |
| python_version: [3.9] | |
| node_version: [22] | |
| skip_rust: [false] | |
| skip_webui: [false] | |
| experimental: [false] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| submodules: "recursive" | |
| fetch-depth: 0 | |
| - name: Set environment variables | |
| run: | | |
| echo "RELEASE=${{ startsWith(github.ref_name, 'v') || github.ref_name == 'master' }}" >> "$GITHUB_ENV" | |
| echo "TAURI_BUILD=true" >> "$GITHUB_ENV" | |
| - name: Set tag metadata | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| run: | | |
| echo "VERSION_TAG=${GITHUB_REF_NAME}" >> "$GITHUB_ENV" | |
| - name: Determine and output version | |
| run: | | |
| VERSION_WITH_V=$(bash scripts/package/getversion.sh) | |
| VERSION_NO_V="${VERSION_WITH_V#v}" | |
| echo "VERSION_WITH_V=${VERSION_WITH_V}" >> "$GITHUB_ENV" | |
| echo "========================================" | |
| echo "Build Version Information (Tauri)" | |
| echo "========================================" | |
| echo "GitHub ref: ${{ github.ref }}" | |
| echo "GitHub ref_name: ${{ github.ref_name }}" | |
| echo "Version (with v): ${VERSION_WITH_V}" | |
| echo "Version (no v): ${VERSION_NO_V}" | |
| echo "========================================" | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python_version }} | |
| - name: Set up Node | |
| if: ${{ !matrix.skip_webui }} | |
| uses: actions/setup-node@v6 | |
| 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: Cache node_modules | |
| uses: actions/cache@v5 | |
| if: ${{ !matrix.skip_webui }} | |
| with: | |
| path: | | |
| aw-server-rust/aw-webui/node_modules | |
| aw-tauri/node_modules | |
| key: ${{ matrix.os }}-node_modules-${{ hashFiles('**/package-lock.json') }} | |
| restore-keys: | | |
| ${{ matrix.os }}-node_modules- | |
| - name: Cache cargo build | |
| uses: actions/cache@v5 | |
| env: | |
| cache-name: cargo-build-target | |
| with: | |
| path: | | |
| aw-server-rust/target | |
| aw-tauri/src-tauri/target | |
| 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 | |
| sudo apt-get install -y \ | |
| libgtk-3-dev \ | |
| libayatana-appindicator3-dev \ | |
| librsvg2-dev \ | |
| libsoup-3.0-dev \ | |
| xdg-utils | |
| # Pin WebKit to avoid blank-webview regression on newer ubuntu-24.04 packages. | |
| # See: ActivityWatch/aw-tauri#99 | |
| sudo apt-get install -y \ | |
| libwebkit2gtk-4.1-0=2.44.0-2 \ | |
| libwebkit2gtk-4.1-dev=2.44.0-2 \ | |
| libjavascriptcoregtk-4.1-0=2.44.0-2 \ | |
| libjavascriptcoregtk-4.1-dev=2.44.0-2 \ | |
| gir1.2-javascriptcoregtk-4.1=2.44.0-2 \ | |
| gir1.2-webkit2-4.1=2.44.0-2 | |
| - name: Install dependencies | |
| run: | | |
| if [ "$RUNNER_OS" == "Windows" ]; then | |
| choco install innosetup | |
| fi | |
| pip3 install poetry==1.4.2 | |
| - name: Build | |
| uses: nick-fields/retry@v4 | |
| 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 | |
| - name: Run tests | |
| uses: nick-fields/retry@v4 | |
| 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 }} | |
| - name: Package | |
| run: | | |
| source venv/bin/activate || source venv/Scripts/activate | |
| poetry install | |
| make package SKIP_SERVER_RUST=${{ matrix.skip_rust }} | |
| - name: Package Linux (Tauri bundles) | |
| if: runner.os == 'Linux' | |
| run: | | |
| # aw-tauri's bundler produces .AppImage/.deb/.rpm under | |
| # dist/activitywatch/aw-tauri/ via `make package`. Copy them out with | |
| # versioned, arch-suffixed filenames so they match the | |
| # `dist/activitywatch-*.*` upload pattern below. | |
| ARCH=$(uname -m) | |
| shopt -s nullglob | |
| for ext in AppImage deb rpm; do | |
| files=( dist/activitywatch/aw-tauri/*.${ext} ) | |
| case ${#files[@]} in | |
| 0) continue ;; | |
| 1) cp -v "${files[0]}" "dist/activitywatch-tauri-${VERSION_WITH_V}-linux-${ARCH}.${ext}" ;; | |
| *) echo "ERROR: expected at most 1 .${ext} bundle, found ${#files[@]}" >&2; exit 1 ;; | |
| esac | |
| done | |
| - name: Package dmg | |
| if: runner.os == 'macOS' | |
| run: | | |
| if [ -n "$APPLE_EMAIL" ]; then | |
| ./scripts/ci/import-macos-p12.sh | |
| fi | |
| source venv/bin/activate | |
| make dist/ActivityWatch.dmg | |
| if [ -n "$APPLE_EMAIL" ]; then | |
| codesign --force --verbose --timestamp -s ${APPLE_PERSONALID} dist/ActivityWatch.dmg | |
| brew install akeru-inc/tap/xcnotary | |
| xcnotary precheck dist/ActivityWatch.app | |
| xcnotary precheck dist/ActivityWatch.dmg | |
| make dist/notarize | |
| fi | |
| mv dist/ActivityWatch.dmg dist/activitywatch-tauri-${VERSION_WITH_V}-macos-$(uname -m).dmg | |
| env: | |
| APPLE_EMAIL: ${{ secrets.APPLE_EMAIL }} | |
| APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} | |
| APPLE_PERSONALID: ${{ secrets.APPLE_TEAMID }} | |
| APPLE_TEAMID: ${{ secrets.APPLE_TEAMID }} | |
| CERTIFICATE_MACOS_P12_BASE64: ${{ secrets.CERTIFICATE_MACOS_P12_BASE64 }} | |
| CERTIFICATE_MACOS_P12_PASSWORD: ${{ secrets.CERTIFICATE_MACOS_P12_PASSWORD }} | |
| - name: Upload packages | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: builds-tauri-${{ matrix.os }}-py${{ matrix.python_version }} | |
| path: dist/activitywatch-*.* | |
| release-notes: | |
| name: Generate release notes | |
| if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| submodules: 'recursive' | |
| fetch-depth: 0 | |
| - 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@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install deps | |
| run: | | |
| pip install requests | |
| - name: Generate release notes | |
| run: | | |
| LAST_RELEASE=`STABLE_ONLY=${{ steps.version.outputs.is_stable }} ./scripts/get_latest_release.sh` | |
| ./scripts/build_changelog.py --range "$LAST_RELEASE...${{ steps.version.outputs.full }}" | |
| - name: Rename | |
| run: | | |
| mv changelog.md release_notes.md | |
| - name: Upload release notes | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: release_notes | |
| path: release_notes.md | |
| release: | |
| name: Publish draft release | |
| if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') | |
| needs: [build-qt, build-tauri, release-notes] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: dist | |
| - name: Display structure of downloaded files | |
| run: ls -R | |
| working-directory: dist | |
| - uses: ActivityWatch/check-version-format-action@v2 | |
| id: version | |
| with: | |
| prefix: 'v' | |
| - name: Release | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| draft: true | |
| files: dist/*/activitywatch-*.* | |
| body_path: dist/release_notes/release_notes.md | |
| prerelease: ${{ !(steps.version.outputs.is_stable == 'true') }} |