main

Triggers Workflow

Tekton Triggers for event-driven pipeline execution via webhooks and automated CI/CD.

When to Use

  • Setting up GitHub/GitLab webhooks
  • Automating pipeline execution from events
  • Creating event listeners
  • Configuring trigger bindings and templates
  • Integrating with version control systems

Trigger Components

EventListener

Listens for incoming HTTP events (webhooks)

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: github-listener
spec:
  serviceAccountName: tekton-triggers-sa
  triggers:
    - name: github-push
      interceptors:
        - ref:
            name: "github"
          params:
            - name: "secretRef"
              value:
                secretName: github-secret
                secretKey: secretToken
            - name: "eventTypes"
              value: ["push"]
      bindings:
        - ref: github-push-binding
      template:
        ref: pipeline-template

TriggerBinding

Extracts data from event payload

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
  name: github-push-binding
spec:
  params:
    - name: gitrevision
      value: $(body.head_commit.id)
    - name: gitrepositoryurl
      value: $(body.repository.clone_url)
    - name: gitbranch
      value: $(body.ref)
    - name: gitauthor
      value: $(body.head_commit.author.username)
    - name: gitmessage
      value: $(body.head_commit.message)

TriggerTemplate

Creates PipelineRun or TaskRun from event

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
  name: pipeline-template
spec:
  params:
    - name: gitrevision
      description: Git commit SHA
    - name: gitrepositoryurl
      description: Repository URL
    - name: gitbranch
      description: Git branch ref
  resourcetemplates:
    - apiVersion: tekton.dev/v1
      kind: PipelineRun
      metadata:
        generateName: ci-pipeline-run-
      spec:
        pipelineRef:
          name: ci-pipeline
        params:
          - name: git-url
            value: $(tt.params.gitrepositoryurl)
          - name: git-revision
            value: $(tt.params.gitrevision)
        workspaces:
          - name: source-code
            volumeClaimTemplate:
              spec:
                accessModes:
                  - ReadWriteOnce
                resources:
                  requests:
                    storage: 1Gi

GitHub Integration

Complete GitHub Webhook Setup

1. Create Secret for Webhook Validation

apiVersion: v1
kind: Secret
metadata:
  name: github-secret
type: Opaque
stringData:
  secretToken: "your-webhook-secret-here"

2. Create ServiceAccount with RBAC

apiVersion: v1
kind: ServiceAccount
metadata:
  name: tekton-triggers-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: tekton-triggers-role
rules:
  - apiGroups: ["triggers.tekton.dev"]
    resources: ["eventlisteners", "triggerbindings", "triggertemplates"]
    verbs: ["get"]
  - apiGroups: ["tekton.dev"]
    resources: ["pipelineruns", "pipelineresources", "taskruns"]
    verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: tekton-triggers-binding
subjects:
  - kind: ServiceAccount
    name: tekton-triggers-sa
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: tekton-triggers-role

3. Create EventListener

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: github-listener
spec:
  serviceAccountName: tekton-triggers-sa
  triggers:
    - name: github-push
      interceptors:
        - ref:
            name: "github"
          params:
            - name: "secretRef"
              value:
                secretName: github-secret
                secretKey: secretToken
            - name: "eventTypes"
              value: ["push", "pull_request"]
      bindings:
        - ref: github-binding
      template:
        ref: pipeline-template

4. Expose EventListener

# Get event listener service
kubectl get svc el-github-listener

# Expose via Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: github-webhook
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - webhooks.example.com
      secretName: webhook-tls
  rules:
    - host: webhooks.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: el-github-listener
                port:
                  number: 8080

5. Configure GitHub Webhook

  • Go to GitHub repository Settings → Webhooks
  • Payload URL: https://webhooks.example.com
  • Content type: application/json
  • Secret: Same value as in github-secret
  • Events: Push, Pull Request
  • Active: ✓

GitHub TriggerBinding Examples

Push event:

spec:
  params:
    - name: gitrevision
      value: $(body.head_commit.id)
    - name: gitrepositoryurl
      value: $(body.repository.clone_url)
    - name: gitbranch
      value: $(extensions.branch_name)

Pull Request event:

spec:
  params:
    - name: pr-number
      value: $(body.pull_request.number)
    - name: pr-title
      value: $(body.pull_request.title)
    - name: pr-head-sha
      value: $(body.pull_request.head.sha)
    - name: pr-base-branch
      value: $(body.pull_request.base.ref)

GitLab Integration

GitLab EventListener

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: gitlab-listener
spec:
  serviceAccountName: tekton-triggers-sa
  triggers:
    - name: gitlab-push
      interceptors:
        - ref:
            name: "gitlab"
          params:
            - name: "secretRef"
              value:
                secretName: gitlab-secret
                secretKey: secretToken
            - name: "eventTypes"
              value: ["Push Hook", "Merge Request Hook"]
      bindings:
        - ref: gitlab-binding
      template:
        ref: pipeline-template

GitLab TriggerBinding

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
  name: gitlab-binding
spec:
  params:
    - name: gitrevision
      value: $(body.checkout_sha)
    - name: gitrepositoryurl
      value: $(body.project.git_http_url)
    - name: gitbranch
      value: $(body.ref)
    - name: project-name
      value: $(body.project.name)

Interceptors

CEL Interceptor (Custom Logic)

interceptors:
  - name: "filter-branch"
    ref:
      name: "cel"
    params:
      - name: "filter"
        value: "body.ref.startsWith('refs/heads/main')"
      - name: "overlays"
        value:
          - key: branch_name
            expression: "body.ref.split('/')[2]"

Webhook Interceptor (Custom Service)

interceptors:
  - name: "custom-logic"
    webhook:
      objectRef:
        apiVersion: v1
        kind: Service
        name: custom-interceptor
        namespace: default
      header:
        - name: X-Custom-Header
          value: "custom-value"

Advanced Patterns

Multiple Triggers in One EventListener

spec:
  triggers:
    - name: main-branch
      interceptors:
        - ref:
            name: "cel"
          params:
            - name: "filter"
              value: "body.ref == 'refs/heads/main'"
      bindings:
        - ref: prod-binding
      template:
        ref: prod-template

    - name: feature-branch
      interceptors:
        - ref:
            name: "cel"
          params:
            - name: "filter"
              value: "body.ref.startsWith('refs/heads/feature/')"
      bindings:
        - ref: dev-binding
      template:
        ref: dev-template

Conditional Pipeline Execution

# In TriggerTemplate
spec:
  resourcetemplates:
    - apiVersion: tekton.dev/v1
      kind: PipelineRun
      metadata:
        generateName: conditional-run-
      spec:
        pipelineRef:
          name: my-pipeline
        params:
          - name: deploy-to-prod
            value: $(tt.params.gitbranch == "refs/heads/main")

ClusterTriggerBinding (Cluster-Wide Reuse)

apiVersion: triggers.tekton.dev/v1beta1
kind: ClusterTriggerBinding
metadata:
  name: common-git-binding
spec:
  params:
    - name: gitrevision
      value: $(body.head_commit.id)
    - name: gitrepositoryurl
      value: $(body.repository.clone_url)

Testing Triggers

Test with curl

# Get EventListener URL
EL_URL=$(kubectl get eventlistener github-listener -o jsonpath='{.status.address.url}')

# Send test payload
curl -X POST $EL_URL \
  -H "Content-Type: application/json" \
  -H "X-GitHub-Event: push" \
  -H "X-Hub-Signature: sha1=..." \
  -d @test-payload.json

# Watch for pipelinerun creation
kubectl get pipelineruns -w

Test Payload Examples

GitHub push:

{
  "ref": "refs/heads/main",
  "head_commit": {
    "id": "abc123...",
    "message": "Test commit",
    "author": {
      "username": "testuser"
    }
  },
  "repository": {
    "clone_url": "https://github.com/org/repo.git",
    "name": "repo"
  }
}

Troubleshooting

EventListener Not Receiving Events

# Check EventListener pod
kubectl get pods -l eventlistener=github-listener

# Check logs
kubectl logs -l eventlistener=github-listener

# Check service
kubectl get svc el-github-listener

# Test connectivity
kubectl port-forward svc/el-github-listener 8080:8080
curl -X POST http://localhost:8080 -d '{}'

Webhook Validation Failing

# Check secret exists
kubectl get secret github-secret

# Verify secret value matches GitHub
kubectl get secret github-secret -o jsonpath='{.data.secretToken}' | base64 -d

# Check interceptor logs
kubectl logs -l eventlistener=github-listener | grep "validation failed"

PipelineRun Not Created

# Check EventListener logs
kubectl logs -l eventlistener=github-listener

# Check RBAC permissions
kubectl auth can-i create pipelineruns --as=system:serviceaccount:default:tekton-triggers-sa

# Check TriggerTemplate
kubectl get triggertemplate pipeline-template -o yaml

Wrong Parameters Extracted

# View received payload
kubectl logs -l eventlistener=github-listener | grep "event body"

# Test TriggerBinding
# Create test EventListener with logging
# Examine extracted parameters in logs

Best Practices

Security

  • Always validate webhooks with secrets
  • Use HTTPS for webhook endpoints
  • Limit webhook events to necessary types
  • Use dedicated ServiceAccount with minimal permissions
  • Never expose raw event data in logs

Reliability

  • Set resource limits on EventListener pods
  • Use horizontal pod autoscaling for high traffic
  • Implement retry logic in pipelines
  • Monitor EventListener availability
  • Use Ingress with TLS termination

Maintainability

  • Use ClusterTriggerBinding for common parameters
  • Keep TriggerBindings focused and reusable
  • Document expected event payload structure
  • Version your TriggerTemplates
  • Use CEL interceptors for complex filtering

Performance

  • Filter events early with interceptors
  • Avoid creating unnecessary PipelineRuns
  • Use volumeClaimTemplate for workspace isolation
  • Set appropriate timeouts
  • Clean up old PipelineRuns with pruner

Common Patterns

Multi-Repository Trigger

spec:
  triggers:
    - name: repo-a
      interceptors:
        - ref:
            name: "cel"
          params:
            - name: "filter"
              value: "body.repository.name == 'repo-a'"
      template:
        ref: repo-a-template

    - name: repo-b
      interceptors:
        - ref:
            name: "cel"
          params:
            - name: "filter"
              value: "body.repository.name == 'repo-b'"
      template:
        ref: repo-b-template

Branch-Based Pipeline Selection

spec:
  triggers:
    - name: main-branch
      interceptors:
        - ref:
            name: "cel"
          params:
            - name: "filter"
              value: "body.ref == 'refs/heads/main'"
      template:
        ref: production-pipeline-template

    - name: develop-branch
      interceptors:
        - ref:
            name: "cel"
          params:
            - name: "filter"
              value: "body.ref == 'refs/heads/develop'"
      template:
        ref: staging-pipeline-template