Tekton’s PipelineRef allows you to reuse existing Pipeline resources across multiple PipelineRuns, but it’s not just a simple pointer; it’s a mechanism for versioning and modularity in your CI/CD.

Let’s see how it works in practice. Imagine you have a generic build-and-push pipeline that you want to use for different applications.

# pipelines/build-and-push.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: build-and-push
spec:
  params:
    - name: image-name
      type: string
      description: The name of the image to build and push.
    - name: git-repo-url
      type: string
      description: The URL of the Git repository to clone.
  tasks:
    - name: clone-repo
      taskRef:
        name: git-clone # Assuming a pre-existing git-clone task
      params:
        - name: url
          value: $(params.git-repo-url)
    - name: build-image
      taskRef:
        name: buildah-build # Assuming a pre-existing buildah-build task
      runAfter:
        - clone-repo
      params:
        - name: IMAGE
          value: $(params.image-name)
        - name: STORAGE_DRIVER
          value: overlay
    - name: push-image
      taskRef:
        name: buildah-push # Assuming a pre-existing buildah-push task
      runAfter:
        - build-image
      params:
        - name: IMAGE
          value: $(params.image-name)

Now, you can create PipelineRuns that reference this build-and-push pipeline.

# pipelineruns/app1-build.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: app1-build-run
spec:
  pipelineRef:
    name: build-and-push # Referencing the Pipeline by name
  params:
    - name: image-name
      value: "my-registry/app1:latest"
    - name: git-repo-url
      value: "https://github.com/my-org/app1.git"
  # ... other PipelineRun spec details like serviceAccountName, etc.
# pipelineruns/app2-build.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: app2-build-run
spec:
  pipelineRef:
    name: build-and-push
  params:
    - name: image-name
      value: "my-registry/app2:v1.2.0"
    - name: git-repo-url
      value: "https://github.com/my-org/app2.git"
  # ...

This PipelineRef mechanism is Tekton’s way of saying "use this specific definition of a Pipeline." When a PipelineRun is created, Tekton looks for a Pipeline resource in the same namespace that matches the pipelineRef.name. If it finds one, it uses that Pipeline’s definition to create the Tasks and Steps for the run.

The primary problem this solves is duplication and versioning. Without PipelineRef, you’d have to copy and paste the entire Pipeline definition into each PipelineRun (or more likely, create separate Pipeline resources for each application that are nearly identical). When you need to update the build logic, you’d have to update every single copy. PipelineRef centralizes the definition.

The PipelineRef can also include a bundle field. This is where things get interesting for true versioning and distribution. If your Pipeline is packaged as a Tekton Bundle (a OCI image containing Tekton resources), you can reference it like this:

# pipelineruns/app3-build-from-bundle.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: app3-build-run-bundle
spec:
  pipelineRef:
    name: build-and-push # Name within the bundle
    bundle: "my-docker-registry/tekton-bundles/ci-pipelines:v1.5.0" # The OCI image
  params:
    - name: image-name
      value: "my-registry/app3:latest"
    - name: git-repo-url
      value: "https://github.com/my-org/app3.git"

When you use a bundle, Tekton pulls the Pipeline definition from the specified OCI image. This is powerful because the bundle can contain multiple Pipelines, Tasks, and other resources. The pipelineRef.name then specifies which Pipeline within that bundle to use. This allows you to version your entire CI/CD pipeline catalog as a single OCI image, ensuring consistency across your organization.

The most surprising true thing about PipelineRef is that when you specify pipelineRef.bundle, Tekton doesn’t need a Pipeline resource named build-and-push to exist in the cluster’s namespace. It will extract the Pipeline definition from the bundle image itself. The name field then becomes the identifier for the Pipeline within that bundle.

This means you can have a PipelineRun that specifies a bundle and a pipelineRef.name, and Tekton will dynamically discover and use the Pipeline definition from the bundle without any prior Pipeline resource creation in the cluster for that specific definition.

The next concept you’ll likely encounter is how to manage secrets and credentials for pushing images, which often involves PipelineRun’s secrets field or serviceAccountName with appropriate RBAC.

Want structured learning?

Take the full Tekton course →