Create a Git Secret for PAC

When you integrate a repository with PAC over a Webhook (not the GitHub App), the Repository resource references a Kubernetes Secret that holds two pieces of credentials:

  • A Git access token PAC uses to call the Git provider's API during normal pipeline processing, such as reading repository metadata and posting comments or commit statuses.
  • A webhook secret the Git provider includes when delivering an event so PAC can verify the request originated from the expected source.

This guide creates that Secret for GitHub Webhook mode and GitLab Webhook mode. GitHub App mode does not need a per-repository Secret because the controller uses the cluster-wide App credentials.

How PAC reads the Secret

PAC looks up the Secret through the Repository.spec.git_provider fields:

spec:
  git_provider:
    type: gitlab                # or github
    secret:
      name: <secret-name>
      key: provider.token       # default: provider.token
    webhook_secret:
      name: <secret-name>
      key: webhook.secret       # default: webhook.secret
  • Set type to the Git provider used by this Repository, such as github or gitlab.
  • If key is omitted on secret, PAC reads provider.token.
  • If key is omitted on webhook_secret, PAC reads webhook.secret.
  • secret.name and webhook_secret.name can point to the same Secret or to two different ones.

The Secret must live in the same namespace as the Repository resource.

Prerequisites

  • A Git provider account with permission to create a Personal Access Token (PAT) on the repository.
  • A target namespace for the Repository resource.
  • kubectl access to that namespace.

Step 1: Create the Git Access Token

Create a PAT on your Git provider. This token is stored in the Repository namespace and is used by PAC during normal pipeline processing. Keep webhook management permissions in a centralized credential unless you intentionally want each Repository owner to store a token that can create or edit provider webhooks.

ProviderToken typeRepository-local token permissions
GitHubPersonal Access Token (classic)public_repo for public repositories, repo for private repositories. For fine-grained PATs, grant only the repository permissions PAC needs for your workflow, such as repository content read access, commit status write access, and comment write access. Do not grant Webhooks write access to this local token unless it will manage webhooks directly.
GitLabPersonal Access Token (or Project Access Token)api, with normal project access for PAC actions such as reading project data, creating merge request notes, and updating commit statuses. The Repository-local token does not need Maintainer/Owner access solely for webhook registration when a centralized credential is configured.

Copy the token immediately. Most providers display it only once.

If automatic webhook registration is enabled, create a separate centralized credential with webhook management permission. See Centralized webhook registration token.

Step 2: Choose a Webhook Secret

The webhook secret is a shared string between PAC and the Git provider. PAC verifies incoming events against this value.

You can use any sufficiently random string, such as a generated password from your password manager. The same value must be stored in the Kubernetes Secret and configured in the Git provider webhook.

If you want to generate one from the command line, openssl is one option:

openssl rand -hex 16

Example output:

a4b1c2d3e4f5061718293a4b5c6d7e8f

The webhook secret is optional but strongly recommended. Without it, anyone who learns the webhook URL can forge events.

Step 3: Create the Kubernetes Secret

Create one Secret that stores both values under the default keys. Replace:

  • <git-access-token> with the Git provider token from Step 1.

  • <webhook-secret> with the shared webhook secret string from Step 2.

    kubectl create secret generic <secret-name> \
      --from-literal=provider.token='<git-access-token>' \
      --from-literal=webhook.secret='<webhook-secret>' \
      -n <your-namespace>

Example output:

secret/my-repo-auth created

Alternatively, create it from a manifest:

apiVersion: v1
kind: Secret
metadata:
  name: my-repo-auth
  namespace: project-pipelines
type: Opaque
stringData:
  provider.token: glpat-xxxxxxxxxxxxxxxxxxxx
  webhook.secret: a4b1c2d3e4f5061718293a4b5c6d7e8f
kubectl apply -f secret.yaml

Step 4: Reference the Secret from the Repository

In the Repository resource, point both git_provider.secret and git_provider.webhook_secret at the Secret you just created. Because the default keys are used, the key field can be omitted:

apiVersion: pipelinesascode.tekton.dev/v1alpha1
kind: Repository
metadata:
  name: my-repo
  namespace: project-pipelines
spec:
  url: https://gitlab.example.com/team/my-repo
  git_provider:
    type: gitlab
    secret:
      name: my-repo-auth
    webhook_secret:
      name: my-repo-auth

If you stored the credentials under non-default keys, set key explicitly on both fields.

Centralized webhook registration token

For automatic webhook registration, keep high-permission webhook management tokens in labeled Secrets in the webhook registration controller namespace. This is useful when Repository owners should not store a token that can create or edit provider webhooks.

The centralized Secret is only used by the webhook registration controller to register or update the Git provider webhook. PAC still reads the webhook secret from Repository.spec.git_provider.webhook_secret, so each Repository must keep that reference.

The centralized token needs these permissions:

ProviderRequired webhook management permission
GitHubClassic PAT: admin:repo_hook. Fine-grained PAT: target repository Webhooks write permission.
GitLabapi scope, and the token identity must be an instance administrator or have Maintainer/Owner access to the target project.

Create exactly one matching centralized Secret for each provider type and provider URL in the webhook registration controller namespace:

apiVersion: v1
kind: Secret
metadata:
  name: gitlab-webhook-admin
  namespace: <controller-namespace>
  labels:
    pac.tekton.alauda.io/provider-credential: "true"
    pac.tekton.alauda.io/provider-type: gitlab
  annotations:
    pac.tekton.alauda.io/provider-url: https://gitlab.example.com
type: Opaque
stringData:
  provider.token: <token-with-webhook-management-permission>

For GitHub.com, use https://api.github.com as the provider URL. For GitHub Enterprise, use the Enterprise API URL, for example https://github.example.com/api/v3.

Example:

metadata:
  labels:
    pac.tekton.alauda.io/provider-credential: "true"
    pac.tekton.alauda.io/provider-type: github
  annotations:
    pac.tekton.alauda.io/provider-url: https://api.github.com

Matching rules:

  • The Secret must be in the namespace where the webhook registration controller runs. In the default installation this is tekton-pipelines.
  • The Secret must have pac.tekton.alauda.io/provider-credential: "true" so the controller watches it as a centralized credential.
  • provider-type must match spec.git_provider.type.
  • The pac.tekton.alauda.io/provider-url annotation is normalized before matching. For GitLab, https://gitlab.example.com and https://gitlab.example.com/api/v4 both match the same provider. For GitHub Enterprise, use the API URL, for example https://github.example.com/api/v3.
  • If multiple Secrets match the same provider, registration fails with AmbiguousCredential.
  • If spec.git_provider.secret contains a usable token, it is tried first. If that token lacks webhook management permission, the controller retries with the matching centralized Secret.

Verification

Confirm the Secret exists and carries both keys:

kubectl get secret my-repo-auth -n <your-namespace> \
  -o json | jq '.data | keys'

Example output:

["provider.token", "webhook.secret"]

After the Repository resource is created, PAC logs a successful lookup. Tail the controller logs in the PAC namespace:

kubectl logs -n <pac-namespace> -l app=pipelines-as-code-controller --tail=50

An authentication failure ("401 Unauthorized", "invalid token") in the controller logs indicates a wrong or insufficiently-scoped token; see Common Issues for the full troubleshooting checklist.

Updating credentials

Rotate the token by updating the Secret in place:

kubectl create secret generic my-repo-auth \
  --from-literal=provider.token='<new-token>' \
  --from-literal=webhook.secret='<existing-webhook-secret>' \
  -n <your-namespace> \
  --dry-run=client -o yaml | kubectl apply -f -

PAC reads the Secret on every incoming event, so no controller restart is needed. Automatic webhook registration also reacts to changes on directly referenced Repository Secrets without requiring labels on those Secrets.

When a centralized webhook registration credential is updated, the webhook registration controller refreshes Repositories that match either the old or new provider labels and URL. If you remove the centralized credential labels or change the provider URL, existing Repositories that depended on the old credential are reconciled again and will report the current credential state.

Next steps