maintenance(frontend): switch release entrypoints to web-app

This commit is contained in:
Logic
2026-07-27 14:32:26 +08:00
parent a93ca81d4c
commit a741b8a8d2
27 changed files with 329 additions and 293 deletions
+1 -1
View File
@@ -79,7 +79,7 @@ home:
webapp:
- changed-files:
- any-glob-to-any-file:
- "web-next/**/*"
- "web-app/**/*"
e2e:
- changed-files:
+10 -2
View File
@@ -20,13 +20,20 @@
name: Backend CI
permissions:
contents: read
concurrency:
group: backend-ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches: [ master, dev, action*, '2.*' ]
paths-ignore:
- '**.md'
- 'home/**'
- 'web-next/**'
- 'web-app/**'
- 'script/**'
- 'material/**'
pull_request:
@@ -34,13 +41,14 @@ on:
paths-ignore:
- '**.md'
- 'home/**'
- 'web-next/**'
- 'web-app/**'
- 'script/**'
- 'material/**'
jobs:
backend-build:
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
- uses: ./script/ci/github-actions/setup-deps
+29 -70
View File
@@ -15,80 +15,31 @@
# specific language governing permissions and limitations
# under the License.
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Frontend CI
permissions:
contents: read
concurrency:
group: frontend-ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches: [ master, dev, 'action*', 'codex/**', 'feature/**', 'release/**', '2.*' ]
paths:
- 'web-next/**'
- 'web-app/**'
- '.github/workflows/frontend-build-test.yml'
pull_request:
branches: [ master, dev, 'codex/**', 'feature/**', 'release/**', '2.*' ]
paths:
- 'web-next/**'
- 'web-app/**'
- '.github/workflows/frontend-build-test.yml'
jobs:
web-next-scope:
runs-on: ubuntu-latest
outputs:
web_next: ${{ steps.web_next_scope.outputs.web_next }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- id: web_next_scope
uses: dorny/paths-filter@v3
with:
filters: |
web_next:
- 'web-next/**'
- '.github/workflows/frontend-build-test.yml'
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: web-next/package-lock.json
- name: Install
working-directory: web-next
run: npm ci
- name: EsLint Test
working-directory: web-next
run: npm run lint
web-next-contract:
needs: web-next-scope
if: ${{ needs.web-next-scope.outputs.web_next == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: web-next/package-lock.json
- name: Install
working-directory: web-next
run: npm ci
- name: Contract Test
working-directory: web-next
run: npm test
web-next-standards:
needs:
- web-next-scope
- web-next-contract
if: ${{ needs.web-next-scope.outputs.web_next == 'true' }}
verify:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
with:
@@ -96,14 +47,22 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: web-next/package-lock.json
- name: Enable pnpm
run: |
corepack enable
corepack prepare pnpm@10.9.0 --activate
- name: Resolve pnpm store
id: pnpm-store
run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
- uses: actions/cache@v4
with:
path: ${{ steps.pnpm-store.outputs.path }}
key: pnpm-${{ runner.os }}-${{ hashFiles('web-app/pnpm-lock.yaml') }}
restore-keys: |
pnpm-${{ runner.os }}-
- name: Install
working-directory: web-next
run: npm ci
- name: verify:full (blocking)
working-directory: web-next
run: npm run verify:full
- name: parity:smoke:baseline (blocking)
working-directory: web-next
run: npm run parity:smoke:baseline
working-directory: web-app
run: pnpm install --frozen-lockfile
- name: Verify
working-directory: web-app
run: pnpm verify
+16 -3
View File
@@ -17,6 +17,13 @@
name: Nightly CI
permissions:
contents: read
concurrency:
group: nightly-ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
schedule:
# trigger at 00:00 everyday
@@ -27,15 +34,21 @@ on:
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 180
if: ${{ github.repository == 'apache/hertzbeat' }}
steps:
- uses: actions/checkout@v4
- uses: ./script/ci/github-actions/setup-deps
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Build the Frontend
run: |
cd web-next
npm ci
npm run build
corepack enable
corepack prepare pnpm@10.9.0 --activate
cd web-app
pnpm install --frozen-lockfile
pnpm build
- name: Build the Backend
run: |
-5
View File
@@ -49,16 +49,11 @@ node_modules
# codex / browser / screenshot noise
.codex-artifacts/
.playwright-mcp/
web-next-*.png
progress.md
test-results/
web-next/test-results/
playwright-report/
web-next/playwright-report/
reports/
screenshots/
web-next/scripts/topology-scale-proof-seed-lib.mjs
web-next/scripts/topology-scale-proof-seed-lib.test.ts
# local temp runtime data
.tmp/
+12 -12
View File
@@ -27,12 +27,12 @@ Even small corrections to typos are very welcome :)
### Getting HertzBeat up and running
> To get HertzBeat code running on your development tools, and able to debug with breakpoints.
> This is a front-end and back-end separation project. To start the local code, the back-end [startup](hertzbeat-startup) and the front-end [web-next](web-next) must be started separately.
> This is a front-end and back-end separation project. To start the local code, the back-end [startup](hertzbeat-startup) and the front-end [web-app](web-app) must be started separately.
#### Backend start
1. Requires `maven3+`, `java21` and `lombok` environments
1. Requires `maven3+`, Java 25 and `lombok` environments
2. (Optional) Modify the configuration file: `hertzbeat-startup/src/main/resources/application.yml`
@@ -44,13 +44,13 @@ Even small corrections to typos are very welcome :)
#### Frontend start
1. Need `Node.js >= 22` and `npm`
1. Need `Node.js 22` and `pnpm 10`
2. Cd to the `web-next` directory: `cd web-next`
2. Cd to the `web-app` directory: `cd web-app`
3. Install dependencies: `npm ci`
3. Install dependencies: `corepack pnpm@10.9.0 install --frozen-lockfile`
4. After the local backend is started, start the local frontend in the `web-next` directory: `npm run dev`
4. After the local backend is started, start the local frontend in the `web-app` directory: `corepack pnpm@10.9.0 dev`
5. Browser access to localhost:4200 to start, default account/password is *admin/hertzbeat*
@@ -176,11 +176,11 @@ Add WeChat account `ahertzbeat` to pull you into the WeChat group.
### 让 HertzBeat 运行起来
> 让 HertzBeat 的代码在您的开发工具上运行起来,并且能够断点调试。
> 此为前后端分离项目,本地代码启动需将后端[hertzbeat-startup](hertzbeat-startup)和前端[web-next](web-next)分别启动生效。
> 此为前后端分离项目,本地代码启动需将后端[hertzbeat-startup](hertzbeat-startup)和前端[web-app](web-app)分别启动生效。
#### 后端启动
1. 需要 `maven3+`, `java21` 和 `lombok` 环境
1. 需要 `maven3+`、Java 25 和 `lombok` 环境
2. (可选)修改配置文件配置信息-`hertzbeat-startup/src/main/resources/application.yml`
@@ -193,13 +193,13 @@ Add WeChat account `ahertzbeat` to pull you into the WeChat group.
#### 前端启动
1. 需要 `Node.js >= 22` 和 `npm`
1. 需要 `Node.js 22` 和 `pnpm 10`
2. 进入 `web-next` 目录: `cd web-next`
2. 进入 `web-app` 目录: `cd web-app`
3. 安装依赖: `npm ci`
3. 安装依赖: `corepack pnpm@10.9.0 install --frozen-lockfile`
4. 待本地后端启动后,在 `web-next` 目录下启动本地前端: `npm run dev`
4. 待本地后端启动后,在 `web-app` 目录下启动本地前端: `corepack pnpm@10.9.0 dev`
5. 浏览器访问 localhost:4200 即可开始,默认账号密码 *admin/hertzbeat*
+3 -3
View File
@@ -158,9 +158,9 @@ Detailed config refer to [Install HertzBeat via Package](https://hertzbeat.apach
##### 3Start via source code
1. Local source code debugging needs to start the back-end project `hertzbeat-startup` and the front-end project `web-next`.
2. Backendneed `maven3+`, `java21`, `lombok`, add VM options in IDE: ` --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED `, then start the `hertzbeat-startup` service.
3. Webneed `Node.js >= 22` and `npm`, run `npm ci && npm run dev` in `web-next` after backend startup.
1. Local source code debugging needs to start the back-end project `hertzbeat-startup` and the front-end project `web-app`.
2. Backend: need `maven3+`, Java 25, and `lombok`; add VM options in IDE: ` --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED `, then start the `hertzbeat-startup` service.
3. Web: need `Node.js 22` and `pnpm 10`, run `corepack pnpm@10.9.0 install --frozen-lockfile && corepack pnpm@10.9.0 dev` in `web-app` after backend startup.
4. Access `http://localhost:4200` to start, default account: `admin/hertzbeat`
Detailed steps refer to [CONTRIBUTING](CONTRIBUTING.md)
+3 -3
View File
@@ -152,9 +152,9 @@
##### 方式三:本地代码启动
1. 此为前后端分离项目,本地代码调试需要分别启动后端工程 `hertzbeat-startup` 和前端工程 `web-next`
2. 后端:需要 `maven3+`, `java21` 和 `lombok` 环境,修改 `YML` 配置信息,添加JVM参数`--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED`后启动 `hertzbeat-startup` 服务即可。
3. 前端:需要 `Node.js >= 22` 和 `npm` 环境,待本地后端启动后,在 `web-next` 目录下执行 `npm ci && npm run dev`
1. 此为前后端分离项目,本地代码调试需要分别启动后端工程 `hertzbeat-startup` 和前端工程 `web-app`
2. 后端:需要 `maven3+`、Java 25 和 `lombok` 环境,修改 `YML` 配置信息,添加JVM参数`--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED`后启动 `hertzbeat-startup` 服务即可。
3. 前端:需要 `Node.js 22` 和 `pnpm 10` 环境,待本地后端启动后,在 `web-app` 目录下执行 `corepack pnpm@10.9.0 install --frozen-lockfile && corepack pnpm@10.9.0 dev`
4. 浏览器访问 `http://localhost:4200` 即可开始,默认账号密码 `admin/hertzbeat`
详细步骤参考 [参与贡献之本地代码启动](CONTRIBUTING.md)
+3 -3
View File
@@ -155,9 +155,9 @@
##### 方式3:ローカルの実行
1. ローカルの実行には、バックエンドのプロジェクト`hertzbeat-startup`とフロントエンドのプロジェクト`web-next`を起動する必要があります。
2. バックエンド:`maven3+`、`Java21`と`lombok`の環境必要です。`YML` 設定を修正し、Java仮想マシンパラメータに`--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED` を追加し、`hertzbeat-startup` を起動します。
3. フロントエンド:`Node.js >= 22` と `npm` の環境が必要です。ローカルのバックエンドが立ち上がったら、`web-next` ディレクトリで `npm ci && npm run dev` を実行します。
1. ローカルの実行には、バックエンドのプロジェクト`hertzbeat-startup`とフロントエンドのプロジェクト`web-app`を起動する必要があります。
2. バックエンド:`maven3+`、Java 25、`lombok`の環境必要です。`YML` 設定を修正し、Java仮想マシンパラメータに`--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED` を追加し、`hertzbeat-startup` を起動します。
3. フロントエンド:`Node.js 22` と `pnpm 10` の環境が必要です。ローカルのバックエンドが立ち上がったら、`web-app` ディレクトリで `corepack pnpm@10.9.0 install --frozen-lockfile && corepack pnpm@10.9.0 dev` を実行します。
4. スタート:`http://localhost:4200`にアクセスします。デフォルトのアカウントとパスワード:`admin/hertzbeat`。
詳細ステップ [貢献ガイド](CONTRIBUTING.md)
+25 -42
View File
@@ -2,15 +2,15 @@
This document is for the GitHub community alpha preview branch. It is not a
stable Apache HertzBeat release checklist. Use it to try the new entity-centered
observability and Next.js frontend work, report issues, and help harden the
project toward a beta.
observability and Vite React frontend, report issues, and help harden the project
toward a beta.
## What Is In Scope
- Entity-centered observability read models for metrics, logs, traces, topology,
alerts, owners, runbooks, and handoff context.
- Next.js `web-next` frontend work for the new shell, entity detail, topology,
and UI Lab surfaces.
- Vite React `web-app` workflows for the operational shell, entity management,
topology, instrumentation, and the three-signal query workspace.
- OTLP trace/log/metric query paths backed by the existing warehouse and
Greptime integrations.
- Local demo topology relation seeding for the small Checkout API -> Payment API
@@ -18,7 +18,7 @@ project toward a beta.
## Local Source Quickstart
1. Start the backend from `hertzbeat-startup` with Java 21.
1. Start the backend from `hertzbeat-startup` with Java 25.
Keep the Arrow JVM open option when running locally:
@@ -28,12 +28,12 @@ project toward a beta.
The local backend listens on `http://127.0.0.1:1157` by default.
2. Start the Next.js frontend:
2. Start the Vite React frontend:
```shell
cd web-next
npm install
npm run dev
cd web-app
corepack pnpm@10.9.0 install --frozen-lockfile
corepack pnpm@10.9.0 dev
```
The preview frontend listens on `http://127.0.0.1:4200`.
@@ -60,42 +60,25 @@ Startup source package proof:
./mvnw -pl hertzbeat-startup -am -DskipTests package
```
Next.js topology, entity detail, shell, session, and shared UI changes:
Topology, entity, observability, shell, session, and shared UI changes:
```shell
cd web-next
npm exec -- vitest run app/topology/page.test.tsx app/ui-lab/page.test.tsx packages/hertzbeat-ui/src/index.test.tsx packages/hertzbeat-ui/src/topology-g6.test.tsx packages/hertzbeat-ui/src/topology-companion.interaction.test.tsx packages/hertzbeat-ui/src/topology-metric-table.interaction.test.tsx components/pages/entity-detail-surface.test.tsx components/shell/app-frame.chrome.test.tsx components/shell/auth-recovery.chrome.test.ts lib/app-frame-state.test.ts lib/entity-contract.test.ts lib/entity-detail/view-model.test.ts lib/hertzbeat-2-gap-audit.test.ts lib/topology-surface/controller.test.ts lib/topology-surface/query-state.test.ts lib/topology-surface/view-model.test.ts --config vitest.config.ts --pool=forks --maxWorkers=1 --minWorkers=1 --testTimeout=120000 --hookTimeout=120000
cd web-app
corepack pnpm@10.9.0 test -- \
src/features/entity src/features/topology src/features/instrumentation \
src/features/explore
```
Focused frontend lint for touched alpha files:
Complete frontend release gate:
```shell
cd web-next
ESLINT_USE_FLAT_CONFIG=false npm exec -- eslint app components lib packages/hertzbeat-ui/src scripts/topology-g6-browser-smoke.spec.ts test --ext .ts,.tsx
cd web-app
corepack pnpm@10.9.0 verify
```
## Optional Local Smoke
The topology G6 browser smoke is intentionally opt-in. It skips unless the
route and credentials are supplied by the developer:
```shell
cd web-next
TOPOLOGY_G6_BROWSER_USERNAME=admin \
TOPOLOGY_G6_BROWSER_PASSWORD=hertzbeat \
TOPOLOGY_G6_BROWSER_ROUTE='/topology?environment=prod&timeRange=last-1h&viewMode=service-call&sourceKind=otlp-trace-call&depth=2&groupBy=source-kind' \
npm exec -- playwright test scripts/topology-g6-browser-smoke.spec.ts
```
Optional strict assertions can be added with:
- `TOPOLOGY_G6_BROWSER_EXPECTED_NODES`
- `TOPOLOGY_G6_BROWSER_EXPECTED_EDGES`
- `TOPOLOGY_G6_BROWSER_FOCUS_NODE_ID`
- `TOPOLOGY_G6_BROWSER_EXPECTED_RUNTIME_VERSION`
- `TOPOLOGY_G6_BROWSER_EXPECTED_INITIAL_FIT_STRATEGY`
- `TOPOLOGY_G6_BROWSER_EXPECTED_WIDE_ZOOM`
- `TOPOLOGY_G6_BROWSER_EXPECTED_OPERATOR_BOUNDS`
Visible changes also require a production build, a real backend, and a Browser
check of the affected workflow. Do not use mocked topology or signal data as
release evidence.
## Three-Signal SigNoz-Alignment Alpha Cutoff
@@ -144,9 +127,9 @@ TRACE_ID=6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b bash script/dev/run-three-signal-live-
```
That proof starts a non-persistent H2 backend, seeds OTLP metrics/logs/traces,
verifies entity binding and signal query breakouts, starts `web-next`, and runs
live browser checks for saved-view dashboard replay, service overview, and
operation drilldown.
verifies entity binding and signal query breakouts, starts `web-app`, and checks
that the active React routes are served. Product-level browser acceptance remains
a separate real-backend validation step.
## Local Scale Proof Data
@@ -166,8 +149,8 @@ required alpha setup.
## Known Alpha Limitations
- The Next.js frontend is still an alpha preview and may not yet match every
legacy Angular workflow.
- The Vite React frontend is still an alpha preview. Parity claims require
route, action, API read/write, refresh, context-handoff, and Browser evidence.
- Three-signal work is scoped to the alpha cutoff above. Do not describe it as
full SigNoz parity unless a later release adds and proves the omitted product
capabilities.
+5 -4
View File
@@ -14,10 +14,11 @@ Start every Product Design workflow from saved context:
- Local screenshot/reference assets:
`$CODEX_HOME/state/plugins/product-design/assets/`
- Repo guidance: `AGENTS.md` and the latest active slice in `progress.md`
- Frontend implementation: `web-next/app`, `web-next/components`,
`web-next/lib`, and `web-next/packages/hertzbeat-ui`
- Theme and UI constraints: `web-next/app/globals.css`, shared
`@hertzbeat/ui` primitives, `lucide-react` icons, and runtime i18n catalogs
- Frontend implementation: `web-app/src/app`, `web-app/src/layout`,
`web-app/src/features`, and `web-app/src/shared`
- Theme and UI constraints: `web-app/src/app/theme`, feature CSS modules,
shared Ant Design primitives, source-backed icon packages, and runtime i18n
catalogs
Saved context should include the HertzBeat product position, operator audience,
competitive references, design preferences, code paths, screenshots, design
+10 -9
View File
@@ -19,9 +19,8 @@
## Status And Reference Baselines
This document is the implementation contract for replacing `web-next` with a
maintainable React single-page application. It deliberately does not treat the
current Next.js directory as the target architecture.
This document is the implementation contract for the maintainable React
single-page application that replaces the deprecated Next.js frontend.
- Implementation baseline: `2.0.0` at `2de48d2caa43fa58fd93e71b0e22e7d4f431c9d5`.
- Angular behavior and release reference: `apache/master` at
@@ -44,9 +43,9 @@ Use the following precedence for implementation decisions:
GreptimeDB integration, and the current HttpOnly UI session boundary.
3. The Angular three-signal transition defines the simple onboarding and
query workflow that does not require a user to understand storage internals.
4. `web-next` may supply proven DTOs and pure algorithms. Its page structure,
private UI framework, BFF, compatibility scaffolding, and implementation-
detail tests are not migration sources.
4. The removed Next.js implementation supplied only proven DTOs and pure
algorithms. Its page structure, private UI framework, BFF, compatibility
scaffolding, and implementation-detail tests were not migration sources.
## Scope Allowlist
@@ -96,7 +95,9 @@ redirects in the route registry and never duplicate a page implementation.
- ECharts, G6, CodeMirror, and the log virtualizer load only in their owning
features.
- Vitest, React Testing Library, MSW, and Playwright for behavior-level tests.
- Node 22 and pnpm 10 for development and CI. Production runs only the JVM.
- Node 22 and pnpm 10 for development and CI. Release assemblies run only the
JVM; the optional standalone web image serves static assets with Nginx and
never ships a Node runtime.
Vite emits `web-app/dist`. Release assemblies copy that directory to the
external distribution `dist/`, matching `apache/master`. Spring serves the SPA
@@ -162,8 +163,8 @@ must retain their own non-HTML errors.
- No tests that read production source and assert source strings.
- Knip and an explicit dependency-boundary check run in CI.
- Production frontend target: no more than 80,000 lines; hard limit 100,000.
- The final migration must delete at least 40 percent of the current production
frontend source and must not retain `web-next`.
- The final migration must delete at least 40 percent of the previous
production frontend source and must not retain the deprecated Next.js tree.
- Initial shell JavaScript: at most 450 KiB gzip. ECharts, G6, and CodeMirror
are forbidden from the shell chunk.
@@ -21,11 +21,11 @@ description: Install host system dependencies (with mvnd)
runs:
using: composite
steps:
- name: Set up JDK 21
- name: Set up JDK 25
uses: actions/setup-java@v4
with:
distribution: "zulu"
java-version: 21
java-version: 25
- name: Install mvnd
shell: bash
@@ -40,4 +40,4 @@ runs:
- name: Verify mvnd installation
shell: bash
run: mvnd --version
run: mvnd --version
+18 -26
View File
@@ -3,19 +3,15 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
WEB_NEXT_DIR="${ROOT_DIR}/web-next"
HERTZBEAT_BASE="${HERTZBEAT_BASE:-http://127.0.0.1:1157}"
FRONTEND_BASE="${FRONTEND_BASE:-http://127.0.0.1:4200}"
BACKEND_ORIGIN="${BACKEND_ORIGIN:-${HERTZBEAT_BASE}}"
NEXT_PORT="${NEXT_PORT:-4200}"
FRONTEND_PORT="${FRONTEND_PORT:-4200}"
TRACE_ID="${TRACE_ID:-6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b}"
HERTZBEAT_USER="${HERTZBEAT_USER:-admin}"
HERTZBEAT_PASSWORD="${HERTZBEAT_PASSWORD:-hertzbeat}"
SPRING_DATASOURCE_URL="${SPRING_DATASOURCE_URL:-jdbc:h2:mem:hb_live_smoke;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE}"
BACKEND_LOG="${BACKEND_LOG:-/tmp/hb-three-signal-live-backend.log}"
FRONTEND_LOG="${FRONTEND_LOG:-/tmp/hb-three-signal-live-frontend.log}"
PLAYWRIGHT_GREP="${PLAYWRIGHT_GREP:-promotes logs, traces, and metrics saved views into a persisted replay dashboard|saves a service overview dashboard from URL service and entity context|saves an operation drilldown dashboard from URL operation context}"
BACKEND_READY_PATH="${BACKEND_READY_PATH:-/actuator/health}"
READY_ATTEMPTS="${READY_ATTEMPTS:-300}"
READY_SLEEP_SECONDS="${READY_SLEEP_SECONDS:-2}"
@@ -49,7 +45,7 @@ wait_for_http() {
local attempt
for attempt in $(seq 1 "${READY_ATTEMPTS}"); do
local status
status="$(curl -sS -o /tmp/hb-three-signal-live-proof-probe.out -w '%{http_code}' "${url}" 2>/dev/null || true)"
status="$(curl -sS -o /dev/null -w '%{http_code}' "${url}" 2>/dev/null || true)"
if [[ "${status}" == 2* || "${status}" == 3* || "${status}" == "401" ]]; then
printf '[three-signal-live] %s ready: %s\n' "${label}" "${url}"
return 0
@@ -62,14 +58,14 @@ wait_for_http() {
cleanup() {
set +e
if [[ -f /tmp/hb-next-dev.pid ]]; then
local next_pid
next_pid="$(cat /tmp/hb-next-dev.pid 2>/dev/null || true)"
if [[ -n "${next_pid}" ]] && kill -0 "${next_pid}" 2>/dev/null; then
kill "${next_pid}" 2>/dev/null || true
wait "${next_pid}" 2>/dev/null || true
if [[ -f /tmp/hb-web-app-dev.pid ]]; then
local frontend_pid
frontend_pid="$(cat /tmp/hb-web-app-dev.pid 2>/dev/null || true)"
if [[ -n "${frontend_pid}" ]] && kill -0 "${frontend_pid}" 2>/dev/null; then
kill "${frontend_pid}" 2>/dev/null || true
wait "${frontend_pid}" 2>/dev/null || true
fi
rm -f /tmp/hb-next-dev.pid
rm -f /tmp/hb-web-app-dev.pid
fi
if [[ -n "${FRONTEND_WRAPPER_PID}" ]] && kill -0 "${FRONTEND_WRAPPER_PID}" 2>/dev/null; then
kill "${FRONTEND_WRAPPER_PID}" 2>/dev/null || true
@@ -92,22 +88,22 @@ run_dry_plan() {
"persistentH2": false
},
"frontend": {
"command": "BACKEND_ORIGIN='${BACKEND_ORIGIN}' NEXT_PORT='${NEXT_PORT}' script/dev/start-mixed-frontend.sh",
"command": "BACKEND_ORIGIN='${BACKEND_ORIGIN}' FRONTEND_PORT='${FRONTEND_PORT}' script/dev/start-web-app.sh",
"baseUrl": "${FRONTEND_BASE}",
"log": "${FRONTEND_LOG}"
},
"seedAndVerify": {
"command": "TRACE_ID='${TRACE_ID}' HERTZBEAT_BASE='${HERTZBEAT_BASE}' bash script/dev/verify-otlp-three-signal-demo.sh"
},
"playwright": {
"command": "DASHBOARD_SOURCE_EDIT_LIVE_BROWSER_BASE_URL='${FRONTEND_BASE}' DASHBOARD_SOURCE_EDIT_LIVE_IDENTIFIER='${HERTZBEAT_USER}' DASHBOARD_SOURCE_EDIT_LIVE_CREDENTIAL='***' npm exec -- playwright test scripts/dashboard-source-edit-live-browser-smoke.spec.ts -g '${PLAYWRIGHT_GREP}'"
"routeSmoke": {
"routes": ["/dashboard", "/entities", "/topology", "/explore?signal=metrics"]
}
}
EOF
}
require_command curl
require_command npm
require_command corepack
if [[ "${DRY_RUN}" == true ]]; then
run_dry_plan
@@ -134,19 +130,15 @@ printf '[three-signal-live] seeding and verifying three-signal demo data\n'
printf '[three-signal-live] starting frontend on %s\n' "${FRONTEND_BASE}"
(
cd "${ROOT_DIR}"
BACKEND_ORIGIN="${BACKEND_ORIGIN}" NEXT_PORT="${NEXT_PORT}" script/dev/start-mixed-frontend.sh
BACKEND_ORIGIN="${BACKEND_ORIGIN}" FRONTEND_PORT="${FRONTEND_PORT}" script/dev/start-web-app.sh
) > "${FRONTEND_LOG}" 2>&1 &
FRONTEND_WRAPPER_PID=$!
printf '[three-signal-live] frontend wrapper log: %s\n' "${FRONTEND_LOG}"
wait_for_http "${FRONTEND_BASE}/dashboard" 'frontend'
printf '[three-signal-live] running live Playwright proof: %s\n' "${PLAYWRIGHT_GREP}"
(
cd "${WEB_NEXT_DIR}"
DASHBOARD_SOURCE_EDIT_LIVE_BROWSER_BASE_URL="${FRONTEND_BASE}" \
DASHBOARD_SOURCE_EDIT_LIVE_IDENTIFIER="${HERTZBEAT_USER}" \
DASHBOARD_SOURCE_EDIT_LIVE_CREDENTIAL="${HERTZBEAT_PASSWORD}" \
npm exec -- playwright test scripts/dashboard-source-edit-live-browser-smoke.spec.ts -g "${PLAYWRIGHT_GREP}"
)
printf '[three-signal-live] checking active React routes\n'
for route in /dashboard /entities /topology '/explore?signal=metrics'; do
curl --fail --silent --show-error "${FRONTEND_BASE}${route}" > /dev/null
done
printf '[three-signal-live] proof completed successfully\n'
-35
View File
@@ -1,35 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
WEB_NEXT_DIR="$ROOT_DIR/web-next"
BACKEND_ORIGIN="${BACKEND_ORIGIN:-http://127.0.0.1:1157}"
NEXT_PORT="${NEXT_PORT:-4200}"
NEXT_DIST_DIR="${NEXT_DIST_DIR:-.next}"
cleanup_pid() {
local pid_file="$1"
if [[ -f "$pid_file" ]]; then
local pid
pid="$(cat "$pid_file")"
if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
kill "$pid" 2>/dev/null || true
wait "$pid" 2>/dev/null || true
fi
rm -f "$pid_file"
fi
}
cleanup_pid /tmp/hb-next-dev.pid
cd "$WEB_NEXT_DIR"
rm -rf "$NEXT_DIST_DIR"
echo "[web-next] starting Next.js on :$NEXT_PORT (BACKEND_ORIGIN=$BACKEND_ORIGIN, NEXT_DIST_DIR=$NEXT_DIST_DIR)"
BACKEND_ORIGIN="$BACKEND_ORIGIN" NEXT_DIST_DIR="$NEXT_DIST_DIR" ./node_modules/.bin/next dev -p "$NEXT_PORT" > /tmp/hb-next-dev.log 2>&1 &
NEXT_PID=$!
echo "$NEXT_PID" > /tmp/hb-next-dev.pid
echo "[web-next] Next.js: http://127.0.0.1:$NEXT_PORT"
echo "[web-next] logs: /tmp/hb-next-dev.log"
wait
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
WEB_APP_DIR="$ROOT_DIR/web-app"
BACKEND_ORIGIN="${BACKEND_ORIGIN:-http://127.0.0.1:1157}"
FRONTEND_PORT="${FRONTEND_PORT:-4200}"
FRONTEND_PID_FILE="${FRONTEND_PID_FILE:-/tmp/hb-web-app-dev.pid}"
FRONTEND_LOG="${FRONTEND_LOG:-/tmp/hb-web-app-dev.log}"
cleanup_pid() {
local pid_file="$1"
if [[ -f "$pid_file" ]]; then
local pid
pid="$(cat "$pid_file")"
if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
kill "$pid" 2>/dev/null || true
wait "$pid" 2>/dev/null || true
fi
rm -f "$pid_file"
fi
}
cleanup_pid "$FRONTEND_PID_FILE"
trap 'cleanup_pid "$FRONTEND_PID_FILE"' EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
cd "$WEB_APP_DIR"
echo "[web-app] starting Vite on :$FRONTEND_PORT (BACKEND_ORIGIN=$BACKEND_ORIGIN)"
BACKEND_ORIGIN="$BACKEND_ORIGIN" \
corepack pnpm@10.9.0 exec vite --host 0.0.0.0 --port "$FRONTEND_PORT" \
> "$FRONTEND_LOG" 2>&1 &
FRONTEND_PID=$!
echo "$FRONTEND_PID" > "$FRONTEND_PID_FILE"
echo "[web-app] URL: http://127.0.0.1:$FRONTEND_PORT"
echo "[web-app] logs: $FRONTEND_LOG"
wait "$FRONTEND_PID"
@@ -1,58 +0,0 @@
server {
listen 80;
server_name _;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
location ^~ /_next/ {
proxy_pass http://web-next:4200;
}
location ^~ /overview {
proxy_pass http://web-next:4200;
}
location ^~ /entities {
proxy_pass http://web-next:4200;
}
location ^~ /trace/ {
proxy_pass http://web-next:4200;
}
location ^~ /log/ {
proxy_pass http://web-next:4200;
}
location ^~ /monitors {
proxy_pass http://web-next:4200;
}
location ^~ /alert {
proxy_pass http://web-next:4200;
}
location ^~ /topology {
proxy_pass http://web-next:4200;
}
location ^~ /setting {
proxy_pass http://web-next:4200;
}
location ^~ /ingestion/otlp {
proxy_pass http://web-next:4200;
}
location ^~ /api/ {
proxy_pass http://hertzbeat:1157;
}
location / {
proxy_pass http://hertzbeat:1157;
}
}
@@ -87,23 +87,19 @@ services:
networks:
- hertzbeat
web-next:
image: "${HERTZBEAT_WEB_NEXT_IMAGE:-apache/hertzbeat-web-next}:${HERTZBEAT_RELEASE_VERSION:-1.8.0}"
web-app:
image: "${HERTZBEAT_WEB_APP_IMAGE:-apache/hertzbeat-web-app}:${HERTZBEAT_RELEASE_VERSION:-1.8.0}"
build:
context: ../../..
dockerfile: web-next/Dockerfile
dockerfile: web-app/Dockerfile
args:
HERTZBEAT_RELEASE_VERSION: ${HERTZBEAT_RELEASE_VERSION:-1.8.0}
container_name: compose-hertzbeat-web-next
hostname: web-next
container_name: compose-hertzbeat-web-app
hostname: web-app
restart: always
depends_on:
hertzbeat:
condition: service_started
environment:
BACKEND_ORIGIN: http://hertzbeat:1157
NEXT_PUBLIC_LOGIN_PATH: /passport/login
TZ: Asia/Shanghai
networks:
- hertzbeat
@@ -115,7 +111,7 @@ services:
depends_on:
hertzbeat:
condition: service_started
web-next:
web-app:
condition: service_started
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
@@ -0,0 +1,32 @@
server {
listen 80;
server_name _;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
location ^~ /api/ {
proxy_pass http://hertzbeat:1157;
proxy_buffering off;
proxy_read_timeout 3600s;
}
location ^~ /actuator/ {
proxy_pass http://hertzbeat:1157;
}
location ^~ /swagger-ui/ {
proxy_pass http://hertzbeat:1157;
}
location ^~ /v3/api-docs {
proxy_pass http://hertzbeat:1157;
}
location / {
proxy_pass http://web-app:4200;
}
}
+4 -4
View File
@@ -33,10 +33,10 @@ New-Item -ItemType Directory -Path $distPath -Force
Push-Location -Path $projectPath
Write-Host "Installing dependencies and building web-next..."
Push-Location -Path "web-next"
npm ci
npm run build
Write-Host "Installing dependencies and building web-app..."
Push-Location -Path "web-app"
corepack pnpm@10.9.0 install --frozen-lockfile
corepack pnpm@10.9.0 build
Pop-Location
Write-Host "Building project with Maven..."
+38
View File
@@ -0,0 +1,38 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
FROM node:22-alpine@sha256:16e22a550f3863206a3f701448c45f7912c6896a62de43add43bb9c86130c3e2 AS builder
WORKDIR /app
RUN corepack enable && corepack prepare pnpm@10.9.0 --activate
COPY web-app/package.json web-app/pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY web-app ./
RUN pnpm build
FROM nginx:1.27-alpine@sha256:65645c7bb6a0661892a8b03b89d0743208a18dd2f3f17a54ef4b76fb8e2f2a10
ARG HERTZBEAT_RELEASE_VERSION=dev
LABEL org.opencontainers.image.title="Apache HertzBeat Web App"
LABEL org.opencontainers.image.version="${HERTZBEAT_RELEASE_VERSION}"
COPY web-app/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 4200
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD wget -q -O - "http://127.0.0.1:4200/dashboard" > /dev/null || exit 1
CMD ["nginx", "-g", "daemon off;"]
+24
View File
@@ -0,0 +1,24 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
**
!web-app/
!web-app/**
web-app/node_modules/
web-app/dist/
web-app/.tmp/
web-app/coverage/
web-app/playwright-report/
web-app/test-results/
+31
View File
@@ -0,0 +1,31 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
server {
listen 4200;
server_name _;
root /usr/share/nginx/html;
index index.html;
location /assets/ {
try_files $uri =404;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location / {
try_files $uri $uri/ /index.html;
}
}