Tekton Pipelines — Structure#

Layout pattern#

Standard Go Layout (cmd/internal/pkg) with Kubernetes operator conventions

Tekton follows the standard Go project layout rigorously, augmented by Kubernetes controller conventions: generated client code lives in pkg/client/, CRD types under pkg/apis/, reconcilers under pkg/reconciler/, and multiple operator binaries in cmd/. The vendor/ directory is committed (vendored). The project is a single Go module despite containing multiple deployable binaries, which is typical for Kubernetes operators.

Directory map#

tekton-pipeline/
├── cmd/                    # Eight deployable binaries
│   ├── controller/         # Main controller: reconciles TaskRun, PipelineRun, ResolutionRequest
│   ├── entrypoint/         # Injected sidecar binary: gates step execution via file signaling
│   ├── events/             # Events controller: publishes CloudEvents for CustomRun
│   ├── nop/                # No-op container: used to stop sidecars gracefully
│   ├── resolvers/          # Resolution controller: git, hub, bundle, cluster, http resolvers
│   ├── sidecarlogresults/  # Sidecar binary: reads step results from logs/files
│   ├── webhook/            # Admission webhook: defaulting, validation, CRD conversion
│   └── workingdirinit/     # Init container binary: creates working directories in workspaces
├── config/                 # Kubernetes manifests (RBAC, CRDs, Deployments, ConfigMaps)
│   ├── 100-namespace/      # Namespace definition
│   ├── 300-crds/           # CRD YAML definitions
│   └── resolvers/          # Resolver-specific manifests
├── docs/                   # Documentation
│   ├── developers/         # Developer guides
│   └── resolver-template/  # Template for writing custom resolvers
├── examples/v1/            # Example Task/Pipeline YAML definitions
├── hack/                   # Build/codegen scripts
│   ├── boilerplate/        # License header templates
│   ├── reference-docs-template/ # API reference doc templates
│   └── spec-gen/           # OpenAPI spec generation
├── internal/               # Private packages (not importable externally)
│   ├── artifactref/        # Artifact reference parsing
│   ├── sidecarlogresults/  # Sidecar log result reading (shared with cmd/sidecarlogresults)
│   └── test/               # Internal test helpers
├── optional_config/        # Optional Kubernetes configs (e.g., log access to controller)
├── pkg/                    # Core library packages (public API)
│   ├── apis/               # CRD type definitions (v1, v1beta1, v1alpha1) + config
│   ├── client/             # Generated Kubernetes clients, informers, listers, injection
│   ├── container/          # Container manipulation helpers
│   ├── controller/         # Controller wiring helpers
│   ├── credentials/        # Git/Docker credential management (creds-init)
│   ├── entrypoint/         # Entrypointer logic (step gating, result extraction)
│   ├── internal/           # Package-private helpers (computeresources, affinityassistant, etc.)
│   ├── list/               # List utility functions
│   ├── names/              # Name generation utilities
│   ├── pipelinerunmetrics/ # Prometheus metrics for PipelineRun
│   ├── platforms/          # OS/arch platform detection
│   ├── pod/                # Pod building logic (converts TaskSpec → Pod spec)
│   ├── reconciler/         # Reconciler implementations for all CRDs
│   ├── remote/             # Remote resource fetching (OCI, resolution)
│   ├── remoteresolution/   # New-generation resolution framework + built-in resolvers
│   ├── resolution/         # Older resolution framework (being superseded)
│   ├── result/             # Task/step result types and parsing
│   ├── spire/              # SPIRE/SPIFFE workload identity integration
│   ├── status/             # Status management helpers
│   ├── substitution/       # Parameter substitution engine
│   ├── taskrunmetrics/     # Prometheus metrics for TaskRun
│   ├── termination/        # Termination message reading/writing
│   ├── tracing/            # OpenTelemetry distributed tracing setup
│   ├── trustedresources/   # Trusted resource verification (Sigstore, KMS)
│   └── workspace/          # Workspace volume binding helpers
├── tekton/                 # Tekton pipeline definitions for this project's own CI/CD
├── test/                   # Integration and e2e tests + test helpers
│   ├── conformance/        # Conformance test suite
│   ├── custom-task-ctrls/  # Custom task controller examples for testing
│   ├── diff/               # Diff utilities for tests
│   ├── git-resolver/       # Git resolver integration test helpers
│   ├── names/              # Test name helpers
│   ├── parse/              # YAML parsing helpers for test fixtures
│   ├── remoteresolution/   # Remote resolution test helpers
│   ├── resolution/         # Resolution test helpers
│   ├── testdata/           # Test fixture files (YAML, JSON, certs)
│   └── trustedresources-keys/ # Key material for trusted resource tests
└── vendor/                 # Vendored dependencies (committed)

Entry points#

Binarycmd/ pathPurpose
controllercmd/controller/main.goCore Kubernetes operator. Runs three reconcilers: taskrun, pipelinerun, and resolutionrequest. Bootstraps via knative/pkg/injection/sharedmain.
webhookcmd/webhook/main.goKubernetes admission webhook. Handles defaulting, validation, ConfigMap validation, and CRD version conversion (v1alpha1 ↔ v1beta1 ↔ v1).
resolverscmd/resolvers/main.goResolution controller. Runs five resolver controllers: git, hub, bundle, cluster, http — each implements framework.Resolver interface.
eventscmd/events/main.goEvents controller. Publishes CloudEvents for CustomRun resources via notifications/customrun reconciler.
entrypointcmd/entrypoint/main.goInjected into every step container. Gates execution by watching files, writes post-file on completion, extracts results, handles SPIRE signing.
sidecarlogresultscmd/sidecarlogresults/main.goSidecar that reads step results from files/logs and streams them to stdout for collection by the controller.
nopcmd/nop/main.goNo-op binary injected to replace sidecar images when they need to stop. Simply exits (or waits for signal if tekton_run_indefinitely arg is passed).
workingdirinitcmd/workingdirinit/main.goInit container that pre-creates working directories inside workspace volumes before steps run.

Package organization#

Internal packages (internal/)#

  • internal/artifactref — Parsing of artifact reference strings (produced/consumed artifacts).
  • internal/sidecarlogresults — Core logic for scanning step result files and formatting output for the sidecar log results binary.
  • internal/test — Test infrastructure helpers internal to the module.

Internal packages (pkg/internal/)#

  • pkg/internal/affinityassistant — Logic for the affinity assistant that co-locates PipelineRun pods to a node with workspace volumes.
  • pkg/internal/computeresources — Resource request/limit computation across step-level and task-level settings, with LimitRange handling.
  • pkg/internal/defaultresourcerequirements — Default resource requirements application.
  • pkg/internal/resolution — Package-private resolution helpers bridging old and new resolution frameworks.
  • pkg/internal/resultref — Result reference parsing for pipeline-level parameter substitution.

Public packages (pkg/)#

  • pkg/apis/pipeline/{v1,v1beta1,v1alpha1} — CRD type definitions: Task, TaskRun, Pipeline, PipelineRun, StepAction, VerificationPolicy. Each version implements knative/pkg webhook interfaces (defaulting + validation).
  • pkg/apis/configDefaults and FeatureFlags ConfigMap parsing; config store that propagates config via context.Context.
  • pkg/apis/resolution/{v1alpha1,v1beta1}ResolutionRequest CRD types.
  • pkg/client/ — Code-generated Kubernetes client machinery: typed clientsets, informers, listers, and Knative injection wrappers.
  • pkg/pod — The central builder that translates a TaskSpec into a Kubernetes Pod spec, including entrypoint injection, credential mounting, workspace volume binding, and step ordering.
  • pkg/reconciler/taskrunTaskRun reconciler: orchestrates pod creation, status tracking, result extraction, and SPIRE signing.
  • pkg/reconciler/pipelinerunPipelineRun reconciler: implements DAG-based task scheduling, workspace propagation, parameter substitution, and result aggregation.
  • pkg/reconciler/pipeline/dag — DAG construction and traversal for pipeline task dependencies.
  • pkg/remoteresolution — Current resolution framework: framework.Resolver interface + controllers for git, hub, bundle, cluster, and http resolvers.
  • pkg/resolution — Older resolution framework (maintained for backward compatibility).
  • pkg/spire — SPIRE/SPIFFE client integration for workload identity and TaskRun result signing.
  • pkg/trustedresources — Verification of remote resources using Sigstore (Cosign) signatures with KMS backend support.
  • pkg/substitution — Parameter substitution engine ($(params.foo), $(results.bar.output)).
  • pkg/workspace — Workspace binding helpers: validates bindings, creates VolumeMount/Volume specs.
  • pkg/credentials — Git and Docker credential initialization (creds-init replacement).
  • pkg/entrypointEntrypointer struct and step execution orchestration logic.
  • pkg/termination — Termination message reading and writing (result extraction path).
  • pkg/tracing — OpenTelemetry tracer setup and OTLP HTTP exporter configuration.
  • pkg/pipelinerunmetrics / pkg/taskrunmetrics — Prometheus metrics observers for runs.

Layering#

The package structure follows a clear layered architecture:

  1. CRD types (pkg/apis/) — data definitions, no business logic
  2. Generated clients (pkg/client/) — Kubernetes API machinery, generated
  3. Core primitives (pkg/pod, pkg/workspace, pkg/substitution, pkg/entrypoint) — business logic building blocks
  4. Reconcilers (pkg/reconciler/) — orchestration, depends on primitives and clients
  5. Binaries (cmd/) — thin wiring of reconcilers into processes

This is a strict clean-architecture layering with no upward dependencies.

Build system#

  • Build tool: GNU Make (Makefile) — primary build entrypoint; delegates to go build -mod=vendor.
  • Key targets:
    • make all — builds all binaries in bin/ for local OS/arch
    • make cross — cross-compiles all binaries for linux/amd64, arm, arm64, s390x, ppc64le
    • make test — unit tests with timeout
    • make fmtgofmt formatting
    • Targets like make generated-code, make update-codegen invoke hack/ scripts for code generation
  • Docker: Yes, multi-stage. Each cmd/ binary has a corresponding Dockerfile referenced in config/ Kubernetes Deployment manifests. The Makefile builds go binaries that are then layered into distroless-based images via ko or Docker.
  • Code generation: Heavy use — Kubernetes client-gen, lister-gen, informer-gen, and injection-gen produce all of pkg/client/. CRD YAML in config/300-crds/ is generated from Go types.
  • CI: GitHub Actions (.github/workflows/) runs tests, linting (golangci-lint), and end-to-end tests on real clusters.

Notable structural decisions#

  1. Eight binaries from one module: Rather than separate microservices with separate modules, all operator components share a single go.mod. This simplifies dependency management and allows shared packages without import cycles or separate versioning. The tradeoff is a larger vendor directory.

  2. entrypoint as injected sidecar: The cmd/entrypoint binary is the most architecturally unusual artifact — it is not a long-running service but a per-step wrapper injected into every container in a TaskRun Pod. It enforces sequential step execution within a Kubernetes Pod (which normally runs containers in parallel) using file-based semaphores. This is a deliberate architectural workaround for Kubernetes Pod semantics.

  3. Dual resolution frameworks (pkg/resolution vs pkg/remoteresolution): Two parallel resolution implementations exist side-by-side. The older pkg/resolution is being superseded by pkg/remoteresolution, which supports out-of-cluster resolution. Both are compiled in and the controller supports both via feature flags. This coexistence reflects the project’s API stability commitments during a migration period.

  4. config/ directory as Kubernetes source of truth: Unlike projects where Helm charts or Kustomize overlays are the deployment artifact, Tekton ships raw Kubernetes YAML in config/. The hack/ scripts generate these from Go type definitions, making the YAML a derived artifact from code — consistent with Kubernetes operator conventions.

  5. test/ as a first-class directory: Integration and conformance tests live in a top-level test/ directory with their own helpers (test/parse, test/diff, test/names) and test infrastructure. This separation from *_test.go files reflects the scale and importance of e2e testing for a production Kubernetes operator.

  6. pkg/internal/ alongside internal/: The project uses both top-level internal/ (truly private to the module) and pkg/internal/ (private to the pkg/ subtree but used across multiple pkg/ packages). This is an unusual but valid Go convention for organizing package-private helpers within a large pkg/ tree.