diff --git a/task/gitlab-set-status/0.3/README.md b/task/gitlab-set-status/0.3/README.md new file mode 100644 index 0000000000..5a74c09fbd --- /dev/null +++ b/task/gitlab-set-status/0.3/README.md @@ -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. diff --git a/task/gitlab-set-status/0.3/gitlab-set-status.yaml b/task/gitlab-set-status/0.3/gitlab-set-status.yaml new file mode 100644 index 0000000000..11ae74f8eb --- /dev/null +++ b/task/gitlab-set-status/0.3/gitlab-set-status.yaml @@ -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) diff --git a/task/gitlab-set-status/0.3/tests/fixtures/gitlab-set-status.yaml b/task/gitlab-set-status/0.3/tests/fixtures/gitlab-set-status.yaml new file mode 100644 index 0000000000..e4ceddee98 --- /dev/null +++ b/task/gitlab-set-status/0.3/tests/fixtures/gitlab-set-status.yaml @@ -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 diff --git a/task/gitlab-set-status/0.3/tests/pre-apply-task-hook.sh b/task/gitlab-set-status/0.3/tests/pre-apply-task-hook.sh new file mode 100644 index 0000000000..3fe57b8a59 --- /dev/null +++ b/task/gitlab-set-status/0.3/tests/pre-apply-task-hook.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +kubectl -n ${tns} create secret generic gitlab-secret --from-literal token="secret" diff --git a/task/gitlab-set-status/0.3/tests/run.yaml b/task/gitlab-set-status/0.3/tests/run.yaml new file mode 100644 index 0000000000..7dda0a8722 --- /dev/null +++ b/task/gitlab-set-status/0.3/tests/run.yaml @@ -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"