Skip to content
Merged
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
9 changes: 9 additions & 0 deletions .changeset/fix-nightly-css-dts-docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@hyperdx/app': patch
---

Copy `css.d.ts` into the Docker build stage so the app image compiles. The
TypeScript 6 upgrade added ambient `declare module '*.css'` declarations in
`css.d.ts` to satisfy TS2882 for side-effect stylesheet imports, but the
Dockerfiles only copied `mdx.d.ts`, so `next build` failed inside the
container.
191 changes: 191 additions & 0 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
name: Docker Build
# Verifies the release Docker images actually build on PRs, without pushing.
# A source-level type check (`make ci-lint`) cannot catch build failures that
# only surface inside the image — e.g. a declaration file that exists in the
# repo but was never COPYed into the Docker build stage. Each image is built
# only when files that affect it change, so unrelated PRs stay fast.
on:
pull_request:
branches: [main]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
# OTel Collector image (Go build via OCB) — docker/otel-collector/Dockerfile.
otel-collector-image:
name: Build OTel Collector Image
runs-on: ubuntu-24.04
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v47.0.6
with:
files: |
docker/otel-collector/**
packages/otel-collector/**
- name: Setup Docker Buildx
if:
steps.changed-files.outputs.any_changed == 'true' || github.event_name
== 'workflow_dispatch'
uses: docker/setup-buildx-action@v3
- name: Build (no push)
if:
steps.changed-files.outputs.any_changed == 'true' || github.event_name
== 'workflow_dispatch'
uses: docker/build-push-action@v6
with:
context: .
file: ./docker/otel-collector/Dockerfile
target: prod
platforms: linux/amd64
push: false
cache-from: |
type=gha,scope=otel-collector-nightly-amd64
type=gha,scope=docker-build-pr-otel-collector
cache-to: type=gha,mode=max,scope=docker-build-pr-otel-collector

# App/prod image (API + App + common-utils Node build) — docker/hyperdx target prod.
# This is the image the nightly css.d.ts failure surfaced in; the same builder
# stage backs the all-in-one targets below.
app-image:
name: Build App Image
runs-on: ubuntu-24.04
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v47.0.6
with:
files: |
packages/api/**
packages/app/**
packages/common-utils/**
docker/hyperdx/**
package.json
yarn.lock
.yarn/**
.yarnrc.yml
.prettierrc
.prettierignore
tsconfig.base.json
nx.json
- name: Setup Docker Buildx
if:
steps.changed-files.outputs.any_changed == 'true' || github.event_name
== 'workflow_dispatch'
uses: docker/setup-buildx-action@v3
- name: Build (no push)
if:
steps.changed-files.outputs.any_changed == 'true' || github.event_name
== 'workflow_dispatch'
uses: docker/build-push-action@v6
with:
context: .
file: ./docker/hyperdx/Dockerfile
target: prod
platforms: linux/amd64
push: false
build-contexts: |
hyperdx=./docker/hyperdx
api=./packages/api
app=./packages/app
build-args: |
CODE_VERSION=pr-${{ github.event.pull_request.number || github.run_id }}
cache-from: |
type=gha,scope=app-nightly-amd64
type=gha,scope=docker-build-pr-app
cache-to: type=gha,mode=max,scope=docker-build-pr-app

# All-in-one image (adds ClickHouse, MongoDB, OTel Collector to the app build)
# — docker/hyperdx targets all-in-one-auth AND all-in-one-noauth (the Local
# image). The two are siblings off the shared all-in-one-base, each with its
# own final COPY of an entry script (entry.local.auth.sh / .noauth.sh), so
# building auth alone would NOT catch a break in the noauth-specific layer —
# which is what surfaced in the nightly. Both are built here; the base is
# built once and reused from buildx's local cache for the second target, so
# the noauth build only adds its one tiny COPY layer.
#
# This target's base does `COPY --from=prod /app /app`, so it already
# rebuilds the entire App/prod image. To avoid duplicating that ~8-minute
# Node build on every app change, this job is gated ONLY on the incremental
# bundling inputs (ClickHouse / OTel / the shared Dockerfile) — NOT on
# api/app/common-utils/deps. Those are covered by the App Image job above,
# and they can't break the bundling layers, which only COPY the prod output.
all-in-one-image:
name: Build All-in-One Image
runs-on: ubuntu-24.04
timeout-minutes: 40
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v47.0.6
with:
files: |
packages/otel-collector/**
docker/hyperdx/**
docker/clickhouse/**
docker/otel-collector/**
.vex/**
- name: Setup Docker Buildx
if:
steps.changed-files.outputs.any_changed == 'true' || github.event_name
== 'workflow_dispatch'
uses: docker/setup-buildx-action@v3
- name: Build all-in-one-auth (no push)
if:
steps.changed-files.outputs.any_changed == 'true' || github.event_name
== 'workflow_dispatch'
uses: docker/build-push-action@v6
with:
context: .
file: ./docker/hyperdx/Dockerfile
Comment thread
greptile-apps[bot] marked this conversation as resolved.
target: all-in-one-auth
platforms: linux/amd64
push: false
build-contexts: |
clickhouse=./docker/clickhouse
otel-collector=./docker/otel-collector
hyperdx=./docker/hyperdx
api=./packages/api
app=./packages/app
build-args: |
CODE_VERSION=pr-${{ github.event.pull_request.number || github.run_id }}
cache-from: |
type=gha,scope=all-in-one-nightly-amd64
type=gha,scope=docker-build-pr-all-in-one
cache-to: type=gha,mode=max,scope=docker-build-pr-all-in-one
# noauth is a sibling of auth off the shared all-in-one-base; the base is
# already in buildx's local cache from the step above, so this only builds
# the final noauth COPY layer.
- name: Build all-in-one-noauth / Local (no push)
if:
steps.changed-files.outputs.any_changed == 'true' || github.event_name
== 'workflow_dispatch'
uses: docker/build-push-action@v6
with:
context: .
file: ./docker/hyperdx/Dockerfile
target: all-in-one-noauth
platforms: linux/amd64
push: false
build-contexts: |
clickhouse=./docker/clickhouse
otel-collector=./docker/otel-collector
hyperdx=./docker/hyperdx
api=./packages/api
app=./packages/app
build-args: |
CODE_VERSION=pr-${{ github.event.pull_request.number || github.run_id }}
cache-from: |
type=gha,scope=all-in-one-nightly-amd64
type=gha,scope=docker-build-pr-all-in-one
2 changes: 1 addition & 1 deletion docker/hyperdx/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ COPY .yarnrc.yml yarn.lock package.json nx.json .prettierrc .prettierignore ./ts
# full source is copied in the build stages that need it.
COPY ./packages/common-utils/package.json ./packages/common-utils/package.json
COPY ./packages/api/jest.config.js ./packages/api/tsconfig.json ./packages/api/tsconfig.build.json ./packages/api/package.json ./packages/api/
COPY ./packages/app/jest.config.js ./packages/app/tsconfig.json ./packages/app/tsconfig.build.json ./packages/app/package.json ./packages/app/next.config.mjs ./packages/app/mdx.d.ts ./packages/app/eslint.config.mjs ./packages/app/
COPY ./packages/app/jest.config.js ./packages/app/tsconfig.json ./packages/app/tsconfig.build.json ./packages/app/package.json ./packages/app/next.config.mjs ./packages/app/mdx.d.ts ./packages/app/css.d.ts ./packages/app/eslint.config.mjs ./packages/app/

# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/tasks/checkAlerts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ export const getScheduledWindowStart = (
* that history fetched up-front (see getConsecutiveWindowHistories) lines up
* exactly with the window processAlert evaluates.
*/
export const getAlertWindowStart = (alert: IAlert, now: Date): Date => {
const getAlertWindowStart = (alert: IAlert, now: Date): Date => {
const windowSizeInMins = ms(alert.interval) / 60000;
const scheduleStartAt = normalizeScheduleStartAt({
alertId: alert.id,
Expand Down
2 changes: 1 addition & 1 deletion packages/app/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ COPY .yarnrc.yml yarn.lock package.json nx.json .prettierrc .prettierignore ./ts
# Only copy package.json for workspace resolution during yarn install;
# full source is copied in the build stages that need it.
COPY ./packages/common-utils/package.json ./packages/common-utils/package.json
COPY ./packages/app/jest.config.js ./packages/app/tsconfig.json ./packages/app/tsconfig.build.json ./packages/app/package.json ./packages/app/next.config.mjs ./packages/app/mdx.d.ts ./packages/app/eslint.config.mjs ./packages/app/
COPY ./packages/app/jest.config.js ./packages/app/tsconfig.json ./packages/app/tsconfig.build.json ./packages/app/package.json ./packages/app/next.config.mjs ./packages/app/mdx.d.ts ./packages/app/css.d.ts ./packages/app/eslint.config.mjs ./packages/app/
RUN --mount=type=cache,target=/root/.yarn/berry/cache,id=yarn-cache \
yarn install --mode=skip-build && yarn cache clean

Expand Down
Loading