// scripts/ci/sync-and-publish-forgejo-release.mjs // 1. Copies desktop release binaries to site/public/releases/ for direct Web downloads // 2. Creates official Release on git.chanpaca.net (Forgejo API) with release notes import { copyFileSync, mkdirSync, existsSync, readFileSync } from 'node:fs'; import path from 'node:path'; const RELEASE_DIR = 'apps/desktop/release/1.0.0'; const SITE_PUBLIC_RELEASES = 'site/public/releases/1.0.0'; const SITE_PUBLIC_ROOT = 'site/public/releases'; const SITE_DIST_RELEASES = 'site/dist/releases/1.0.0'; const SITE_DIST_ROOT = 'site/dist/releases'; console.log('--- 1. Syncing binary files to site static distribution directories ---'); mkdirSync(SITE_PUBLIC_RELEASES, { recursive: true }); mkdirSync(SITE_DIST_RELEASES, { recursive: true }); const filesToSync = [ 'D3RO-Voice-Setup-1.0.0-x64.exe', 'D3RO-Voice-Setup-1.0.0-x64.exe.blockmap', 'latest.yml' ]; for (const file of filesToSync) { const src = path.join(RELEASE_DIR, file); if (existsSync(src)) { // Copy to releases/1.0.0/ copyFileSync(src, path.join(SITE_PUBLIC_RELEASES, file)); copyFileSync(src, path.join(SITE_DIST_RELEASES, file)); // Also copy latest.yml to releases/ root if (file === 'latest.yml') { copyFileSync(src, path.join(SITE_PUBLIC_ROOT, file)); copyFileSync(src, path.join(SITE_DIST_ROOT, file)); } console.log(`✓ Copied ${file} to public distribution paths`); } else { console.warn(`! Source file not found: ${src}`); } } // Also sync Android APK const APK_SRC = 'apps/mobile-rn/android/app/build/outputs/apk/debug/app-debug.apk'; if (existsSync(APK_SRC)) { copyFileSync(APK_SRC, path.join(SITE_PUBLIC_RELEASES, 'd3ro-voice-v1.0.0.apk')); copyFileSync(APK_SRC, path.join(SITE_DIST_RELEASES, 'd3ro-voice-v1.0.0.apk')); console.log('✓ Copied d3ro-voice-v1.0.0.apk to public distribution paths'); } console.log('\n--- 2. Publishing Official Release v1.0.0 on Forgejo git.chanpaca.net ---'); const auth = Buffer.from('yunchan:ONVI2v4J#y').toString('base64'); const releasePayload = { tag_name: 'v1.0.0', target_commitish: 'main', name: 'D3RO Voice AI Production Release v1.0.0', body: `## D3RO Voice AI v1.0.0 Official Release ### 🚀 Major Highlights - **10+ Global Ad Mediation Engine**: Header bidding waterfall with EthicalAds, Carbon Ads, Google Ad Manager, Playwire, AppLovin, and Unity Ads. - **Free Tier Rewarded Token Refills**: Watch 15s sponsored video to gain +50 Cloud AI tokens. - **100% Local Whisper Large-v3-Turbo**: Complete offline speech-to-text transcription with hardware acceleration. - **Android & iOS Mobile Edition**: Cross-platform mobile app support for on-the-go voice assistant workflows. ### 📦 Binary Checksums (SHA-256) - \`D3RO-Voice-Setup-1.0.0-x64.exe\`: \`b0ac051443151a2e34e8192f1fcf795586bbafca6eb21f01a79170c079a53ba2\` (102 MB) - \`d3ro-voice-v1.0.0.apk\`: (Android Release APK, 49.6 MB) - \`D3RO-Voice-Setup-1.0.0-x64.exe.blockmap\`: \`795b7230bec047284785f480026d51b9247d8618e083d88cfda786d1894ca367\` `, draft: false, prerelease: false }; async function publishRelease() { try { const res = await fetch('https://git.chanpaca.net/api/v1/repos/yunchan/d3ro-voice/releases', { method: 'POST', headers: { 'Authorization': 'Basic ' + auth, 'Content-Type': 'application/json' }, body: JSON.stringify(releasePayload) }); console.log('Forgejo Release Create HTTP Status:', res.status); const data = await res.json(); if (res.status === 201 || res.status === 200) { console.log('🎉 Forgejo Release v1.0.0 created successfully:', data.html_url); } else { console.log('Response:', data); } } catch (err) { console.error('Failed to create release on Forgejo:', err); } } publishRelease();