Skip to content

[HDX-2712] Unified hyperdx entrypoint script for API and tasks - #1951

Merged
kodiakhq[bot] merged 9 commits into
mainfrom
dan/hdx-2712-use-a-single-entry-point-script-for-both-hyperdx-api-and
Mar 20, 2026
Merged

kodiakhq[bot] merged 9 commits into
mainfrom
dan/hdx-2712-use-a-single-entry-point-script-for-both-hyperdx-api-and

Conversation

@dhable

@dhable dhable commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

Summary

The node commands to start the API server and alert task are duplicated across 4+ files, each hardcoding the build output path and node require flags. When the build process changed (esbuild introduction/revert per HDX-2690), the downstream operator and helm chart broke because their entrypoint commands were stale.

This PR introduces packages/api/bin/hyperdx, a single shell script that is the sole source of truth for how to launch API and task processes. It resolves the build directory relative to its own location, applies the correct node flags (-r @hyperdx/node-opentelemetry/build/src/tracing), and exposes two subcommands:

  • hyperdx api -- starts the API server
  • hyperdx task <name> -- runs a named task (e.g., check-alerts)

All Dockerfiles and entry scripts now delegate to this script instead of inlining the node command. Future build changes only need updating in one place.

How to test locally or on Vercel

  1. Build the standalone API image and confirm the entrypoint works:
    docker build . -f packages/api/Dockerfile -t hyperdx-api-test:latest --target prod
    docker run -d --name hdx-api-test -p 18000:8000 hyperdx-api-test:latest
    sleep 5
    docker logs hdx-api-test 2>&1 | head -30
    # Should show OpenTelemetry init + MongoStore error (expected without Mongo)
    # No "file not found" or "permission denied" errors
    docker stop hdx-api-test && docker rm hdx-api-test
  2. Build and run the all-in-one image for a full integration test:
    make build-local
    docker run -d --name hdx-aio-test -p 18080:8080 -p 18000:8000 hyperdx/hyperdx-local:2.21.0
    # Wait up to 90s for startup, then:
    curl -sf http://localhost:18080/api/health  # should return {"data":"OK",...}
    curl -sf http://localhost:18000/health       # should return {"data":"OK",...}
    docker exec hdx-aio-test sh -c "ps aux"
    # Confirm API, APP, and ALERT-TASK processes are running via the hyperdx script
    docker stop hdx-aio-test && docker rm hdx-aio-test
  3. Build the prod image to confirm the entry script changes are valid:
    make build-app

Testing performed: All three Docker image targets were built and verified locally. The standalone API image started node via hyperdx api correctly (crashed on missing MongoDB as expected). The all-in-one image passed health checks on both localhost:18080/api/health and localhost:18000/health, with all three processes (API, APP, ALERT-TASK) confirmed running inside the container using the new entry point script.

References

  • Linear Issue: HDX-2712
  • Related PRs: HDX-2690 (root cause), HDX-2815 (downstream helm chart follow-up)
  • Follow-up needed: Update helm chart cron job template and operator template in ClickHouse/ClickStack-helm-charts to use ./packages/api/bin/hyperdx task check-alerts

Made with Cursor

Replace duplicated node startup commands across Dockerfiles and entry
scripts with a single `packages/api/bin/hyperdx` shell script. This
script is the sole place that knows the build output layout and
required node flags, so future build changes (like the esbuild
introduction/revert that caused HDX-2690) only need updating in one
place.

The script supports two subcommands:
- `hyperdx api` - starts the API server
- `hyperdx task <name>` - runs a named task (e.g., check-alerts)

Made-with: Cursor
@changeset-bot

changeset-bot Bot commented Mar 20, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dc36740

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/api Patch
@hyperdx/app Patch
@hyperdx/otel-collector Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Mar 20, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview, Comment Mar 20, 2026 4:35pm

Request Review

@github-actions

github-actions Bot commented Mar 20, 2026 •

Copy link
Copy Markdown
Contributor

E2E Test Results

✅ All tests passed • 92 passed • 3 skipped • 931s

Status Count
✅ Passed 92
❌ Failed 0
⚠️ Flaky 1
⏭️ Skipped 3

Tests ran across 4 shards in parallel.

View full report →

@github-actions

github-actions Bot commented Mar 20, 2026 •

Copy link
Copy Markdown
Contributor

PR Review

✅ No critical issues found.

The new packages/api/bin/hyperdx shell script is clean and correctly structured:

  • SCRIPT_DIR resolution using cd "$(dirname "$0")" && pwd is the correct POSIX approach
  • Unquoted $NODE_REQUIRE_FLAGS for intentional word-splitting is properly documented with shellcheck disable
  • shift 2>/dev/null || true correctly handles zero-arg invocations
  • File is marked 100755 so Docker COPY will preserve executable bit
  • exec is used correctly to replace the shell process

Docker changes look correct — bin/ is copied in both build and final stages, and the relative-path ENTRYPOINT resolves against the WORKDIR /app correctly.

The start script is not used by any Docker or CI path, so keep it
as the plain node command to avoid silently adding OTel tracing.

Made-with: Cursor
@dhable
dhable requested review from a team and pulpdrew and removed request for a team March 20, 2026 15:58
The hyperdx script is referenced by full path in all Dockerfiles and
entry scripts. The bin field only adds a node_modules/.bin symlink
that nothing uses, and it requires a yarn.lock update.

Made-with: Cursor
Remove bin field and revert any lockfile drift so these files
have no diff against main.

Made-with: Cursor
@kodiakhq
kodiakhq Bot merged commit a0b3361 into main Mar 20, 2026
16 checks passed
@kodiakhq
kodiakhq Bot deleted the dan/hdx-2712-use-a-single-entry-point-script-for-both-hyperdx-api-and branch March 20, 2026 18:27
knudtty pushed a commit that referenced this pull request Apr 16, 2026
## Summary

The node commands to start the API server and alert task are duplicated across 4+ files, each hardcoding the build output path and node require flags. When the build process changed (esbuild introduction/revert per HDX-2690), the downstream operator and helm chart broke because their entrypoint commands were stale.

This PR introduces `packages/api/bin/hyperdx`, a single shell script that is the **sole source of truth** for how to launch API and task processes. It resolves the build directory relative to its own location, applies the correct node flags (`-r @hyperdx/node-opentelemetry/build/src/tracing`), and exposes two subcommands:

- `hyperdx api` -- starts the API server
- `hyperdx task <name>` -- runs a named task (e.g., `check-alerts`)

All Dockerfiles and entry scripts now delegate to this script instead of inlining the node command. Future build changes only need updating in one place.

### How to test locally or on Vercel

1. **Build the standalone API image** and confirm the entrypoint works:
   ```bash
   docker build . -f packages/api/Dockerfile -t hyperdx-api-test:latest --target prod
   docker run -d --name hdx-api-test -p 18000:8000 hyperdx-api-test:latest
   sleep 5
   docker logs hdx-api-test 2>&1 | head -30
   # Should show OpenTelemetry init + MongoStore error (expected without Mongo)
   # No "file not found" or "permission denied" errors
   docker stop hdx-api-test && docker rm hdx-api-test
   ```
2. **Build and run the all-in-one image** for a full integration test:
   ```bash
   make build-local
   docker run -d --name hdx-aio-test -p 18080:8080 -p 18000:8000 hyperdx/hyperdx-local:2.21.0
   # Wait up to 90s for startup, then:
   curl -sf http://localhost:18080/api/health  # should return {"data":"OK",...}
   curl -sf http://localhost:18000/health       # should return {"data":"OK",...}
   docker exec hdx-aio-test sh -c "ps aux"
   # Confirm API, APP, and ALERT-TASK processes are running via the hyperdx script
   docker stop hdx-aio-test && docker rm hdx-aio-test
   ```
3. **Build the prod image** to confirm the entry script changes are valid:
   ```bash
   make build-app
   ```

**Testing performed:** All three Docker image targets were built and verified locally. The standalone API image started node via `hyperdx api` correctly (crashed on missing MongoDB as expected). The all-in-one image passed health checks on both `localhost:18080/api/health` and `localhost:18000/health`, with all three processes (API, APP, ALERT-TASK) confirmed running inside the container using the new entry point script.

### References

- Linear Issue: [HDX-2712](https://linear.app/clickhouse/issue/HDX-2712/use-a-single-entry-point-script-for-both-hyperdx-api-and-alert-job)
- Related PRs: HDX-2690 (root cause), HDX-2815 (downstream helm chart follow-up)
- **Follow-up needed:** Update helm chart cron job template and operator template in `ClickHouse/ClickStack-helm-charts` to use `./packages/api/bin/hyperdx task check-alerts`

Made with [Cursor](https://cursor.com)
wrn14897 added a commit to ClickHouse/ClickStack-helm-charts that referenced this pull request Nov 9, 2026
## Summary

The `check-alerts` CronJob started its container with `node
/app/packages/api/build/tasks/index.js check-alerts`. That bypasses
`bin/hyperdx`, the entrypoint the image itself uses in `entry.prod.sh`,
so the task never loaded a self-telemetry preload and
`OTEL_SERVICE_NAME=hdx-oss-task-check-alerts` was dead config.

ClickHouse/ClickStack#3575 swaps the self-instrumentation SDK for
`@clickhouse/clickstack-node`, and the preload path moves with it.
Mirroring DeploySentinel/hyperdx-operator#314, the CronJob now runs
`/app/packages/api/bin/hyperdx task check-alerts` so the image picks its
own preload and the chart stops caring where it lives.

Linear: [HDX-5951](https://linear.app/hyperdx/issue/HDX-5951)

## Changes

- `templates/hyperdx/cronjob-check-alerts.yaml`: the command switch now
has three branches, keyed on the image tag:
- `< 2.7.0`: `node /app/packages/api/tasks/index check-alerts`
(unchanged)
- `>= 2.7.0, < 2.22.0`: `node /app/packages/api/build/tasks/index.js
check-alerts` (unchanged)
- `>= 2.22.0` or non-semver tag (`2-beta`, `latest`):
`/app/packages/api/bin/hyperdx task check-alerts` (new; default
`appVersion` 2.39.1 takes this path)
  - `additionalArgs` passthrough is preserved in every branch.
- `tests/task-checkAlerts_test.yaml`: `2-beta` and `3.0.0` cases expect
the new command; added boundary tests for `2.21.9`, `2.22.0`, the
default tag, and `additionalArgs` on the new path.
- Changeset (patch).

## Compatibility

`bin/hyperdx` first ships in HyperDX 2.22.0 (ClickHouse/ClickStack#1951) and
is copied into every stage of the all-in-one image. It `exec`s node so
PID 1 and signal handling are unchanged. Post-#3575 the preload only
starts the SDK when `HYPERDX_API_KEY` or `OTEL_EXPORTER_OTLP_HEADERS` is
set; the chart sets `HYPERDX_API_KEY` by default, so the task starts
exporting to the chart's collector like the API pod already does.

## Validation

- `make test`: 286/286
- `make coverage`: 99.85% line, 91.19% branch
- `helm template --set hyperdx.tasks.enabled=true --set
hyperdx.tasks.checkAlerts.additionalArgs.concurrency=4` renders
`["/app/packages/api/bin/hyperdx", "task", "check-alerts",
"--concurrency", "4"]`

This branch was successfully deployed

1 active deployment
Preview — dc367405 Deployed Mar 20, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants