Documentation Index Fetch the complete documentation index at: https://mintlify.com/CspmIT/mas-agua-front/llms.txt
Use this file to discover all available pages before exploring further.
The Mas Agua desktop application uses Tauri’s built-in updater plugin to deliver seamless automatic updates from GitHub Releases.
How It Works
Application checks for updates on startup or manually
Updater queries GitHub Releases for latest.json manifest
If new version available, download update bundle
Verify signature using public key
Install update and relaunch application
Configuration
Tauri Configuration
From src-tauri/tauri.conf.json:38-45:
{
"plugins" : {
"updater" : {
"active" : true ,
"endpoints" : [
"https://github.com/CspmIT/mas-agua-front/releases/latest/download/latest.json"
],
"dialog" : true ,
"pubkey" : "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IENFOUE0OEYyMDA5NDkyNEQKUldSTmtwUUE4a2lhenBraVNOd2cwOU1ZbkxWdVJTU0lEbUZiTkp0VTFRenhtdndVZ1VwUlQ4OG0K"
}
}
}
Configuration Options :
active : Enable/disable updater (true)
endpoints : Array of URLs to check for updates
dialog : Show built-in update dialog (true)
pubkey : Public key for signature verification (base64 encoded)
Rust Backend Setup
From src-tauri/src/main.rs:8:
. plugin ( tauri_plugin_updater :: Builder :: new () . build ())
The updater plugin is initialized in the Tauri builder.
Security Capabilities
From src-tauri/tauri.conf.json:28-35:
{
"security" : {
"capabilities" : [
{
"identifier" : "store-access" ,
"windows" : [ "main" ],
"platforms" : [ "linux" , "macOS" , "windows" ],
"permissions" : [
"store:default" ,
"process:default" ,
"updater:default" ,
"core:app:allow-version"
]
}
]
}
}
The updater:default permission grants access to the updater API.
Frontend Implementation
Update Hook
From src/hooks/useUpdater.js:
import { check } from '@tauri-apps/plugin-updater'
import { relaunch } from '@tauri-apps/plugin-process'
import Swal from 'sweetalert2'
import {
showInstallMessage ,
showUpdateError ,
showUpdateProgress ,
updateProgress
} from '../utils/js/updateSwal'
export const useUpdater = () => {
const checkForUpdates = async () => {
try {
// Check for available updates
const update = await check ()
if ( ! update ) return
// Show confirmation dialog
const confirm = await Swal . fire ({
title: 'Nueva versión disponible' ,
text: '¿Deseás actualizar ahora?' ,
icon: 'info' ,
showCancelButton: true ,
confirmButtonText: 'Actualizar' ,
cancelButtonText: 'Más tarde' ,
})
if ( ! confirm . isConfirmed ) return
// Download and install
let downloaded = 0
let contentLength = 0
let downloadStarted = false
showUpdateProgress ()
const timeoutId = setTimeout (() => {
if ( ! downloadStarted ) {
Swal . fire ({
icon: 'error' ,
title: 'No se pudo descargar la actualización' ,
text: 'Intenta nuevamente o descárgala manualmente' ,
})
}
}, 20000 )
await update . downloadAndInstall (( event ) => {
switch ( event . event ) {
case 'Started' :
contentLength = event . data . contentLength
downloaded = 0
downloadStarted = true
break
case 'Progress' :
downloaded += event . data . chunkLength
if ( contentLength > 0 ) {
const percent = Math . floor (( downloaded / contentLength ) * 100 )
updateProgress ( percent )
}
break
case 'Finished' :
clearTimeout ( timeoutId )
showInstallMessage ()
break
}
})
// Relaunch application
await relaunch ()
} catch ( error ) {
console . error ( 'Updater error:' , error )
showUpdateError ( 'No se pudo completar la actualización. Verificá tu conexión e intentá nuevamente.' )
}
}
return { checkForUpdates }
}
Usage in Components
import { useUpdater } from './hooks/useUpdater'
function App () {
const { checkForUpdates } = useUpdater ()
useEffect (() => {
// Check for updates on app startup
checkForUpdates ()
}, [])
return (
< button onClick = { checkForUpdates } >
Check for Updates
</ button >
)
}
Update Events
The downloadAndInstall callback receives events:
Event Description Data StartedDownload started { contentLength: number }ProgressDownload progress { chunkLength: number }FinishedDownload complete {}
Update Artifacts
Generating Update Files
From src-tauri/tauri.conf.json:15:
"createUpdaterArtifacts" : true
When building, Tauri automatically creates:
src-tauri/target/release/bundle/msi/
├── Mas Agua_1.0.5_x64_en-US.msi
├── Mas Agua_1.0.5_x64_en-US.msi.zip # Update bundle
└── Mas Agua_1.0.5_x64_en-US.msi.zip.sig # Signature
src-tauri/target/release/bundle/macos/
├── Mas Agua.app
├── Mas Agua.app.tar.gz # Update bundle
└── Mas Agua.app.tar.gz.sig # Signature
src-tauri/target/release/bundle/appimage/
├── mas-agua_1.0.5_amd64.AppImage
├── mas-agua_1.0.5_amd64.AppImage.tar.gz # Update bundle
└── mas-agua_1.0.5_amd64.AppImage.tar.gz.sig # Signature
Update Manifest (latest.json)
Create latest.json for each release:
{
"version" : "1.0.5" ,
"notes" : "Bug fixes and performance improvements" ,
"pub_date" : "2026-03-04T10:00:00Z" ,
"platforms" : {
"windows-x86_64" : {
"signature" : "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUldSTmtwUUE4a2lhenBraVNOd2cwOU1ZbkxWdVJTU0lEbUZiTkp0VTFRenhtdndVZ1VwUlQ4OG0K" ,
"url" : "https://github.com/CspmIT/mas-agua-front/releases/download/v1.0.5/Mas.Agua_1.0.5_x64_en-US.msi.zip"
},
"darwin-x86_64" : {
"signature" : "..." ,
"url" : "https://github.com/CspmIT/mas-agua-front/releases/download/v1.0.5/Mas.Agua.app.tar.gz"
},
"darwin-aarch64" : {
"signature" : "..." ,
"url" : "https://github.com/CspmIT/mas-agua-front/releases/download/v1.0.5/Mas.Agua_aarch64.app.tar.gz"
},
"linux-x86_64" : {
"signature" : "..." ,
"url" : "https://github.com/CspmIT/mas-agua-front/releases/download/v1.0.5/mas-agua_1.0.5_amd64.AppImage.tar.gz"
}
}
}
Code Signing
Generate Signing Keys
# Install Tauri CLI globally (if not already)
npm install -g @tauri-apps/cli
# Generate key pair
tauri signer generate -- -w ~/.tauri/masagua.key
This creates:
Private key : ~/.tauri/masagua.key (keep secret!)
Public key : Printed to console (add to tauri.conf.json)
NEVER commit the private key to version control. Store it securely (e.g., GitHub Secrets, password manager).
Sign Update Bundles
# Sign a file
tauri signer sign ~/.tauri/masagua.key path/to/update-bundle.zip
# Creates: update-bundle.zip.sig
Update Public Key in Config
Copy the public key output and add to tauri.conf.json:
{
"plugins" : {
"updater" : {
"pubkey" : "YOUR_PUBLIC_KEY_HERE"
}
}
}
GitHub Releases Workflow
Manual Release Process
Build for all platforms :
# On each platform (Windows, macOS, Linux)
npm run tauri build
Create GitHub Release :
gh release create v1.0.5 \
--title "v1.0.5" \
--notes "Release notes here"
Upload artifacts :
# Upload all bundles and signatures
gh release upload v1.0.5 \
src-tauri/target/release/bundle/ ** / * .{zip,tar.gz,sig}
Create and upload latest.json :
gh release upload v1.0.5 latest.json
Automated CI/CD
name : Release
on :
push :
tags :
- 'v*'
jobs :
build :
strategy :
matrix :
os : [ ubuntu-latest , macos-latest , windows-latest ]
runs-on : ${{ matrix.os }}
steps :
- uses : actions/checkout@v4
- name : Setup Node.js
uses : actions/setup-node@v4
with :
node-version : 18
- name : Install Rust
uses : dtolnay/rust-toolchain@stable
- name : Install dependencies (Linux)
if : matrix.os == 'ubuntu-latest'
run : |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev \
build-essential curl wget file libxdo-dev libssl-dev \
libayatana-appindicator3-dev librsvg2-dev
- name : Install Node dependencies
run : npm install
- name : Build Tauri app
run : npm run tauri build
env :
TAURI_SIGNING_PRIVATE_KEY : ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD : ${{ secrets.TAURI_KEY_PASSWORD }}
- name : Upload to Release
uses : softprops/action-gh-release@v1
with :
files : src-tauri/target/release/bundle/**/*.{zip,tar.gz,sig,msi,dmg,deb,rpm,AppImage}
env :
GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
create-manifest :
needs : build
runs-on : ubuntu-latest
steps :
- name : Generate latest.json
run : |
# Script to generate latest.json from uploaded artifacts
# Upload to release
Update Channels
Multiple Update Tracks
Support stable and beta channels:
{
"plugins" : {
"updater" : {
"endpoints" : [
"https://github.com/CspmIT/mas-agua-front/releases/latest/download/latest.json" ,
"https://github.com/CspmIT/mas-agua-front/releases/download/beta/latest.json"
]
}
}
}
Switch channels dynamically:
import { check } from '@tauri-apps/plugin-updater'
const checkBetaUpdates = async () => {
const update = await check ({
endpoints: [ 'https://github.com/.../beta/latest.json' ]
})
}
Troubleshooting
Updates Not Detected
Verify latest.json is accessible :
curl https://github.com/CspmIT/mas-agua-front/releases/latest/download/latest.json
Check version format : Use semantic versioning (1.0.5, not v1.0.5)
Inspect console logs : Open DevTools in development mode
Signature Verification Failed
Error : Invalid signature
Ensure public key in tauri.conf.json matches private key used for signing
Verify .sig file uploaded alongside update bundle
Re-sign bundles if keys were regenerated
Download Timeout
From src/hooks/useUpdater.js:29-37, timeout is 20 seconds:
const timeoutId = setTimeout (() => {
if ( ! downloadStarted ) {
Swal . fire ({
icon: 'error' ,
title: 'No se pudo descargar la actualización' ,
text: 'Intenta nuevamente o descárgala manualmente' ,
})
}
}, 20000 )
Increase timeout for slower connections:
const TIMEOUT_MS = 60000 // 60 seconds
Manual Update Installation
If auto-update fails, users can download manually:
Visit GitHub Releases
Download installer for their platform
Run installer to upgrade
Best Practices
Use semantic versioning: MAJOR.MINOR.PATCH
Increment MAJOR for breaking changes
Increment MINOR for new features
Increment PATCH for bug fixes
Example: 1.0.5 → 1.1.0 (new feature)
Write clear, user-friendly release notes
Highlight breaking changes prominently
Group changes by category (Features, Fixes, etc.)
Include migration instructions if needed
Test update process on all platforms before release
Verify signature validation works
Test rollback if update fails
Monitor error rates after release
Keep previous version artifacts available
Update latest.json to point to previous version if critical bug found
Communicate rollback to users via release notes
Next Steps
Building Learn how to build production releases
Desktop Overview Understand desktop architecture