diff --git a/charts/notification/.helmignore b/charts/notification/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/charts/notification/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/notification/Chart.lock b/charts/notification/Chart.lock new file mode 100644 index 0000000..ee0f31d --- /dev/null +++ b/charts/notification/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: file://../../common + version: 0.1.0 +digest: sha256:dd0c1a55ae9ff1f26b9173be4e954796ab5aafd5aed0828b443dc68684e8d592 +generated: "2023-10-06T22:08:04.524035034-06:00" diff --git a/charts/notification/Chart.yaml b/charts/notification/Chart.yaml new file mode 100644 index 0000000..cccebb0 --- /dev/null +++ b/charts/notification/Chart.yaml @@ -0,0 +1,29 @@ +apiVersion: v2 +name: notification +Name: notification +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" +dependencies: + - name: common + version: 0.1.0 + repository: file://../../common diff --git a/charts/notification/charts/common-0.1.0.tgz b/charts/notification/charts/common-0.1.0.tgz new file mode 100644 index 0000000..35d6b8b Binary files /dev/null and b/charts/notification/charts/common-0.1.0.tgz differ diff --git a/charts/notification/templates/eventlistener.yaml b/charts/notification/templates/eventlistener.yaml new file mode 100644 index 0000000..c9b64a8 --- /dev/null +++ b/charts/notification/templates/eventlistener.yaml @@ -0,0 +1 @@ +{{- template "common.eventlistener" . -}} diff --git a/charts/notification/templates/pipeline.yaml b/charts/notification/templates/pipeline.yaml new file mode 100644 index 0000000..d783b7a --- /dev/null +++ b/charts/notification/templates/pipeline.yaml @@ -0,0 +1 @@ +{{- template "common.pipeline" . -}} diff --git a/charts/notification/templates/task-copy-shared-utilities.yaml b/charts/notification/templates/task-copy-shared-utilities.yaml new file mode 100644 index 0000000..a6e87a5 --- /dev/null +++ b/charts/notification/templates/task-copy-shared-utilities.yaml @@ -0,0 +1,2 @@ +{{- template "common.task-copy-shared-utilities" . -}} + diff --git a/charts/notification/templates/task-git-semver.yaml b/charts/notification/templates/task-git-semver.yaml new file mode 100644 index 0000000..684e62c --- /dev/null +++ b/charts/notification/templates/task-git-semver.yaml @@ -0,0 +1,2 @@ +{{- template "common.task-git-semver" . -}} + diff --git a/charts/notification/templates/task-gitea-set-status.yaml b/charts/notification/templates/task-gitea-set-status.yaml new file mode 100644 index 0000000..3ea07f7 --- /dev/null +++ b/charts/notification/templates/task-gitea-set-status.yaml @@ -0,0 +1 @@ +{{- template "common.task-gitea-set-status" . -}} diff --git a/charts/notification/templates/task-golangci-lint.yaml b/charts/notification/templates/task-golangci-lint.yaml new file mode 100644 index 0000000..4abab23 --- /dev/null +++ b/charts/notification/templates/task-golangci-lint.yaml @@ -0,0 +1 @@ +{{- template "common.golangci-lint" . -}} diff --git a/charts/notification/templates/task-helm-upgrade-from-source.yaml b/charts/notification/templates/task-helm-upgrade-from-source.yaml new file mode 100644 index 0000000..105710a --- /dev/null +++ b/charts/notification/templates/task-helm-upgrade-from-source.yaml @@ -0,0 +1 @@ +{{- template "common.task-helm-upgrade-from-source" . -}} diff --git a/charts/notification/templates/task-openshift-client.yaml b/charts/notification/templates/task-openshift-client.yaml new file mode 100644 index 0000000..c5d5a12 --- /dev/null +++ b/charts/notification/templates/task-openshift-client.yaml @@ -0,0 +1 @@ +{{- template "common.task-openshift-client" . -}} diff --git a/charts/notification/templates/task-promote.yaml b/charts/notification/templates/task-promote.yaml new file mode 100644 index 0000000..3348059 --- /dev/null +++ b/charts/notification/templates/task-promote.yaml @@ -0,0 +1 @@ +{{- template "common.promote" . -}} diff --git a/charts/notification/templates/task-s2i-go.yaml b/charts/notification/templates/task-s2i-go.yaml new file mode 100644 index 0000000..4b5155d --- /dev/null +++ b/charts/notification/templates/task-s2i-go.yaml @@ -0,0 +1 @@ +{{- template "common.s2i-go" . -}} diff --git a/charts/notification/templates/triggerbinding.yaml b/charts/notification/templates/triggerbinding.yaml new file mode 100644 index 0000000..507db97 --- /dev/null +++ b/charts/notification/templates/triggerbinding.yaml @@ -0,0 +1 @@ +{{- template "common.triggerbinding" . -}} diff --git a/charts/notification/templates/triggertemplate.yaml b/charts/notification/templates/triggertemplate.yaml new file mode 100644 index 0000000..84f6cf8 --- /dev/null +++ b/charts/notification/templates/triggertemplate.yaml @@ -0,0 +1 @@ +{{- template "common.triggertemplate" . -}} diff --git a/charts/notification/values.yaml b/charts/notification/values.yaml new file mode 100644 index 0000000..fd54163 --- /dev/null +++ b/charts/notification/values.yaml @@ -0,0 +1,21 @@ +# Default values for notification. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: pipeline +quayHostname: quay01.ipa.endofday.com +eventlistener: + triggerBinding: gitea + interceptors: + secretKey: sharedSecret + secretName: webhook-secret + eventTypes: + - pull_request + additionalFilter: + - name: filter + value: | + body.action in ["opened"] + diff --git a/common/.helmignore b/common/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/common/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/common/Chart.yaml b/common/Chart.yaml new file mode 100644 index 0000000..c45a37a --- /dev/null +++ b/common/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: common +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.1.0" diff --git a/common/templates/_eventlistener.yaml b/common/templates/_eventlistener.yaml new file mode 100644 index 0000000..c16682a --- /dev/null +++ b/common/templates/_eventlistener.yaml @@ -0,0 +1,48 @@ +{{- define "common.eventlistener" }} +{{- $common := dict "Values" .Values.common -}} +{{- $noCommon := omit .Values "common" -}} +{{- $overrides := dict "Values" $noCommon -}} +{{- $noValues := omit . "Values" -}} +{{- with merge $noValues $overrides $common -}} +apiVersion: triggers.tekton.dev/v1beta1 +kind: EventListener +metadata: + name: {{ include "common.name" . }} + namespace: {{ .Release.Namespace }} +spec: + serviceAccountName: {{ .Values.serviceAccount }} + triggers: + - name: {{ include "common.name" . }}-trigger + template: + ref: {{ include "common.name" . }} + bindings: + - kind: TriggerBinding + ref: {{ .Values.eventlistener.triggerBinding }} + interceptors: + - name: gitea + params: + - name: secretRef + value: + secretKey: {{ .Values.eventlistener.interceptors.secretKey }} + secretName: {{ .Values.eventlistener.interceptors.secretName }} + - name: eventTypes + value: + {{- range .Values.eventlistener.eventTypes }} + - {{ . }} + {{- end }} + ref: + apiVersion: triggers.tekton.dev + kind: ClusterInterceptor + name: gitea + {{- if not (kindIs "invalid" .Values.eventlistener.additionalFilter ) }} + - name: run-if-additional-conditions-met + params: + {{- range .Values.eventlistener.additionalFilter }} + - {{ . | toYaml | nindent 14 }} + {{- end }} + ref: + kind: ClusterInterceptor + name: cel + {{- end }} +{{- end }} +{{- end }} diff --git a/common/templates/_helpers.tpl b/common/templates/_helpers.tpl new file mode 100644 index 0000000..5c3f420 --- /dev/null +++ b/common/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "common.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "common.labels" -}} +helm.sh/chart: {{ include "common.chart" . }} +{{ include "common.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "common.selectorLabels" -}} +app.kubernetes.io/name: {{ include "common.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "common.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "common.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/common/templates/_pipeline.yaml b/common/templates/_pipeline.yaml new file mode 100644 index 0000000..ee52c69 --- /dev/null +++ b/common/templates/_pipeline.yaml @@ -0,0 +1,442 @@ +{{- define "common.pipeline" }} +{{- $common := dict "Values" .Values.common -}} +{{- $noCommon := omit .Values "common" -}} +{{- $overrides := dict "Values" $noCommon -}} +{{- $noValues := omit . "Values" -}} +{{- with merge $noValues $overrides $common -}} +{{- $thisapp := include "common.name" . -}} +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + app: {{ include "common.name" . }} + name: {{ include "common.name" . }} + namespace: {{ .Release.Namespace }} +spec: + params: + - description: Ref of the application + name: ref + type: string + - description: git unique head commit id + name: revision + type: string + - description: repository name + name: repourl + type: string + - description: repository full name + name: repofullname + type: string + - description: commit author username + name: author + type: string + - description: commit author email + name: email + type: string + - description: commit message + name: message + type: string + - description: pull request index number + name: index + type: string + - description: The URL of the repo containing the helm charts + name: git-helm-url + type: string + - description: the base git server hostname + name: githost + type: string + - description: the base quay server hostname + name: quayhost + type: string + tasks: + - name: set-pending-status + params: + - name: githost + value: $(params.githost) + - name: statusurl + value: https://console-openshift-console.apps.ocp.endofday.com/pipelines/ns/goghvideo-cicd-pipeline/pipeline-runs + - name: revision + value: $(params.revision) + - name: repofullname + value: $(params.repofullname) + - name: description + value: CI Pipeline + - name: state + value: pending + taskRef: + kind: Task + name: gitea-set-status + workspaces: + - name: gitauth + workspace: gitauth + - name: copy-shared-utilities + runAfter: + - set-pending-status + taskRef: + kind: Task + name: copy-shared-utilities + workspaces: + - name: utilities + - name: prepare + params: + - name: gitrepositoryurl + value: $(params.repourl) + - name: gitbranch + value: $(params.ref) + runAfter: + - set-pending-status + taskRef: + kind: Task + name: git-semver + workspaces: + - name: repo + workspace: source + - name: gitauth + workspace: gitauth + - name: standards + params: + - name: package + value: $(params.githost)/goghvideo/{{ include "common.name" . }} + - name: context + value: ./{{ include "common.name" . }}/src + - name: version + value: latest + runAfter: + - prepare + taskRef: + kind: Task + name: golangci-lint + workspaces: + - name: source + workspace: source + - name: build + params: + - name: TLSVERIFY + value: "false" + - name: BUILDER_IMAGE + value: {{ .Values.quayHostname }}/goghvideo/golang-s2i-buildah:v1 + - name: PATH_CONTEXT + value: {{ include "common.name" . }}/src + - name: verbose + value: "true" + - name: IMAGE + value: {{ .Values.quayHostname }}/goghvideo/{{ include "common.name" . }}:$(params.revision) + - name: ENV_VARS + value: + - semver=$(tasks.prepare.results.version) + runAfter: + - standards + taskRef: + kind: Task + name: s2i-go + workspaces: + - name: source + workspace: source + - name: dockerconfig + workspace: dockerconfig + - name: ephemeral-namespace + params: + - name: VERSION + value: "4.11" + - name: SCRIPT + value: | + echo "${SHELL}" + RANDOMID=$(openssl rand -hex 4) + oc new-project goghvideo-test-${RANDOMID} >/dev/null + oc label namespace goghvideo-test-${RANDOMID} app=goghvideo-test + + x=0; until [[ -n $(oc -n goghvideo-test-${RANDOMID} get secret/goghvideo-openshift-builder-pull-secret 2>/dev/null) || $x -eq 10 ]]; do echo "Waiting for secret replication" && sleep 10 && ((x++)); done + if [[ "${x}" -eq 10 ]]; then exit 1; fi + + oc -n goghvideo-test-${RANDOMID} secrets link default goghvideo-openshift-builder-pull-secret --for=pull + + oc apply -f - </dev/null ) || $x -eq 10 ]]; do echo "Waiting for operator to deploy rabbit" && sleep 5 && ((x++)); done + if [[ "${x}" -eq 10 ]]; then exit 1; fi + + oc -n goghvideo-test-${RANDOMID} adm policy add-scc-to-user anyuid -z rabbitmq-server + + x=0; until [[ $(oc -n goghvideo-test-${RANDOMID} get sts rabbitmq-server -o jsonpath="{.status.readyReplicas}") -gt 0 || $x -eq 20 ]]; do echo "Waiting for Rabbit MQ to startup" && sleep 15 && ((x++)); done + if [[ "${x}" -eq 20 ]]; then exit 1; fi + oc -n goghvideo-test-${RANDOMID} create route edge --service=rabbitmq --port=15672 + + oc -n goghvideo-test-${RANDOMID} get pods + + RABBITHOST=$(oc -n goghvideo-test-${RANDOMID} get secret/rabbitmq-default-user -o template='{{ "{{" }} .data.host | base64decode {{ "}}" }}') + RABBITUSER=$(oc -n goghvideo-test-${RANDOMID} get secret/rabbitmq-default-user -o template='{{ "{{" }} .data.username | base64decode {{ "}}" }}') + RABBITPASS=$(oc -n goghvideo-test-${RANDOMID} get secret/rabbitmq-default-user -o template='{{ "{{" }} .data.password | base64decode {{ "}}" }}') + oc -n goghvideo-test-${RANDOMID} create secret generic amqp --from-literal=url=amqp://${RABBITUSER}:${RABBITPASS}@${RABBITHOST}/ + + curl -O http://${RABBITHOST}:15672/cli/rabbitmqadmin + chmod +x rabbitmqadmin + + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare exchange name=conversion type=topic + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=transcode durable=true queue_type=quorum + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=notification durable=true queue_type=quorum + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=upload-nextcloud durable=true queue_type=quorum + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=complete durable=true queue_type=quorum + + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="transcode" routing_key="transcode" + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="notification" routing_key="notification" + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="upload-nextcloud" routing_key="upload-nextcloud" + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="complete" routing_key="complete" + + echo -n "goghvideo-test-${RANDOMID}" > $(results.namespace.path) + runAfter: + - build + taskRef: + kind: Task + name: openshift-client + workspaces: + - name: kubeconfig-dir + workspace: dockerconfig + - name: prepare-helm-charts + params: + - name: url + value: $(params.git-helm-url) + runAfter: + - ephemeral-namespace + taskRef: + kind: Task + name: git-clone + workspaces: + - name: output + workspace: helm + - name: basic-auth + workspace: gitauth + - name: deploy-notification-app + params: + - name: charts_dir + value: notification + - name: release_namespace + value: $(tasks.ephemeral-namespace.results.namespace) + - name: release_name + value: notification + {{- if eq $thisapp "notification" }} + - name: overwrite_values + value: image.tag=$(params.revision) + {{- end }} + runAfter: + - prepare-helm-charts + taskRef: + kind: Task + name: helm-upgrade-from-source + workspaces: + - name: source + workspace: helm + - name: deploy-upload-to-nextcloud-app + params: + - name: charts_dir + value: upload-to-nextcloud + - name: release_namespace + value: $(tasks.ephemeral-namespace.results.namespace) + - name: release_name + value: upload-to-nextcloud + {{- if eq $thisapp "upload-to-nextcloud" }} + - name: overwrite_values + value: image.tag=$(params.revision) + {{- end }} + runAfter: + - prepare-helm-charts + taskRef: + kind: Task + name: helm-upgrade-from-source + workspaces: + - name: source + workspace: helm + - name: deploy-conversion-engine-job + params: + - name: charts_dir + value: conversion-engine + - name: release_namespace + value: $(tasks.ephemeral-namespace.results.namespace) + - name: release_name + value: conversion-engine + {{- if eq $thisapp "conversion-engine" }} + - name: overwrite_values + value: image.tag=$(params.revision) + {{- end }} + runAfter: + - prepare-helm-charts + taskRef: + kind: Task + name: helm-upgrade-from-source + workspaces: + - name: source + workspace: helm + - name: get-filedrop-name + params: + - name: VERSION + value: "4.11" + - name: SCRIPT + value: | + #!/usr/bin/env bash + wget "https://github.com/jqlang/jq/releases/download/jq-1.7/jq-linux-amd64" -O /usr/local/bin/jq + chmod +x /usr/local/bin/jq + INPUTSRC=$(oc -n $(tasks.ephemeral-namespace.results.namespace) get scaledjob/conversion-engine -o json | /usr/local/bin/jq -r '.spec.jobTargetRef.template.spec.initContainers[0].env[] | select(.name == "sourcefile").value') + if [[ -z "${INPUTSRC}" ]]; then exit 1; fi + echo -n "${INPUTSRC}" > $(results.filedrop.path) + runAfter: + - deploy-conversion-engine-job + - deploy-upload-to-nextcloud-app + - deploy-notification-app + taskRef: + kind: Task + name: openshift-client + workspaces: + - name: kubeconfig-dir + workspace: dockerconfig + - name: perform-e2e-test + params: + - name: VERSION + value: "4.11" + - name: SCRIPT + value: | + #!/usr/bin/env bash + oc create -f - < $(results.version.path) + exit 0 + securityContext: + runAsNonRoot: true + runAsUser: 65532 + workspaces: + - name: repo + - name: gitauth +{{- end }} +{{- end }} diff --git a/common/templates/_task-gitea-set-status.yaml b/common/templates/_task-gitea-set-status.yaml new file mode 100644 index 0000000..2200241 --- /dev/null +++ b/common/templates/_task-gitea-set-status.yaml @@ -0,0 +1,81 @@ +{{- define "common.task-gitea-set-status" }} +{{- $common := dict "Values" .Values.common -}} +{{- $noCommon := omit .Values "common" -}} +{{- $overrides := dict "Values" $noCommon -}} +{{- $noValues := omit . "Values" -}} +{{- with merge $noValues $overrides $common -}} +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: gitea-set-status + namespace: {{ .Release.Namespace }} +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 `gitea-set-status` task allows external services to mark Gitea commits with an `error`, `failure`, `pending`, or `success` state, which is then reflected in pull requests involving those commits. Statuses include as well a `description` and a `target_url`, to give the user informations about the CI statuses or a direct link to the full log. + params: + - name: githost + type: string + - name: repofullname + type: string + - name: revision + type: string + - name: statusurl + type: string + - name: description + type: string + - default: continuous-integration/tekton + name: context + type: string + - name: state + type: string + steps: + - image: {{ .Values.quayHostname }}/goghvideo/python:3-alpine + name: set-status + script: | + #!/usr/bin/env python + + """This script will set the CI status on a Gitea commit""" + + import json + import sys + import http.client + + gitea_token = open("$(workspaces.gitauth.path)/password", "r").read() + + status_url = "/api/v1/repos/$(params.repofullname)/statuses/$(params.revision)" + + data = { + "state": "$(params.state)", + "target_url": "$(params.statusurl)", + "description": "$(params.description)", + "context": "$(params.context)" + } + print("Sending this data to Gitea: ") + print(data) + + authHeader = "token " + gitea_token + + conn = http.client.HTTPSConnection("$(params.githost)") + + conn.request( + "POST", + status_url, + body=json.dumps(data), + headers={ + "User-Agent": "TektonCD, the peaceful cat", + "Authorization": authHeader, + "Accept": "application/json", + "Content-Type": "application/json", + }) + resp = conn.getresponse() + if not str(resp.status).startswith("2"): + print("Error: %d" % (resp.status)) + print(resp.read()) + sys.exit(1) + else: + print("Gitea status has been set") + workspaces: + - name: gitauth +{{- end }} +{{- end }} diff --git a/common/templates/_task-golangci-lint.yaml b/common/templates/_task-golangci-lint.yaml new file mode 100644 index 0000000..1555447 --- /dev/null +++ b/common/templates/_task-golangci-lint.yaml @@ -0,0 +1,78 @@ +{{- define "common.golangci-lint" }} +{{- $common := dict "Values" .Values.common -}} +{{- $noCommon := omit .Values "common" -}} +{{- $overrides := dict "Values" $noCommon -}} +{{- $noValues := omit . "Values" -}} +{{- with merge $noValues $overrides $common -}} +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: golangci-lint + namespace: {{ .Release.Namespace }} +spec: + description: This Task is Golang task to validate Go projects. + params: + - description: base package (and its children) under validation + name: package + type: string + - default: . + description: path to the directory to use as context. + name: context + type: string + - default: --verbose + description: flags to use for the test command + name: flags + type: string + - default: v1.39 + description: golangci-lint version to use + name: version + type: string + - default: linux + description: running operating system target + name: GOOS + type: string + - default: amd64 + description: running architecture target + name: GOARCH + type: string + - default: auto + description: value of module support + name: GO111MODULE + type: string + - default: "" + description: Go caching directory path + name: GOCACHE + type: string + - default: "" + description: Go mod caching directory path + name: GOMODCACHE + type: string + - default: "" + description: golangci-lint cache path + name: GOLANGCI_LINT_CACHE + type: string + steps: + - env: + - name: GOPATH + value: /workspace + - name: GOOS + value: $(params.GOOS) + - name: GOARCH + value: $(params.GOARCH) + - name: GO111MODULE + value: $(params.GO111MODULE) + - name: GOCACHE + value: $(params.GOCACHE) + - name: GOMODCACHE + value: $(params.GOMODCACHE) + - name: GOLANGCI_LINT_CACHE + value: $(params.GOLANGCI_LINT_CACHE) + image: {{ .Values.quayHost }}/goghvideo/golang-lint:$(params.version) + name: lint + script: | + golangci-lint run $(params.flags) + workingDir: $(workspaces.source.path)/$(params.context) + workspaces: + - name: source +{{- end }} +{{- end }} diff --git a/common/templates/_task-helm-upgrade-from-source.yaml b/common/templates/_task-helm-upgrade-from-source.yaml new file mode 100644 index 0000000..bcf476c --- /dev/null +++ b/common/templates/_task-helm-upgrade-from-source.yaml @@ -0,0 +1,60 @@ +{{- define "common.task-helm-upgrade-from-source" }} +{{- $common := dict "Values" .Values.common -}} +{{- $noCommon := omit .Values "common" -}} +{{- $overrides := dict "Values" $noCommon -}} +{{- $noValues := omit . "Values" -}} +{{- with merge $noValues $overrides $common -}} +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: helm-upgrade-from-source + namespace: {{ .Release.Namespace }} +spec: + description: These tasks will install / upgrade a helm chart into your Kubernetes + / OpenShift Cluster using Helm + params: + - description: The directory in source that contains the helm chart + name: charts_dir + type: string + - default: v1.0.0 + description: The helm release version in semantic versioning format + name: release_version + type: string + - default: helm-release + description: The helm release name + name: release_name + type: string + - default: "" + description: The helm release namespace + name: release_namespace + type: string + - default: "" + description: 'Specify the values you want to overwrite, comma separated: autoscaling.enabled=true,replicas=1' + name: overwrite_values + type: string + - default: values.yaml + description: The values file to be used + name: values_file + type: string + - default: docker.io/lachlanevenson/k8s-helm@sha256:5c792f29950b388de24e7448d378881f68b3df73a7b30769a6aa861061fd08ae + description: helm image to be used + name: helm_image + type: string + - default: "" + description: Extra parameters passed for the helm upgrade command + name: upgrade_extra_params + type: string + steps: + - image: $(params.helm_image) + name: upgrade + script: | + echo current installed helm releases + helm list --namespace "$(params.release_namespace)" + + echo installing helm chart... + helm upgrade --install --wait --values "$(params.charts_dir)/$(params.values_file)" --namespace "$(params.release_namespace)" --version "$(params.release_version)" "$(params.release_name)" "$(params.charts_dir)" --debug --set "$(params.overwrite_values)" $(params.upgrade_extra_params) + workingDir: /workspace/source + workspaces: + - name: source +{{- end }} +{{- end }} diff --git a/common/templates/_task-openshift-client.yaml b/common/templates/_task-openshift-client.yaml new file mode 100644 index 0000000..b6da707 --- /dev/null +++ b/common/templates/_task-openshift-client.yaml @@ -0,0 +1,56 @@ +{{- define "common.task-openshift-client" }} +{{- $common := dict "Values" .Values.common -}} +{{- $noCommon := omit .Values "common" -}} +{{- $overrides := dict "Values" $noCommon -}} +{{- $noValues := omit . "Values" -}} +{{- with merge $noValues $overrides $common -}} +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: openshift-client + namespace: {{ .Release.Namespace }} +spec: + description: |- + This task runs commands against the cluster provided by user and if not provided then where the Task is being executed. + OpenShift is a Kubernetes distribution from Red Hat which provides oc, the OpenShift CLI that complements kubectl for simplifying deployment and configuration applications on OpenShift. + params: + - default: oc help + description: The OpenShift CLI arguments to run + name: SCRIPT + type: string + - default: "4.7" + description: The OpenShift Version to use + name: VERSION + type: string + results: + - description: The namespace which was created + name: namespace + type: string + - description: The name of the filedrop for testing + name: filedrop + type: string + steps: + - image: quay.io/openshift/origin-cli:$(params.VERSION) + name: oc + script: | + #!/usr/bin/env bash + + [[ "$(workspaces.manifest-dir.bound)" == "true" ]] && \ + cd $(workspaces.manifest-dir.path) + + [[ "$(workspaces.kubeconfig-dir.bound)" == "true" ]] && \ + [[ -f $(workspaces.kubeconfig-dir.path)/kubeconfig ]] && \ + export KUBECONFIG=$(workspaces.kubeconfig-dir.path)/kubeconfig + + $(params.SCRIPT) + workspaces: + - description: The workspace which contains kubernetes manifests which we want to + apply on the cluster. + name: manifest-dir + optional: true + - description: The workspace which contains the the kubeconfig file if in case we + want to run the oc command on another cluster. + name: kubeconfig-dir + optional: true +{{- end }} +{{- end }} diff --git a/common/templates/_task-promote.yaml b/common/templates/_task-promote.yaml new file mode 100644 index 0000000..0bf3915 --- /dev/null +++ b/common/templates/_task-promote.yaml @@ -0,0 +1,241 @@ +{{- define "common.promote" }} +{{- $common := dict "Values" .Values.common -}} +{{- $noCommon := omit .Values "common" -}} +{{- $overrides := dict "Values" $noCommon -}} +{{- $noValues := omit . "Values" -}} +{{- with merge $noValues $overrides $common -}} +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: promote + namespace: {{ .Release.Namespace }} +spec: + params: + - description: The git branch reference + name: ref + type: string + - name: repofullname + type: string + - description: git unique head commit id + name: revision + type: string + - description: Symantic version number + name: semver + type: string + - name: author + type: string + - name: email + type: string + - name: appname + type: string + - name: index + type: string + - name: githost + type: string + - name: quayhost + type: string + steps: + - image: {{ .Values.quayHostname }}/goghvideo/python:3-alpine + name: tag-image-with-release-ver + script: | + #!/usr/bin/env python + + """This script will set tag the image with the release version""" + + import json + import sys + import http.client + import ssl + + quay_token = open("$(workspaces.quayauth.path)/apikey", "r").read() + authHeader = "Bearer " + quay_token + + conn = http.client.HTTPSConnection( + "{{ .Values.quayHostname }}", + context = ssl._create_unverified_context() + ) + + existing_tag = "/api/v1/repository/$(params.repofullname)/tag/?specificTag=$(params.revision)" + + print("Getting existing tag information from Quay") + print("URL: %s" % (existing_tag)) + + conn.request( + "GET", + existing_tag, + headers={ + "User-Agent": "TektonCD, the peaceful cat", + "Authorization": authHeader, + "Accept": "application/json", + "Content-Type": "application/json", + } + ) + resp = conn.getresponse() + if not str(resp.status).startswith("2"): + print("Error: %d" % (resp.status)) + print(resp.read()) + sys.exit(1) + else: + print("Successfully Retrieved quay information for tag") + tag_info = json.loads(resp.read().decode('utf-8')) + for item in tag_info['tags']: + manifest_digest = item['manifest_digest'] + + print("Tagging image with semver") + tag_url = "/api/v1/repository/$(params.repofullname)/tag/v$(params.semver)" + print("URL: %s" % (tag_url)) + print("Manifest SHA: %s" % (manifest_digest)) + + data = { + "manifest_digest": manifest_digest + } + + conn.request( + "PUT", + tag_url, + body=json.dumps(data), + headers={ + "User-Agent": "TektonCD, the peaceful cat", + "Authorization": authHeader, + "Accept": "application/json", + "Content-Type": "application/json", + } + ) + resp = conn.getresponse() + if not str(resp.status).startswith("2"): + print("Error: %d" % (resp.status)) + print(resp.read()) + sys.exit(1) + else: + print("Successfully tagged image") + - image: {{ .Values.quayHostname }}/goghvideo/bitnami-git:latest + name: release-notes + script: | + #!/bin/sh + export USERNAME=$(cat $(workspaces.gitauth.path)/username) + export PASSWORD=$(cat $(workspaces.gitauth.path)/password) + + git config --global --add safe.directory $(workspaces.source.path)/$(params.appname) + git config --global user.name "$(params.author)" + git config --global user.email "$(params.email)" + + HOSTPATH=$(git remote get-url origin | sed 's_https://__') + git remote set-url origin https://${USERNAME}:${PASSWORD}@${HOSTPATH} + + git fetch --all --tags >/dev/null 2>&1 + #git log main..$(params.ref) --oneline --no-merges --decorate > release-v$(params.semver).md 2>/dev/null + #git add release-v$(params.semver).md + #git commit -m "Including release notes" + git tag -a v$(params.semver) -m "Upgrade to v$(params.semver)" + git push origin $(params.ref) --tags + workingDir: $(workspaces.source.path)/$(params.appname) + - image: {{ .Values.quayHostname }}/goghvideo/python:3-alpine + name: get-tag-data + script: | + #!/usr/bin/env python + + """This script will get the Gitea tag status""" + + import json + import sys + import http.client + + gitea_token = open("$(workspaces.gitauth.path)/password", "r").read() + + merge_url = "https://$(params.githost)/api/v1" + "/repos/$(params.repofullname)/" + \ + "commits/v$(params.semver)/status" + + authHeader = "token " + gitea_token + + conn = http.client.HTTPSConnection("$(params.githost)") + + conn.request( + "GET", + merge_url, + headers={ + "User-Agent": "TektonCD, the peaceful cat", + "Authorization": authHeader, + "Accept": "application/json", + "Content-Type": "application/json", + }) + resp = conn.getresponse() + if not str(resp.status).startswith("2"): + print("Error: %d" % (resp.status)) + print(resp.read()) + sys.exit(1) + else: + print("Gitea tag verification completed on $(params.githost)") + - image: {{ .Values.quayHostname }}/goghvideo/python:3-alpine + name: merge-pull-request + script: | + #!/usr/bin/env python + + """This script will set the CI status on a Gitea commit""" + + import json + import sys + import http.client + + gitea_token = open("$(workspaces.gitauth.path)/password", "r").read() + + merge_url = "https://$(params.githost)/api/v1" + "/repos/$(params.repofullname)/" + \ + "pulls/$(params.index)/merge" + + data = { + "Do": "merge" + } + print("Sending this data to Gitea: ") + print(data) + + authHeader = "token " + gitea_token + + conn = http.client.HTTPSConnection("$(params.githost)") + + conn.request( + "POST", + merge_url, + body=json.dumps(data), + headers={ + "User-Agent": "TektonCD, the peaceful cat", + "Authorization": authHeader, + "Accept": "application/json", + "Content-Type": "application/json", + }) + resp = conn.getresponse() + if not str(resp.status).startswith("2"): + print("Error: %d" % (resp.status)) + print(resp.read()) + sys.exit(1) + else: + print("Gitea merge completed on $(params.githost)") + - image: {{ .Values.quayHostname}}/goghvideo/bitnami-git:latest + name: update-helm-chart + script: | + #!/bin/sh + export USERNAME=$(cat $(workspaces.gitauth.path)/username) + export PASSWORD=$(cat $(workspaces.gitauth.path)/password) + + git config --global --add safe.directory $(workspaces.helm.path) + git config --global user.name "$(params.author)" + git config --global user.email "$(params.email)" + + HOSTPATH=$(git remote get-url origin | sed 's_https://__') + git remote set-url origin https://${USERNAME}:${PASSWORD}@${HOSTPATH} + git fetch + git checkout main && git pull + + $(workspaces.utilities.path)/yq -i '.version |= (split(".") | .[-1] |= ((. tag = "!!int") + 1) | join("."))' $(params.appname)/Chart.yaml + $(workspaces.utilities.path)/yq -i '.appVersion="v$(params.semver)"' $(params.appname)/Chart.yaml + + git add $(params.appname)/Chart.yaml + git commit -m "Updating chart version" + git push + workingDir: $(workspaces.helm.path) + workspaces: + - name: source + - name: gitauth + - name: quayauth + - name: utilities + - name: helm +{{- end }} +{{- end }} diff --git a/common/templates/_task-s2i-go.yaml b/common/templates/_task-s2i-go.yaml new file mode 100644 index 0000000..6106d60 --- /dev/null +++ b/common/templates/_task-s2i-go.yaml @@ -0,0 +1,115 @@ +{{- define "common.s2i-go" }} +{{- $common := dict "Values" .Values.common -}} +{{- $noCommon := omit .Values "common" -}} +{{- $overrides := dict "Values" $noCommon -}} +{{- $noValues := omit . "Values" -}} +{{- with merge $noValues $overrides $common -}} +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: s2i-go + namespace: {{ .Release.Namespace }} +spec: + description: s2i-go task clones a Git repository and builds and pushes a container + image using S2I and a Go builder image. + params: + - default: latest + description: The tag of go imagestream for go version + name: VERSION + type: string + - default: . + description: The location of the path to run s2i from. + name: PATH_CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - description: Location of the repo where image has to be pushed + name: IMAGE + type: string + - default: registry.redhat.io/rhel8/buildah@sha256:00795fafdab9bbaa22cd29d1faa1a01e604e4884a2c935c1bf8e3d1f0ad1c084 + description: The location of the buildah builder image. + name: BUILDER_IMAGE + type: string + - default: "false" + description: Skip pushing the built image + name: SKIP_PUSH + type: string + - description: Environment variables to set during _build-time_. + name: ENV_VARS + type: array + results: + - description: Digest of the image just built. + name: IMAGE_DIGEST + type: string + steps: + - args: + - $(params.ENV_VARS[*]) + env: + - name: HOME + value: /tekton/home + image: registry.redhat.io/ocp-tools-4-tech-preview/source-to-image-rhel8@sha256:98d8cb3a255641ca6a1bce854e5e2460c20de9fb9b28e3cc67eb459f122873dd + name: generate + script: | + echo "Processing Build Environment Variables" + echo "" > /env-vars/env-file + for var in "$@" + do + echo "$var" >> /env-vars/env-file + done + + echo "Outputting Generated /env-vars/env-file" + cat /env-vars/env-file + + s2i build $(params.PATH_CONTEXT) image-registry.openshift-image-registry.svc:5000/openshift/golang:$(params.VERSION) \ + --as-dockerfile /gen-source/Dockerfile.gen --environment-file /env-vars/env-file + + echo "Outputting Generated /gen-source/Dockerfile.gen file" + cat /gen-source/Dockerfile.gen + volumeMounts: + - mountPath: /gen-source + name: gen-source + - mountPath: /env-vars + name: env-vars + workingDir: $(workspaces.source.path) + - image: $(params.BUILDER_IMAGE) + name: build-and-push + script: | + find . -type f -ls + + buildah --log-level=info bud --storage-driver=vfs --tls-verify=$(params.TLSVERIFY) \ + --layers -f /gen-source/Dockerfile.gen -t $(params.IMAGE) . + + [[ "$(params.SKIP_PUSH)" == "true" ]] && echo "Push skipped" && exit 0 + [[ "$(workspaces.dockerconfig.bound)" == "true" ]] && export DOCKER_CONFIG="$(workspaces.dockerconfig.path)" + buildah push --storage-driver=vfs --tls-verify=$(params.TLSVERIFY) \ + --digestfile $(workspaces.source.path)/image-digest $(params.IMAGE) \ + docker://$(params.IMAGE) + + cat $(workspaces.source.path)/image-digest | tee /tekton/results/IMAGE_DIGEST + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /gen-source + name: gen-source + workingDir: /gen-source + volumes: + - name: varlibcontainers + - name: gen-source + - name: env-vars + workspaces: + - mountPath: /workspace/source + name: source + - description: An optional workspace that allows providing a .docker/config.json + file for Buildah to access the container registry. The file should be placed + at the root of the Workspace with name config.json. + name: dockerconfig + optional: true +{{- end }} +{{- end }} diff --git a/common/templates/_triggerbinding.yaml b/common/templates/_triggerbinding.yaml new file mode 100644 index 0000000..53290d8 --- /dev/null +++ b/common/templates/_triggerbinding.yaml @@ -0,0 +1,34 @@ +{{- define "common.triggerbinding" }} +{{- $common := dict "Values" .Values.common -}} +{{- $noCommon := omit .Values "common" -}} +{{- $overrides := dict "Values" $noCommon -}} +{{- $noValues := omit . "Values" -}} +{{- with merge $noValues $overrides $common -}} +apiVersion: triggers.tekton.dev/v1beta1 +kind: TriggerBinding +metadata: + name: gitea + namespace: {{ .Release.Namespace }} +spec: + params: + - name: ref + value: $(body.pull_request.head.ref) + - name: revision + value: $(body.pull_request.head.sha) + - name: repourl + value: $(body.pull_request.head.repo.clone_url) + - name: reponame + value: $(body.pull_request.head.repo.name) + - name: repofullname + value: $(body.pull_request.head.repo.full_name) + - name: message + value: $(body.pull_request.title) + - name: author + value: $(body.pull_request.user.login) + - name: email + value: $(body.pull_request.user.email) + - name: index + value: $(body.pull_request.number) +{{- end }} +{{- end }} + diff --git a/common/templates/_triggertemplate.yaml b/common/templates/_triggertemplate.yaml new file mode 100644 index 0000000..4ee1765 --- /dev/null +++ b/common/templates/_triggertemplate.yaml @@ -0,0 +1,95 @@ +{{- define "common.triggertemplate" }} +{{- $common := dict "Values" .Values.common -}} +{{- $noCommon := omit .Values "common" -}} +{{- $overrides := dict "Values" $noCommon -}} +{{- $noValues := omit . "Values" -}} +{{- with merge $noValues $overrides $common -}} +apiVersion: triggers.tekton.dev/v1beta1 +kind: TriggerTemplate +metadata: + name: {{ include "common.name" . }} + namespace: {{ .Release.Namespace }} +spec: + params: + - description: The git repository url + name: gitrepositoryurl + - description: The org and repo name + name: gitfullreponame + - description: The name of the repo + name: gitreponame + - description: Branch to act on + name: gitbranch + - description: The SHA head + name: gitcommitsha + - description: The pull request reference + name: gitprindex + resourcetemplates: + - apiVersion: tekton.dev/v1beta1 + kind: PipelineRun + metadata: + generateName: {{ include "common.name" . }}- + spec: + params: + - name: git-repo-url + value: $(tt.params.gitrepositoryurl) + - name: git-repo-full-name + value: $(tt.params.gitfullreponame) + - name: git-branch + value: $(tt.params.gitbranch) + - name: git-commit-sha + value: $(tt.params.gitcommitsha) + - name: git-pr-index + value: $(tt.params.gitprindex) + - name: verbose + value: true + - name: lint-package + value: git.endofday.com/goghvideo/{{ include "common.name" . }} + - name: lint-context + value: $(tt.params.gitreponame)/src + - name: image + value: {{ .Values.quayHostname }}/goghvideo/{{ include "common.name" . }} + - name: s2i-builder-image + value: {{ .Values.quayHostname }}/goghvideo/golang-s2i-buildah:v1 + - name: git-token-secret-name + value: git-http-credentials + - name: git-token-secret-key + value: password + - name: git-merge-type + value: merge + - name: git-merge-delete-branch + value: true + - name: git-helm-url + value: https://git.endofday.com/goghvideo/helm.git + pipelineRef: + name: {{ include "common.name" . }} + serviceAccountName: pipeline + workspaces: + - name: source + volumeClaimTemplate: + spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: nfs-client + - name: gitauth + secret: + secretName: git-http-credentials + - name: gitsshauth + secret: + secretName: git-credentials + - name: dockerconfig + secret: + secretName: goghvideo-container-registry-push + - name: helm + volumeClaimTemplate: + spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: nfs-client +{{- end }} +{{- end }} diff --git a/common/values.yaml b/common/values.yaml new file mode 100644 index 0000000..023fda8 --- /dev/null +++ b/common/values.yaml @@ -0,0 +1,4 @@ +# Default values for common. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + diff --git a/eventlistener/notification-webhook-listener-orig.yaml b/eventlistener/notification-webhook-listener-orig.yaml new file mode 100644 index 0000000..46f5a6d --- /dev/null +++ b/eventlistener/notification-webhook-listener-orig.yaml @@ -0,0 +1,34 @@ +apiVersion: triggers.tekton.dev/v1beta1 +kind: EventListener +metadata: + name: notification-webhook-listener + namespace: goghvideo-cicd-pipeline +spec: + serviceAccountName: pipeline + triggers: + - name: notification-greeter-webhook + interceptors: + - name: gitea + ref: + name: gitea + kind: ClusterInterceptor + apiVersion: triggers.tekton.dev + params: + - name: secretRef + value: + secretName: webhook-secret + secretKey: sharedSecret + - name: eventTypes + value: ["pull_request", "pull_request_sync"] + - name: allow-create-and-update-only + ref: + name: cel + kind: ClusterInterceptor + params: + - name: filter + value: > + body.action in ['opened', 'synchronized'] + bindings: + - ref: gitea-binding + template: + ref: notification-template diff --git a/eventlistener/notification-webhook-listener-push.yaml b/eventlistener/notification-webhook-listener-push.yaml new file mode 100644 index 0000000..f139058 --- /dev/null +++ b/eventlistener/notification-webhook-listener-push.yaml @@ -0,0 +1,34 @@ +apiVersion: triggers.tekton.dev/v1beta1 +kind: EventListener +metadata: + name: notification + namespace: goghvideo-cicd-pipeline +spec: + serviceAccountName: pipeline + triggers: + - name: notification-push-webhook + interceptors: + - name: gitea + ref: + name: gitea + kind: ClusterInterceptor + apiVersion: triggers.tekton.dev + params: + - name: secretRef + value: + secretName: webhook-secret + secretKey: sharedSecret + - name: eventTypes + value: ["push"] +# - name: allow-create-and-update-only +# ref: +# name: cel +# kind: ClusterInterceptor +# params: +# - name: filter +# value: > +# body.ref in ["feature"] + bindings: + - ref: gitea-push-binding + template: + ref: notification-trigger-template diff --git a/pipeline/cd-notification.yaml b/pipeline/cd-notification.yaml new file mode 100644 index 0000000..ac7a058 --- /dev/null +++ b/pipeline/cd-notification.yaml @@ -0,0 +1,437 @@ +apiVersion: tekton.dev/v1beta1 +kind: Pipeline +metadata: + name: notification-deploy + namespace: goghvideo-cicd-pipeline +spec: + workspaces: + - name: source + - name: gitauth + - name: dockerconfig + - name: helm + - name: gitsshauth + params: + - name: git-repo-full-name + type: string + - name: git-token-secret-name + type: string + - name: git-token-secret-key + type: string + - name: git-commit-sha + type: string + - name: git-repo-url + type: string + description: Git URL to retrieve + - name: git-branch + type: string + description: branch to checkout + - name: git-pr-index + description: PR number to merge + - name: git-merge-type + description: What type of merge to do + - name: git-merge-delete-branch + description: delete the branch after merge + - name: verbose + type: string + default: "false" + - name: lint-package + type: string + - name: lint-context + type: string + description: Path to where the modules are stored + - name: lint-version + type: string + default: latest + - name: image + type: string + - name: s2i-builder-image + type: string + - name: git-helm-url + type: string + tasks: + - name: set-check-pending + taskRef: + name: gitea-set-status + params: + - name: SHA + value: $(params.git-commit-sha) + - name: GITEA_HOST_URL + value: git.endofday.com + - name: REPO_FULL_NAME + value: $(params.git-repo-full-name) + - name: GITEA_TOKEN_SECRET_NAME + value: $(params.git-token-secret-name) + - name: GITEA_TOKEN_SECRET_KEY + value: $(params.git-token-secret-key) + - name: DESCRIPTION + value: Build started + - name: STATE + value: pending + - name: TARGET_URL + value: https://console-openshift-console.apps.ocp.endofday.com/pipelines/all-namespaces + - name: git-semver + runAfter: + - set-check-pending + taskRef: + name: git-semver + params: + - name: gitrepositoryurl + value: $(params.git-repo-url) + - name: gitbranch + value: $(params.git-branch) + workspaces: + - name: repo + workspace: source + - name: gitauth + workspace: gitauth + - name: golangci-lint + runAfter: + - git-semver + taskRef: + name: golangci-lint + params: + - name: package + value: $(params.lint-package) + - name: context + value: $(params.lint-context) + - name: version + value: $(params.lint-version) + workspaces: + - name: source + workspace: source + - name: generate-imagetag + runAfter: + - golangci-lint + taskRef: + name: generate-image-tag + params: + - name: version + value: $(tasks.git-semver.results.version) + - name: image + value: $(params.image) + - name: s2i-build + runAfter: + - generate-imagetag + taskRef: + name: s2i-go-debug + params: + - name: TLSVERIFY + value: false + - name: BUILDER_IMAGE + value: $(params.s2i-builder-image) + - name: PATH_CONTEXT + value: $(params.lint-context) + - name: verbose + value: true + - name: IMAGE + value: $(tasks.generate-imagetag.results.imagetag) + - name: ENV_VARS + value: + - semver=$(tasks.git-semver.results.version) + workspaces: + - name: source + workspace: source + - name: dockerconfig + workspace: dockerconfig + - name: ephemeral-ns + runAfter: + - s2i-build + taskref: + name: openshift-ephemeral-namespace-client + kind: Task + params: + - name: VERSION + value: 4.11 + - name: SCRIPT + value: | + echo "${SHELL}" + RANDOMID=$(openssl rand -hex 4) + oc new-project goghvideo-test-${RANDOMID} >/dev/null + oc label namespace goghvideo-test-${RANDOMID} app=goghvideo-test + + x=0; until [[ -n $(oc -n goghvideo-test-${RANDOMID} get secret/goghvideo-openshift-builder-pull-secret 2>/dev/null) || $x -eq 10 ]]; do echo "Waiting for secret replication" && sleep 10 && ((x++)); done + if [[ "${x}" -eq 10 ]]; then exit 1; fi + + oc -n goghvideo-test-${RANDOMID} secrets link default goghvideo-openshift-builder-pull-secret --for=pull + + oc apply -f - </dev/null ) || $x -eq 10 ]]; do echo "Waiting for operator to deploy rabbit" && sleep 5 && ((x++)); done + if [[ "${x}" -eq 10 ]]; then exit 1; fi + + oc -n goghvideo-test-${RANDOMID} adm policy add-scc-to-user anyuid -z rabbitmq-server + + x=0; until [[ $(oc -n goghvideo-test-${RANDOMID} get sts rabbitmq-server -o jsonpath="{.status.readyReplicas}") -gt 0 || $x -eq 20 ]]; do echo "Waiting for Rabbit MQ to startup" && sleep 15 && ((x++)); done + if [[ "${x}" -eq 20 ]]; then exit 1; fi + oc -n goghvideo-test-${RANDOMID} create route edge --service=rabbitmq --port=15672 + + oc -n goghvideo-test-${RANDOMID} get pods + + RABBITHOST=$(oc -n goghvideo-test-${RANDOMID} get secret/rabbitmq-default-user -o template='{{ .data.host | base64decode }}') + RABBITUSER=$(oc -n goghvideo-test-${RANDOMID} get secret/rabbitmq-default-user -o template='{{ .data.username | base64decode }}') + RABBITPASS=$(oc -n goghvideo-test-${RANDOMID} get secret/rabbitmq-default-user -o template='{{ .data.password | base64decode }}') + oc -n goghvideo-test-${RANDOMID} create secret generic amqp --from-literal=url=amqp://${RABBITUSER}:${RABBITPASS}@${RABBITHOST}/ + + curl -O http://${RABBITHOST}:15672/cli/rabbitmqadmin + chmod +x rabbitmqadmin + + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare exchange name=conversion type=topic + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=transcode durable=true queue_type=quorum + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=notification durable=true queue_type=quorum + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=upload-nextcloud durable=true queue_type=quorum + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=complete durable=true queue_type=quorum + + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="transcode" routing_key="transcode" + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="notification" routing_key="notification" + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="upload-nextcloud" routing_key="upload-nextcloud" + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="complete" routing_key="complete" + + echo -n "goghvideo-test-${RANDOMID}" > $(results.namespace.path) + workspaces: + - name: kubeconfig-dir + workspace: dockerconfig + - name: clone-helm-charts + runAfter: ["ephemeral-ns"] + taskRef: + name: git-clone + params: + - name: url + value: $(params.git-helm-url) + workspaces: + - name: output + workspace: helm + - name: ssh-directory + workspace: gitsshauth + - name: deploy-notification + runAfter: ["clone-helm-charts"] + taskRef: + name: helm-upgrade-from-source + params: + - name: charts_dir + value: notification + - name: release_namespace + value: $(tasks.ephemeral-ns.results.namespace) + - name: release_name + value: notification + - name: overwrite_values + value: "image.tag=v$(tasks.git-semver.results.version)" + workspaces: + - name: source + workspace: helm + - name: deploy-upload-to-nextcloud + runAfter: ["clone-helm-charts"] + taskRef: + name: helm-upgrade-from-source + params: + - name: charts_dir + value: upload-to-nextcloud + - name: release_namespace + value: $(tasks.ephemeral-ns.results.namespace) + - name: release_name + value: upload-to-nextcloud + workspaces: + - name: source + workspace: helm + - name: deploy-conversion-engine + runAfter: ["clone-helm-charts"] + taskRef: + name: helm-upgrade-from-source + params: + - name: charts_dir + value: conversion-engine + - name: release_namespace + value: $(tasks.ephemeral-ns.results.namespace) + - name: release_name + value: conversion-engine + workspaces: + - name: source + workspace: helm + - name: get-filedrop-name + runAfter: ["deploy-conversion-engine", "deploy-upload-to-nextcloud", "deploy-notification"] + taskref: + name: openshift-ephemeral-namespace-client + kind: Task + params: + - name: VERSION + value: 4.11 + - name: SCRIPT + value: | + #!/usr/bin/env bash + wget "https://github.com/jqlang/jq/releases/download/jq-1.7/jq-linux-amd64" -O /usr/local/bin/jq + chmod +x /usr/local/bin/jq + INPUTSRC=$(oc -n $(tasks.ephemeral-ns.results.namespace) get scaledjob/conversion-engine -o json | /usr/local/bin/jq -r '.spec.jobTargetRef.template.spec.initContainers[0].env[] | select(.name == "sourcefile").value') + if [[ -z "${INPUTSRC}" ]]; then exit 1; fi + echo -n "${INPUTSRC}" > $(results.filedrop.path) + workspaces: + - name: kubeconfig-dir + workspace: dockerconfig + - name: perform-e2e-test + runAfter: ["get-filedrop-name"] + taskref: + name: openshift-ephemeral-namespace-client + kind: Task + params: + - name: VERSION + value: 4.11 + - name: SCRIPT + value: | + #!/usr/bin/env bash + oc create -f - </dev/null + oc label namespace goghvideo-test-${RANDOMID} app=goghvideo-test + + x=0; until [[ -n $(oc -n goghvideo-test-${RANDOMID} get secret/goghvideo-openshift-builder-pull-secret 2>/dev/null) || $x -eq 10 ]]; do echo "Waiting for secret replication" && sleep 10 && ((x++)); done + if [[ "${x}" -eq 10 ]]; then exit 1; fi + + oc -n goghvideo-test-${RANDOMID} secrets link default goghvideo-openshift-builder-pull-secret --for=pull + + oc apply -f - </dev/null ) || $x -eq 10 ]]; do echo "Waiting for operator to deploy rabbit" && sleep 5 && ((x++)); done + if [[ "${x}" -eq 10 ]]; then exit 1; fi + + oc -n goghvideo-test-${RANDOMID} adm policy add-scc-to-user anyuid -z rabbitmq-server + + x=0; until [[ $(oc -n goghvideo-test-${RANDOMID} get sts rabbitmq-server -o jsonpath="{.status.readyReplicas}") -gt 0 || $x -eq 20 ]]; do echo "Waiting for Rabbit MQ to startup" && sleep 15 && ((x++)); done + if [[ "${x}" -eq 20 ]]; then exit 1; fi + oc -n goghvideo-test-${RANDOMID} create route edge --service=rabbitmq --port=15672 + + oc -n goghvideo-test-${RANDOMID} get pods + + RABBITHOST=$(oc -n goghvideo-test-${RANDOMID} get secret/rabbitmq-default-user -o template='{{ .data.host | base64decode }}') + RABBITUSER=$(oc -n goghvideo-test-${RANDOMID} get secret/rabbitmq-default-user -o template='{{ .data.username | base64decode }}') + RABBITPASS=$(oc -n goghvideo-test-${RANDOMID} get secret/rabbitmq-default-user -o template='{{ .data.password | base64decode }}') + oc -n goghvideo-test-${RANDOMID} create secret generic amqp --from-literal=url=amqp://${RABBITUSER}:${RABBITPASS}@${RABBITHOST}/ + + curl -O http://${RABBITHOST}:15672/cli/rabbitmqadmin + chmod +x rabbitmqadmin + + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare exchange name=conversion type=topic + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=transcode durable=true queue_type=quorum + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=notification durable=true queue_type=quorum + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=upload-nextcloud durable=true queue_type=quorum + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare queue name=complete durable=true queue_type=quorum + + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="transcode" routing_key="transcode" + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="notification" routing_key="notification" + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="upload-nextcloud" routing_key="upload-nextcloud" + ./rabbitmqadmin -H ${RABBITHOST} -u ${RABBITUSER} -p ${RABBITPASS} declare binding source="conversion" destination_type="queue" destination="complete" routing_key="complete" + + echo -n "goghvideo-test-${RANDOMID}" > $(results.namespace.path) + workspaces: + - name: kubeconfig-dir + workspace: dockerconfig + - name: clone-helm-charts + runAfter: ["ephemeral-ns"] + taskRef: + name: git-clone + params: + - name: url + value: $(params.git-helm-url) + workspaces: + - name: output + workspace: helm + - name: ssh-directory + workspace: gitsshauth + - name: deploy-notification + runAfter: ["clone-helm-charts"] + taskRef: + name: helm-upgrade-from-source + params: + - name: charts_dir + value: notification + - name: release_namespace + value: $(tasks.ephemeral-ns.results.namespace) + - name: release_name + value: notification + - name: overwrite_values + value: "image.tag=v$(tasks.git-semver.results.version)" + workspaces: + - name: source + workspace: helm + - name: deploy-upload-to-nextcloud + runAfter: ["clone-helm-charts"] + taskRef: + name: helm-upgrade-from-source + params: + - name: charts_dir + value: upload-to-nextcloud + - name: release_namespace + value: $(tasks.ephemeral-ns.results.namespace) + - name: release_name + value: upload-to-nextcloud + workspaces: + - name: source + workspace: helm + - name: deploy-conversion-engine + runAfter: ["clone-helm-charts"] + taskRef: + name: helm-upgrade-from-source + params: + - name: charts_dir + value: conversion-engine + - name: release_namespace + value: $(tasks.ephemeral-ns.results.namespace) + - name: release_name + value: conversion-engine + workspaces: + - name: source + workspace: helm + - name: get-filedrop-name + runAfter: ["deploy-conversion-engine", "deploy-upload-to-nextcloud", "deploy-notification"] + taskref: + name: openshift-ephemeral-namespace-client + kind: Task + params: + - name: VERSION + value: 4.11 + - name: SCRIPT + value: | + #!/usr/bin/env bash + wget "https://github.com/jqlang/jq/releases/download/jq-1.7/jq-linux-amd64" -O /usr/local/bin/jq + chmod +x /usr/local/bin/jq + INPUTSRC=$(oc -n $(tasks.ephemeral-ns.results.namespace) get scaledjob/conversion-engine -o json | /usr/local/bin/jq -r '.spec.jobTargetRef.template.spec.initContainers[0].env[] | select(.name == "sourcefile").value') + if [[ -z "${INPUTSRC}" ]]; then exit 1; fi + echo -n "${INPUTSRC}" > $(results.filedrop.path) + workspaces: + - name: kubeconfig-dir + workspace: dockerconfig + - name: perform-e2e-test + runAfter: ["get-filedrop-name"] + taskref: + name: openshift-ephemeral-namespace-client + kind: Task + params: + - name: VERSION + value: 4.11 + - name: SCRIPT + value: | + #!/usr/bin/env bash + oc create -f - <