Skip to content

Commit 2a43eed

Browse files
authored
Merge pull request #160 from streamdevs/152-gitlab-mr-merged-to-route
feat: 'MergeRequestOpened' and 'MergeRequestMerged'
2 parents eae00cb + 7d41815 commit 2a43eed

File tree

4 files changed

+116
-3
lines changed

4 files changed

+116
-3
lines changed

src/reactions/gitlab/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { TwitchChat } from '../../services/TwitchChat';
2+
import { StreamLabs } from '../../services/StreamLabs';
3+
import { MergeRequestMerged } from './merge-request-merged';
4+
import { MergeRequestPayload } from '../../schemas/gitlab/merge-request-payload';
5+
import { MergeRequestOpened } from './merge-request-opened';
6+
import { Reaction } from '../github/reaction';
7+
8+
export const buildGitLabReactions = (
9+
twitchChat: TwitchChat,
10+
streamlabs: StreamLabs,
11+
): Reaction<MergeRequestPayload>[] => {
12+
return [
13+
new MergeRequestMerged(twitchChat, streamlabs),
14+
new MergeRequestOpened(twitchChat, streamlabs),
15+
];
16+
};

src/routes/gitlab/index.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { ServerRoute, ResponseObject, Request, ResponseToolkit } from '@hapi/hapi';
22
import { gitlabHeader } from '../../schemas/gitlab/joi/gitlab-headers-schema';
3+
import { buildGitLabReactions } from '../../reactions/gitlab';
4+
import { TwitchChat } from '../../services/TwitchChat';
5+
import { Config } from '../../config';
6+
import { StreamLabs } from '../../services/StreamLabs';
7+
import { MergeRequestPayload } from '../../schemas/gitlab/merge-request-payload';
38

4-
export const routes = (): ServerRoute[] => {
9+
export const routes = (config: Config): ServerRoute[] => {
510
return [
611
{
712
method: 'POST',
@@ -11,9 +16,31 @@ export const routes = (): ServerRoute[] => {
1116
},
1217
},
1318
handler: async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
14-
const { headers } = request;
19+
const { headers, payload } = (request as unknown) as {
20+
headers: { 'x-gitlab-event': string };
21+
payload: MergeRequestPayload;
22+
};
1523
const event = headers['x-gitlab-event'];
1624

25+
const twitchChat = new TwitchChat({
26+
botName: config?.TWITCH_BOT_NAME || '',
27+
botToken: config?.TWITCH_BOT_TOKEN || '',
28+
channel: config?.TWITCH_BOT_CHANNEL || '',
29+
});
30+
const streamlabs = new StreamLabs({ token: config?.STREAMLABS_TOKEN || '' });
31+
32+
const reactions = buildGitLabReactions(twitchChat, streamlabs).filter((reaction) =>
33+
reaction.canHandle({ event, payload, config }),
34+
);
35+
36+
if (reactions.length > 0) {
37+
const messages = await Promise.all(
38+
reactions.map((reaction) => reaction.handle({ payload })),
39+
);
40+
41+
return h.response({ messages }).code(200);
42+
}
43+
1744
return h.response({ message: `Ignoring event: '${event}'` }).code(200);
1845
},
1946
path: '/gitlab',

src/routes/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ import { routes as github } from './github';
44
import { Config } from '../config';
55

66
export const routes = (config: Config): ServerRoute[] => {
7-
return [...github(config), ...gitlab()];
7+
return [...github(config), ...gitlab(config)];
88
};
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { getConfig } from '../../../src/config';
2+
import { initServer } from '../../../src/server';
3+
import { StreamLabs } from '../../../src/services/StreamLabs';
4+
import { TwitchChat } from '../../../src/services/TwitchChat';
5+
import { MergeRequestPayloadBuilder } from '../../builders/payload/gitlab/merge-request-payload-builder';
6+
7+
describe('POST /gitlab', () => {
8+
let streamLabsSpy: jest.SpyInstance<Promise<void>>;
9+
let twitchChatSpy: jest.SpyInstance<Promise<void>>;
10+
11+
beforeEach(() => {
12+
streamLabsSpy = jest.spyOn(StreamLabs.prototype, 'alert');
13+
streamLabsSpy.mockImplementationOnce(jest.fn());
14+
15+
twitchChatSpy = jest.spyOn(TwitchChat.prototype, 'send');
16+
twitchChatSpy.mockImplementationOnce(jest.fn());
17+
});
18+
19+
describe('Merge Request Hook', () => {
20+
it('handles merge request merged event', async () => {
21+
const subject = await initServer(getConfig());
22+
const payload = new MergeRequestPayloadBuilder()
23+
.with({ object_attributes: { state: 'merged' } })
24+
.getInstance();
25+
26+
const { result } = await subject.inject({
27+
method: 'POST',
28+
url: '/gitlab',
29+
payload,
30+
headers: { 'x-gitlab-event': 'Merge Request Hook' },
31+
});
32+
33+
expect(result).toEqual(
34+
expect.objectContaining({
35+
messages: [
36+
expect.objectContaining({
37+
twitchChat: expect.anything(),
38+
streamlabs: expect.anything(),
39+
}),
40+
],
41+
}),
42+
);
43+
});
44+
45+
it('handles merge request opened event', async () => {
46+
const subject = await initServer(getConfig());
47+
const payload = new MergeRequestPayloadBuilder()
48+
.with({ object_attributes: { state: 'opened' } })
49+
.getInstance();
50+
51+
const { result } = await subject.inject({
52+
method: 'POST',
53+
url: '/gitlab',
54+
payload,
55+
headers: { 'x-gitlab-event': 'Merge Request Hook' },
56+
});
57+
58+
expect(result).toEqual(
59+
expect.objectContaining({
60+
messages: [
61+
expect.objectContaining({
62+
twitchChat: expect.anything(),
63+
streamlabs: expect.anything(),
64+
}),
65+
],
66+
}),
67+
);
68+
});
69+
});
70+
});

0 commit comments

Comments
 (0)