Skip to content

.github/workflows/desktop_cd.yaml #987

.github/workflows/desktop_cd.yaml

.github/workflows/desktop_cd.yaml #987

Workflow file for this run

# https://docs.crabnebula.dev/cloud/ci/tauri-v2-workflow/
on:
workflow_dispatch:
inputs:
channel:
description: "Release channel"
required: true
type: choice
options:
- staging
- stable
publish:
description: "Publish to Crabnebula and create GitHub release (ignored for staging)"
type: boolean
default: true
version:
description: "Optional explicit version for stable releases"
required: false
type: string
default: ""
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.channel }}
cancel-in-progress: true
env:
CN_APPLICATION: "fastrepl/hyprnote2"
RELEASE_CHANNEL: ${{ inputs.channel }}
TAURI_CONF_PATH: ./src-tauri/tauri.conf.${{ inputs.channel }}.json
NODE_OPTIONS: "--max-old-space-size=4096"
jobs:
compute-version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
with:
lfs: true
fetch-depth: 0
fetch-tags: true
- run: |
git remote set-url origin "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git"
git fetch --tags --force
- uses: ./.github/actions/doxxer_install
- id: version
run: |
if [[ -n "${{ inputs.version }}" ]]; then
VERSION="${{ inputs.version }}"
elif [[ "${{ inputs.channel }}" == "staging" ]]; then
VERSION=$(doxxer --config doxxer.desktop.toml next dev)
elif [[ "${{ inputs.channel }}" == "stable" ]]; then
VERSION=$(doxxer --config doxxer.desktop.toml next patch)
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Computed version: $VERSION"
cn-draft:
if: ${{ inputs.channel != 'staging' }}
needs: compute-version
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./scripts/version.sh "./apps/desktop/src-tauri/tauri.conf.json" "${{ needs.compute-version.outputs.version }}"
- uses: ./.github/actions/cn_release
with:
cmd: draft
app: ${{ env.CN_APPLICATION }}
key: ${{ secrets.CN_API_KEY }}
channel: ${{ env.RELEASE_CHANNEL }}
framework: tauri
working-directory: ./apps/desktop
build-macos:
needs: [compute-version, cn-draft]
if: ${{ !cancelled() && (needs.cn-draft.result == 'success' || needs.cn-draft.result == 'skipped') }}
permissions:
contents: write
runs-on: depot-macos-15
strategy:
fail-fast: true
matrix:
include: ${{ inputs.channel == 'staging' && fromJSON('[{"target":"aarch64-apple-darwin","arch":"aarch64","artifact_name":"silicon"}]') || fromJSON('[{"target":"aarch64-apple-darwin","arch":"aarch64","artifact_name":"silicon"},{"target":"x86_64-apple-darwin","arch":"x86_64","artifact_name":"intel"}]') }}
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
with:
lfs: true
fetch-depth: 0
fetch-tags: true
submodules: recursive
- run: |
git remote set-url origin "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git"
git fetch --tags --force
- uses: ./.github/actions/macos_tcc
- run: ./scripts/version.sh "./apps/desktop/src-tauri/tauri.conf.json" "${{ needs.compute-version.outputs.version }}"
- uses: ./.github/actions/install_desktop_deps
with:
target: macos
- uses: ./.github/actions/rust_install
with:
platform: macos
- run: echo "SDKROOT=$(xcrun --sdk macosx --show-sdk-path)" >> $GITHUB_ENV
- uses: ./.github/actions/pnpm_install
- run: pnpm -F ui build
- run: |
TAURI_ENV_TARGET_TRIPLE=${{ matrix.target }} cargo xtask prepare-binaries
./scripts/sidecar.sh "./apps/desktop/${{ env.TAURI_CONF_PATH }}" "binaries/char-chrome-native-host"
./scripts/sidecar.sh "./apps/desktop/${{ env.TAURI_CONF_PATH }}" "binaries/check-permissions"
- uses: ./.github/actions/apple_cert
id: apple-cert
with:
apple-certificate: ${{ secrets.APPLE_CERTIFICATE }}
apple-certificate-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
keychain-password: ${{ secrets.KEYCHAIN_PASSWORD }}
- run: |
BUILD_ARGS=(--target "${{ matrix.target }}" --config "${{ env.TAURI_CONF_PATH }}" --verbose)
if [[ "${{ matrix.target }}" == "x86_64-apple-darwin" ]]; then
BUILD_ARGS+=(--config ./src-tauri/tauri.conf.macos-intel.json)
fi
if [[ "${{ inputs.channel }}" == "staging" ]]; then
BUILD_ARGS+=(--features devtools)
fi
pnpm -F desktop tauri build "${BUILD_ARGS[@]}"
env:
# https://v2.tauri.app/reference/environment-variables/
CI: false
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
VITE_POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN_HYPRNOTE_2 }}
APP_VERSION: ${{ needs.compute-version.outputs.version }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ steps.apple-cert.outputs.cert-id }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }}
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }}
VITE_APP_URL: "https://anarlog.so"
VITE_API_URL: "https://api.anarlog.so"
VITE_PRO_PRODUCT_ID: ${{ secrets.VITE_PRO_PRODUCT_ID }}
VITE_APP_VERSION: ${{ needs.compute-version.outputs.version }}
- id: find-dmg
shell: bash
run: |
DMG_FILE=$(find "apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/dmg/" -name "*.dmg" -type f | head -1)
if [[ -z "$DMG_FILE" ]]; then
echo "::error::No DMG found in bundle output"
exit 1
fi
echo "path=$DMG_FILE" >> $GITHUB_OUTPUT
- uses: ./.github/actions/macos_notarize_dmg
with:
dmg-path: ${{ steps.find-dmg.outputs.path }}
signing-identity: ${{ steps.apple-cert.outputs.cert-id }}
apple-id: ${{ secrets.APPLE_ID }}
apple-password: ${{ secrets.APPLE_PASSWORD }}
apple-team-id: ${{ secrets.APPLE_TEAM_ID }}
- run: |
mkdir -p target/release/
find target/${{ matrix.target }}/release -type f -not -path "*/\.*" -exec cp {} target/release/ \;
shell: bash
working-directory: ./apps/desktop/src-tauri
- if: ${{ inputs.channel != 'staging' }}
uses: ./.github/actions/cn_release
with:
cmd: upload
app: ${{ env.CN_APPLICATION }}
key: ${{ secrets.CN_API_KEY }}
channel: ${{ env.RELEASE_CHANNEL }}
framework: tauri
working-directory: ./apps/desktop
- if: ${{ inputs.channel == 'staging' }}
uses: actions/upload-artifact@v4
with:
name: hyprnote-staging-macos-${{ matrix.artifact_name }}
path: apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/dmg/*.dmg
retention-days: 3
- if: ${{ inputs.channel == 'staging' }}
run: |
TIMESTAMP=$(date -u +"%Y%m%d%H%M%S")
COMMIT_HASH=$(git rev-parse --short HEAD)
DMG_FILE=$(find "apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/dmg/" -name "*.dmg" -type f)
FILENAME="hyprnote-staging-${TIMESTAMP}-${COMMIT_HASH}-macos-${{ matrix.arch }}.dmg"
cp "$DMG_FILE" "$FILENAME"
aws s3 cp "$FILENAME" \
"s3://hyprnote-build/desktop/staging/$FILENAME" \
--endpoint-url ${{ secrets.CLOUDFLARE_R2_ENDPOINT_URL }} \
--region auto
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
create-tag:
if: ${{ inputs.channel != 'staging' && !cancelled() && needs.build-macos.result == 'success' }}
needs: [compute-version, build-macos]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- run: |
git fetch --tags --force
TAG="desktop_v${{ needs.compute-version.outputs.version }}"
TARGET=$(git rev-parse HEAD)
EXISTING=$(git rev-parse -q --verify "refs/tags/$TAG" || true)
if [[ -n "$EXISTING" && -z "${{ inputs.version }}" ]]; then
echo "::error::Tag $TAG already exists"
exit 1
fi
git tag -f "$TAG" "$TARGET"
git push origin "refs/tags/$TAG" --force
cn-publish:
if: ${{ inputs.channel != 'staging' && inputs.publish }}
needs: [compute-version, build-macos, create-tag]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./scripts/version.sh "./apps/desktop/src-tauri/tauri.conf.json" "${{ needs.compute-version.outputs.version }}"
- uses: ./.github/actions/cn_release
with:
cmd: publish
app: ${{ env.CN_APPLICATION }}
key: ${{ secrets.CN_API_KEY }}
channel: ${{ env.RELEASE_CHANNEL }}
framework: tauri
working-directory: ./apps/desktop
release:
if: ${{ inputs.channel != 'staging' && inputs.publish && !cancelled() && needs.cn-publish.result == 'success' && needs.build-macos.result == 'success' }}
needs: [compute-version, build-macos, cn-publish]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- run: git fetch --tags --force
- if: ${{ needs.build-macos.result == 'success' }}
uses: ./.github/actions/cn_download
with:
app: ${{ env.CN_APPLICATION }}
version: ${{ needs.compute-version.outputs.version }}
channel: ${{ env.RELEASE_CHANNEL }}
platform: dmg-aarch64
output: hyprnote-macos-aarch64.dmg
key: ${{ secrets.CN_API_KEY }}
- if: ${{ needs.build-macos.result == 'success' }}
uses: ./.github/actions/cn_download
with:
app: ${{ env.CN_APPLICATION }}
version: ${{ needs.compute-version.outputs.version }}
channel: ${{ env.RELEASE_CHANNEL }}
platform: dmg-x86_64
output: hyprnote-macos-x86_64.dmg
key: ${{ secrets.CN_API_KEY }}
- id: checksums
uses: ./.github/actions/generate_checksums
with:
files: |
${{ needs.build-macos.result == 'success' && 'hyprnote-macos-aarch64.dmg' || '' }}
${{ needs.build-macos.result == 'success' && 'hyprnote-macos-x86_64.dmg' || '' }}
- id: artifacts
run: |
ARTIFACTS=""
if [[ "${{ needs.build-macos.result }}" == "success" ]]; then
ARTIFACTS="hyprnote-macos-aarch64.dmg,hyprnote-macos-x86_64.dmg"
fi
if [[ -z "$ARTIFACTS" ]]; then
echo "No artifacts to release" >&2
exit 1
fi
if [[ -n "${{ steps.checksums.outputs.checksum_files }}" ]]; then
ARTIFACTS="$ARTIFACTS,${{ steps.checksums.outputs.checksum_files }}"
fi
echo "list=$ARTIFACTS" >> $GITHUB_OUTPUT
- id: release-body
run: |
echo "value=https://anarlog.so/changelog/${{ needs.compute-version.outputs.version }}" >> "$GITHUB_OUTPUT"
- uses: ncipollo/release-action@v1
with:
tag: desktop_v${{ needs.compute-version.outputs.version }}
name: desktop_v${{ needs.compute-version.outputs.version }}
body: ${{ steps.release-body.outputs.value }}
prerelease: false
makeLatest: true
artifacts: ${{ steps.artifacts.outputs.list }}