mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
fix(cli): gate main package release on platform packages being live (#1187)
- prepare-npm-packages: exit(1) instead of warn-and-continue when a platform binary is missing, so a broken build aborts the release - release-all: after publishing platform packages, poll npm view for every @twsxtd/hapi-<platform> package until it matches the release version (10min timeout, 15s interval) before publishing the main package Fixes #1149
This commit is contained in:
@@ -179,9 +179,9 @@ async function preparePlatform(
|
||||
const destBin = join(binDir, platform.binName);
|
||||
|
||||
if (!existsSync(srcBin)) {
|
||||
console.warn(`Warning: Binary not found: ${srcBin}`);
|
||||
console.warn(` Run 'bun run build:exe:all' first to build binaries.`);
|
||||
return;
|
||||
console.error(`Error: Binary not found: ${srcBin}`);
|
||||
console.error(` Run 'bun run build:exe:all' first to build binaries.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
copyFileSync(srcBin, destBin);
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
* 1. Bump version
|
||||
* 2. Build binaries (with embedded web assets)
|
||||
* 3. Publish platform packages first (so lockfile can resolve them)
|
||||
* 4. Publish main package
|
||||
* 5. bun install --lockfile-only --os=* --cpu=* (to lock all platform packages)
|
||||
* 6. Git commit + tag + push
|
||||
* 4. Verify all platform packages are live on npm
|
||||
* 5. Publish main package
|
||||
* 6. bun install --lockfile-only --os=* --cpu=* (to lock all platform packages)
|
||||
* 7. Git commit + tag + push
|
||||
*/
|
||||
|
||||
import { execSync } from 'node:child_process';
|
||||
@@ -58,6 +59,37 @@ function updateBuildInfoVersion(nextVersion: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForPlatformPackages(platforms: string[], expectedVersion: string): Promise<void> {
|
||||
const timeoutMs = 10 * 60 * 1000;
|
||||
const intervalMs = 15_000;
|
||||
const deadline = Date.now() + timeoutMs;
|
||||
const pending = new Set(platforms.map(platform => `@twsxtd/hapi-${platform}`));
|
||||
|
||||
while (pending.size > 0) {
|
||||
for (const name of [...pending]) {
|
||||
try {
|
||||
const published = execSync(`npm view ${name} version`, { encoding: 'utf-8' }).trim();
|
||||
if (published === expectedVersion) {
|
||||
console.log(` ✓ ${name}@${expectedVersion} is live on npm`);
|
||||
pending.delete(name);
|
||||
}
|
||||
} catch {
|
||||
// Not published yet, keep waiting
|
||||
}
|
||||
}
|
||||
if (pending.size === 0) {
|
||||
return;
|
||||
}
|
||||
if (Date.now() >= deadline) {
|
||||
console.error(`❌ Timed out waiting for platform packages on npm: ${[...pending].join(', ')}`);
|
||||
console.error(' The main package was NOT published. Publish the missing platform packages and re-run with --publish-npm.');
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(` ⏳ Waiting for: ${[...pending].join(', ')} (retry in ${intervalMs / 1000}s)...`);
|
||||
await new Promise(resolve => setTimeout(resolve, intervalMs));
|
||||
}
|
||||
}
|
||||
|
||||
async function runWithTimeoutRetry(cmd: string, cwd = projectRoot): Promise<void> {
|
||||
const timeoutCmd = `timeout 60s ${cmd}`;
|
||||
while (true) {
|
||||
@@ -130,8 +162,18 @@ async function main(): Promise<void> {
|
||||
run(`npm publish --access public${dryRun ? ' --dry-run' : ''}`, npmDir);
|
||||
}
|
||||
|
||||
// Step 4: Publish main package
|
||||
console.log('\n📤 Step 4: Publishing main package...');
|
||||
// Step 4: Verify all platform packages are live on npm before publishing the main package.
|
||||
// The main package pins platform packages via optionalDependencies, so publishing it first
|
||||
// would let users install a version whose platform binary does not exist yet.
|
||||
if (dryRun) {
|
||||
console.log('\n🔍 Step 4: Skipping platform package verification (dry-run)');
|
||||
} else {
|
||||
console.log('\n🔍 Step 4: Verifying platform packages are live on npm...');
|
||||
await waitForPlatformPackages(platforms, version);
|
||||
}
|
||||
|
||||
// Step 5: Publish main package
|
||||
console.log('\n📤 Step 5: Publishing main package...');
|
||||
const mainNpmDir = join(projectRoot, 'npm', 'main');
|
||||
run(`npm publish --access public${dryRun ? ' --dry-run' : ''}`, mainNpmDir);
|
||||
|
||||
@@ -141,12 +183,12 @@ async function main(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 5: bun install to get complete lockfile
|
||||
console.log('\n📥 Step 5: Updating lockfile for all platform packages...');
|
||||
// Step 6: bun install to get complete lockfile
|
||||
console.log('\n📥 Step 6: Updating lockfile for all platform packages...');
|
||||
|
||||
await runWithTimeoutRetry('bun install --lockfile-only --os=* --cpu=*', repoRoot);
|
||||
// Step 6: Git commit + tag + push
|
||||
console.log('\n📝 Step 6: Creating git commit and tag...');
|
||||
// Step 7: Git commit + tag + push
|
||||
console.log('\n📝 Step 7: Creating git commit and tag...');
|
||||
run(`git add .`, repoRoot);
|
||||
run(`git commit -m "Release version ${version}"`, repoRoot);
|
||||
run(`git tag v${version}`, repoRoot);
|
||||
|
||||
Reference in New Issue
Block a user