Files
deepseek-harness/apps/desktop/scripts/generate-release-json.mjs
T
Pine aaa434afbd feat(desktop): dynamic About version, update manifest date, and a unified publish flow
The About section hardcoded its version; the main process now exposes
get-app-info so it reads app.getVersion() dynamically, and the update result
carries the manifest release date. The manifest generator orders versions
numerically (0.10.0 outranks 0.9.0). A new stage-release script copies
releases.json plus installers into the deepseek-harness-web site root's
updates/, which deploy.py publishes to OSS alongside the download page, so the
app and web share one update channel. The About section also gains links to the
release site and official site.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 23:01:36 +08:00

77 lines
3.0 KiB
JavaScript

#!/usr/bin/env node
/**
* Generate the OSS update manifest (`releases.json`) from the packaged
* installers in `apps/desktop/dist`. The manifest drives both the desktop app's
* manual "check for updates" (main-process fetch + version compare) and the
* web download page. Run after `desktop:pack`, then upload `releases.json`
* together with the installers to the OSS `updates/` folder.
*
* The installer URLs are derived from the `DSH_UPDATE_BASE` (default
* `https://deepseek.pinesound.cn/updates/`) plus the artifact filename.
* `DSH_RELEASE_NOTES` optionally supplies the release-notes text.
*/
import { readdirSync, writeFileSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
const root = resolve(dirname(fileURLToPath(import.meta.url)), '../../..')
const dist = join(root, 'apps/desktop/dist')
const base = process.env.DSH_UPDATE_BASE ?? 'https://deepseek.pinesound.cn/updates/'
/** Extract a semver-ish version from a filename like `…0.1.0-rc.5-arm64.dmg`. */
function versionOf(filename) {
const base = filename.replace(/\.(dmg|exe)$/, '').replace(/-(arm64|x64)$/, '')
const match = /(\d+\.\d+\.\d+(?:-[0-9A-Za-z.]+)?)$/.exec(base)
return match === null ? undefined : match[1]
}
/** Order two versions: numeric segments first, then the pre-release suffix. */
function compareVersions(a, b) {
const num = (v) => v.split(/[-+]/)[0].split('.').map((n) => Number(n))
const pre = (v) => { const i = v.indexOf('-'); return i === -1 ? '' : v.slice(i + 1) }
const an = num(a), bn = num(b)
for (let i = 0; i < 3; i++) {
if (an[i] !== bn[i]) return an[i] - bn[i]
}
// Equal numeric core: a release with a pre-release suffix is OLDER than a
// stable one (e.g. `1.0.0-rc.1` < `1.0.0`); two suffixes compare by string.
const ap = pre(a), bp = pre(b)
if (ap === bp) return 0
if (ap === '') return 1
if (bp === '') return -1
return ap < bp ? -1 : 1
}
const platforms = {}
let latestVersion
let latestDate = process.env.DSH_RELEASE_DATE ?? new Date().toISOString().slice(0, 10)
for (const entry of readdirSync(dist)) {
if (!entry.endsWith('.dmg') && !entry.endsWith('.exe')) continue
const version = versionOf(entry)
if (version === undefined) continue
const key = entry.endsWith('.dmg')
? entry.includes('arm64') ? 'mac-arm64' : 'mac-x64'
: 'win-x64'
platforms[key] = { url: `${base}${encodeURIComponent(entry)}` }
if (latestVersion === undefined || compareVersions(version, latestVersion) > 0) {
latestVersion = version
latestDate = process.env.DSH_RELEASE_DATE ?? new Date().toISOString().slice(0, 10)
}
}
if (latestVersion === undefined) {
console.error(`generate-release-json: no installers found in ${dist}`)
process.exit(1)
}
const manifest = {
latest: { version: latestVersion, date: latestDate },
releaseNotes: process.env.DSH_RELEASE_NOTES ?? '',
platforms,
}
writeFileSync(join(dist, 'releases.json'), `${JSON.stringify(manifest, null, 2)}\n`)
console.log(`wrote ${join(dist, 'releases.json')} for ${latestVersion}`)