Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions task/gitlab-set-status/0.3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# GitLab Set Status

GitLab Set Status is part of a collection of GitLab tasks to help working
with the [GitLab API](https://docs.gitlab.com/ee/api/).

## Set Status on a Commit/MR

The `gitlab-set-status` task uses the [commit api](https://docs.gitlab.com/ee/api/commits.html#post-the-build-status-to-a-commit)
to mark GitLab commits with a `pending`,`running`, `success`, `failed`, or `canceled` state, which is then reflected in merge requests involving those commits.

Statuses include as well a `description`, a `target_url` and a `coverage`, to give the user
informations about the CI statuses or a direct link to the full log.

### Install the Task

```shell
kubectl apply -f https://api.hub.tekton.dev/v1/resource/tekton/task/gitlab-set-status/0.3/raw
```

### Parameters

* **STATE** (string): The state of the status. Can be one of the following `pending`, `running`, `success`, `failed`, or `canceled`.
* **GITLAB_TOKEN_SECRET_NAME** (string, optional): The name of the kubernetes secret that contains the GitLab access token. _default:_ `gitlab-api-secret`
* **GITLAB_TOKEN_SECRET_KEY** (string, optional): The key within the kubernetes secret that contains the GitLab token. _default:_ `token`
* **SHA** (string): The commit SHA to set the status for.
* **TARGET_URL** (string): The target URL to associate with this status. This URL will
be linked from the GitLab UI to allow users to easily see the source of the
status. For example you can link to a
[dashboard](https://github.com/tektoncd/dashboard) URL so users can follow a
Pipeline/Task run.
* **GITLAB_HOST_URL** (string, optional): The GitLab host domain. _default:_ `gitlab.com`
* **API_PATH_PREFIX** (string, optional): The GitLab Enterprise has a prefix for the API path. _default:_ `/api/v4`
* **REPO_FULL_NAME** (string, optional): The GitLab repository full name. _default:_ `tektoncd/catalog`
* **DESCRIPTION** (string): A short description of the status. _e.g:_ `Building your MR`
* **CONTEXT** (string, optional): The GitLab context, A string label to differentiate this status
from the status of other systems. _e.g:_ `continuous-integration/tekton`
* **COVERAGE** (string, optional): The total code coverage. Should be a float string. _default:_ `""`
* **SSL_VERIFY** (string, optional): Whether to verify SSL certificates. Set to `"false"` to disable verification (useful for self-signed certificates). _default:_ `"true**_*

## Platforms

The Task can be run on `linux/amd64` platform.
190 changes: 190 additions & 0 deletions task/gitlab-set-status/0.3/gitlab-set-status.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: gitlab-set-status
labels:
app.kubernetes.io/version: "0.3"
annotations:
tekton.dev/pipelines.minVersion: "0.12.1"
tekton.dev/categories: Git
tekton.dev/tags: gitlab, git
tekton.dev/displayName: "Set Gitlab commit status"
tekton.dev/platforms: "linux/amd64"
spec:
description: >-
This task will set the status of the CI job to the specified value along
with a link to the specified target URL where developers can follow the
progress of the CI job.

The `gitlab-set-status` task allows external services to mark GitLab commits
with an `error`, `failure`, `pending`, or `success` state, which is then
reflected in merge requests involving those commits. Statuses include as well a
`description`, a `target_url` and a `coverage`, to give the user informations
about the CI statuses or a direct link to the full log.

params:
- name: GITLAB_HOST_URL
description: |
The GitLab host, adjust this if you run a GitLab enterprise.
default: "gitlab.com"
type: string

- name: API_PATH_PREFIX
description: |
The API path prefix, GitLab Enterprise has a prefix e.g. /api/v4
default: "/api/v4"
type: string

- name: REPO_NAME
description: |
The GitLab repository name, e.g.: catalog
type: string

- name: REPO_GROUP_PATH
description: |
The GitLab repository full group path, e.g.: tektoncd/hub
type: string

- name: GITLAB_TOKEN_SECRET_NAME
description: |
The name of the kubernetes secret that contains the GitLab token, default: gitlab-api-secret
type: string
default: gitlab-api-secret

- name: GITLAB_TOKEN_SECRET_KEY
description: |
The key within the kubernetes secret that contains the GitLab token, default: token
type: string
default: token

- name: SHA
description: |
Commit SHA to set the status for.
type: string

- name: TARGET_URL
description: |
The target URL to associate with this status. This URL will be linked
from the GitLab UI to allow users to easily see the source of the
status.
type: string

- name: DESCRIPTION
description: |
A short description of the status.
type: string

- name: CONTEXT
description: |
The GitLab context, A string label to differentiate this status from
the status of other systems. ie: "continuous-integration/tekton"
default: "continuous-integration/tekton"
type: string

- name: STATE
description: |
The state of the status. Can be one of the following `pending`,
`running`, `success`, `failed`, or `canceled`.
type: string

- name: COVERAGE
description: |
The total code coverage.
type: string
default: ""

- name: SSL_VERIFY
description: |
Whether to verify SSL certificates. Set to false to disable SSL verification (useful for self-signed certificates).
default: "true"
type: string

steps:
- name: set-status
image: registry.access.redhat.com/ubi8/python-38@sha256:af6f93b81f9313de95966e8cd681edb9dbcb5fdbddc5a4cc365af8e4534096ef
script: |
#!/usr/libexec/platform-python

"""This script will set the pipeline status of a commit on GitLab."""
import os
import sys
import json
import http.client
import ssl
import urllib.parse

GITLAB_TOKEN = os.getenv("GITLAB_TOKEN")
GITLAB_HOST_URL = "$(params.GITLAB_HOST_URL)"
API_PATH_PREFIX = "$(params.API_PATH_PREFIX)"
REPO_NAME = "$(params.REPO_NAME)"
REPO_GROUP_PATH = "$(params.REPO_GROUP_PATH)"
SHA = "$(params.SHA)"
STATE = "$(params.STATE)"
CONTEXT = "$(params.CONTEXT)"
TARGET_URL = "$(params.TARGET_URL)"
DESCRIPTION = "$(params.DESCRIPTION)"
COVERAGE = "$(params.COVERAGE)"
SSL_VERIFY = "$(params.SSL_VERIFY)".lower() == "true"

headers = {
"User-Agent": "TektonCD, the peaceful cat",
"Authorization": f"Bearer {GITLAB_TOKEN}",
}

URLENCODED_REPO_NAME = urllib.parse.quote(REPO_NAME, safe="")

params = {
"state": STATE,
"context": CONTEXT,
"target_url": TARGET_URL,
"description": DESCRIPTION
}

if COVERAGE:
params["coverage"] = float(COVERAGE)

ssl_context = None if SSL_VERIFY else ssl._create_unverified_context()

if GITLAB_HOST_URL.startswith("http://"):
conn = http.client.HTTPConnection(GITLAB_HOST_URL[7:])
elif GITLAB_HOST_URL.startswith("https://"):
conn = http.client.HTTPSConnection(GITLAB_HOST_URL[8:], context=ssl_context)
else:
conn = http.client.HTTPSConnection(GITLAB_HOST_URL, context=ssl_context)

try:
project_api_url = f"{API_PATH_PREFIX}/projects?search={URLENCODED_REPO_NAME}"
conn.request("GET", project_api_url, headers=headers)
resp = conn.getresponse()
if not str(resp.status).startswith("2"):
print(f"{resp.status} | Unable to get project id")
response_data = json.dumps(json.loads(resp.read()), indent=4)
print(response_data)
sys.exit(1)
else:
response_data = json.loads(resp.read())
target_path = f"{REPO_GROUP_PATH}/{URLENCODED_REPO_NAME}"
project_id = next((item["id"] for item in response_data if item["path_with_namespace"] == target_path), None)
print(f"Project ID of {REPO_GROUP_PATH}/{URLENCODED_REPO_NAME} is {project_id}")

encoded_params = urllib.parse.urlencode(params)
status_api_url = f"{API_PATH_PREFIX}/projects/{project_id}/statuses/{SHA}?{encoded_params}"
print(f"POST to {GITLAB_HOST_URL}{status_api_url}")
conn.request("POST", status_api_url, headers=headers)
resp = conn.getresponse()
if not str(resp.status).startswith("2"):
print(f"{resp.status} | Unable to set status")
response_data = json.dumps(json.loads(resp.read()), indent=4)
print(response_data)
sys.exit(1)
else:
print(f"Just set status of {REPO_GROUP_PATH}/{URLENCODED_REPO_NAME}#{SHA} to {STATE}")
finally:
conn.close()

env:
- name: GITLAB_TOKEN
valueFrom:
secretKeyRef:
name: $(params.GITLAB_TOKEN_SECRET_NAME)
key: $(params.GITLAB_TOKEN_SECRET_KEY)
11 changes: 11 additions & 0 deletions task/gitlab-set-status/0.3/tests/fixtures/gitlab-set-status.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
headers:
method: POST
path: /api/v4/projects/{project_id:[0-9]+}/statuses/{[^/]+}
response:
status: 201
output: |
{
"some": "data"
}
content-type: application/json
3 changes: 3 additions & 0 deletions task/gitlab-set-status/0.3/tests/pre-apply-task-hook.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash

kubectl -n ${tns} create secret generic gitlab-secret --from-literal token="secret"
31 changes: 31 additions & 0 deletions task/gitlab-set-status/0.3/tests/run.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: gitlab-set-status
spec:
pipelineSpec:
tasks:
- name: set-status
taskRef:
name: gitlab-set-status
params:
- name: GITLAB_HOST_URL
value: http://localhost:8080
- name: REPO_FULL_NAME
value: tektoncd/catalog
- name: SHA
value: 1234567890abcdef
- name: TARGET_URL
value: http://localhost:8080/this-could-be-your-pipeline-dashboard
- name: DESCRIPTION
value: An update to Gitlab about our pipeline status
- name: STATE
value: success
- name: COVERAGE
value: "100.0"
- name: GITLAB_TOKEN_SECRET_NAME
value: gitlab-secret
- name: GITLAB_TOKEN_SECRET_KEY
value: token
- name: SSL_VERIFY
value: "true"