diff --git a/README.md b/README.md index 8ce82e0..b6ba39d 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ At the moment one template has helm chart support and this is the [chatbot appli The gitops component, handled by ArgoCD for the RHDH case, is replaced by the `application_gitops` project. Therefore, post application deployment a kubernetes Job is taking care of the github application repository creation. The source code is [here](https://github.com/redhat-ai-dev/developer-images/tree/main/helm-charts/application-gitops) -## OpenShift Pipelines Configuration +## OpenShift Pipelines -For OpenShift Pipelines configuration there's a separate (optional) helm chart, that a user can use to install and configure the pipelines for their project. The configuration helm chart is [here](/charts/openshift-pipelines/). +For OpenShift Pipelines configuration there's an [OpenShift Pipelines Configuration Guide](/docs/PIPELINES_CONFIGURATION.md) that the user can follow to configure their pipelines, prior to installing the helm chart. -The helm chart mainly uses the pipelines under [rhdh-pipelines](https://github.com/redhat-ai-dev/rhdh-pipelines) repo. The only customized resources used for the helm chart case are: +The helm chart mainly uses the tekton pipelines under [rhdh-pipelines](https://github.com/redhat-ai-dev/rhdh-pipelines) repo. The only customized resources used for the helm chart case are: - The [.tekton/docker-push.yaml](/pac/pipelineRuns/.tekton/docker-push.yaml) PipelineRun used to manage `push` events received from the github app webhook. - The [update-deployment.yaml](/pac/tasks/update-deployment.yaml) Task which is used to update the application deployment whenever a new image is pushed to the image registry. diff --git a/charts/ai-software-templates/chatbot/0.1.0/README.md b/charts/ai-software-templates/chatbot/0.1.0/README.md index 66cd1b5..4a1cba2 100644 --- a/charts/ai-software-templates/chatbot/0.1.0/README.md +++ b/charts/ai-software-templates/chatbot/0.1.0/README.md @@ -8,8 +8,9 @@ The deployment flow, will create an application instance, a model server and a g - You have a Github APP created with sufficient permissions for the organization that the application repository will be created. Detailed instructions for the github application creation can be found [here](https://github.com/redhat-ai-dev/ai-rhdh-installer/blob/main/docs/APP-SETUP.md#github-app). - You need to have access to a cluster for each operation with OpenShift 4, like deploying and testing. -- Your cluster should have [Openshift Pipelines Operator](https://www.redhat.com/en/technologies/cloud-computing/openshift/pipelines) installed and should be connected to your Github APP's webhook. In case your cluster is not configured yet, check the ["Setup Openshift Pipelines Operator"](#setup-openshift-pipelines-operator) below for further instructions. -- A Secret is already created in the Namespace that you are planning to install your helm release, containing a [Github Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) with sufficient access to the given Github Organization. You can find the exact permissions [here](https://github.com/redhat-ai-dev/ai-rhdh-installer/blob/main/docs/APP-SETUP.md#procedure). +- The Namespace that your application will run is already created in your cluster. +- Your cluster should have [Openshift Pipelines Operator](https://www.redhat.com/en/technologies/cloud-computing/openshift/pipelines) installed and should be connected to your Github APP's webhook. In case your cluster is not configured yet, check the ["Pipelines Configuration Guide"](../../../../docs/PIPELINES_CONFIGURATION.md) for further instructions. +- A `key/value` Secret is already created in the Namespace that you are planning to install your helm release, containing a [Github Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) with sufficient access to the given Github Organization. You can find the exact permissions [here](https://github.com/redhat-ai-dev/ai-rhdh-installer/blob/main/docs/APP-SETUP.md#procedure). Your Secret's name and the Key of the github token will be provided as values to the helm chart. ## Background @@ -27,12 +28,6 @@ Apart from the two main deployments, the gitops & OpenShift Pipelines parts are The helm chart can be directly installed from the OpenShift Dev Console. Check [here](https://docs.redhat.com/en/documentation/openshift_container_platform/4.8/html/building_applications/working-with-helm-charts#understanding-helm) for more information. -### Setup Openshift Pipelines Operator - -The suggested way to subscribe to, configure and connect the Openshift Pipelines and your Github App, is the through [openshift-pipelines](../../../openshift-pipelines/) helm chart. - - - ### Install using Helm In order to install AI Software Template Helm chart using helm directly, you can run: diff --git a/charts/openshift-pipelines/Chart.yaml b/charts/openshift-pipelines/Chart.yaml deleted file mode 100644 index 8966f9c..0000000 --- a/charts/openshift-pipelines/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v2 -description: This chart is part of the chatbot ai software template chart and configures the openshift pipelines. -name: chatbot-ai-software-template-pipelines-configuration -tags: chatbot,python,llama.cpp,vllm -version: 0.1.0 diff --git a/charts/openshift-pipelines/README.md b/charts/openshift-pipelines/README.md deleted file mode 100644 index 3f96bae..0000000 --- a/charts/openshift-pipelines/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# OpenShift Pipelines Configuration - AI Software Template Helm Chart - -This helm chart tries to provide an easy way to configure OpenShift Pipelines on your cluster and set everything up for the installation of the [AI Software Template Chat Application Helm Chart](../ai-software-templates/chatbot/0.1.0/). - -## Requirements - -Before installing the pipelines configuration helm chart, make sure you have created a Secret inside the Namespace you plan to release your Chat Application. The necessary fields are mentioned in the [values.gitops](#gitops) section. - -## Usage - -To install the configuration helm chart simply run: - -``` -helm upgrade --install --namespace . -``` - -## Values - -### application - -| Value | Description | Default | Additional Information | -| ----------- | --------------------------------------------------------- | --------------------------- | ---------------------- | -| `name` | The name of the configuration helm chart release. | `chatbot-configuration` | | -| `namespace` | The namespace that the chat application will be released. | `ai-software-templates-dev` | | - -### gitops - -| Value | Description | Default | Additional Information | -| ---------------------------------- | ----------------------------------------------------------------------------------- | --------------------------- | ---------------------- | -| `gitSecretName` | The name of the Secret containing the required Github credentials. | `git-secrets` | | -| `gitSecretKeyToken` | The name of the Secret's key with your Github token value. | `GITHUB_TOKEN` | | -| `gitSecretKeyAppId` | The name of the Secret's key with your Github App's application id value. | `GITHUB_APP_APP_ID` | | -| `gitSecretKeyWebhookURL` | The name of the Secret's key with your Github App's webhook url value. | `GITHUB_APP_WEBHOOK_URL` | | -| `gitSecretKeyWebhookSecret` | The name of the Secret's key with your Github App's webhook secret value. | `GITHUB_APP_WEBHOOK_SECRET` | | -| `gitSecretKeyPrivateKey` | The name of the Secret's key with your Github App's private key value. | `GITHUB_APP_PRIVATE_KEY` | | -| `gitSecretKeyQuayDockerConfigJSON` | The name of the Secret's key with your Github App's quay.io DockerConfigJson value. | `QUAY_DOCKERCONFIGJSON` | | diff --git a/charts/openshift-pipelines/templates/service-account.yaml b/charts/openshift-pipelines/templates/service-account.yaml deleted file mode 100644 index b7a56fb..0000000 --- a/charts/openshift-pipelines/templates/service-account.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: helm-manager - namespace: {{.Release.Namespace}} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: helm-manager-admin -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: helm-manager - namespace: {{.Release.Namespace}} diff --git a/charts/openshift-pipelines/templates/setup-pipelines-job.yaml b/charts/openshift-pipelines/templates/setup-pipelines-job.yaml deleted file mode 100644 index 33e81b4..0000000 --- a/charts/openshift-pipelines/templates/setup-pipelines-job.yaml +++ /dev/null @@ -1,325 +0,0 @@ ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: "{{.Release.Name}}-configure-openshift-pipelines" - namespace: {{ .Release.Namespace }} - labels: - app.kubernetes.io/managed-by: {{ .Release.Service | quote }} - app.kubernetes.io/instance: {{ .Release.Name | quote }} - app.kubernetes.io/version: {{ .Chart.AppVersion }} - helm.sh/chart: "{{.Chart.Name}}-{{.Chart.Version}}" -spec: - template: - metadata: - name: "{{.Release.Name}}-configure-operators" - labels: - app.kubernetes.io/managed-by: {{ .Release.Service | quote }} - app.kubernetes.io/instance: {{ .Release.Name | quote }} - helm.sh/chart: "{{.Chart.Name}}-{{.Chart.Version}}" - spec: - containers: - - name: configure-operators - image: "registry.redhat.io/openshift4/ose-tools-rhel8:latest" - workingDir: /tmp - env: - - name: GITHUB_TOKEN - valueFrom: - secretKeyRef: - name: {{ .Values.gitops.gitSecretName }} - key: {{ .Values.gitops.gitSecretKeyToken }} - - name: GITHUB_APP_APP_ID - valueFrom: - secretKeyRef: - name: {{ .Values.gitops.gitSecretName }} - key: {{ .Values.gitops.gitSecretKeyAppId }} - - name: GITHUB_APP_WEBHOOK_URL - valueFrom: - secretKeyRef: - name: {{ .Values.gitops.gitSecretName }} - key: {{ .Values.gitops.gitSecretKeyWebhookURL }} - - name: GITHUB_APP_WEBHOOK_SECRET - valueFrom: - secretKeyRef: - name: {{ .Values.gitops.gitSecretName }} - key: {{ .Values.gitops.gitSecretKeyWebhookSecret }} - - name: GITHUB_APP_PRIVATE_KEY - valueFrom: - secretKeyRef: - name: {{ .Values.gitops.gitSecretName }} - key: {{ .Values.gitops.gitSecretKeyPrivateKey }} - - name: QUAY_DOCKERCONFIGJSON - valueFrom: - secretKeyRef: - name: {{ .Values.gitops.gitSecretName }} - key: {{ .Values.gitops.gitSecretKeyQuayDockerConfigJSON }} - - name: NAMESPACE - value: {{ .Values.application.namespace }} - command: - - /bin/bash - - -c - - | - echo "Step 1: Configure Operators" - set -o errexit - set -o nounset - set -o pipefail - - echo -n "* Fetching sigstore/cosign: " - curl -sL https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 -o /usr/bin/cosign && chmod +x /usr/bin/cosign - echo "OK" - - PIPELINES_NAMESPACE="openshift-pipelines" - - echo -n "* Waiting for pipelines operator deployment: " - until kubectl get namespace "$PIPELINES_NAMESPACE" >/dev/null 2>&1; do - echo -n "." - sleep 3 - done - until kubectl get route -n "$PIPELINES_NAMESPACE" pipelines-as-code-controller >/dev/null 2>&1; do - echo -n "." - sleep 3 - done - echo "OK" - - echo -n "* Configuring Chains secret: " - SECRET="signing-secrets" - if [ "$(kubectl get secret -n "$PIPELINES_NAMESPACE" "$SECRET" -o jsonpath='{.data}' --ignore-not-found --allow-missing-template-keys)" == "" ]; then - # Delete secret/signing-secrets if already exists since by default cosign creates immutable secrets - echo -n "." - kubectl delete secrets -n "$PIPELINES_NAMESPACE" "$SECRET" --ignore-not-found=true - - # To make this run conveniently without user input let's create a random password - echo -n "." - RANDOM_PASS=$( openssl rand -base64 30 ) - - # Generate the key pair secret directly in the cluster. - # The secret should be created as immutable. - echo -n "." - env COSIGN_PASSWORD=$RANDOM_PASS cosign generate-key-pair "k8s://$PIPELINES_NAMESPACE/$SECRET" >/dev/null - fi - # If the secret is not marked as immutable, make it so. - if [ "$(kubectl get secret -n "$PIPELINES_NAMESPACE" "$SECRET" -o jsonpath='{.immutable}')" != "true" ]; then - echo -n "." - kubectl patch secret -n "$PIPELINES_NAMESPACE" "$SECRET" --dry-run=client -o yaml \ - --patch='{"immutable": true}' \ - | kubectl apply -f - >/dev/null - fi - echo "OK" - - echo - echo "Configuration successful" - echo "Step 1: Completed" - - ## Configure Pipelines - echo "Step 2: Configure Pipelines" - - # Variables - PIPELINES_NAMESPACE=${PIPELINES_NAMESPACE:-"openshift-pipelines"} - PIPELINES_SECRET_NAME=${PIPELINES_SECRET_NAME:-'chatbot-pipelines-secret'} - - # Waiting for CRD - # Waits for TektonConfig CRD to become avaiable when performing deployment of the pipelines - # services. - echo -n "* Waiting for 'tektonconfigs' CRD: " - while [ $(kubectl api-resources | grep -c "^tektonconfigs ") = "0" ] ; do - echo -n "." - sleep 3 - done - if [ $? -ne 0 ]; then - echo "FAIL" - exit 1 - fi - echo "OK" - - # Waiting for pipelines operator deployment - # Waits for the deployment of the pipelines services to finish before proceeding. - echo -n "* Waiting for pipelines operator deployment: " - until kubectl get namespace "$PIPELINES_NAMESPACE" >/dev/null 2>&1; do - echo -n "." - sleep 3 - done - until kubectl get route -n "$PIPELINES_NAMESPACE" pipelines-as-code-controller >/dev/null 2>&1; do - echo -n "." - sleep 3 - done - if [ $? -ne 0 ]; then - echo "FAIL" - exit 1 - fi - echo "OK" - - # Update the TektonConfig resource - # Updates Tekton config CR to have setup with target namespace and - # compatiablty with RHDH instances - echo -n "* Update the TektonConfig resource: " - until kubectl get tektonconfig config >/dev/null 2>&1; do - echo -n "_" - sleep 3 - done - - echo -n "* Update the TektonConfig resource: " - until kubectl get tektonconfig config >/dev/null 2>&1; do - echo -n "_" - sleep 3 - done - kubectl patch tektonconfig config --type 'merge' --patch "$( cat </dev/null - else - WEBHOOK_SECRET="$(kubectl -n "$NAMESPACE" get secret "$PIPELINES_SECRET_NAME" ) -o jsonpath="{.data.webhook-github-secret}" | base64 -d" - fi - if [ $? -ne 0 ]; then - echo "FAIL" - exit 1 - fi - - if [ "$(kubectl get secret -n "$PIPELINES_NAMESPACE" "pipelines-as-code-secret" -o name --ignore-not-found | wc -l | tr -d '[:space:]')" = "0" ]; then - kubectl -n "$PIPELINES_NAMESPACE" create secret generic pipelines-as-code-secret \ - --from-literal github-application-id="$GITHUB_APP_APP_ID" \ - --from-literal github-private-key="$GITHUB_APP_PRIVATE_KEY" \ - --from-literal webhook.secret="$GITHUB_APP_WEBHOOK_SECRET" \ - --dry-run=client -o yaml | kubectl apply -f - >/dev/null - - if [ $? -ne 0 ]; then - echo "FAIL" - exit 1 - fi - fi - echo "OK" - - # Fetching cosign public key - # Fetches cosign public key needed for namespace setup - echo -n "* Fetching cosign public key: " - while ! kubectl get secrets -n $PIPELINES_NAMESPACE signing-secrets >/dev/null 2>&1; do - echo -n "_" - sleep 2 - done - echo -n "." - COSIGN_SIGNING_PUBLIC_KEY="" - while [ -z "${COSIGN_SIGNING_PUBLIC_KEY:-}" ]; do - echo -n "_" - sleep 2 - COSIGN_SIGNING_PUBLIC_KEY=$(kubectl get secrets -n $PIPELINES_NAMESPACE signing-secrets -o jsonpath='{.data.cosign\.pub}' 2>/dev/null) - if [ $? -ne 0 ]; then - echo -n "FAIL" - exit 1 - fi - done - echo "OK" - - # Configure Namespaces - # Configuring namespaces with needed resources - echo -n "* Configuring Namespaces: " - - SECRET_NAME="cosign-pub" - if [ -n "$COSIGN_SIGNING_PUBLIC_KEY" ]; then - cat </dev/null - apiVersion: v1 - data: - cosign.pub: $COSIGN_SIGNING_PUBLIC_KEY - kind: Secret - metadata: - labels: - app.kubernetes.io/instance: default - app.kubernetes.io/part-of: tekton-chains - operator.tekton.dev/operand-name: tektoncd-chains - name: $SECRET_NAME - namespace: $NAMESPACE - type: Opaque - EOF - if [ $? -ne 0 ]; then - echo -n "FAIL" - exit 1 - fi - echo -n "." - fi - - SECRET_NAME="gitops-auth-secret" - if [ -n "$GITHUB_TOKEN" ]; then - kubectl -n $NAMESPACE create secret generic "$SECRET_NAME" \ - --from-literal=password=$GITHUB_TOKEN \ - --type=kubernetes.io/basic-auth \ - --dry-run=client -o yaml | kubectl -n $NAMESPACE apply --filename - --overwrite=true >/dev/null - if [ $? -ne 0 ]; then - echo -n "FAIL" - exit 1 - fi - echo -n "." - fi - - SECRET_NAME="pipelines-secret" - if [ -n "$GITHUB_APP_WEBHOOK_SECRET" ]; then - kubectl -n $NAMESPACE create secret generic "$SECRET_NAME" \ - --from-literal=webhook.secret=$GITHUB_APP_WEBHOOK_SECRET \ - --dry-run=client -o yaml | kubectl -n $NAMESPACE apply --filename - --overwrite=true >/dev/null - if [ $? -ne 0 ]; then - echo -n "FAIL" - exit 1 - fi - echo -n "." - fi - - SECRET_NAME="helm-chart-image-registry-token" - if [ -n "$QUAY_DOCKERCONFIGJSON" ]; then - DATA=$(mktemp) - echo -n "$QUAY_DOCKERCONFIGJSON" >"$DATA" - kubectl -n $NAMESPACE create secret docker-registry "$SECRET_NAME" \ - --from-file=.dockerconfigjson="$DATA" --dry-run=client -o yaml | \ - kubectl -n $NAMESPACE apply --filename - --overwrite=true >/dev/null - if [ $? -ne 0 ]; then - echo -n "FAIL" - exit 1 - fi - rm "$DATA" - echo -n "." - while ! kubectl -n $NAMESPACE get serviceaccount pipeline >/dev/null; do - sleep 2 - echo -n "_" - done - for SA in default pipeline; do - kubectl -n $NAMESPACE patch serviceaccounts "$SA" --patch " - secrets: - - name: $SECRET_NAME - imagePullSecrets: - - name: $SECRET_NAME - " >/dev/null - if [ $? -ne 0 ]; then - echo -n "FAIL" - exit 1 - fi - echo -n "." - done - echo -n "." - fi - echo "OK" - restartPolicy: "Never" - serviceAccountName: helm-manager diff --git a/charts/openshift-pipelines/templates/subscription.yaml b/charts/openshift-pipelines/templates/subscription.yaml deleted file mode 100644 index 786dd0e..0000000 --- a/charts/openshift-pipelines/templates/subscription.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - annotations: - helm.sh/resource-policy: keep - name: openshift-pipelines-operator - namespace: openshift-operators -spec: - channel: pipelines-1.14 - installPlanApproval: Automatic - name: openshift-pipelines-operator-rh - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/charts/openshift-pipelines/values.yaml b/charts/openshift-pipelines/values.yaml deleted file mode 100644 index 58ed63b..0000000 --- a/charts/openshift-pipelines/values.yaml +++ /dev/null @@ -1,12 +0,0 @@ -application: - name: "chatbot-configuration" - namespace: "ai-software-templates-dev" - -gitops: - gitSecretName: "github-secrets" - gitSecretKeyToken: "GITHUB_TOKEN" - gitSecretKeyAppId: "GITHUB_APP_APP_ID" - gitSecretKeyWebhookURL: "GITHUB_APP_WEBHOOK_URL" - gitSecretKeyWebhookSecret: "GITHUB_APP_WEBHOOK_SECRET" - gitSecretKeyPrivateKey: "GITHUB_APP_PRIVATE_KEY" - gitSecretKeyQuayDockerConfigJSON: "QUAY_DOCKERCONFIGJSON" diff --git a/docs/PIPELINES_CONFIGURATION.md b/docs/PIPELINES_CONFIGURATION.md new file mode 100644 index 0000000..0088177 --- /dev/null +++ b/docs/PIPELINES_CONFIGURATION.md @@ -0,0 +1,127 @@ +# Openshift Pipelines Configuration Instructions + +The OpenShift Pipelines configuration is a requirement in order to support CI/CD between your app's github repository and your application's deployment in OpenShift. To configure the pipelines you'll need to: + +1. Install the [Openshift Pipelines Operator](https://docs.redhat.com/en/documentation/openshift_container_platform/4.6/html/pipelines/installing-pipelines#installing-pipelines). + +2. Ensure that the `pipeline-as-code-controller` is up by getting its route: + +``` +kubectl get route -n pipelines-as-code-controller +``` + +3. Download `cosign`, which will be used to generate the updated `signing-secrets`. + +``` +curl -sL https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 -o /usr/bin/cosign && chmod +x /usr/bin/cosign +``` + +4. In your Operator's Namespace, delete (if exists) the `signing-secrets` Secret. + +5. Generate the new `signing-secrets` inside the Operator's Namespace and patch the new secret as immutable: + +``` +export KUBERNETES_SERVICE_PORT= +export KUBERNETES_SERVICE_HOST=" +cosign generate-key-pair k8s:///signing-secrets +kubectl patch secret -n signing-secrets -o yaml --patch='{"immutable": true}' +``` + +6. Ensure that the `tektonconfigs` CRDs are available. You can verify that if the below command returns 1 as response: + +``` +kubectl api-resources | grep -c "^tektonconfigs " +``` + +7. Update the `TektonConfig`, by enabling the necessary resolvers and use a targeted namespace: + +``` +kubectl patch tektonconfig config --type 'merge' --patch "$( cat < +export PIPELINES_SECRET_NAME= +export GITHUB_APP_WEBHOOK_SECRET= +export GITHUB_APP_WEBHOOK_URL= +kubectl -n "$APP_NAMESPACE" create secret generic "$PIPELINES_SECRET_NAME" \ + --from-literal="webhook-github-secret=$GITHUB_APP_WEBHOOK_SECRET" \ + --from-literal="webhook-url=$GITHUB_APP_WEBHOOK_URL" +``` + +9. Create the `pipelines-as-code-secret`, containing your Github App's `App ID`, `Private Key`, `Webhook Secret`. + +``` + +kubectl -n "$PIPELINES_NAMESPACE" create secret generic pipelines-as-code-secret \ + --from-literal github-application-id="$GITHUB_APP_APP_ID" \ + --from-literal github-private-key="$GITHUB_APP_PRIVATE_KEY" \ + --from-literal webhook.secret="$GITHUB_APP_WEBHOOK_SECRET" +``` + +10. Fetch the codesign public key from the `signing-secrets` Secret inside the Operator's Namespace. + +``` +export COSIGN_SIGNING_PUBLIC_KEY=$(kubectl get secrets -n $PIPELINES_NAMESPACE signing-secrets -o jsonpath='{.data.cosign\.pub}') +cat </dev/null +apiVersion: v1 +data: + cosign.pub: $COSIGN_SIGNING_PUBLIC_KEY +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-chains + operator.tekton.dev/operand-name: tektoncd-chains + name: cosign-pub + namespace: $APP_NAMESPACE +type: Opaque +EOF +``` + +11. Create the `pipelines-secret` in your application's Namespace, containing your Github App's `Webhook Secret`: + +``` +kubectl -n $APP_NAMESPACE create secret generic pipelines-secret --from-literal=webhook.secret=$GITHUB_APP_WEBHOOK_SECRET +``` + +12. Similarly with the previous step, create the `image-registry-token` in your application's Namespace, containing the docker `config.json` file of your Quay.io account (see more info [here](https://docs.redhat.com/en/documentation/red_hat_quay/3.6/html-single/use_red_hat_quay/index#allow-robot-access-user-repo)): + +``` +export IMAGE_REGISTRY_TOKEN_SECRET= +kubectl -n $APP_NAMESPACE create secret docker-registry "$IMAGE_REGISTRY_TOKEN_SECRET" --from-file=.dock +erconfigjson= +``` + +13. Patch the `default` and `pipeline` ServiceAccounts by adding to them the image registry token secret created above: + +``` +for SA in default pipeline; do + kubectl -n $APP_NAMESPACE patch serviceaccounts "$SA" --patch " + secrets: + - name: $IMAGE_REGISTRY_TOKEN_SECRET + imagePullSecrets: + - name: $IMAGE_REGISTRY_TOKEN_SECRET + " +done +```