{"id":5819,"date":"2024-03-18T11:01:20","date_gmt":"2024-03-18T10:01:20","guid":{"rendered":"https:\/\/onlu.ch\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/"},"modified":"2025-07-18T12:02:05","modified_gmt":"2025-07-18T10:02:05","slug":"tekton-cicd-example-project-pipeline-design-implementation-part-2-3","status":"publish","type":"post","link":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/","title":{"rendered":"Tekton CICD example project &#8211; Pipeline design &amp; implementation (part 2\/3)"},"content":{"rendered":"\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:66.66%\">\n<p>In this second part of the Tekton CICD example project, we&#8217;ll delve into the design and implementation of the CI\/CD pipeline. We&#8217;ll walk through an example project, demonstrating how to structure and orchestrate the various stages of the pipeline to streamline the software delivery lifecycle. <\/p>\n\n\n\n<p>Our example project focuses on a simple application built with Go, a popular programming language for building scalable and efficient software. We&#8217;ll explore how Tekton pipelines can be leveraged to automate tasks such as linting, uni- and integration testing, building container images, packaging helm charts, and deploying to desired environments. <\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:33.33%\">\n<figure class=\"wp-block-image size-full is-resized\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon.png\" alt=\"\" class=\"wp-image-2490\" style=\"width:266px;height:auto\" srcset=\"https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon.png 1024w, https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon-300x300.png 300w, https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon-150x150.png 150w, https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon-768x768.png 768w, https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon-650x650.png 650w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">1 Pipeline overview<\/h3>\n\n\n\n<p>Let us have a look at a common pattern of a pipeline strategy you can face.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Feature branch<\/h4>\n\n\n\n<p>When committing changes to a feature branch, the pipeline initiates with the following stages:<br\/>1. <strong>Notify GitHub<\/strong>: This very first step will notify github via status-api the beginning of a build.<br\/>2. <strong>Lint and test<\/strong>: The code changes are linted and subjected to unit or integration tests.<br\/>3. <strong>Go build<\/strong>: If the linting and tests pass successfully, the code is built using the Go compiler.<br\/>4. <strong>Notify GitHub<\/strong>: This last step will notify github via status-api the status of the build.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Main branch<\/h4>\n\n\n\n<p>Commits to the main branch initiate the following stages:<\/p>\n\n\n\n<p>1.  <strong>Notify GitHub<\/strong>: This very first step will notify github via status-api the beginning of a build.<br\/>2.  <strong>Lint and test<\/strong>: The code changes are lined and subjected to unit or integration tests.<br\/>3.  <strong>Go build<\/strong>: If the linting and tests pass successfully, the code is built using the Go compiler.<br\/>4.  <strong>Container image build<\/strong>: The built code is containerized into a container image tagged as the <strong>latest<\/strong> version and pushed to a container registry.<br\/>5.  <strong>Helm chart package<\/strong>: The helmet chart is packaged and published as <strong>latest<\/strong> to a central location.<br\/>6.  <strong>Deploy to dev stage<\/strong>: This step is used to deploy the <strong>latest<\/strong> version into the <strong>dev<\/strong> namespace on the current kubernetes cluster.<br\/>7.  <strong>Notify GitHub<\/strong>: This last step will notify github via status-api the status of the build.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Git tag created<\/h4>\n\n\n\n<p>When a Git tag is created, indicating a release version, the following stages are executed:<br\/>1. <strong>Notify GitHub<\/strong>: This very first step will notify github via status-api the beginning of a build<br\/>2. <strong>Lint and test<\/strong>: The code changes are lined and subjected to unit or integration tests.  <br\/>3.  <strong>Go build<\/strong>: If the linting and tests pass successfully, the code is built using the Go compiler.<br\/>4.  <strong>Container image build<\/strong>: The built code is containerized into a container image tagged as the <strong>latest<\/strong> version and pushed to a container registry.<br\/>5.  <strong>Helm chart package<\/strong>: The helm chart versioned based on the created <strong>git-tag<\/strong> is packaged and published to a central location.<br\/>6.  <strong>Deploy to qa stage<\/strong>: This step is used to deploy the <strong>git-tag<\/strong> version into the <strong>qa<\/strong> namespace on the current kubernetes cluster.<br\/>7.  <strong>Notify GitHub<\/strong>: This last step will notify github via status-api the status of the build.<\/p>\n<\/div><\/div>\n\n<div style=\"height:63px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"889\" height=\"385\" src=\"https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/diagram.drawio-1.png\" alt=\"\" class=\"wp-image-2468\" srcset=\"https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/diagram.drawio-1.png 889w, https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/diagram.drawio-1-300x130.png 300w, https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/diagram.drawio-1-768x333.png 768w, https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/diagram.drawio-1-650x281.png 650w\" sizes=\"(max-width: 889px) 100vw, 889px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2 Pipeline implementation<\/h3>\n\n\n\n<p>Now that we have designed our CI\/CD pipeline using Tekton, let&#8217;s dive into its implementation details. Our pipeline is structured to automate the build, test, and deployment processes for a Go-based application. Below, we&#8217;ll explore each component and configuration file involved in our pipeline setup.  <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Directory structure<\/h4>\n\n\n\n<pre class=\"wp-block-code\">\n.\n|-- pipelines\n|   `-- 7.02-go-pipeline.yaml\n|-- rbac\n|   |-- 7.02-rbac-deployer.yaml\n|   `-- 7.02-rbac-trigger.yaml\n|-- secrets\n|   |-- 7.02-github-interceptor-secret.yaml\n|   |-- 7.02-github-repo-secret.yaml\n|   |-- 7.02-github-status-api-secret.yaml\n|   `-- 7.02-quay-secret.yaml\n|-- tasks\n|   `-- 7.02-helm-build-push.yaml\n`-- trigger\n    |-- 7.02-eventlistener.yaml\n    |-- 7.02-tb.yaml\n    |-- 7.02-trigger.yaml\n    `-- 7.02-tt.yaml\n<\/pre>\n\n\n\n<p>.<strong>\/pipelines<\/strong>: Contains the Tekton pipeline configuration file. <br\/>.<strong>\/rbac<\/strong>: Contains the rbac for the trigger and the deployer service-account <br\/>.<strong>\/secrets<\/strong>: Includes secrets such as for quay &amp; github. <br\/><strong>.\/tasks<\/strong>: Holds self-maintained task definitions used within the pipeline. <br\/><strong>.\/trigger<\/strong>: Contains configuration files for triggering pipeline execution.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3 Pipeline definition<\/h3>\n\n\n\n<p>Our pipeline configuration is defined in the <code>7.02-go-pipeline.yaml<\/code> file. This file outlines the workflow of our CI\/CD pipeline. <\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary><code>7.02-go-pipeline.yaml<\/code><\/summary>\n<pre class=\"wp-block-code\">\napiVersion: tekton.dev\/v1beta1\nkind: Pipeline\nmetadata:\n  name: 7-02-go-pipeline\n  namespace: default\nspec:\n  workspaces:\n    - name: shared-workspace\n    - name: helm-workspace\n    - name: dockerconfig-ws\n  params:\n    - name: git-url\n      description: Git Repo to checkout the desired git repository\n      type: string\n    - name: git-revision\n      description: Revision to be used from repo of the code for building and testing\n      type: string\n      default: main\n    - name: git-repo-full-name\n      description: Used to leverage git status api\n      type: string\n    - name: is-main-branch\n      description: Flag to be used for conditional pipeline executing (CI CD up to dev namespace)\n      type: string\n      default: false\n    - name: is-git-tag\n      description: Flag to be used for conditional pipeline executing (CI CD up to qa namespace)\n      type: string\n      default: false\n    - name: image-repository\n      description: Image registry where images are going to be pushed\n      type: string\n      default: quay.io\/christoph_linse\n    - name: app-name\n      description: App name to be used for container-image and helm-chart build\n      type: string\n    - name: image-tag\n      description: Container-image tag to be used\n      type: string\n      default: latest\n    - name: chart-tag\n      description: Default helm-chart tag to be used\n      type: string\n      default: 1.0.0\n    - name: golang-version\n      description: Version of golang to be used\n      type: string\n      default: \"1.22\"\n  tasks:\n    - name: notify-github\n      taskRef:\n        name: github-set-status\n      params:\n        - name: REPO_FULL_NAME\n          value: \"$(params.git-repo-full-name)\"\n        - name: SHA\n          value: \"$(params.git-revision)\"\n        - name: DESCRIPTION\n          value: \"Build has started\"\n        - name: STATE\n          value: pending\n        - name: TARGET_URL\n          value: \"http:\/\/localhost:9097\/#\/pipelineruns\"\n    - name: fetch-source\n      taskRef:\n        name: git-clone\n      params:\n        - name: url\n          value: $(params.git-url)\n        - name: deleteExisting\n          value: \"true\"\n        - name: revision\n          value: $(params.git-revision)\n      workspaces:\n        - name: output\n          workspace: shared-workspace\n    - name: test-code\n      taskRef:\n        name: golang-test\n      params:\n        - name: package\n          value: \"$(params.app-name)\"\n        - name: version\n          value: \"$(params.golang-version)\"\n      workspaces:\n        - name: source\n          workspace: shared-workspace\n      runAfter:\n        - fetch-source\n    - name: lint-code\n      taskRef:\n        name: golangci-lint\n      params:\n        - name: package\n          value: \"$(params.app-name)\"\n        - name: flags\n          value: --verbose\n        - name: version\n          value: \"v$(params.golang-version)\"\n      workspaces:\n        - name: source\n          workspace: shared-workspace\n      runAfter:\n        - fetch-source\n    - name: build-image\n      taskRef:\n        name: buildah\n      params:\n        - name: IMAGE\n          value: $(params.image-repository)\/$(params.app-name):$(params.image-tag)\n      workspaces:\n        - name: source\n          workspace: shared-workspace\n        - name: dockerconfig\n          workspace: dockerconfig-ws\n      runAfter:\n        - lint-code\n        - test-code\n      when:\n        - input: \"true\"\n          operator: in\n          values: [ \"$(params.is-main-branch)\", \"$(params.is-git-tag)\" ]\n    - name: build-helm\n      taskRef:\n        name: 7-02-helm-build-push\n      params:\n        - name: HELM_CHART_NAME\n          value: \"$(params.app-name)\"\n        - name: HELM_CHART_TAG\n          value: \"$(params.chart-tag)\"\n      workspaces:\n        - name: source\n          workspace: shared-workspace\n        - name: helm-repo\n          workspace: helm-workspace\n      runAfter:\n        - build-image\n      when:\n        - input: \"true\"\n          operator: in\n          values: [ \"$(params.is-main-branch)\", \"$(params.is-git-tag)\" ]\n    - name: deploy-dev\n      taskRef:\n        name: helm-upgrade-from-repo\n      params:\n        - name: helm_repo\n          value: https:\/\/c-linse.github.io\/tekton-course-charts\n        - name: chart_name\n          value: \"tekton-course-charts\/$(params.app-name)\"\n        - name: release_version\n          value: \"$(params.chart-tag)\"\n        - name: release_name\n          value: \"$(params.app-name)\"\n        - name: release_namespace\n          value: dev\n      runAfter:\n        - build-helm\n      when:\n        - input: \"true\"\n          operator: in\n          values: [ \"$(params.is-main-branch)\" ]\n    - name: deploy-qa\n      taskRef:\n        name: helm-upgrade-from-repo\n      params:\n        - name: helm_repo\n          value: https:\/\/c-linse.github.io\/tekton-course-charts\n        - name: chart_name\n          value: \"tekton-course-charts\/$(params.app-name)\"\n        - name: release_version\n          value: \"$(params.chart-tag)\"\n        - name: release_name\n          value: \"$(params.app-name)\"\n        - name: release_namespace\n          value: qa\n      runAfter:\n        - build-helm\n      when:\n        - input: \"true\"\n          operator: in\n          values: [ \"$(params.is-git-tag)\" ]\n  finally:\n    - name: notify-git-state-success\n      taskRef:\n        name: github-set-status\n      when:\n        - input: \"$(tasks.status)\"\n          operator: notin\n          values: [ \"Failed\" ]\n      params:\n        - name: REPO_FULL_NAME\n          value: \"$(params.git-repo-full-name)\"\n        - name: SHA\n          value: \"$(params.git-revision)\"\n        - name: DESCRIPTION\n          value: \"Build has been successful\"\n        - name: STATE\n          value: success\n        - name: TARGET_URL\n          value: \"http:\/\/localhost:9097\/#\/pipelineruns\"\n<\/pre>\n<\/details>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"key-features-of-go-pipeline\">Key features of go-pipeline:<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>GitHub repository integration<\/strong>: The pipeline fetches source code from a git repository, enabling seamless integration with version control systems such as GitHub.<\/li>\n\n\n\n<li><strong>Linting and testing<\/strong>: Utilizes linting to ensure code quality by identifying linting errors and potential issues in the codebase and performs testing like unit and integration tests.<\/li>\n\n\n\n<li><strong>Container image building<\/strong>: Builds container images containing the Go application, facilitating containerization for deployment across various environments.<\/li>\n\n\n\n<li><strong>Helm chart packaging<\/strong>: Packages the containerized applications manifests into a helm chart, simplifying the deployment process in kubernetes environments.<\/li>\n\n\n\n<li><strong>Deployment dev\/qa<\/strong>: Deploys into the same cluster into the <strong>dev<\/strong> or <strong>qa<\/strong> namespace depending on the git revision (main branch or git tag)<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"customizable-parameters\">Customizable parameters:<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>git-url<\/strong>: Git repo to checkout the desired code base<\/li>\n\n\n\n<li><strong>git-revision<\/strong>: Revision to be used from repo of the code<\/li>\n\n\n\n<li><strong>git-repo-full-name<\/strong>: Used to leverage git status api<\/li>\n\n\n\n<li><strong>is-main-branch<\/strong>: Flag to be used for conditional pipeline executing (CI CD up to dev namespace)<\/li>\n\n\n\n<li><strong>is-git-tag<\/strong>: Flag to be used for conditional pipeline executing (CI CD up to qa namespace)<\/li>\n\n\n\n<li><strong>image-repository<\/strong>: Image registry where images are going to be pushed to<\/li>\n\n\n\n<li><strong>app-name<\/strong>: App name to be used for container-image and helm-chart build<\/li>\n\n\n\n<li><strong>image-tag<\/strong>: Container-image tag to be used<\/li>\n\n\n\n<li><strong>chart-tag<\/strong>: Default helm-chart tag to be used<\/li>\n\n\n\n<li><strong>golang-version<\/strong>: Version of golang to be used<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"conditional-execution\">Conditional execution:<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The pipeline includes conditional logic to differentiate between feature branch commits and main branch commits. Certain tasks, such as container image building and helm chart packaging, are executed only for commits to the main branch and on git tag creation, optimizing resource usage and ensuring efficient pipeline execution.   <\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4 Task installation<\/h3>\n\n\n\n<p>To install Tekton tasks on the GKE cluster, let&#8217;s have a look at the provided script. These task are beeing used by the tekton pipeline we have just defined. <\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Task Installation<\/summary>\n<pre class=\"wp-block-code\">\ntkn hub install task git-clone --version 0.9 --namespace default\ntkn hub install task golangci-lint --version 0.2 --namespace default\ntkn hub install task golang-test --version 0.2 --namespace default\ntkn hub install task buildah --version 0.7 --namespace default\ntkn hub install task helm-upgrade-from-repo --version 0.2 --namespace default\ntkn hub install task github-set-status --version 0.4 --namespace default\n<\/pre>\n<\/details>\n\n\n\n<h3 class=\"wp-block-heading\">5 Custom helmet task<\/h3>\n\n\n\n<p>The <em>helm-build-push<\/em> task is a custom Tekton task designed to lint and package a Helm chart into a tar.gz file and push it to a<br\/>web server. This task streamlines the process of packaging and publishing helm charts, facilitating the deployment of<br\/>applications in Kubernetes environments. <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Parameters<\/h4>\n\n\n\n<p><strong>HELM_CHART_NAME<\/strong>: Defines the name of the helmet chart to be packaged and pushed.<\/p>\n\n\n\n<p><strong>HELM_CHART_TAG<\/strong>: Specifies the tag to be used for the helmet chart version.<\/p>\n\n\n\n<p><strong>HELM_TARGET_ARTIFACTORY<\/strong>: Specifies the server URL to which the helm chart will be pushed.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Steps<\/h4>\n\n\n\n<p>1. <strong>helm-lint<\/strong>: Lint the Helm chart to dectect potential linting issues<\/p>\n\n\n\n<p>2. <strong>helm-package<\/strong>: Packages the helm chart into a tar.gz file using the specified chart name and version.<\/p>\n\n\n\n<p>3. <strong>helm-publish<\/strong>: Clones the target artifact repository, copies the packaged chart, updates the repository index, commits the changes, and pushes them to the remote repository.<\/p>\n\n\n\n<p>The task looks like the following:<\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>7.02-helm-build-push.yaml<\/summary>\n<pre class=\"wp-block-code\">\napiVersion: tekton.dev\/v1\nkind: Task\nmetadata:\n  name: 7-02-helm-build-push\nspec:\n  description: This task run helm lint and packages a helm chart to tar.gz and pushes it into a webserver\n  params:\n    - name: HELM_CHART_NAME\n      description: Chart name to use for packaging and pushing\n      type: string\n    - name: HELM_CHART_TAG\n      description: Tag to be used for helm build and push\n      type: string\n    - name: HELM_TARGET_ARTIFACTORY\n      description: Server to be used for publishing helm package\n      type: string\n      default: https:\/\/github.com\/c-linse\/tekton-course-charts.git\n  workspaces:\n    - name: source\n    - name: helm-repo\n  steps:\n    - name: helm-lint\n      image: dtzar\/helm-kubectl:3.14.1\n      workingDir: $(workspaces.source.path)\n      script: |\n        #!\/bin\/bash\n        set -e\n        cd helm\n        helm lint . \n\n    - name: helm-package\n      image: dtzar\/helm-kubectl:3.14.1\n      workingDir: $(workspaces.source.path)\n      script: |\n        #!\/bin\/bash\n        set -e\n        cd helm\n        helm package . \\\n        --version \"$(params.HELM_CHART_TAG)\" \\\n        --app-version \"$(params.HELM_CHART_TAG)\" \\\n        -d \"$(workspaces.source.path)\/$(params.HELM_CHART_NAME)\"\n\n    - name: helm-publish\n      image: dtzar\/helm-kubectl:3.14.1\n      workingDir: $(workspaces.helm-repo.path)\n      script: |\n        #!\/bin\/bash\n        set -e\n        git clone $(params.HELM_TARGET_ARTIFACTORY) .\n        git config user.name \"c-linse\"\n        git config user.email \"christophlinse@googlemail.com\"\n        mkdir -p \"$(params.HELM_CHART_NAME)\"\n        cp -R \\\n        \"$(workspaces.source.path)\/$(params.HELM_CHART_NAME)\/$(params.HELM_CHART_NAME)-$(params.HELM_CHART_TAG).tgz\" \\\n        \"$(params.HELM_CHART_NAME)\/\"\n        helm repo index .\n        git add index.yaml \"$(params.HELM_CHART_NAME)\" \n        git commit -m \"$(params.HELM_CHART_NAME)-$(params.HELM_CHART_TAG)\"\n        git push origin main\n<\/pre>\n<\/details>\n<\/div><\/div>\n\n<h3 class=\"wp-block-heading\">6 Secrets<\/h3>\n\n<p>In our pipeline setup, we utilize a couple of secrets to securely manage sensitive information required for various operations. These secrets can be created and maintained in GitHub on project and organization level and of course on quay.io for the container registry secret. These secrets have to be configured and applied to kubernetes secrets as mention in the following:  <\/p>\n\n<h4 class=\"wp-block-heading\">GitHub repo secret<\/h4>\n\n<p>This secret contains the authentication credentials required to access the GitHub repository hosting the application code. This secret will be used by the git clone task from the TektonHub. <\/p>\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>7.02-github-repo-secret.yaml<\/summary>\n<pre class=\"wp-block-code\">\napiVersion: v1\nkind: Secret\nmetadata:\n  name: 7-02-git-repo-secret\n  annotations:\n    tekton.dev\/git-0: https:\/\/github.com\ntype: kubernetes.io\/basic-auth\nstringData:\n  username: \"c-linse\"\n  password: \"\"\n<\/pre>\n<\/details>\n\n<h4 class=\"wp-block-heading\">GitHub status api secret<\/h4>\n\n<p>This secret holds a GitHub token used for authentication when interacting with GitHub status api. It will be used to update the state of the git-revision the pipeline executes. <\/p>\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>7.02-github-status-api-secret.yaml<\/summary>\n<pre class=\"wp-block-code\">\napiVersion: v1\nkind: Secret\nmetadata:\n  name: github\n  namespace: default\ntype: Opaque\ndata:\n  token: \"\"\n<\/pre>\n<\/details>\n\n<h4 class=\"wp-block-heading\">GitHub interceptor secret<\/h4>\n\n<p>This secret holds a GitHub token used for authentication when interacting with GitHub repositories. It will be used by the tekton trigger interceptor to ensure that only valid webhooks will instantiate the pipeline. <\/p>\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>7.02-github-interceptor-secret.yaml<\/summary>\n<pre class=\"wp-block-code\">\napiVersion: v1\nkind: Secret\nmetadata:\n  name: 7-02-github-interceptor-secret\ntype: Opaque\nstringData:\n  token: \"\"\n<\/pre>\n<\/details>\n\n<h4 class=\"wp-block-heading\">Quay registry secret<\/h4>\n\n<p>This secret stores the authentication credentials necessary for pushing container images to the <a href=\"https:\/\/quay.io\/\">https:\/\/quay.io<\/a> container registry. It ensures secure access to the registry, facilitating image publishing and distribution. This secret will be used by the buildah task from the tekton hub.  <\/p>\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>7.02-quay-secret.yaml<\/summary>\n<pre class=\"wp-block-code\">\napiVersion: v1\nkind: Secret\nmetadata:\n  name: 7-02-quay-secret\nstringData:\n  config.json: |\n    {\n      \"auths\": {\n        \"quay.io\/christoph_linse\": {\n          \"auth\": \"\"\n        }\n      }\n    }\n<\/pre>\n<\/details>\n\n<h3 class=\"wp-block-heading\">7 Trigger definition<\/h3>\n\n<h4 class=\"wp-block-heading\">Eventlistener  <\/h4>\n\n<p>The eventlistener resource <strong>7-02-github-el<\/strong> will be additionally exposed by a loadbalancer. That instructs GCP to<br\/>expose the eventlistener pod with a public ip address which we are able to reach and more important GitHub can leverage for sending webhooks. <\/p>\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>7.02-eventlistener.yaml<\/summary>\n<pre class=\"wp-block-code\">\napiVersion: triggers.tekton.dev\/v1beta1\nkind: EventListener\nmetadata:\n  name: 7-02-github-el\nspec:\n  triggers:\n    - triggerRef: 7-02-github-trigger\n  serviceAccountName: 7-02-tekton-triggers-sa\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: lb-tekton-event-listener-service\nspec:\n  selector:\n    eventlistener: 7-02-github-el\n  ports:\n    - protocol: TCP\n      port: 80\n      targetPort: 8080\n  type: LoadBalancer\n<\/pre>\n<\/details>\n\n<p><\/p>\n\n<h4 class=\"wp-block-heading\"><strong>TriggerBinding<\/strong><\/h4>\n\n<p>The TriggerBinding resource named <strong>7-02-github-tb<\/strong> defines parameters that extract information from GitHub webhook<br\/>payloads. It captures details like the repository url, revision, image tag, whether it&#8217;s a git-tag and more. <\/p>\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>7.02-tb.yaml<\/summary>\n<pre class=\"wp-block-code\">\napiVersion: triggers.tekton.dev\/v1beta1\nkind: TriggerBinding\nmetadata:\n  name: 7-02-github-tb\n  namespace: default\nspec:\n  params:\n    - name: git-repository-url\n      value: $(body.repository.clone_url)\n    - name: git-repo-full-name\n      value: $(body.repository.full_name)\n    - name: git-revision\n      value: $(body.head_commit.id)\n    - name: app-name\n      value: $(body.repository.name)\n    - name: image-tag\n      value: $(extensions.image-tag)\n    - name: chart-tag\n      value: $(extensions.chart-tag)\n    - name: is-main-branch\n      value: $(extensions.is-main-branch)\n    - name: is-git-tag\n      value: $(extensions.is-git-tag)\n<\/pre>\n<\/details>\n\n<h4 class=\"wp-block-heading\"><strong>TriggerTemplate<\/strong><\/h4>\n\n<p>The TriggerTemplate resource named <strong>7-02-github-tt<\/strong> defines parameters and resource templates for pipeline runs. It<br\/>extracts parameters from the TriggerBinding and configures workspace volumes for pipeline execution, ensuring access<br\/>to required resources like Git repositories and Docker configuration secrets. <\/p>\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>7.02-tt.yaml<\/summary>\n<pre class=\"wp-block-code\">\napiVersion: triggers.tekton.dev\/v1beta1\nkind: TriggerTemplate\nmetadata:\n  name: 7-02-github-tt\n  namespace: default\nspec:\n  params:\n    - name: git-repository-url\n    - name: git-revision\n    - name: git-repo-full-name\n    - name: image-tag\n    - name: chart-tag\n    - name: app-name\n    - name: is-main-branch\n    - name: is-git-tag\n  resourcetemplates:\n    - apiVersion: tekton.dev\/v1beta1\n      kind: PipelineRun\n      metadata:\n        generateName: go-pipeline-run-\n        namespace: default\n      spec:\n        pipelineRef:\n          name: 7-02-go-pipeline\n        podTemplate:\n          securityContext:\n            fsGroup: 65532 # to make the volumes accessible by the non-root user, we need to either configure the permissions manually or set the fsGroup\n        taskRunSpecs:\n          - pipelineTaskName: deploy-dev\n            taskServiceAccountName: 7-02-deployer-sa\n          - pipelineTaskName: deploy-qa\n            taskServiceAccountName: 7-02-deployer-sa\n        params:\n          - name: git-url\n            value: $(tt.params.git-repository-url)\n          - name: git-revision\n            value: $(tt.params.git-revision)\n          - name: git-repo-full-name\n            value: $(tt.params.git-repo-full-name)\n          - name: app-name\n            value: $(tt.params.app-name)\n          - name: image-tag\n            value: $(tt.params.image-tag)\n          - name: chart-tag\n            value: $(tt.params.chart-tag)\n          - name: is-main-branch\n            value: $(tt.params.is-main-branch)\n          - name: is-git-tag\n            value: $(tt.params.is-git-tag)\n        workspaces:\n          - name: shared-workspace\n            volumeClaimTemplate:\n              spec:\n                accessModes:\n                  - ReadWriteOnce # access mode may affect how you can use this volume in parallel tasks\n                resources:\n                  requests:\n                    storage: 10Mi\n          - name: dockerconfig-ws\n            secret:\n              secretName: 7-02-quay-secret\n          - name: helm-workspace\n            emptyDir:\n              medium: Memory\n<\/pre>\n<\/details>\n\n<h4 class=\"wp-block-heading\"><strong>Trigger<\/strong><\/h4>\n\n<p>The Trigger resource <strong>7-02-github-trigger<\/strong> binds to the <strong>7-02-github-tb<\/strong> TriggerBinding and references the<br\/><strong>7-02-github-tt<\/strong> TriggerTemplate. It intercepts GitHub webhook events using interceptors, modifies parameters using CEL<br\/>expressions, and triggers pipeline-runs based on the defined conditions.   <\/p>\n\n<p>To have a detail look the following yaml must be seen:<\/p>\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>7.02-trigger.yaml<\/summary>\n<pre class=\"wp-block-code\">\napiVersion: triggers.tekton.dev\/v1beta1\nkind: Trigger\nmetadata:\n  name: 07-github-trigger\n  namespace: default\nspec:\n  bindings:\n    - ref: 07-github-tb\n  template:\n    ref: 07-github-tt\n  interceptors:\n    - ref:\n        name: \"github\"\n        kind: ClusterInterceptor\n        apiVersion: triggers.tekton.dev\n      params:\n        - name: \"secretRef\"\n          value:\n            secretName: 07-github-interceptor-secret\n            secretKey: token\n    - ref:\n        name: \"cel\"\n      params:\n        - name: overlays\n          value:\n            - key: is-main-branch\n              expression: body.ref.matches('refs\/heads\/main')\n            - key: is-git-tag\n              expression: body.ref.matches('refs\/tags\/.*')\n            - key: image-tag\n              expression: body.ref.split('\/')[2].replace('main','latest')\n            - key: chart-tag\n              expression: body.ref.split('\/')[2].replace('main','1.0.0')\n<\/pre>\n<\/details>\n\n<h3 class=\"wp-block-heading\">8 RBAC<\/h3>\n\n<p>Rbac is beeing used to enable the service-account <strong>7-02-tekton-triggers-sa<\/strong> to create tekton resources and the service-account <strong>7-02-deployer-sa<\/strong> to be able to deploy to certain stages.<\/p>\n\n<h4 class=\"wp-block-heading\">Setup Namespaces<\/h4>\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Setup dev &amp; qa namespace<\/summary>\n<pre class=\"wp-block-code\">\n$ kubectl create namespace dev\n$ kubectl create namespace qa\n<\/pre>\n<\/details>\n\n<h4 class=\"wp-block-heading\">RBAC trigger<\/h4>\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>7.02-rbac-trigger.yaml<\/summary>\n<pre class=\"wp-block-code\">\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: 7-02-tekton-triggers-sa\n  namespace: default\n---\napiVersion: rbac.authorization.k8s.io\/v1\nkind: RoleBinding\nmetadata:\n  name: 7-02-triggers-eventlistener-binding\n  namespace: default\nsubjects:\n  - kind: ServiceAccount\n    name: 7-02-tekton-triggers-sa\n    namespace: default\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: tekton-triggers-eventlistener-roles\n---\napiVersion: rbac.authorization.k8s.io\/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: 7-02-triggers-eventlistener-clusterbinding\nsubjects:\n  - kind: ServiceAccount\n    name: 7-02-tekton-triggers-sa\n    namespace: default\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: tekton-triggers-eventlistener-clusterroles\n<\/pre>\n<\/details>\n\n<h4 class=\"wp-block-heading\">RBAC Deployer<\/h4>\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>7.02-rbac-deployer.yaml<\/summary>\n<pre class=\"wp-block-code\">\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: 7-02-deployer-sa\n  namespace: default\n---\nkind: Role\napiVersion: rbac.authorization.k8s.io\/v1\nmetadata:\n  namespace: dev\n  name: 7-02-deployer-role-dev\nrules:\n  - apiGroups: [\"\"]\n    resources: [\"secrets\", \"configmaps\", \"deployments\", \"serviceaccounts\",\"services\"]\n    verbs: [\"get\", \"list\", \"create\", \"update\", \"delete\", \"patch\"]\n  - apiGroups: [\"apps\"]\n    resources: [\"deployments\", \"replicasets\"]\n    verbs: [\"get\", \"list\", \"create\", \"update\", \"delete\", \"patch\"]\n---\nkind: Role\napiVersion: rbac.authorization.k8s.io\/v1\nmetadata:\n  namespace: qa\n  name: 7-02-deployer-role-qa\nrules:\n  - apiGroups: [\"\"]\n    resources: [\"secrets\", \"configmaps\", \"deployments\", \"serviceaccounts\", \"services\"]\n    verbs: [\"get\", \"list\", \"create\", \"update\", \"delete\", \"patch\"]\n  - apiGroups: [\"apps\"]\n    resources: [\"deployments\", \"replicasets\"]\n    verbs: [\"get\", \"list\", \"create\", \"update\", \"delete\", \"patch\"]\n---\nkind: RoleBinding\napiVersion: rbac.authorization.k8s.io\/v1\nmetadata:\n  name: 7-02-deployer-dev-rolebinding\n  namespace: dev\nsubjects:\n  - kind: ServiceAccount\n    name: 7-02-deployer-sa\n    namespace: default\nroleRef:\n  kind: Role\n  name: 7-02-deployer-role-dev\n  apiGroup: rbac.authorization.k8s.io\n---\nkind: RoleBinding\napiVersion: rbac.authorization.k8s.io\/v1\nmetadata:\n  name: 7-02-deployer-qa-rolebinding\n  namespace: qa\nsubjects:\n  - kind: ServiceAccount\n    name: 7-02-deployer-sa\n    namespace: default\nroleRef:\n  kind: Role\n  name: 7-02-deployer-role-qa\n  apiGroup: rbac.authorization.k8s.io\n<\/pre>\n<\/details>\n\n<h3 class=\"wp-block-heading\">9 References &amp; links<\/h3>\n\n<p>Checkout Github for code and the <a href=\"https:\/\/www.udemy.com\/course\/tekton-the-quick-start\/\">Tekton Udemy course<\/a> to understand and get even more content!<\/p>\n\n<ul class=\"wp-block-social-links is-layout-flex wp-block-social-links-is-layout-flex\"><li class=\"wp-social-link wp-social-link-github  wp-block-social-link\"><a href=\"https:\/\/github.com\/c-linse\/tekton-course-gcp\" class=\"wp-block-social-link-anchor\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">GitHub<\/span><\/a><\/li>\n\n<li class=\"wp-social-link wp-social-link-chain  wp-block-social-link\"><a href=\"https:\/\/udemy.com\" class=\"wp-block-social-link-anchor\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15.6,7.2H14v1.5h1.6c2,0,3.7,1.7,3.7,3.7s-1.7,3.7-3.7,3.7H14v1.5h1.6c2.8,0,5.2-2.3,5.2-5.2,0-2.9-2.3-5.2-5.2-5.2zM4.7,12.4c0-2,1.7-3.7,3.7-3.7H10V7.2H8.4c-2.9,0-5.2,2.3-5.2,5.2,0,2.9,2.3,5.2,5.2,5.2H10v-1.5H8.4c-2,0-3.7-1.7-3.7-3.7zm4.6.9h5.3v-1.5H9.3v1.5z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Link<\/span><\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In this second part of the Tekton CICD example project, we&#8217;ll delve into the design and implementation of the CI\/CD pipeline. We&#8217;ll walk through an example project, demonstrating how to [&hellip;]<\/p>\n","protected":false},"author":12,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[78],"tags":[],"class_list":["post-5819","post","type-post","status-publish","format-standard","hentry","category-tech-en"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Tekton CICD example project - Pipeline design &amp; implementation (part 2\/3) - ONLU AG<\/title>\n<meta name=\"description\" content=\"Raspberry Pi, Angular, Golang, Ansible, Podman\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tekton CICD example project - Pipeline design &amp; implementation (part 2\/3) - ONLU AG\" \/>\n<meta property=\"og:description\" content=\"Raspberry Pi, Angular, Golang, Ansible, Podman\" \/>\n<meta property=\"og:url\" content=\"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/\" \/>\n<meta property=\"og:site_name\" content=\"ONLU AG\" \/>\n<meta property=\"article:published_time\" content=\"2024-03-18T10:01:20+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-07-18T10:02:05+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon.png\" \/>\n<meta name=\"author\" content=\"Christoph Linse\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Christoph Linse\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/\"},\"author\":{\"name\":\"Christoph Linse\",\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/#\\\/schema\\\/person\\\/0e9364e73631edf8539a5f0b9d951caf\"},\"headline\":\"Tekton CICD example project &#8211; Pipeline design &amp; implementation (part 2\\\/3)\",\"datePublished\":\"2024-03-18T10:01:20+00:00\",\"dateModified\":\"2025-07-18T10:02:05+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/\"},\"wordCount\":1499,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/onlu.ch\\\/wp-content\\\/uploads\\\/2024\\\/03\\\/tekton-icon.png\",\"articleSection\":[\"Tech\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/\",\"url\":\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/\",\"name\":\"Tekton CICD example project - Pipeline design &amp; implementation (part 2\\\/3) - ONLU AG\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/onlu.ch\\\/wp-content\\\/uploads\\\/2024\\\/03\\\/tekton-icon.png\",\"datePublished\":\"2024-03-18T10:01:20+00:00\",\"dateModified\":\"2025-07-18T10:02:05+00:00\",\"description\":\"Raspberry Pi, Angular, Golang, Ansible, Podman\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/#primaryimage\",\"url\":\"https:\\\/\\\/onlu.ch\\\/wp-content\\\/uploads\\\/2024\\\/03\\\/tekton-icon.png\",\"contentUrl\":\"https:\\\/\\\/onlu.ch\\\/wp-content\\\/uploads\\\/2024\\\/03\\\/tekton-icon.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\\\/\\\/onlu.ch\\\/en\\\/home-page\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tekton CICD example project &#8211; Pipeline design &amp; implementation (part 2\\\/3)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/onlu.ch\\\/en\\\/\",\"name\":\"ONLU AG\",\"description\":\"Massgeschneiderte Software \u2013 Ihr hoch-qualifiziertes IT Team\",\"publisher\":{\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/onlu.ch\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/#organization\",\"name\":\"ONLU AG\",\"alternateName\":\"ONLU.CH\",\"url\":\"https:\\\/\\\/onlu.ch\\\/en\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/onlu.ch\\\/wp-content\\\/uploads\\\/2023\\\/06\\\/onlu-logo-red-arrow.png\",\"contentUrl\":\"https:\\\/\\\/onlu.ch\\\/wp-content\\\/uploads\\\/2023\\\/06\\\/onlu-logo-red-arrow.png\",\"width\":800,\"height\":221,\"caption\":\"ONLU AG\"},\"image\":{\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/ch.linkedin.com\\\/company\\\/onlu\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/onlu.ch\\\/en\\\/#\\\/schema\\\/person\\\/0e9364e73631edf8539a5f0b9d951caf\",\"name\":\"Christoph Linse\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3a295372eae36b7fa132ff908936fec734764799ddec57d186881d0f2a164372?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3a295372eae36b7fa132ff908936fec734764799ddec57d186881d0f2a164372?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3a295372eae36b7fa132ff908936fec734764799ddec57d186881d0f2a164372?s=96&d=mm&r=g\",\"caption\":\"Christoph Linse\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Tekton CICD example project - Pipeline design &amp; implementation (part 2\/3) - ONLU AG","description":"Raspberry Pi, Angular, Golang, Ansible, Podman","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/","og_locale":"en_US","og_type":"article","og_title":"Tekton CICD example project - Pipeline design &amp; implementation (part 2\/3) - ONLU AG","og_description":"Raspberry Pi, Angular, Golang, Ansible, Podman","og_url":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/","og_site_name":"ONLU AG","article_published_time":"2024-03-18T10:01:20+00:00","article_modified_time":"2025-07-18T10:02:05+00:00","og_image":[{"url":"https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon.png","type":"","width":"","height":""}],"author":"Christoph Linse","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Christoph Linse","Est. reading time":"16 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/#article","isPartOf":{"@id":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/"},"author":{"name":"Christoph Linse","@id":"https:\/\/onlu.ch\/en\/#\/schema\/person\/0e9364e73631edf8539a5f0b9d951caf"},"headline":"Tekton CICD example project &#8211; Pipeline design &amp; implementation (part 2\/3)","datePublished":"2024-03-18T10:01:20+00:00","dateModified":"2025-07-18T10:02:05+00:00","mainEntityOfPage":{"@id":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/"},"wordCount":1499,"commentCount":0,"publisher":{"@id":"https:\/\/onlu.ch\/en\/#organization"},"image":{"@id":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/#primaryimage"},"thumbnailUrl":"https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon.png","articleSection":["Tech"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/","url":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/","name":"Tekton CICD example project - Pipeline design &amp; implementation (part 2\/3) - ONLU AG","isPartOf":{"@id":"https:\/\/onlu.ch\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/#primaryimage"},"image":{"@id":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/#primaryimage"},"thumbnailUrl":"https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon.png","datePublished":"2024-03-18T10:01:20+00:00","dateModified":"2025-07-18T10:02:05+00:00","description":"Raspberry Pi, Angular, Golang, Ansible, Podman","breadcrumb":{"@id":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/#primaryimage","url":"https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon.png","contentUrl":"https:\/\/onlu.ch\/wp-content\/uploads\/2024\/03\/tekton-icon.png"},{"@type":"BreadcrumbList","@id":"https:\/\/onlu.ch\/en\/tekton-cicd-example-project-pipeline-design-implementation-part-2-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/onlu.ch\/en\/home-page\/"},{"@type":"ListItem","position":2,"name":"Tekton CICD example project &#8211; Pipeline design &amp; implementation (part 2\/3)"}]},{"@type":"WebSite","@id":"https:\/\/onlu.ch\/en\/#website","url":"https:\/\/onlu.ch\/en\/","name":"ONLU AG","description":"Massgeschneiderte Software \u2013 Ihr hoch-qualifiziertes IT Team","publisher":{"@id":"https:\/\/onlu.ch\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/onlu.ch\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/onlu.ch\/en\/#organization","name":"ONLU AG","alternateName":"ONLU.CH","url":"https:\/\/onlu.ch\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/onlu.ch\/en\/#\/schema\/logo\/image\/","url":"https:\/\/onlu.ch\/wp-content\/uploads\/2023\/06\/onlu-logo-red-arrow.png","contentUrl":"https:\/\/onlu.ch\/wp-content\/uploads\/2023\/06\/onlu-logo-red-arrow.png","width":800,"height":221,"caption":"ONLU AG"},"image":{"@id":"https:\/\/onlu.ch\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/ch.linkedin.com\/company\/onlu"]},{"@type":"Person","@id":"https:\/\/onlu.ch\/en\/#\/schema\/person\/0e9364e73631edf8539a5f0b9d951caf","name":"Christoph Linse","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/3a295372eae36b7fa132ff908936fec734764799ddec57d186881d0f2a164372?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/3a295372eae36b7fa132ff908936fec734764799ddec57d186881d0f2a164372?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3a295372eae36b7fa132ff908936fec734764799ddec57d186881d0f2a164372?s=96&d=mm&r=g","caption":"Christoph Linse"}}]}},"_links":{"self":[{"href":"https:\/\/onlu.ch\/en\/wp-json\/wp\/v2\/posts\/5819","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/onlu.ch\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/onlu.ch\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/onlu.ch\/en\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/onlu.ch\/en\/wp-json\/wp\/v2\/comments?post=5819"}],"version-history":[{"count":2,"href":"https:\/\/onlu.ch\/en\/wp-json\/wp\/v2\/posts\/5819\/revisions"}],"predecessor-version":[{"id":5824,"href":"https:\/\/onlu.ch\/en\/wp-json\/wp\/v2\/posts\/5819\/revisions\/5824"}],"wp:attachment":[{"href":"https:\/\/onlu.ch\/en\/wp-json\/wp\/v2\/media?parent=5819"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/onlu.ch\/en\/wp-json\/wp\/v2\/categories?post=5819"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/onlu.ch\/en\/wp-json\/wp\/v2\/tags?post=5819"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}