This folder includes all the resources that are used to setup and run CI for Tekton using Tekton. A general concept is available with diagrams to explain the general setup.
The CI system provides the following facilities:
- Run Tekton tasks or pipelines as GitHub checks, in response to pull request events and specific comments
- Update the status of the check on GitHub when a job is started and when it completes
- Filter the jobs to be executed based on the content of the PR
All the resources used for CI are deployed in the tektonci
namespace in the
dogfooding
cluster.
The resources in eventlistener.yaml
and ingress.yaml
set up the service and
ingress that are configured in repository specific webhook settings on GitHub.
The Event Listener uses a secret called ci-webhook
:
apiVersion: v1
data:
secret: [Base64 encoded secret specified when creating the WebHook in GitHub]
kind: Secret
metadata:
name: ci-webhook
namespace: tektonci
type: Opaque
A domain name webhook-draft.ci.dogfooding.tekton.dev
is configured manually
in Netifly to point to the public IP from the ingress.
The ingress in annotated so that cert-manager automatically obtains a
certificate from Let's Encrypt and configures HTTPs termination on the load
balancer.
The configuration on GitHub side is manual. Two events are required:
- pull_request
- issue_comment
If more events are added to the webhook, they will be filtered out by the GitHub interceptor.
Triggers in the eventlistener.yaml
that are not filtered by project apply to
all project with the webhook registered. They can be used to jobs to be applied
across the org. Templates that apply to all repos are defined in all-template.yaml
.
The project specific template defines which CI Jobs are available for execution.
For tektoncd/plumbing
they are defined in plumbing-template.yaml
.
Eventually this template needs to be split up in reusable parts and project
specific ones, so to reduce boiler-plate code and simplify the configuration of
CI jobs.
The Tasks and Pipelines used to define the CI Job must be available in the
tektonci
namespace. There is no facility yet to avoid name conflicts, so
projects should namespace job names by including the project name in the check
names.
The comment trigger requires a custom interceptor add-pr-body to enrich the event with the details of the pull request where the comment was made.
The ability to filter events based on the user requires a custom interceptor add-team-members to enrich the event payload with details about members of the GitHub org and of the repo maintainer team.
Tekton is deployed the dogfooding
cluster with cloud events enabled.
All cloud events are sent to the tekton-events
event listener. CEL filters are used to select events from CI jobs TaskRuns
.
When a start, failed or succeeded event is received for a CI job, the
github-template.yaml
is triggered,
which takes care of updating the check status on GitHub side accordingly.
The existing overlays and bindings produce a set of parameters available to CI jobs via the trigger templates. This interface is maintained consistent across CI jobs and trigger templates:
Parameter Name | Description | Source | Notes |
---|---|---|---|
buildUUID | Unique GitHub Event ID | X-GitHub-Delivery header |
base binding |
package | GitHub org/repo | repository.full_name | base binding |
gitRepository | GitHub repo HTML URL | repository.html_url | base binding |
gitRevision | Git rev of the HEAD commit | pull_request.head.sha | Added by add_pr_body for comments |
gitCloneDepth | Number of commits + 1 | extensions.git_clone_depth | Added by an overlay |
pullRequestNumber | Pull request number | pull_request.number | Added by add_pr_body or overlay for comments |
pullRequestURL | Pull request HTML URL | pull_request.html_url | |
gitHubCommand | GitHub comment body | comment.body | Only available for comments, default for PR |
labels | GitHub labels for PR | pull_request.labels | Only available for PRs, missing for comment |
A new CI Job requires the following:
- a unique GitHub check name, used to identify the check on GitHub side and to trigger the job on demand
- one or more
Tasks
to be executed - a
Pipeline
that maps the CI Job Interface to theTasks
- a
PipelineRun
to be added to aTriggerTemplate
that runs thePipeline
with the right metadata and parameters from the event
The check name is build according to the following convention:
TRIGGER[-PROJECT]-TEST_NAME
The TRIGGER
can be:
pull
for jobs executed against a pull requestperiodic[-BRANCH]
for periodic jobs executed against aBRANCH
TheBRANCH
part can be omitted if the branch is the main one for the repositorypost
for jobs executed after a change is merged
The PROJECT
part is optional, so job that are identical across repositories
shall not include it in the name.
Example of job names:
pull-pipeline-build-tests
pull-triggers-go-coverage
periodic-dashboard-integration-tests
post-catalog-publish-tasks
pull-check-kind-label
Tasks should be from the catalog when possible. Non catalog tasks shall be stored
in the tektoncd/plumbing
repo under tekton/ci/jobs
if they are applicable
across repos, or in the tekton
folder of the specific repository.
NOTE Resources from the plumbing repo are deployed automatically to the dogfooding
cluster. Tasks from the catalog and from other repos must be deployed and updated
manually for now.
Common CI pipelines shall be stored in the tektoncd/plumbing
repo under
tekton/ci/jobs
, ideally one YAML file per pipeline.
The current structure of pipelines is based on Conditions
; it will be migrated
to when
expressions once they become available in a release.
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: [PIPELINE NAME]
namespace: tektonci
spec:
params:
- name: checkName
description: The name of the GitHub check that this pipeline is used for
- name: gitCloneDepth
description: Number of commits in the change + 1
- name: fileFilterRegex
description: Names regex to be matched in the list of modified files
- name: gitHubCommand
description: The command that was used to trigger testing
# Additional parameters may be added here as required, as long as the
# pipeline run will be in a position to supply them based on the CI interface
resources:
- name: source
type: git
tasks:
- name: [CI JOB specific name]
conditions:
- conditionRef: "check-git-files-changed"
params:
- name: gitCloneDepth
value: $(params.gitCloneDepth)
- name: regex
value: $(params.fileFilterRegex)
resources:
- name: source
resource: source
- conditionRef: "check-name-matches"
params:
- name: gitHubCommand
value: $(params.gitHubCommand)
- name: checkName
value: $(params.checkName)
taskRef:
name: [CI JOB Task Ref]
resources:
inputs:
- name: source
resource: source
In case the CI Job is made of multiple tasks, all should run after an initial one to which conditions are applied.
The check-name-matches
condition is required for the CI job to
excuted on demand via the /test [regex]
command.
The check-git-files-changed
condition is optional, it is used to only execute
the CI job when relevant files have been modified. This condition uses a
PipelineResource
of type git
. Plan is to migrate to a workspace eventually.
The PipelineRun
is added to the relevant TriggerTemplate
in the
tektoncd/plumbing
repo under tekton/ci/templates
. The all-template.yaml
is used for jobs that are shared across repos. The REPO-template.yaml
ones are used for specific repos.
The event listener will trigger the correct template based on the event.
The PipelineRun
must define specific metadata for the conditions and the
downstream CEL filters to work correctly.
- apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: CHECK-NAME-$(uid) # uid *MUST* be used here. The name is for information only.
labels:
tekton.dev/kind: ci
tekton.dev/check-name: CHECK-NAME # *MUST* be the GitHub check name
tekton.dev/pr-number: $(tt.params.pullRequestNumber)
prow.k8s.io/build-id: $(tt.params.buildUUID)
annotations:
tekton.dev/gitRevision: "$(tt.params.gitRevision)"
tekton.dev/gitURL: "$(tt.params.gitRepository)"
spec:
serviceAccountName: tekton-ci-jobs
pipelineRef:
name: PIPELINE_NAME # The name of the CI pipeline
params:
- name: checkName
value: CHECK-NAME # *MUST* be the GitHub check name
- name: pullRequestNumber
value: $(tt.params.pullRequestNumber)
- name: gitCloneDepth
value: $(tt.params.gitCloneDepth)
- name: fileFilterRegex
value: "some/relevant/path/**" # A RegExp to match all relevant files
# The match is executed roughly follows:
# git diff-tree --no-commit-id --name-only -r HEAD "$(params.gitCloneDepth) - 1" | \
# grep -E '$(params.fileFilterRegex)
- name: gitHubCommand
value: $(tt.params.gitHubCommand)
# Extra parameters required by the pipeline shall be passed here
resources:
- name: source
resourceSpec: # Pipeline resources *MUST* be embedded
type: git
params:
- name: revision
value: $(tt.params.gitRevision)
- name: url
value: $(tt.params.gitRepository)
- name: depth
value: $(tt.params.gitCloneDepth)
NOTE The naming convention for labels and annotations may change in future
as the tekton.dev
namespace has been reserved for Tekton itself only.
If a TriggerTemplate
for a specific repository does not exists yet, it must be
created under tekton/ci/templates
and named REPO-template.yaml
.
When a new trigger template is added, the event listener needs to be updated to
trigger the new template for the right events.
A good starting point is to look at the two triggers already defined for the
plumbing
repo and replicate them for the new repo.
To react to pull requests:
triggers:
- name: plumbing-pull-request-ci
interceptors:
- github:
secretRef:
secretName: ci-webhook
secretKey: secret
eventTypes:
- pull_request
- cel:
filter: >-
body.repository.full_name == 'tektoncd/plumbing' &&
(body.action == 'opened' || body.action == 'synchronize')
overlays:
- key: extensions.git_clone_depth
expression: "string(body.pull_request.commits + 1.0)"
bindings:
- ref: tekton-ci-github-base
- ref: tekton-ci-webhook-pull-request
- ref: tekton-ci-clone-depth
- ref: tekton-ci-webhook-pr-labels
template:
name: tekton-plumbing-ci-pipeline
To react to issue comments:
- name: all-comment-ci
interceptors:
- github:
secretRef:
secretName: ci-webhook
secretKey: secret
eventTypes:
- issue_comment
- cel:
filter: >-
body.repository.full_name.startsWith('tektoncd/') &&
body.repository.name in ['plumbing', 'pipeline', 'triggers', 'cli', 'dashboard', 'catalog', 'hub'] &&
body.action == 'created' &&
'pull_request' in body.issue &&
body.issue.state == 'open' &&
body.comment.body.matches('^/test($| [^ ]*[ ]*$)')
overlays:
- key: add_pr_body.pull_request_url
expression: "body.issue.pull_request.url"
- webhook:
objectRef:
kind: Service
name: add-pr-body
apiVersion: v1
namespace: tektonci
- cel:
overlays:
- key: extensions.git_clone_depth
expression: "string(body.add_pr_body.pull_request_body.commits + 1.0)"
bindings:
- ref: tekton-ci-github-base
- ref: tekton-ci-webhook-comment
- ref: tekton-ci-clone-depth
- ref: tekton-ci-webhook-pr-labels
template:
name: tekton-plumbing-ci-pipeline