diff --git a/.gitignore b/.gitignore index 98db478c5b8f2..d6c10c4e1fe7f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules .yarn +packages/cubejs-docker/stacklet-patches/*-dist/ .yarnrc /.idea /.vscode diff --git a/packages/cubejs-docker/DEVELOPMENT.md b/packages/cubejs-docker/DEVELOPMENT.md index 2342e933ed723..745e330ad44c7 100644 --- a/packages/cubejs-docker/DEVELOPMENT.md +++ b/packages/cubejs-docker/DEVELOPMENT.md @@ -24,3 +24,44 @@ docker build -t cubejs/cube:latest-jdk -f latest-debian-jdk.Dockerfile . docker build -t cubejs/cube:dev -f dev.Dockerfile ../../ docker buildx build --platform linux/amd64 -t cubejs/cube:dev -f dev.Dockerfile ../../ ``` + +## Stacklet builds + +The Stacklet fork patches certain Cube packages at the TypeScript source level. +Because `latest.Dockerfile` installs packages from npm (not from the local +workspace), a wrapper script is required to compile modified packages and stage +their compiled output before `docker build` runs. + +**Always use the build script — never `docker build` directly:** + +```sh +# From the repo root: +./scripts/build-docker.sh cubejs/cube:v1.6.6-stacklet-$(git rev-parse --short HEAD) +``` + +The script: +1. Runs `yarn workspace @cubejs-backend/server-core build` (and any other + patched packages) +2. Copies compiled `dist/` output into `stacklet-patches/-dist/` +3. Runs `docker build`; the Dockerfile overlays those dist files on the + npm-installed versions +4. Cleans up the staged files on exit + +### Adding a new patched package + +1. Make source changes and compile: `yarn workspace @cubejs-backend/ build` +2. Add a compile + stage block to `scripts/build-docker.sh`: + ```bash + mkdir -p "$PATCHES_DIR/-dist" + cp -r "$REPO_ROOT/packages/cubejs-/dist/." "$PATCHES_DIR/-dist/" + ``` +3. No Dockerfile change is needed — `latest.Dockerfile` automatically applies + any `*-dist/` directories it finds in `stacklet-patches/`. + +### Verifying a patch is in the image + +```sh +docker run --rm grep -c "Performing query completed" \ + /cube/node_modules/@cubejs-backend/server-core/dist/src/core/logger.js +# expected: 2 +``` diff --git a/packages/cubejs-docker/latest.Dockerfile b/packages/cubejs-docker/latest.Dockerfile index 0088df1b68a95..8802e49c99334 100644 --- a/packages/cubejs-docker/latest.Dockerfile +++ b/packages/cubejs-docker/latest.Dockerfile @@ -33,6 +33,14 @@ RUN yarn install --prod \ && rm -rf /cube/node_modules/duckdb/src \ && yarn cache clean +# Stacklet: overlay locally compiled dist files over npm-installed packages. +# stacklet-patches/-dist/ dirs are populated by scripts/build-docker.sh. +COPY stacklet-patches/ /cube/stacklet-patches/ +RUN find /cube/stacklet-patches -maxdepth 1 -name '*-dist' -type d | while read d; do \ + pkg=$(basename "$d" -dist); \ + cp -r "$d/." "/cube/node_modules/@cubejs-backend/$pkg/dist/"; \ + done && rm -rf /cube/stacklet-patches + FROM node:22.22.0-bookworm-slim ARG IMAGE_VERSION=unknown diff --git a/packages/cubejs-docker/stacklet-patches/.gitkeep b/packages/cubejs-docker/stacklet-patches/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/cubejs-server-core/src/core/logger.ts b/packages/cubejs-server-core/src/core/logger.ts index c7c4844e2b0dc..3f7f5a977517d 100644 --- a/packages/cubejs-server-core/src/core/logger.ts +++ b/packages/cubejs-server-core/src/core/logger.ts @@ -126,6 +126,12 @@ export const prodLogger = (level?: LogLevel) => (msg: string, params: ProdLogPar const logMessage = () => console.log(JSON.stringify({ message: msg, ...params })); + // Always emit regardless of log level — used by CloudWatch log metric filter + if (msg === 'Performing query completed') { + logMessage(); + return; + } + // eslint-disable-next-line default-case switch ((level || 'warn').toLowerCase()) { case 'trace': { diff --git a/scripts/build-docker.sh b/scripts/build-docker.sh new file mode 100755 index 0000000000000..0703d8960b8ab --- /dev/null +++ b/scripts/build-docker.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# Build a Stacklet Cube Docker image. +# +# Usage: ./scripts/build-docker.sh [TAG] +# TAG defaults to cubejs/cube:dev +# +# This script compiles Stacklet-patched packages and stages their dist output +# into packages/cubejs-docker/stacklet-patches/ before invoking docker build. +# The Dockerfile picks up whatever *-dist/ directories it finds there and +# overlays them on the npm-installed versions of those packages. +# +# To add a new patched package in the future: +# 1. Make your source changes and run: yarn workspace @cubejs-backend/ build +# 2. Add a compile + stage block below (following the server-core example) +# 3. No Dockerfile change is needed. + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +DOCKER_DIR="$REPO_ROOT/packages/cubejs-docker" +PATCHES_DIR="$DOCKER_DIR/stacklet-patches" +TAG="${1:-cubejs/cube:dev}" + +cleanup() { + echo "Cleaning up staged patches..." + find "$PATCHES_DIR" -maxdepth 1 -name '*-dist' -type d -exec rm -rf {} + 2>/dev/null || true +} +trap cleanup EXIT + +# --------------------------------------------------------------------------- +# Compile and stage Stacklet-patched packages +# --------------------------------------------------------------------------- + +echo "==> Building @cubejs-backend/server-core..." +yarn --cwd "$REPO_ROOT" workspace @cubejs-backend/server-core build + +echo "==> Staging server-core dist..." +mkdir -p "$PATCHES_DIR/server-core-dist" +cp -r "$REPO_ROOT/packages/cubejs-server-core/dist/." \ + "$PATCHES_DIR/server-core-dist/" + +# --------------------------------------------------------------------------- +# Docker build +# --------------------------------------------------------------------------- + +echo "==> Building Docker image $TAG..." +docker build -t "$TAG" -f "$DOCKER_DIR/latest.Dockerfile" "$DOCKER_DIR" + +echo "==> Done: $TAG" + +echo "==> Verifying logger patch..." +COUNT=$(docker run --rm "$TAG" grep -c 'Performing query completed' \ + /cube/node_modules/@cubejs-backend/server-core/dist/src/core/logger.js) +if [ "$COUNT" -ne 2 ]; then + echo "ERROR: logger patch check failed (expected 2 matches, got $COUNT)" + exit 1 +fi +echo "Logger patch OK ($COUNT matches)"