Skip to content
Architecture
On this page

Architecture

Pipelines-as-Code (PAC) is built on top of Tekton Pipelines and provides a GitOps-native CI/CD experience. This page explains the architecture, components, and how they work together.

Architecture Overview

PAC consists of three main components that work together to process Git events and manage pipeline executions. See Tekton Ecosystem for how PAC connects to Tekton Pipelines, Chains, Results, Dashboard, and Operator.

Core Components

Controller

Binary: pipelines-as-code-controller Responsibilities:

  • Receives webhook events from Git providers
  • Validates event authenticity and permissions
  • Resolves pipeline definitions from .tekton/ directory
  • Creates PipelineRuns on the Kubernetes cluster
  • Manages concurrency and queueing
  • Handles GitOps commands (/test, /retest, /cancel)

Key Packages:

  • pkg/adapter: Event processing and webhook handling
  • pkg/matcher: Matches events against pipeline annotations
  • pkg/provider: Git provider integrations (GitHub, GitLab, etc.)
  • pkg/acl: Access control and permission validation
  • pkg/pipelineascode: Core pipeline processing logic

Location: cmd/pipelines-as-code-controller/main.go

Watcher

Binary: pipelines-as-code-watcher Responsibilities:

  • Watches PipelineRun resources for status changes
  • Reports status back to Git providers (checks, comments, badges)
  • Manages PipelineRun cleanup based on retention policies
  • Handles concurrency queue processing
  • Updates Repository CR status

Key Packages:

  • pkg/reconciler: PipelineRun reconciliation logic
  • pkg/kubeinteraction: Kubernetes API interactions
  • pkg/formatting: Status formatting for different providers
  • pkg/queue: Concurrency queue management

Location: cmd/pipelines-as-code-watcher/main.go

Webhook Handler

Binary: pipelines-as-code-webhook (embedded in controller) Responsibilities:

  • Receives HTTP webhook requests from Git providers
  • Validates webhook signatures
  • Routes events to the controller
  • Handles incoming webhook feature for manual triggers

Location: cmd/pipelines-as-code-webhook/main.go

Event Flow

The following describes how a typical pull request event flows through the system:

1

Git Event

A developer opens a pull request on GitHub, GitLab, or another supported Git provider.

2

Webhook Delivery

The Git provider sends a webhook HTTP POST request to the PAC webhook handler.

3

Event Validation

The webhook handler:

  • Verifies the webhook signature
  • Validates the event payload
  • Checks for skip CI markers ([skip ci], [ci skip])

4

Repository Lookup

The controller:

  • Finds the matching Repository CR
  • Retrieves authentication credentials
  • Validates the repository configuration

5

Permission Check

The ACL system validates:

  • User is authorized (org member, collaborator, or in OWNERS file)
  • Pull request doesn’t require /ok-to-test approval
  • Event matches allowed event types

6

Pipeline Resolution

The resolver:

  • Fetches .tekton/ directory from the repository
  • Matches pipelines to the event using annotations
  • Resolves remote tasks from Artifact Hub
  • Substitutes template variables ({{repo_url}}, {{revision}}, etc.)

7

PipelineRun Creation

The controller creates a PipelineRun resource on Kubernetes with:

  • Resolved pipeline definition
  • Workspaces and secrets
  • Labels and annotations for tracking

8

Execution

Tekton Pipelines executes the PipelineRun:

  • Creates pods for each task
  • Runs the pipeline steps
  • Manages task dependencies and workspaces

9

Status Monitoring

The watcher:

  • Monitors PipelineRun status changes
  • Reports progress to the Git provider
  • Updates GitHub Checks, GitLab MR notes, etc.

10

Completion

When the PipelineRun completes:

  • Final status is reported to the Git provider
  • Logs and artifacts are linked in comments
  • Repository CR status is updated
  • Cleanup is scheduled based on retention policy

Key Design Patterns

Repository CR

The Repository Custom Resource (CR) is the central configuration object:

apiVersion: pipelinesascode.tekton.dev/v1alpha1
kind: Repository
metadata:
  name: my-repo
  namespace: my-namespace
spec:
  url: "https://github.com/org/repo"
  git_provider:
    type: "github"
    secret:
      name: "github-token"
      key: "token"
  settings:
    policy: "allowed"

Purpose:

  • Maps Git repositories to Kubernetes namespaces
  • Stores authentication credentials
  • Configures provider-specific settings
  • Tracks PipelineRun history and status

Event Matching

Pipelines are matched to events using annotations:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  annotations:
    pipelinesascode.tekton.dev/on-event: "[pull_request]"
    pipelinesascode.tekton.dev/on-target-branch: "[main, develop]"
    pipelinesascode.tekton.dev/on-cel-expression: |
      event == "pull_request" && source_branch.startsWith("feature/")

Matching Logic:

  1. Check on-event annotation matches event type
  2. Verify on-target-branch matches target branch
  3. Evaluate on-cel-expression if present
  4. Check on-path-change if file patterns specified

Package: pkg/matcher

Pipeline Resolution

The resolver processes pipeline definitions: Steps:

  1. Fetch .tekton/ directory from the repository at the event revision

  2. Parse YAML files for PipelineRun resources

  3. Match pipelines to the event

  4. Resolve remote tasks from Pipelines-as-Code annotations and inline them into the PipelineRun:

    metadata:
      annotations:
        pipelinesascode.tekton.dev/task: "git-clone"
    spec:
      pipelineSpec:
        tasks:
        - name: fetch-repository
          taskRef:
            name: git-clone

    Task references that set taskRef.resolver are left for Tekton to resolve in the cluster:

    taskRef:
      resolver: hub
      params:
        - name: catalog
          value: git-clone
        - name: kind
          value: task
        - name: name
          value: git-clone
  5. Substitute template variables:

    • {{repo_url}} → Repository clone URL
    • {{revision}} → Git SHA
    • {{target_branch}} → PR target branch
    • {{source_branch}} → PR source branch

Package: pkg/pipelineascode/resolve

Access Control (ACL)

PAC implements a flexible ACL system: Permission Levels:

  1. Repository admins: Full access
  2. Organization members: Can trigger pipelines
  3. Collaborators: Can trigger pipelines if configured
  4. OWNERS file: Custom approval rules
  5. /ok-to-test: Manual approval for untrusted PRs

Configuration:

# Repository CR
spec:
  settings:
    policy: "allowed"  # allowed, required (OWNERS), denied

Package: pkg/acl

Concurrency Control

PAC manages pipeline execution concurrency: Annotation:

metadata:
  annotations:
    pipelinesascode.tekton.dev/max-concurrency: "1"

Queue Management:

  • PipelineRuns exceeding concurrency limit are queued
  • State: queued → started → completed
  • FIFO queue per repository
  • Automatic promotion when slots become available

See Concurrency Flow for details. Package: pkg/queue

Provider Integrations

PAC supports multiple Git providers through a common interface:

Provider Interface

All providers implement the Interface in pkg/provider/interface.go:

type Interface interface {
    // Validate webhook signature
    Validate(req *http.Request) error

    // Parse webhook payload
    ParsePayload(payload []byte) (*info.Event, error)

    // Create status check/comment
    CreateStatus(repo string, sha string, status string) error

    // Post comment on PR/MR
    CreateComment(repo string, prNum int, comment string) error

    // Get changed files
    GetFiles(repo string, prNum int) ([]string, error)
}

Supported Providers

  • GitHub
  • GitLab
  • Forgejo
  • Bitbucket

Package: pkg/provider/githubFeatures:

  • GitHub App authentication
  • Webhook authentication
  • GitHub Checks API integration
  • Line annotations for errors
  • Re-run from UI support

Authentication:

  • GitHub App (recommended)
  • Personal Access Token

Package: pkg/provider/gitlabFeatures:

  • Merge Request notes
  • Pipeline status badges
  • Commit status integration
  • Group-level tokens

Authentication:

  • Personal Access Token
  • Project Access Token

Package: pkg/provider/gitea (shared with Gitea)Features:

  • Pull request comments
  • Commit status
  • Empty webhook secrets (optional)

Status: Tech PreviewAuthentication:

  • Personal Access Token

Package: pkg/provider/bitbucketcloud, pkg/provider/bitbucketserverFeatures:

  • Pull request comments
  • Build status API
  • Separate Cloud/Server implementations

Authentication:

  • Scoped API token (Cloud)
  • Personal Access Token (Server)

Package Structure

The following is an overview of the main packages:

pkg/
├── acl/              # Access control and permissions
├── adapter/          # Event adapter and webhook processing
├── apis/             # CR definitions and types
├── cel/              # CEL expression evaluation
├── changedfiles/     # File change detection
├── cli/              # tkn-pac CLI implementation
├── formatting/       # Status and output formatting
├── hub/              # Artifact Hub integration
├── kubeinteraction/  # Kubernetes API client
├── matcher/          # Event and pipeline matching
├── opscomments/      # GitOps command parsing (/test, /retest)
├── params/           # Configuration and settings
├── pipelineascode/   # Core pipeline processing
├── provider/         # Git provider integrations
├── queue/            # Concurrency queue management
├── reconciler/       # PipelineRun reconciliation
└── secrets/          # Secret management

Configuration and Settings

PAC is configured through:

ConfigMap Settings

Name: pipelines-as-code (in pipelines-as-code namespace) Common Settings:

apiVersion: v1
kind: ConfigMap
metadata:
  name: pipelines-as-code
  namespace: pipelines-as-code
data:
  # Application settings
  application-name: "Pipelines as Code"

  # Artifact Hub API URL
  hub-url: "https://artifacthub.io"

  # Remote tasks support
  remote-tasks: "true"

  # Auto-create secrets
  secret-auto-create: "true"

  # Bitbucket settings
  bitbucket-cloud-check-source-ip: "true"

  # Maximum PipelineRuns to keep
  max-keep-runs: "10"

Repository-Level Settings

Settings can be overridden per repository:

apiVersion: pipelinesascode.tekton.dev/v1alpha1
kind: Repository
metadata:
  annotations:
    pipelinesascode.tekton.dev/max-keep-runs: "5"

Secrets Management

PAC uses Kubernetes secrets for:

Git Provider Credentials

apiVersion: v1
kind: Secret
metadata:
  name: github-token
type: Opaque
stringData:
  token: "ghp_xxxxx"  # Personal access token or GitHub App token

Webhook Secrets

apiVersion: v1
kind: Secret
metadata:
  name: webhook-secret
type: Opaque
stringData:
  webhook.secret: "random-secret-string"

Pipeline Secrets

Secrets for use within pipelines:

apiVersion: v1
kind: Secret
metadata:
  name: registry-credentials
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: <base64-encoded-config>

Logging and Observability

Structured Logging

PAC uses structured JSON logging:

{
  "level": "info",
  "ts": "2024-03-01T10:30:00.000Z",
  "logger": "pipelinesascode",
  "msg": "Processing pull request event",
  "provider": "github",
  "repository": "org/repo",
  "event": "pull_request"
}

Log Levels

Configure via ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-logging
  namespace: pipelines-as-code
data:
  zap-logger-config: |
    {
      "level": "info",
      "development": false,
      "outputPaths": ["stdout"],
      "errorOutputPaths": ["stderr"],
      "encoding": "json"
    }

Performance Considerations

Resource Requirements

Controller:

  • CPU: 100m - 500m
  • Memory: 128Mi - 512Mi

Watcher:

  • CPU: 50m - 200m
  • Memory: 64Mi - 256Mi

Scaling

  • Controllers run in active/passive mode (leader election)
  • Watchers can run multiple replicas
  • Use horizontal pod autoscaling for high-traffic scenarios

Optimization Tips

  • Use concurrency limits to prevent cluster overload
  • Configure PipelineRun retention (max-keep-runs)
  • Enable remote task caching
  • Use volume workspaces instead of PVCs for better performance
  • Informer cache transforms automatically strip unused fields from cached objects, reducing watcher memory usage by up to 94% per object — see Informer Cache Optimization

Security Architecture

Webhook Signature Validation

All webhooks are cryptographically verified:

  • GitHub: HMAC-SHA256 signature
  • GitLab: Secret token validation
  • Bitbucket: HMAC-SHA256 signature
  • Forgejo: Optional signature validation

Secret Redaction

Secrets are automatically redacted from:

  • GitHub Checks annotations
  • Log outputs in comments
  • PipelineRun status messages

RBAC

PAC requires specific Kubernetes permissions:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pipelines-as-code-controller
rules:
- apiGroups: ["pipelinesascode.tekton.dev"]
  resources: ["repositories"]
  verbs: ["get", "list", "watch", "update"]
- apiGroups: ["tekton.dev"]
  resources: ["pipelineruns", "taskruns"]
  verbs: ["get", "list", "watch", "create", "delete"]

Extension Points

Custom Parameters

Inject custom parameters into PipelineRuns: Package: pkg/customparams

apiVersion: v1
kind: ConfigMap
metadata:
  name: pipelines-as-code
data:
  custom-console-name: "Tekton Dashboard"
  custom-console-url: "https://dashboard.example.com"

LLM Integration

PAC includes experimental LLM integration for:

  • Automatic issue analysis
  • Error explanation
  • Suggested fixes

Package: pkg/llm

Next Steps