How do you handle pipeline-as-code with Tekton and Git repository versioning?
Quick Answer
Tekton pipeline-as-code stores Pipeline, Task, and Trigger definitions as YAML files within the application's Git repository, versioned alongside the source code. The Tekton Pipelines-as-Code controller watches for changes in a designated directory like .tekton/ and automatically creates PipelineRuns when pull requests or pushes occur. This ensures pipeline definitions evolve with the codebase, enables code review for CI/CD changes, and provides full auditability through Git history.
Detailed Answer
Pipeline-as-code is the practice of storing CI/CD pipeline definitions in the same version-controlled repository as the application source code, treating them as first-class software artifacts subject to the same review, testing, and versioning processes as the application itself. Tekton's pipeline-as-code implementation, through the Pipelines-as-Code component, extends this concept by providing a controller that automatically discovers, validates, and executes pipeline definitions from repository directories when triggered by Git events. This eliminates the disconnect between the application code and the pipeline that builds it, a problem that plagues organizations where pipeline definitions live in a separate central repository and drift out of sync with the applications they serve.
The Pipelines-as-Code controller integrates with GitHub, GitLab, and Bitbucket through webhook events and GitHub App installations. When a developer on the payments-api team creates a pull request, the controller detects the .tekton/ directory in the repository, reads the PipelineRun definitions from that directory, resolves any Task references using in-repo definitions or Tekton Hub references, and creates the PipelineRun in the target namespace. The pipeline runs against the pull request branch, and the results are reported back to the Git provider as commit status checks. This means the pipeline definition in the pull request branch is the one that executes, allowing developers to modify both their application code and the pipeline in the same pull request and see the combined effect immediately. For the checkout-service team, updating a Dockerfile and simultaneously modifying the build pipeline to accommodate the new multi-stage build structure happens in a single reviewable, testable pull request.
Version control of pipeline definitions provides capabilities that centrally managed pipelines cannot match. Every pipeline change has a Git commit with an author, timestamp, reviewer, and description of why the change was made. If the order-processing-service pipeline starts failing after a recent change, git log on the .tekton/ directory immediately reveals what changed, who changed it, and the associated code review discussion. Rolling back a pipeline change is a standard git revert. Branching allows the inventory-sync team to experiment with pipeline changes on a feature branch without affecting the main pipeline. Release tagging pins a specific pipeline version to a release, ensuring reproducible builds even months later. This versioning capability is essential for regulated environments where auditors need to prove that the pipeline used to build a specific release artifact was reviewed and approved through the same change management process as the application code.
The organizational pattern for pipeline-as-code at scale involves a layered template system. A central platform-pipelines repository maintained by the DevOps team contains base Task definitions and Pipeline templates for common technology stacks like Java-Maven, Node-npm, Python-pip, and Go-modules. Application teams reference these shared tasks from their .tekton/ PipelineRun definitions using Tekton Bundles, which package Tasks and Pipelines as OCI artifacts versioned in the container registry. The user-auth-service team's .tekton/pull-request.yaml references the shared maven-build task from the latest approved bundle version, adds service-specific integration test tasks defined locally in the repository, and customizes parameters like the deployment target and notification channels. When the platform team releases a new version of the shared tasks with security improvements, application teams update the bundle reference in their .tekton/ definitions through standard pull requests, ensuring controlled adoption with review and testing.
Operational considerations for pipeline-as-code include security boundaries, resource management, and debugging workflows. The Pipelines-as-Code controller must validate that pipeline definitions in untrusted pull requests from external contributors do not reference privileged resources or attempt to exfiltrate secrets. The controller supports a policy where pull requests from non-collaborators require an explicit comment like /ok-to-test from a repository maintainer before the pipeline executes, preventing untrusted code from running in the CI environment. The .tekton/ directory can contain multiple PipelineRun definitions for different events: pull-request.yaml for pull request validation, push-main.yaml for main branch builds, and release.yaml for tagged releases. Each definition specifies its trigger conditions through annotations, allowing fine-grained control over which pipeline runs for which event. Debugging pipeline failures uses the standard Tekton tools like tkn pipelinerun logs with the addition of being able to reproduce any historical pipeline run by checking out the corresponding Git commit and applying the .tekton/ definitions manually.