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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion charts/plane-enterprise/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Meet Plane. An Enterprise software development tool to manage issue

type: application

version: 2.2.5
version: 2.3.0
appVersion: "2.5.0"

home: https://plane.so/
Expand Down
14 changes: 11 additions & 3 deletions charts/plane-enterprise/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ airgapped:

| Setting | Default | Required | Description |
| ----------------------------------- | :------------------: | :------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| services.postgres.local_setup | true | | Plane uses `postgres` as the primary database to store all the transactional data. This database can be hosted within kubernetes as part of helm chart deployment or can be used as hosted service remotely (e.g. aws rds or similar services). Set this to `true` when you choose to setup stateful deployment of `postgres`. Mark it as `false` when using a remotely hosted database |
| services.postgres.local_setup | true | | Plane uses `postgres` as the primary database to store all the transactional data. This database can be hosted within kubernetes as part of helm chart deployment or can be used as hosted service remotely (e.g. aws rds or similar services). Set this to `true` when you choose to setup stateful deployment of `postgres`. Mark it as `false` when using a remotely hosted database. Important: if you configure PostgreSQL credentials via AWS Secrets Manager ARNs (for example `env.apiSecrets.rds_secret_arn`, and/or PI ARNs under `services.pi.apiSecrets.*_rds_secret_arn`), keep this set to `false` so the chart does not compute `DATABASE_URL` from in-cluster services. |
| services.postgres.image | postgres:15.7-alpine | | Using this key, user must provide the docker image name to setup the stateful deployment of `postgres`. (must be set when `services.postgres.local_setup=true`) |
| services.postgres.pullPolicy | IfNotPresent | | Using this key, user can set the pull policy for the stateful deployment of `postgres`. (must be set when `services.postgres.local_setup=true`) |
| services.postgres.servicePort | 5432 | | This key sets the default port number to be used while setting up stateful deployment of `postgres`. |
Expand All @@ -157,7 +157,7 @@ airgapped:

| Setting | Default | Required | Description |
| -------------------------------- | :-------------------------: | :------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| services.redis.local_setup | true | | Plane uses `valkey` to cache the session authentication and other static data. This database can be hosted within kubernetes as part of helm chart deployment or can be used as hosted service remotely (e.g. aws rds or similar services). Set this to `true` when you choose to setup stateful deployment of `redis`. Mark it as `false` when using a remotely hosted database |
| services.redis.local_setup | true | | Plane uses `valkey` to cache the session authentication and other static data. This database can be hosted within kubernetes as part of helm chart deployment or can be used as hosted service remotely (e.g. aws rds or similar services). Set this to `true` when you choose to setup stateful deployment of `redis`. Mark it as `false` when using a remotely hosted database. Important: if you configure Redis credentials via AWS Secrets Manager ARNs (for example `env.apiSecrets.elasticache_secret_arn`) and provide the Redis key mapping (`env.redis_auth_token_key`), keep this set to `false` so the chart does not compute `REDIS_URL` from in-cluster services. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Redis hosted-service example uses the wrong AWS service name

Line 160 references “aws rds” for Redis; this should be Redis-specific (e.g., AWS ElastiCache/MemoryDB) to avoid operator confusion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@charts/plane-enterprise/README.md` at line 160, The README text for the
services.redis.local_setup description incorrectly mentions “aws rds”; update
the wording to reference Redis-specific hosted services (e.g., AWS ElastiCache
or MemoryDB) so operators aren’t misled—edit the description string associated
with services.redis.local_setup to replace “aws rds or similar services” with
something like “AWS ElastiCache or MemoryDB (or other managed Redis services)”.

| services.redis.image | valkey/valkey:7.2.11-alpine | | Using this key, user must provide the docker image name to setup the stateful deployment of `redis`. (must be set when `services.redis.local_setup=true`) |
| services.redis.pullPolicy | IfNotPresent | | Using this key, user can set the pull policy for the stateful deployment of `redis`. (must be set when `services.redis.local_setup=true`) |
| services.redis.servicePort | 6379 | | This key sets the default port number to be used while setting up stateful deployment of `redis`. |
Expand All @@ -174,7 +174,7 @@ airgapped:

| Setting | Default | Required | Description |
| --------------------------------------- | :-------------------------------: | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| services.rabbitmq.local_setup | true | | Plane uses `rabbitmq` as message queuing system. This can be hosted within kubernetes as part of helm chart deployment or can be used as hosted service remotely (e.g. aws mq or similar services). Set this to `true` when you choose to setup stateful deployment of `rabbitmq`. Mark it as `false` when using a remotely hosted service |
| services.rabbitmq.local_setup | true | | Plane uses `rabbitmq` as message queuing system. This can be hosted within kubernetes as part of helm chart deployment or can be used as hosted service remotely (e.g. aws mq or similar services). Set this to `true` when you choose to setup stateful deployment of `rabbitmq`. Mark it as `false` when using a remotely hosted service. Important: if you configure RabbitMQ credentials via AWS Secrets Manager ARNs (for example `env.apiSecrets.amazonmq_secret_arn`) and provide the key mappings (`env.rabbitmq_user_key` and `env.rabbitmq_password_key`), keep this set to `false` so the chart does not compute `AMQP_URL` from in-cluster services. |
| services.rabbitmq.image | rabbitmq:3.13.6-management-alpine | | Using this key, user must provide the docker image name to setup the stateful deployment of `rabbitmq`. (must be set when `services.rabbitmq.local_setup=true`) |
| services.rabbitmq.pullPolicy | IfNotPresent | | Using this key, user can set the pull policy for the stateful deployment of `rabbitmq`. (must be set when `services.rabbitmq.local_setup=true`) |
| services.rabbitmq.servicePort | 5672 | | This key sets the default port number to be used while setting up stateful deployment of `rabbitmq`. |
Expand Down Expand Up @@ -601,6 +601,14 @@ Note: When the email service is enabled, the cert-issuer will be automatically c
| env.storageClass | <k8s-default-storage-class> | | Creating the persitant volumes for the stateful deployments needs the `storageClass` name. Set the correct value as per your kubernetes cluster configuration. |
| env.secret_key | 60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5 | Yes | This must a random string which is used for hashing/encrypting the sensitive data within the application. Once set, changing this might impact the already hashed/encrypted data |

### AWS Secrets Manager (ARN) wiring

When you configure AWS Secrets Manager credentials using Secret ARNs (via `env.apiSecrets.*_secret_arn` and/or PI secret ARNs), you must **disable local setups** for the corresponding services so the chart does not compute `REDIS_URL`, `DATABASE_URL`, and `AMQP_URL` from in-cluster deployments.

- If `env.apiSecrets.elasticache_secret_arn` is set (and `env.redis_auth_token_key` is set), set `services.redis.local_setup=false`.
- If `env.apiSecrets.amazonmq_secret_arn` is set (and `env.rabbitmq_user_key` + `env.rabbitmq_password_key` are set), set `services.rabbitmq.local_setup=false`.
- If `env.apiSecrets.rds_secret_arn` is set (and/or PI sets `services.pi.apiSecrets.*_rds_secret_arn`), set `services.postgres.local_setup=false`.

### Extra Environment Variables

| Setting | Default | Required | Description |
Expand Down
51 changes: 51 additions & 0 deletions charts/plane-enterprise/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{{- if .Values.podIdentity.enabled }}
EKS Pod Identity (out-of-band) configuration

This chart configures the Kubernetes `ServiceAccount` name as:
{{ printf "%s-srv-account" .Release.Name }}

1. Ensure the Pod Identity agent addon is installed:
eksctl create addon --cluster {{ default "<CLUSTER_NAME>" .Values.podIdentity.clusterName }} --name eks-pod-identity-agent

2. Create the Pod Identity association:
eksctl create podidentityassociation \
--cluster {{ default "<CLUSTER_NAME>" .Values.podIdentity.clusterName }} \
--namespace {{ default .Release.Namespace .Values.podIdentity.namespace }} \
--service-account-name {{ default (printf "%s-srv-account" .Release.Name) .Values.podIdentity.serviceAccountName }} \
--role-arn {{ default "<ROLE_ARN>" .Values.podIdentity.roleArn }}

Alternative (AWS CLI):
aws eks create-pod-identity-association \
--cluster-name {{ default "<CLUSTER_NAME>" .Values.podIdentity.clusterName }} \
--namespace {{ default .Release.Namespace .Values.podIdentity.namespace }} \
--service-account {{ default (printf "%s-srv-account" .Release.Name) .Values.podIdentity.serviceAccountName }} \
--role-arn {{ default "<ROLE_ARN>" .Values.podIdentity.roleArn }}

Important:
- Pod Identity associations are managed outside of Helm/Kubernetes manifests (for example via `eksctl` / AWS APIs).
- Pod Identity is not configured purely by ServiceAccount annotations in this setup.
{{- else }}
IRSA configuration (IAM Roles for Service Accounts)

To enable AWS permissions for this chart's ServiceAccount:
- set `irsa.roleArn`, or
- set `serviceAccount.annotations` / `irsa.annotations` with `eks.amazonaws.com/role-arn`.

This chart's ServiceAccount name is:
{{ printf "%s-srv-account" .Release.Name }}
{{- end }}

---
## Secret ARN driven env wiring

This chart conditionally renders AWS Secrets Manager ARN-related env vars (for example `AMAZONMQ_SECRET_ARN`, `ELASTICACHE_SECRET_ARN`, `RDS_SECRET_ARN`) and the corresponding `*_KEY` mappings only when the ARN values (and the required key-name values) are provided.

To verify what will be rendered for your current values, run:

```sh
helm template <RELEASE_NAME> ./charts/plane-enterprise \
--namespace <NAMESPACE> \
-f <YOUR_VALUES_YAML> | \
rg -n "AMAZONMQ_SECRET_ARN|ELASTICACHE_SECRET_ARN|RDS_SECRET_ARN|RABBITMQ_(USER_KEY|PASSWORD_KEY)|RDS_DB_(HOST_KEY|NAME_KEY|PASSWORD_KEY|PORT_KEY|USERNAME_KEY)|FOLLOWER_RDS_DB_(HOST_KEY|NAME_KEY|PASSWORD_KEY|PORT_KEY|USERNAME_KEY)|MODEL_CUSTOM_LLM_API_KEY"
```

39 changes: 39 additions & 0 deletions charts/plane-enterprise/templates/config-secrets/app-env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ stringData:
LIVE_SERVER_SECRET_KEY: {{ .Values.env.live_server_secret_key | default "htbqvBJAgpm9bzvf3r4urJer0ENReatceh" | quote }}
PI_INTERNAL_SECRET: {{ .Values.env.pi_envs.internal_secret | default "tyfvfqvBJAgpm9bzvf3r4urJer0Ehfdubk" | quote }}

# AWS Secrets Manager ARNs (consumed by workloads via envFrom plane-app-secrets)
{{- if and (not (empty .Values.env.apiSecrets.amazonmq_secret_arn)) (not (empty .Values.env.rabbitmq_user_key)) (not (empty .Values.env.rabbitmq_password_key)) }}
AMAZONMQ_SECRET_ARN: {{ .Values.env.apiSecrets.amazonmq_secret_arn | quote }}
{{- end }}
{{- if and (not (empty .Values.env.apiSecrets.elasticache_secret_arn)) (not (empty .Values.env.redis_auth_token_key)) }}
ELASTICACHE_SECRET_ARN: {{ .Values.env.apiSecrets.elasticache_secret_arn | quote }}
{{- end }}
{{- if and (not (empty .Values.env.apiSecrets.rds_secret_arn)) (not (empty .Values.env.rds_db_host_key)) (not (empty .Values.env.rds_db_name_key)) (not (empty .Values.env.rds_db_password_key)) (not (empty .Values.env.rds_db_port_key)) (not (empty .Values.env.rds_db_username_key)) }}
RDS_SECRET_ARN: {{ .Values.env.apiSecrets.rds_secret_arn | quote }}
{{- end }}

{{- if .Values.services.redis.local_setup }}
REDIS_URL: "redis://{{ .Release.Name }}-redis.{{ .Release.Namespace }}.svc.cluster.local:6379/"
{{- else }}
Expand Down Expand Up @@ -91,3 +102,31 @@ data:
{{- else}}
CORS_ALLOWED_ORIGINS: "http://{{ .Values.license.licenseDomain }},https://{{ .Values.license.licenseDomain }}"
{{- end }}

# Secret cache TTL for the credentials provider used by the app.
AWS_SECRET_CACHE_TTL: {{ .Values.env.aws_secret_cache_ttl | default "300" | quote }}

# Runner base URL used by the automation runner integration.
{{- if .Values.env.runner_base_url }}
RUNNER_BASE_URL: {{ .Values.env.runner_base_url | quote }}
{{- else }}
RUNNER_BASE_URL: "http://plane-node-runner.{{ .Release.Namespace }}.svc.cluster.local:3000"
{{- end }}
Comment on lines +109 to +114

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if node-runner service is defined in this chart with a fixed or release-based name
rg -n "node-runner" --type yaml charts/plane-enterprise/

Repository: makeplane/helm-charts

Length of output: 224


🏁 Script executed:

# Check service definitions and deployments to understand the naming pattern
fd "service" charts/plane-enterprise/templates/ -type f | head -20

Repository: makeplane/helm-charts

Length of output: 235


🏁 Script executed:

# Look for other service URL patterns in app-env.yaml to compare naming conventions
rg -A 2 "Release.Name" charts/plane-enterprise/templates/config-secrets/app-env.yaml | head -40

Repository: makeplane/helm-charts

Length of output: 1917


🏁 Script executed:

# Check if there are any node-runner related deployments or services
fd . charts/plane-enterprise/templates/ -type f -exec rg -l "runner" {} \;

Repository: makeplane/helm-charts

Length of output: 235


🏁 Script executed:

# Check values.yaml for runner configuration and service definitions
head -100 charts/plane-enterprise/values.yaml | grep -A 10 -B 10 "runner\|Runner" || rg -C 5 "runner.*service\|node.runner" charts/plane-enterprise/values.yaml | head -50

Repository: makeplane/helm-charts

Length of output: 47


🏁 Script executed:

# Check if node-runner has deployment templates in this chart
find charts/plane-enterprise/templates -type f -name "*runner*" -o -type f -name "*node*"

Repository: makeplane/helm-charts

Length of output: 47


🏁 Script executed:

# Look for Chart.yaml or dependencies that might reference node-runner
rg -i "dependencies|node-runner" charts/plane-enterprise/Chart.yaml

Repository: makeplane/helm-charts

Length of output: 47


🏁 Script executed:

# Check if there's a separate node-runner chart
ls -la charts/ | grep -i runner

Repository: makeplane/helm-charts

Length of output: 47


🏁 Script executed:

# Check the values.yaml file for runner-related configuration
grep -n "runner" charts/plane-enterprise/values.yaml

Repository: makeplane/helm-charts

Length of output: 158


🏁 Script executed:

# Look at the complete context of RUNNER_BASE_URL in app-env.yaml
sed -n '100,120p' charts/plane-enterprise/templates/config-secrets/app-env.yaml

Repository: makeplane/helm-charts

Length of output: 1126


🏁 Script executed:

# Check if there are any other references to "plane-node-runner" in the entire chart
rg "plane-node-runner" charts/plane-enterprise/

Repository: makeplane/helm-charts

Length of output: 220


🏁 Script executed:

# Check if there's any documentation about plane-node-runner in README or docs
find charts/plane-enterprise -name "*.md" -o -name "*.txt" -o -name "*.rst" | xargs grep -l "node-runner\|runner" 2>/dev/null

Repository: makeplane/helm-charts

Length of output: 49


🏁 Script executed:

# Check the git history to see if there's context about this naming choice
git log --oneline -n 30 -- charts/plane-enterprise/templates/config-secrets/app-env.yaml 2>/dev/null | head -10

Repository: makeplane/helm-charts

Length of output: 108


🏁 Script executed:

# Look at the entire values.yaml section about services to understand the architecture
sed -n '480,510p' charts/plane-enterprise/values.yaml

Repository: makeplane/helm-charts

Length of output: 850


Hardcoded service name doesn't follow release-name convention.

The default RUNNER_BASE_URL uses plane-node-runner instead of {{ .Release.Name }}-node-runner, which is inconsistent with every other internal service URL in this template (redis, pgdb, rabbitmq, monitor, live). If the node-runner service is deployed as part of this chart, this will cause connection failures when users deploy with a custom release name.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@charts/plane-enterprise/templates/config-secrets/app-env.yaml` around lines
109 - 114, The default RUNNER_BASE_URL fallback currently hardcodes the service
as "plane-node-runner", causing mismatches with release-scoped services; update
the template logic that sets RUNNER_BASE_URL (the block using
.Values.env.runner_base_url) so the fallback host follows the same release-name
convention as other services by using .Release.Name (e.g., "{{ .Release.Name
}}-node-runner") combined with .Release.Namespace and port 3000, preserving the
existing conditional that prefers .Values.env.runner_base_url when provided.


# AWS Secrets Manager key mappings (key names, not the secret ARNs).
{{- if and (not (empty .Values.env.apiSecrets.elasticache_secret_arn)) (not (empty .Values.env.redis_auth_token_key)) }}
REDIS_AUTH_TOKEN_KEY: {{ .Values.env.redis_auth_token_key | quote }}
{{- end }}

{{- if and (not (empty .Values.env.apiSecrets.amazonmq_secret_arn)) (not (empty .Values.env.rabbitmq_user_key)) (not (empty .Values.env.rabbitmq_password_key)) }}
RABBITMQ_USER_KEY: {{ .Values.env.rabbitmq_user_key | quote }}
RABBITMQ_PASSWORD_KEY: {{ .Values.env.rabbitmq_password_key | quote }}
{{- end }}

{{- if and (not (empty .Values.env.apiSecrets.rds_secret_arn)) (not (empty .Values.env.rds_db_host_key)) (not (empty .Values.env.rds_db_name_key)) (not (empty .Values.env.rds_db_password_key)) (not (empty .Values.env.rds_db_port_key)) (not (empty .Values.env.rds_db_username_key)) }}
RDS_DB_HOST_KEY: {{ .Values.env.rds_db_host_key | quote }}
RDS_DB_NAME_KEY: {{ .Values.env.rds_db_name_key | quote }}
RDS_DB_PASSWORD_KEY: {{ .Values.env.rds_db_password_key | quote }}
RDS_DB_PORT_KEY: {{ .Values.env.rds_db_port_key | quote }}
RDS_DB_USERNAME_KEY: {{ .Values.env.rds_db_username_key | quote }}
{{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ metadata:
name: {{ .Release.Name }}-live-secrets
stringData:
LIVE_SERVER_SECRET_KEY: {{ .Values.env.live_server_secret_key | default "htbqvBJAgpm9bzvf3r4urJer0ENReatceh" | quote }}
# Used by PI workloads to resolve ElastiCache credentials.
# This value is rendered into `live-secrets` (not `pi-api-vars`/`pi-api-secrets`).
{{- if and (not (empty .Values.env.apiSecrets.elasticache_secret_arn)) (not (empty .Values.env.redis_auth_token_key)) }}
ELASTICACHE_SECRET_ARN: {{ .Values.env.apiSecrets.elasticache_secret_arn | quote }}
REDIS_AUTH_TOKEN_KEY: {{ .Values.env.redis_auth_token_key | quote }}
{{- end }}
{{- if .Values.services.redis.local_setup }}
REDIS_URL: "redis://{{ .Release.Name }}-redis.{{ .Release.Namespace }}.svc.cluster.local:6379/"
{{- else }}
Expand All @@ -26,6 +32,9 @@ data:
LIVE_SENTRY_TRACES_SAMPLE_RATE: {{ .Values.env.live_sentry_traces_sample_rate | default "" | quote }}
LIVE_BASE_PATH: "/live"

# Secret cache TTL used by the credentials provider in workloads.
AWS_SECRET_CACHE_TTL: {{ .Values.env.aws_secret_cache_ttl | default "300" | quote }}

{{- if .Values.env.external_iframely_url }}
IFRAMELY_URL: {{ .Values.env.external_iframely_url | default "" | quote }}
{{- else }}
Expand Down
Loading
Loading