Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"enabledPlugins": {
"svelte@svelte": true
}
}
150 changes: 150 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
name: Release

# Push a tag such as v0.2.0 to build signed installers for macOS, Windows, and
# Linux. The release stays a draft until every platform uploads, so installed
# apps never see a partial latest.json.
on:
push:
tags: ['v*']

permissions:
contents: read

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

jobs:
create-release:
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
release_id: ${{ steps.release.outputs.id }}
tag: ${{ steps.version.outputs.tag }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false
- name: Check that the tag matches the app version
id: version
run: |
tag="${GITHUB_REF_NAME}"
app_version="$(jq -r .version src-tauri/tauri.conf.json)"
cargo_version="$(sed -n '/^\[workspace.package\]/,/^\[/s/^version = "\(.*\)"/\1/p' Cargo.toml)"
if [ "$tag" != "v$app_version" ] || [ "$app_version" != "$cargo_version" ]; then
echo "::error::Tag $tag must equal v<version>, and tauri.conf.json ($app_version) must match Cargo.toml ($cargo_version)."
exit 1
fi
echo "tag=$tag" >> "$GITHUB_OUTPUT"
- name: Create a draft release
id: release
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.version.outputs.tag }}
run: |
if ! gh release view "$TAG" -R "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
gh release create "$TAG" -R "$GITHUB_REPOSITORY" --draft --verify-tag \
--title "Noura ${TAG#v}" --generate-notes
fi
echo "id=$(gh release view "$TAG" -R "$GITHUB_REPOSITORY" --json databaseId -q .databaseId)" >> "$GITHUB_OUTPUT"

build:
needs: create-release
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
args: --target universal-apple-darwin
rust-targets: aarch64-apple-darwin,x86_64-apple-darwin,wasm32-unknown-unknown
- os: windows-latest
args: ''
rust-targets: wasm32-unknown-unknown
# The oldest supported Ubuntu keeps the AppImage compatible with older glibc.
- os: ubuntu-22.04
args: ''
rust-targets: wasm32-unknown-unknown
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable
with: { toolchain: '1.91', targets: '${{ matrix.rust-targets }}' }
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
with: { key: release }
- uses: taiki-e/install-action@76c2e6406e52637deed7160d77bded76bd83e06e # v2.87.14
with: { tool: wasm-bindgen-cli@0.2.127 }
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with: { bun-version: 1.3.14 }
- run: bun install --frozen-lockfile
- name: Install Linux desktop build dependencies
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
# Apple signing is optional. Without a Developer ID certificate the app is
# ad-hoc signed, and macOS asks users to approve it on first launch.
- name: Load Apple signing credentials when configured
if: runner.os == 'macOS'
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
for name in APPLE_CERTIFICATE APPLE_CERTIFICATE_PASSWORD APPLE_SIGNING_IDENTITY APPLE_ID APPLE_PASSWORD APPLE_TEAM_ID; do
value="${!name}"
if [ -n "$value" ]; then
echo "::add-mask::$value"
echo "$name=$value" >> "$GITHUB_ENV"
fi
done
- uses: tauri-apps/tauri-action@1deb371b0cd8bd54025b384f1cd735e725c4060f # action-v1.0.0
env:
GITHUB_TOKEN: ${{ github.token }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
Comment thread
lobbystack marked this conversation as resolved.
with:
releaseId: ${{ needs.create-release.outputs.release_id }}
tauriScript: bun run tauri
args: --config tauri.release.conf.json ${{ matrix.args }}
uploadUpdaterJson: true
updaterJsonPreferNsis: true

publish:
needs: [create-release, build]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Add stable download names and publish
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.create-release.outputs.tag }}
run: |
set -euo pipefail
gh release download "$TAG" -R "$GITHUB_REPOSITORY" -D dist \
-p '*_universal.dmg' -p '*-setup.exe' -p '*.AppImage' -p '*_amd64.deb' -p 'latest.json'
test -s dist/latest.json

# The website links to releases/latest/download/<stable name>.
stable() {
local matches=(dist/$1)
if [ "${#matches[@]}" -ne 1 ] || [ ! -f "${matches[0]}" ]; then
echo "::error::Expected exactly one asset matching $1"
exit 1
fi
cp "${matches[0]}" "stable/$2"
}
mkdir stable
stable '*_universal.dmg' Noura-macOS.dmg
stable '*-setup.exe' Noura-Windows-Setup.exe
stable '*.AppImage' Noura-Linux.AppImage
stable '*_amd64.deb' Noura-Linux.deb
Comment thread
lobbystack marked this conversation as resolved.

gh release upload "$TAG" -R "$GITHUB_REPOSITORY" --clobber stable/*
gh release edit "$TAG" -R "$GITHUB_REPOSITORY" --draft=false --latest
Loading
Loading