88 lines
3.8 KiB
JavaScript
88 lines
3.8 KiB
JavaScript
#!/usr/bin/env node
|
|
// bundle-store-msixbundle.mjs — the Store-submission bundle step of the
|
|
// desktop-bundled-release workflow's store-publish job.
|
|
//
|
|
// The win32 build legs produce per-arch Store-submission packages
|
|
// (Store-<name>-<fileVersion>-win-<arch>.msix, built with
|
|
// HERMES_DESKTOP_VARIANT=store / the Partner Center identity). This script
|
|
// bundles the x64 + arm64 packages into ONE universal Store .msixbundle for
|
|
// the Windows Store submission. --output-file writes its absolute path for
|
|
// callers, independently of the installer's download/progress logs.
|
|
//
|
|
// The bundle is deliberately left UNSIGNED: the Store re-signs the package
|
|
// with the Microsoft Store certificate on ingestion (same posture as the
|
|
// build legs, whose Store-*.msix ship unsigned — see sign-msix.mjs).
|
|
//
|
|
// Usage (win runner, bash):
|
|
// node scripts/bundle-store-msixbundle.mjs --tag vX.Y.Z
|
|
import { execFileSync } from 'node:child_process'
|
|
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
import { appIdentity } from './msix-shared.mjs'
|
|
import { ensureWindowsBundleTools } from '../apps/desktop/scripts/windows-bundle-tools.mjs'
|
|
|
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
|
|
|
// node strips the first '--' (and an immediately-following option) for its
|
|
// own use; parse space-separated flag pairs, not --flag=value.
|
|
const args = process.argv.slice(2)
|
|
const flagValue = (name) => {
|
|
for (let i = 0; i < args.length - 1; i += 1) {
|
|
if (args[i] === name) return args[i + 1]
|
|
}
|
|
return undefined
|
|
}
|
|
const tag = flagValue('--tag') || process.env.HERMES_PAYLOAD_TAG
|
|
if (!tag) {
|
|
console.error('[bundle-store] --tag=<vX.Y.Z> is required')
|
|
process.exit(1)
|
|
}
|
|
if (process.platform !== 'win32') {
|
|
console.error('[bundle-store] this job must run on a Windows runner (makeappx)')
|
|
process.exit(1)
|
|
}
|
|
|
|
// product-identity.cjs keys the app name off HERMES_DESKTOP_VARIANT — the
|
|
// Store-submission artifacts carry the Store- prefix + Partner Center
|
|
// identity, so the env var MUST be 'store' before the identity lookup.
|
|
process.env.HERMES_DESKTOP_VARIANT = 'store'
|
|
|
|
const desktop = path.join(REPO_ROOT, 'apps', 'desktop')
|
|
const releaseDir = path.join(desktop, 'release')
|
|
const { name, version, fileVersion } = appIdentity(desktop, tag)
|
|
|
|
// Per-arch Store-submission packages: electron-builder names them with the
|
|
// Store- prefix + appInfo.version (the 3-part or full-canary string), which
|
|
// appIdentity reports as `fileVersion` — same convention as the out-of-store
|
|
// bundle in stage-msixbundle.mjs.
|
|
const storeMsix = (arch) => path.join(releaseDir, `Store-${name}-${fileVersion}-win-${arch}.msix`)
|
|
const x64 = storeMsix('x64')
|
|
const arm64 = storeMsix('arm64')
|
|
if (!fs.existsSync(x64) || !fs.existsSync(arm64)) {
|
|
console.error(`[bundle-store] need both per-arch Store-*.msix to bundle:\n ${x64}\n ${arm64}`)
|
|
process.exit(1)
|
|
}
|
|
|
|
// makeappx bundle /d includes EVERY .msix in the dir — stage only the two
|
|
// Store packages into a clean dir (mirror stage-msixbundle.mjs).
|
|
const staging = path.join(releaseDir, '__store-bundle-staging')
|
|
fs.rmSync(staging, { recursive: true, force: true })
|
|
fs.mkdirSync(staging, { recursive: true })
|
|
fs.copyFileSync(x64, path.join(staging, path.basename(x64)))
|
|
fs.copyFileSync(arm64, path.join(staging, path.basename(arm64)))
|
|
|
|
const bundle = path.join(releaseDir, `Store-${name}-${version}-win.msixbundle`)
|
|
const { makeappx } = await ensureWindowsBundleTools()
|
|
if (fs.existsSync(bundle)) fs.rmSync(bundle, { force: true })
|
|
execFileSync(makeappx, ['bundle', '/o', '/bv', version, '/d', staging, '/p', bundle], {
|
|
stdio: 'inherit'
|
|
})
|
|
fs.rmSync(staging, { recursive: true, force: true })
|
|
|
|
// Download logs can share stdout. The explicit output file is the machine contract.
|
|
const outputFile = flagValue('--output-file')
|
|
if (outputFile) fs.writeFileSync(outputFile, bundle, 'utf8')
|
|
console.log(bundle)
|