diff --git a/src/entry/webtriggers/process-gitlab-event.test.ts b/src/entry/webtriggers/process-gitlab-event.test.ts
index 4effbf5..258a6a7 100644
--- a/src/entry/webtriggers/process-gitlab-event.test.ts
+++ b/src/entry/webtriggers/process-gitlab-event.test.ts
@@ -87,6 +87,17 @@ describe('processGitlabEvent', () => {
expect(serverResponse).toHaveBeenCalledWith('Invalid event format', 400);
});
+ it('returns server response error in case of unexpected error', async () => {
+ const webtriggerRequest = generateWebtriggerRequest('
Invalid body
');
+
+ storage.getSecret.mockRejectedValue(new Error());
+
+ await processGitlabEvent(webtriggerRequest, MOCK_CONTEXT);
+
+ expect(mockHandlePushEvent).not.toHaveBeenCalled();
+ expect(serverResponse).toHaveBeenCalledWith('The webhook could not be processed', 500);
+ });
+
it('handles pipeline event when FF is enabled', async () => {
const webtriggerRequest = generateWebtriggerRequest(JSON.stringify(MOCK_PIPELINE_EVENT));
diff --git a/src/entry/webtriggers/process-gitlab-event.ts b/src/entry/webtriggers/process-gitlab-event.ts
index 6e2d6ec..c874a12 100644
--- a/src/entry/webtriggers/process-gitlab-event.ts
+++ b/src/entry/webtriggers/process-gitlab-event.ts
@@ -19,59 +19,71 @@ import {
handlePipelineEvent,
} from './gitlab-event-handlers';
import { listFeatures } from '../../services/feature-flags';
+import { ParseWebhookEventPayloadError, ValidateWebhookSignatureError } from '../../models/errors';
type Context = {
principal: undefined;
installContext: string;
};
-class ValidateWebhookSignatureError extends Error {}
-
const validateWebhookSignature = (eventSignature: string, controlSignature: string): void | never => {
if (eventSignature !== controlSignature) {
throw new ValidateWebhookSignatureError();
}
};
-export const processGitlabEvent = async (event: WebtriggerRequest, context: Context): Promise => {
- const { installContext } = context;
- const cloudId = parse(installContext).resourceId;
- const groupId = event.queryParameters.groupId[0];
- const groupToken = await storage.getSecret(`${STORAGE_SECRETS.GROUP_TOKEN_KEY_PREFIX}${groupId}`);
- const eventPayload = event.body;
- let parsedEvent: GitlabEvent;
+const parseEventPayload = (eventPayload: string): GitlabEvent | never => {
+ try {
+ return JSON.parse(eventPayload);
+ } catch {
+ throw new ParseWebhookEventPayloadError();
+ }
+};
+export const processGitlabEvent = async (event: WebtriggerRequest, context: Context): Promise => {
try {
+ const { installContext } = context;
+ const cloudId = parse(installContext).resourceId;
+ const groupId = event.queryParameters.groupId[0];
+ const groupToken = await storage.getSecret(`${STORAGE_SECRETS.GROUP_TOKEN_KEY_PREFIX}${groupId}`);
+ const eventPayload = event.body;
+
validateWebhookSignature(
event.headers['x-gitlab-token'][0],
await storage.get(`${STORAGE_KEYS.WEBHOOK_SIGNATURE_PREFIX}${groupId}`),
);
- parsedEvent = JSON.parse(eventPayload);
+
+ const parsedEvent = parseEventPayload(eventPayload);
+
+ if (parsedEvent.object_kind === 'push') {
+ await handlePushEvent(parsedEvent as PushEvent, groupToken, cloudId);
+ }
+
+ if (parsedEvent.object_kind === 'merge_request') {
+ await handleMergeRequestEvent(parsedEvent as MergeRequestEvent, groupToken, cloudId);
+ }
+
+ if (parsedEvent.object_kind === 'pipeline') {
+ await handlePipelineEvent(parsedEvent as PipelineEvent, groupToken, cloudId);
+ }
+
+ if (parsedEvent.object_kind === 'deployment') {
+ await handleDeploymentEvent(parsedEvent as DeploymentEvent, groupToken, cloudId);
+ }
+
+ return serverResponse('Processed webhook event');
} catch (error) {
if (error instanceof ValidateWebhookSignatureError) {
console.error({ message: 'Webhook event secret is invalid', error });
return serverResponse('Invalid webhook secret', 403);
}
- console.error({ message: 'Failed parsing webhook event', error });
- return serverResponse('Invalid event format', 400);
- }
-
- if (parsedEvent.object_kind === 'push') {
- await handlePushEvent(parsedEvent as PushEvent, groupToken, cloudId);
- }
-
- if (parsedEvent.object_kind === 'merge_request') {
- await handleMergeRequestEvent(parsedEvent as MergeRequestEvent, groupToken, cloudId);
- }
-
- if (parsedEvent.object_kind === 'pipeline') {
- await handlePipelineEvent(parsedEvent as PipelineEvent, groupToken, cloudId);
- }
+ if (error instanceof ParseWebhookEventPayloadError) {
+ console.error({ message: 'Failed parsing webhook event', error });
+ return serverResponse('Invalid event format', 400);
+ }
- if (parsedEvent.object_kind === 'deployment') {
- await handleDeploymentEvent(parsedEvent as DeploymentEvent, groupToken, cloudId);
+ console.error({ message: 'Unexpected error while processing webhook', error });
+ return serverResponse('The webhook could not be processed', 500);
}
-
- return serverResponse('Processed webhook event');
};
diff --git a/src/models/errors.ts b/src/models/errors.ts
index 5b415dc..1e3d95f 100644
--- a/src/models/errors.ts
+++ b/src/models/errors.ts
@@ -55,3 +55,7 @@ export class GitlabHttpMethodError extends Error {
this.statusText = statusText;
}
}
+
+export class ValidateWebhookSignatureError extends Error {}
+
+export class ParseWebhookEventPayloadError extends Error {}