#!/usr/bin/env node import { execSync } from 'child_process'; import { readFileSync, writeFileSync, statSync, existsSync } from 'fs'; import { resolve, basename } from 'path'; const ROOT = resolve(import.meta.dirname, '..'); const PRODUCT_NAME = 'Multi-Hoster-Upload'; const REPO = 'Administrator/Multi-Hoster-Upload-2'; const BASE = process.env.GITEA_BASE_URL || 'https://git.24-music.de'; const args = process.argv.slice(2); const version = args.find(a => /^\d+\.\d+\.\d+$/.test(a)); const notes = args.filter(a => a !== version).join(' ') || `${PRODUCT_NAME} v${version}`; if (!version) { console.error('Usage: node scripts/release_gitea.mjs [notes]'); process.exit(1); } const tag = `v${version}`; const sh = (cmd) => { console.log(` $ ${cmd}`); return execSync(cmd, { cwd: ROOT, encoding: 'utf-8' }).trim(); }; function resolveToken() { if (process.env.GITEA_TOKEN) return process.env.GITEA_TOKEN; const out = execSync('git credential fill', { input: 'protocol=https\nhost=git.24-music.de\n\n', encoding: 'utf-8', cwd: ROOT }); return (out.match(/password=(.+)/) || [])[1]?.trim(); } async function api(method, path, token, body) { const r = await fetch(`${BASE}${path}`, { method, headers: { Authorization: `token ${token}`, 'Content-Type': 'application/json' }, body: body ? JSON.stringify(body) : undefined, }); const text = await r.text(); let json = null; try { json = JSON.parse(text); } catch {} if (!r.ok && r.status !== 409 && r.status !== 422) throw new Error(`Gitea ${r.status}: ${text.slice(0, 300)}`); return { status: r.status, data: json }; } async function uploadAsset(releaseId, filePath, token) { const name = basename(filePath); const size = statSync(filePath).size; console.log(` Uploading ${name} (${(size/1024/1024).toFixed(1)} MB)...`); const buf = readFileSync(filePath); const form = new FormData(); form.append('attachment', new Blob([buf]), name); const r = await fetch( `${BASE}/api/v1/repos/${REPO}/releases/${releaseId}/assets?name=${encodeURIComponent(name)}`, { method: 'POST', headers: { Authorization: `token ${token}` }, body: form } ); if (!r.ok) throw new Error(`upload ${name}: ${r.status}`); console.log(` ok`); } (async () => { const token = resolveToken(); if (!token) { console.error('No token'); process.exit(1); } try { sh('git remote get-url gitea'); } catch { sh(`git remote add gitea https://git.24-music.de/${REPO}.git`); } const pkgPath = resolve(ROOT, 'package.json'); const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')); pkg.version = version; writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n'); const cargoPath = resolve(ROOT, 'src-tauri/Cargo.toml'); const cargo = readFileSync(cargoPath, 'utf-8').replace(/^version = "[^"]+"/m, `version = "${version}"`); writeFileSync(cargoPath, cargo); const tauriPath = resolve(ROOT, 'src-tauri/tauri.conf.json'); const tauri = JSON.parse(readFileSync(tauriPath, 'utf-8')); tauri.version = version; writeFileSync(tauriPath, JSON.stringify(tauri, null, 2) + '\n'); sh('git add package.json src-tauri/Cargo.toml src-tauri/tauri.conf.json'); try { sh(`git commit -m "release: ${tag}"`); } catch {} try { sh(`git tag ${tag}`); } catch {} try { sh('git push gitea HEAD:master'); } catch (e) { console.log(' push HEAD warn'); } try { sh(`git push gitea ${tag}`); } catch {} const exePath = resolve(ROOT, 'src-tauri/target/release/multi-hoster-upload.exe'); const nsisPath = resolve(ROOT, `src-tauri/target/release/bundle/nsis/Multi-Hoster-Upload_${version}_x64-setup.exe`); const msiPath = resolve(ROOT, `src-tauri/target/release/bundle/msi/Multi-Hoster-Upload_${version}_x64_en-US.msi`); for (const p of [exePath, nsisPath, msiPath]) { if (!existsSync(p)) { console.error(`Missing: ${p}`); process.exit(1); } } let releaseId; const created = await api('POST', `/api/v1/repos/${REPO}/releases`, token, { tag_name: tag, name: `${PRODUCT_NAME} ${tag}`, body: notes }); if (created.status === 409 || created.status === 422) { const existing = await api('GET', `/api/v1/repos/${REPO}/releases/tags/${tag}`, token); releaseId = existing.data.id; console.log(`Release exists (id=${releaseId})`); } else { releaseId = created.data.id; console.log(`Created release (id=${releaseId})`); } await uploadAsset(releaseId, exePath, token); await uploadAsset(releaseId, nsisPath, token); await uploadAsset(releaseId, msiPath, token); console.log(`\nhttps://git.24-music.de/${REPO}/releases/tag/${tag}`); })().catch(e => { console.error(e); process.exit(1); });