Table of Contents
- Introduction
- Course Information
- Information about the Project
- What I have done as part of the project
- Task 1 - Setup of GitHub Actions and implement a workflow
- Task 2 - Building a Tekton Pipeline
- Task 3 - Adding GitHub Triggers
- Task 4 - Using Tekton Continous Delivery Catalog
- Task 5 - Integrating Linting and Unit Test Automation
- Task 6 - Building an Image
- Task 7 - Deploy to OpenShift
- Getting Started
- Contact
This repository was created as part of IBM's "Continuous Integration and Delivery (CI/CD)" course.
It's a project about building a CI/CD pipeline.
Much of the code was cloned from the IBM repository: https://github.com/ibm-developer-skills-network/wtecc-CICD_PracticeCode
Preview images of the project:
Title: Continuous Integration and Delivery (CI/CD)
Type: Practice Project
Course Provider: IBM
- Client: Myself
- Project Goal: Building a CI/CD pipeline. Gain a deeper understanding of Continous Integration and Continous Delivery.
- Number of Project Participants: 1 (Cloned repository of IBM. Developed the rest on my own)
- Time Period: November - December, 2024
- Industry / Area: DevOps
- Role: Developer
- Languages: English
- Result: CI/CD pipeline successfully built. Improved understanding of implementing Continous Integration and Continous Delivery.
With regard to my role:
- CI/CD Tool: GitHub Actions
- CI/CD Tool: Tekton
- Container Orchestration: Kubernetes
- Container Orchestration: Red Hat OpenShift
- IBM Cloud IDE (based on Theia and Container)
First implemented the setup for GitHub Actions: The creation of a .github/workflows folder with a workflow YML file.
The name of the workflow as well as the events, the job and the runner including the container were defined.
If you check the Actions tab on the GitHub website, you will see failed workflows, as the workflow has been triggered but not yet fully implemented.
After the workflow file was created, the steps were added:
The changes were pushed into the repository. This triggered the workflow again.
It is now running successfully thanks to the implemented steps:
After clicking on the build job, exact details of the individual steps can be viewed:
The first step of the task was to create a traditional Hello World program / pipeline in Tekton.
The Tekton object "Task" is used for this.
According to the Tekton documentation, a Task is a collection of Steps that you define and arrange in a specific order of execution as part of your continuous integration flow.
The corresponding Task has been implemented in the tasks.yaml file:
It is then applied to the cluster with the following command:
kubectl apply -f tasks.yaml
The Task has been successfully created:
Next, a Tekton object called "Pipeline" is created that uses and executes the Task object.
The implementation is in the pipeline.yaml:
It is then applied to the cluster with the following command:
kubectl apply -f pipeline.yaml
The Pipeline has been successfully created:
The Pipeline is now executed with the following command:
tkn pipeline start --showlog hello-world-pipeline
Output of the Pipeline:
Parameters are now added to make the pipeline more flexible.
Both the task and the pipeline are changed for this.
The modified tasks.yaml file:
The changes are then applied to the cluster with the following command:
kubectl apply -f tasks.yaml
The Task has been successfully created:
The modified pipeline.yaml file:
The changes are then applied to the cluster with the following command:
kubectl apply -f pipeline.yaml
The Pipeline has been successfully created:
The Pipeline is now executed with the following command:
tkn pipeline start hello-world-pipeline \
--showlog \
-p message="Hello Tekton! I added params to pipeline!"
Output of the Pipeline:
To embellish the whole thing a little, another Pipeline is added: cd-pipeline with checkout Task.
The checkout task with parameters and the clone command have been added to the tasks.yaml file:
The output after applying to the cluster with the following command:
kubectl apply -f tasks.yaml
The pipeline.yaml file has been extended by the cd-pipeline:
The output after applying to the cluster with the following command:
kubectl apply -f pipeline.yaml
If you execute the new Pipeline with the following command, the output appears:
tkn pipeline start cd-pipeline \
--showlog \
-p repo-url="https://github.com/christian-schw/cicd-practice-project.git" \
-p branch="main"
As a final exercise in this section, four placeholder Tasks (lint, tests, build and deploy) are added to the cd-pipeline.
The echo Task already created is used as a placeholder.
The placeholders are replaced in the following sections below.
The modified pipeline.yaml:
The output after applying the changes to the cluster and executing the following command:
tkn pipeline start cd-pipeline \
--showlog \
-p repo-url="https://github.com/christian-schw/cicd-practice-project.git" \
-p branch="main"
Since it is tedious and offers limited possibilities to run the pipeline manually, Tekton objects EventListener, TriggerBinding and TriggerTemplate are created.
This makes it possible for the pipeline to be started automatically by external events (e.g. changes in the GitHub repository).
The corresponding files are located in the folder: ../labs/02_add_git_trigger/
First, the EventListener was implemented to be able to listen to events on GitHub:
The output after applying to the cluster with the following command:
kubectl apply -f eventlistener.yaml
Next, the TriggerBinding was implemented to be able to bind the incoming data from the event to pass on to the pipeline:
The output after applying to the cluster with the following command:
kubectl apply -f triggerbinding.yaml
The TriggerTemplate takes the parameters passed in from the TriggerBinding and creates a PipelineRun to start the pipeline:
The output after applying to the cluster with the following command:
kubectl apply -f triggertemplate.yaml
To test the Pipeline Run, the curl command is used (Note: localhost port of IBM Cloud IDE is 8090):
curl -X POST http://localhost:8090 \
-H 'Content-Type: application/json' \
-d '{"ref":"main","repository":{"url":"https://github.com/christian-schw/cicd-practice-project.git"}}'
The output:
The red marked PipelineRun is the pipeline in this task. Everything works!
The self-created clone task is very small and hardly robust.
To improve the whole thing, a prefabricated task in the Tekton Hub is integrated into our pipeline.
With the help of the Tekton CLI, this task is installed in our cluster in the current active namespace:
The task requires two inputs:
- The URL of a Git repo to clone ('url' param)
- A workspace / disk volume that can be shared across tasks ('output' param)
To create the workspace, the PersistentVolumeClaim file (pvc.yaml) already predefined by the IBM course is used:
The output after applying to the cluster with the following command:
kubectl apply -f pvc.yaml
This persistent volume can now be referenced by its name 'pipelinerun-pvc' when creating workspaces for the Tekton tasks.
The pipeline.yaml is then changed so that the Tekton Hub Task is now used instead of the self-created task.
At the same time, the workspace is defined (as a required parameter according to Tekton Hub):
The output after applying to the cluster with the following command:
kubectl apply -f pipeline.yaml
A PipelineRun is then created to run the pipeline:
tkn pipeline start cd-pipeline \
-p repo-url="https://github.com/christian-schw/cicd-practice-project.git" \
-p branch="main" \
-w name=pipeline-workspace,claimName=pipelinerun-pvc \
--showlog
The logs already show significantly more information than before:
The pipeline was successfully executed and the Tekton Hub Task integrated:
Two further tasks in the pipeline (folder: /labs/04_unit_test_automation/) are replaced, which previously acted as placeholders: lint and tests.
First the lint task.
Flake8 is used for the linting. There is already a predefined task for this in the Tekton Hub, which will be installed:
The existing task reference in the pipeline is adapted and the corresponding required task parameters are implemented:
The output after applying to the cluster with the following command:
kubectl apply -f pipeline.yaml
If you run the pipeline with the following command, you will see that the new task is working and is being executed:
tkn pipeline start cd-pipeline \
-p repo-url="https://github.com/christian-schw/cicd-practice-project.git" \
-p branch="main" \
-w name=pipeline-workspace,claimName=pipelinerun-pvc \
--showlog
Linting is done, now the unit test task will be implemented.
The testing framework nose is used.
However, there is nothing ready-made for this in the Tekton Hub.
This means that I have to define this task myself:
The existing task reference in the pipeline is adapted and the corresponding required task parameters are implemented:
The changes are then applied to the cluster with the following command:
kubectl apply -f pipeline.yaml
The output after running the pipeline with the following command:
tkn pipeline start cd-pipeline \
-p repo-url="https://github.com/christian-schw/cicd-practice-project.git" \
-p branch="main" \
-w name=pipeline-workspace,claimName=pipelinerun-pvc \
--showlog
The status of the PipelineRun object is succeeded.
Everything works as intended!
The next placeholder task in the pipeline to be replaced is the build task.
Before the application can be deployed, it's necessary to build a Docker image and push it to an image registry (in this case: OpenShift Image Registry).
The Tekton Hub buildah task is used for this.
First of all, it is necessary to check whether the task has already been installed in the cluster.
This step was previously omitted in the previous tasks (for learning reasons).
Tasks that are available for pipelines in the entire cluster are called ClusterTasks in Tekton.
According to the Tekton documentation, ClusterTasks are deprecated and cluster resolvers should be used instead.
A ClusterTask is used / required in the practice project, so a ClusterTask is also used here.
The output after running the pipeline with the following command:
tkn clustertask ls
The buildah task is listed. This means that it has already been installed and can be used for the pipeline.
The task reference in the pipeline is then changed to the buildah task (folder: /labs/05_build_an_image/):
The changes are then applied to the cluster with the following command:
kubectl apply -f pipeline.yaml
It has also been checked whether the PVC for the workspace exists.
The output:
The extended pipeline is now executed with the following command and the logs are examined:
tkn pipeline start cd-pipeline \
-p repo-url="https://github.com/christian-schw/cicd-practice-project.git" \
-p branch=main \
-p build-image=image-registry.openshift-image-registry.svc:5000/$SN_ICR_NAMESPACE/tekton-lab:latest \
-w name=pipeline-workspace,claimName=pipelinerun-pvc \
--showlog
To make sure that everything worked, we also check whether the image exists in the OpenShift image registry - and yes, it does! Everything fits.
The last step of this pipeline: Deploy the Docker image to an OpenShift cluster.
There is an already defined task for this in the Tekton Hub: openshift-client.
First check whether the (cluster) task openshift-client is already installed.
The output after the following command:
tkn clustertask ls
It's already installed.
The task reference in the pipeline is then changed to the openshift-client task (folder: /labs/06_deploy_to_kubernetes/):
The extended pipeline is now executed with the following command and the logs are examined:
tkn pipeline start cd-pipeline \
-p repo-url="https://github.com/christian-schw/cicd-practice-project.git" \
-p branch=main \
-p app-name=hitcounter \
-p build-image=image-registry.openshift-image-registry.svc:5000/$SN_ICR_NAMESPACE/tekton-lab:latest \
-w name=pipeline-workspace,claimName=pipelinerun-pvc \
--showlog
Finally, check whether the deployment has worked.
The pod of the deployment is running which means the application has been successfully deployed!
The pipeline is now fully implemented and the practice project is complete.
The code was only executable with the help of the IBM Cloud IDE.
The IDE had many necessary tools and accesses preconfigured. These include, for example, Kubernetes installation or IBM Cloud Container Registry.
If you have any questions, please feel free to reach out via email: christian-schwanse (at) gmx.net























































