hackatime-desktop/.github/workflows/release.yaml
2025-10-09 15:48:53 -04:00

330 lines
No EOL
13 KiB
YAML

---
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://pub-d35fbe65a5b5426bb6d62ff02a8c7d03.r2.dev'
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 <<EOF
{
"version": "${VERSION}",
"notes": "A new version of Hackatime is out!",
"pub_date": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
"platforms": {
"darwin-x86_64": {
"signature": "${DARWIN_SIGNATURE}",
"url": "${DOWNLOAD_URL_BASE}/releases/${VERSION}/macos-latest/universal-apple-darwin/release/bundle/macos/Hackatime%20Desktop.app.tar.gz",
"install_urls": [
"${DOWNLOAD_URL_BASE}/releases/${VERSION}/macos-latest/universal-apple-darwin/release/bundle/dmg/Hackatime%20Desktop_${VERSION}_universal.dmg"
]
},
"darwin-aarch64": {
"signature": "${DARWIN_SIGNATURE}",
"url": "${DOWNLOAD_URL_BASE}/releases/${VERSION}/macos-latest/universal-apple-darwin/release/bundle/macos/Hackatime%20Desktop.app.tar.gz",
"install_urls": [
"${DOWNLOAD_URL_BASE}/releases/${VERSION}/macos-latest/universal-apple-darwin/release/bundle/macos/Hackatime%20Desktop.app.tar.gz"
]
},
"linux-x86_64": {
"signature": "${LINUX_SIGNATURE}",
"url": "${DOWNLOAD_URL_BASE}/releases/${VERSION}/ubuntu-24.04/release/bundle/appimage/Hackatime%20Desktop_${VERSION}_amd64.AppImage.tar.gz",
"install_urls": [
"${DOWNLOAD_URL_BASE}/releases/${VERSION}/ubuntu-24.04/release/bundle/deb/Hackatime%20Desktop_${VERSION}_amd64.deb",
"${DOWNLOAD_URL_BASE}/releases/${VERSION}/ubuntu-24.04/release/bundle/appimage/Hackatime%20Desktop_${VERSION}_amd64.AppImage",
"${DOWNLOAD_URL_BASE}/releases/${VERSION}/ubuntu-24.04/release/bundle/rpm/Hackatime%20Desktop-${VERSION}-1.x86_64.rpm"
]
},
"windows-x86_64": {
"signature": "${WINDOWS_SIGNATURE}",
"url": "${DOWNLOAD_URL_BASE}/releases/${VERSION}/windows-latest/release/bundle/nsis/Hackatime%20Desktop_${VERSION}_x64-setup.nsis.zip",
"install_urls": [
"${DOWNLOAD_URL_BASE}/releases/${VERSION}/windows-latest/release/bundle/nsis/Hackatime%20Desktop_${VERSION}_x64-setup.exe"
]
}
}
}
EOF
- name: Upload artifacts to R2
uses: ryand56/r2-upload-action@latest
with:
r2-account-id: '${{ secrets.CLOUDFLARE_ACCOUNT_ID }}'
r2-access-key-id: '${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}'
r2-secret-access-key: '${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}'
r2-bucket: hackclub-hackatime-desktop
destination-dir: 'releases/${{ steps.get_version.outputs.version }}'
source-dir: artifacts
keep-file-fresh: true
- name: Upload update manifest to R2
uses: ryand56/r2-upload-action@latest
with:
r2-account-id: '${{ secrets.CLOUDFLARE_ACCOUNT_ID }}'
r2-access-key-id: '${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}'
r2-secret-access-key: '${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}'
r2-bucket: hackclub-hackatime-desktop
source-dir: update-manifest.json
destination-dir: ./
keep-file-fresh: true