--- name: Release 'on': workflow_dispatch: null push: branches: - main concurrency: group: '${{ github.workflow }}' cancel-in-progress: false permissions: contents: read pages: write id-token: write jobs: release-please: runs-on: ubuntu-latest outputs: manifest: '${{ toJSON(steps.rp.outputs) }}' release_created: '${{ steps.rp.outputs.releases_created }}' tag_name: '${{ steps.rp.outputs.tag_name }}' upload_url: '${{ steps.rp.outputs.upload_url }}' steps: - name: Generate App Token uses: tibdex/github-app-token@v2 id: generate-token with: app_id: '${{ secrets.APP_ID }}' private_key: '${{ secrets.APP_PRIVATE_KEY }}' - name: Release Please id: rp uses: googleapis/release-please-action@v4 with: token: '${{ steps.generate-token.outputs.token }}' build: name: Build needs: - release-please if: >- ${{ fromJSON(needs.release-please.outputs.manifest).releases_created == 'true' }} strategy: fail-fast: false matrix: platform: - macos-latest - windows-latest - ubuntu-24.04 runs-on: '${{ matrix.platform }}' permissions: id-token: write attestations: write contents: read steps: - uses: actions/checkout@v5 with: lfs: true - name: Rust setup (mac) if: 'startsWith(matrix.platform, ''macos'')' uses: dtolnay/rust-toolchain@stable with: components: 'rustfmt, clippy' targets: 'aarch64-apple-darwin, x86_64-apple-darwin' - name: Rust setup if: '!startsWith(matrix.platform, ''macos'')' uses: dtolnay/rust-toolchain@stable with: components: 'rustfmt, clippy' - name: Setup rust cache uses: actions/cache@v4 with: path: | target/** !target/*/release/bundle/*/*.dmg !target/*/release/bundle/*/*.app.tar.gz !target/*/release/bundle/*/*.app.tar.gz.sig !target/release/bundle/*/*.dmg !target/release/bundle/*/*.app.tar.gz !target/release/bundle/*/*.app.tar.gz.sig !target/release/bundle/appimage/*.AppImage !target/release/bundle/appimage/*.AppImage.tar.gz !target/release/bundle/appimage/*.AppImage.tar.gz.sig !target/release/bundle/deb/*.deb !target/release/bundle/rpm/*.rpm !target/release/bundle/msi/*.msi !target/release/bundle/msi/*.msi.zip !target/release/bundle/msi/*.msi.zip.sig !target/release/bundle/nsis/*.exe !target/release/bundle/nsis/*.nsis.zip !target/release/bundle/nsis/*.nsis.zip.sig key: '${{ runner.os }}-rust-target-${{ hashFiles(''**/Cargo.lock'') }}' restore-keys: | ${{ runner.os }}-rust-target- - name: Install pnpm uses: pnpm/action-setup@v4 with: version: 10.18.0 - name: Use Node.js uses: actions/setup-node@v5 with: node-version: 20 cache: pnpm - name: Get pnpm store directory id: pnpm-cache shell: bash run: | echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - name: Setup pnpm cache uses: actions/cache@v4 with: path: '${{ steps.pnpm-cache.outputs.STORE_PATH }}' key: '${{ runner.os }}-pnpm-store-${{ hashFiles(''**/pnpm-lock.yaml'') }}' restore-keys: | ${{ runner.os }}-pnpm-store- - name: install dependencies (ubuntu only) if: matrix.platform == 'ubuntu-24.04' run: | sudo apt-get update 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 \ libappindicator3-dev \ librsvg2-dev \ patchelf - name: Install frontend dependencies run: | pnpm install - name: build app (macos) run: >- pnpm run tauri build --target universal-apple-darwin if: 'startsWith(matrix.platform, ''macos'')' env: GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' ENABLE_CODE_SIGNING: '${{ secrets.CSC_LINK }}' APPLE_CERTIFICATE: '${{ secrets.CSC_LINK }}' APPLE_CERTIFICATE_PASSWORD: '${{ secrets.CSC_KEY_PASSWORD }}' APPLE_SIGNING_IDENTITY: '${{ secrets.APPLE_SIGNING_IDENTITY }}' APPLE_ID: '${{ secrets.APPLE_ID }}' APPLE_TEAM_ID: '${{ secrets.APPLE_TEAM_ID }}' APPLE_PASSWORD: '${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}' TAURI_SIGNING_PRIVATE_KEY: '${{ secrets.TAURI_PRIVATE_KEY }}' TAURI_SIGNING_PRIVATE_KEY_PASSWORD: '${{ secrets.TAURI_KEY_PASSWORD }}' SENTRY_RELEASE: 'hackatime-desktop@${{ needs.release-please.outputs.tag_name }}' SENTRY_ENVIRONMENT: 'production' - name: build app run: >- pnpm run tauri build id: build_os if: '!startsWith(matrix.platform, ''macos'')' env: GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' TAURI_SIGNING_PRIVATE_KEY: '${{ secrets.TAURI_PRIVATE_KEY }}' TAURI_SIGNING_PRIVATE_KEY_PASSWORD: '${{ secrets.TAURI_KEY_PASSWORD }}' SENTRY_RELEASE: 'hackatime-desktop@${{ needs.release-please.outputs.tag_name }}' SENTRY_ENVIRONMENT: 'production' - name: Sign files with Trusted Signing if: 'startsWith(matrix.platform, ''windows'')' uses: azure/trusted-signing-action@v0.5.1 with: azure-tenant-id: '${{ secrets.AZURE_TENANT_ID }}' azure-client-id: '${{ secrets.AZURE_CLIENT_ID }}' azure-client-secret: '${{ secrets.AZURE_CLIENT_SECRET }}' endpoint: 'https://eus.codesigning.azure.net/' trusted-signing-account-name: hackclub certificate-profile-name: hackatime-desktop files-folder: '${{ github.workspace }}/src-tauri/target/release/bundle' files-folder-filter: 'msi,exe' files-folder-recurse: true file-digest: SHA256 timestamp-rfc3161: 'http://timestamp.acs.microsoft.com' timestamp-digest: SHA256 - name: Attest macOS binaries if: 'startsWith(matrix.platform, ''macos'')' uses: actions/attest-build-provenance@v3 with: subject-path: | src-tauri/target/*/release/bundle/*/*.dmg src-tauri/target/*/release/bundle/*/*.app.tar.gz src-tauri/target/release/bundle/*/*.dmg src-tauri/target/release/bundle/*/*.app.tar.gz - name: Attest Linux binaries if: 'startsWith(matrix.platform, ''ubuntu'')' uses: actions/attest-build-provenance@v3 with: subject-path: | src-tauri/target/release/bundle/*/*.AppImage src-tauri/target/release/bundle/*/*.AppImage.tar.gz src-tauri/target/release/bundle/*/*.deb src-tauri/target/release/bundle/*/*.rpm - name: Attest Windows binaries if: 'startsWith(matrix.platform, ''windows'')' uses: actions/attest-build-provenance@v3 with: subject-path: | src-tauri/target/release/bundle/msi/*.msi src-tauri/target/release/bundle/msi/*.msi.zip src-tauri/target/release/bundle/nsis/*.exe src-tauri/target/release/bundle/nsis/*.nsis.zip - name: 'upload ${{ matrix.platform }}' uses: actions/upload-artifact@v4 with: name: '${{ matrix.platform }}' path: | src-tauri/target/*/release/bundle/*/*.dmg src-tauri/target/*/release/bundle/*/*.app.tar.gz src-tauri/target/*/release/bundle/*/*.app.tar.gz.sig src-tauri/target/release/bundle/*/*.dmg src-tauri/target/release/bundle/*/*.app.tar.gz src-tauri/target/release/bundle/*/*.app.tar.gz.sig src-tauri/target/release/bundle/*/*.AppImage src-tauri/target/release/bundle/*/*.AppImage.tar.gz src-tauri/target/release/bundle/*/*.AppImage.tar.gz.sig src-tauri/target/release/bundle/*/*.deb src-tauri/target/release/bundle/*/*.rpm src-tauri/target/release/bundle/msi/*.msi src-tauri/target/release/bundle/msi/*.msi.zip src-tauri/target/release/bundle/msi/*.msi.zip.sig src-tauri/target/release/bundle/nsis/*.exe src-tauri/target/release/bundle/nsis/*.nsis.zip src-tauri/target/release/bundle/nsis/*.nsis.zip.sig upload-s3: needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 with: lfs: true - name: Get version from manifest id: get_version run: | version=$(jq -r '."."' .release-please-manifest.json) echo "version=$version" >> $GITHUB_OUTPUT - name: Download all artifacts uses: actions/download-artifact@v5 with: path: artifacts - name: Print directory structure run: ls -R artifacts - name: Generate update manifest id: generate_manifest env: DOWNLOAD_URL_BASE: 'https://desktop.hackatime.hackclub-assets.com' VERSION: '${{ steps.get_version.outputs.version }}' run: > # Read signatures into variables DARWIN_SIGNATURE=$(cat artifacts/macos-latest/universal-apple-darwin/release/bundle/macos/*.app.tar.gz.sig) LINUX_SIGNATURE=$(cat artifacts/ubuntu-24.04/release/bundle/appimage/*.AppImage.tar.gz.sig) WINDOWS_SIGNATURE=$(cat "artifacts/windows-latest/release/bundle/nsis/Hackatime Desktop_${VERSION}_x64-setup.nsis.zip.sig") # Generate JSON file cat > update-manifest.json <