virtual-code-owners 5.1.0 → 6.0.0

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/dist/cli.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { main } from "./main.js";
3
- main();
2
+ import { cli } from "./main.js";
3
+ cli();
@@ -35,7 +35,7 @@ function transformForYamlAndMinimatch(pOriginalString) {
35
35
  lReturnValue = "**";
36
36
  }
37
37
  if (lReturnValue.startsWith("*")) {
38
- lReturnValue = `'${lReturnValue}'`;
38
+ lReturnValue = `"${lReturnValue}"`;
39
39
  }
40
40
  if (pOriginalString.endsWith("/")) {
41
41
  lReturnValue = `${lReturnValue}**`;
package/dist/main.js CHANGED
@@ -6,7 +6,6 @@ import generateLabelerYml from "./generate-labeler-yml.js";
6
6
  import readTeamMap from "./read-team-map.js";
7
7
  import readVirtualCodeOwners from "./read-virtual-code-owners.js";
8
8
  import { VERSION } from "./version.js";
9
- import { getAnomalies } from "./parse.js";
10
9
  const HELP_MESSAGE = `Usage: virtual-code-owners [options]
11
10
 
12
11
  Merges a VIRTUAL-CODEOWNERS.txt and a virtual-teams.yml into CODEOWNERS
@@ -27,7 +26,7 @@ Options:
27
26
  --labelerLocation [file-name] The location of the labeler.yml file
28
27
  (default: ".github/labeler.yml")
29
28
  -h, --help display help for command`;
30
- export function main(pArguments = process.argv.slice(2), pOutStream = process.stdout, pErrorStream = process.stderr) {
29
+ export function cli(pArguments = process.argv.slice(2), pOutStream = process.stdout, pErrorStream = process.stderr) {
31
30
  try {
32
31
  const lOptions = getOptions(pArguments);
33
32
  if (lOptions.help) {
@@ -38,45 +37,13 @@ export function main(pArguments = process.argv.slice(2), pOutStream = process.st
38
37
  pOutStream.write(`${VERSION}${EOL}`);
39
38
  return;
40
39
  }
41
- const lTeamMap = readTeamMap(lOptions.virtualTeams);
42
- const lVirtualCodeOwners = readVirtualCodeOwners(lOptions.virtualCodeOwners, lTeamMap);
43
- const lAnomalies = getAnomalies(lVirtualCodeOwners);
44
- if (lAnomalies.length > 0) {
45
- throw new Error(`${EOL}${reportAnomalies(lOptions.virtualCodeOwners, lAnomalies)}`);
46
- }
47
- const lCodeOwnersContent = generateCodeOwners(lVirtualCodeOwners, lTeamMap);
48
- writeFileSync(lOptions.codeOwners, lCodeOwnersContent, {
49
- encoding: "utf-8",
50
- });
51
- if (lOptions.emitLabeler) {
52
- const lLabelerContent = generateLabelerYml(lVirtualCodeOwners, lTeamMap);
53
- writeFileSync(lOptions.labelerLocation, lLabelerContent, {
54
- encoding: "utf-8",
55
- });
56
- pErrorStream.write(`${EOL}Wrote ${lOptions.codeOwners} AND ${lOptions.labelerLocation}${EOL}${EOL}`);
57
- }
58
- else {
59
- pErrorStream.write(`${EOL}Wrote ${lOptions.codeOwners}${EOL}${EOL}`);
60
- }
40
+ main(lOptions, pErrorStream);
61
41
  }
62
42
  catch (pError) {
63
43
  pErrorStream.write(`${EOL}ERROR: ${pError.message}${EOL}${EOL}`);
64
44
  process.exitCode = 1;
65
45
  }
66
46
  }
67
- function reportAnomalies(pFileName, pAnomalies) {
68
- return pAnomalies
69
- .map((pAnomaly) => {
70
- if (pAnomaly.type === "invalid-line") {
71
- return `${pFileName}:${pAnomaly.line}:1 invalid line - neither a rule, comment nor empty: '${pAnomaly.raw}'`;
72
- }
73
- else {
74
- return (`${pFileName}:${pAnomaly.line}:1 invalid user or team name '${pAnomaly.raw}' (# ${pAnomaly.userNumberWithinLine} on this line). ` +
75
- `It should either start with '@' or be an e-mail address.`);
76
- }
77
- })
78
- .join(EOL);
79
- }
80
47
  function getOptions(pArguments) {
81
48
  return parseArgs({
82
49
  args: pArguments,
@@ -113,3 +80,21 @@ function getOptions(pArguments) {
113
80
  tokens: false,
114
81
  }).values;
115
82
  }
83
+ function main(pOptions, pErrorStream) {
84
+ const lTeamMap = readTeamMap(pOptions.virtualTeams);
85
+ const lVirtualCodeOwners = readVirtualCodeOwners(pOptions.virtualCodeOwners, lTeamMap);
86
+ const lCodeOwnersContent = generateCodeOwners(lVirtualCodeOwners, lTeamMap);
87
+ writeFileSync(pOptions.codeOwners, lCodeOwnersContent, {
88
+ encoding: "utf-8",
89
+ });
90
+ if (pOptions.emitLabeler) {
91
+ const lLabelerContent = generateLabelerYml(lVirtualCodeOwners, lTeamMap);
92
+ writeFileSync(pOptions.labelerLocation, lLabelerContent, {
93
+ encoding: "utf-8",
94
+ });
95
+ pErrorStream.write(`${EOL}Wrote '${pOptions.codeOwners}' AND '${pOptions.labelerLocation}'${EOL}${EOL}`);
96
+ }
97
+ else {
98
+ pErrorStream.write(`${EOL}Wrote '${pOptions.codeOwners}'${EOL}${EOL}`);
99
+ }
100
+ }
@@ -1,8 +1,30 @@
1
+ import Ajv from "ajv";
1
2
  import { readFileSync } from "node:fs";
3
+ import { EOL } from "node:os";
2
4
  import { parse as parseYaml } from "yaml";
5
+ const TEAM_MAP_SCHEMA = JSON.parse(readFileSync(new URL("./virtual-teams.schema.json", import.meta.url), "utf-8"));
3
6
  export default function readTeamMap(pVirtualTeamsFileName) {
4
7
  const lVirtualTeamsAsAString = readFileSync(pVirtualTeamsFileName, {
5
8
  encoding: "utf-8",
6
9
  });
7
- return parseYaml(lVirtualTeamsAsAString);
10
+ const lTeamMap = parseYaml(lVirtualTeamsAsAString);
11
+ validateTeamMap(lTeamMap, pVirtualTeamsFileName);
12
+ return lTeamMap;
13
+ }
14
+ function validateTeamMap(pTeamMap, pVirtualTeamsFileName) {
15
+ const ajv = new Ajv({
16
+ allErrors: true,
17
+ verbose: true,
18
+ });
19
+ if (!ajv.validate(TEAM_MAP_SCHEMA, pTeamMap)) {
20
+ throw new Error(`This is not a valid virtual-teams.yml:${EOL}${formatAjvErrors(ajv.errors, pVirtualTeamsFileName)}.\n`);
21
+ }
22
+ }
23
+ function formatAjvErrors(pAjvErrors, pVirtualTeamsFileName) {
24
+ return pAjvErrors
25
+ .map((pAjvError) => formatAjvError(pAjvError, pVirtualTeamsFileName))
26
+ .join(EOL);
27
+ }
28
+ function formatAjvError(pAjvError, pVirtualTeamsFileName) {
29
+ return `${pVirtualTeamsFileName}: ${pAjvError.instancePath} - ${JSON.stringify(pAjvError.data)} ${pAjvError.message}`;
8
30
  }
@@ -1,8 +1,27 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { parse as parseVirtualCodeOwners } from "./parse.js";
2
+ import { EOL } from "node:os";
3
+ import { getAnomalies, parse as parseVirtualCodeOwners } from "./parse.js";
3
4
  export default function readVirtualCodeOwners(pVirtualCodeOwnersFileName, pTeamMap) {
4
5
  const lVirtualCodeOwnersAsAString = readFileSync(pVirtualCodeOwnersFileName, {
5
6
  encoding: "utf-8",
6
7
  });
7
- return parseVirtualCodeOwners(lVirtualCodeOwnersAsAString, pTeamMap);
8
+ const lVirtualCodeOwners = parseVirtualCodeOwners(lVirtualCodeOwnersAsAString, pTeamMap);
9
+ const lAnomalies = getAnomalies(lVirtualCodeOwners);
10
+ if (lAnomalies.length > 0) {
11
+ throw new Error(`This is not a valid virtual code-owners file:${EOL}${reportAnomalies(pVirtualCodeOwnersFileName, lAnomalies)}`);
12
+ }
13
+ return lVirtualCodeOwners;
14
+ }
15
+ function reportAnomalies(pFileName, pAnomalies) {
16
+ return pAnomalies
17
+ .map((pAnomaly) => {
18
+ if (pAnomaly.type === "invalid-line") {
19
+ return `${pFileName}:${pAnomaly.line}:1 invalid line - neither a rule, comment nor empty: "${pAnomaly.raw}"`;
20
+ }
21
+ else {
22
+ return (`${pFileName}:${pAnomaly.line}:1 invalid user or team name "${pAnomaly.raw}" (#${pAnomaly.userNumberWithinLine} on this line). ` +
23
+ `It should either start with "@" or be an e-mail address.`);
24
+ }
25
+ })
26
+ .join(EOL);
8
27
  }
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = "5.1.0";
1
+ export const VERSION = "6.0.0";
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "virtual teams schema for virtual-code-owners",
4
+ "description": "a list of teams and their team members",
5
+ "$id": "org.js.virtual-code-owners/4.1.0",
6
+ "type": "object",
7
+ "additionalProperties": {
8
+ "type": "array",
9
+ "items": {
10
+ "type": "string",
11
+ "description": "Username or e-mail address of a team member. (Don't prefix usernames with '@')",
12
+ "pattern": "^[^@][^\\s]+$"
13
+ }
14
+ }
15
+ }
package/package.json CHANGED
@@ -1,18 +1,33 @@
1
1
  {
2
2
  "name": "virtual-code-owners",
3
- "version": "5.1.0",
3
+ "version": "6.0.0",
4
4
  "description": "Merges a VIRTUAL-CODEOWNERS.txt and a virtual-teams.yml into CODEOWNERS",
5
5
  "type": "module",
6
6
  "exports": {
7
- ".": [
7
+ "parse": [
8
8
  {
9
- "import": "./dist/parse-and-generate.js",
10
- "types": "./types/parse-and-generate.d.ts"
9
+ "import": "./dist/parse.js",
10
+ "types": "./types/parse.d.ts"
11
11
  },
12
- "./dist/parse-and-generate.js"
12
+ "./dist/parse.js"
13
+ ],
14
+ "generateCodeOwners": [
15
+ {
16
+ "import": "./dist/generate-codeowners.js",
17
+ "types": "./types/generate-codeowners.d.ts"
18
+ },
19
+ "./dist/generate-codeowners.js"
20
+ ],
21
+ "generateLabelerYml": [
22
+ {
23
+ "import": "./dist/generate-labeler-yml.js",
24
+ "types": "./types/generate-labeler-yml.d.ts"
25
+ },
26
+ "./dist/generate-labeler-yml.js"
13
27
  ]
14
28
  },
15
- "main": "dist/parse-and-generate.js",
29
+ "main": "dist/main.js",
30
+ "types": "types/types.d.ts",
16
31
  "bin": "dist/cli.js",
17
32
  "files": [
18
33
  "dist",
@@ -21,7 +36,7 @@
21
36
  "LICENSE"
22
37
  ],
23
38
  "scripts": {
24
- "build": "rm -rf dist && node --no-warnings --loader ts-node/esm tools/get-version.ts > src/version.ts && tsc",
39
+ "build": "rm -rf dist && node --no-warnings --loader ts-node/esm tools/get-version.ts > src/version.ts && tsc && cp -f src/*.json dist/.",
25
40
  "check": "npm run format && npm run build && npm run depcruise -- --no-progress && npm test",
26
41
  "depcruise": "depcruise src tools",
27
42
  "depcruise:graph": "depcruise src --include-only '^(src)' --output-type dot | dot -T svg | depcruise-wrap-stream-in-html > dependency-graph.html",
@@ -54,8 +69,8 @@
54
69
  },
55
70
  "devDependencies": {
56
71
  "@types/mocha": "10.0.1",
57
- "@types/node": "20.3.0",
58
- "c8": "7.14.0",
72
+ "@types/node": "20.3.1",
73
+ "c8": "8.0.0",
59
74
  "dependency-cruiser": "13.0.3",
60
75
  "husky": "8.0.3",
61
76
  "lint-staged": "13.2.2",
@@ -67,6 +82,7 @@
67
82
  "watskeburt": "0.11.3"
68
83
  },
69
84
  "dependencies": {
85
+ "ajv": "8.12.0",
70
86
  "yaml": "2.3.1"
71
87
  },
72
88
  "engines": {