feat: i18n control, Gitea auto-update CI, license-gated updater, fixes
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+1
-1
@@ -62,7 +62,7 @@ async function buildNodeTargets() {
|
||||
bundle: true,
|
||||
minify: isProd,
|
||||
sourcemap: !isProd,
|
||||
external: ['electron', 'sharp', 'ffmpeg-static'],
|
||||
external: ['electron', 'electron-updater', 'sharp', 'ffmpeg-static'],
|
||||
define,
|
||||
drop: isProd ? ['console', 'debugger'] : [],
|
||||
};
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Складывает артефакты electron-builder (win + mac) в публичный репозиторий,
|
||||
* ветка `updates`, чтобы generic URL …/raw/branch/updates/ указывал на актуальные latest*.yml и установщики.
|
||||
*
|
||||
* Переменные окружения (имена без префикса GITEA_ — в Gitea секреты GITEA_* зарезервированы):
|
||||
* DND_UPDATES_SERVER — https://git.example.com (без слэша в конце)
|
||||
* UPDATES_REPO — owner/repo (публичный репозиторий «только релизы»)
|
||||
* DND_UPDATES_PUSH_TOKEN — PAT с правом push в UPDATES_REPO
|
||||
* ARTIFACT_WIN — каталог с файлами сборки Windows
|
||||
* ARTIFACT_MAC — каталог с файлами сборки macOS
|
||||
* GIT_COMMIT_TAG — опционально, для сообщения коммита
|
||||
*/
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const ALLOWED_EXT = new Set(['.yml', '.yaml', '.exe', '.blockmap', '.zip', '.dmg', '.pkg']);
|
||||
|
||||
function mustEnv(name) {
|
||||
const v = process.env[name]?.trim();
|
||||
if (!v) throw new Error(`Missing env ${name}`);
|
||||
return v;
|
||||
}
|
||||
|
||||
function copyFlatReleaseFiles(fromDir, toDir) {
|
||||
if (!fs.existsSync(fromDir)) {
|
||||
console.warn(`[sync-update-feed] skip missing dir: ${fromDir}`);
|
||||
return 0;
|
||||
}
|
||||
let n = 0;
|
||||
for (const name of fs.readdirSync(fromDir)) {
|
||||
const src = path.join(fromDir, name);
|
||||
if (!fs.statSync(src).isFile()) continue;
|
||||
const ext = path.extname(name).toLowerCase();
|
||||
if (!ALLOWED_EXT.has(ext)) continue;
|
||||
fs.copyFileSync(src, path.join(toDir, name));
|
||||
n += 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
function runGit(args, cwd) {
|
||||
execFileSync('git', args, { cwd, stdio: 'inherit' });
|
||||
}
|
||||
|
||||
function emptyWorkingTreeExceptGit(cwd) {
|
||||
for (const ent of fs.readdirSync(cwd)) {
|
||||
if (ent === '.git') continue;
|
||||
fs.rmSync(path.join(cwd, ent), { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
const server = mustEnv('DND_UPDATES_SERVER').replace(/\/+$/u, '');
|
||||
const updatesRepo = mustEnv('UPDATES_REPO');
|
||||
const token = mustEnv('DND_UPDATES_PUSH_TOKEN');
|
||||
const winDir = mustEnv('ARTIFACT_WIN');
|
||||
const macDir = mustEnv('ARTIFACT_MAC');
|
||||
|
||||
const u = new URL(server);
|
||||
const host = u.host;
|
||||
const cloneUrl = `https://oauth2:${encodeURIComponent(token)}@${host}/${updatesRepo}.git`;
|
||||
|
||||
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'dnd-feed-'));
|
||||
const work = path.join(tmp, 'repo');
|
||||
|
||||
try {
|
||||
execFileSync('git', ['clone', '--depth', '1', '-b', 'updates', cloneUrl, work], { stdio: 'inherit' });
|
||||
} catch {
|
||||
execFileSync('git', ['clone', '--depth', '1', cloneUrl, work], { stdio: 'inherit' });
|
||||
runGit(['checkout', '-B', 'updates'], work);
|
||||
}
|
||||
|
||||
runGit(['config', 'user.email', 'ci@gitea-actions.local'], work);
|
||||
runGit(['config', 'user.name', 'gitea-actions'], work);
|
||||
|
||||
emptyWorkingTreeExceptGit(work);
|
||||
|
||||
const copied = copyFlatReleaseFiles(winDir, work) + copyFlatReleaseFiles(macDir, work);
|
||||
if (copied === 0) {
|
||||
throw new Error('[sync-update-feed] no release files copied (check ARTIFACT_WIN / ARTIFACT_MAC)');
|
||||
}
|
||||
|
||||
const tag = process.env.GIT_COMMIT_TAG?.trim() || 'ci';
|
||||
runGit(['add', '-A'], work);
|
||||
const st = execFileSync('git', ['status', '--porcelain'], { cwd: work }).toString().trim();
|
||||
if (st) {
|
||||
runGit(['commit', '-m', `update feed ${tag}`], work);
|
||||
runGit(['push', '-u', 'origin', 'updates'], work);
|
||||
} else {
|
||||
console.warn('[sync-update-feed] nothing to commit (identical artifacts?)');
|
||||
}
|
||||
|
||||
fs.rmSync(tmp, { recursive: true, force: true });
|
||||
console.log(`[sync-update-feed] done (${String(copied)} file(s) staged)`);
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user