-
Notifications
You must be signed in to change notification settings - Fork 136
Expand file tree
/
Copy pathpre-release-check.ts
More file actions
148 lines (127 loc) · 4.62 KB
/
Copy pathpre-release-check.ts
File metadata and controls
148 lines (127 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env bun
/**
* Pre-release sanity check — run BEFORE tagging a release.
*
* Verifies:
* 1. All required external NAPI modules are in package.json dependencies
* 2. The publish script will include them in the wrapper package
* 3. A local build produces a binary that actually starts
*
* Usage: bun run packages/opencode/script/pre-release-check.ts
*/
import fs from "fs"
import path from "path"
import { spawnSync } from "child_process"
import { fileURLToPath } from "url"
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const pkgDir = path.resolve(__dirname, "..")
const repoRoot = path.resolve(pkgDir, "../..")
const pkg = JSON.parse(fs.readFileSync(path.join(pkgDir, "package.json"), "utf-8"))
let failures = 0
function pass(msg: string) {
console.log(` ✓ ${msg}`)
}
function fail(msg: string) {
console.error(` ✗ ${msg}`)
failures++
}
// ---------------------------------------------------------------------------
// Check 1: Required externals are in package.json dependencies
// ---------------------------------------------------------------------------
console.log("\n[1/4] Checking required externals in package.json...")
const requiredExternals = ["@altimateai/altimate-core"]
for (const ext of requiredExternals) {
if (pkg.dependencies?.[ext]) {
pass(`${ext} is in dependencies (${pkg.dependencies[ext]})`)
} else {
fail(`${ext} is NOT in dependencies — binary will crash at runtime`)
}
}
// ---------------------------------------------------------------------------
// Check 2: Required externals are resolvable in node_modules
// ---------------------------------------------------------------------------
console.log("\n[2/4] Checking required externals are installed...")
for (const ext of requiredExternals) {
try {
require.resolve(ext)
pass(`${ext} resolves from node_modules`)
} catch {
fail(`${ext} is NOT installed — run \`bun install\``)
}
}
// ---------------------------------------------------------------------------
// Check 3: Build and smoke-test the binary
// ---------------------------------------------------------------------------
console.log("\n[3/4] Building local binary...")
const buildResult = spawnSync("bun", ["run", "build:local"], {
cwd: pkgDir,
encoding: "utf-8",
timeout: 120_000,
env: {
...process.env,
MODELS_DEV_API_JSON: path.join(pkgDir, "test/tool/fixtures/models-api.json"),
},
})
if (buildResult.status !== 0) {
fail(`Build failed:\n${buildResult.stderr}`)
} else {
pass("Local build succeeded")
// Find the binary — walk recursively for scoped packages (@altimateai/...)
const distDir = path.join(pkgDir, "dist")
let binaryPath: string | undefined
function searchDist(dir: string): string | undefined {
if (!fs.existsSync(dir)) return undefined
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
if (!entry.isDirectory()) continue
const sub = path.join(dir, entry.name)
const candidate = path.join(sub, "bin", "altimate")
if (fs.existsSync(candidate)) return candidate
const nested = searchDist(sub)
if (nested) return nested
}
return undefined
}
binaryPath = searchDist(distDir)
if (!binaryPath) {
fail("No binary found in dist/ after build")
} else {
console.log("\n[4/4] Smoke-testing compiled binary...")
// Resolve NODE_PATH like the bin wrapper does — start from pkgDir
// to include workspace-level node_modules where NAPI modules live
const nodePaths: string[] = []
let current = pkgDir
for (;;) {
const nm = path.join(current, "node_modules")
if (fs.existsSync(nm)) nodePaths.push(nm)
const parent = path.dirname(current)
if (parent === current) break
current = parent
}
const smokeResult = spawnSync(binaryPath, ["--version"], {
encoding: "utf-8",
timeout: 15_000,
env: {
...process.env,
NODE_PATH: nodePaths.join(":"),
OPENCODE_DISABLE_TELEMETRY: "1",
},
})
if (smokeResult.status === 0) {
const version = (smokeResult.stdout ?? "").trim()
pass(`Binary starts successfully (${version})`)
} else {
const output = (smokeResult.stdout ?? "") + (smokeResult.stderr ?? "")
fail(`Binary crashed on startup:\n${output}`)
}
}
}
// ---------------------------------------------------------------------------
// Summary
// ---------------------------------------------------------------------------
console.log("")
if (failures > 0) {
console.error(`FAILED: ${failures} check(s) failed. Do NOT tag a release.`)
process.exit(1)
} else {
console.log("ALL CHECKS PASSED. Safe to tag a release.")
}