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: 3.0.0
version: 3.0.1
appVersion: "3.0.0"

home: https://plane.so/
Expand Down
4 changes: 4 additions & 0 deletions charts/plane-enterprise/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,10 @@ securityContext:
| env.web_url | | | (optional) Custom Web URL for the application. If not set, it will be auto-generated based on the license domain and SSL settings |
| env.webhook_allowed_ips | | | (optional) Comma-separated list of IPs/CIDRs that webhooks are allowed to target. Leave empty to allow all. |
| env.webhook_allowed_hosts | | | (optional) Comma-separated list of hostnames that webhooks are allowed to target. Leave empty to allow all. |
| env.gunicorn_max_requests | 1000 | | Maximum requests a gunicorn worker handles before restart. Set to `0` to disable rotation. |
| env.gunicorn_max_requests_jitter | 150 | | Random jitter added to `GUNICORN_MAX_REQUESTS` to stagger worker restarts across replicas. Set to `0` when rotation is disabled. |
| env.celery_task_publish_retry | true | | When `true`, Celery retries task publishing on transient AMQP failures instead of silently dropping tasks. Prevents stuck export/import records caused by brief broker reconnect windows. |
| env.celery_broker_pool_limit | 10 | | Bounds the Celery broker connection pool. Prevents stale connections from accumulating without bound; tune relative to worker concurrency. |
Comment thread
akshat5302 marked this conversation as resolved.
| services.api.assign_cluster_ip | false | | Set it to `true` if you want to assign `ClusterIP` to the service |
| services.api.nodeSelector | {} | | This key allows you to set the node selector for the deployment of `api`. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster. |
| services.api.tolerations | [] | | This key allows you to set the tolerations for the deployment of `api`. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster. |
Expand Down
20 changes: 20 additions & 0 deletions charts/plane-enterprise/questions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,26 @@ questions:
label: "Webhook Allowed Hosts"
type: string
default: ""
- variable: env.gunicorn_max_requests
label: "Gunicorn Max Requests"
description: "Maximum number of requests a gunicorn worker handles before being restarted. Set to 0 to disable rotation."
type: int
default: 1000
- variable: env.gunicorn_max_requests_jitter
label: "Gunicorn Max Requests Jitter"
description: "Random jitter added to GUNICORN_MAX_REQUESTS to stagger worker restarts. Set to 0 when rotation is disabled."
type: int
default: 150
- variable: env.celery_task_publish_retry
label: "Celery Task Publish Retry"
description: "Retry task publishing on transient AMQP failures instead of silently dropping tasks."
type: boolean
default: true
- variable: env.celery_broker_pool_limit
label: "Celery Broker Pool Limit"
description: "Maximum number of connections in the Celery broker connection pool. Limits stale connection accumulation."
type: int
default: 10
- variable: services.external_api.enabled
label: "Enable External API"
type: boolean
Expand Down
4 changes: 4 additions & 0 deletions charts/plane-enterprise/templates/config-secrets/app-env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ data:
DEBUG: "0"
DOCKERIZED: "1"
GUNICORN_WORKERS: "1"
GUNICORN_MAX_REQUESTS: {{ .Values.env.gunicorn_max_requests | default 1000 | quote }}
GUNICORN_MAX_REQUESTS_JITTER: {{ .Values.env.gunicorn_max_requests_jitter | default 150 | quote }}
CELERY_TASK_PUBLISH_RETRY: {{ .Values.env.celery_task_publish_retry | ternary "True" "False" | quote }}
CELERY_BROKER_POOL_LIMIT: {{ .Values.env.celery_broker_pool_limit | default 10 | quote }}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

helm template plane-enterprise charts/plane-enterprise \
  --set env.celery_broker_pool_limit=0 |
  grep -F 'CELERY_BROKER_POOL_LIMIT: "0"'

Repository: makeplane/helm-charts

Length of output: 197


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== candidate files =="
fd -a 'app-env.yaml|values.yaml|Chart.yaml' charts 2>/dev/null | sort

echo
echo "== app-env relevant section =="
if [ -f charts/plane-enterprise/templates/config-secrets/app-env.yaml ]; then
  nl -ba charts/plane-enterprise/templates/config-secrets/app-env.yaml | sed -n '70,90p'
fi

echo
echo "== values references for celery_broker_pool_limit =="
rg -n "celery_broker_pool_limit|broker_pool_limit|CELERY_BROKER_POOL_LIMIT" -S .

Repository: makeplane/helm-charts

Length of output: 610


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
# Read-only behavioral probe of Helm Go `default` equivalent semantics as described:
# numeric 0 is treated empty by the chart template, so an explicit 0 via default 10 becomes 10.
from functools import reduce
values = {'env': {'celery_broker_pool_limit': 0}}
actual = values.get('env') or {}
actual = actual.get('celery_broker_pool_limit')
result = actual if actual is not None and actual != '' else 10
print('env.celery_broker_pool_limit 0 ->', result)

values = {'env': {'celery_broker_pool_limit': None}}
actual = values.get('env') or {}
actual = actual.get('celery_broker_pool_limit')
result = actual if actual is not None and actual != '' else 10
print('missing default fallback key ->', result)
PY

Repository: makeplane/helm-charts

Length of output: 230


🌐 Web query:

Helm chart function default zero numeric treated empty documentation

💡 Result:

In Helm charts, the default function treats a numeric 0 as an "empty" value [1][2]. Consequently, if you use {{ default "fallback".Values.myValue }} and.Values.myValue is set to 0, Helm will return "fallback" instead of 0 [3][4]. This behavior is intended by the template engine, which considers the following types "empty" [1][2]: - Numeric: 0 - String: "" - Lists: [] - Dictionaries: {} - Boolean: false - Nil (null) Because 0 is categorized as empty, the default function cannot natively distinguish between a value that is missing (nil) and a value that is explicitly set to 0 [4][5]. Workarounds If your use case requires treating 0 as a valid value while still providing a default for truly missing/null values, you must implement logic to explicitly check the value instead of relying on the default function [3][4]: 1. Explicit Check with if/else: You can check if the value is specifically 0 before applying a default [5]: {{- if eq (toString.Values.myValue) "0" }} myValue: 0 {{- else }} myValue: {{ default "fallback".Values.myValue }} {{- end }} 2. Kind Checking: Some developers use the kindIs function to verify if the value is set before deciding how to handle it, which helps avoid type-related comparison errors [6]: {{- if or (kindIs "int64".Values.myValue) (kindIs "float64".Values.myValue) }} myValue: {{.Values.myValue }} {{- else }} myValue: {{ default "fallback".Values.myValue }} {{- end }} 3. Setting Defaults in values.yaml: The most robust practice is to define static default values directly in your values.yaml file rather than using the default function in templates [7][8][5]. This ensures the value is explicitly defined and avoids the ambiguity of the default function [5].

Citations:


🌐 Web query:

Celery broker_pool_limit 0 disable connection pool documentation

💡 Result:

According to official Celery documentation, setting the broker_pool_limit configuration option to 0 or None will disable the broker connection pool [1][2][3]. When disabled, Celery will establish and close a connection for every individual use [1][2][3]. While this is the documented behavior, it is worth noting that some users have reported issues in recent versions of Celery where setting this parameter to 0 or None does not appear to have the expected effect of disabling the pool, leading to potential connection exhaustion in certain client configurations [4]. The broker connection pool has been enabled by default since Celery version 2.5, with a default limit of 10 connections [1][2][3]. Increasing this limit is generally recommended to minimize contention in environments with high numbers of active threads or green-threads [5][1][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path("charts/plane-enterprise/templates/config-secrets/app-env.yaml")
text = p.read_text()
idx = text.find("CELERY_BROKER_POOL_LIMIT")
print(text[idx-120: idx+160])

path = Path("charts/plane-enterprise/values.yaml")
print("\n=== values.yaml celery_broker_pool_limit context ==")
lines = [ln.splitlines()[0] for ln in path.read_text().splitlines()]
for i, line in enumerate(lines, 1):
    if "celery_broker_pool_limit" in line:
        for offset in range(-3, 4):
            j = i + offset
            if 0 < j <= len(lines):
                print(f"{j}: {lines[j-1]}")
PY

Repository: makeplane/helm-charts

Length of output: 642


Preserve an explicit 0 broker pool limit.

default treats numeric 0 as empty, so --set env.celery_broker_pool_limit=0 renders CELERY_BROKER_POOL_LIMIT: "10". Since Celery allows 0 and None to disable the connection pool, use presence-based handling such as hasKey or validate/reject 0 explicitly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@charts/plane-enterprise/templates/config-secrets/app-env.yaml` at line 82,
Update the CELERY_BROKER_POOL_LIMIT template expression to preserve an
explicitly configured value of 0 instead of allowing default to replace it with
10. Use presence-based handling such as hasKey on
.Values.env.celery_broker_pool_limit, while retaining 10 only when the key is
absent.

{{- if .Values.env.web_url}}
WEB_URL: {{ .Values.env.web_url | default "" | quote }}
{{- else if or .Values.ssl.tls_secret_name (and .Values.ssl.createIssuer .Values.ssl.generateCerts) }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ data:

FEATURE_FLAG_SERVER_BASE_URL: "http://{{ .Release.Name }}-monitor.{{ .Release.Namespace }}.svc.{{ .Values.env.default_cluster_domain | default "cluster.local" }}:8080"
PI_BASE_PATH: "/pi"
PLANE_INTERNAL_API_HOST: "http://{{ .Release.Name }}-api.{{ .Release.Namespace }}.svc.{{ .Values.env.default_cluster_domain | default "cluster.local" }}:8000"


{{- if eq .Values.env.pi_envs.cors_allowed_origins "*"}}
Expand Down
10 changes: 10 additions & 0 deletions charts/plane-enterprise/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,16 @@ env:
secret_key: "60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5"
api_key_rate_limit: "60/minute"

# Gunicorn worker rotation settings.
gunicorn_max_requests: 1000
gunicorn_max_requests_jitter: 150

# Celery broker settings.
# celery_task_publish_retry: retry task publishing on transient AMQP failures instead of silently dropping.
# celery_broker_pool_limit: bound the connection pool to prevent stale connections accumulating.
celery_task_publish_retry: true
celery_broker_pool_limit: 10

sentry_dsn: ''
sentry_environment: ''

Expand Down