From 0c144904ff4bd849f10e70e38c73b929048b8e28 Mon Sep 17 00:00:00 2001 From: Damien Degois Date: Mon, 6 Jan 2025 19:53:41 +0100 Subject: [PATCH] feat: add filter on participant Signed-off-by: Damien Degois --- README.md | 2 ++ app.py | 14 +++++++++++++- webhook/merge_request.py | 16 +++++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 510421e..6f261fb 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,8 @@ On your GitLab repository, follow these steps to add a new webhook: 4. Fill out the form with the following details: * **URL**: https://hostname-of-this-api.example.org/api/v1/gitlab-webhook + * Since v0.12.0, you can specify a filter to publish notifications only if certain users are involved as the opener, reviewers, or assignees. \ + Use query parameters `filter_on_participant_ids` with a comma-separated list of user IDs (integers). * **Add custom header**: * name: `X-Conversation-Token` * value: comma separated list of conversation tokens you want the MR messages sent to diff --git a/app.py b/app.py index fe40fa4..13f8fee 100755 --- a/app.py +++ b/app.py @@ -92,6 +92,7 @@ async def handle_webhook( payload: MergeRequestPayload | PipelinePayload | EmojiPayload, x_conversation_token: Annotated[str, Header()], x_gitlab_token: Annotated[str, Header()], + filter_on_participant_ids: str | None = None, ): validate_gitlab_token(x_gitlab_token) conversation_tokens = list( @@ -100,9 +101,20 @@ async def handle_webhook( [validate_uuid(ct.strip()) for ct in x_conversation_token.split(",")], ) ) + try: if isinstance(payload, MergeRequestPayload): - await webhook.merge_request(payload, conversation_tokens) + participant_ids_filter: list[int] = [] + if filter_on_participant_ids: + try: + participant_ids_filter = [int(entry) for entry in filter_on_participant_ids.split(",")] + except ValueError: + raise HTTPException( + status_code=400, + detail="filter_on_participant_ids must be a list of comma separated integers", + ) + + await webhook.merge_request(payload, conversation_tokens, participant_ids_filter) if isinstance(payload, PipelinePayload): await webhook.pipeline(payload, conversation_tokens) if isinstance(payload, EmojiPayload): diff --git a/webhook/merge_request.py b/webhook/merge_request.py index e903c06..1ed4bff 100644 --- a/webhook/merge_request.py +++ b/webhook/merge_request.py @@ -134,6 +134,7 @@ async def create_or_update_message( async def merge_request( mr: MergeRequestPayload, conversation_tokens: list[str], + participant_ids_filter: list[int], ): mri = await dbh.get_merge_request_ref_infos(mr) convtoken_to_msgrefs = await get_or_create_message_refs( @@ -141,6 +142,18 @@ async def merge_request( conversation_tokens, ) + participant_found = True + if participant_ids_filter: + participant_found = False + participant_found |= mri.merge_request_extra_state.opener.id in participant_ids_filter + participant_found |= any( + [ + user.id in participant_ids_filter + for userlist in (mri.merge_request_payload.assignees, mri.merge_request_payload.reviewers) + for user in userlist + ] + ) + connection: asyncpg.Connection if mr.object_attributes.action in ("update"): @@ -196,7 +209,8 @@ async def merge_request( "merged", ) or mr.object_attributes.draft - or mr.object_attributes.work_in_progress, + or mr.object_attributes.work_in_progress + or not participant_found, ) if mr.object_attributes.action in ("merge", "close") or mr.object_attributes.state in (