Skip to content

Commit f2abe67

Browse files
authored
Add RequiredLabels handler (#268)
1 parent a2fb976 commit f2abe67

File tree

4 files changed

+109
-2
lines changed

4 files changed

+109
-2
lines changed

services/bots/src/github-webhook/github-webhook.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { MonthOfWTH } from './handlers/month_of_wth';
2323
import { NewIntegrationsHandler } from './handlers/new_integrations';
2424
import { PlatinumReview } from './handlers/platinum_review';
2525
import { QualityScaleLabeler } from './handlers/quality_scale';
26+
import { RequiredLabels } from './handlers/required_labels';
2627
import { ReviewDrafter } from './handlers/review_drafter';
2728
import { SetDocumentationSection } from './handlers/set_documentation_section';
2829
import { SetIntegration } from './handlers/set_integration';
@@ -48,6 +49,7 @@ import { ValidateCla } from './handlers/validate-cla';
4849
NewIntegrationsHandler,
4950
PlatinumReview,
5051
QualityScaleLabeler,
52+
RequiredLabels,
5153
ReviewDrafter,
5254
SetDocumentationSection,
5355
SetIntegration,
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { PullRequestLabeledEvent, PullRequestUnlabeledEvent } from '@octokit/webhooks-types';
2+
import { EventType, HomeAssistantRepository, Repository } from '../github-webhook.const';
3+
import { WebhookContext } from '../github-webhook.model';
4+
import { BaseWebhookHandler } from './base';
5+
6+
export const LabelsToCheck: {
7+
[key in Repository]?: string[];
8+
} = {
9+
[HomeAssistantRepository.CORE]: [
10+
'breaking-change',
11+
'bugfix',
12+
'code-quality',
13+
'dependency',
14+
'deprecation',
15+
'new-feature',
16+
'new-integration',
17+
],
18+
};
19+
20+
export class RequiredLabels extends BaseWebhookHandler {
21+
public allowedEventTypes = [
22+
EventType.PULL_REQUEST_LABELED,
23+
EventType.PULL_REQUEST_UNLABELED,
24+
EventType.PULL_REQUEST_SYNCHRONIZE,
25+
];
26+
public allowedRepositories = Object.keys(LabelsToCheck) as Repository[];
27+
28+
async handle(context: WebhookContext<PullRequestLabeledEvent | PullRequestUnlabeledEvent>) {
29+
const currentLabels = new Set(context.payload.pull_request.labels.map((label) => label.name));
30+
const requiredLabels = LabelsToCheck[context.repository];
31+
32+
const hasRequiredLabels = requiredLabels.some((label) => currentLabels.has(label));
33+
34+
await context.github.repos.createCommitStatus(
35+
context.repo({
36+
sha: context.payload.pull_request.head.sha,
37+
context: 'required-labels',
38+
state: hasRequiredLabels ? 'success' : 'failure',
39+
description: `Has at least one of the required labels (${requiredLabels.join(', ')})`,
40+
}),
41+
);
42+
}
43+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { WebhookContext } from '../../../../../services/bots/src/github-webhook/github-webhook.model';
2+
import {
3+
RequiredLabels,
4+
LabelsToCheck,
5+
} from '../../../../../services/bots/src/github-webhook/handlers/required_labels';
6+
import { loadJsonFixture } from '../../../../utils/fixture';
7+
import { mockWebhookContext } from '../../../../utils/test_context';
8+
import {
9+
ESPHomeRepository,
10+
EventType,
11+
HomeAssistantRepository,
12+
Repository,
13+
} from '../../../../../services/bots/src/github-webhook/github-webhook.const';
14+
15+
describe('RequiredLabels', () => {
16+
let handler: RequiredLabels;
17+
let mockContext: WebhookContext<any>;
18+
let createCommitStatusCall: any;
19+
20+
beforeEach(function () {
21+
handler = new RequiredLabels();
22+
createCommitStatusCall = {};
23+
mockContext = mockWebhookContext({
24+
payload: loadJsonFixture('pull_request.opened'),
25+
eventType: EventType.PULL_REQUEST_LABELED,
26+
// @ts-ignore partial mock
27+
github: {
28+
repos: {
29+
// @ts-ignore partial mock
30+
createCommitStatus: jest.fn(),
31+
},
32+
},
33+
});
34+
});
35+
36+
for (const [repository, lables] of Object.entries(LabelsToCheck)) {
37+
for (const result of ['success', 'failure']) {
38+
it(`Validate handling ${result} for ${repository} with ${lables}`, async () => {
39+
mockContext.payload = loadJsonFixture('pull_request.opened', {
40+
pull_request: { labels: result === 'success' ? [{ name: lables[0] }] : [] },
41+
});
42+
mockContext.repository = repository as Repository;
43+
await handler.handle(mockContext);
44+
45+
expect(mockContext.github.repos.createCommitStatus).toHaveBeenCalledWith(
46+
expect.objectContaining({
47+
context: 'required-labels',
48+
description: `Has at least one of the required labels (${lables.join(', ')})`,
49+
state: result,
50+
}),
51+
);
52+
});
53+
}
54+
}
55+
});

tests/services/bots/github-webhook/verify_enabled_handlers.spec.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,20 @@ describe('GithubWebhookModule', () => {
103103
},
104104
{
105105
eventType: EventType.PULL_REQUEST_SYNCHRONIZE,
106-
handlers: ['DocsMissing', 'MergeConflictChecker', 'PlatinumReview', 'ValidateCla'],
106+
handlers: [
107+
'DocsMissing',
108+
'MergeConflictChecker',
109+
'PlatinumReview',
110+
'RequiredLabels',
111+
'ValidateCla',
112+
],
107113
payload: {
108114
repository: { full_name: 'home-assistant/core', owner: { login: 'home-assistant' } },
109115
},
110116
},
111117
{
112118
eventType: EventType.PULL_REQUEST_UNLABELED,
113-
handlers: ['BlockingLabels', 'DocsMissing', 'PlatinumReview'],
119+
handlers: ['BlockingLabels', 'DocsMissing', 'RequiredLabels', 'PlatinumReview'],
114120
payload: {
115121
repository: { full_name: 'home-assistant/core', owner: { login: 'home-assistant' } },
116122
},
@@ -124,6 +130,7 @@ describe('GithubWebhookModule', () => {
124130
'NewIntegrationsHandler',
125131
'PlatinumReview',
126132
'QualityScaleLabeler',
133+
'RequiredLabels',
127134
'ValidateCla',
128135
],
129136
payload: {

0 commit comments

Comments
 (0)