Driving builds on GitHub release with Tekton
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.