Tekton Triggers in practice

No Comments

This article is part of a series that deals with Tekton CI/CD and its practical use. In the first article we did the installation and created the first pipeline. In the second article we experienced the advantages of Tekton through the clever use of the reusable components.

This article is about embedding Tekton in a project context. The goal for this article is to first lay the groundwork for this. We will open a WebHook interface with Tekton Triggers and send a GitHub WebHook JSON object which starts a build in the Tekton installation.

Possible use

What do I mean by a “project context” at this point? So far we have been running Tekton in an isolated setup, which is not helpful in practice, since the developer experience suffers because of lost transparency of build states. The overall view is spread over at least two systems which are not linked to each other. Even worse, Tekton has to be started manually so far.

Why not just use the integrated?

The trend with the big platforms like GitHub or Gitlab is to integrate the development tools. Starting with the Git repository, to a pipeline solution like GitHub Actions, to the Container Repository, to the integration of the Organization Tools. The underlying reason for this is to increase transparency.

This is countered by the use of Tekton for the CI/CD execution aspect. This makes sense when the desire for compliance, reusability and supposed future viability increases. The directional vision is to spread API compatibility and build a broad eco-system. Of course, this is only the beginning of a journey and it remains to be seen if this is realistic. For decisions concerning the CI/CD system, future viability is an interesting criterion from my point of view.

Feel free to write your opinion in the comments or give feedback via Twitter.

Triggers installation

Tekton Triggers are another component that needs to be installed in the cluster. For this we can follow the installation instructions in the GitHub – Project to import the necessary manifests. In the chapter “Setting Up Tekton Triggers” you can find the two files which can be imported via the tool of choice.

The file named release.yaml contains the whole Triggers base installation and the interceptors.yaml file brings interceptors for easy connection to systems like gitlab, github or bitbucket. These should be installed as well, because we will use an installed ClusterInterceptor later on. In the next section I will describe what purpose these have.

At this point just the short hint that the Tekton – installation including the Tekton Triggers is ready built in my GitHub project. Just clone and test it. Everything important can be found in the README.md or in the github action which tests the code on every push.

Triggers API objects

The Triggers API looks very complicated at first glance, at least that’s how it looked to me. Best we go through step by step and understand what each object is used for. Here is my short Remarkable – note which helped me a lot in finding my direction:

EventListener

Our goal is to receive a WebHook from the outside. On the Kubernetes side, this means that a service provides a TCP port that can be used for this purpose. As an anchor, the EventListener is described and linked to the other objects. Besides the ServiceAccount to be used, the triggers are attached at this point. Behind an EventListener any number of triggers can listen to different requests.

By creating the EventListener, the described service is automatically created. Just briefly for classification: This service is only available in the cluster and, depending on the use case, can be made visible to other applications outside the cluster, for example, by means of an Ingress.

Trigger

The task of the trigger is based on assigning and processing the requests by using interceptors, TriggerBindings and TriggerTemplates. The trigger has a name and everything else is used in the objects used.

Interceptor

WebHooks are often called by specific systems. In the case of Tekton, these are Git repositories such as Gitlab or Github. The formats of the invocation and the security mechanisms used differ between the systems.

For example, a WebHook from Github is secured with an HMAC of the payload and a secret string whereas by Gitlab an X-Gitlab-Token HTTP header is added with a secret.

We can use the appropriate interceptor, define the necessary secret and event type.

TriggerBinding

With this binding we access the JSON body of the request and extract the necessary information such as the URL of the git repository and the branch name.

The extracted values are then usable as parameters and can be used in the last object.

TriggerTemplate

At this point, the actual call is now made, namely the extracted parameters are referenced here and made available to a template, e.g. a PipelineRun. The PipelineRun is started with a WebHook call.

Practical implementation in the sample project

Here the complete example from the demo project:

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: gitlab-listener
spec:
  serviceAccountName: tekton-triggers-gitlab-sa
  triggers:
    - name: gitlab-push-events-trigger
      interceptors:
        - name: "verify-gitlab-payload"
          ref:
            name: "gitlab"
            kind: ClusterInterceptor
          params:
            - name: secretRef
              value:
                secretName: "gitlab-secret"
                secretKey: "secretToken"
            - name: eventTypes
              value:
                - "Push Hook"
      bindings:
        - name: git-revision
          value: $(body.checkout_sha)
        - name: git-repository-url
          value: $(body.repository.git_http_url)
      template:
        spec:
          params:
            - name: git-revision
            - name: git-repository-url
          resourcetemplates:
            - apiVersion: tekton.dev/v1beta1
              kind: PipelineRun
              metadata:
                generateName: show-parameter-triggered-pipeline-
              spec:
                pipelineRef:
                  name: show-parameter-pipeline
                params:
                  - name: image
                    value: test-image-build-by-buildpack-and-triggered:latest
                  - name: git-repository-url
                    value: $(tt.params.git-repository-url)
                  - name: git-revision
                    value: $(tt.params.git-revision)

In the example, the call by a Gitlab instance is simulated by a curl. The call contains, as described for the interceptors, the necessary secret and the actual data of the call.

curl -v \
-H 'X-GitLab-Token: 1234567' \
-H 'X-Gitlab-Event: Push Hook' \
-H 'Content-Type: application/json' \
--data-binary "@gitlab-push-event.json" \
http://localhost:8081

In this short excerpt I would like to describe how a mapping to the call can take place, because on the one hand this call is a fire-and-forget solution, but on the other hand it can be necessary to trace the Tekton processing in the context of a debugging. This is possible because Tekton Triggers returns a JSON object which defines an event ID. This event ID is passed as a label to the PipelineRun which can then be identified by it. The following snippet shows this in practice and can be found in full here.

EVENT_ID=$(./trigger-tekton.sh | jq -r '.eventID')
          echo "EVENT-ID found in the response of the web-hook call${EVENT_ID}"
          # Wait for the triggered PipelineRun to complete
          kubectl -n tekton-pipelines wait --for=condition=SUCCEEDED=True --timeout=60s pipelineruns.tekton.dev -l triggers.tekton.dev/triggers-eventid==$EVENT_ID

Conclusion

This article shows with a practical example how Tekton can be integrated and used in an existing environment. At this point we have built a CI system that automatically starts pipelines when a push has occurred.

How does the series continue? As announced, a post will follow showing the integration with Gitlab in a practical way, based on an AWS EKS cluster. What comes after that is still open: It would be possible, for example, to develop a separate task and make it available or to turn in the direction of supply chain security.

If you have any questions or comments about the post, I would be happy to receive feedback from you here on the blog, by email or on Twitter.

Marco is passionate about developing software. He enjoys working in teams to solve complex problems.
In the past, he has successfully modernized legacy applications to prepare them for new challenges. Taking everyone along on this journey and getting them excited about new technologies – that’s a natural part of his job.

More content about Continuous Integration

Comment

Your email address will not be published.