Skip to content

Commit 7fef52e

Browse files
feat(github-actions): add auto labeling by path to github labeler action
This adds the ability to add additional labels automatically if a specific path is matched in the pull request commits.
1 parent e126086 commit 7fef52e

File tree

13 files changed

+17012
-3834
lines changed

13 files changed

+17012
-3834
lines changed

.github/local-actions/branch-manager/main.js

Lines changed: 7 additions & 1 deletion
Large diffs are not rendered by default.

.github/local-actions/labels-sync/main.js

Lines changed: 7 additions & 1 deletion
Large diffs are not rendered by default.

github-actions/branch-manager/main.js

Lines changed: 7 additions & 1 deletion
Large diffs are not rendered by default.

github-actions/pull-request-labeling/BUILD.bazel

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ ts_project(
1313
":node_modules/@actions/core",
1414
":node_modules/@actions/github",
1515
":node_modules/@octokit/rest",
16+
":node_modules/@types/micromatch",
1617
":node_modules/@types/node",
18+
":node_modules/micromatch",
1719
":node_modules/undici",
1820
"//github-actions:utils",
1921
"//ng-dev/commit-message",
2022
"//ng-dev/pr/common/labels",
23+
"//ng-dev/pr/config",
24+
"//ng-dev/utils",
2125
],
2226
)
2327

@@ -27,6 +31,9 @@ esbuild_checked_in(
2731
":lib",
2832
],
2933
entry_point = "lib/main.ts",
34+
external = [
35+
"pnpapi",
36+
],
3037
format = "esm",
3138
platform = "node",
3239
target = "node22",

github-actions/pull-request-labeling/lib/main.ts

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ import {context} from '@actions/github';
33
import {Octokit, RestEndpointMethodTypes} from '@octokit/rest';
44
import {Commit, parseCommitMessage} from '../../../ng-dev/commit-message/parse.js';
55
import {actionLabels, managedLabels, targetLabels} from '../../../ng-dev/pr/common/labels/index.js';
6+
import {assertValidPullRequestConfig, PullRequestConfig} from '../../../ng-dev/pr/config/index.js';
67
import {ANGULAR_ROBOT, getAuthTokenFor, revokeActiveInstallationToken} from '../../utils.js';
78
import {ManagedRepositories} from '../../../ng-dev/pr/common/labels/base.js';
9+
import {getConfig, NgDevConfig} from '../../../ng-dev/utils/config.js';
10+
import micromatch from 'micromatch';
811

912
/** The type of the response data for a the pull request get method on from octokit. */
1013
type PullRequestGetData = RestEndpointMethodTypes['pulls']['get']['response']['data'];
@@ -17,7 +20,8 @@ class PullRequestLabeling {
1720
const token = await getAuthTokenFor(ANGULAR_ROBOT);
1821
const git = new Octokit({auth: token});
1922
try {
20-
const inst = new this(git);
23+
const config = await getConfig([assertValidPullRequestConfig]);
24+
const inst = new this(git, config);
2125
await inst.run();
2226
} finally {
2327
await revokeActiveInstallationToken(git);
@@ -32,8 +36,13 @@ class PullRequestLabeling {
3236
commits: Commit[] = [];
3337
/** The pull request information from the github API. */
3438
pullRequestMetadata?: PullRequestGetData;
39+
/** The files changed in the pull request */
40+
pullRequestFilePaths?: string[];
3541

36-
private constructor(private git: Octokit) {}
42+
private constructor(
43+
private git: Octokit,
44+
private config: NgDevConfig<{pullRequest: PullRequestConfig}>,
45+
) {}
3746

3847
/** Run the action, and revoke the installation token on completion. */
3948
async run() {
@@ -43,6 +52,7 @@ class PullRequestLabeling {
4352

4453
await this.commitMessageBasedLabeling();
4554
await this.pullRequestMetadataLabeling();
55+
await this.pathBasedLabeling();
4656
}
4757

4858
/**
@@ -107,6 +117,26 @@ class PullRequestLabeling {
107117
}
108118
}
109119

120+
/**
121+
* Perform labeling based on the paths of the files in the pull request.
122+
*/
123+
async pathBasedLabeling() {
124+
const managedLabelByPath = this.config.pullRequest.managedLabelByPath;
125+
if (
126+
managedLabelByPath === undefined ||
127+
this.pullRequestFilePaths === undefined ||
128+
Object.keys(managedLabelByPath).length === 0
129+
) {
130+
return;
131+
}
132+
133+
for (const [label, paths] of Object.entries(managedLabelByPath)) {
134+
if (paths.length > 0 && micromatch.any(this.pullRequestFilePaths, paths)) {
135+
await this.addLabel(label);
136+
}
137+
}
138+
}
139+
110140
/** Remove the provided label to the pull request. */
111141
async removeLabel(label: string) {
112142
const {number: issue_number, owner, repo} = context.issue;
@@ -159,6 +189,13 @@ class PullRequestLabeling {
159189
await this.git.pulls.get({owner, repo, pull_number: number}).then(({data}) => {
160190
this.pullRequestMetadata = data;
161191
});
192+
193+
if (this.config.pullRequest.managedLabelByPath) {
194+
this.pullRequestFilePaths = [];
195+
await this.git
196+
.paginate(this.git.pulls.listFiles, {owner, pull_number: number, repo})
197+
.then((files) => this.pullRequestFilePaths?.push(...files.map((file) => file.filename)));
198+
}
162199
}
163200
}
164201

0 commit comments

Comments
 (0)