Step 1 - Listen to Events

- By: Thomas Jungbauer ( Lastmod: 2023-07-04 ) - 5 min read

In this first step, we will simply prepare our environment to be able to retrieve calls from Git. In Git we will fork a prepared source code into a repository and any time a developer pushes a new code into our repository a webhook will notify OpenShift Pipelines to start the pipeline. Like most pipelines, the first task to be executed is to fetch the source code so it can be used for the next steps. The application I am going to use is called globex-ui and is an example webUI build with Angular.

Goals

The goals of this step are:

  • Create the EventListener and Trigger-Settings that will take care of notifications by GitHub.

  • Create a secret for GitHub authentication.

  • Fork a prepared source code and create a webhook inside Git.

Create the EventListener

  1. The first thing we need to create is a Namespace that will be responsible for all our Pipeline-objects. In this example, it is called ci:

    oc new-project ci
  2. Now we need to create the so-called EventListener. This requires the creation of several objects:

    1. Create a TriggerBinding: A TriggerBinding captures fields from an event and provides them as named parameters to the TriggerTemplate and subsequently to the PipelineRun.

      We will create two TriggerBindings:

      • globex-ui - For the required settings of our example application

      • github-push - For the relevant parameters to push into git. These parameters will be provided by Git whenever Git is using the Webhook to inform OpenShift that a new push event happened.

        Copy the following examples into your cluster.

        The list of parameters in these manifests will be extended throughout this series.
        apiVersion: triggers.tekton.dev/v1beta1
        kind: TriggerBinding
        metadata:
          name: globex-ui
          namespace: ci
        spec:
          params:
          - name: tlsVerify (1)
            value: "false"
          - name: gitRepoHost (2)
            value: github.com
        1Default values for verifying SSL is "false" (Since I do not have certificates in place)
        2The default value for the Git URL is github.com
        apiVersion: triggers.tekton.dev/v1alpha1
        kind: TriggerBinding
        metadata:
          name: github-push
          namespace: ci
        spec:
          params:
            - name: gitrepositoryurl (1)
              value: $(body.repository.clone_url)
            - name: fullname
              value: $(body.repository.full_name)
            - name: io.openshift.build.commit.ref
              value: $(extensions.ref)
            - name: io.openshift.build.commit.id
              value: $(body.head_commit.id)
            - name: io.openshift.build.commit.date
              value: $(body.head_commit.timestamp)
            - name: io.openshift.build.commit.message
              value: $(body.head_commit.message)
            - name: io.openshift.build.commit.author
              value: $(body.head_commit.author.name)
        1Several parameters, coming from Git via the Webhook, for example the exact URL to the repository, the ID of the commit, the date of the commit etc.
    2. Create a TriggerTemplate: A TriggerTemplate acts as a blueprint for PipelineRuns (or TaskRuns). The resources and parameters here will be used when our Pipeline is executed. It also defines the workspaces, that will be used by the pipeline. For now, we are using the space shared-data where we will pull the source code for further checks.

      apiVersion: triggers.tekton.dev/v1alpha1
      kind: TriggerTemplate
      metadata:
        name: app-globex-ui-template
        namespace: ci
      spec:
        params: (1)
          - description: The git repository URL.
            name: gitrepositoryurl
          - description: The repository name for this PullRequest.
            name: fullname
          - description: The git branch for this PR.
            name: io.openshift.build.commit.ref
          - description: the specific commit SHA.
            name: io.openshift.build.commit.id
          - description: The date at which the commit was made
            name: io.openshift.build.commit.date
          - description: The commit message
            name: io.openshift.build.commit.message
          - description: The name of the github user handle that made the commit
            name: io.openshift.build.commit.author
          - description: The host name of the git repo
            name: gitRepoHost
          - description: Enable image repository TLS certification verification.
            name: tlsVerify
          - description: Extra parameters passed for the push command when pushing images.
            name: build_extra_args
          - description: Target image repository name
            name: imageRepo
        resourcetemplates: (2)
          - apiVersion: tekton.dev/v1beta1
            kind: PipelineRun
            metadata:
              generateName: secure-supply-chain- (3)
            spec:
              params: (4)
                - name: REPO_HOST
                  value: $(tt.params.gitRepoHost)
                - name: GIT_REPO
                  value: $(tt.params.gitrepositoryurl)
                - name: TLSVERIFY
                  value: $(tt.params.tlsVerify)
                - name: BUILD_EXTRA_ARGS
                  value: $(tt.params.build_extra_args)
                - name: IMAGE_REPO
                  value: $(tt.params.imageRepo)
                - name: IMAGE_TAG
                  value: >-
                    $(tt.params.io.openshift.build.commit.ref)-$(tt.params.io.openshift.build.commit.id)
                - name: COMMIT_SHA
                  value: $(tt.params.io.openshift.build.commit.id)
                - name: GIT_REF
                  value: $(tt.params.io.openshift.build.commit.ref)
                - name: COMMIT_DATE
                  value: $(tt.params.io.openshift.build.commit.date)
                - name: COMMIT_AUTHOR
                  value: $(tt.params.io.openshift.build.commit.author)
                - name: COMMIT_MESSAGE
                  value: $(tt.params.io.openshift.build.commit.message)
              pipelineRef: (5)
                name: secure-supply-chain
              serviceAccountName: pipeline (6)
              workspaces: (7)
                - name: shared-data
                  volumeClaimTemplate:
                    metadata:
                      creationTimestamp: null
                    spec:
                      accessModes:
                        - ReadWriteOnce
                      resources:
                        requests:
                          storage: 3Gi
                    status: {}
      1List of parameters for this TriggerTemplate, that should be used further for the pipeline.
      2The resources we are going to use.
      3The name prefix of the generated PipelineRun
      4List of parameters that shall be provided to the pipeline
      5The reference to the pipeline that shall be executed.
      6Name of the ServiceAccount that will execute the Pipeline. Per default, this is pipeline which is managed by the Operator.
      7The workspaces that will be used by the PipelineRun. Currently shared-data only.
    3. Create an EventListener that sets up a Service and listens for specific events and exposes a sink that receives incoming events, for example from a GitHub Webhook. It connects TriggerTemplate to a TriggerBinding. In this example, we create a Listener with 1 replica (that’s enough for testing) and connect our two TriggerBindings.

      We also refer to the secret webhook-secret-globex-ui which will hold the password for GitHub to authenticate. We filter any push event coming from my Git repository tjungbauer/globex-ui

      apiVersion: triggers.tekton.dev/v1alpha1
      kind: EventListener
      metadata:
        name: globex-ui-event-listener
        namespace: ci
      spec:
        namespaceSelector: {}
        resources:
          kubernetesResource:
            replicas: 1
            spec:
              template:
                metadata:
                  creationTimestamp: null
                spec:
                  containers: null
        serviceAccountName: pipeline
        triggers: (1)
          - bindings:
              - kind: TriggerBinding
                ref: globex-ui
              - kind: TriggerBinding
                ref: github-push
            interceptors:
              - params:
                  - name: secretRef
                    value:
                      secretKey: webhook-secret-key
                      secretName: webhook-secret-globex-ui (2)
                ref:
                  kind: ClusterInterceptor
                  name: github
              - params:
                  - name: filter (3)
                    value: >-
                      (header.match('X-GitHub-Event', 'push') &&
                      body.repository.full_name == 'tjungbauer/globex-ui')
                  - name: overlays
                    value:
                      - expression: 'body.ref.split(''/'')[2]'
                        key: ref
                ref:
                  kind: ClusterInterceptor
                  name: cel
            name: build-from-push-globex-ui
            template: (4)
              ref: app-globex-ui-template
      1TriggerBindings that are used.
      2Reference to the secret.
      3A filter for push events and our repository name.
      4The TriggerTemplate that will be used.
    4. Now let us create a Route object to allow external traffic (from Git) to the EventListener.

      apiVersion: route.openshift.io/v1
      kind: Route
      metadata:
        name: el-event-listener
        namespace: ci
      spec:
        port:
          targetPort: http-listener
        to:
          kind: Service
          name: el-globex-ui-event-listener (1)
          weight: 100
        tls:
          termination: edge
          insecureEdgeTerminationPolicy: Redirect
        wildcardPolicy: None
      1Service that will be automatically created when the EventListener has been created.
    5. And finally, we create a Secret to allow GitHub to authenticate. The name of the Secret is referenced inside the EventListener object.

      kind: Secret
      apiVersion: v1
      metadata:
        name: webhook-secret-globex-ui (1)
        namespace: ci
      stringData:
        webhook-secret-key: yoursecret (2)
      type: Opaque
      1Name as referenced in the EventListener
      2Your super secure password

Prepare GitHub

Now we have everything in place to prepare our source code in Git. All we need to do is to create a repository that holds our source code and a Webhook.

  1. Fork the Source Code: https://github.com/redhat-gpte-devopsautomation/globex-ui

    Why fork? I want to be able to update the files and trigger the Pipeline whenever I want to. My forked repository can be found at: https://github.com/tjungbauer/globex-ui

  2. Create a Webhook in GitHub. Go to Settings > Webhooks and add a new Webhook using:

    Create a new Webhook.
    Figure 1. Create a new Webhook.
    1. The Route URL that was created.

    2. Content type: application/json.

    3. Your Password as used in the secret above.

    4. Enable or disable SSL verification, since I was too lazy to create a certificate at my demo cluster, I disabled it.

    5. And select which events, shall be sent to the Listener. In our case, push events are just fine.

  3. After a few seconds GitHub should have validated the Webhook (reload the page eventually)

    Verify Webhook
    Figure 2. Verify Webhook

Summary

That’s it, we now have a Git repository, that will send any push-event to the EventListener, which uses the Triggers to fill out any required parameters and starts the pipeline named: secure-supply-chain.

This pipeline does not exist yet and will be created in the next step together with its first task to pull from the Git repository.