From cd957bae91c255bd68f9cd0416f16304c15194a8 Mon Sep 17 00:00:00 2001 From: Akshat Jain Date: Thu, 22 May 2025 15:16:10 +0530 Subject: [PATCH 1/3] [INFRA-119] Plane-EE: feat: Add Email Service (#98) * Plane-EE: Add Email Service configuration to Helm chart * Add TLS certificate configuration for email service in Helm chart * Update Plane version to 1.2.3 and change email service image references to use artifacts.plane.so for consistency across configurations. * Refactor email service configuration: remove webhook URL from values and questions, update email secrets to use ConfigMap, and add readiness probe to email deployment. * Disable email service in values.yaml configuration * Update cert-issuers.yaml to conditionally enable SSL issuer based on ingress or email service configuration * Refactor condition for SSL issuer in cert-issuers.yaml to prioritize ingress configuration --- charts/plane-enterprise/Chart.yaml | 2 +- charts/plane-enterprise/questions.yml | 52 +++++++++ .../templates/certs/cert-issuers.yaml | 2 +- .../templates/certs/email-certs.yaml | 15 +++ .../templates/config-secrets/email-env.yaml | 22 ++++ .../templates/workloads/email.deployment.yaml | 102 ++++++++++++++++++ charts/plane-enterprise/values.yaml | 10 ++ 7 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 charts/plane-enterprise/templates/certs/email-certs.yaml create mode 100644 charts/plane-enterprise/templates/config-secrets/email-env.yaml create mode 100644 charts/plane-enterprise/templates/workloads/email.deployment.yaml diff --git a/charts/plane-enterprise/Chart.yaml b/charts/plane-enterprise/Chart.yaml index 4e7980ff..55433cd9 100644 --- a/charts/plane-enterprise/Chart.yaml +++ b/charts/plane-enterprise/Chart.yaml @@ -5,7 +5,7 @@ description: Meet Plane. An Enterprise software development tool to manage issue type: application -version: 1.2.2 +version: 1.2.3 appVersion: "1.9.2" home: https://plane.so/ diff --git a/charts/plane-enterprise/questions.yml b/charts/plane-enterprise/questions.yml index a3e57292..5aab7472 100644 --- a/charts/plane-enterprise/questions.yml +++ b/charts/plane-enterprise/questions.yml @@ -60,9 +60,15 @@ questions: required: true default: "artifacts.plane.so/makeplane/backend-commercial" description: "Used by API, Worker, Beat-Worker" + - variable: services.email_service.image + label: Email Service Docker Image + type: string + required: true + default: "artifacts.plane.so/makeplane/email-commercial" - variable: env.storageClass label: "Storage Class for Persistent Volume Claims" type: storageclass + - variable: license.licenseServer label: "License Server" @@ -423,6 +429,52 @@ questions: type: string default: 500m +- variable: services.email_service.enabled + label: "Enable Email Service" + type: boolean + default: false + group: "Email Service Setup" + show_subquestion_if: true + subquestions: + - variable: services.email_service.replicas + label: "Default Replica Count" + type: int + default: 1 + - variable: services.email_service.memory_limit + label: "Memory Limit" + type: string + default: 1000Mi + - variable: services.email_service.cpu_limit + label: "CPU Limit" + type: string + default: 500m + - variable: env.email_service_envs.smtp_domain + label: "SMTP Domain" + type: string + default: "" + - variable: ssl.issuer + label: "SSL Issuer" + type: enum + options: + - "http" + - "cloudflare" + - "digitalocean" + default: "http" + - variable: ssl.server + label: "Let's Encrypt Server URL" + type: string + default: "https://acme-v02.services.api.letsencrypt.org/directory" + - variable: ssl.email + label: "Let's Encrypt Reg. Email" + type: string + default: "plane@example.com" + - variable: ssl.token + label: "Provider API Token" + type: password + default: "" + description: "Not required for 'http' issuer" + show_if: "ssl.issuer=cloudflare || ssl.issuer=digitalocean" + - variable: services.redis.local_setup label: "Install Redis" type: boolean diff --git a/charts/plane-enterprise/templates/certs/cert-issuers.yaml b/charts/plane-enterprise/templates/certs/cert-issuers.yaml index 8082ebfc..3c760552 100644 --- a/charts/plane-enterprise/templates/certs/cert-issuers.yaml +++ b/charts/plane-enterprise/templates/certs/cert-issuers.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.ingress.enabled .Values.ssl.createIssuer (empty .Values.ssl.tls_secret_name) }} +{{- if and .Values.ingress.enabled (or .Values.services.email_service.enabled .Values.ssl.createIssuer) (empty .Values.ssl.tls_secret_name) }} apiVersion: v1 kind: Secret diff --git a/charts/plane-enterprise/templates/certs/email-certs.yaml b/charts/plane-enterprise/templates/certs/email-certs.yaml new file mode 100644 index 00000000..ecab422f --- /dev/null +++ b/charts/plane-enterprise/templates/certs/email-certs.yaml @@ -0,0 +1,15 @@ +{{- if and .Values.services.email_service.enabled .Values.env.email_service_envs.smtp_domain }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ .Release.Name }}-mail-tls-cert + namespace: {{ .Release.Namespace }} +spec: + dnsNames: + - {{ .Values.env.email_service_envs.smtp_domain | quote }} + + issuerRef: + name: {{ .Release.Name }}-cert-issuer + secretName: {{ .Release.Name }}-mail-tls-secret +--- +{{- end }} \ No newline at end of file diff --git a/charts/plane-enterprise/templates/config-secrets/email-env.yaml b/charts/plane-enterprise/templates/config-secrets/email-env.yaml new file mode 100644 index 00000000..9b4a33b3 --- /dev/null +++ b/charts/plane-enterprise/templates/config-secrets/email-env.yaml @@ -0,0 +1,22 @@ +{{- if .Values.services.email_service.enabled }} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-email-vars + namespace: {{ .Release.Namespace }} +data: + SMTP_DOMAIN: {{ .Values.env.email_service_envs.smtp_domain | default "" | quote }} + EMAIL_SAVE_ENDPOINT: "http://{{ .Release.Name }}-api.{{ .Release.Namespace }}.svc.cluster.local:8000/intake/email/" + WEBHOOK_URL: "http://{{ .Release.Name }}-api.{{ .Release.Namespace }}.svc.cluster.local:8000/intake/email/" + domain-blacklist.txt: | + 10minutemail.com + 10minutemail.net + 10minutemail.org + spam.txt: | + casino + lottery + jackpot + +--- +{{- end }} \ No newline at end of file diff --git a/charts/plane-enterprise/templates/workloads/email.deployment.yaml b/charts/plane-enterprise/templates/workloads/email.deployment.yaml new file mode 100644 index 00000000..ecc1888e --- /dev/null +++ b/charts/plane-enterprise/templates/workloads/email.deployment.yaml @@ -0,0 +1,102 @@ +{{- if .Values.services.email_service.enabled }} + +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-email-service + namespace: {{ .Release.Namespace }} +spec: + type: LoadBalancer + externalTrafficPolicy: Local # Important for email servers + selector: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-email-app + ports: + - name: smtp + port: 25 + targetPort: 10025 + protocol: TCP + - name: smtps + port: 465 + targetPort: 10465 + protocol: TCP + - name: submission + port: 587 + targetPort: 10587 + protocol: TCP +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-email-app + namespace: {{ .Release.Namespace }} + annotations: + reloader.stakater.com/auto: "true" +spec: + replicas: {{ .Values.services.email_service.replicas | default 1 }} + selector: + matchLabels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-email-app + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-email-app + annotations: + timestamp: {{ now | quote }} + spec: + containers: + - name: {{ .Release.Name }}-email-app + image: {{ .Values.services.email_service.image | default "artifacts.plane.so/makeplane/email-commercial" }}:{{ .Values.planeVersion }} + securityContext: + runAsUser: 100 + stdin: true + tty: true + readinessProbe: + exec: + command: + - nc + - -zv + - localhost + - "10025" + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + resources: + requests: + memory: "50Mi" + cpu: "50m" + limits: + memory: {{ .Values.services.email_service.memory_limit | default "1000Mi" | quote }} + cpu: {{ .Values.services.email_service.cpu_limit | default "500m" | quote}} + envFrom: + - configMapRef: + name: {{ .Release.Name }}-email-vars + optional: false + volumeMounts: + - name: tls-cert + mountPath: /opt/email/keys + - name: spam-blacklist + mountPath: /opt/email/spam.txt + subPath: spam.txt + - name: spam-blacklist + mountPath: /opt/email/domain-blacklist.txt + subPath: domain-blacklist.txt + volumes: + - name: spam-blacklist + configMap: + name: {{ .Release.Name }}-email-vars + - name: tls-cert + secret: + secretName: {{ .Release.Name }}-mail-tls-secret + items: + - key: tls.crt + path: cert.pem + - key: tls.key + path: key.pem + optional: false + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account +--- +{{- end }} \ No newline at end of file diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index d3b7d770..1a6cb1f1 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -151,6 +151,13 @@ services: client_id: '' client_secret: '' + email_service: + enabled: false + replicas: 1 + memory_limit: 1000Mi + cpu_limit: 500m + image: artifacts.plane.so/makeplane/email-commercial + external_secrets: # Name of the existing Kubernetes Secret resource; see README for more details rabbitmq_existingSecret: '' @@ -206,3 +213,6 @@ env: hmac_secret_key: '' aes_secret_key: 'dsOdt7YrvxsTIFJ37pOaEVvLxN8KGBCr' cors_allowed_origins: '' + + email_service_envs: + smtp_domain: '' From 21a680ff5272d53668f7d8788662c7227727a411 Mon Sep 17 00:00:00 2001 From: Akshat Jain Date: Thu, 22 May 2025 15:45:28 +0530 Subject: [PATCH 2/3] Plane-EE: Update Plane version to v1.9.3 and add email service configuration in README (#107) * Update Plane version to v1.9.3 and add email service configuration to Helm chart * Update README to clarify SMTP domain usage for email service * Update Plane version to v1.10.0 in Chart.yaml, questions.yml, README.md, and values.yaml --- charts/plane-enterprise/Chart.yaml | 2 +- charts/plane-enterprise/README.md | 22 +++++++++++++++---- charts/plane-enterprise/questions.yml | 3 +-- .../templates/workloads/email.deployment.yaml | 1 + charts/plane-enterprise/values.yaml | 3 ++- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/charts/plane-enterprise/Chart.yaml b/charts/plane-enterprise/Chart.yaml index 55433cd9..3f039a49 100644 --- a/charts/plane-enterprise/Chart.yaml +++ b/charts/plane-enterprise/Chart.yaml @@ -6,7 +6,7 @@ description: Meet Plane. An Enterprise software development tool to manage issue type: application version: 1.2.3 -appVersion: "1.9.2" +appVersion: "1.10.0" home: https://plane.so/ icon: https://plane.so/favicon/favicon-32x32.png diff --git a/charts/plane-enterprise/README.md b/charts/plane-enterprise/README.md index e7a1b52f..eff4081a 100644 --- a/charts/plane-enterprise/README.md +++ b/charts/plane-enterprise/README.md @@ -11,7 +11,7 @@ Copy the format of constants below, paste it on Terminal to start setting environment variables, set values for each variable, and hit ENTER or RETURN. ```bash - PLANE_VERSION=v1.9.2 # or the last released version + PLANE_VERSION=v1.10.0 # or the last released version DOMAIN_NAME= ``` @@ -65,7 +65,7 @@ ``` Make sure you set the minimum required values as below. - - `planeVersion: v1.9.2 ` + - `planeVersion: v1.10.0 ` - `license.licenseDomain: ` - `ingress.enabled: ` - `ingress.ingressClass: ` @@ -100,7 +100,7 @@ | Setting | Default | Required | Description | |---|:---:|:---:|---| -| planeVersion | v1.9.2 | Yes | Specifies the version of Plane to be deployed. Copy this from prime.plane.so. | +| planeVersion | v1.10.0 | Yes | Specifies the version of Plane to be deployed. Copy this from prime.plane.so. | | license.licenseDomain | plane.example.com | Yes | The fully-qualified domain name (FQDN) in the format `sudomain.domain.tld` or `domain.tld` that the license is bound to. It is also attached to your `ingress` host to access Plane. | ### Postgres @@ -285,7 +285,21 @@ | services.beatworker.replicas | 1 | Yes | Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for each deployment. This key helps you setting up number of replicas you want to run for this deployment. It must be >=1 | | services.beatworker.memoryLimit | 1000Mi | | Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.| | services.beatworker.cpuLimit | 500m | | Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.| - + +### Email Service Deployment + +| Setting | Default | Required | Description | +|---|:---:|:---:|---| +| services.email_service.enabled | false | | Set to `true` to enable the email service deployment | +| services.email_service.replicas | 1 | | Number of replicas for the email service deployment | +| services.email_service.memory_limit | 1000Mi | | Memory limit for the email service deployment | +| services.email_service.cpu_limit | 500m | | CPU limit for the email service deployment | +| services.email_service.image | artifacts.plane.so/makeplane/email-commercial | | Docker image for the email service deployment | +| services.email_service.pullPolicy | Always | | Image pull policy for the email service deployment | +| env.email_service_envs.smtp_domain | | Yes | The SMTP Domain to be used with email service | + +Note: When the email service is enabled, the cert-issuer will be automatically created to handle TLS certificates for the email service. + ### Ingress and SSL Setup | Setting | Default | Required | Description | diff --git a/charts/plane-enterprise/questions.yml b/charts/plane-enterprise/questions.yml index 5aab7472..845a8d5e 100644 --- a/charts/plane-enterprise/questions.yml +++ b/charts/plane-enterprise/questions.yml @@ -20,7 +20,7 @@ questions: - variable: planeVersion label: Plane Version (Docker Image Tag) type: string - default: v1.9.2 + default: v1.10.0 required: true group: "Docker Registry" subquestions: @@ -68,7 +68,6 @@ questions: - variable: env.storageClass label: "Storage Class for Persistent Volume Claims" type: storageclass - - variable: license.licenseServer label: "License Server" diff --git a/charts/plane-enterprise/templates/workloads/email.deployment.yaml b/charts/plane-enterprise/templates/workloads/email.deployment.yaml index ecc1888e..6db99ea1 100644 --- a/charts/plane-enterprise/templates/workloads/email.deployment.yaml +++ b/charts/plane-enterprise/templates/workloads/email.deployment.yaml @@ -47,6 +47,7 @@ spec: spec: containers: - name: {{ .Release.Name }}-email-app + imagePullPolicy: {{ .Values.services.email_service.pullPolicy | default "Always" }} image: {{ .Values.services.email_service.image | default "artifacts.plane.so/makeplane/email-commercial" }}:{{ .Values.planeVersion }} securityContext: runAsUser: 100 diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index 1a6cb1f1..5c5f4b3d 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -1,4 +1,4 @@ -planeVersion: v1.9.2 +planeVersion: v1.10.0 dockerRegistry: enabled: false @@ -157,6 +157,7 @@ services: memory_limit: 1000Mi cpu_limit: 500m image: artifacts.plane.so/makeplane/email-commercial + pullPolicy: Always external_secrets: # Name of the existing Kubernetes Secret resource; see README for more details From 2ee447e8dd22cacc37b84f91f2f8a1de76667754 Mon Sep 17 00:00:00 2001 From: Akshat Jain Date: Thu, 22 May 2025 19:07:32 +0530 Subject: [PATCH 3/3] Add intake email domain configuration to Helm chart (#109) * Add intake email domain configuration to Helm chart - Added `env.intake_email_domain` variable to `questions.yml` and `values.yaml` with a default value. - Updated `README.md` to include documentation for the new `intake_email_domain` variable. - Modified `app-env.yaml` to include the new environment variable for email intake functionality. * Update default value for intake email domain in app-env.yaml and remove related entry from README - Set default value for `INTAKE_EMAIL_DOMAIN` in `app-env.yaml` to "intake.example.com". - Removed the `env.intake_email_domain` entry from the README documentation as it is now handled in the configuration file. * Remove intake email domain configuration from questions.yml, values.yaml, and README.md. Update app-env.yaml to use SMTP domain for email intake functionality. --- charts/plane-enterprise/README.md | 2 +- charts/plane-enterprise/templates/config-secrets/app-env.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/charts/plane-enterprise/README.md b/charts/plane-enterprise/README.md index eff4081a..413d218f 100644 --- a/charts/plane-enterprise/README.md +++ b/charts/plane-enterprise/README.md @@ -378,4 +378,4 @@ If you are planning to use 3rd party ingress providers, here is the available ro | plane.example.com | /auth/* | | Yes | | plane.example.com | /uploads/* | | Yes (Only if using local setup) | | plane-minio.example.com | / | | (Optional) if using local setup, this will enable minio console access | -| plane-mq.example.com | / | | (Optional) if using local setup, this will enable management console access | +| plane-mq.example.com | / | | (Optional) if using local setup, this will enable management console access | \ No newline at end of file diff --git a/charts/plane-enterprise/templates/config-secrets/app-env.yaml b/charts/plane-enterprise/templates/config-secrets/app-env.yaml index bafa4c8b..46e463ea 100644 --- a/charts/plane-enterprise/templates/config-secrets/app-env.yaml +++ b/charts/plane-enterprise/templates/config-secrets/app-env.yaml @@ -49,6 +49,7 @@ data: API_KEY_RATE_LIMIT: {{ .Values.env.api_key_rate_limit | default "60/minute" | quote }} MINIO_ENDPOINT_SSL: {{ .Values.services.minio.env.minio_endpoint_ssl | default false | ternary "1" "0" | quote }} + INTAKE_EMAIL_DOMAIN: {{ .Values.env.email_service_envs.smtp_domain | default "" | quote }} SENTRY_DSN: {{ .Values.env.sentry_dsn | default "" | quote}} SENTRY_ENVIRONMENT: {{ .Values.env.sentry_environment | default "" | quote}}