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#
| Binary | cmd/ path | Purpose |
|---|---|---|
controller | cmd/controller/main.go | Core Kubernetes operator. Runs three reconcilers: taskrun, pipelinerun, and resolutionrequest. Bootstraps via knative/pkg/injection/sharedmain. |
webhook | cmd/webhook/main.go | Kubernetes admission webhook. Handles defaulting, validation, ConfigMap validation, and CRD version conversion (v1alpha1 ↔ v1beta1 ↔ v1). |
resolvers | cmd/resolvers/main.go | Resolution controller. Runs five resolver controllers: git, hub, bundle, cluster, http — each implements framework.Resolver interface. |
events | cmd/events/main.go | Events controller. Publishes CloudEvents for CustomRun resources via notifications/customrun reconciler. |
entrypoint | cmd/entrypoint/main.go | Injected into every step container. Gates execution by watching files, writes post-file on completion, extracts results, handles SPIRE signing. |
sidecarlogresults | cmd/sidecarlogresults/main.go | Sidecar that reads step results from files/logs and streams them to stdout for collection by the controller. |
nop | cmd/nop/main.go | No-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). |
workingdirinit | cmd/workingdirinit/main.go | Init 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 implementsknative/pkgwebhook interfaces (defaulting + validation).pkg/apis/config—DefaultsandFeatureFlagsConfigMap parsing; config store that propagates config viacontext.Context.pkg/apis/resolution/{v1alpha1,v1beta1}—ResolutionRequestCRD types.pkg/client/— Code-generated Kubernetes client machinery: typed clientsets, informers, listers, and Knative injection wrappers.pkg/pod— The central builder that translates aTaskSpecinto a KubernetesPodspec, including entrypoint injection, credential mounting, workspace volume binding, and step ordering.pkg/reconciler/taskrun—TaskRunreconciler: orchestrates pod creation, status tracking, result extraction, and SPIRE signing.pkg/reconciler/pipelinerun—PipelineRunreconciler: 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.Resolverinterface + 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/entrypoint—Entrypointerstruct 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:
- CRD types (
pkg/apis/) — data definitions, no business logic - Generated clients (
pkg/client/) — Kubernetes API machinery, generated - Core primitives (
pkg/pod,pkg/workspace,pkg/substitution,pkg/entrypoint) — business logic building blocks - Reconcilers (
pkg/reconciler/) — orchestration, depends on primitives and clients - 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 togo build -mod=vendor. - Key targets:
make all— builds all binaries inbin/for local OS/archmake cross— cross-compiles all binaries for linux/amd64, arm, arm64, s390x, ppc64lemake test— unit tests with timeoutmake fmt—gofmtformatting- Targets like
make generated-code,make update-codegeninvokehack/scripts for code generation
- Docker: Yes, multi-stage. Each
cmd/binary has a corresponding Dockerfile referenced inconfig/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 inconfig/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#
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.entrypointas injected sidecar: Thecmd/entrypointbinary 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.Dual resolution frameworks (
pkg/resolutionvspkg/remoteresolution): Two parallel resolution implementations exist side-by-side. The olderpkg/resolutionis being superseded bypkg/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.config/directory as Kubernetes source of truth: Unlike projects where Helm charts or Kustomize overlays are the deployment artifact, Tekton ships raw Kubernetes YAML inconfig/. Thehack/scripts generate these from Go type definitions, making the YAML a derived artifact from code — consistent with Kubernetes operator conventions.test/as a first-class directory: Integration and conformance tests live in a top-leveltest/directory with their own helpers (test/parse,test/diff,test/names) and test infrastructure. This separation from*_test.gofiles reflects the scale and importance of e2e testing for a production Kubernetes operator.pkg/internal/alongsideinternal/: The project uses both top-levelinternal/(truly private to the module) andpkg/internal/(private to thepkg/subtree but used across multiplepkg/packages). This is an unusual but valid Go convention for organizing package-private helpers within a largepkg/tree.