You've already forked archr-flasher
mirror of
https://github.com/archr-linux/archr-flasher.git
synced 2026-07-12 18:19:47 -07:00
Add auto-update via tauri-plugin-updater + GitHub Releases
- tauri-plugin-updater + tauri-plugin-process for self-update - check_app_update / install_app_update Rust commands (UpdaterExt) - tauri.conf.json: createUpdaterArtifacts + updater endpoint - Capabilities: updater:default, process:allow-restart, dialog:allow-ask - Frontend: checkForAppUpdate() with native dialog prompt - CI/CD: replaced manual build with tauri-apps/tauri-action@v0 - includeUpdaterJson generates latest.json automatically - TAURI_SIGNING_PRIVATE_KEY for update signature verification - Rust cache via swatinem/rust-cache@v2 - i18n: app_update_title/text/updating in all 4 locales NOTE: pubkey in tauri.conf.json is placeholder — replace after running `cargo tauri signer generate` and adding secrets to GitHub. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+23
-61
@@ -15,13 +15,13 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- platform: ubuntu-22.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
args: ''
|
||||
- platform: macos-latest
|
||||
target: aarch64-apple-darwin
|
||||
args: '--target aarch64-apple-darwin'
|
||||
- platform: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
args: '--target x86_64-apple-darwin'
|
||||
- platform: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
args: ''
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
@@ -31,7 +31,12 @@ jobs:
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: './src-tauri -> target'
|
||||
|
||||
- name: Install system dependencies (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
@@ -47,9 +52,6 @@ jobs:
|
||||
libglib2.0-dev \
|
||||
libgtk-3-dev
|
||||
|
||||
- name: Install Tauri CLI
|
||||
run: cargo install tauri-cli --version "^2"
|
||||
|
||||
# macOS: import signing certificate from GitHub Secrets
|
||||
- name: Import Apple certificate
|
||||
if: runner.os == 'macOS'
|
||||
@@ -72,65 +74,25 @@ jobs:
|
||||
-k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||
|
||||
# macOS: build with signing + notarization
|
||||
- name: Build (macOS signed)
|
||||
if: runner.os == 'macOS'
|
||||
- name: Build and release
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
run: cargo tauri build --target ${{ matrix.target }}
|
||||
|
||||
# Linux/Windows: build without signing
|
||||
- name: Build
|
||||
if: runner.os != 'macOS'
|
||||
run: cargo tauri build --target ${{ matrix.target }}
|
||||
with:
|
||||
tagName: v__VERSION__
|
||||
releaseName: 'Arch R Flasher v__VERSION__'
|
||||
releaseBody: 'See the assets to download and install.'
|
||||
releaseDraft: true
|
||||
prerelease: false
|
||||
includeUpdaterJson: true
|
||||
args: ${{ matrix.args }}
|
||||
|
||||
# macOS: cleanup keychain
|
||||
- name: Cleanup keychain
|
||||
if: runner.os == 'macOS' && always()
|
||||
run: security delete-keychain $RUNNER_TEMP/app-signing.keychain-db 2>/dev/null || true
|
||||
|
||||
- name: Upload artifacts (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: archr-flasher-linux-${{ matrix.target }}
|
||||
path: |
|
||||
src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
|
||||
src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage
|
||||
|
||||
- name: Upload artifacts (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: archr-flasher-macos-${{ matrix.target }}
|
||||
path: |
|
||||
src-tauri/target/${{ matrix.target }}/release/bundle/dmg/*.dmg
|
||||
|
||||
- name: Upload artifacts (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: archr-flasher-windows-${{ matrix.target }}
|
||||
path: |
|
||||
src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi
|
||||
src-tauri/target/${{ matrix.target }}/release/bundle/nsis/*.exe
|
||||
|
||||
release:
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
draft: true
|
||||
generate_release_notes: true
|
||||
files: artifacts/**/*
|
||||
|
||||
@@ -20,6 +20,8 @@ xz2 = "0.1"
|
||||
sys-locale = "0.3"
|
||||
sha2 = "0.10"
|
||||
fs2 = "0.4"
|
||||
tauri-plugin-updater = "2"
|
||||
tauri-plugin-process = "2"
|
||||
|
||||
[features]
|
||||
default = ["custom-protocol"]
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
"core:default",
|
||||
"shell:allow-open",
|
||||
"dialog:allow-open",
|
||||
"dialog:default"
|
||||
"dialog:default",
|
||||
"dialog:allow-ask",
|
||||
"updater:default",
|
||||
"process:allow-restart"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use disk::DiskInfo;
|
||||
use github::{DownloadResult, ReleaseInfo};
|
||||
use panels::Panel;
|
||||
use tauri::Manager;
|
||||
use tauri_plugin_updater::UpdaterExt;
|
||||
|
||||
/// Returns the OS locale (e.g. "pt-BR", "en-US") for i18n.
|
||||
#[tauri::command]
|
||||
@@ -78,10 +79,55 @@ async fn flash_image(
|
||||
Ok("Flash complete".into())
|
||||
}
|
||||
|
||||
/// Check if a new version of the Flasher app is available.
|
||||
/// Returns "version|body" string if update available, null if up to date.
|
||||
#[tauri::command]
|
||||
async fn check_app_update(app: tauri::AppHandle) -> Result<Option<String>, String> {
|
||||
let update = app.updater_builder()
|
||||
.build()
|
||||
.map_err(|e| format!("{}", e))?
|
||||
.check()
|
||||
.await
|
||||
.map_err(|e| format!("{}", e))?;
|
||||
|
||||
match update {
|
||||
Some(u) => Ok(Some(format!("{}|{}", u.version, u.body.unwrap_or_default()))),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
/// Download and install the app update, then restart.
|
||||
#[tauri::command]
|
||||
async fn install_app_update(app: tauri::AppHandle) -> Result<(), String> {
|
||||
let update = app.updater_builder()
|
||||
.build()
|
||||
.map_err(|e| format!("{}", e))?
|
||||
.check()
|
||||
.await
|
||||
.map_err(|e| format!("{}", e))?;
|
||||
|
||||
if let Some(update) = update {
|
||||
update.download_and_install(|_, _| {}, || {})
|
||||
.await
|
||||
.map_err(|e| format!("{}", e))?;
|
||||
app.restart();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_process::init())
|
||||
.setup(|app| {
|
||||
#[cfg(desktop)]
|
||||
app.handle().plugin(
|
||||
tauri_plugin_updater::Builder::new().build()
|
||||
)?;
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
get_locale,
|
||||
get_panels,
|
||||
@@ -89,6 +135,8 @@ fn main() {
|
||||
check_latest_release,
|
||||
download_image,
|
||||
flash_image,
|
||||
check_app_update,
|
||||
install_app_update,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"createUpdaterArtifacts": true,
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
@@ -39,5 +40,16 @@
|
||||
"signingIdentity": null,
|
||||
"entitlements": null
|
||||
}
|
||||
},
|
||||
"plugins": {
|
||||
"updater": {
|
||||
"pubkey": "PLACEHOLDER_GERAR_COM_CARGO_TAURI_SIGNER",
|
||||
"endpoints": [
|
||||
"https://github.com/archr-linux/archr-flasher/releases/latest/download/latest.json"
|
||||
],
|
||||
"windows": {
|
||||
"installMode": "passive"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -42,5 +42,8 @@
|
||||
"error_checksum_failed": "Checksum verification failed. Re-download the image.",
|
||||
"verifying_checksum": "Verifying checksum...",
|
||||
"latest_version": "Latest: {version}",
|
||||
"offline": "Offline"
|
||||
"offline": "Offline",
|
||||
"app_update_title": "Update Available",
|
||||
"app_update_text": "Version {version} available. Update now?",
|
||||
"app_updating": "Updating..."
|
||||
}
|
||||
|
||||
+4
-1
@@ -42,5 +42,8 @@
|
||||
"error_checksum_failed": "Verificacion de checksum fallo. Descargue la imagen nuevamente.",
|
||||
"verifying_checksum": "Verificando checksum...",
|
||||
"latest_version": "Ultima: {version}",
|
||||
"offline": "Sin conexion"
|
||||
"offline": "Sin conexion",
|
||||
"app_update_title": "Actualizacion disponible",
|
||||
"app_update_text": "Version {version} disponible. Actualizar ahora?",
|
||||
"app_updating": "Actualizando..."
|
||||
}
|
||||
|
||||
+4
-1
@@ -42,5 +42,8 @@
|
||||
"error_checksum_failed": "Verificacao de checksum falhou. Baixe a imagem novamente.",
|
||||
"verifying_checksum": "Verificando checksum...",
|
||||
"latest_version": "Ultima: {version}",
|
||||
"offline": "Offline"
|
||||
"offline": "Offline",
|
||||
"app_update_title": "Atualizacao disponivel",
|
||||
"app_update_text": "Versao {version} disponivel. Atualizar agora?",
|
||||
"app_updating": "Atualizando..."
|
||||
}
|
||||
|
||||
+4
-1
@@ -42,5 +42,8 @@
|
||||
"error_checksum_failed": "校验和验证失败。请重新下载镜像。",
|
||||
"verifying_checksum": "正在验证校验和...",
|
||||
"latest_version": "最新:{version}",
|
||||
"offline": "离线"
|
||||
"offline": "离线",
|
||||
"app_update_title": "有更新可用",
|
||||
"app_update_text": "版本 {version} 可用。立即更新?",
|
||||
"app_updating": "正在更新..."
|
||||
}
|
||||
|
||||
+20
@@ -381,6 +381,7 @@ function translateError(msg) {
|
||||
async function init() {
|
||||
await initI18n();
|
||||
checkLatestVersion(); // fire-and-forget (does not block UI)
|
||||
checkForAppUpdate(); // fire-and-forget (check for flasher app update)
|
||||
}
|
||||
|
||||
async function checkLatestVersion() {
|
||||
@@ -393,4 +394,23 @@ async function checkLatestVersion() {
|
||||
}
|
||||
}
|
||||
|
||||
async function checkForAppUpdate() {
|
||||
try {
|
||||
const result = await window.__TAURI__.core.invoke('check_app_update');
|
||||
if (!result) return;
|
||||
|
||||
const [version, ...rest] = result.split('|');
|
||||
const yes = await window.__TAURI__.dialog.ask(
|
||||
t('app_update_text', { version }),
|
||||
{ title: t('app_update_title'), kind: 'info' }
|
||||
);
|
||||
if (!yes) return;
|
||||
|
||||
setStatus(t('app_updating'), '');
|
||||
await window.__TAURI__.core.invoke('install_app_update');
|
||||
} catch (_) {
|
||||
// offline or error — ignore silently
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
Reference in New Issue
Block a user