Files
easyai-ai-gateway/scripts/release-preflight.mjs
T
easyai dae5d16a58 refactor(release): 改为 Agent 双阶段人工发布
删除 Gitea Actions、Tag/Main 自动流水线和旧 Runner 配置,取消 Git 操作与发布授权的绑定。\n\n新增本地镜像发布、固定生产部署助手、digest manifest、迁移安全检查、simulation 冒烟及显式回滚流程。\n\n验证:pnpm lint、pnpm test、pnpm build、Go 全量测试、ShellCheck、Compose 配置、人工发布测试和 linux/amd64 完整栈冒烟。
2026-07-22 15:13:40 +08:00

43 lines
1.4 KiB
JavaScript
Executable File

#!/usr/bin/env node
import { execFileSync, spawnSync } from 'node:child_process'
function fail(message) {
console.error(`release_preflight=FAIL ${message}`)
process.exit(1)
}
function git(args) {
try {
return execFileSync('git', args, {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
}).trim()
} catch (error) {
const stderr = error.stderr?.toString().trim()
fail(stderr ? `git_error=${JSON.stringify(stderr)}` : 'git command failed')
}
}
const root = git(['rev-parse', '--show-toplevel'])
process.chdir(root)
for (const args of [['diff', '--quiet'], ['diff', '--cached', '--quiet']]) {
if (spawnSync('git', args, { stdio: 'ignore' }).status !== 0) {
fail('the worktree must be clean')
}
}
if (git(['ls-files', '--others', '--exclude-standard'])) {
fail('the worktree must not contain untracked files')
}
const sourceSha = git(['rev-parse', '--verify', 'HEAD^{commit}'])
if (!/^[0-9a-f]{40}$/.test(sourceSha)) fail('HEAD is not a full Git commit')
const mainSha = git(['rev-parse', '--verify', 'refs/remotes/origin/main^{commit}'])
if (!/^[0-9a-f]{40}$/.test(mainSha)) fail('origin/main is unavailable')
if (spawnSync('git', ['merge-base', '--is-ancestor', sourceSha, mainSha], { stdio: 'ignore' }).status !== 0) {
fail('HEAD is not part of origin/main history')
}
console.log(JSON.stringify({ sourceSha, originMainSha: mainSha }))