feat: ship skill and MCP workflows with signed updater for v0.0.7
This commit is contained in:
1 parent
1b52df0603
commit
a01085c656
136 files changed
+18646
-217
No files matched your search
@@ -0,0 +1,79 @@
|
||||
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))
|
||||
Reference in new issue
Block a user