Transform GitLab webhook events into CDEvents.
This transformer converts GitLab webhook events (pipelines, jobs, merge requests, issues, releases, etc.) into standardized CDEvents following the CDEvents specification.
The transformer uses VRL (Vector Remap Language) to detect event types from webhook payloads and map them to appropriate CDEvents.
Event type detection is performed in VRL based on the object_kind field or X-Gitlab-Event header:
| GitLab Event | CDEvent Type | Detection Logic |
|---|---|---|
| pipeline:created/pending | pipelineRun.queued | object_kind=pipeline AND status in [created, waiting_for_resource, preparing, pending] |
| pipeline:running | pipelineRun.started | object_kind=pipeline AND status=running |
| pipeline:success/failed | pipelineRun.finished | object_kind=pipeline AND status in [success, failed, canceled, skipped] |
| build:created/pending | taskRun.queued | object_kind=build AND build_status in [created, pending] |
| build:running | taskRun.started | object_kind=build AND build_status=running |
| build:success/failed | taskRun.finished | object_kind=build AND build_status in [success, failed, canceled] |
| release:created | artifact.published | object_kind=release |
| tag_push | artifact.published | object_kind=tag_push AND tag created |
| issue:open/reopen | ticket.created | object_kind=issue AND action in [open, reopen] |
| issue:close | ticket.closed | object_kind=issue AND action=close |
| issue:update | ticket.updated | object_kind=issue AND other actions |
| merge_request:open/reopen | change.created | object_kind=merge_request AND action in [open, reopen] |
| merge_request:merge | change.merged | object_kind=merge_request AND action=merge |
| merge_request:close | change.abandoned | object_kind=merge_request AND action=close (not merged) |
| merge_request:approved | change.reviewed | object_kind=merge_request AND action=approved |
| merge_request:update | change.updated | object_kind=merge_request AND other actions |
| push (branch) | branch.created/deleted | object_kind=push AND ref starts with refs/heads/ |
For artifact.published events, artifactId is generated as a PURL:
- Release:
pkg:generic/<project_path>@<tag_name>?repository_url=<encoded_url> - Tag Push:
pkg:generic/<project_path>@<tag_name>?repository_url=<encoded_url>
inputs/examplesare copied/extracted from GitLab documentation.inputs/capturereal captured payload (+ obfuscation)
To capture authentic GitLab webhook payloads for testing:
- Visit webhook.site
- Copy your unique URL (e.g.,
https://webhook.site/abc123-def456-...) - Keep the browser tab open to monitor incoming webhooks
- Go to your GitLab project
- Navigate to Settings > Webhooks
- Or visit:
https://gitlab.com/<namespace>/<project>/-/hooks
Add webhook configuration:
URL: https://webhook.site/YOUR-UNIQUE-ID (for testing) or https://your-cdviz-collector.example.com/webhook/000-gitlab (for production)
Secret token: changeme (optional, for webhook authentication)
Trigger events: Select the events you want to capture:
- ✅ Push events
- ✅ Tag push events
- ✅ Issues events
- ✅ Merge request events
- ✅ Pipeline events
- ✅ Job events
- ✅ Release events
SSL verification: Enable (recommended for production)
Click Test next to the webhook to send test events, or trigger real events by:
# Trigger a pipeline
git push origin main
# Create a tag
git tag v1.0.0
git push origin v1.0.0
# Create an issue
# (via GitLab UI)
# Create a merge request
git checkout -b feature-branch
git commit --allow-empty -m "Test commit"
git push origin feature-branch
# (then create MR via GitLab UI)- Go to your webhook.site browser tab
- Click on each webhook request to view the full payload
- Copy the JSON body
- Save to
inputs/capture/<event_type>/<verb>.json
Example file naming:
inputs/capture/pipeline/created.json- Pipeline queuedinputs/capture/pipeline/running.json- Pipeline startedinputs/capture/pipeline/success.json- Pipeline completed successfullyinputs/capture/pipeline/failed.json- Pipeline failedinputs/capture/job/running.json- Job startedinputs/capture/job/success.json- Job completedinputs/capture/issue/open.json- Issue createdinputs/capture/issue/close.json- Issue closedinputs/capture/merge_request/open.json- MR createdinputs/capture/merge_request/merge.json- MR mergedinputs/capture/release/created.json- Release publishedinputs/capture/tag_push/created.json- Tag pushedinputs/capture/push/branch_created.json- Branch createdinputs/capture/push/branch_deleted.json- Branch deleted
# Check transformation against expected outputs (validates CDEvents)
mise run '//gitlab_events:test'
# Generate/overwrite expected outputs (after adding new inputs)
cd transformers/gitlab_events
../../target/debug/cdviz-collector transform \
--mode overwrite \
--directory . \
--config ./cdviz-collector.toml \
-t gitlab_events \
--input ./inputs \
--output ./outputsConfigure collector to accept GitLab webhooks:
# In your main cdviz-collector.toml
[sources.gitlab_webhook]
enabled = true
transformer_refs = ["gitlab_events"]
[sources.gitlab_webhook.extractor]
type = "webhook"
id = "000-gitlab"
headers_to_keep = ["X-Gitlab-Event"]
[sources.gitlab_webhook.extractor.headers]
# Optional: Verify webhook authenticity with token
"x-gitlab-token" = { type = "secret", value = "token-changeme" }Start the server:
cdviz-collector connectSend test events:
# Using curl with a captured webhook
curl -X POST http://localhost:8080/webhook/000-gitlab \
-H "Content-Type: application/json" \
-H "X-Gitlab-Token: token-changeme" \
-d @transformers/gitlab_events/inputs/pipeline/success.jsonThe transformer is configured via cdviz-collector.toml:
[transformers.gitlab_events]
type = "vrl"
template_file = "./transformer.vrl"Webhook source configuration (in main cdviz-collector.toml):
[sources.gitlab_webhook]
enabled = true
transformer_refs = ["gitlab_events"]
[sources.gitlab_webhook.extractor]
type = "webhook"
id = "000-gitlab"
headers_to_keep = ["X-Gitlab-Event"]
[sources.gitlab_webhook.extractor.headers]
# Optional: Verify webhook authenticity with token
"x-gitlab-token" = { type = "secret", value = "token-changeme" }Key transformation rules:
- Event detection: VRL logic determines event type from
object_kindfield orX-Gitlab-Eventheader - context.id: Auto-generated by collector (set to "0")
- context.source:
/gitlab(consistent with other transformers) - subject.id: Web URL of the entity (pipeline, job, issue, MR, etc.) or PURL for artifacts
- subject.source: Project web URL
- customData.gitlab: Preserves GitLab-specific details (project, user, event-specific metadata)
-
Verify webhook is enabled in GitLab project settings:
Settings > Webhooks -
Check webhook delivery logs in GitLab:
Settings > Webhooks > Edit > Recent Deliveries -
Verify cdviz-collector is running and accessible:
curl http://localhost:8080/healthz
-
Check cdviz-collector logs for webhook processing errors
If webhook.site shows errors or malformed JSON:
- Verify GitLab webhook configuration includes correct Content-Type header
- Check GitLab version compatibility (tested with GitLab 15.0+)
- Review Recent Deliveries in GitLab for error messages
If using X-Gitlab-Token authentication:
- Ensure token in cdviz-collector.toml matches GitLab webhook secret token
- Verify header name is exactly
x-gitlab-token(case-insensitive) - Check collector logs for authentication errors
- GitLab Webhook Events Documentation
- GitLab Webhooks Guide
- CDEvents Specification
- webhook.site - Free webhook testing tool
- VRL Documentation
Centralized Logic: Event type detection in VRL keeps transformation logic in one place, making it easier to maintain and test. GitLab provides clear event type indicators in the webhook payload (object_kind field), making VRL-based detection straightforward.
Benefits:
- Single source of truth for event mapping
- Easier to add new event types
- Testable transformation logic
- Version-controlled event detection rules
Flexible Artifact Identification: GitLab releases can contain various artifact types (container images, packages, binaries). Using pkg:generic allows representing any release artifact with a consistent PURL format.
Alternative: For specific artifact types (container images, npm packages, etc.), the transformer can be extended to generate type-specific PURLs based on release asset information.
Supported Events: The transformer covers the most common GitLab CI/CD and development workflow events:
- ✅ Pipeline lifecycle (queued, started, finished)
- ✅ Job lifecycle (queued, started, finished)
- ✅ Issues (created, updated, closed)
- ✅ Merge requests (created, updated, merged, abandoned, reviewed)
- ✅ Releases and tags (artifact published)
- ✅ Branch operations (created, deleted)
Not Yet Supported:
- Deployment events →
service.deployed - Wiki page events
- Comment events
- Confidential issues/MRs
- System hooks
These can be added as needed following the existing event mapping pattern.