<p>We're already using <a href="https://hub.tekton.dev/tekton/task/gitlab-set-status" rel="nofollow noreferrer">the <code>gitlab-set-status</code> Task from Tekton Hub</a> to report our Tekton Pipeline's status back into our GitLab instance (here's <a href="https://github.com/jonashackt/tekton-argocd-eks" rel="nofollow noreferrer">our EKS setup &amp; Tekton installment</a> and <a href="https://gitlab.com/jonashackt/microservice-api-spring-boot" rel="nofollow noreferrer">a example project on gitlab.com</a>). Our <a href="https://github.com/jonashackt/tekton-argocd-eks/blob/main/pipelines/pipeline.yml" rel="nofollow noreferrer"><code>pipeline.yml</code></a> looks like this and currently reports the <code>STATE</code> success every time the Tekton Pipeline runs:</p>
<pre><code>apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: buildpacks-test-pipeline
spec:
  params:
    - name: IMAGE
      type: string
      description: image URL to push
    - name: SOURCE_URL
      type: string
      description: A git repo url where the source code resides.
    - name: REPO_PATH_ONLY
      type: string
      description: GitLab group &amp; repo name only (e.g. jonashackt/microservice-api-spring-boot)
    - name: SOURCE_REVISION
      description: The branch, tag or SHA to checkout.
      default: &quot;&quot;
    - name: GITLAB_HOST
      type: string
      description: Your GitLabs host only (e.g. gitlab.com)
    - name: TEKTON_DASHBOARD_HOST
      type: string
      description: The Tekton dashboard host name only

  workspaces:
    - name: source-workspace # Directory where application source is located. (REQUIRED)
    - name: cache-workspace # Directory where cache is stored (OPTIONAL)
  tasks:
    - name: fetch-repository # This task fetches a repository from github, using the `git-clone` task you installed
      taskRef:
        name: git-clone
      workspaces:
        - name: output
          workspace: source-workspace
      params:
        - name: url
          value: &quot;$(params.SOURCE_URL)&quot;
        - name: revision
          value: &quot;$(params.SOURCE_REVISION)&quot;
        - name: subdirectory
          value: &quot;&quot;
        - name: deleteExisting
          value: &quot;true&quot;
    - name: buildpacks # This task uses the `buildpacks` task to build the application
      taskRef:
        name: buildpacks
      runAfter:
        - fetch-repository
      workspaces:
        - name: source
          workspace: source-workspace
        - name: cache
          workspace: cache-workspace
      params:
        - name: APP_IMAGE
          value: &quot;$(params.IMAGE)&quot;
        - name: BUILDER_IMAGE
          value: paketobuildpacks/builder:base # This is the builder we want the task to use (REQUIRED)
    - name: report-pipeline-end-to-gitlab
      taskRef:
        name: &quot;gitlab-set-status&quot;
      runAfter:
        - buildpacks
      params:
        - name: &quot;STATE&quot;
          value: &quot;success&quot;
        - name: &quot;GITLAB_HOST_URL&quot;
          value: &quot;$(params.GITLAB_HOST)&quot;
        - name: &quot;REPO_FULL_NAME&quot;
          value: &quot;$(params.REPO_PATH_ONLY)&quot;
        - name: &quot;GITLAB_TOKEN_SECRET_NAME&quot;
          value: &quot;gitlab-api-secret&quot;
        - name: &quot;GITLAB_TOKEN_SECRET_KEY&quot;
          value: &quot;token&quot;
        - name: &quot;SHA&quot;
          value: &quot;$(params.SOURCE_REVISION)&quot;
        - name: &quot;TARGET_URL&quot;
          value: &quot;$(params.TEKTON_DASHBOARD_HOST)/#/namespaces/default/pipelineruns/$(context.pipelineRun.name)&quot;
        - name: &quot;CONTEXT&quot;
          value: &quot;tekton-pipeline&quot;
        - name: &quot;DESCRIPTION&quot;
          value: &quot;Finished building your commit in Tekton&quot;
</code></pre>
<p>How can we enhance our Tekton Pipeline to report the status correctly and regardless of any failure or success to GitLab?</p>

<p><a href="https://github.com/tektoncd/pipeline/releases/tag/v0.14.0" rel="nofollow noreferrer">In v0.14 Tekton introduced the so called <code>finally</code> Tasks</a>, which run at the end of every <code>Pipeline</code> - regardless which Task failed or succeeded. <a href="https://tekton.dev/docs/pipelines/pipelines/#adding-finally-to-the-pipeline" rel="nofollow noreferrer">As the docs state</a>:</p>
<blockquote>
<p>finally tasks are guaranteed to be executed in parallel after all PipelineTasks under tasks have completed regardless of success or error.</p>
</blockquote>
<p>In general <code>finally</code> tasks look like this:</p>
<pre class="lang-yaml prettyprint-override"><code>spec:
  tasks:
    - name: tests
      taskRef:
        name: integration-test
  finally:
    - name: cleanup-test
      taskRef:
        name: cleanup
</code></pre>
<p><strong>But how do we create the corresponding <code>STATE</code> in our <code>gitlab-set-status</code> Task?</strong> With <a href="https://tekton.dev/docs/pipelines/pipelines/#guard-finally-task-execution-using-when-expressions" rel="nofollow noreferrer">using <code>when</code> expressions inside our <code> finally</code> tasks</a> we can run our <code>gitlab-set-status</code> Task based on <a href="https://tekton.dev/docs/pipelines/pipelines/#when-expressions-using-aggregate-execution-status-of-tasks-in-finally-tasks" rel="nofollow noreferrer">the overall Pipeline status (or Aggregate Pipeline status)</a>:</p>
<pre><code>finally:
  - name: notify-any-failure # executed only when one or more tasks fail
    when:
      - input: $(tasks.status)
        operator: in
        values: [&quot;Failed&quot;]
    taskRef:
      name: notify-failure
</code></pre>
<p>We grab the <a href="https://tekton.dev/docs/pipelines/pipelines/#using-aggregate-execution-status-of-all-tasks" rel="nofollow noreferrer">Aggregate Execution Status</a> by simply using <code>$(tasks.status)</code>. This variable is stated to have those 4 possible status:</p>
<ul>
<li><code>Succeeded</code> (&quot;all tasks have succeeded&quot;)</li>
<li><code>Completed</code> (&quot;all tasks completed successfully including one or more skipped tasks&quot;)</li>
</ul>
<p>-&gt; which could be translated into the <code>gitlab-set-status</code> Tasks <code>STATE</code> value <code>success</code>.</p>
<ul>
<li><code>Failed</code> (&quot;one ore more tasks failed&quot;)</li>
<li><code>None</code> (&quot;no aggregate execution status available (i.e. none of the above), one or more tasks could be pending/running/cancelled/timedout&quot;)</li>
</ul>
<p>-&gt; which could both be translated into the <code>gitlab-set-status</code> Tasks <code>STATE</code> value <code>failed</code>. For <code>None</code> this is only valid, since we're in a <code>finally task</code>, since <code>pending/running</code> could otherwise also mean that a Pipeline is in a good state.</p>
<p>Having 4 states we need to check in our <code>when</code> expressions, do we need to implement a separate finally Task for each of them? No, since luckily the <code>when</code> expressions <a href="https://tekton.dev/docs/pipelines/pipelines/#guard-task-execution-using-when-expressions" rel="nofollow noreferrer">&quot;values is an array of string values.&quot;</a>. So we're able to do</p>
<pre><code>  when:
    - input: $(tasks.status)
      operator: in
      values: [ &quot;Failed&quot;, &quot;None&quot; ]
</code></pre>
<p>and</p>
<pre><code>  when:
    - input: $(tasks.status)
      operator: in
      values: [ &quot;Succeeded&quot;, &quot;Completed&quot; ]
</code></pre>
<p>Finally this results in our Tekton Pipeline's locking like this (and implementing 2 finally tasks <code>report-pipeline-failed-to-gitlab</code> and <code>report-pipeline-success-to-gitlab</code>):</p>
<pre><code>...
  finally:
    - name: report-pipeline-failed-to-gitlab
      when:
        - input: $(tasks.status)
          operator: in
          values: [ &quot;Failed&quot;, &quot;None&quot; ] # see aggregated status https://tekton.dev/docs/pipelines/pipelines/#using-aggregate-execution-status-of-all-tasks
      taskRef:
        name: &quot;gitlab-set-status&quot;
      params:
        - name: &quot;STATE&quot;
          value: &quot;failed&quot;
        - name: &quot;GITLAB_HOST_URL&quot;
          value: &quot;$(params.GITLAB_HOST)&quot;
        - name: &quot;REPO_FULL_NAME&quot;
          value: &quot;$(params.REPO_PATH_ONLY)&quot;
        - name: &quot;GITLAB_TOKEN_SECRET_NAME&quot;
          value: &quot;gitlab-api-secret&quot;
        - name: &quot;GITLAB_TOKEN_SECRET_KEY&quot;
          value: &quot;token&quot;
        - name: &quot;SHA&quot;
          value: &quot;$(params.SOURCE_REVISION)&quot;
        - name: &quot;TARGET_URL&quot;
          value: &quot;$(params.TEKTON_DASHBOARD_HOST)/#/namespaces/default/pipelineruns/$(context.pipelineRun.name)&quot;
        - name: &quot;CONTEXT&quot;
          value: &quot;tekton-pipeline&quot;
        - name: &quot;DESCRIPTION&quot;
          value: &quot;An error occurred building your commit in Tekton&quot;
    - name: report-pipeline-success-to-gitlab
      when:
          - input: $(tasks.status)
            operator: in
            values: [ &quot;Succeeded&quot;, &quot;Completed&quot; ] # see aggregated status https://tekton.dev/docs/pipelines/pipelines/#using-aggregate-execution-status-of-all-tasks
      taskRef:
        name: &quot;gitlab-set-status&quot;
      params:
        - name: &quot;STATE&quot;
          value: &quot;success&quot;
        - name: &quot;GITLAB_HOST_URL&quot;
          value: &quot;$(params.GITLAB_HOST)&quot;
        - name: &quot;REPO_FULL_NAME&quot;
          value: &quot;$(params.REPO_PATH_ONLY)&quot;
        - name: &quot;GITLAB_TOKEN_SECRET_NAME&quot;
          value: &quot;gitlab-api-secret&quot;
        - name: &quot;GITLAB_TOKEN_SECRET_KEY&quot;
          value: &quot;token&quot;
        - name: &quot;SHA&quot;
          value: &quot;$(params.SOURCE_REVISION)&quot;
        - name: &quot;TARGET_URL&quot;
          value: &quot;$(params.TEKTON_DASHBOARD_HOST)/#/namespaces/default/pipelineruns/$(context.pipelineRun.name)&quot;
        - name: &quot;CONTEXT&quot;
          value: &quot;tekton-pipeline&quot;
        - name: &quot;DESCRIPTION&quot;
          value: &quot;Finished building your commit in Tekton&quot;
</code></pre>
<p>Executing our Tekton Pipeline should now be reported correctly to our GitLab. Failures look like this:</p>
<p><a href="https://i.stack.imgur.com/SSxKP.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/SSxKP.png" alt="enter image description here" /></a></p>
<p>Succeeded Pipelines look like this:</p>
<p><a href="https://i.stack.imgur.com/c03It.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/c03It.png" alt="enter image description here" /></a></p>
