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 --installer [--transport ssh|local] [--base-url ] [--public-key ] [--ssh-host local001] [--local-root ] [--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))