You just followed a guide to start your Tekton pipeline (or task) when a merge request is created or updated on your GitLab project. So you configured GitLab to send merge request events as webhooks. And you deployed some Tekton components:
- EventListener: receives webhooks from GitLab
- Trigger: starts your Pipeline every time the EventListener receives a new webhook from GitLab
- Pipeline: fetches the source code from GitLab and builds it
Then you notice that any event in your merge request (a new comment, a tag change) triggers the pipeline. That's not the behavior you desire. You don't need to build a comment or a tag, after all. You only want the pipeline to run when there is actual new code to build. Here's how I use Tekton's CEL Interceptor to create conditionals for my pipelines.
Have your trigger ready
I expect you have a trigger already defined. It's probably something similar to the snippet below.
The trigger's interceptor rejects anything that's not coming from a merge request. Still, the interceptor is not able to differentiate between code and non-code updates (like new comments).
apiVersion: triggers.tekton.dev/v1beta1 kind: Trigger metadata: name: webhook-listener-trigger spec: interceptors: # reject any payload that's not a merge request webhook - name: "filter-event-types" ref: name: "gitlab" kind: ClusterInterceptor params: - name: eventTypes value: - "Merge Request Hook" bindings: - ref: binding template: ref: template
Add a CEL interceptor
Here comes the
cel interceptor. This interceptor filters the webhook payload using the CEL expression language. If the filter expression evaluates to
true, the pipeline starts.
Here I'm checking for the
object_attributes.oldrev field to exist in the JSON body of the webhook payload. If
object_attributes.oldrev exists, then that means this event is about a code change. If there wasn't a code change, there's no previous revision (
oldrev) to refer to.
spec: interceptors: - name: "allow-code-changes-only" ref: name: cel kind: ClusterInterceptor params: - name: filter value: > has(body.object_attributes.oldrev)
Add the new interceptor to your trigger. Now your trigger looks like this:
apiVersion: triggers.tekton.dev/v1beta1 kind: Trigger metadata: name: gitlab-listener-trigger spec: interceptors: - name: "verify-gitlab-payload" ref: name: "gitlab" kind: ClusterInterceptor params: - name: eventTypes value: - "Merge Request Hook" - name: "allow-code-changes-only" ref: name: "cel" kind: ClusterInterceptor params: - name: filter value: > has(body.object_attributes.oldrev) bindings: - ref: binding template: ref: template
Deploy this new version of the trigger and enjoy the powers of automation. From now on, your pipeline only starts if there is some new code to build.
There are no limits to the conditions you can set in a CEL filter.
You may check that the merge request is currently open:
body.object_attributes.state in ['opened']
You can make sure the contributor finished their work on the code:
body.object_attributes.work_in_progress == false
You just have to concatenate multiple conditions correctly:
- name: filter value: > has(body.object_attributes.oldrev) && body.object_attributes.state in ['opened'] && body.object_attributes.work_in_progress == false
Check out the merge request events documentation to get inspired to write your own conditions.
You may need the CEL language definition to know how to translate your thoughts into code.
To evaluate types other than strings, you want to know the mapping between JSON and CEL types.
Comments are closed.