Cloud Native 20 min read

Auto‑Trigger Tekton Pipelines with GitLab Webhooks: A Step‑by‑Step Guide

This article explains how to use Tekton Trigger to automatically start PipelineRuns from GitLab webhook events, covering the core components, CRD definitions, installation steps, and detailed configurations of TriggerTemplate, TriggerBinding, EventListener, ServiceAccount, Ingress, and secret management, enabling fully automated CI/CD on Kubernetes.

Ops Development Stories
Ops Development Stories
Ops Development Stories
Auto‑Trigger Tekton Pipelines with GitLab Webhooks: A Step‑by‑Step Guide

What Is Tekton Trigger?

Tekton Trigger is a Tekton component that detects events from various sources, extracts required information, and runs

TaskRun

and

PipelineRun

objects, passing the extracted data to satisfy different execution requirements.

The core components are:

EventListener – the external event entry point, usually exposed via HTTP for webhook integration.

Trigger – defines what happens when an EventListener detects an event; it references a TriggerBinding, TriggerTemplate, and optional Interceptor.

TriggerTemplate – templates resources; parameters received from the event are used to instantiate Tekton objects such as

TaskRun

or

PipelineRun

.

TriggerBinding – captures fields from the event and stores them as parameters for the TriggerTemplate.

ClusterTriggerBinding – similar to TriggerBinding but scoped at the cluster level.

Interceptor – runs before TriggerBinding to filter, validate, or transform the event payload.

Tekton Trigger workflow diagram
Tekton Trigger workflow diagram

Trigger CRD Objects

TriggerTemplate

TriggerTemplate modularizes Tekton resources, allowing parameters to be used anywhere in the resource template. Example:

<code>apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
  name: pipeline-template
spec:
  params:
  - name: gitrevision
    description: The git revision
    default: main
  - name: gitrepositoryurl
    description: The git repository url
  - name: message
    description: The message to print
    default: This is the default message
  - name: contenttype
    description: The Content-Type of the event
  resourcetemplates:
  - apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
      generateName: simple-pipeline-run-
    spec:
      pipelineRef:
        name: simple-pipeline
      params:
      - name: message
        value: $(tt.params.message)
      - name: contenttype
        value: $(tt.params.contenttype)
      resources:
      - name: git-source
        resourceSpec:
          type: git
          params:
          - name: revision
            value: $(tt.params.gitrevision)
          - name: url
            value: $(tt.params.gitrepositoryurl)</code>

The

resourcetemplates

field defines the actual Tekton object (here a

PipelineRun

) that will be created, and the

params

field lists the parameters extracted from the event.

TriggerBinding

TriggerBinding captures fields from the event and stores them as parameters:

<code>apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
  name: pipeline-binding
spec:
  params:
  - name: gitrevision
    value: $(body.head_commit.id)
  - name: gitrepositoryurl
    value: $(body.repository.url)
  - name: contenttype
    value: $(header.Content-Type)</code>

The values are extracted using

$(...)

JSONPath expressions.

Trigger

Defines the binding, template, and optional interceptors:

<code>apiVersion: triggers.tekton.dev/v1beta1
kind: Trigger
metadata:
  name: trigger
spec:
  interceptors:
  - ref:
      name: "cel"
    params:
    - name: "filter"
      value: "header.match('X-GitHub-Event', 'pull_request')"
    - name: "overlays"
      value:
      - key: extensions.truncated_sha
        expression: "body.pull_request.head.sha.truncate(7)"
  bindings:
  - ref: pipeline-binding
  template:
    ref: pipeline-template</code>

When the EventListener receives an event, the Trigger runs the interceptors first, then passes the data to the binding and template.

ClusterTriggerBinding

Works like TriggerBinding but is cluster‑scoped:

<code>apiVersion: triggers.tekton.dev/v1beta1
kind: ClusterTriggerBinding
metadata:
  name: pipeline-clusterbinding
spec:
  params:
  - name: gitrevision
    value: $(body.head_commit.id)
  - name: gitrepositoryurl
    value: $(body.repository.url)
  - name: contenttype
    value: $(header.Content-Type)</code>

Interceptor

Interceptors process the event before the binding. Tekton provides several built‑in interceptors, such as Webhook, Github, Gitlab, Bitbucket, and CEL. Example of a GitLab interceptor:

<code>interceptors:
- ref:
    name: "gitlab"
  params:
  - name: "secretRef"
    value:
      secretName: foo
      secretKey: bar
  - name: "eventTypes"
    value: ["Push Hook"]</code>

EventListener

EventListener is a Kubernetes object that listens on a port for HTTP events and forwards them to the defined triggers:

<code>apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
  name: gitlab-listener
spec:
  serviceAccountName: tekton-triggers-example-sa
  triggers:
  - name: foo-trig
    interceptors:
    - gitlab:
        secretRef:
          secretName: foo
          secretKey: bar
        eventTypes:
        - "Push Hook"
    bindings:
    - ref: pipeline-binding
    template:
      ref: pipeline-template</code>

Installing Tekton Trigger

Apply the official manifests (or a custom mirror if the network blocks the download):

<code>kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml</code>

After installation, the following pods should be running in the

tekton-pipelines

namespace:

<code># kubectl get po -n tekton-pipelines
NAME                                            READY   STATUS    RESTARTS   AGE
tekton-dashboard-565c78b68d-6fjdz               1/1     Running   12        32d
tekton-pipelines-controller-75c456df85-qxvq2   1/1     Running   5         32d
tekton-pipelines-webhook-5bc8d6b7c4-w6pdn       1/1     Running   5         32d
tekton-triggers-controller-686c6c8f79-fp7wd    1/1     Running   0         9m37s
tekton-triggers-core-interceptors-5d77595f79-8q9hb 1/1 Running   0         10s
tekton-triggers-webhook-76c55d6799-h997b       1/1     Running   0         9m36s</code>

Using Tekton Trigger for Automatic CI/CD

Define TriggerTemplate

The pipeline defined in the earlier "Tekton practice" article expects parameters such as

revision

,

git_url

,

imageUrl

,

imageTag

, and

namespace

. The TriggerTemplate passes these parameters to a

PipelineRun

:

<code>apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
  name: trigger-rd-pipeline-template
spec:
  params:
  - name: gitrevision
    description: The git revision
    default: master
  - name: gitrepositoryurl
    description: The git repository url
  - name: namespace
    description: The namespace to create the resources
    default: tekton-devops-pipeline
  - name: projectname
    description: The project name
  - name: imagetag
    description: The image tag
    default: latest
  resourcetemplates:
  - apiVersion: tekton.dev/v1alpha1
    kind: PipelineRun
    metadata:
      name: rd-pipeline-run-$(uid)
      namespace: $(tt.params.namespace)
    spec:
      serviceAccountName: tekton-build-sa
      params:
      - name: revision
        value: $(tt.params.gitrevision)
      - name: git_url
        value: $(tt.params.gitrepositoryurl)
      - name: imageUrl
        value: registry.cn-hangzhou.aliyuncs.com/coolops/$(tt.params.projectname)
      - name: imageTag
        value: $(tt.params.imagetag)
      - name: pathToDockerfile
        value: Dockerfile
      - name: chart_username
        value: xxx
      - name: chart_password
        value: xxx
      - name: app_name
        value: hello-world
      - name: sonar_url
        value: http://sonarqube.coolops.cn
      pipelineRef:
        name: rd-pipeline
      workspaces:
      - name: rd-repo-pvc
        volumeClaimTemplate:
          spec:
            accessModes:
            - ReadWriteOnce
            storageClassName: local
            resources:
              requests:
                storage: 1Gi
      - name: docker-config
        secret:
          secretName: docker-config
      - name: kubernetes-config
        secret:
          secretName: kubernetes-config</code>

Define TriggerBinding

Map fields from a GitLab push event to the parameters expected by the TriggerTemplate:

<code>apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
  name: trigger-rd-pipeline-bingding
  namespace: tekton-devops-pipeline
spec:
  params:
  - name: gitrevision
    value: $(body.ref)
  - name: namespace
    value: tekton-devops-pipeline
  - name: gitrepositoryurl
    value: $(body.project.git_http_url)
  - name: projectname
    value: $(body.project.name)</code>

Define EventListener

Connect the TriggerTemplate and TriggerBinding:

<code>apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: trigger-rd-pipeline-eventlistener
spec:
  serviceAccountName: tekton-triggers-gitlab-sa
  triggers:
  - bindings:
    - ref: trigger-rd-pipeline-bingding
    template:
      ref: trigger-rd-pipeline-template</code>

ServiceAccount and RBAC

Create a ServiceAccount with the minimal permissions required by the EventListener and bind it to a ClusterRole:

<code>apiVersion: v1
kind: ServiceAccount
metadata:
  name: tekton-triggers-gitlab-sa
secrets:
- name: gitlab-secret
- name: gitlab-auth
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: tekton-triggers-gitlab-minimal
rules:
- apiGroups: ["triggers.tekton.dev"]
  resources: ["eventlisteners","triggerbindings","triggertemplates","clustertriggerbindings","clusterinterceptors","triggers"]
  verbs: ["get","list","watch"]
- apiGroups: [""]
  resources: ["configmaps","secrets","serviceaccounts"]
  verbs: ["get","list","watch"]
- apiGroups: ["tekton.dev"]
  resources: ["pipelineruns","pipelineresources","taskruns"]
  verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tekton-triggers-gitlab-binding
subjects:
- kind: ServiceAccount
  name: tekton-triggers-gitlab-sa
  namespace: tekton-devops-pipeline
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: tekton-triggers-gitlab-minimal</code>

Create GitLab Secret Token

<code>apiVersion: v1
kind: Secret
metadata:
  name: gitlab-secret
type: Opaque
stringData:
  secretToken: "coolops"</code>

Expose EventListener via Ingress

<code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: el-trigger-test-eventlistener
spec:
  rules:
  - host: hello-word.webhook.coolops.cn
    http:
      paths:
      - backend:
          serviceName: el-trigger-rd-pipeline-eventlistener
          servicePort: 8080</code>
Ingress configuration
Ingress configuration

Create GitLab Webhook

Configure the webhook in GitLab to point to the Ingress URL and use the secret token defined above. After pushing code, GitLab sends a payload like the following:

<code>{
  "object_kind": "push",
  "event_name": "push",
  "ref": "refs/heads/master",
  "checkout_sha": "ac84d875c6094b5feebd477809a2021fd745c9df",
  "project": {
    "name": "Devops Hello World",
    "git_http_url": "http://192.168.205.128/root/devops-hello-world.git"
  },
  "commits": [
    {
      "id": "ac84d875c6094b5feebd477809a2021fd745c9df",
      "message": "ceshi ",
      "added": [],
      "modified": ["Jenkinsfile"],
      "removed": []
    }
  ]
}</code>

The TriggerBinding extracts

$(body.ref)

,

$(body.project.git_http_url)

, and

$(body.project.name)

from this payload, which are then passed to the TriggerTemplate to instantiate a

PipelineRun

. The pipeline runs automatically, as shown in the following screenshot:

Pipeline execution result
Pipeline execution result

With these resources in place, any code push to GitLab triggers a Tekton PipelineRun via the configured webhook, achieving fully automated continuous deployment on Kubernetes.

cloud-nativeci/cdkubernetesGitLabTektonTriggers
Ops Development Stories
Written by

Ops Development Stories

Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.