I’ve written before about Tekton Triggers, they’re pretty useful for driving different tasks in k8s, using the Tasks and Pipelines from the Tekton Pipeline project.

In this example, I’ll show how to automate building and publishing of container images when a release is created in GitHub, this works with the currently released versions of Pipeline and Triggers (v0.10.1 and v0.3.1).

To do this, there are three main resources, the EventListener, Trigger (Binding and Template) and the Pipeline.

EventListener

apiVersion: tekton.dev/v1alpha1
kind: EventListener
metadata:
  name: demo-event-listener
spec:
  serviceAccountName: demo-sa
  triggers:
    - name: build-on-release
      interceptors:
        - cel: >-
            filter: header.canonical('X-GitHub-Event') == 'release' &&
                    body.action == 'published' &&
                    body.repository.full_name == '<INSERT your repo here e.g. tektoncd/triggers >' &&
                    body.release.prerelease == false
      bindings:
        - name: build-on-release-binding
      template:
        name: build-on-release-template

This is a fairly standard CEL interceptor for handling GitHub webhooks, it handles release events, responding to newly published releases in the named repository and triggering the build-on-release-template through the build-on-release-binding.

If instead of not building prerelease releases, you wanted to do something like adding a -pre extension to the tag for pre-releases you could add an overlay:

overlays:
  key: intercepted.image_tag
  expression: $(body.release.tag_name) + (body.release.prerelease == true ?  "-pre" : "")

And then use that in the TriggerBinding.

TriggerBinding

apiVersion: tekton.dev/v1alpha1
kind: TriggerBinding
metadata:
  name: build-on-release-binding
spec:
  params:
  - name: tag_name
    value: $(body.release.tag_name)
  - name: gitrepositoryurl
    value: $(body.repository.clone_url)

This is pulling values from the event body.

TriggerTemplate

apiVersion: tekton.dev/v1alpha1
kind: TriggerTemplate
metadata:
  name: build-on-release-template
spec:
  params:
  - name: tag_name
    description: The newly created tag.
    default: master
  - name: gitrepositoryurl
    description: The git repository url
  resourcetemplates:
  - apiVersion: tekton.dev/v1alpha1
    kind: PipelineRun
    metadata:
      name: build-on-release-run-$(uid)
    spec:
      serviceAccountName: demo-sa
      pipelineRef:
        name: build-on-release
      params:
        - name: image-url
          value: quay.io/<INSERT YOUR Quay.IO username/repository>:$(params.tag_name)
      resources:
        - name: source-repo
          resourceSpec:
            type: git
            params:
            - name: revision
              value: $(params.tag_name)
            - name: url
              value: $(params.gitrepositoryurl)

This template triggers the build-on-release pipeline, providing a git resource to checkout, and an image name to push the image to.

Pipeline

apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
  name: build-on-release
spec:
  resources:
    - name: source-repo
      type: git
  params:
    - name: image-url
      type: string
      description: where to push the newly built image to e.g. quay.io/user/image
  tasks:
    - name: build-image
      taskRef:
        name: buildah-task
      params:
        - name: IMAGE_URL
          value: $(params.image-url)
      resources:
        inputs:
          - name: source
            resource: source-repo

The pipeline has a single task that builds an image.

Putting it altogether

To try this out:

$ kubectl apply -f https://github.com/tektoncd/pipeline/releases/download/v0.10.1/release.yaml
$ kubectl apply -f https://github.com/tektoncd/triggers/releases/download/v0.3.1/release.yaml

You’ll need to create DockerConfigJSON secret, so that the image can be pushed to:

$ kubectl create secret generic regcred --from-file=.dockerconfigjson=<insert path to an authenticated Docker config> --type=kubernetes.io/dockerconfigjson

I’ve provided a complete example.

Checkout the example code, and look for the changes that need to be made and adapt to your own repositories and image storage, these are in the files demo-event-listener.yaml and build-on-release-template.yaml.

$ kubectl apply -f <INSERT PATH TO CHECKED OUT buildonrelease EXAMPLE>

This will create an event-listener, with an associated service (svc/el-demo-event-listener on port 8080), you’ll need to expose this to the internet.

Then create a webhook in your own repository, pointing at your exposed event-listener.

(For test purposes, I use minikube, “kubectl port-forward svc/el-demo-event-listener 8080”, and “ngrok http 8080”).

Create a new release of your own application code, see here for how to do that.

This should trigger a PipelineRun, and after your code is built, it will push the image to your image repository, with the tag from your release.