codeowners-git 1.4.2 → 1.6.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/README.md +70 -4
- package/dist/cli.js +189 -18
- package/package.json +10 -4
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Managing large-scale migrations in big monorepos with multiple codeowners can be overwhelming. Massive PRs touching thousands of files make it hard for teams to review changes efficiently.
|
|
8
8
|
|
|
9
|
-
`codeowners-git` solves this by:
|
|
9
|
+
`codeowners-git` (or `cg` for short) solves this by:
|
|
10
10
|
|
|
11
11
|
- Identifying files owned by specific teams using the CODEOWNERS file.
|
|
12
12
|
- Creating compact, team-specific branches with only their affected files.
|
|
@@ -24,6 +24,8 @@ Run commands directly without installation:
|
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
npx codeowners-git <command>
|
|
27
|
+
# or use the short alias
|
|
28
|
+
npx cg <command>
|
|
27
29
|
```
|
|
28
30
|
|
|
29
31
|
### Install globally via npm
|
|
@@ -36,6 +38,8 @@ Then run commands directly:
|
|
|
36
38
|
|
|
37
39
|
```bash
|
|
38
40
|
codeowners-git <command>
|
|
41
|
+
# or use the short alias
|
|
42
|
+
cg <command>
|
|
39
43
|
```
|
|
40
44
|
|
|
41
45
|
## Configuration
|
|
@@ -46,6 +50,29 @@ The tool automatically detects CODEOWNERS files in:
|
|
|
46
50
|
2. `docs/CODEOWNERS`
|
|
47
51
|
3. `CODEOWNERS` (root directory)
|
|
48
52
|
|
|
53
|
+
### Pull Request Features
|
|
54
|
+
|
|
55
|
+
The `--pr` and `--draft-pr` options require the [GitHub CLI (`gh`)](https://cli.github.com/) to be installed and authenticated:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Install GitHub CLI (macOS)
|
|
59
|
+
brew install gh
|
|
60
|
+
|
|
61
|
+
# Install GitHub CLI (Windows)
|
|
62
|
+
winget install --id GitHub.cli
|
|
63
|
+
|
|
64
|
+
# Install GitHub CLI (Linux)
|
|
65
|
+
sudo apt install gh
|
|
66
|
+
|
|
67
|
+
# Authenticate with GitHub
|
|
68
|
+
gh auth login
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The tool will automatically:
|
|
72
|
+
- Use PR templates if they exist in your repository (`.github/pull_request_template.md`, etc.)
|
|
73
|
+
- Set the PR title to your commit message
|
|
74
|
+
- Create PRs against the repository's default branch
|
|
75
|
+
|
|
49
76
|
## Commands
|
|
50
77
|
|
|
51
78
|
### `--version`
|
|
@@ -58,6 +85,8 @@ Usage:
|
|
|
58
85
|
codeowners-git --version
|
|
59
86
|
# or
|
|
60
87
|
codeowners-git -V
|
|
88
|
+
# or using the short alias
|
|
89
|
+
cg --version
|
|
61
90
|
```
|
|
62
91
|
|
|
63
92
|
### `list`
|
|
@@ -68,6 +97,8 @@ Usage:
|
|
|
68
97
|
|
|
69
98
|
```bash
|
|
70
99
|
codeowners-git list [options]
|
|
100
|
+
# or
|
|
101
|
+
cg list [options]
|
|
71
102
|
```
|
|
72
103
|
|
|
73
104
|
Options:
|
|
@@ -79,6 +110,8 @@ Example:
|
|
|
79
110
|
|
|
80
111
|
```bash
|
|
81
112
|
codeowners-git list -o @myteam
|
|
113
|
+
# or
|
|
114
|
+
cg list -o @myteam
|
|
82
115
|
```
|
|
83
116
|
|
|
84
117
|
### `branch`
|
|
@@ -89,6 +122,8 @@ Usage:
|
|
|
89
122
|
|
|
90
123
|
```bash
|
|
91
124
|
codeowners-git branch [options]
|
|
125
|
+
# or
|
|
126
|
+
cg branch [options]
|
|
92
127
|
```
|
|
93
128
|
|
|
94
129
|
Options:
|
|
@@ -102,11 +137,26 @@ Options:
|
|
|
102
137
|
- `--upstream, -u` Upstream branch name (defaults to local branch name)
|
|
103
138
|
- `--force, -f` Force push to remote
|
|
104
139
|
- `--keep-branch-on-failure, -k` Keep the created branch even if operation fails
|
|
140
|
+
- `--append` Add commits to existing branch instead of creating a new one
|
|
141
|
+
- `--pr` Create a pull request after pushing (requires `--push` and GitHub CLI)
|
|
142
|
+
- `--draft-pr` Create a draft pull request after pushing (requires `--push` and GitHub CLI)
|
|
105
143
|
|
|
106
144
|
Example:
|
|
107
145
|
|
|
108
146
|
```bash
|
|
147
|
+
# Create a new branch
|
|
109
148
|
codeowners-git branch -o @myteam -b "feature/new-feature" -m "Add new feature" -p
|
|
149
|
+
# or
|
|
150
|
+
cg branch -o @myteam -b "feature/new-feature" -m "Add new feature" -p
|
|
151
|
+
|
|
152
|
+
# Create a branch and automatically create a pull request
|
|
153
|
+
cg branch -o @myteam -b "feature/new-feature" -m "Add new feature" -p --pr
|
|
154
|
+
|
|
155
|
+
# Create a branch and automatically create a draft pull request
|
|
156
|
+
cg branch -o @myteam -b "feature/new-feature" -m "Add new feature" -p --draft-pr
|
|
157
|
+
|
|
158
|
+
# Add more commits to the same branch later
|
|
159
|
+
cg branch -o @myteam -b "feature/new-feature" -m "Add more changes" --append -p
|
|
110
160
|
```
|
|
111
161
|
|
|
112
162
|
### `multi-branch`
|
|
@@ -117,6 +167,8 @@ Usage:
|
|
|
117
167
|
|
|
118
168
|
```bash
|
|
119
169
|
codeowners-git multi-branch [options]
|
|
170
|
+
# or
|
|
171
|
+
cg multi-branch [options]
|
|
120
172
|
```
|
|
121
173
|
|
|
122
174
|
Options:
|
|
@@ -132,6 +184,9 @@ Options:
|
|
|
132
184
|
- `--default-owner, -d` Default owner to use when no codeowners are found for changed files
|
|
133
185
|
- `--ignore` Comma-separated patterns to exclude codeowners (e.g., 'team-a,team-b')
|
|
134
186
|
- `--include` Comma-separated patterns to include codeowners (e.g., 'team-_,@org/_')
|
|
187
|
+
- `--append` Add commits to existing branches instead of creating new ones
|
|
188
|
+
- `--pr` Create pull requests after pushing (requires `--push` and GitHub CLI)
|
|
189
|
+
- `--draft-pr` Create draft pull requests after pushing (requires `--push` and GitHub CLI)
|
|
135
190
|
|
|
136
191
|
> **Note:** You cannot use both `--ignore` and `--include` options at the same time.
|
|
137
192
|
|
|
@@ -140,15 +195,26 @@ Example:
|
|
|
140
195
|
```bash
|
|
141
196
|
# Create branches for all codeowners
|
|
142
197
|
codeowners-git multi-branch -b "feature/new-feature" -m "Add new feature" -p
|
|
198
|
+
# or
|
|
199
|
+
cg multi-branch -b "feature/new-feature" -m "Add new feature" -p
|
|
200
|
+
|
|
201
|
+
# Create branches and automatically create pull requests for each
|
|
202
|
+
cg multi-branch -b "feature/new-feature" -m "Add new feature" -p --pr
|
|
203
|
+
|
|
204
|
+
# Create branches and automatically create draft pull requests for each
|
|
205
|
+
cg multi-branch -b "feature/new-feature" -m "Add new feature" -p --draft-pr
|
|
143
206
|
|
|
144
207
|
# Exclude specific teams
|
|
145
|
-
|
|
208
|
+
cg multi-branch -b "feature/new-feature" -m "Add new feature" --ignore "@ce-orca,@ce-ece"
|
|
146
209
|
|
|
147
210
|
# Include only specific patterns
|
|
148
|
-
|
|
211
|
+
cg multi-branch -b "feature/new-feature" -m "Add new feature" --include "@team-*"
|
|
149
212
|
|
|
150
213
|
# Use default owner when no codeowners found
|
|
151
|
-
|
|
214
|
+
cg multi-branch -b "feature/new-feature" -m "Add new feature" -d "@default-team"
|
|
215
|
+
|
|
216
|
+
# Add more commits to existing branches
|
|
217
|
+
cg multi-branch -b "feature/new-feature" -m "Add more changes" --append -p
|
|
152
218
|
```
|
|
153
219
|
|
|
154
220
|
This will:
|
package/dist/cli.js
CHANGED
|
@@ -14686,6 +14686,24 @@ var pushBranch = async (branchName, {
|
|
|
14686
14686
|
throw new Error(`Push failed: ${error}`);
|
|
14687
14687
|
}
|
|
14688
14688
|
};
|
|
14689
|
+
var getDefaultBranch = async () => {
|
|
14690
|
+
try {
|
|
14691
|
+
const result = await git.raw(["symbolic-ref", "refs/remotes/origin/HEAD"]);
|
|
14692
|
+
const match = result.match(/refs\/remotes\/origin\/(.+)/);
|
|
14693
|
+
if (match) {
|
|
14694
|
+
return match[1].trim();
|
|
14695
|
+
}
|
|
14696
|
+
} catch {
|
|
14697
|
+
const branches = await git.branch(["-r"]);
|
|
14698
|
+
if (branches.all.includes("origin/main")) {
|
|
14699
|
+
return "main";
|
|
14700
|
+
}
|
|
14701
|
+
if (branches.all.includes("origin/master")) {
|
|
14702
|
+
return "master";
|
|
14703
|
+
}
|
|
14704
|
+
}
|
|
14705
|
+
return "main";
|
|
14706
|
+
};
|
|
14689
14707
|
|
|
14690
14708
|
// src/utils/codeowners.ts
|
|
14691
14709
|
var codeowners;
|
|
@@ -14776,6 +14794,107 @@ var listCodeowners = async (options) => {
|
|
|
14776
14794
|
}
|
|
14777
14795
|
};
|
|
14778
14796
|
|
|
14797
|
+
// src/utils/github.ts
|
|
14798
|
+
import { spawn as spawn3 } from "child_process";
|
|
14799
|
+
import { readFile } from "fs/promises";
|
|
14800
|
+
var isGitHubCliInstalled = async () => {
|
|
14801
|
+
return new Promise((resolve) => {
|
|
14802
|
+
const process3 = spawn3("gh", ["--version"], { stdio: "pipe" });
|
|
14803
|
+
process3.on("close", (code) => {
|
|
14804
|
+
resolve(code === 0);
|
|
14805
|
+
});
|
|
14806
|
+
process3.on("error", () => {
|
|
14807
|
+
resolve(false);
|
|
14808
|
+
});
|
|
14809
|
+
});
|
|
14810
|
+
};
|
|
14811
|
+
var findPRTemplate = async () => {
|
|
14812
|
+
const possiblePaths = [
|
|
14813
|
+
".github/pull_request_template.md",
|
|
14814
|
+
".github/PULL_REQUEST_TEMPLATE.md",
|
|
14815
|
+
".github/PULL_REQUEST_TEMPLATE/pull_request_template.md",
|
|
14816
|
+
"docs/pull_request_template.md",
|
|
14817
|
+
"docs/PULL_REQUEST_TEMPLATE.md",
|
|
14818
|
+
"pull_request_template.md",
|
|
14819
|
+
"PULL_REQUEST_TEMPLATE.md"
|
|
14820
|
+
];
|
|
14821
|
+
for (const templatePath of possiblePaths) {
|
|
14822
|
+
try {
|
|
14823
|
+
const content = await readFile(templatePath, "utf-8");
|
|
14824
|
+
log.info(`Found PR template at: ${templatePath}`);
|
|
14825
|
+
return { path: templatePath, content: content.trim() };
|
|
14826
|
+
} catch {}
|
|
14827
|
+
}
|
|
14828
|
+
return null;
|
|
14829
|
+
};
|
|
14830
|
+
var createPullRequest = async (options) => {
|
|
14831
|
+
const { title, body, draft = false, base = "main", head } = options;
|
|
14832
|
+
if (!await isGitHubCliInstalled()) {
|
|
14833
|
+
throw new Error("GitHub CLI (gh) is not installed. Please install it to create pull requests.");
|
|
14834
|
+
}
|
|
14835
|
+
const args = ["pr", "create", "--title", title];
|
|
14836
|
+
if (body) {
|
|
14837
|
+
args.push("--body", body);
|
|
14838
|
+
}
|
|
14839
|
+
if (draft) {
|
|
14840
|
+
args.push("--draft");
|
|
14841
|
+
}
|
|
14842
|
+
if (base) {
|
|
14843
|
+
args.push("--base", base);
|
|
14844
|
+
}
|
|
14845
|
+
if (head) {
|
|
14846
|
+
args.push("--head", head);
|
|
14847
|
+
}
|
|
14848
|
+
return new Promise((resolve, reject) => {
|
|
14849
|
+
const process3 = spawn3("gh", args, { stdio: "pipe" });
|
|
14850
|
+
let output = "";
|
|
14851
|
+
let errorOutput = "";
|
|
14852
|
+
process3.stdout.on("data", (data) => {
|
|
14853
|
+
output += data.toString();
|
|
14854
|
+
});
|
|
14855
|
+
process3.stderr.on("data", (data) => {
|
|
14856
|
+
errorOutput += data.toString();
|
|
14857
|
+
});
|
|
14858
|
+
process3.on("close", (code) => {
|
|
14859
|
+
if (code === 0) {
|
|
14860
|
+
const urlMatch = output.match(/https:\/\/github\.com\/[^\s]+/);
|
|
14861
|
+
const numberMatch = output.match(/#(\d+)/);
|
|
14862
|
+
if (urlMatch && numberMatch) {
|
|
14863
|
+
const url = urlMatch[0];
|
|
14864
|
+
const number = parseInt(numberMatch[1], 10);
|
|
14865
|
+
log.success(`${draft ? "Draft " : ""}Pull request created: ${url}`);
|
|
14866
|
+
resolve({ url, number });
|
|
14867
|
+
} else {
|
|
14868
|
+
log.success(`${draft ? "Draft " : ""}Pull request created successfully`);
|
|
14869
|
+
resolve({ url: output.trim(), number: 0 });
|
|
14870
|
+
}
|
|
14871
|
+
} else {
|
|
14872
|
+
const error = new Error(`Failed to create pull request: ${errorOutput || output}`);
|
|
14873
|
+
log.error(error.message);
|
|
14874
|
+
reject(error);
|
|
14875
|
+
}
|
|
14876
|
+
});
|
|
14877
|
+
process3.on("error", (error) => {
|
|
14878
|
+
reject(new Error(`Failed to execute gh command: ${error.message}`));
|
|
14879
|
+
});
|
|
14880
|
+
});
|
|
14881
|
+
};
|
|
14882
|
+
var createPRWithTemplate = async (title, branchName, options = {}) => {
|
|
14883
|
+
const template = await findPRTemplate();
|
|
14884
|
+
let body = "";
|
|
14885
|
+
if (template) {
|
|
14886
|
+
body = template.content;
|
|
14887
|
+
log.info("Using PR template for pull request body");
|
|
14888
|
+
}
|
|
14889
|
+
return createPullRequest({
|
|
14890
|
+
title,
|
|
14891
|
+
body,
|
|
14892
|
+
draft: options.draft,
|
|
14893
|
+
base: options.base,
|
|
14894
|
+
head: branchName
|
|
14895
|
+
});
|
|
14896
|
+
};
|
|
14897
|
+
|
|
14779
14898
|
// src/commands/branch.ts
|
|
14780
14899
|
var branch = async (options) => {
|
|
14781
14900
|
let originalBranch = "";
|
|
@@ -14786,7 +14905,13 @@ var branch = async (options) => {
|
|
|
14786
14905
|
if (!options.branch || !options.message || !options.owner) {
|
|
14787
14906
|
throw new Error("Missing required options for branch creation");
|
|
14788
14907
|
}
|
|
14789
|
-
|
|
14908
|
+
if ((options.pr || options.draftPr) && !options.push) {
|
|
14909
|
+
throw new Error("Pull request creation requires --push option");
|
|
14910
|
+
}
|
|
14911
|
+
if (options.pr && options.draftPr) {
|
|
14912
|
+
throw new Error("Cannot use both --pr and --draft-pr options");
|
|
14913
|
+
}
|
|
14914
|
+
log.info(options.append ? "Starting branch update process..." : "Starting branch creation process...");
|
|
14790
14915
|
originalBranch = await getCurrentBranch();
|
|
14791
14916
|
log.info(`Currently on branch: ${originalBranch}`);
|
|
14792
14917
|
filesToCommit = await getOwnerFiles(options.owner, options.isDefaultOwner || false);
|
|
@@ -14797,13 +14922,19 @@ var branch = async (options) => {
|
|
|
14797
14922
|
log.file(`Files to be committed:
|
|
14798
14923
|
${filesToCommit.join(`
|
|
14799
14924
|
`)}`);
|
|
14800
|
-
|
|
14801
|
-
|
|
14925
|
+
const branchAlreadyExists = await branchExists(options.branch);
|
|
14926
|
+
if (branchAlreadyExists && !options.append) {
|
|
14927
|
+
throw new Error(`Branch "${options.branch}" already exists. Use --append to add commits to it, or use a different name.`);
|
|
14802
14928
|
}
|
|
14803
14929
|
try {
|
|
14804
|
-
|
|
14805
|
-
|
|
14806
|
-
|
|
14930
|
+
if (branchAlreadyExists && options.append) {
|
|
14931
|
+
log.info(`Checking out existing branch "${options.branch}"...`);
|
|
14932
|
+
await checkout(options.branch);
|
|
14933
|
+
} else {
|
|
14934
|
+
log.info(`Creating new branch "${options.branch}"...`);
|
|
14935
|
+
await createBranch(options.branch);
|
|
14936
|
+
newBranchCreated = true;
|
|
14937
|
+
}
|
|
14807
14938
|
log.info(`Committing changes with message: "${options.message}" ${!options.verify ? "(no-verify)" : ""}...`);
|
|
14808
14939
|
await commitChanges(filesToCommit, {
|
|
14809
14940
|
message: options.message ?? "",
|
|
@@ -14817,9 +14948,28 @@ var branch = async (options) => {
|
|
|
14817
14948
|
noVerify: !options.verify
|
|
14818
14949
|
});
|
|
14819
14950
|
}
|
|
14951
|
+
if ((options.pr || options.draftPr) && options.push) {
|
|
14952
|
+
try {
|
|
14953
|
+
const defaultBranch = await getDefaultBranch();
|
|
14954
|
+
const prResult = await createPRWithTemplate(options.message, options.branch, {
|
|
14955
|
+
draft: options.draftPr,
|
|
14956
|
+
base: defaultBranch
|
|
14957
|
+
});
|
|
14958
|
+
if (prResult) {
|
|
14959
|
+
log.success(`${options.draftPr ? "Draft " : ""}Pull request #${prResult.number} created: ${prResult.url}`);
|
|
14960
|
+
}
|
|
14961
|
+
} catch (prError) {
|
|
14962
|
+
log.error(`Failed to create pull request: ${prError}`);
|
|
14963
|
+
log.info("Branch was successfully created and pushed, but PR creation failed");
|
|
14964
|
+
}
|
|
14965
|
+
}
|
|
14820
14966
|
log.info(`Checking out original branch "${originalBranch}"...`);
|
|
14821
14967
|
await checkout(originalBranch);
|
|
14822
|
-
|
|
14968
|
+
if (branchAlreadyExists && options.append) {
|
|
14969
|
+
log.success(options.push ? `Changes committed to existing branch "${options.branch}" and pushed to remote.` : `Changes committed to existing branch "${options.branch}".`);
|
|
14970
|
+
} else {
|
|
14971
|
+
log.success(options.push ? `Branch "${options.branch}" created, changes committed, and pushed to remote.` : `Branch "${options.branch}" created and changes committed.`);
|
|
14972
|
+
}
|
|
14823
14973
|
} catch (operationError) {
|
|
14824
14974
|
log.error(`Operation failed: ${operationError}`);
|
|
14825
14975
|
if (newBranchCreated) {
|
|
@@ -14866,7 +15016,13 @@ var multiBranch = async (options) => {
|
|
|
14866
15016
|
if (options.ignore && options.include) {
|
|
14867
15017
|
throw new Error("Cannot use both --ignore and --include options at the same time");
|
|
14868
15018
|
}
|
|
14869
|
-
|
|
15019
|
+
if ((options.pr || options.draftPr) && !options.push) {
|
|
15020
|
+
throw new Error("Pull request creation requires --push option");
|
|
15021
|
+
}
|
|
15022
|
+
if (options.pr && options.draftPr) {
|
|
15023
|
+
throw new Error("Cannot use both --pr and --draft-pr options");
|
|
15024
|
+
}
|
|
15025
|
+
log.info(options.append ? "Starting multi-branch update process..." : "Starting multi-branch creation process...");
|
|
14870
15026
|
const changedFiles = await getChangedFiles();
|
|
14871
15027
|
if (changedFiles.length === 0) {
|
|
14872
15028
|
throw new Error("No changed files found in the repository");
|
|
@@ -14914,14 +15070,16 @@ var multiBranch = async (options) => {
|
|
|
14914
15070
|
}
|
|
14915
15071
|
const results = {
|
|
14916
15072
|
success: [],
|
|
14917
|
-
failure: []
|
|
15073
|
+
failure: [],
|
|
15074
|
+
prSuccess: [],
|
|
15075
|
+
prFailure: []
|
|
14918
15076
|
};
|
|
14919
15077
|
for (const owner of codeowners2) {
|
|
14920
15078
|
try {
|
|
14921
15079
|
const sanitizedOwner = owner.replace(/[^a-zA-Z0-9-_@]/g, "-").replace(/^@/, "");
|
|
14922
15080
|
const branchName = `${options.branch}/${sanitizedOwner}`;
|
|
14923
15081
|
const commitMessage = `${options.message} - ${owner}`;
|
|
14924
|
-
log.info(`Creating branch for ${owner}...`);
|
|
15082
|
+
log.info(options.append ? `Updating branch for ${owner}...` : `Creating branch for ${owner}...`);
|
|
14925
15083
|
await branch({
|
|
14926
15084
|
owner,
|
|
14927
15085
|
branch: branchName,
|
|
@@ -14932,29 +15090,42 @@ var multiBranch = async (options) => {
|
|
|
14932
15090
|
upstream: options.upstream,
|
|
14933
15091
|
force: options.force,
|
|
14934
15092
|
keepBranchOnFailure: options.keepBranchOnFailure,
|
|
14935
|
-
isDefaultOwner: owner === options.defaultOwner
|
|
15093
|
+
isDefaultOwner: owner === options.defaultOwner,
|
|
15094
|
+
append: options.append,
|
|
15095
|
+
pr: options.pr,
|
|
15096
|
+
draftPr: options.draftPr
|
|
14936
15097
|
});
|
|
14937
15098
|
results.success.push(owner);
|
|
15099
|
+
if ((options.pr || options.draftPr) && options.push) {
|
|
15100
|
+
results.prSuccess.push(owner);
|
|
15101
|
+
}
|
|
14938
15102
|
} catch (error) {
|
|
14939
|
-
log.error(`Failed to create branch for ${owner}: ${error}`);
|
|
15103
|
+
log.error(`Failed to ${options.append ? "update" : "create"} branch for ${owner}: ${error}`);
|
|
14940
15104
|
results.failure.push(owner);
|
|
14941
15105
|
}
|
|
14942
15106
|
}
|
|
14943
|
-
log.header("Multi-branch creation summary");
|
|
14944
|
-
log.info(`Successfully created branches for ${results.success.length} of ${codeowners2.length} codeowners`);
|
|
15107
|
+
log.header(options.append ? "Multi-branch update summary" : "Multi-branch creation summary");
|
|
15108
|
+
log.info(options.append ? `Successfully updated branches for ${results.success.length} of ${codeowners2.length} codeowners` : `Successfully created branches for ${results.success.length} of ${codeowners2.length} codeowners`);
|
|
14945
15109
|
if (results.success.length) {
|
|
14946
15110
|
log.success(`Successful: ${results.success.join(", ")}`);
|
|
14947
15111
|
}
|
|
14948
15112
|
if (results.failure.length) {
|
|
14949
15113
|
log.error(`Failed: ${results.failure.join(", ")}`);
|
|
14950
15114
|
}
|
|
15115
|
+
if (options.pr || options.draftPr) {
|
|
15116
|
+
log.header(`${options.draftPr ? "Draft " : ""}Pull request creation summary`);
|
|
15117
|
+
log.info(`Successfully created ${options.draftPr ? "draft " : ""}pull requests for ${results.prSuccess.length} of ${results.success.length} successful branches`);
|
|
15118
|
+
if (results.prSuccess.length) {
|
|
15119
|
+
log.success(`${options.draftPr ? "Draft " : ""}PRs created for: ${results.prSuccess.join(", ")}`);
|
|
15120
|
+
}
|
|
15121
|
+
}
|
|
14951
15122
|
} catch (err) {
|
|
14952
15123
|
log.error(`Multi-branch operation failed: ${err}`);
|
|
14953
15124
|
process.exit(1);
|
|
14954
15125
|
}
|
|
14955
15126
|
};
|
|
14956
15127
|
// package.json
|
|
14957
|
-
var version = "1.
|
|
15128
|
+
var version = "1.6.0";
|
|
14958
15129
|
|
|
14959
15130
|
// src/commands/version.ts
|
|
14960
15131
|
function getVersion() {
|
|
@@ -14963,8 +15134,8 @@ function getVersion() {
|
|
|
14963
15134
|
|
|
14964
15135
|
// src/cli.ts
|
|
14965
15136
|
var program2 = new Command;
|
|
14966
|
-
program2.name("codeowners").description("CLI tool for grouping and managing staged files by CODEOWNERS").version(getVersion());
|
|
15137
|
+
program2.name("codeowners-git (cg)").description("CLI tool for grouping and managing staged files by CODEOWNERS").version(getVersion());
|
|
14967
15138
|
program2.command("list").description("Lists all git changed files by CODEOWNER").option("-o, --owner <owner>", "Filter by specific code owner").option("-i, --include <patterns>", "Filter by owner patterns").action(listCodeowners);
|
|
14968
|
-
program2.command("branch").description("Create new branch with codeowner changes").requiredOption("-o, --owner <owner>", "Code owner name").requiredOption("-b, --branch <branch>", "Branch name").requiredOption("-m, --message <message>", "Commit message").option("-n, --no-verify", "Skip lint-staged or any other ci checks").option("-p, --push", "Push branch to remote after commit").option("-r, --remote <remote>", "Remote name to push to", "origin").option("-u, --upstream <upstream>", "Upstream branch name (defaults to local branch name)").option("-f, --force", "Force push to remote").option("-k, --keep-branch-on-failure", "Keep the created branch even if operation fails").action(branch);
|
|
14969
|
-
program2.command("multi-branch").description("Create branches for all codeowners").requiredOption("-b, --branch <branch>", "Base branch name (will be suffixed with codeowner name)").requiredOption("-m, --message <message>", "Base commit message (will be suffixed with codeowner name)").option("-n, --no-verify", "Skip lint-staged or any other ci checks").option("-p, --push", "Push branches to remote after commit").option("-r, --remote <remote>", "Remote name to push to", "origin").option("-u, --upstream <upstream>", "Upstream branch name pattern (defaults to local branch name)").option("-f, --force", "Force push to remote").option("-k, --keep-branch-on-failure", "Keep created branches even if operation fails").option("-d, --default-owner <defaultOwner>", "Default owner to use when no codeowners are found for changed files").option("--ignore <patterns>", "Comma-separated patterns to exclude codeowners (e.g., 'team-a,team-b')").option("--include <patterns>", "Comma-separated patterns to include codeowners (e.g., 'team-*,@org/*')").action(multiBranch);
|
|
15139
|
+
program2.command("branch").description("Create new branch with codeowner changes").requiredOption("-o, --owner <owner>", "Code owner name").requiredOption("-b, --branch <branch>", "Branch name").requiredOption("-m, --message <message>", "Commit message").option("-n, --no-verify", "Skip lint-staged or any other ci checks").option("-p, --push", "Push branch to remote after commit").option("-r, --remote <remote>", "Remote name to push to", "origin").option("-u, --upstream <upstream>", "Upstream branch name (defaults to local branch name)").option("-f, --force", "Force push to remote").option("-k, --keep-branch-on-failure", "Keep the created branch even if operation fails").option("--append", "Add commits to existing branch instead of creating a new one").option("--pr", "Create a pull request after pushing (requires --push)").option("--draft-pr", "Create a draft pull request after pushing (requires --push)").action(branch);
|
|
15140
|
+
program2.command("multi-branch").description("Create branches for all codeowners").requiredOption("-b, --branch <branch>", "Base branch name (will be suffixed with codeowner name)").requiredOption("-m, --message <message>", "Base commit message (will be suffixed with codeowner name)").option("-n, --no-verify", "Skip lint-staged or any other ci checks").option("-p, --push", "Push branches to remote after commit").option("-r, --remote <remote>", "Remote name to push to", "origin").option("-u, --upstream <upstream>", "Upstream branch name pattern (defaults to local branch name)").option("-f, --force", "Force push to remote").option("-k, --keep-branch-on-failure", "Keep created branches even if operation fails").option("-d, --default-owner <defaultOwner>", "Default owner to use when no codeowners are found for changed files").option("--ignore <patterns>", "Comma-separated patterns to exclude codeowners (e.g., 'team-a,team-b')").option("--include <patterns>", "Comma-separated patterns to include codeowners (e.g., 'team-*,@org/*')").option("--append", "Add commits to existing branches instead of creating new ones").option("--pr", "Create pull requests after pushing (requires --push)").option("--draft-pr", "Create draft pull requests after pushing (requires --push)").action(multiBranch);
|
|
14970
15141
|
program2.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeowners-git",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"module": "src/cli.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -32,13 +32,19 @@
|
|
|
32
32
|
"build": "bun build src/cli.ts --compile --outfile bin/codeowners-git",
|
|
33
33
|
"build:dist": "bun build src/cli.ts --outdir dist/ --target node",
|
|
34
34
|
"test": "bun test --watch",
|
|
35
|
-
"test:
|
|
35
|
+
"test:unit": "bun test src/**",
|
|
36
|
+
"test:e2e": "bun test test/e2e",
|
|
37
|
+
"test:e2e:local": "TEST_REPO_URL=../cg-test bun test test/e2e",
|
|
38
|
+
"test:all": "bun run test:unit && bun run test:e2e",
|
|
39
|
+
"test:ci": "bun run test:all",
|
|
40
|
+
"type-check": "bun tsc",
|
|
36
41
|
"format": "biome format --write ./src",
|
|
37
42
|
"lint": "biome lint ./src",
|
|
38
|
-
"prepublish": "bun run build:dist && bun test"
|
|
43
|
+
"prepublish": "bun run build:dist && bun run test:all"
|
|
39
44
|
},
|
|
40
45
|
"bin": {
|
|
41
|
-
"codeowners-git": "dist/cli.js"
|
|
46
|
+
"codeowners-git": "dist/cli.js",
|
|
47
|
+
"cg": "dist/cli.js"
|
|
42
48
|
},
|
|
43
49
|
"devDependencies": {
|
|
44
50
|
"@changesets/cli": "^2.27.12",
|