virtual-code-owners 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022-2022 Sander Verweij
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,119 @@
1
+ ## What?
2
+
3
+ This takes a
4
+
5
+ - VIRTUAL-CODEOWNERS.txt file with (virtual) teams
6
+ - a `virtual-teams.yml` file which define the teams
7
+
8
+ ... and churns out a CODEOWNERS with user names.
9
+
10
+ ## Usage
11
+
12
+ - Rename your `CODEOWNERS` to `VIRTUAL-CODEOWNERS.txt` and put team names in them.
13
+ - Specify team names that don't (yet) exist on GitHub level in a `virtual-teams.yml`
14
+ - Run this:
15
+
16
+ ```
17
+ npx virtual-code-owners VIRTUAL-CODEOWNERS.txt virtual-teams.yml > .github/CODEOWNERS
18
+ ```
19
+
20
+ ## Why?
21
+
22
+ Organizations sometimes have large mono repositories with loads of code owners.
23
+ They or their bureaucracy haven't landed on actually using GitHub teams to clearly
24
+ demarcate that. Teams in those organizations who want to have clear code ownership
25
+ have the following choices:
26
+
27
+ - Wrestle the bureaucracy.
28
+ This is the recommended approach. It might take a while, though - and even
29
+ though there are good people on many levels in bureaucracies, it might
30
+ eventually not pan out because #reasons.
31
+ - Maintain a CODEOWNERS file with code assigned to large lists of individuals.
32
+ An option, but laborious to maintain.
33
+ - Use `virtual-code-owners`.
34
+
35
+ ## Formats
36
+
37
+ ### VIRTUAL-CODEOWNERS.txt
38
+
39
+ `VIRTUAL_CODEOWNERS.txt` is a regular, valid GitHub [CODEOWNERS](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-and-branch-protection) file.
40
+ The only difference between VIRTUAL-CODEOWNERS and a CODEOWNERS file is that
41
+ the _teams_ the former uses might not exist yet, except in a `virtual-teams.yml`.
42
+
43
+ Example:
44
+
45
+ ```
46
+ * @cloud-heroes-all
47
+ .github/ @ch/transversal
48
+ apps/broker @ch/transversal
49
+ apps/ux-portal/ @ch/ux @ch/transversal
50
+ libs/ubc-sales/ @ch/sales
51
+ libs/ubc-after-sales/ @ch/after-sales
52
+ libs/ubc-pre-sales/ @ch/pre-sales
53
+ libs/components/ @ch/ux
54
+ ```
55
+
56
+ ### virtual-teams.yml
57
+
58
+ A valid YAML file that contains a list of teams, with for each team its members:
59
+
60
+ ```yaml
61
+ ch/after-sales:
62
+ - john-doe-ch
63
+ - pete-peterson-ch
64
+ - william-the-fourth-ch
65
+ ch/sales:
66
+ - gregory-gregson-ch
67
+ - jane-doe-ch
68
+ ch/pre-sales:
69
+ - jean-claude-ch
70
+ - valerie-valerton-ch
71
+ - averel-dalton-ch
72
+ ch/ux:
73
+ - davy-davidson-ch
74
+ - john-johnson-ch
75
+ - joe-dalton-ch
76
+ ch/transversal:
77
+ - luke-the-lucky-ch
78
+ # etc
79
+ ```
80
+
81
+ ## FAQ
82
+
83
+ ### Can I mix real and virtual teams in `VIRTUAL-CODEOWNERS.txt`?
84
+
85
+ Yes.
86
+
87
+ It might be you already have a team or two defined, but just want to use
88
+ _additional_ teams. In that case just don't specify the already-defined teams
89
+ in `virtual-teams.yml` and _virtual-code-owners_ will leave them alone.
90
+
91
+ ### Can I still use usernames in `VIRTUAL-CODEOWNERS.txt`
92
+
93
+ Yes.
94
+
95
+ Just make sure there's no name clashes between the username and a (virtual)
96
+ team name and _virtual-code-owners_ will leave the real name alone.
97
+
98
+ ### Any limitations I should know of?
99
+
100
+ - Currently only works for _usernames_ to identify team members - not for e-mail
101
+ addresses.
102
+ - If people are in more than one team, chances are they get mentioned multiple
103
+ times on the same line if both teams are code owners of the same part of the
104
+ code. While maybe not _looking_ ideal, the resulting code owners file is still
105
+ valid & ready to rock'n roll.
106
+ - _virtual-code-owners_ assumes the VIRTUAL-CODEOWNERS.txt is a valid CODEOWNERS
107
+ file and the virtual-teams.yml is a valid yaml file with teams names as keys
108
+ and team members as arrays under these. It will likely throw errors when this
109
+ assumption is not met, but the error-messages might not be as clear as possible.
110
+
111
+ ### Why the `.txt` extension?
112
+
113
+ Various editors assume an ALL_CAPS file name with `#` characters on various lines
114
+ to be markdown, and will auto format them as such - making for either very ugly
115
+ or in worst cases invalid CODOWNERS files. Usually such autoformatting is not
116
+ present on text files.
117
+
118
+ Apparently these editors know about CODEOWNERS, though so this auto formatting
119
+ doesn't seem to be happening over there.
package/dist/cli.js ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import { program } from "commander";
3
+ import { VERSION } from "./version.js";
4
+ import { readAndConvert } from "./read-and-convert.js";
5
+ program
6
+ .description("Takes a VIRTUAL-CODEOWNERS.txt & a virtual-teams.yml and emits a CODEOWNERS to stdout")
7
+ .version(VERSION)
8
+ .arguments("<virtual-code-owners-file> <virtual-teams.yml>")
9
+ .parse(process.argv);
10
+ try {
11
+ console.log(readAndConvert(program.args[0], program.args[1]));
12
+ }
13
+ catch (pError) {
14
+ console.error(`ERROR: ${pError.message}`);
15
+ }
@@ -0,0 +1,33 @@
1
+ import { EOL } from "node:os";
2
+ const DEFAULT_GENERATED_WARNING = `#${EOL}` +
3
+ `# DO NOT EDIT - this file is generated and your edits will be overwritten${EOL}` +
4
+ `#${EOL}` +
5
+ `# To make changes:${EOL}` +
6
+ `#${EOL}` +
7
+ `# - edit VIRTUAL-CODEOWNERS.txt${EOL}` +
8
+ `# - run 'npx virtual-code-owners VIRTUAL-CODE-OWNERS.txt virtual-teams.yml > CODEOWNERS'${EOL}` +
9
+ `#${EOL}${EOL}`;
10
+ function replaceTeamNames(pLine, pTeamMap) {
11
+ let lReturnValue = pLine;
12
+ for (let lTeamName of Object.keys(pTeamMap)) {
13
+ lReturnValue = lReturnValue.replace(`@${lTeamName}`, pTeamMap[lTeamName].map((pUserName) => `@${pUserName}`).join(" "));
14
+ }
15
+ return lReturnValue;
16
+ }
17
+ function convertLine(pTeamMap) {
18
+ return (pUntreatedLine) => {
19
+ const lTrimmedLine = pUntreatedLine.trimStart();
20
+ if (lTrimmedLine.startsWith("#") || lTrimmedLine === "") {
21
+ return pUntreatedLine;
22
+ }
23
+ else {
24
+ return replaceTeamNames(pUntreatedLine, pTeamMap);
25
+ }
26
+ };
27
+ }
28
+ export function convert(pCodeOwnersFileAsString, pTeamMap, pGeneratedWarning = DEFAULT_GENERATED_WARNING) {
29
+ return `${pGeneratedWarning}${pCodeOwnersFileAsString
30
+ .split(EOL)
31
+ .map(convertLine(pTeamMap))
32
+ .join(EOL)}`;
33
+ }
@@ -0,0 +1,13 @@
1
+ import { readFileSync } from "node:fs";
2
+ import yaml from "js-yaml";
3
+ import { convert } from "./convert-virtual-code-owners.js";
4
+ export function readAndConvert(pVirtualCodeOwnersFileName, pVirtualTeamsFileName) {
5
+ const lVirtualCodeOwnersFileAsAString = readFileSync(pVirtualCodeOwnersFileName, {
6
+ encoding: "utf-8",
7
+ });
8
+ const lVirtualTeamsYamlAsAString = readFileSync(pVirtualTeamsFileName, {
9
+ encoding: "utf-8",
10
+ });
11
+ const lTeamMap = yaml.load(lVirtualTeamsYamlAsAString);
12
+ return convert(lVirtualCodeOwnersFileAsAString, lTeamMap);
13
+ }
@@ -0,0 +1 @@
1
+ export const VERSION = "1.0.0";
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "virtual-code-owners",
3
+ "version": "1.0.0",
4
+ "description": "merges a VIRTUAL-CODEOWNERS.txt and a virtual-teams.yml into CODEOWNERS",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": [
8
+ {
9
+ "import": "./dist/read-and-convert.js"
10
+ },
11
+ "./dist/read-and-convert.js"
12
+ ]
13
+ },
14
+ "main": "dist/read-and-convert.js",
15
+ "bin": "dist/cli.js",
16
+ "files": [
17
+ "dist",
18
+ "package.json",
19
+ "README.md"
20
+ ],
21
+ "scripts": {
22
+ "build": "rm -rf dist && node tools/get-version.mjs > src/version.ts && tsc",
23
+ "depcruise": "depcruise src --config .dependency-cruiser.cjs",
24
+ "depcruise:graph": "depcruise src --include-only '^(src)' --config --output-type dot | dot -T svg | depcruise-wrap-stream-in-html > dependency-graph.html",
25
+ "depcruise:graph:dev": "depcruise src --prefix vscode://file/$(pwd)/ --config --output-type dot | dot -T svg | depcruise-wrap-stream-in-html | browser",
26
+ "depcruise:graph:diff:dev": "depcruise src --prefix vscode://file/$(pwd)/ --config --output-type dot --reaches \"$(watskeburt $SHA -T regex)\"| dot -T svg | depcruise-wrap-stream-in-html | browser",
27
+ "depcruise:graph:diff:mermaid": "depcruise src --config --output-type mermaid --output-to - --reaches \"$(watskeburt $SHA -T regex)\"",
28
+ "depcruise:html": "depcruise src --config --output-type err-html --output-to dependency-violation-report.html",
29
+ "format": "prettier --loglevel warn --write \"**/*.{md,ts,json,yml}\"",
30
+ "scm:stage": "git add .",
31
+ "test": "NODE_OPTIONS=--no-warnings mocha",
32
+ "test:cover": "NODE_OPTIONS=--no-warnings c8 mocha",
33
+ "update-dependencies": "npm run upem:update && npm run upem:install && npm run format && npm run build && npm test",
34
+ "upem-outdated": "npm outdated --json --long | upem --dry-run",
35
+ "upem:install": "npm install",
36
+ "upem:update": "npm outdated --json --long | upem | pbcopy && pbpaste",
37
+ "version": "npm run build && npm run scm:stage"
38
+ },
39
+ "keywords": [
40
+ "CODEOWNERS"
41
+ ],
42
+ "author": "Sander Verweij (https://sverweij.github.io/)",
43
+ "license": "MIT",
44
+ "homepage": "https://github.com/sverweij/virtual-code-owners",
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "git+https://github.com/sverweij/virtual-code-owners"
48
+ },
49
+ "bugs": {
50
+ "url": "https://github.com/sverweij/virtual-code-owners/issues"
51
+ },
52
+ "devDependencies": {
53
+ "@types/js-yaml": "4.0.5",
54
+ "@types/node": "18.14.5",
55
+ "c8": "7.13.0",
56
+ "dependency-cruiser": "12.10.0",
57
+ "mocha": "10.2.0",
58
+ "prettier": "2.8.4",
59
+ "ts-node": "10.9.1",
60
+ "typescript": "4.9.5",
61
+ "upem": "7.3.2",
62
+ "watskeburt": "0.10.0"
63
+ },
64
+ "dependencies": {
65
+ "commander": "10.0.0",
66
+ "js-yaml": "4.1.0"
67
+ },
68
+ "engines": {
69
+ "node": "^14.13.1||^16||>=18"
70
+ }
71
+ }