From 881d55a37d012c4fbb1698711421b76eaa196e33 Mon Sep 17 00:00:00 2001 From: Matti Nannt <675065+mattinannt@users.noreply.github.com> Date: Tue, 28 Jul 2026 10:54:11 +0200 Subject: [PATCH 1/2] chore: remove dead nextBundleAnalysis config from root package.json (#8657) Co-authored-by: Claude --- package.json | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/package.json b/package.json index 5bb60c639046..47f746bc4a8a 100644 --- a/package.json +++ b/package.json @@ -79,11 +79,5 @@ "engines": { "node": ">=20.19.0 <21 || >=22.12.0 <23 || >=24.0.0 <25" }, - "packageManager": "pnpm@11.7.0", - "nextBundleAnalysis": { - "budget": 358400, - "budgetPercentIncreaseRed": 20, - "minimumChangeThreshold": 0, - "showDetails": true - } + "packageManager": "pnpm@11.7.0" } From ca66695a19ec85ee90ee505418d4e7008ae65efd Mon Sep 17 00:00:00 2001 From: Bhagya Amarasinghe Date: Tue, 28 Jul 2026 14:25:52 +0530 Subject: [PATCH 2/2] fix: disable external pre-aggregations for bundled Cube (#8652) --- .github/workflows/helm-chart-validation.yml | 23 +++++++++++++++++++++ charts/formbricks/README.md | 6 +++++- charts/formbricks/values.yaml | 3 +++ docker/README.md | 18 +++++++++++++++- docker/__tests__/formbricks-script.test.ts | 9 ++++++++ docker/docker-compose.yml | 1 + 6 files changed, 58 insertions(+), 2 deletions(-) diff --git a/.github/workflows/helm-chart-validation.yml b/.github/workflows/helm-chart-validation.yml index b8051ab7223f..6af5d1d2ce32 100644 --- a/.github/workflows/helm-chart-validation.yml +++ b/.github/workflows/helm-chart-validation.yml @@ -37,6 +37,29 @@ jobs: helm lint "$chart" --set formbricks.webappUrl=https://qa.example.com + helm template qa "$chart" \ + --set formbricks.webappUrl=https://qa.example.com \ + --show-only templates/cube-deployment.yaml > "$render_dir/cube-default.yaml" + grep -A1 'name: CUBEJS_EXTERNAL_DEFAULT' "$render_dir/cube-default.yaml" \ + | grep -q 'value: "false"' + + helm template qa "$chart" \ + --set formbricks.webappUrl=https://qa.example.com \ + --set-string cube.env.CUBEJS_EXTERNAL_DEFAULT=true \ + --show-only templates/cube-deployment.yaml > "$render_dir/cube-external.yaml" + grep -A1 'name: CUBEJS_EXTERNAL_DEFAULT' "$render_dir/cube-external.yaml" \ + | grep -q 'value: "true"' + + if helm template qa "$chart" \ + --set formbricks.webappUrl=https://qa.example.com \ + --set cube.replicas=2 \ + --show-only templates/cube-deployment.yaml > "$render_dir/cube-invalid.yaml" 2>&1; then + echo "Expected the in-memory Cube configuration with multiple replicas to fail" >&2 + exit 1 + fi + grep -q 'CUBEJS_CACHE_AND_QUEUE_DRIVER=memory is only supported when cube.replicas=1' \ + "$render_dir/cube-invalid.yaml" + helm template qa "$chart" \ --set formbricks.webappUrl=https://qa.example.com \ --show-only templates/migration-job.yaml > "$render_dir/default.yaml" diff --git a/charts/formbricks/README.md b/charts/formbricks/README.md index 3c3ed9710169..2b93da1df4ac 100644 --- a/charts/formbricks/README.md +++ b/charts/formbricks/README.md @@ -59,7 +59,11 @@ Cube is part of the baseline Formbricks v5 stack and is deployed by this chart b - The generated app secret supplies `CUBEJS_API_SECRET` by default. If you disable generated secrets, provide it through your existing secret management flow. - Provide `CUBEJS_DB_*` connection variables to the Cube deployment through `cube.envFrom` or `cube.env`. -- Keep `cube.replicas=1` while `cube.env.CUBEJS_CACHE_AND_QUEUE_DRIVER` is `memory`. Configure Cube Store before running multiple Cube replicas. +- The bundled single-replica Cube has no external pre-aggregations and defaults + `cube.env.CUBEJS_EXTERNAL_DEFAULT` to `false`, so it does not require Cube Store. If you add external + pre-aggregations, configure Cube Store before overriding this value to `true`. +- Keep `cube.replicas=1` while `cube.env.CUBEJS_CACHE_AND_QUEUE_DRIVER` is `memory`. Configure Cube Store + and switch cache and queue storage away from memory before running multiple Cube replicas. - Keep Hub enabled. Cube should point at the same feedback records database that Hub writes to, unless you intentionally split that storage. ## Hub worker and self-hosted embeddings diff --git a/charts/formbricks/values.yaml b/charts/formbricks/values.yaml index 57c03680c867..f5fb9dfdd717 100644 --- a/charts/formbricks/values.yaml +++ b/charts/formbricks/values.yaml @@ -884,6 +884,9 @@ cube: # the Cube listener port through envFrom. CUBEJS_DB_TYPE: "postgres" CUBEJS_DEFAULT_API_SCOPES: "meta,data" + # The bundled schema has no external pre-aggregations, so Cube Store is not required. + # Override this only after configuring Cube Store for custom external pre-aggregations. + CUBEJS_EXTERNAL_DEFAULT: "false" # Keep the in-memory cache/queue driver at one Cube replica only. The chart # fails rendering when this remains "memory" and cube.replicas is greater than 1. CUBEJS_CACHE_AND_QUEUE_DRIVER: "memory" diff --git a/docker/README.md b/docker/README.md index 945d0f7fef28..e786d3568dfa 100644 --- a/docker/README.md +++ b/docker/README.md @@ -33,7 +33,23 @@ That's it! After running the command and providing the required information, vis The stack includes the [Formbricks Hub](https://github.com/formbricks/hub) API (`ghcr.io/formbricks/hub`) and the bundled Cube service. Hub and Cube share the same database as Formbricks by default and both start as part of the baseline `docker compose up`. - **Migrations**: A `formbricks-migrate` service runs Formbricks Prisma migrations before `hub-migrate` writes Hub tables to the shared database. `hub-migrate` then runs Hub's database migrations (goose + river) before the Hub API starts. Both migration services run on every `docker compose up` and are idempotent. -- **Production** (`docker/docker-compose.yml`): Set non-empty `HUB_API_KEY` and `CUBEJS_API_SECRET` in `.env` before starting the stack. `docker compose config >/dev/null` validates compose syntax, but missing secrets are reported by the service that needs them at startup. `HUB_API_URL` defaults to `http://hub:8080` and `CUBEJS_API_URL` defaults to `http://cube:4000` so the Formbricks app reaches Hub and Cube inside the compose network. Cube JWT issuer/audience default to `formbricks-web` and `formbricks-cube`, and the bundled Cube service exposes only `meta,data` API scopes. Override `HUB_DATABASE_URL` and `CUBEJS_DB_*` only if Hub or Cube should use a separate database. The Hub image tracks `:latest` by default so `formbricks.sh update` advances Hub in lockstep with the app. `hub` and `hub-migrate` always resolve to the same image. To pin to an immutable reference, set `HUB_IMAGE_REF` in `docker/.env` to either a tag (e.g. `:0.3.0`) or a digest (e.g. `@sha256:14db7b3d...`). +- **Production** (`docker/docker-compose.yml`): Set non-empty `HUB_API_KEY` and + `CUBEJS_API_SECRET` in `.env` before starting the stack. `docker compose config >/dev/null` validates + Compose syntax, but missing secrets are reported by the service that needs them at startup. + `HUB_API_URL` defaults to `http://hub:8080` and `CUBEJS_API_URL` defaults to `http://cube:4000` so the + Formbricks app reaches Hub and Cube inside the Compose network. Cube JWT issuer/audience default to + `formbricks-web` and `formbricks-cube`, and the bundled Cube service exposes only `meta,data` API + scopes. The bundled single-replica Cube uses in-memory cache and queue storage and defaults + `CUBEJS_EXTERNAL_DEFAULT` to `false`, so it does not require Cube Store. If you add external + pre-aggregations, configure Cube Store before overriding `CUBEJS_EXTERNAL_DEFAULT=true`. Override + `HUB_DATABASE_URL` and `CUBEJS_DB_*` only if Hub or Cube should use a separate database. The Hub image + tracks `:latest` by default so `formbricks.sh update` advances Hub in lockstep with the app. `hub` and + `hub-migrate` always resolve to the same image. To pin to an immutable reference, set `HUB_IMAGE_REF` + in `docker/.env` to either a tag (e.g. `:0.3.0`) or a digest + (e.g. `@sha256:14db7b3d...`). +- **Existing production installs**: Pulling new images does not replace an existing + `docker-compose.yml`. Add `CUBEJS_EXTERNAL_DEFAULT: ${CUBEJS_EXTERNAL_DEFAULT:-false}` to the Cube + service's `environment` block, then run `docker compose up -d --no-deps --force-recreate cube`. - **Development** (`docker-compose.dev.yml`): Hub uses a dedicated local `hub` database and `HUB_API_KEY` defaults to `dev-api-key`. The dev stack starts `hub` plus `hub-worker`; set `EMBEDDING_PROVIDER`, `EMBEDDING_MODEL`, and any provider credentials in the repo root `.env` to enable Hub embeddings locally. See the [Hub embeddings environment reference](https://hub.formbricks.com/reference/environment-variables/#embeddings) for provider-specific values. Cube starts with the dev stack, `CUBEJS_API_URL` defaults to `http://localhost:4000`, and `pnpm dev:setup` generates `CUBEJS_API_SECRET` in the repo root `.env`. The Hub image is pinned to a semver tag (`hub`, `hub-worker`, and `hub-migrate` share the same value); override `HUB_IMAGE_TAG` in the repo root `.env` to test a specific Hub release. ## Smart Functionality AI with Qwen/vLLM diff --git a/docker/__tests__/formbricks-script.test.ts b/docker/__tests__/formbricks-script.test.ts index e374e608d72f..a26ea5fadfd8 100644 --- a/docker/__tests__/formbricks-script.test.ts +++ b/docker/__tests__/formbricks-script.test.ts @@ -62,6 +62,15 @@ afterEach(() => { } }); +describe("docker/docker-compose.yml Cube configuration", () => { + test("disables external pre-aggregations by default while allowing an operator override", () => { + const composeContents = readFileSync(dockerComposeTemplatePath, "utf8"); + const cubeBlock = getServiceBlock(composeContents, "cube"); + + expect(cubeBlock).toContain(" CUBEJS_EXTERNAL_DEFAULT: ${CUBEJS_EXTERNAL_DEFAULT:-false}"); + }); +}); + describe("docker/formbricks.sh Traefik label injection", () => { test("adds HTTPS Traefik labels to the formbricks service only", () => { const composePath = writeDockerComposeTemplate(); diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 0be96e1f0495..3eae8e0cc248 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -458,6 +458,7 @@ services: CUBEJS_JWT_ISSUER: ${CUBEJS_JWT_ISSUER:-formbricks-web} CUBEJS_JWT_AUDIENCE: ${CUBEJS_JWT_AUDIENCE:-formbricks-cube} CUBEJS_DEFAULT_API_SCOPES: meta,data + CUBEJS_EXTERNAL_DEFAULT: ${CUBEJS_EXTERNAL_DEFAULT:-false} CUBEJS_CACHE_AND_QUEUE_DRIVER: memory volumes: - ./cube/cube.js:/cube/conf/cube.js:ro