Skip to content

Add GitLab support#9

Draft
sondrebr wants to merge 4 commits into
boegel:mainfrom
sondrebr:add-gitlab-support
Draft

Add GitLab support#9
sondrebr wants to merge 4 commits into
boegel:mainfrom
sondrebr:add-gitlab-support

Conversation

@sondrebr
Copy link
Copy Markdown

Implements support for handling GitLab events.

The PyGHee class is configurable for GH vs. GL using the event_source parameter, which defaults to 'github'.
When it is configured to handle GitHub events it should function as before, meaning that this PR (hopefully) does not contain any breaking changes.

This implementation assumes that some intermediary, e.g. a custom Smee server, uses the webhook secret to sign the event and add an X-Gitlab-Signature header since GitLab does not yet support webhook signatures.

I'm open to making both major and minor changes if you have any suggestions. I personally think the if/elif/elses look a bit messy, especially in the constructor.

@sondrebr sondrebr marked this pull request as draft April 14, 2026 12:16
@sondrebr
Copy link
Copy Markdown
Author

Changing this to draft while waiting for GitLab to implement signed webhooks, which seems like might happen soon: https://gitlab.com/gitlab-org/gitlab/-/work_items/19367

Based on the issue description, the signature will be "an HMAC-SHA256 hex digest of {timestamp}.{webhook-uuid}.{payload}, prefixed with sha256=". I will likely update this PR sometime in the coming days to verify this kind of signature instead.

@sondrebr
Copy link
Copy Markdown
Author

This PR should now (hopefully) support the upcoming GitLab implementation. Meanwhile, I have created a Smee server fork for testing here that signs GL webhooks using the "secret" token.

To test the PR, one can use the Smee server fork and a Smee client, and create a webhook on some GL project with the Comments trigger and a secret token. The secret token must be stored in the environment variable GITLAB_WEBHOOK_SECRET_TOKEN. Below is a short script that provides a simple PyGHee implementation logging GL comments:

from pyghee.lib import PyGHee, create_app, GITLAB
from pyghee.utils import log
import waitress


class GLTest(PyGHee):
    def __init__(self):
        super().__init__(event_source=GITLAB)

    def handle_note_event(self, event_info, log_file=None):
        comment_body = event_info["raw_request_body"]["object_attributes"]["note"]
        log(f"Comment received: {comment_body}", log_file=log_file)


if __name__ == "__main__":
    app = create_app(GLTest)
    print("Starting GitLab test app, listening on port 3000")
    waitress.serve(app, listen="*:3000")

@sondrebr
Copy link
Copy Markdown
Author

They did a last-minute change to the backend MR before it was merged, such that the webhook follows the Standard Webhooks specification. This means that:

  • Signatures will use the format v1,<sign> with a base64-encoded HMAC-SHA256 digest
  • Signatures will be generated using {webhook-id}.{timestamp}.{payload}
  • The webhook uses standardized headers for signatures, webhook-<id|timestamp|signature>
    • webhook-id is also now set to be the same as the idempotency key
  • Signing tokens use the format whsec_<key> with a base64-encoded 32-byte key

I have updated the PR to reflect these changes, including a slight restructuring of verify_request(). A few things may still be discussed:

  • Standard Webhooks are rejected if PyGHee is configured for GH or if the request does not come from GL (based on a User-Agent header check). Is this the best approach, and which status codes should be used?
  • Should the verification parts of verify_request() be moved to verify_gh_signature() and verify_gl_signature() methods?
  • GITLAB_WEBHOOK_SECRET_TOKEN should maybe be renamed to GITLAB_WEBHOOK_SIGNING_TOKEN.

I have also updated my Smee server fork to make GL webhook events Standard Webhooks-compliant when they contain whsec_-prefixed tokens, by formatting the signature correctly and setting the webhook-<id|timestamp|signature> headers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant