Files
Fractured/tools/fractured-launcher-electron/lib/gitea-release.js
T
Docker Build 2a3107a78d feat(launcher): Linux AppImage 1.0.2, Gitea sync + CI, manual pack script
- Add pack:linux (AppImage x64), linux/appImage artifact names in package.json.
- Gitea sync: parallel build-electron-linux, merge Windows+Linux into Gitea upload;
  rename Windows artifact to electron-dist-windows.
- Fractured launcher CI: electron-launcher-windows + electron-launcher-linux jobs.
- scripts/manual-pack-linux.sh for local test builds from current tree.
- Normalize Gitea base_url (prepend https if missing); baked channel uses full URL.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 20:50:06 -05:00

108 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
const { downloadBodyToFile } = require('./http-download');
function normalizeGiteaBaseUrl(raw) {
let b = String(raw || '').trim().replace(/\/+$/, '');
if (!b) return '';
if (!/^https?:\/\//i.test(b)) b = `https://${b}`;
return b;
}
function giteaApiBase(cfg) {
const base = normalizeGiteaBaseUrl(cfg.gitea.base_url);
return `${base}/api/v1`;
}
function giteaToken(cfg) {
const name = cfg.gitea && cfg.gitea.token_env;
if (name && process.env[name]) return String(process.env[name]).trim();
return String(process.env.GITEA_TOKEN || '').trim();
}
function giteaHeaders(token, json = false) {
const h = { 'User-Agent': 'Fractured-Launcher-Electron' };
if (json) h.Accept = 'application/json';
if (token) h.Authorization = `token ${token}`;
return h;
}
function useGiteaReleases(cfg) {
const g = cfg.gitea;
if (!g) return false;
return !!(String(g.base_url || '').trim() && String(g.owner || '').trim() && String(g.repo || '').trim());
}
async function downloadGiteaReleaseAsset(cfg, assetName, destPath) {
const api = giteaApiBase(cfg);
const { owner, repo } = cfg.gitea;
const tag = (cfg.gitea.release_tag || 'latest').trim() || 'latest';
const token = giteaToken(cfg);
let listUrl;
if (tag.toLowerCase() === 'latest') {
listUrl = `${api}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/releases/latest`;
} else {
listUrl = `${api}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/releases/tags/${encodeURIComponent(tag)}`;
}
const res = await fetch(listUrl, { headers: giteaHeaders(token, true) });
const text = await res.text();
if (!res.ok) {
let hint = '';
if (res.status === 404) hint = ' (wrong tag / no release / check base_url owner repo)';
if (res.status === 401 || res.status === 403) hint = ' (set GITEA_TOKEN or gitea.token_env)';
throw new Error(`Gitea release ${res.status}${hint}: ${text.slice(0, 600)}`);
}
const rel = JSON.parse(text);
const list = rel.attachments || rel.assets || [];
let downloadUrl = '';
for (const a of list) {
if (a.name !== assetName) continue;
downloadUrl = a.browser_download_url || a.download_url || '';
break;
}
if (!downloadUrl) {
const names = list.map((x) => x.name).filter(Boolean);
throw new Error(`Gitea release asset "${assetName}" not found; attachments: ${names.join(', ') || '(none)'}`);
}
const h = { Accept: 'application/octet-stream' };
if (token) h.Authorization = `token ${token}`;
const dl = await fetch(downloadUrl, { headers: h, redirect: 'follow' });
await downloadBodyToFile(dl, destPath);
}
/**
* Base URL for electron-updater generic provider (expects latest.yml under this path).
* Matches Giteas pattern: …/owner/repo/releases/download/{tag}/latest.yml
*/
async function getGiteaUpdaterFeedBase(cfg) {
if (!useGiteaReleases(cfg)) return null;
const api = giteaApiBase(cfg);
const { owner, repo } = cfg.gitea;
const tag = (cfg.gitea.release_tag || 'latest').trim() || 'latest';
const token = giteaToken(cfg);
let listUrl;
if (tag.toLowerCase() === 'latest') {
listUrl = `${api}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/releases/latest`;
} else {
listUrl = `${api}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/releases/tags/${encodeURIComponent(tag)}`;
}
const res = await fetch(listUrl, { headers: giteaHeaders(token, true) });
if (!res.ok) return null;
const rel = await res.json();
const tagName = rel.tag_name;
if (!tagName || typeof tagName !== 'string') return null;
const root = normalizeGiteaBaseUrl(cfg.gitea.base_url);
const url = `${root}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/releases/download/${encodeURIComponent(tagName)}/`;
return { url, token };
}
module.exports = {
downloadGiteaReleaseAsset,
giteaToken,
useGiteaReleases,
getGiteaUpdaterFeedBase,
};