enablement-build-monorepo-version 2.0.7 → 2.0.9
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 +6 -6
- package/src/index.mjs +17 -7
- package/tests/index.test.mjs +120 -0
- package/tests/lib.test.mjs +59 -0
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "enablement-build-monorepo-version",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.9",
|
|
4
4
|
"description": "This detects changes in the children packages of a monorepo.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./src/index.mjs",
|
|
7
7
|
"bin": "./src/index.mjs",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"author": "Contributors",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node src/index.mjs",
|
|
12
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
13
|
+
"test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch"
|
|
14
|
+
},
|
|
10
15
|
"jest": {
|
|
11
16
|
"testEnvironment": "node",
|
|
12
17
|
"testMatch": [
|
|
@@ -18,10 +23,5 @@
|
|
|
18
23
|
},
|
|
19
24
|
"devDependencies": {
|
|
20
25
|
"jest": "^30.4.2"
|
|
21
|
-
},
|
|
22
|
-
"scripts": {
|
|
23
|
-
"start": "node src/index.mjs",
|
|
24
|
-
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
25
|
-
"test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch"
|
|
26
26
|
}
|
|
27
27
|
}
|
package/src/index.mjs
CHANGED
|
@@ -35,7 +35,7 @@ function buildHashesForCicd(current) {
|
|
|
35
35
|
hashData[entry.fullName] = {
|
|
36
36
|
hash: entry.hash,
|
|
37
37
|
version: entry.version,
|
|
38
|
-
|
|
38
|
+
name: entry.fullName,
|
|
39
39
|
packageFolder: entry.packageFolder
|
|
40
40
|
};
|
|
41
41
|
versions[entry.fullName] = entry.version;
|
|
@@ -155,16 +155,25 @@ async function main(options) {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
// Load
|
|
158
|
+
// Load previous hashes.
|
|
159
|
+
// - hash.json mode: compare directly by short package folder name.
|
|
160
|
+
// - manifest.json mode: defer to full-name mapping after building current.
|
|
159
161
|
let manifestData = {};
|
|
160
162
|
if (usesManifestHashFile) {
|
|
161
163
|
const data = existsSync(changeConfig) ? readFileSync(changeConfig, "utf8") : "{}";
|
|
162
164
|
manifestData = JSON.parse(data || "{}");
|
|
163
|
-
}
|
|
164
165
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
// Backward compatibility: some manifests may still store hashes in the old
|
|
167
|
+
// flat format. Keep these as a fallback in case cicd is not present.
|
|
168
|
+
if (!manifestData.cicd) {
|
|
169
|
+
previous = convertOldHashFormat(manifestData);
|
|
170
|
+
} else {
|
|
171
|
+
previous = {};
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
const data = existsSync(changeConfig) ? readFileSync(changeConfig, "utf8") : "{}";
|
|
175
|
+
previous = JSON.parse(data || "{}");
|
|
176
|
+
}
|
|
168
177
|
if (options.debug) console.log("PREVIOUS", JSON.stringify(previous));
|
|
169
178
|
|
|
170
179
|
options.hashFiles.forEach(file => {
|
|
@@ -319,7 +328,8 @@ async function main(options) {
|
|
|
319
328
|
if (!manifest.cicd) manifest.cicd = {};
|
|
320
329
|
if (!manifest.cicd[fullname]) manifest.cicd[fullname] = {};
|
|
321
330
|
manifest.cicd[fullname].hash = hashData[fullname].hash;
|
|
322
|
-
manifest.cicd[fullname].
|
|
331
|
+
manifest.cicd[fullname].name = hashData[fullname].name;
|
|
332
|
+
delete manifest.cicd[fullname].folderName;
|
|
323
333
|
manifest.cicd[fullname].packageFolder = hashData[fullname].packageFolder;
|
|
324
334
|
});
|
|
325
335
|
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { execFileSync } from "child_process";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import {
|
|
7
|
+
mkdtempSync,
|
|
8
|
+
mkdirSync,
|
|
9
|
+
readFileSync,
|
|
10
|
+
rmSync,
|
|
11
|
+
writeFileSync,
|
|
12
|
+
} from "fs";
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
16
|
+
const repoRoot = path.resolve(__dirname, "..", "..");
|
|
17
|
+
const cliPath = path.resolve(repoRoot, "monorepo-version", "src", "index.mjs");
|
|
18
|
+
|
|
19
|
+
function setupWorkspace() {
|
|
20
|
+
const root = mkdtempSync(path.join(os.tmpdir(), "monorepo-version-"));
|
|
21
|
+
|
|
22
|
+
mkdirSync(path.join(root, "packages", "example"), { recursive: true });
|
|
23
|
+
mkdirSync(path.join(root, ".cicd"), { recursive: true });
|
|
24
|
+
|
|
25
|
+
writeFileSync(
|
|
26
|
+
path.join(root, "package.json"),
|
|
27
|
+
JSON.stringify(
|
|
28
|
+
{
|
|
29
|
+
name: "tmp-monorepo",
|
|
30
|
+
private: true,
|
|
31
|
+
workspaces: ["packages/*"],
|
|
32
|
+
},
|
|
33
|
+
null,
|
|
34
|
+
2,
|
|
35
|
+
) + "\n",
|
|
36
|
+
"utf8",
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
writeFileSync(
|
|
40
|
+
path.join(root, "packages", "example", "package.json"),
|
|
41
|
+
JSON.stringify(
|
|
42
|
+
{
|
|
43
|
+
name: "@scope/example",
|
|
44
|
+
version: "1.0.0",
|
|
45
|
+
},
|
|
46
|
+
null,
|
|
47
|
+
2,
|
|
48
|
+
) + "\n",
|
|
49
|
+
"utf8",
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
writeFileSync(path.join(root, "packages", "example", "index.js"), "export default 1;\n", "utf8");
|
|
53
|
+
|
|
54
|
+
return root;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function runRelease(root, hashFile) {
|
|
58
|
+
const stdout = execFileSync(
|
|
59
|
+
"node",
|
|
60
|
+
[
|
|
61
|
+
cliPath,
|
|
62
|
+
"--hash",
|
|
63
|
+
"--changed",
|
|
64
|
+
"--children",
|
|
65
|
+
"packages",
|
|
66
|
+
"--prefixPath",
|
|
67
|
+
root,
|
|
68
|
+
"--hashFile",
|
|
69
|
+
hashFile,
|
|
70
|
+
],
|
|
71
|
+
{
|
|
72
|
+
cwd: repoRoot,
|
|
73
|
+
encoding: "utf8",
|
|
74
|
+
},
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const changedMatch = stdout.match(/CHANGED - (\[[^\n]*\])/);
|
|
78
|
+
if (!changedMatch) {
|
|
79
|
+
throw new Error(`Could not find changed list in output:\n${stdout}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return JSON.parse(changedMatch[1]);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
describe("index CLI hash loading", () => {
|
|
86
|
+
it("supports non-manifest hash mode across repeated runs", () => {
|
|
87
|
+
const root = setupWorkspace();
|
|
88
|
+
try {
|
|
89
|
+
const first = runRelease(root, ".cicd/hash.json");
|
|
90
|
+
const second = runRelease(root, ".cicd/hash.json");
|
|
91
|
+
|
|
92
|
+
expect(first).toContain("example");
|
|
93
|
+
expect(second).toEqual([]);
|
|
94
|
+
|
|
95
|
+
const hashJson = JSON.parse(readFileSync(path.join(root, ".cicd", "hash.json"), "utf8"));
|
|
96
|
+
expect(hashJson.example).toBeDefined();
|
|
97
|
+
expect(hashJson.example.hash).toBeTruthy();
|
|
98
|
+
} finally {
|
|
99
|
+
rmSync(root, { recursive: true, force: true });
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("supports manifest hash mode across repeated runs", () => {
|
|
104
|
+
const root = setupWorkspace();
|
|
105
|
+
try {
|
|
106
|
+
const first = runRelease(root, ".cicd/manifest.json");
|
|
107
|
+
const second = runRelease(root, ".cicd/manifest.json");
|
|
108
|
+
|
|
109
|
+
expect(first).toContain("example");
|
|
110
|
+
expect(second).toEqual([]);
|
|
111
|
+
|
|
112
|
+
const manifest = JSON.parse(readFileSync(path.join(root, ".cicd", "manifest.json"), "utf8"));
|
|
113
|
+
expect(manifest.cicd["@scope/example"]).toBeDefined();
|
|
114
|
+
expect(manifest.cicd["@scope/example"].hash).toBeTruthy();
|
|
115
|
+
expect(manifest.versions["@scope/example"]).toBe("1.0.0");
|
|
116
|
+
} finally {
|
|
117
|
+
rmSync(root, { recursive: true, force: true });
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
});
|
package/tests/lib.test.mjs
CHANGED
|
@@ -343,6 +343,65 @@ describe("version manifest precedence and updates", () => {
|
|
|
343
343
|
rmSync(root, { recursive: true, force: true });
|
|
344
344
|
});
|
|
345
345
|
|
|
346
|
+
it("reads current version and name from version.json when package.json is absent", () => {
|
|
347
|
+
const root = mkdtempSync(path.join(os.tmpdir(), "monorepo-version-"));
|
|
348
|
+
const pkgDir = path.join(root, "packages", "gamma");
|
|
349
|
+
mkdirSync(pkgDir, { recursive: true });
|
|
350
|
+
|
|
351
|
+
writeFileSync(
|
|
352
|
+
path.join(pkgDir, "version.json"),
|
|
353
|
+
JSON.stringify({ name: "@s/gamma-version", version: "2.1.0" }, null, 2),
|
|
354
|
+
"utf8",
|
|
355
|
+
);
|
|
356
|
+
writeFileSync(
|
|
357
|
+
path.join(pkgDir, "pyproject.toml"),
|
|
358
|
+
'[project]\nname = "gamma-toml"\nversion = "3.0.0"\n',
|
|
359
|
+
"utf8",
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
const current = getCurrentVersion(root, "packages", "gamma");
|
|
363
|
+
expect(current.version).toBe("2.1.0");
|
|
364
|
+
expect(current.fullName).toBe("@s/gamma-version");
|
|
365
|
+
|
|
366
|
+
rmSync(root, { recursive: true, force: true });
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it("reads current version and name from pyproject.toml only when package.json and version.json are absent", () => {
|
|
370
|
+
const root = mkdtempSync(path.join(os.tmpdir(), "monorepo-version-"));
|
|
371
|
+
const pkgDir = path.join(root, "packages", "delta");
|
|
372
|
+
mkdirSync(pkgDir, { recursive: true });
|
|
373
|
+
|
|
374
|
+
writeFileSync(
|
|
375
|
+
path.join(pkgDir, "pyproject.toml"),
|
|
376
|
+
'[project]\nname = "delta-toml"\nversion = "3.2.0"\n',
|
|
377
|
+
"utf8",
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
const current = getCurrentVersion(root, "packages", "delta");
|
|
381
|
+
expect(current.version).toBe("3.2.0");
|
|
382
|
+
expect(current.fullName).toBe("delta-toml");
|
|
383
|
+
|
|
384
|
+
rmSync(root, { recursive: true, force: true });
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it("does not fall back to folder name when no manifest name exists", () => {
|
|
388
|
+
const root = mkdtempSync(path.join(os.tmpdir(), "monorepo-version-"));
|
|
389
|
+
const pkgDir = path.join(root, "packages", "epsilon");
|
|
390
|
+
mkdirSync(pkgDir, { recursive: true });
|
|
391
|
+
|
|
392
|
+
writeFileSync(
|
|
393
|
+
path.join(pkgDir, "package.json"),
|
|
394
|
+
JSON.stringify({ version: "1.0.0" }, null, 2),
|
|
395
|
+
"utf8",
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
const current = getCurrentVersion(root, "packages", "epsilon");
|
|
399
|
+
expect(current.version).toBe("1.0.0");
|
|
400
|
+
expect(current.fullName).toBeUndefined();
|
|
401
|
+
|
|
402
|
+
rmSync(root, { recursive: true, force: true });
|
|
403
|
+
});
|
|
404
|
+
|
|
346
405
|
it("updates all version manifests when package.json, version.json, and pyproject.toml exist", async () => {
|
|
347
406
|
const root = mkdtempSync(path.join(os.tmpdir(), "monorepo-version-"));
|
|
348
407
|
const pkgDir = path.join(root, "packages", "beta");
|