@celilo/cli 5.1.0 → 5.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
2
5
|
import { findStaleBundledDeps, refreshAndVerifyBundledDeps } from './bundled-deps';
|
|
3
6
|
|
|
4
7
|
describe('findStaleBundledDeps (ISS-0104)', () => {
|
|
@@ -52,4 +55,45 @@ describe('refreshAndVerifyBundledDeps (ISS-0104)', () => {
|
|
|
52
55
|
expect(result).toEqual({ refreshed: false, mismatches: [] });
|
|
53
56
|
expect(installs).toBe(0);
|
|
54
57
|
});
|
|
58
|
+
|
|
59
|
+
// celilo#1447: the release run's sweep installs seconds after the same run
|
|
60
|
+
// published the packages it resolves, so bun's cached packument 404s them.
|
|
61
|
+
describe('just-published dep (celilo#1447)', () => {
|
|
62
|
+
function moduleWithScripts(): string {
|
|
63
|
+
const dir = mkdtempSync(join(tmpdir(), 'bundled-deps-'));
|
|
64
|
+
mkdirSync(join(dir, 'scripts'), { recursive: true });
|
|
65
|
+
writeFileSync(join(dir, 'scripts', 'package.json'), '{"name":"m"}');
|
|
66
|
+
return dir;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
test('retries with --no-cache when the first install cannot resolve it', () => {
|
|
70
|
+
const cmds: string[] = [];
|
|
71
|
+
const slept: number[] = [];
|
|
72
|
+
refreshAndVerifyBundledDeps(
|
|
73
|
+
moduleWithScripts(),
|
|
74
|
+
(cmd) => {
|
|
75
|
+
cmds.push(cmd);
|
|
76
|
+
if (cmds.length === 1) throw new Error('failed to resolve (but package exists)');
|
|
77
|
+
},
|
|
78
|
+
(ms) => void slept.push(ms),
|
|
79
|
+
);
|
|
80
|
+
expect(cmds).toEqual(['bun install', 'bun install --no-cache']);
|
|
81
|
+
expect(slept).toEqual([2_000]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('rethrows once the retries are exhausted', () => {
|
|
85
|
+
const cmds: string[] = [];
|
|
86
|
+
expect(() =>
|
|
87
|
+
refreshAndVerifyBundledDeps(
|
|
88
|
+
moduleWithScripts(),
|
|
89
|
+
(cmd) => {
|
|
90
|
+
cmds.push(cmd);
|
|
91
|
+
throw new Error('still unresolvable');
|
|
92
|
+
},
|
|
93
|
+
() => {},
|
|
94
|
+
),
|
|
95
|
+
).toThrow('still unresolvable');
|
|
96
|
+
expect(cmds).toHaveLength(3);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
55
99
|
});
|
|
@@ -65,6 +65,44 @@ function findWorkspaceRoot(start: string): string | undefined {
|
|
|
65
65
|
return undefined;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* celilo#1447: in a release run this install happens SECONDS after the same
|
|
70
|
+
* run published the workspace packages it must resolve. bun has already cached
|
|
71
|
+
* the pre-publish packument (the workspace install at the top of the job), so
|
|
72
|
+
* it fails with "@celilo/capabilities@^6.1.0 failed to resolve ... but package
|
|
73
|
+
* exists" — and the whole module sweep aborts AFTER npm and the CLI shipped,
|
|
74
|
+
* which is exactly the half-shipped release #1369 reordered the steps to
|
|
75
|
+
* prevent. `--no-cache` re-reads the registry; the backoff covers the case
|
|
76
|
+
* where npm's own metadata has not propagated yet.
|
|
77
|
+
*
|
|
78
|
+
* ponytail: fixed 3 attempts, no jitter. If propagation ever needs longer,
|
|
79
|
+
* raise RETRY_DELAYS_MS rather than adding a scheduler.
|
|
80
|
+
*/
|
|
81
|
+
const RETRY_DELAYS_MS = [2_000, 8_000];
|
|
82
|
+
|
|
83
|
+
function installWithRetry(
|
|
84
|
+
run: (cmd: string, cwd: string) => void,
|
|
85
|
+
sleep: (ms: number) => void,
|
|
86
|
+
scriptsDir: string,
|
|
87
|
+
): void {
|
|
88
|
+
try {
|
|
89
|
+
run('bun install', scriptsDir);
|
|
90
|
+
return;
|
|
91
|
+
} catch (err) {
|
|
92
|
+
let lastErr = err;
|
|
93
|
+
for (const delay of RETRY_DELAYS_MS) {
|
|
94
|
+
sleep(delay);
|
|
95
|
+
try {
|
|
96
|
+
run('bun install --no-cache', scriptsDir);
|
|
97
|
+
return;
|
|
98
|
+
} catch (retryErr) {
|
|
99
|
+
lastErr = retryErr;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
throw lastErr;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
68
106
|
export interface RefreshResult {
|
|
69
107
|
/** Whether the module had a scripts/ package to refresh. */
|
|
70
108
|
refreshed: boolean;
|
|
@@ -84,6 +122,7 @@ export function refreshAndVerifyBundledDeps(
|
|
|
84
122
|
moduleDir: string,
|
|
85
123
|
run: (cmd: string, cwd: string) => void = (cmd, cwd) =>
|
|
86
124
|
void execSync(cmd, { cwd, stdio: 'pipe' }),
|
|
125
|
+
sleep: (ms: number) => void = (ms) => Bun.sleepSync(ms),
|
|
87
126
|
): RefreshResult {
|
|
88
127
|
const scriptsDir = join(moduleDir, 'scripts');
|
|
89
128
|
if (!existsSync(join(scriptsDir, 'package.json'))) {
|
|
@@ -92,7 +131,7 @@ export function refreshAndVerifyBundledDeps(
|
|
|
92
131
|
|
|
93
132
|
// Reconcile node_modules with the lockfile + package.json pins so the pack
|
|
94
133
|
// bundles a CURRENT closure, not whatever the operator last installed.
|
|
95
|
-
run
|
|
134
|
+
installWithRetry(run, sleep, scriptsDir);
|
|
96
135
|
|
|
97
136
|
const workspaceRoot = findWorkspaceRoot(moduleDir);
|
|
98
137
|
if (!workspaceRoot) {
|