microsoft/typespec

Public

mirrored fromhttps://github.com/microsoft/typespecAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
379a0aec4451d65f7126f9292fc7a6d627c68508

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

eng/scripts/helpers.js

105lines · modecode

1import { spawn, spawnSync } from "child_process";
2import { readFileSync } from "fs";
3import { dirname, join, resolve } from "path";
4import { fileURLToPath } from "url";
5
6function read(filename) {
7 const txt = readFileSync(filename, "utf-8")
8 .replace(/\r/gm, "")
9 .replace(/\n/gm, "«")
10 .replace(/\/\*.*?\*\//gm, "")
11 .replace(/«/gm, "\n")
12 .replace(/\s+\/\/.*/g, "");
13 return JSON.parse(txt);
14}
15
16export const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
17export const prettier = resolve(repoRoot, "packages/compiler/node_modules/.bin/prettier");
18export const tsc = resolve(repoRoot, "packages/compiler/node_modules/.bin/tsc");
19
20const rush = read(`${repoRoot}/rush.json`);
21
22export function forEachProject(onEach) {
23 // load all the projects
24 for (const each of rush.projects) {
25 const packageName = each.packageName;
26 const projectFolder = resolve(`${repoRoot}/${each.projectFolder}`);
27 const project = JSON.parse(readFileSync(`${projectFolder}/package.json`, "utf-8"));
28 onEach(packageName, projectFolder, project);
29 }
30}
31
32export function npmForEach(cmd, options) {
33 forEachProject((name, location, project) => {
34 if (cmd === "test-official" && !project.scripts[cmd] && project.scripts["test"]) {
35 const pj = join(location, "package.json");
36 throw new Error(`${pj} has a 'test' script, but no 'test-official' script for CI.`);
37 }
38
39 if (project.scripts[cmd] || cmd === "pack") {
40 const args = cmd === "pack" ? [cmd] : ["run", cmd];
41 run("npm", args, { cwd: location, ...options });
42 }
43 });
44}
45
46// We could use { shell: true } to let Windows find .cmd, but that causes other issues.
47// It breaks ENOENT checking for command-not-found and also handles command/args with spaces
48// poorly.
49const isCmdOnWindows = ["rush", "npm", "code", "code-insiders", tsc, prettier];
50
51export class CommandFailedError extends Error {
52 constructor(msg, proc) {
53 super(msg);
54 this.proc = proc;
55 }
56}
57
58export function run(command, args, options) {
59 console.log();
60 console.log(`> ${command} ${args.join(" ")}`);
61
62 options = {
63 stdio: "inherit",
64 sync: true,
65 throwOnNonZeroExit: true,
66 ...options,
67 };
68
69 if (process.platform === "win32" && isCmdOnWindows.includes(command)) {
70 command += ".cmd";
71 }
72
73 const proc = (options.sync ? spawnSync : spawn)(command, args, options);
74 if (proc.error) {
75 if (options.ignoreCommandNotFound && proc.error.code === "ENOENT") {
76 console.log(`Skipped: Command \`${command}\` not found.`);
77 } else {
78 throw proc.error;
79 }
80 } else if (options.throwOnNonZeroExit && proc.status !== undefined && proc.status !== 0) {
81 throw new CommandFailedError(
82 `Command \`${command} ${args.join(" ")}\` failed with exit code ${proc.status}`,
83 proc
84 );
85 }
86
87 return proc;
88}
89
90export function runPrettier(...args) {
91 run(
92 prettier,
93 [
94 ...args,
95 "--config",
96 ".prettierrc.json",
97 "--ignore-path",
98 ".prettierignore",
99 "**/*.{ts,js,tsx,jsx,cjs,mjs,css,json,yml,yaml,typespec,md}",
100 ],
101 {
102 cwd: repoRoot,
103 }
104 );
105}