clean builds and add auto-updater

This commit is contained in:
vcoppe committed 2026-11-04 20:02:18 +01:00
1 parent c0afd1fea9
commit a67b982b1c
12 files changed
+842 -135

No files matched your search

-124
View File
@@ -1,124 +0,0 @@
name: Desktop beta
on:
push:
branches: 'dev'
workflow_dispatch:
concurrency:
group: desktop-beta-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- platform: macos-latest
rust_targets: aarch64-apple-darwin,x86_64-apple-darwin,wasm32-unknown-unknown
args: --target universal-apple-darwin
bundles: target/universal-apple-darwin/release/bundle/dmg/*.dmg
# the oldest supported Ubuntu, so that the AppImage runs on older systems too
- platform: ubuntu-22.04
rust_targets: wasm32-unknown-unknown
args: ''
bundles: |
target/release/bundle/deb/*.deb
target/release/bundle/rpm/*.rpm
target/release/bundle/appimage/*.AppImage
- platform: windows-latest
rust_targets: wasm32-unknown-unknown
args: ''
bundles: |
target/release/bundle/msi/*.msi
target/release/bundle/nsis/*.exe
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Install Linux dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: website/package-lock.json
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust_targets }}
- name: Cache Rust build
uses: Swatinem/rust-cache@v2
- name: Install wasm-pack
uses: taiki-e/install-action@v2
with:
tool: wasm-pack
# the desktop app does not use it, but the website depends on its package
- name: Build wasm
run: wasm-pack build --target bundler
working-directory: wasm
- name: Install dependencies for website
run: npm install --prefix website
# the key would be readable in the app: it is left empty, so only the MapTiler layer fails
- name: Create env file
run: echo "PUBLIC_MAPTILER_KEY=" >> website/.env
- name: Build app
run: npx --yes @tauri-apps/cli@2 build ${{ matrix.args }}
working-directory: tauri
# after the build, which gives the app the website it embeds
- name: Test engine and app
run: cargo test -p gpx-engine -p gpx-studio-desktop
- name: Upload bundles
uses: actions/upload-artifact@v4
with:
name: bundles-${{ matrix.platform }}
path: ${{ matrix.bundles }}
if-no-files-found: error
# replaces the beta release only once every platform is built
release:
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
steps:
- name: Download bundles
uses: actions/download-artifact@v5
with:
pattern: bundles-*
path: bundles
merge-multiple: true
- name: Publish beta release
# the bundles of a platform are in a folder per format (deb, msi…)
run: |
mapfile -t files < <(find bundles -type f)
gh release delete desktop-beta --cleanup-tag --yes || true
gh release create desktop-beta "${files[@]}" \
--prerelease \
--target ${{ github.sha }} \
--title "Desktop beta" \
--notes "Beta of the desktop app, built from ${{ github.sha }} on the dev branch. The builds are not signed yet: macOS and Windows will warn before opening them."
+214
View File
@@ -0,0 +1,214 @@
name: Desktop release
# run by hand: from `main` for a release, from `dev` for a pre-release
on:
workflow_dispatch:
concurrency:
group: desktop-${{ github.ref }}
jobs:
# the release stays a draft until every platform is built and tested
prepare:
runs-on: ubuntu-latest
permissions:
contents: write
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
outputs:
version: ${{ steps.version.outputs.version }}
draft_tag: ${{ steps.version.outputs.draft_tag }}
release_id: ${{ steps.draft.outputs.release_id }}
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Choose version
id: version
run: |
base=$(jq -r .version tauri/tauri.conf.json)
if [[ ! "$base" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::The version in tauri.conf.json should be x.y.z, not $base"
exit 1
fi
case "$GITHUB_REF_NAME" in
main)
version=$base
draft_tag=desktop-v$base
if git ls-remote --exit-code --tags origin "refs/tags/$draft_tag"; then
echo "::error::$draft_tag is already released: bump the version in tauri.conf.json"
exit 1
fi
if [ -z "$(jq -r '.plugins.updater.pubkey' tauri/tauri.conf.json)" ]; then
echo "::error::The public key of the updater is missing from tauri.conf.json"
exit 1
fi
;;
dev)
version=$base-beta.$GITHUB_RUN_NUMBER
draft_tag=desktop-beta-$GITHUB_RUN_NUMBER
;;
*)
echo "::error::Desktop builds are made from main or dev, not $GITHUB_REF_NAME"
exit 1
;;
esac
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "draft_tag=$draft_tag" >> "$GITHUB_OUTPUT"
- name: Create draft release
id: draft
env:
VERSION: ${{ steps.version.outputs.version }}
DRAFT_TAG: ${{ steps.version.outputs.draft_tag }}
run: |
# what a previous attempt left: this tag is not released, so it can only be a draft
gh release delete "$DRAFT_TAG" --yes || true
if [ "$GITHUB_REF_NAME" = main ]; then
gh release create "$DRAFT_TAG" --draft --target "$GITHUB_SHA" \
--title "Desktop $VERSION" --generate-notes
else
gh release create "$DRAFT_TAG" --draft --prerelease --target "$GITHUB_SHA" \
--title "Desktop beta $VERSION" \
--notes "Beta of the desktop app, built from $GITHUB_SHA on the dev branch. The builds are not signed yet: macOS and Windows will warn before opening them."
fi
echo "release_id=$(gh release view "$DRAFT_TAG" --json databaseId --jq .databaseId)" >> "$GITHUB_OUTPUT"
build:
needs: prepare
strategy:
fail-fast: false
matrix:
include:
- platform: macos-latest
rust_targets: aarch64-apple-darwin,x86_64-apple-darwin,wasm32-unknown-unknown
args: --target universal-apple-darwin
# the oldest supported Ubuntu, so that the AppImage runs on older systems too
- platform: ubuntu-22.04
rust_targets: wasm32-unknown-unknown
args: ''
- platform: windows-latest
rust_targets: wasm32-unknown-unknown
args: ''
runs-on: ${{ matrix.platform }}
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Install Linux dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: website/package-lock.json
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust_targets }}
- name: Cache Rust build
uses: Swatinem/rust-cache@v2
- name: Install wasm-pack
uses: taiki-e/install-action@v2
with:
tool: wasm-pack
# the desktop app does not use it, but the website depends on its package
- name: Build wasm
run: wasm-pack build --target bundler
working-directory: wasm
- name: Install dependencies for website
run: npm install --prefix website
# the key would be readable in the app: it is left empty, so only the MapTiler layer fails
- name: Create env file
run: echo "PUBLIC_MAPTILER_KEY=" >> website/.env
# only the releases update themselves: they need the updater files, and the signing key
- name: Set version and updater files
shell: bash
env:
VERSION: ${{ needs.prepare.outputs.version }}
UPDATER: ${{ github.ref_name == 'main' }}
run: |
node -e "
const fs = require('fs');
const path = 'tauri/tauri.conf.json';
const config = JSON.parse(fs.readFileSync(path));
config.version = process.env.VERSION;
config.bundle.createUpdaterArtifacts = process.env.UPDATER === 'true';
fs.writeFileSync(path, JSON.stringify(config, null, 4));
"
- name: Build app and upload it to the draft
uses: tauri-apps/tauri-action@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ github.ref_name == 'main' && secrets.TAURI_SIGNING_PRIVATE_KEY || '' }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ github.ref_name == 'main' && secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD || '' }}
with:
projectPath: tauri
tauriScript: npx --yes @tauri-apps/cli@2
args: ${{ matrix.args }}
releaseId: ${{ needs.prepare.outputs.release_id }}
# given with the id for the addresses in `latest.json`
tagName: ${{ needs.prepare.outputs.draft_tag }}
uploadUpdaterJson: ${{ github.ref_name == 'main' }}
# after the build, which gives the app the website it embeds
- name: Test engine and app
run: cargo test -p gpx-engine -p gpx-studio-desktop
# `releases/latest`, which the updater reads, only changes here
publish:
needs: [prepare, build]
runs-on: ubuntu-latest
permissions:
contents: write
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
DRAFT_TAG: ${{ needs.prepare.outputs.draft_tag }}
steps:
# the builds of the platforms add themselves to it in parallel, and could overwrite each other
- name: Check updater file
if: github.ref_name == 'main'
run: |
gh release download "$DRAFT_TAG" --pattern latest.json
for platform in darwin-aarch64 darwin-x86_64 linux-x86_64 windows-x86_64; do
if ! jq -e --arg platform "$platform" '.platforms[$platform].signature | length > 0' latest.json; then
echo "::error::latest.json has no signed update for $platform"
exit 1
fi
done
- name: Publish release
if: github.ref_name == 'main'
run: gh release edit "$DRAFT_TAG" --draft=false --latest
- name: Replace beta release
if: github.ref_name == 'dev'
run: |
gh release delete desktop-beta --cleanup-tag --yes || true
gh release edit "$DRAFT_TAG" --tag desktop-beta --draft=false --prerelease --latest=false
Generated
+516 -9
View File
@@ -475,6 +475,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cfg_aliases"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
[[package]]
name = "chrono"
version = "0.4.45"
@@ -537,6 +543,16 @@ dependencies = [
"version_check",
]
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation"
version = "0.10.1"
@@ -560,7 +576,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97"
dependencies = [
"bitflags 2.13.2",
"core-foundation",
"core-foundation 0.10.1",
"core-graphics-types",
"foreign-types",
"libc",
@@ -573,7 +589,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
dependencies = [
"bitflags 2.13.2",
"core-foundation",
"core-foundation 0.10.1",
"libc",
]
@@ -1020,6 +1036,16 @@ dependencies = [
"rustc_version",
]
[[package]]
name = "filetime"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759"
dependencies = [
"cfg-if",
"libc",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.12"
@@ -1287,6 +1313,17 @@ dependencies = [
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "getrandom"
version = "0.3.4"
@@ -1306,8 +1343,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"r-efi 6.0.0",
"wasm-bindgen",
]
[[package]]
@@ -1431,7 +1470,9 @@ dependencies = [
"tauri-build",
"tauri-plugin-dialog",
"tauri-plugin-opener",
"tauri-plugin-process",
"tauri-plugin-single-instance",
"tauri-plugin-updater",
"trash",
"uuid",
]
@@ -1631,6 +1672,21 @@ dependencies = [
"want",
]
[[package]]
name = "hyper-rustls"
version = "0.27.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfa8e654703247911e29c23fbeaa261834bd9bb74efba2f9acddc37bfb127f53"
dependencies = [
"http",
"hyper",
"hyper-util",
"rustls",
"tokio",
"tokio-rustls",
"tower-service",
]
[[package]]
name = "hyper-util"
version = "0.1.21"
@@ -1650,9 +1706,11 @@ dependencies = [
"percent-encoding",
"pin-project-lite",
"socket2",
"system-configuration",
"tokio",
"tower-service",
"tracing",
"windows-registry",
]
[[package]]
@@ -1990,6 +2048,36 @@ dependencies = [
"windows-sys 0.45.0",
]
[[package]]
name = "jni"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
dependencies = [
"cfg-if",
"combine",
"jni-macros",
"jni-sys 0.4.1",
"log",
"simd_cesu8",
"thiserror 2.0.21",
"walkdir",
"windows-link",
]
[[package]]
name = "jni-macros"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"simd_cesu8",
"syn 2.0.118",
]
[[package]]
name = "jni-sys"
version = "0.3.1"
@@ -2214,6 +2302,12 @@ dependencies = [
"walkdir",
]
[[package]]
name = "minisign-verify"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "871285dc19d8d0ebe0eef3d0e99a205f2a71363b122632cbbfa4a6c370a960ce"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
@@ -2303,6 +2397,18 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]]
name = "nix"
version = "0.31.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
dependencies = [
"bitflags 2.13.2",
"cfg-if",
"cfg_aliases",
"libc",
]
[[package]]
name = "notify"
version = "8.2.0"
@@ -2529,6 +2635,18 @@ dependencies = [
"objc2-core-foundation",
]
[[package]]
name = "objc2-osa-kit"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f112d1746737b0da274ef79a23aac283376f335f4095a083a267a082f21db0c0"
dependencies = [
"bitflags 2.13.2",
"objc2",
"objc2-app-kit",
"objc2-foundation",
]
[[package]]
name = "objc2-quartz-core"
version = "0.3.2"
@@ -2609,6 +2727,12 @@ dependencies = [
"libc",
]
[[package]]
name = "openssl-probe"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e036b411754132fd6b74e94b74e9a13c5cf606fa93d1885c35860d3060820b1"
[[package]]
name = "option-ext"
version = "0.2.0"
@@ -2625,6 +2749,20 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "osakit"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "732c71caeaa72c065bb69d7ea08717bd3f4863a4f451402fc9513e29dbd5261b"
dependencies = [
"objc2",
"objc2-foundation",
"objc2-osa-kit",
"serde",
"serde_json",
"thiserror 2.0.21",
]
[[package]]
name = "pango"
version = "0.18.3"
@@ -3049,15 +3187,20 @@ dependencies = [
"http-body",
"http-body-util",
"hyper",
"hyper-rustls",
"hyper-util",
"js-sys",
"log",
"percent-encoding",
"pin-project-lite",
"rustls",
"rustls-pki-types",
"rustls-platform-verifier",
"serde",
"serde_json",
"sync_wrapper",
"tokio",
"tokio-rustls",
"tokio-util",
"tower",
"tower-http",
@@ -3093,6 +3236,20 @@ dependencies = [
"windows-sys 0.60.2",
]
[[package]]
name = "ring"
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [
"cc",
"cfg-if",
"getrandom 0.2.17",
"libc",
"untrusted",
"windows-sys 0.52.0",
]
[[package]]
name = "rustc-hash"
version = "2.1.3"
@@ -3121,6 +3278,79 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "rustls"
version = "0.23.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf"
dependencies = [
"once_cell",
"ring",
"rustls-pki-types",
"rustls-webpki",
"subtle",
"zeroize",
]
[[package]]
name = "rustls-native-certs"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a073f5dc7469f984c52ad2752b63b0807745133b6de880b7b64c1ac4c48aec4"
dependencies = [
"openssl-probe",
"rustls-pki-types",
"schannel",
"security-framework",
]
[[package]]
name = "rustls-pki-types"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96"
dependencies = [
"zeroize",
]
[[package]]
name = "rustls-platform-verifier"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98"
dependencies = [
"core-foundation 0.10.1",
"core-foundation-sys",
"jni 0.22.4",
"log",
"once_cell",
"rustls",
"rustls-native-certs",
"rustls-platform-verifier-android",
"rustls-webpki",
"security-framework",
"security-framework-sys",
"webpki-root-certs",
"windows-sys 0.61.2",
]
[[package]]
name = "rustls-platform-verifier-android"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f"
[[package]]
name = "rustls-webpki"
version = "0.103.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281"
dependencies = [
"ring",
"rustls-pki-types",
"untrusted",
]
[[package]]
name = "rustversion"
version = "1.0.23"
@@ -3136,6 +3366,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cb23c424d8ee841bb4d813677ca237e2a610067d594fec130f87d6093495ab5"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "schemars"
version = "0.8.22"
@@ -3193,6 +3432,29 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "security-framework"
version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [
"bitflags 2.13.2",
"core-foundation 0.10.1",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "selectors"
version = "0.38.0"
@@ -3425,6 +3687,22 @@ version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
[[package]]
name = "simd_cesu8"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520"
dependencies = [
"rustc_version",
"simdutf8",
]
[[package]]
name = "simdutf8"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "siphasher"
version = "1.0.4"
@@ -3546,6 +3824,12 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "swift-rs"
version = "1.0.9"
@@ -3609,6 +3893,27 @@ dependencies = [
"syn 3.0.6",
]
[[package]]
name = "system-configuration"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
dependencies = [
"bitflags 2.13.2",
"core-foundation 0.9.4",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "system-deps"
version = "6.2.2"
@@ -3630,7 +3935,7 @@ checksum = "f37f381f4e048e6cdf038b5705f8cf14ad108279d46eb968140a7b291aba9400"
dependencies = [
"bitflags 2.13.2",
"block2",
"core-foundation",
"core-foundation 0.10.1",
"core-graphics",
"crossbeam-channel",
"dbus",
@@ -3640,7 +3945,7 @@ dependencies = [
"gdkwayland-sys",
"gdkx11-sys",
"gtk",
"jni",
"jni 0.21.1",
"libc",
"log",
"ndk",
@@ -3673,6 +3978,17 @@ dependencies = [
"syn 2.0.118",
]
[[package]]
name = "tar"
version = "0.4.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840"
dependencies = [
"filetime",
"libc",
"xattr",
]
[[package]]
name = "target-lexicon"
version = "0.12.16"
@@ -3696,7 +4012,7 @@ dependencies = [
"gtk",
"heck 0.5.0",
"http",
"jni",
"jni 0.21.1",
"libc",
"log",
"mime",
@@ -3872,6 +4188,16 @@ dependencies = [
"zbus",
]
[[package]]
name = "tauri-plugin-process"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74ae3d8549ae564c0397377373e262f340908eb23a5b9fbe03f2a00007dc0038"
dependencies = [
"tauri",
"tauri-plugin",
]
[[package]]
name = "tauri-plugin-single-instance"
version = "2.5.3"
@@ -3888,6 +4214,40 @@ dependencies = [
"zbus",
]
[[package]]
name = "tauri-plugin-updater"
version = "2.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d957abbcb3f9f6c76d22a3a0f012f30880640d0bccb5634d2b12a9937e4c872b"
dependencies = [
"base64 0.23.1",
"dirs",
"flate2",
"futures-util",
"http",
"infer",
"libc",
"log",
"minisign-verify",
"osakit",
"percent-encoding",
"reqwest",
"rustls",
"semver",
"serde",
"serde_json",
"tar",
"tauri",
"tauri-plugin",
"tempfile",
"thiserror 2.0.21",
"time",
"tokio",
"url",
"windows-sys 0.61.2",
"zip",
]
[[package]]
name = "tauri-runtime"
version = "2.12.1"
@@ -3898,7 +4258,7 @@ dependencies = [
"dpi",
"gtk",
"http",
"jni",
"jni 0.21.1",
"objc2",
"objc2-ui-kit",
"objc2-web-kit",
@@ -3921,7 +4281,7 @@ checksum = "7f9e7e0c9f80a5130773cfabb6df4dc924518fb1b2c923726966804634b57d22"
dependencies = [
"gtk",
"http",
"jni",
"jni 0.21.1",
"log",
"objc2",
"objc2-app-kit",
@@ -4110,6 +4470,16 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "tokio-rustls"
version = "0.26.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db"
dependencies = [
"rustls",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.20"
@@ -4341,6 +4711,12 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "typed-path"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce898823d8cd0f028662d2f349694b1af0a5cc9be83f1d213a00d3147445e1e"
[[package]]
name = "typeid"
version = "1.0.3"
@@ -4376,6 +4752,12 @@ version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
version = "2.5.8"
@@ -4675,6 +5057,15 @@ dependencies = [
"system-deps",
]
[[package]]
name = "webpki-root-certs"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e49d0e65abc00c142e8f9428da991da9f1a250c39be97459901eb12b9b49f62a"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "webview2-com"
version = "0.39.1"
@@ -4839,6 +5230,17 @@ dependencies = [
"windows-link",
]
[[package]]
name = "windows-registry"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720"
dependencies = [
"windows-link",
"windows-result",
"windows-strings",
]
[[package]]
name = "windows-result"
version = "0.4.1"
@@ -4866,6 +5268,15 @@ dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.60.2"
@@ -4899,6 +5310,22 @@ dependencies = [
"windows_x86_64_msvc 0.42.2",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.5"
@@ -4909,7 +5336,7 @@ dependencies = [
"windows_aarch64_gnullvm 0.53.1",
"windows_aarch64_msvc 0.53.1",
"windows_i686_gnu 0.53.1",
"windows_i686_gnullvm",
"windows_i686_gnullvm 0.53.1",
"windows_i686_msvc 0.53.1",
"windows_x86_64_gnu 0.53.1",
"windows_x86_64_gnullvm 0.53.1",
@@ -4940,6 +5367,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.1"
@@ -4952,6 +5385,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.1"
@@ -4964,12 +5403,24 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.1"
@@ -4982,6 +5433,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.1"
@@ -4994,6 +5451,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.1"
@@ -5006,6 +5469,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.1"
@@ -5018,6 +5487,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.1"
@@ -5082,7 +5557,7 @@ dependencies = [
"gtk",
"http",
"javascriptcore-rs",
"jni",
"jni 0.21.1",
"libc",
"ndk",
"objc2",
@@ -5129,6 +5604,16 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "xattr"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
dependencies = [
"libc",
"rustix",
]
[[package]]
name = "yoke"
version = "0.8.3"
@@ -5243,6 +5728,12 @@ dependencies = [
"synstructure",
]
[[package]]
name = "zeroize"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879"
[[package]]
name = "zerotrie"
version = "0.2.5"
@@ -5276,6 +5767,22 @@ dependencies = [
"syn 3.0.6",
]
[[package]]
name = "zip"
version = "9.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaeb7f16d2605b49aef586996ded29e65642fab7259a3077e537351df6d80426"
dependencies = [
"crc32fast",
"getrandom 0.4.3",
"indexmap 2.14.2",
"libc",
"memchr",
"nix",
"typed-path",
"windows-sys 0.61.2",
]
[[package]]
name = "zlib-rs"
version = "0.6.8"
+4
View File
@@ -37,3 +37,7 @@ tauri-plugin-single-instance = "2.5.3"
tauri-plugin-opener = "2"
trash = "5"
[target.'cfg(any(target_os = "macos", windows, target_os = "linux"))'.dependencies]
tauri-plugin-process = "2.4.0"
tauri-plugin-updater = "2.14.1"
+1 -1
View File
@@ -3,5 +3,5 @@
"identifier": "default",
"description": "Permissions for the main window",
"windows": ["main"],
"permissions": ["core:default"]
"permissions": ["core:default", "updater:default", "process:allow-restart"]
}
+6
View File
@@ -55,6 +55,12 @@ pub fn run() {
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_opener::init())
.setup(|app| {
#[cfg(desktop)]
{
app.handle()
.plugin(tauri_plugin_updater::Builder::new().build())?;
app.handle().plugin(tauri_plugin_process::init())?;
}
let handle = app.handle().clone();
let emit: state::Emit = std::sync::Arc::new(move |event, payload| {
let _ = handle.emit(event, payload);
+10 -1
View File
@@ -27,7 +27,8 @@
},
"bundle": {
"active": true,
"targets": "all",
"targets": ["app", "dmg", "appimage", "deb", "rpm", "nsis"],
"macOS": { "signingIdentity": "-" },
"fileAssociations": [
{
"ext": ["gpx"],
@@ -44,5 +45,13 @@
"icons/icon.icns",
"icons/icon.ico"
]
},
"plugins": {
"updater": {
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE5NTFDQzVDOUYwNEMyNEMKUldSTXdnU2ZYTXhSR1ZXRDV6aVErc3dUWXBaK0VGSitYRnFFR21hZ2s5UEJTT01aYkE5Unp5c0cKdW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEFFNTU3Q0Y1NzhFODkyMTEKUldRUmt1aDQ5WHhWcmdXQmx0UG83V29TenRxSVJjdkc4ckN1Zi93ajc3ZUhVUVp3eFlCOXphb1IK",
"endpoints": [
"https://github.com/gpxstudio/gpx.studio/releases/latest/download/latest.json"
]
}
}
}
+22
View File
@@ -32,6 +32,8 @@
"@sveltejs/vite-plugin-svelte": "^6.2.4",
"@tailwindcss/vite": "^4.1.8",
"@tauri-apps/api": "^2.12.3",
"@tauri-apps/plugin-process": "^2.4.0",
"@tauri-apps/plugin-updater": "^2.14.1",
"@types/eslint": "^9.6.1",
"@types/events": "^3.0.3",
"@types/file-saver": "^2.0.7",
@@ -2667,6 +2669,26 @@
"url": "https://opencollective.com/tauri"
}
},
"node_modules/@tauri-apps/plugin-process": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-process/-/plugin-process-2.4.0.tgz",
"integrity": "sha512-GddrmsSLAYrLa/yTXlXK/YRDzUgYeeOnUXTbiyvJWkmI424RmDPD3FVLeqcon7rv6O6ZfhBilcrHWnSo7o6hIQ==",
"dev": true,
"license": "MIT OR Apache-2.0",
"dependencies": {
"@tauri-apps/api": "^2.12.0"
}
},
"node_modules/@tauri-apps/plugin-updater": {
"version": "2.14.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-updater/-/plugin-updater-2.14.1.tgz",
"integrity": "sha512-Hr7nlBm1wT6xbwzjZ/S36YULazu8MNlj5vvOwMl47fXI7HTa5Bjl1PbDEwVHaZTAKzE1VZsUy35UqnbrQxmYQw==",
"dev": true,
"license": "MIT OR Apache-2.0",
"dependencies": {
"@tauri-apps/api": "^2.12.0"
}
},
"node_modules/@types/cookie": {
"version": "0.6.0",
"dev": true,
+2
View File
@@ -27,6 +27,8 @@
"@sveltejs/vite-plugin-svelte": "^6.2.4",
"@tailwindcss/vite": "^4.1.8",
"@tauri-apps/api": "^2.12.3",
"@tauri-apps/plugin-process": "^2.4.0",
"@tauri-apps/plugin-updater": "^2.14.1",
"@types/eslint": "^9.6.1",
"@types/events": "^3.0.3",
"@types/file-saver": "^2.0.7",
+58
View File
@@ -0,0 +1,58 @@
import { BundleType, getBundleType, getVersion } from '@tauri-apps/api/app';
import { relaunch } from '@tauri-apps/plugin-process';
import { check, type Update } from '@tauri-apps/plugin-updater';
import { toast } from 'svelte-sonner';
import { engine } from '$lib/engine';
import { i18n } from '$lib/i18n/i18n.svelte';
/** Where the `.deb` and `.rpm` packages can be downloaded, as they do not update themselves. */
const releases = 'https://github.com/gpxstudio/gpx.studio/releases/latest';
/**
* Offers the update, if there is one. The app does not restart by itself, as it would interrupt
* the user. The beta versions are not updated, as they would be replaced by the stable release.
*/
export async function checkForUpdates() {
if (import.meta.env.DEV || (await getVersion()).includes('-')) {
return;
}
const update = await check().catch((error) => {
// most likely offline: it will be checked again the next time the app starts
console.warn('Could not check for updates', error);
return null;
});
if (update === null) {
return;
}
const message = i18n._('desktop.update_available').replace('{version}', update.version);
const bundle = await getBundleType();
if (bundle === BundleType.Deb || bundle === BundleType.Rpm) {
toast.info(message, {
duration: Number.POSITIVE_INFINITY,
action: {
label: i18n._('desktop.update_download'),
onClick: () => engine.openUrl(releases),
},
});
} else {
toast.info(message, {
duration: Number.POSITIVE_INFINITY,
action: {
label: i18n._('desktop.update_restart'),
onClick: () => install(update),
},
});
}
}
async function install(update: Update) {
const installing = toast.loading(i18n._('desktop.update_installing'));
try {
await update.downloadAndInstall();
await relaunch();
} catch (error) {
console.error('Could not install the update', error);
toast.error(i18n._('desktop.update_failed'), { id: installing });
}
}
+7
View File
@@ -598,5 +598,12 @@
"title": "This page is out of date",
"description": "Your files were saved by a newer version of gpx.studio, which this page cannot read. Reload the page to get the latest version.",
"reload": "Reload"
},
"desktop": {
"update_available": "gpx.studio {version} is available",
"update_restart": "Update and restart",
"update_download": "Download",
"update_installing": "Installing the update...",
"update_failed": "The update could not be installed"
}
}
@@ -87,6 +87,8 @@
);
}
languageRestored = true;
// in its own chunk, as the website does not need it
import('$lib/desktop/updates').then(({ checkForUpdates }) => checkForUpdates());
}
let files: string[] = JSON.parse(page.url.searchParams.get('files') || '[]');