|
2 | 2 |
|
3 | 3 | // @ts-check
|
4 | 4 |
|
5 |
| -// NOTE: |
6 |
| -// We cannot use `yarn pack` since we need to set our OCaml binaries executable. |
7 |
| -// Yarn (Berry) only allow `bin` to be executable, wouldn't preserve permission bits. |
8 |
| - |
9 |
| -// This performs `npm pack` and retrieves the list of artifact files from the output. |
| 5 | +// This performs `yarn pack` and retrieves the list of artifact files from the output. |
10 | 6 | //
|
11 |
| -// In local dev, invoke it with `-updateArtifactList` to perform a dry run of `npm pack` |
| 7 | +// In local dev, invoke it with `-updateArtifactList` to perform a dry run of `yarn pack` |
12 | 8 | // and recreate `packages/artifacts.txt`.
|
13 |
| -// The exes for all platforms will then be included in the list, even if not present locally. |
14 | 9 | //
|
15 |
| -// In CI, the scripts is invoked without options. It then performs `npm pack` for real, |
| 10 | +// In CI, the scripts is invoked without options. It then performs `yarn pack` for real, |
16 | 11 | // recreates the artifact list and verifies that it has no changes compared to the committed state.
|
17 | 12 |
|
18 |
| -/** |
19 |
| - * @typedef {{ |
20 |
| - * path: string, |
21 |
| - * size: number, |
22 |
| - * mode: number, |
23 |
| - * }} PackOutputFile |
24 |
| - * |
25 |
| - * @typedef {{ |
26 |
| - * files: PackOutputFile[], |
27 |
| - * entryCount: number, |
28 |
| - * bundled: unknown[], |
29 |
| - * }} PackOutputEntry |
30 |
| - * |
31 |
| - * @typedef {[PackOutputEntry]} PackOutput |
| 13 | +import { spawn, execSync } from "node:child_process"; |
| 14 | +import fs from "node:fs"; |
| 15 | +import { parseArgs } from "node:util"; |
| 16 | +import { artifactListFile } from "#dev/paths"; |
| 17 | + |
| 18 | +/** |
| 19 | + * @typedef {( |
| 20 | + * | { "base": string } |
| 21 | + * | { "location": string } |
| 22 | + * | { "output": string } |
| 23 | + * )} YarnPackOutputLine |
32 | 24 | */
|
33 | 25 |
|
34 |
| -import { execSync, spawnSync } from "node:child_process"; |
35 |
| -import fs from "node:fs"; |
36 |
| -import path from "node:path"; |
37 |
| -import { projectDir } from "#dev/paths"; |
| 26 | +const { values } = parseArgs({ |
| 27 | + args: process.argv.slice(2), |
| 28 | + options: { |
| 29 | + updateArtifactList: { |
| 30 | + type: "boolean", |
| 31 | + short: "u", |
| 32 | + }, |
| 33 | + }, |
| 34 | +}); |
38 | 35 |
|
39 |
| -const mode = process.argv.includes("-updateArtifactList") |
| 36 | +const mode = values.updateArtifactList |
40 | 37 | ? "updateArtifactList"
|
41 | 38 | : "package";
|
42 | 39 |
|
43 |
| -const fileListPath = path.join(projectDir, "packages", "artifacts.txt"); |
44 |
| - |
45 |
| -const output = spawnSync( |
46 |
| - `npm pack --json${mode === "updateArtifactList" ? " --dry-run" : ""}`, |
47 |
| - { |
48 |
| - cwd: projectDir, |
49 |
| - encoding: "utf8", |
50 |
| - shell: true, |
51 |
| - }, |
52 |
| -).stdout; |
53 |
| - |
54 |
| -/** @type {PackOutput} */ |
55 |
| -const parsedOutput = JSON.parse(output); |
56 |
| -let filePaths = parsedOutput[0].files.map(file => file.path); |
57 |
| - |
58 |
| -if (mode === "updateArtifactList") { |
59 |
| - filePaths = Array.from(new Set(filePaths.concat(getFilesAddedByCI()))); |
| 40 | +const child = spawn( |
| 41 | + "yarn", |
| 42 | + [ |
| 43 | + "workspace", |
| 44 | + "rescript", |
| 45 | + "pack", |
| 46 | + "--json", |
| 47 | + mode === "updateArtifactList" ? "--dry-run" : "", |
| 48 | + ].filter(Boolean), |
| 49 | +); |
| 50 | +const exitCode = new Promise((resolve, reject) => { |
| 51 | + child.once("error", reject); |
| 52 | + child.once("close", code => resolve(code)); |
| 53 | +}); |
| 54 | + |
| 55 | +fs.unlinkSync(artifactListFile); |
| 56 | + |
| 57 | +for await (const chunk of child.stdout.setEncoding("utf8")) { |
| 58 | + const lines = /** @type {string} */ (chunk).trim().split(/\s/); |
| 59 | + for (const line of lines) { |
| 60 | + /** @type {YarnPackOutputLine} */ |
| 61 | + const json = JSON.parse(line); |
| 62 | + if ("location" in json) { |
| 63 | + // Workaround for false positive reports |
| 64 | + // See https://github.com/yarnpkg/berry/issues/6766 |
| 65 | + if (json.location.startsWith("_build")) { |
| 66 | + continue; |
| 67 | + } |
| 68 | + fs.appendFileSync( |
| 69 | + artifactListFile, |
| 70 | + json.location + "\n", |
| 71 | + "utf8", |
| 72 | + ); |
| 73 | + } |
| 74 | + } |
60 | 75 | }
|
61 | 76 |
|
62 |
| -filePaths.sort(); |
63 |
| -fs.writeFileSync(fileListPath, filePaths.join("\n")); |
| 77 | +await exitCode; |
64 | 78 |
|
65 | 79 | if (mode === "package") {
|
66 |
| - execSync(`git diff --exit-code ${fileListPath}`, { stdio: "inherit" }); |
67 |
| -} |
68 |
| - |
69 |
| -function getFilesAddedByCI() { |
70 |
| - const platforms = ["darwin", "darwinarm64", "linux", "linuxarm64", "win32"]; |
71 |
| - const exes = [ |
72 |
| - "bsb_helper.exe", |
73 |
| - "bsc.exe", |
74 |
| - "ninja.exe", |
75 |
| - "rescript.exe", |
76 |
| - "rescript-editor-analysis.exe", |
77 |
| - "rescript-tools.exe", |
78 |
| - "rewatch.exe", |
79 |
| - ]; |
80 |
| - |
81 |
| - const files = ["ninja.COPYING"]; |
82 |
| - |
83 |
| - for (const platform of platforms) { |
84 |
| - for (const exe of exes) { |
85 |
| - files.push(`${platform}/${exe}`); |
86 |
| - } |
87 |
| - } |
88 |
| - |
89 |
| - return files; |
| 80 | + execSync(`git diff --exit-code ${artifactListFile}`, { stdio: "inherit" }); |
90 | 81 | }
|
0 commit comments