GitLab’s webhook system, when integrated with Tekton Triggers, doesn’t just react to events; it orchestrates an entire CI/CD pipeline based on the nuanced state of your code repository.

Let’s see this in action. Imagine a simple GitLab Merge Request event. When a developer pushes a new branch and opens a Merge Request targeting main, a GitLab webhook fires. This webhook, configured to point to a Tekton TriggerTemplate and TriggerBinding, contains a payload of information about the MR. The TriggerBinding then extracts key details like the MR title, author, and source/target branches. This extracted data is then used to populate parameters within the TriggerTemplate. The TriggerTemplate, in turn, uses these parameters to instantiate a Tekton PipelineRun. This PipelineRun then kicks off a specific Tekton Pipeline, which might include tasks for linting, testing, building, and deploying your application, all triggered by that single GitLab event.

Here’s a simplified PipelineRun that might be instantiated:

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: gitlab-mr-pipeline-run-$(params.git-branch)-$(context.pipelineRun.uid | truncate 6)
spec:
  pipelineRef:
    name: gitlab-ci-pipeline # This is the Tekton Pipeline defined elsewhere
  params:
    - name: git-url
      value: $(params.gitlab-hook.repository.url)
    - name: git-branch
      value: $(params.gitlab-hook.object_attributes.source_branch)
    - name: git-commit
      value: $(params.gitlab-hook.object_attributes.last_commit.id)
    - name: mr-iid
      value: $(params.gitlab-hook.object_attributes.iid)
    - name: mr-title
      value: $(params.gitlab-hook.object_attributes.title)
  workspaces:
    - name: shared-data
      persistentVolumeClaim:
        claimName: shared-pvc # A PVC for sharing data between tasks

The problem this solves is the disconnect between code changes and automated workflows. Traditionally, you’d have separate CI systems polling repositories or relying on manual triggers. GitLab Triggers with Tekton allow for a real-time, event-driven approach where the act of pushing code or opening an MR directly initiates a complex, pre-defined sequence of actions.

Internally, Tekton Triggers acts as the bridge. You define TriggerTemplates that specify what resources (like PipelineRuns) to create, TriggerBindings to extract data from incoming webhook payloads, and EventListeners that listen for these webhooks. When a GitLab webhook hits your EventListener, it consults the associated TriggerBinding to pick out the relevant bits of data from the JSON payload. This data is then passed as parameters to the TriggerTemplate, which generates the PipelineRun with those parameters embedded. The PipelineRun then tells Tekton to execute the specified Pipeline using the provided code and parameters.

The EventListener can be exposed via a Kubernetes Service of type LoadBalancer or NodePort, or even managed by an Ingress controller. GitLab’s webhook configuration then simply points to the URL of this EventListener. The secretToken configured in both GitLab and the Tekton EventListener provides a crucial layer of security, ensuring that only authenticated requests from your GitLab instance can trigger pipelines.

The magic of parameterization is where the real power lies. You can configure your Tekton Pipeline to be generic, accepting parameters for branch names, commit SHAs, or even specific deployment targets. The GitLab webhook payload is rich with this information. For instance, $(params.gitlab-hook.repository.url) pulls the repository URL directly from the GitLab payload, while $(params.gitlab-hook.object_attributes.source_branch) gets the name of the branch associated with the event. This allows a single Tekton Pipeline to handle diverse scenarios – building from feature branches, testing merge requests, or deploying tagged releases – all driven by the specific details of the GitLab event.

A common point of confusion is how to handle different event types. GitLab sends distinct payloads for push events, merge request events, tag events, etc. Your Tekton TriggerBinding needs to be written to anticipate the structure of the payload for the specific event type you want to trigger on. For example, a TriggerBinding for a merge request event will look for keys like object_attributes.state or object_attributes.source_branch, whereas a push event binding might focus on ref and checkout_sha.

The EventListener itself can be configured with multiple Triggers, each with its own TriggerTemplate and TriggerBinding. This allows a single EventListener endpoint to serve different pipeline workflows based on the event type or even specific attributes within the GitLab payload, often using a matchExpressions field within the Trigger definition to filter events.

When you’re debugging webhook issues, remember that the GitLab webhook secret is not just for security; it’s also a piece of data that Tekton uses to verify the request’s origin. If that token doesn’t match between GitLab and your EventListener, the request will be silently dropped, and your pipelines won’t run.

The next step after setting up basic event triggers is often handling pipeline failures and retries, or integrating with external systems based on event outcomes.

Want structured learning?

Take the full Tekton course →