Files

80 lines
2.6 KiB
JavaScript

import path from 'node:path'
import {
DEFAULT_BASE_URL,
DEFAULT_PUBLIC_KEY,
DEFAULT_SSH_HOST,
normalizeBaseUrl,
parseOptions,
resolvePath,
usageError
} from './lib.mjs'
import {
publishLocalRelease,
publishViaSsh,
readLatestViaSsh,
readLocalLatest,
validateReleaseBundle
} from './transport.mjs'
const usage = `Usage:
node scripts/updates/deploy.mjs --manifest <latest.json> --installer <YCode-Setup.exe>
[--transport ssh|local] [--base-url <url>] [--public-key <path>]
[--ssh-host local001] [--local-root <dir>] [--dry-run]
The SSH transport uploads to /srv/ycode-staging, verifies the current signed latest.json,
installs an immutable version directory, then atomically replaces latest.json.
The local transport is for temporary fake-transport tests only.
`
async function main() {
const options = parseOptions(process.argv.slice(2), {
values: ['manifest', 'installer', 'transport', 'base-url', 'public-key', 'ssh-host', 'local-root'],
booleans: ['dry-run']
})
if (!options.manifest || !options.installer) throw new Error('--manifest and --installer are required')
const transport = options.transport || 'ssh'
if (transport !== 'ssh' && transport !== 'local') throw new Error('--transport must be ssh or local')
if (transport === 'local' && !options['local-root']) throw new Error('--local-root is required for local transport')
const baseUrl = normalizeBaseUrl(options['base-url'] || DEFAULT_BASE_URL)
const publicKeyPath = resolvePath(options['public-key'] || DEFAULT_PUBLIC_KEY)
const release = await validateReleaseBundle({
manifestPath: resolvePath(options.manifest),
installerPath: resolvePath(options.installer),
publicKeyPath,
baseUrl
})
let current
if (transport === 'ssh') {
current = await readLatestViaSsh(options['ssh-host'] || DEFAULT_SSH_HOST, release.publicKeyPem, baseUrl)
} else {
current = await readLocalLatest(resolvePath(options['local-root']), release.publicKeyPem, baseUrl)
}
if (options['dry-run']) {
console.log(`Verified ${release.document.payload.version} for ${transport} publication.`)
console.log(`Current latest: ${current.document?.payload.version || 'none'}`)
return
}
if (transport === 'ssh') {
await publishViaSsh({
host: options['ssh-host'] || DEFAULT_SSH_HOST,
release,
current
})
} else {
await publishLocalRelease({
root: path.resolve(options['local-root']),
release,
current
})
}
console.log(`Published ${release.document.payload.version} via ${transport}.`)
}
main().catch((error) => usageError(usage, error))