In this article we will setup OpenShift-TektonCD-Triggers (Tekton Triggers) for the CICD Pipeline from the previous article.

Quick Overview of Tekton Triggers

Triggers enable us to hook our CICD Pipelines to respond to external events (push events, pull requests etc). It consists of 3 main components (CRDs):

  1. EventListener
  2. TriggerTemplate
  3. TriggerBinding


This is the public facing part of Tekton Triggers. An EventListener sets up a Kubernetes Service which can be exposed as an OpenShift Route (or K8s Ingress). The route URL can be used to configure webhooks in your GitHub repositories (or in any event source). In addition, an EventListener connects TriggerTemplates to TriggerBindings. (Read more)


A TriggerTemplate defines a Template for how a Pipeline should be run in reaction to events. We can define templates for PipelineResources (git, image) and PipelineRuns (based on an existing Pipeline) as a TriggerTemplate. When a event is received by our EventListener, the TriggerTemplate is rendered by extracting parameter values (eg: git repository url, revision etc.) from the event payload. This will result in the creation of new PipelineResources and the starting of a new PipelineRun. (Read more)


In simple words, TriggerBinding specifies the mapping (binding) between event payloads received by the EventListener and parameters specified in a TriggerTemplate. For example, a PipelineResource template in a TriggerTemplate might require a git repository url. We specify the mapping between the right key in the event (eg: body.repository.url) and the parameter in TriggerTemplate by creating a TriggerBinding. (Read more)


  • A publicly accessible OpenShift 4.x cluster. We should be able to expose a publicly accessible route. If you are using a local cluster (eg: CRC) you won’t be able to test Triggers with push events to a external git repository like Github. (OpenShift on AWS or any OpenShift 4.x Cluster which has a public URL)
  • Install OpenShift Pipelines (part 1: How to Install OpenShift-Pipelines on OpenShift 4.x)
  • Install Tetkon CLI ‘tkn’ on your local machine:


Initial Setup

We will be using the same CICD Pipeline from the previous article.

Fork and clone it to your local machine.

$ git clone<you-github-username>/vote-cicd.git

Checkout branch part-3-cicd-pipeline-triggers

$ cd vote-cicdvote-cicd$ git checkout part-3-cicd-pipeline-triggersBranch 'part-3-cicd-pipeline-triggers' set up to track remote branch 'part-3-cicd-pipeline-triggers' from 'origin'.
Switched to a new branch 'part-3-cicd-pipeline-triggers'

At this point we should have the following directory structure.

├── + 02-pipelineresources
├── 03-tasks
│ └── 01-oc-apply-deployment-task.yaml
├── 04-pipelines
│ └── 01-build-deploy-pipeline.yaml
├── + 05-pipelineruns
├── 06-pipeline-triggers
│ ├── 01-triggers-rbac.yaml
│ ├── 02-vote-cicd-triggertemplate.yaml
│ ├── 03_trigger-binding.yaml
│ ├── 04-event-listener.yaml
│ └── 05-eventlistener-route.yaml
├── 07-github-webhooks
│ ├── 01_create-webhook-user.yaml
│ ├── 02_webhook-secret.yaml
│ ├── 03_create-webhook-task.yaml
│ ├── 04.1_create-api-repo-webhook-run.yaml
│ └── 04.2_create-uii-repo-webhook-run.yaml

As we are going to create a TriggerTemplate which defines templates for PipelineResources and PipelineRuns, we don’t have to create PipelineResurces and PipelineRuns manually. Directories 02-pipelineresources and 05-pipelineruns are given as a reference.

Setup the Pipeline

We need to setup the CICD Pipeline which will be referenced by PipelineRuns triggered in reaction to events received by the Event-Listener.

The pipeline we will be using is build-and-deploy. We can see the definition in 04-pipelines/01-build-deploy-pipeline.yaml.

kind: Pipeline
name: build-and-deploy
- name: build-image
name: buildah-v0-8-0
kind: ClusterTask
- name: create-upate-deployment
name: oc-apply-deployment

The build-and-deploy pipeline uses 2 Tasks, buildah-v0–8–0 ClusterTask and oc-apply-deployment Task. The ClusterTask buildah-v0–8–0 is a default Task supplied by OpenShift-Pipelines-Operator. It should be already present on your cluster as we have installed OpenShift-Pipelines using OpenShift-Pipeline-Operator.

$ oc get clustertask buildah-v0-8-0NAME             AGE
buildah-v0-8-0 6h39m

The other task oc-apply-deployment is a custom Task defined in 03-tasks/ 01-oc-apply-deployment-task.yaml.

First let’s create a new project for our CICD Pipeline and Triggers.

$ oc new-project vote-cicdNow using project "vote-cicd" on server ...

Let’s create the custom Task,

vote-cicd$ oc apply -f 03-tasks/ created

and the Pipeline.

vote-cicd$ c apply -f 04-pipelines/ created

If we switch to Developer Perspective on OpenShift WebConsole (using Top-Left drop down), we should see build-and-deploy Pipeline in vote-cicd project.

Adding Triggers to our Voting Application CICD

Now let’s add a TriggerTemplate, TriggerBinding, and an EventListener to our project.


The definition of our TriggerTemplate is given in vote-cicd/06-pipeline-triggers/02-vote-cicd-triggertemplate.yaml. We can see the key parts of our TriggerTemplate below. In short, it specifies templates for:

  1. PipelineResource — type: git
  2. PipelineResource — type: image
  3. PipelineRun — pipelineRef: build-and-deploy
kind: TriggerTemplate
name: vote-cicd-triggertemplate
- apiVersion:
kind: PipelineResource
- apiVersion:
kind: PipelineResource
name: image-source-$(params.gitrepositoryname)-$(uid)
namespace: $(params.namespace)
type: image
- apiVersion:
kind: PipelineRun
name: vote-cicd-$(params.gitrepositoryname)-$(uid)
namespace: $(params.namespace)
name: build-and-deploy


A TriggerBinding is a map from event payload data to parameters specified in a TriggerTemplate. The TriggerBinding for our TriggerTemplate can be found in vote-cicd/06-pipeline-triggers/03_trigger-binding.yaml.

kind: TriggerBinding
name: vote-cicd-pipelinebinding
- name: gitrevision
value: $(
- name: namespace
value: vote-cicd
- name: gitrepositoryurl
value: $(body.repository.url)
- name: gitrepositoryname
value: $(

The exact paths (keys) of parameter we need can be found by examining the event payload (eg: GitHub events).

Note:- The parameter namespace is hardcoded. It can be also parameterized. It can also be dropped from your TriggerTemplates and let Triggers use current Namespace.


This component sets up a Service and listens for events. It also connects a TriggerTemplate (what to run) to a TriggerBinding (what to extract from events). The definition for our EventListener can be found in vote-cicd/06-pipeline-triggers/04-event-listener.yaml.

kind: EventListener
name: votecicd-listener
serviceAccountName: tekton-triggers-sa
- binding:
name: vote-cicd-pipelinebinding
name: vote-cicd-triggertemplate

Note:- EventListener will setup a Service. We need to expose that Service as an OpenShift Route to make it publicly accessible. Refer: vote-cicd/06-pipeline-triggers/05-eventlistener-route.yaml.

Note:- At present RBAC needed by Triggers to manage Trigger Resources is not handled by the operator. Hence, we need to create them using vote-cicd/06-pipeline-triggers/01-triggers-rbac.yaml.

Let’s Create Trigger Resources.

vote-cicd$ oc apply -f created
serviceaccount/tekton-triggers-sa created created created created created created

Configuring GitHub WebHooks

Now let’s use the Triggers we have setup. We need to configure webhooks on frontend and backend source code repositories with the Route we exposed in the previous step.

Note:- Fork the backend and frontend source code repositories so that you have sufficient privileges to configure GitHub webhooks.

We can either configure the webhooks manually from GitHub web ui or automate the process using the create-webhook Task defined in vote-cicd/07-github-webhooks/03_create-webhook-task.yaml.

Create GitHub Access Token

Running the create-webhook Task needs your GitHub token to configure webhooks on your GitHub repositories. Create your GitHub access token with the following access: (refer: creating a personal access token)

  • public_repo
  • admin:repo_hook

Once you have created the token, add it to the Secret webhook-secret vote-cicd/07-github-webhooks/02_webhook-secret.yaml.

apiVersion: v1
kind: Secret
name: webhook-secret
token: # add your github token here
secret: random-string-data

Configuring Webhooks for vote-api and vote-ui

We need to create 2 TaskRuns (with TaskRef: create-webhook Task). One for vote-api repository and one for vote-ui repository. The TaskRuns are defined in vote-cicd2/07-github-webhooks. Make sure you edit the 2 TaskRuns with the following information with respect to your setup.

  1. GitHubOrg: your GitHub username (or your GitHub org name, depending on where your cloned vote-api and vote-ui
  2. GitHubUser: your GitHub username
  3. GitHubRepo: vote-api in one TaskRun and vote-ui in the other.
  4. ExternalDomain: The url of the Route we created it the above section — Adding Triggers to our Voting Application CICD. Run `oc get route vote-cicd-eventlistener` find the host URL for the route.

Example: vote-cicd/07-github-webhooks/04.1_create-api-repo-webhook-run.yaml

kind: TaskRun
name: create-api-repo-webhook-run
name: create-webhook
- name: GitHubOrg
value: "<your user name or or org name>"
- name: GitHubUser
value: "<your user name>"
- name: GitHubRepo
value: "vote-api"
- name: GitHubSecretName
value: webhook-secret
- name: GitHubAccessTokenKey
value: token
- name: GitHubSecretStringKey
value: secret
- name: ExternalDomain
value: <route url from previous section>
timeout: 1000s
serviceAccount: tekton-triggers-createwebhook

Once we have filled in the GitHub token in the webhook-secret manifest and the details in 2 TaskRuns (frontend and backend), run:

vote-cicd$ oc apply -f created
serviceaccount/tekton-triggers-createwebhook created created
secret/webhook-secret created created created created

Ensure that the 2 TaskRuns are completed successfully.

vote-cicd$ tkn taskrun lsNAME                          STARTED         DURATION     STATUS      
create-api-repo-webhook-run 2 minutes ago 26 seconds Succeeded
create-ui-repo-webhook-run 2 minutes ago 26 seconds Succeeded

Now we should see a webhook configured in your fork of frontend and backend source code repositories (on our GitHub Repo, go to Settings>Webhooks).

Let’s Trigger a PipelineRun

We have setup our Pipeline, Trigger and Webhooks. Suppose a push event or a pull request occur in the backend repo (vote-api) the following should happen.

  1. The configured webhook in vote-api GitHub repository should push the event to our route (exposed EventListener Service).
  2. The Event-Listner will pass the event to the TriggerBinding and TriggerTemplate pair.
  3. TriggerBinding will extract parameters needed for rendering the TriggerTemplate.
  4. Successful rendering of TriggerTemplate should create 2 PipelineResources (api-git and api-image) and a PipelineRun (build-and-deploy-vote-api)

We can test this by pushing a commit to vote-api repository from GitHub web ui or from terminal.

Let’s push an empty commit to vote-api repository.

vote-api$ git commit -m "empty-commit" --allow-empty && git push origin master...
Writing objects: 100% (1/1), 190 bytes | 190.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
89a12e1..784d1c3 master -> master

Watch OpenShift WebConsole Developer perspective and a PipelineRun will be automatically created.

Note:- make sure that the Complete and Running filters are seelcted

Let’s trigger a PipelineRun for vote-ui as well.

vote-ui$ git commit -m "empty-commit" --allow-empty && git push origin master...
Writing objects: 100% (1/1), 188 bytes | 188.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
1073d7c..bc27f5f master -> master

Let’s Vote

When both the PipelineRuns succeed the backend and frontend Deployments, Services and frontend Service will be created (or updated on reruns).

vote-cicd$ oc get DeploymentNAME                   READY   UP-TO-DATE   AVAILABLE   AGE
el-votecicd-listener 1/1 1 1 121m
vote-api 1/1 1 1 5m6s
vote-ui 1/1 1 1 3m25s
vote-cicd$ oc get serviceNAME TYPE AGE
el-votecicd-listener ClusterIP 122m
vote-api ClusterIP 6m25s
vote-ui NodePort 4m44s
vote-cicd$ oc get routeNAME HOST/PORT
(Note:- output is edited to reducenoise)

go to the Host URL of vote-ui Route:

Note:- PipelineResources, PipelineRuns and Logs

PipelineResources and PipelineRuns

Each time the the TriggerTemplate is rendered as a result of an event in a source code Repository, the PipelineResources and PipelineRuns for that source code repository is re-created with a randomized name.

vote-cicd$ tkn resources lssource-repo-vote-api-qtpnk    git     url:
source-repo-vote-ui-jkd9n git url:
image-source-vote-api-qtpnk image url: image-registry.openshift-image-registry.svc:5000/vote-cicd/vote-api:latest
image-source-vote-ui-jkd9n image url: image-registry.openshift-image-registry.svc:5000/vote-cicd/vote-ui:latest

vote-cicd$ tkn pipelineruns ls
vote-cicd-vote-ui-jkd9n 21 minutes ago 1 minute Succeeded
vote-cicd-vote-api-qtpnk 24 minutes ago 2 minutes Succeeded


We can view the logs either from OpensShift WebConsole Developer Perspective or from CLI (tkn pipelinerun logs command).


End-to-end CICD workflow with OpenShift Pipelines

  1. Write your CICD Pipeline
  2. Setup Triggers (TriggerTemplate, TriggerBinding, EventListener)
  3. Configure Webhooks
  4. Write code and push commits

Other Articles in this series


  1. TektonCD Triggers Getting Started
  2. What’s New in OpenShift 4.2 — Tekton Pipelines with GitHub Webhooks
  3. Triggers: Event Based Workflows for Tekton Pipelines and More! — Dibyo Mukherjee, Google

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store