Tekton Pipelines for Kubernetes-Native CI/CD Testing

Tekton Pipelines for Kubernetes-Native CI/CD Testing

Tekton is a Kubernetes-native CI/CD framework. If your team runs workloads on Kubernetes and wants CI/CD that uses the same primitives — pods, volumes, service accounts — Tekton is worth a serious look.

This guide covers setting up Tekton Pipelines for automated testing workflows, from installing the basics to running parallel test suites.

What Makes Tekton Different

Most CI/CD systems run on their own infrastructure and call into Kubernetes when needed. Tekton runs inside Kubernetes. Every pipeline step is a container. Every pipeline run is a set of pods. There's no separate server to maintain — Tekton installs as a set of CRDs (Custom Resource Definitions) in your cluster.

This means:

  • Pipeline state lives in etcd alongside your workloads
  • Steps use the same RBAC and network policies as your apps
  • Scaling is handled by Kubernetes itself
  • You can use kubectl to inspect pipeline runs

The tradeoff: Tekton has more setup overhead than hosted CI/CD. It's not a good fit for teams that want zero-infrastructure CI. But if you're already managing Kubernetes, the operational cost is low.

Core Concepts

Task — a reusable unit of work. A Task contains one or more Steps (containers that run sequentially). Tasks can declare Parameters and Workspaces (shared volumes).

Pipeline — an ordered sequence of Tasks. Tasks in a Pipeline can run sequentially or in parallel, share data via Workspaces, and pass results between each other.

TaskRun / PipelineRun — an execution instance of a Task or Pipeline. These are Kubernetes resources you can create manually, via triggers, or via the Tekton CLI (tkn).

Trigger — a component that listens for external events (webhooks from GitHub, GitLab, etc.) and creates PipelineRuns in response.

Installing Tekton

Install the Tekton Pipelines controller into your cluster:

kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

Install the Tekton Dashboard (optional but useful):

kubectl apply --filename https://storage.googleapis.com/tekton-releases/dashboard/latest/release.yaml

Install the tkn CLI for local interaction:

# macOS
brew install tektoncd-cli

# Linux
curl -LO https://github.com/tektoncd/cli/releases/latest/download/tkn_Linux_x86_64.tar.gz
tar xvzf tkn_Linux_x86_64.tar.gz -C /usr/local/bin tkn

Verify the install:

kubectl get pods --namespace tekton-pipelines
tkn version

Writing a Test Task

Here's a Task that runs a Node.js test suite:

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: run-tests
spec:
  params:
    - name: repo-url
      type: string
    - name: revision
      type: string
      default: main
  workspaces:
    - name: source
  steps:
    - name: clone
      image: alpine/git
      script: |
        git clone $(params.repo-url) $(workspaces.source.path)
        cd $(workspaces.source.path)
        git checkout $(params.revision)
    - name: install
      image: node:20-alpine
      workingDir: $(workspaces.source.path)
      script: |
        npm ci
    - name: test
      image: node:20-alpine
      workingDir: $(workspaces.source.path)
      script: |
        npm test

Apply it:

kubectl apply -f run-tests-task.yaml

Creating a Test Pipeline

A Pipeline that clones, lints, and tests in sequence — with the option to run lint and unit tests in parallel:

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: test-pipeline
spec:
  params:
    - name: repo-url
    - name: revision
      default: main
  workspaces:
    - name: shared-workspace
  tasks:
    - name: fetch-source
      taskRef:
        name: git-clone
        kind: ClusterTask
      workspaces:
        - name: output
          workspace: shared-workspace
      params:
        - name: url
          value: $(params.repo-url)
        - name: revision
          value: $(params.revision)

    - name: lint
      runAfter: [fetch-source]
      taskRef:
        name: run-lint
      workspaces:
        - name: source
          workspace: shared-workspace

    - name: unit-tests
      runAfter: [fetch-source]
      taskRef:
        name: run-tests
      workspaces:
        - name: source
          workspace: shared-workspace

    - name: integration-tests
      runAfter: [unit-tests]
      taskRef:
        name: run-integration-tests
      workspaces:
        - name: source
          workspace: shared-workspace

lint and unit-tests both depend on fetch-source but not on each other, so Tekton runs them in parallel.

Running the Pipeline

Create a PipelineRun:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: test-pipeline-run-1
spec:
  pipelineRef:
    name: test-pipeline
  params:
    - name: repo-url
      value: https://github.com/your-org/your-repo
    - name: revision
      value: main
  workspaces:
    - name: shared-workspace
      volumeClaimTemplate:
        spec:
          accessModes: [ReadWriteOnce]
          resources:
            requests:
              storage: 1Gi

Apply it and watch:

kubectl apply -f pipeline-run.yaml
tkn pipelinerun logs test-pipeline-run-1 --follow

Or via the CLI directly:

tkn pipeline start test-pipeline \
  --param repo-url=https://github.com/your-org/your-repo \
  --workspace name=shared-workspace,claimName=pipeline-pvc \
  --showlog

Setting Up GitHub Triggers

Install Tekton Triggers:

kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml

Create an EventListener that responds to GitHub push events:

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: github-listener
spec:
  serviceAccountName: tekton-triggers-sa
  triggers:
    - name: github-push
      interceptors:
        - ref:
            name: github
          params:
            - name: secretRef
              value:
                secretName: github-webhook-secret
                secretKey: secretToken
            - name: eventTypes
              value: [push]
      bindings:
        - ref: github-push-binding
      template:
        ref: pipeline-trigger-template

Expose the EventListener with a Service and configure your GitHub repo's webhook to point to it. On push, Tekton creates a PipelineRun automatically.

Parallel Test Sharding

For large test suites, split tests across multiple TaskRuns using a matrix:

- name: test-shards
  taskRef:
    name: run-test-shard
  matrix:
    params:
      - name: shard-index
        value: ["0", "1", "2", "3"]
  params:
    - name: total-shards
      value: "4"

Each shard runs in its own pod. Total test time drops by roughly 1/n for n shards (minus startup overhead).

Integrating HelpMeTest

Tekton handles your build and unit test pipeline well. For end-to-end and browser tests, HelpMeTest complements it with zero-configuration monitoring.

Add a Tekton Task that triggers HelpMeTest after your build:

- name: run-e2e-tests
  runAfter: [deploy-staging]
  taskRef:
    name: helpmetest-trigger
  params:
    - name: api-key
      value: $(params.helpmetest-api-key)
    - name: test-suite
      value: smoke-tests

Or skip the pipeline integration entirely — HelpMeTest can run your end-to-end tests on a schedule (every 5 minutes, usage-based pricing at $0.003/run) independent of your Tekton pipeline. When Tekton handles the build and unit tests, HelpMeTest handles continuous production monitoring.

Observability

Tekton exports metrics to Prometheus. Key metrics for testing pipelines:

  • tekton_pipelines_controller_pipelinerun_duration_seconds — pipeline execution time
  • tekton_pipelines_controller_taskrun_duration_seconds — individual task time
  • tekton_pipelines_controller_pipelinerun_count — total runs

Add a Grafana dashboard to visualize test pass rates and flakiness over time. The Tekton Dashboard (kubectl port-forward -n tekton-pipelines svc/tekton-dashboard 9097:9097) gives a visual view of recent runs without Grafana setup.

Common Issues

PVC not releasing between runs: Use volumeClaimTemplate in PipelineRuns instead of a persistent PVC — Tekton creates and deletes the volume automatically per run.

Steps sharing data: Use Workspaces. Tekton Steps in the same Task share a filesystem, but Tasks in a Pipeline need an explicit Workspace to share files.

Secrets in steps: Mount Kubernetes Secrets as environment variables or volumes. Never hardcode credentials in Task specs.

Slow startup: Container image pulls dominate startup time for small tasks. Use slim images (node:20-alpine vs node:20) and configure an image pull policy of IfNotPresent for internal registries.

Summary

Tekton is the right CI/CD choice when you want Kubernetes-native pipelines with no external CI server. The learning curve is real — you're writing YAML for every concept — but the operational payoff is strong if you're already running Kubernetes.

For teams without Kubernetes, hosted CI (GitHub Actions, CircleCI) is less setup. For teams on Kubernetes who want full control over pipeline execution, Tekton fits well.

Pair it with HelpMeTest for continuous end-to-end test monitoring — Tekton handles your build pipeline, HelpMeTest handles your always-on test coverage.

Read more

Start now free