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 +21 -0
- package/README.md +119 -0
- package/dist/cli.js +15 -0
- package/dist/convert-virtual-code-owners.js +33 -0
- package/dist/read-and-convert.js +13 -0
- package/dist/version.js +1 -0
- package/package.json +71 -0
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
|
+
}
|
package/dist/version.js
ADDED
|
@@ -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
|
+
}
|