diff --git a/.github/workflows/fractured-launcher-ci.yml b/.github/workflows/fractured-launcher-ci.yml index d66a062..3339e4c 100644 --- a/.github/workflows/fractured-launcher-ci.yml +++ b/.github/workflows/fractured-launcher-ci.yml @@ -38,9 +38,13 @@ jobs: cache-dependency-path: tools/fractured-launcher-electron/package-lock.json - name: Install and pack (NSIS + portable) + env: + GITEA_BASE_URL: ${{ secrets.GITEA_BASE_URL }} + GITEA_OWNER: ${{ secrets.GITEA_OWNER }} + GITEA_REPO: ${{ secrets.GITEA_REPO }} run: | npm ci - npx electron-builder --win nsis portable --x64 --publish never + npm run pack:win - uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/gitea-release-sync.yml b/.github/workflows/gitea-release-sync.yml index e7e77fa..dd8f571 100644 --- a/.github/workflows/gitea-release-sync.yml +++ b/.github/workflows/gitea-release-sync.yml @@ -74,11 +74,15 @@ jobs: - name: Install and pack (NSIS + portable) working-directory: tools/fractured-launcher-electron + env: + # Same values as upload step — baked into default-launcher.json (no token). + GITEA_BASE_URL: ${{ secrets.GITEA_BASE_URL }} + GITEA_OWNER: ${{ secrets.GITEA_OWNER }} + GITEA_REPO: ${{ secrets.GITEA_REPO }} run: | npm ci - # --publish never: on tagged checkouts electron-builder otherwise tries to - # push to GitHub releases and fails without GH_TOKEN (we upload via Gitea). - npx electron-builder --win nsis portable --x64 --publish never + # pack:win runs inject-release-channel.js then electron-builder --publish never + npm run pack:win - name: Stage launcher files for upload shell: pwsh diff --git a/tools/fractured-launcher-electron/README.md b/tools/fractured-launcher-electron/README.md index 6a424e4..541ee11 100644 --- a/tools/fractured-launcher-electron/README.md +++ b/tools/fractured-launcher-electron/README.md @@ -35,6 +35,15 @@ Produces under **`dist/`**: | `Fractured-Launcher-${version}-Setup.exe` (NSIS) | **Recommended for players** — supports seamless **auto-update** and restart. | | `Fractured-Launcher-${version}-Windows-Portable.exe` | No installer; players replace the file manually. Auto-update is **less reliable** than NSIS. | +### Baked Gitea channel (non-token) + +**`npm run pack:win`** runs **`scripts/inject-release-channel.js`** first. It merges **`gitea.base_url`**, **`owner`**, **`repo`**, and optional **`release_tag`** into **`default-launcher.json`** for that build only (then **electron-builder** packs that file). + +- **GitHub Actions** — **Sync release to Gitea** and **Fractured launcher CI** export **`GITEA_BASE_URL`**, **`GITEA_OWNER`**, **`GITEA_REPO`** (same names as your upload secrets) for the pack step, so installers match the repo you sync to. Nothing embeds **`GITEA_TOKEN`**. +- **Local packs** — put the same values in **`fractured-release-channel.json`** (committed or personal copy) **or** export those env vars before **`npm run pack:win`**. + +First launch still copies **`default-launcher.json`** → **`launcher.json`** beside the exe, so players get the baked **`gitea.*`** without editing unless they override. + ## Auto-update behaviour - **Packaged** builds only (`npm run pack:win` output). In `npm start` dev mode, update checks are skipped (button still explains that). @@ -81,7 +90,7 @@ CI workflow **Sync release to Gitea** (`.github/workflows/gitea-release-sync.yml **Optional variable** (Settings → Variables): **`GITEA_TARGET_REF`** — default branch/commitish used **only when the workflow must create a new Gitea release** and Gitea needs `target_commitish` (defaults to **`main`** in the upload script if unset). -**Player `launcher.json`:** set **`gitea`** so **`from_release`** files resolve on your instance: +**Player `launcher.json`:** packaged builds should already include **`gitea.base_url` / `owner` / `repo`** from the bake step above. Players only need to set **`GITEA_TOKEN`** (or your **`token_env`**) if the Gitea repo is **private**. To point at another instance, edit **`gitea`** in **`launcher.json`**: ```json "gitea": { diff --git a/tools/fractured-launcher-electron/fractured-release-channel.json b/tools/fractured-launcher-electron/fractured-release-channel.json new file mode 100644 index 0000000..8663169 --- /dev/null +++ b/tools/fractured-launcher-electron/fractured-release-channel.json @@ -0,0 +1,8 @@ +{ + "gitea": { + "base_url": "", + "owner": "", + "repo": "", + "release_tag": "latest" + } +} diff --git a/tools/fractured-launcher-electron/package.json b/tools/fractured-launcher-electron/package.json index e480994..3adbd44 100644 --- a/tools/fractured-launcher-electron/package.json +++ b/tools/fractured-launcher-electron/package.json @@ -9,8 +9,8 @@ }, "scripts": { "start": "electron .", - "pack:win": "electron-builder --win nsis portable --x64 --publish never", - "publish:win": "electron-builder --win nsis portable --x64 --publish never" + "pack:win": "node scripts/inject-release-channel.js && electron-builder --win nsis portable --x64 --publish never", + "publish:win": "node scripts/inject-release-channel.js && electron-builder --win nsis portable --x64 --publish never" }, "author": "", "license": "GPL-3.0", diff --git a/tools/fractured-launcher-electron/scripts/inject-release-channel.js b/tools/fractured-launcher-electron/scripts/inject-release-channel.js new file mode 100644 index 0000000..e14f874 --- /dev/null +++ b/tools/fractured-launcher-electron/scripts/inject-release-channel.js @@ -0,0 +1,77 @@ +#!/usr/bin/env node +'use strict'; + +/** + * Merge Gitea release channel (non-token) into default-launcher.json before pack. + * Precedence: env → fractured-release-channel.json → leave existing default-launcher values. + * + * Env (any of these names): + * FRACTURED_LAUNCHER_GITEA_BASE_URL | GITEA_BASE_URL + * FRACTURED_LAUNCHER_GITEA_OWNER | GITEA_OWNER + * FRACTURED_LAUNCHER_GITEA_REPO | GITEA_REPO + * FRACTURED_LAUNCHER_GITEA_RELEASE_TAG | GITEA_RELEASE_TAG + */ +const fs = require('fs'); +const path = require('path'); + +const root = path.join(__dirname, '..'); +const defPath = path.join(root, 'default-launcher.json'); +const channelPath = path.join(root, 'fractured-release-channel.json'); + +function pickEnv() { + return { + base_url: String( + process.env.FRACTURED_LAUNCHER_GITEA_BASE_URL || process.env.GITEA_BASE_URL || '' + ).trim(), + owner: String( + process.env.FRACTURED_LAUNCHER_GITEA_OWNER || process.env.GITEA_OWNER || '' + ).trim(), + repo: String( + process.env.FRACTURED_LAUNCHER_GITEA_REPO || process.env.GITEA_REPO || '' + ).trim(), + release_tag: String( + process.env.FRACTURED_LAUNCHER_GITEA_RELEASE_TAG || process.env.GITEA_RELEASE_TAG || '' + ).trim(), + }; +} + +function main() { + const cfg = JSON.parse(fs.readFileSync(defPath, 'utf8')); + cfg.gitea = cfg.gitea && typeof cfg.gitea === 'object' ? cfg.gitea : {}; + + let fileGitea = {}; + try { + const raw = JSON.parse(fs.readFileSync(channelPath, 'utf8')); + if (raw && raw.gitea && typeof raw.gitea === 'object') fileGitea = raw.gitea; + } catch (e) { + if (e.code !== 'ENOENT') throw e; + } + + const env = pickEnv(); + const keys = ['base_url', 'owner', 'repo', 'release_tag']; + let changed = false; + + for (const k of keys) { + const fromEnv = env[k]; + const fromFile = + fileGitea[k] != null && String(fileGitea[k]).trim() !== '' ? String(fileGitea[k]).trim() : ''; + const val = (fromEnv && String(fromEnv).trim()) || fromFile; + if (!val) continue; + if (cfg.gitea[k] !== val) { + cfg.gitea[k] = val; + changed = true; + } + } + + if (!changed) { + console.log( + 'inject-release-channel: no overrides (set GITEA_* env and/or fill fractured-release-channel.json)' + ); + return; + } + + fs.writeFileSync(defPath, `${JSON.stringify(cfg, null, 2)}\n`, 'utf8'); + console.log('inject-release-channel: wrote gitea.* into default-launcher.json for this build'); +} + +main();