On this page
Multiple GitHub Applications Support
Multi-GitHub Apps Support is a Technology Preview feature only. Technology Preview features are not currently supported and might not be functionally complete. We do not recommend using them in production. These features provide early access to upcoming Pipelines-as-Code features, enabling you to test functionality and provide feedback during the development process.
This page explains how to run multiple GitHub applications on the same cluster with Pipelines-as-Code. You need this when your organization integrates with more than one GitHub instance – for example, public GitHub for open-source projects and GitHub Enterprise Server for internal repositories.
When to Use This
Deploy a second controller when you need to:
- Connect to both public GitHub and a GitHub Enterprise Server instance from the same cluster.
- Isolate credentials and configuration between different GitHub Apps.
- Route webhooks from different GitHub instances to dedicated controllers.
If you only use a single GitHub instance, the default controller is sufficient and you do not need this setup.
Deployment Architecture
Each GitHub application requires:
- A dedicated controller deployment
- An associated Service resource
- Network exposure via Ingress (Kubernetes) or Route (OpenShift) or smee.io for webhook tunneling
- Unique configuration through:
- A Secret containing GitHub App credentials (
private key,application_id,webhook_secret) - A ConfigMap for application-specific settings
- A Secret containing GitHub App credentials (
Controller Configuration Parameters
| Environment Variable | Description | Example |
|---|---|---|
PAC_CONTROLLER_LABEL | Unique identifier for the controller instance | github-enterprise |
PAC_CONTROLLER_SECRET | Secret containing GitHub App credentials | gh-enterprise-secret |
PAC_CONTROLLER_CONFIGMAP | ConfigMap with application settings | gh-enterprise-config |
Automated CI Setup with startpaac
For automated testing environments, startpaac can install and configure second controllers automatically.
Prerequisites
- startpaac installed and configured
- Secret files for the second GitHub application
Automatic Installation in CI Mode
When you run startpaac with the --ci flag, it automatically detects and installs the second controller if:
- The
PAC_SECOND_SECRET_FOLDERenvironment variable is set - The folder contains the required secret files:
github-application-idgithub-private-keywebhook.secretsmee(optional, for webhook tunneling)
Example:
# Create secret folder with GitHub App credentials
mkdir -p ~/secrets-second
echo "12345" > ~/secrets-second/github-application-id
echo "...RSA PRIVATE KEY..." > ~/secrets-second/github-private-key
echo "webhook-secret-value" > ~/secrets-second/webhook.secret
echo "https://smee.io/your-channel" > ~/secrets-second/smee
# Export environment variable
export PAC_SECOND_SECRET_FOLDER=~/secrets-second
# Run startpaac in CI mode
cd startpaac
./startpaac --ci -aThis will:
- Generate TLS certificates using minica for the second controller domain
- Create Kubernetes secrets from the secret folder
- Deploy the second controller with proper ingress/route configuration
- Configure gosmee for webhook tunneling (if you provided a smee URL)
Manual Setup
For manual installation or custom configurations, use the second-controller.py script described below.
Deployment Automation Script
The second-controller.py script generates the deployment YAML for a second controller.
Location: ./hack/second-controller.py in the Pipelines-as-Code repository
Basic Usage
python3 hack/second-controller.py <LABEL> | kubectl apply -f -Advanced Options
Usage: second-controller.py [-h] [--configmap CONFIGMAP]
[--ingress-domain INGRESS_DOMAIN]
[--secret SECRET]
[--controller-image CONTROLLER_IMAGE]
[--gosmee-image GOSMEE_IMAGE]
[--smee-url SMEE_URL] [--namespace NAMESPACE]
[--openshift-route]
LABELKey Options
| Option | Description |
|---|---|
--configmap | ConfigMap name (default: <LABEL>-configmap) |
--secret | Secret name (default: <LABEL>-secret) |
--ingress-domain | Create Ingress with specified domain (Kubernetes) |
--openshift-route | Create OpenShift Route instead of Ingress |
--controller-image | Custom controller image (use ko for local builds) |
--smee-url | Deploy Gosmee sidecar for webhook tunneling |
--namespace | Target namespace (default: pipelines-as-code) |
Example Scenarios
The following examples show common deployment patterns.
- Basic Kubernetes Deployment
# Generate and apply configuration for GitHub Enterprise
python3 hack/second-controller.py ghe \
--ingress-domain "ghe.example.com" \
--namespace pipelines-as-code | kubectl apply -f -- OpenShift Deployment with Custom Config
# Create configuration with custom secret and route
python3 hack/second-controller.py enterprise \
--openshift-route \
--secret my-custom-secret \
--configmap enterprise-config | oc apply -f -- Local Development with Ko
# Build and deploy controller image using ko
export KO_DOCKER_REPO=quay.io/your-username
ko apply -f <(
python3 hack/second-controller.py dev \
--controller-image=ko \
--namespace pipelines-as-code
)4. Webhook Tunneling with Smee.io
Use tunneling when your cluster is not directly reachable from the internet.
# Deploy with webhook tunneling for local testing
python3 hack/second-controller.py test \
--smee-url https://smee.io/your-channel | kubectl apply -f -Environment Variables
The script respects these environment variables for customization:
PAC_CONTROLLER_LABEL Controller identifier
PAC_CONTROLLER_TARGET_NS Target namespace (default: pipelines-as-code)
PAC_CONTROLLER_SECRET Secret name (default: <LABEL>-secret)
PAC_CONTROLLER_CONFIGMAP ConfigMap name (default: <LABEL>-configmap)
PAC_CONTROLLER_SMEE_URL Smee.io URL for webhook tunneling
PAC_CONTROLLER_IMAGE Controller image (default: ghcr.io/openshift-pipelines/pipelines-as-code-controller:stable)