Skip to content

Commit fdc5813

Browse files
committed
fix: auto updater tauri
1 parent 10b9df8 commit fdc5813

16 files changed

Lines changed: 680 additions & 46 deletions

.github/workflows/desktop-release.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,19 @@ jobs:
7070
working-directory: web
7171
env:
7272
RELEASE_VERSION: 0.1.${{ github.run_number }}
73+
UPDATER_ENDPOINT: https://github.com/${{ github.repository }}/releases/download/desktop/latest.json
74+
UPDATER_PUBKEY: ${{ secrets.TAURI_UPDATER_PUBKEY }}
7375
run: |
76+
if [ -z "$UPDATER_PUBKEY" ]; then
77+
echo "Secret TAURI_UPDATER_PUBKEY manquant."
78+
exit 1
79+
fi
80+
7481
python3 << 'PY'
7582
import json, os, re
7683
version = os.environ["RELEASE_VERSION"]
84+
updater_endpoint = os.environ["UPDATER_ENDPOINT"]
85+
updater_pubkey = os.environ["UPDATER_PUBKEY"]
7786
os.chdir("src-tauri")
7887
with open("Cargo.toml", encoding="utf-8") as f:
7988
lines = f.read().splitlines(keepends=True)
@@ -93,6 +102,13 @@ jobs:
93102
with open("tauri.conf.json", encoding="utf-8") as f:
94103
conf = json.load(f)
95104
conf["version"] = version
105+
conf.setdefault("bundle", {})
106+
conf["bundle"]["createUpdaterArtifacts"] = True
107+
conf.setdefault("plugins", {})
108+
conf["plugins"]["updater"] = {
109+
"endpoints": [updater_endpoint],
110+
"pubkey": updater_pubkey
111+
}
96112
with open("tauri.conf.json", "w", encoding="utf-8") as f:
97113
json.dump(conf, f, indent=2, ensure_ascii=False)
98114
f.write("\n")
@@ -109,6 +125,8 @@ jobs:
109125
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
110126
NUXT_PUBLIC_API_BASE: ${{ secrets.NUXT_PUBLIC_API_BASE }}
111127
NUXT_PUBLIC_GITHUB_REPO: ${{ github.repository }}
128+
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
129+
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
112130
with:
113131
projectPath: web
114132
tagName: desktop

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ api/.venv
44
api/__pycache__
55
api/*.pyc
66
api/.env
7-
web/.env
7+
web/.env
8+
web/goupixdex.key
9+
web/goupixdex.key.pub

api/README.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,24 @@ api/
4343

4444
- Python **3.10+**
4545
- MariaDB or MySQL (local or Docker)
46-
- Optional: `POKE_WALLET_API_KEY`, `GROQ_API_KEY`, **Chromium** for Vinted (voir ci-dessous)
46+
- Optional: `POKE_WALLET_API_KEY`, `GROQ_API_KEY`, **Chromium** for Vinted (see below)
4747

48-
### Vinted (Chromium) et Xvfb
48+
### Vinted (Chromium) and Xvfb
4949

50-
La publication Vinted lance **Chromium** via **nodriver**. Sur une machine **sans écran** (VPS, conteneur, CI), `VINTED_BROWSER_HEADLESS=false` exige un **DISPLAY** : le dépôt prévoit **Xvfb** pour ne rien configurer à la main.
50+
Vinted publishing launches **Chromium** through **nodriver**. On a **headless machine** (VPS, container, CI), `VINTED_BROWSER_HEADLESS=false` requires a **DISPLAY**: this repository uses **Xvfb** so no manual display setup is needed.
5151

52-
| Environnement | Comportement |
52+
| Environment | Behavior |
5353
|----------------|---------------|
54-
| **Docker Compose** (`api/`) | L’image installe **chromium**, **xvfb**, **xauth** ; la commande de service enveloppe **uvicorn** avec **`xvfb-run`**. Aucune étape manuelle. |
55-
| **Déploiement GitHub → VPS** (`.github/workflows/deploy-api.yml`) | `apt install` inclut **xvfb** et **xauth** ; l’unité **systemd** lance Uvicorn sous **`xvfb-run`**. |
56-
| **Linux sans Docker** (venv + systemd maison) | Installez `xvfb` et `xauth` (`apt install xvfb xauth`), puis lancez l’API avec : `xvfb-run -a --server-args="-screen 0 1920x1080x24" uvicorn …` si `VINTED_BROWSER_HEADLESS=false`. |
57-
| **Windows (dev)** | Pas besoin d’Xvfb ; utilisez `VINTED_BROWSER_HEADLESS=false` avec un bureau local, ou `run_dev.py` si vous utilisez `--reload` avec Vinted. |
54+
| **Docker Compose** (`api/`) | The image installs **chromium**, **xvfb**, and **xauth**; the service command wraps **uvicorn** with **`xvfb-run`**. No manual step required. |
55+
| **GitHub → VPS deploy** (`.github/workflows/deploy-api.yml`) | `apt install` includes **xvfb** and **xauth**; the **systemd** unit runs Uvicorn under **`xvfb-run`**. |
56+
| **Linux without Docker** (venv + custom systemd) | Install `xvfb` and `xauth` (`apt install xvfb xauth`), then run the API with: `xvfb-run -a --server-args="-screen 0 1920x1080x24" uvicorn …` when `VINTED_BROWSER_HEADLESS=false`. |
57+
| **Windows (dev)** | No Xvfb needed; use `VINTED_BROWSER_HEADLESS=false` with a local desktop session, or use `run_dev.py` when running `--reload` with Vinted. |
5858

59-
**GitHub Actions (secret optionnel)** : `VINTED_BROWSER_HEADLESS`si absent ou vide, la valeur générée sur le VPS reste **`true`** (comportement historique). Mettez **`false`** pour un Chromium fenêtré sur Xvfb (souvent moins refusé par Vinted que le headless intégré). **Cloudflare / IP hébergeur** peuvent quand même bloquer des requêtes : un `curl` en **403** depuis le VPS alors qu’un navigateur répond **200** est possible.
59+
**GitHub Actions (optional secret)**: `VINTED_BROWSER_HEADLESS`if missing or empty, the value generated on the VPS remains **`true`** (historical behavior). Set **`false`** for a headed Chromium session on Xvfb (often less likely to be blocked by Vinted than built-in headless mode). **Cloudflare / hosting IPs** can still block requests: it is possible to get a **403** from `curl` on the VPS while a browser returns **200**.
6060

61-
Variables utiles dans `.env` / `.env.example` : `VINTED_BROWSER_HEADLESS`, `VINTED_CHROME_EXECUTABLE` (souvent `/usr/bin/chromium` sous Linux).
61+
Useful variables in `.env` / `.env.example`: `VINTED_BROWSER_HEADLESS`, `VINTED_CHROME_EXECUTABLE` (often `/usr/bin/chromium` on Linux).
6262

63-
**Windows / macOS (app desktop)** : avec `VINTED_BROWSER_HEADLESS=false`, le mode **`VINTED_BROWSER_DISCREET=true`** (défaut) garde `--start-maximized`, puis applique `--window-position` (hors écran) + `--start-minimized` pour rester discret tout en gardant un rendu "headed". Vous pouvez désactiver la minimisation via `VINTED_BROWSER_DISCREET_MINIMIZE=false`. Sur **Linux + Xvfb plein écran**, mettre `VINTED_BROWSER_DISCREET=false` pour garder le comportement standard.
63+
**Windows / macOS (desktop app)**: with `VINTED_BROWSER_HEADLESS=false`, **`VINTED_BROWSER_DISCREET=true`** (default) keeps `--start-maximized`, then applies `--window-position` (off-screen) + `--start-minimized` to stay discreet while keeping a headed rendering path. You can disable minimization with `VINTED_BROWSER_DISCREET_MINIMIZE=false`. On **Linux + full-screen Xvfb**, set `VINTED_BROWSER_DISCREET=false` to keep standard behavior.
6464

6565
## Install
6666

@@ -113,13 +113,13 @@ python migrations/run_migrations.py
113113
uvicorn main:app --reload --host 0.0.0.0 --port 8000
114114
```
115115

116-
Sous **Windows**, si vous utilisez **`--reload`** et la publication **Vinted** (nodriver / Chrome), uvicorn choisit une boucle sans support des sous-processus → erreur `NotImplementedError` dans nodriver. Utilisez plutôt :
116+
On **Windows**, if you use **`--reload`** with **Vinted** publishing (nodriver / Chrome), uvicorn can pick an event loop without subprocess support → `NotImplementedError` in nodriver. Use instead:
117117

118118
```bash
119119
python run_dev.py
120120
```
121121

122-
ou explicitement (Windows uniquementla classe stdlib `ProactorEventLoop`) :
122+
or explicitly (Windows only — stdlib `ProactorEventLoop` class):
123123

124124
```bash
125125
uvicorn main:app --reload --host 0.0.0.0 --port 8000 --loop asyncio.windows_events:ProactorEventLoop
@@ -159,16 +159,16 @@ From `api/`:
159159
docker compose up --build
160160
```
161161

162-
- API: port **8000** (migrations + seed conditionnel au démarrage, puis **uvicorn** sous **`xvfb-run`** pour Vinted)
162+
- API: port **8000** (migrations + optional seed at startup, then **uvicorn** under **`xvfb-run`** for Vinted)
163163
- MariaDB: **3306**
164164
- phpMyAdmin: **8080**
165-
- L’image inclut **Chromium**, **Xvfb** et **xauth** ; les variables `VINTED_*` et **Supabase** peuvent être définies dans un fichier **`.env`** à côté de `docker-compose.yml` (substitution `${…}` — voir [Compose env files](https://docs.docker.com/compose/environment-variables/set-environment-variables/)).
165+
- The image includes **Chromium**, **Xvfb**, and **xauth**; `VINTED_*` and **Supabase** variables can be defined in a **`.env`** file next to `docker-compose.yml` (`${…}` substitution — see [Compose env files](https://docs.docker.com/compose/environment-variables/set-environment-variables/)).
166166

167167
Create a user after startup: `docker compose exec api python seeders/user_seeder.py` (with env vars set), or use `POST /users` and `POST /auth/login`.
168168

169-
### Déploiement API (GitHub → VPS)
169+
### API deployment (GitHub → VPS)
170170

171-
Le workflow **Deploy API** installe **xvfb** et **xauth**, écrit l’unité **systemd** avec **`ExecStart=/usr/bin/xvfb-run … uvicorn`**, et peut fixer **`VINTED_BROWSER_HEADLESS`** via le secret du même nom (défaut **`true`** si le secret est absent). Aucune installation manuelle de Xvfb sur le VPS n’est nécessaire après un déploiement via cette CI.
171+
The **Deploy API** workflow installs **xvfb** and **xauth**, writes the **systemd** unit with **`ExecStart=/usr/bin/xvfb-run … uvicorn`**, and can set **`VINTED_BROWSER_HEADLESS`** via the secret of the same name (default **`true`** when the secret is missing). No manual Xvfb installation is required on the VPS after deploying through this CI.
172172

173173
## Limitations
174174

web/README.md

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
11
# GoupixDex Web + Desktop UI (Nuxt 4 + Tauri)
22

3-
Frontend unique partagé entre :
3+
Single frontend shared between:
44

5-
- la version **web** (Nuxt 4),
6-
- la version **desktop** (Tauri, Windows + macOS).
5+
- the **web** version (Nuxt 4),
6+
- the **desktop** version (Tauri, Windows + macOS).
77

8-
## Prérequis
8+
## Prerequisites
99

1010
- Node.js 22+
1111
- npm 10+
12-
- Pour Tauri local : Rust toolchain installé
12+
- For local Tauri: Rust toolchain installed
1313

1414
## Installation
1515

1616
```bash
1717
npm install
1818
```
1919

20-
## Variables d’environnement
20+
## Environment variables
2121

22-
Exemple dans `.env.example` :
22+
Example in `.env.example`:
2323

24-
- `NUXT_PUBLIC_API_BASE` : URL API distante (prod ou local)
25-
- `NUXT_PUBLIC_GITHUB_REPO` : slug `owner/repo` pour la page Download
26-
- `NUXT_PUBLIC_DESKTOP_RELEASE_CHANNEL` : `latest` ou tag GitHub Release
27-
- `NUXT_PUBLIC_GITHUB_API_BASE` : API GitHub (défaut `https://api.github.com`)
24+
- `NUXT_PUBLIC_API_BASE`: remote API URL (prod or local)
25+
- `NUXT_PUBLIC_GITHUB_REPO`: `owner/repo` slug for the Download page
26+
- `NUXT_PUBLIC_DESKTOP_RELEASE_CHANNEL`: `latest` or a GitHub Release tag
27+
- `NUXT_PUBLIC_GITHUB_API_BASE`: GitHub API base (default `https://api.github.com`)
2828

29-
## Développement web
29+
## Web development
3030

3131
```bash
3232
npm run dev
@@ -38,34 +38,34 @@ npm run dev
3838
npm run build
3939
```
4040

41-
## Version desktop (Tauri)
41+
## Desktop version (Tauri)
4242

4343
### Dev desktop
4444

4545
```bash
4646
npm run tauri:dev
4747
```
4848

49-
Si vous voyez une erreur Cargo du type :
49+
If you see a Cargo error like:
5050

5151
`this version of Cargo is older than the 2024 edition`
5252

53-
mettez à jour Rust/Cargo (Windows/macOS/Linux) :
53+
update Rust/Cargo (Windows/macOS/Linux):
5454

5555
```bash
5656
rustup self update
5757
rustup update stable
5858
rustup default stable
5959
```
6060

61-
Puis redémarrez le terminal et vérifiez :
61+
Then restart your terminal and check:
6262

6363
```bash
6464
cargo -V
6565
rustc -V
6666
```
6767

68-
Sous Windows, si la version ne change pas, vérifiez que `cargo` pointe bien vers `~/.cargo/bin` :
68+
On Windows, if the version does not change, ensure `cargo` points to `~/.cargo/bin`:
6969

7070
```bash
7171
where cargo
@@ -78,14 +78,49 @@ where rustc
7878
npm run tauri:build
7979
```
8080

81-
La commande génère d’abord le frontend Nuxt en mode desktop (`NUXT_DESKTOP_BUILD=1`) puis bundle l’application via Tauri.
81+
The command first builds the Nuxt frontend in desktop mode (`NUXT_DESKTOP_BUILD=1`), then bundles the app with Tauri.
8282

83-
## Comportement Vinted
83+
## Vinted behavior
8484

85-
- **Web** : fonctionnalités de mise en ligne Vinted désactivées, avec message d’orientation vers la page de téléchargement.
86-
- **Desktop** : fonctionnalités Vinted disponibles (runtime détecté via Tauri WebView).
85+
- **Web**: Vinted publishing features are disabled, with a message pointing users to the download page.
86+
- **Desktop**: Vinted features are available (runtime detected through Tauri WebView).
8787

8888
## CI/CD
8989

9090
- `deploy-web.yml` : build + déploiement web (Nitro + PM2).
9191
- `desktop-release.yml` : build desktop Windows/macOS en **release** (binaire sans console Windows) et publication sur GitHub Release stable (`desktop`, non-prerelease).
92+
93+
## Tauri updater: key generation and GitHub secrets
94+
95+
From the `web/` folder, generate the keypair:
96+
97+
```bash
98+
npx @tauri-apps/cli signer generate -w goupixdex.key
99+
```
100+
101+
Read the private key (to copy into a GitHub secret):
102+
103+
```bash
104+
cat goupixdex.key
105+
```
106+
107+
If you are using PowerShell:
108+
109+
```powershell
110+
Get-Content .\goupixdex.key -Raw
111+
```
112+
113+
Then configure these 3 secrets in `GitHub > Settings > Secrets and variables > Actions`:
114+
115+
- `TAURI_SIGNING_PRIVATE_KEY`
116+
- Value: full contents of `goupixdex.key` (Tauri/minisign format, as-is, including line breaks).
117+
- Note: it is normal not to have `BEGIN PRIVATE KEY` / `END PRIVATE KEY`.
118+
- `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`
119+
- Value: the password entered during `signer generate`.
120+
- `TAURI_UPDATER_PUBKEY`
121+
- Value: the public key generated by the command (`signer generate`) or the contents of `goupixdex.key.pub`.
122+
123+
Important:
124+
125+
- Never commit `goupixdex.key` or `goupixdex.key.pub`.
126+
- Keep `goupixdex.key` in a secure location (secret manager, vault, etc.).
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { check } from '@tauri-apps/plugin-updater'
2+
3+
export default defineNuxtPlugin(async () => {
4+
const { isDesktopApp } = useDesktopRuntime()
5+
6+
if (!isDesktopApp.value || !import.meta.client) {
7+
return
8+
}
9+
10+
if (window.sessionStorage.getItem('goupix-updater-checked') === '1') {
11+
return
12+
}
13+
window.sessionStorage.setItem('goupix-updater-checked', '1')
14+
15+
try {
16+
const update = await check()
17+
18+
if (!update) {
19+
return
20+
}
21+
22+
const confirmed = window.confirm(
23+
`Une mise a jour ${update.version} est disponible.\n\n` +
24+
'Voulez-vous la telecharger et l installer maintenant ?'
25+
)
26+
27+
if (!confirmed) {
28+
return
29+
}
30+
31+
await update.downloadAndInstall()
32+
33+
window.alert(
34+
'La mise a jour est installee. Fermez puis relancez GoupixDex pour appliquer la nouvelle version.'
35+
)
36+
} catch (error) {
37+
console.error('[Updater] Echec de verification/installation de mise a jour:', error)
38+
}
39+
})

web/package-lock.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@internationalized/date": "^3.12.0",
2121
"@nuxt/ui": "^4.6.1",
2222
"@tanstack/table-core": "^8.21.3",
23+
"@tauri-apps/plugin-updater": "^2.10.1",
2324
"@unovis/ts": "^1.6.4",
2425
"@unovis/vue": "^1.6.4",
2526
"@vueuse/core": "^14.2.1",
@@ -34,8 +35,8 @@
3435
"zod": "^4.3.6"
3536
},
3637
"devDependencies": {
37-
"@tauri-apps/cli": "^2.0.0",
3838
"@nuxt/eslint": "^1.15.2",
39+
"@tauri-apps/cli": "^2.0.0",
3940
"@types/node": "^25.5.2",
4041
"cross-env": "^10.1.0",
4142
"eslint": "^10.2.0",

0 commit comments

Comments
 (0)