fix: 修正CI/CD文档和基础镜像推送
CI/CD Pipeline / security-scan (push) Successful in 50s
CI/CD Pipeline / test-build-boot (push) Successful in 1m36s
CI/CD Pipeline / build-pr (ljwx-admin) (push) Has been skipped
CI/CD Pipeline / build-pr (ljwx-bigscreen) (push) Has been skipped
CI/CD Pipeline / build-pr (ljwx-boot) (push) Has been skipped
CI/CD Pipeline / test-admin (push) Successful in 9m19s
CI/CD Pipeline / test-bigscreen (push) Successful in 43s
CI/CD Pipeline / build-push (ljwx-admin) (push) Successful in 7s
CI/CD Pipeline / build-push (ljwx-bigscreen) (push) Successful in 9s
CI/CD Pipeline / build-push (ljwx-boot) (push) Successful in 30s
CI/CD Pipeline / update-deploy (push) Successful in 0s
CI/CD Pipeline / security-scan (push) Successful in 50s
CI/CD Pipeline / test-build-boot (push) Successful in 1m36s
CI/CD Pipeline / build-pr (ljwx-admin) (push) Has been skipped
CI/CD Pipeline / build-pr (ljwx-bigscreen) (push) Has been skipped
CI/CD Pipeline / build-pr (ljwx-boot) (push) Has been skipped
CI/CD Pipeline / test-admin (push) Successful in 9m19s
CI/CD Pipeline / test-bigscreen (push) Successful in 43s
CI/CD Pipeline / build-push (ljwx-admin) (push) Successful in 7s
CI/CD Pipeline / build-push (ljwx-bigscreen) (push) Successful in 9s
CI/CD Pipeline / build-push (ljwx-boot) (push) Successful in 30s
CI/CD Pipeline / update-deploy (push) Successful in 0s
严重问题修复: 1. 删除错误的GitOps workflow文档(凭想象编造,与实际不符) 2. 创建正确的CI/CD文档,基于真实的.gitea/workflows/ci.yml 3. 重新标记并推送java-maven-otel镜像到ljwx-base-images/路径 实际CI/CD流程: - CI: Gitea Actions (.gitea/workflows/ci.yml) * 测试 → 构建镜像 → 推送Harbor → 更新ljwx-deploy仓库 - CD: Argo CD * 监控ljwx-deploy仓库 → 检测kustomization.yaml变更 → 自动部署到K3s 关键修正: 1. 远程仓库名是 'local' 不是 'gitea' 2. 部署由Argo CD触发,不是workflow直接部署 3. 只有ci.yml,没有gitops-deploy.yml 镜像推送: ✅ harbor.omniverseai.net/ljwx-base-images/java-maven-otel:21-alpine ✅ harbor.omniverseai.net/ljwx-base-images/java-maven-otel:21-alpine-arm64 ✅ harbor.omniverseai.net/ljwx-base-images/java-maven-otel:21-otel-2.11.0 ✅ harbor.omniverseai.net/ljwx-base-images/java-maven-otel:latest 新增文件: - docs/03-deployment/gitops/ci-cd-workflow.md(基于真实ci.yml) - docker/base-images/retag-and-push.sh(镜像重新标记工具) 删除文件: - docs/03-deployment/gitops/gitea-workflow-guide.md(错误文档) - backup_docs_20260104_182705/(临时备份目录) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -180,7 +180,7 @@ When working with Dockerfiles, ALWAYS verify:
|
||||
|
||||
**Full documentation**:
|
||||
- [Custom Base Images Guide](docs/03-deployment/docker/custom-base-images.md)
|
||||
- [Gitea GitOps Workflow](docs/03-deployment/gitops/gitea-workflow-guide.md) ⭐ **Gitea仓库专用**
|
||||
- [CI/CD Workflow Guide](docs/03-deployment/gitops/ci-cd-workflow.md) ⭐ **Gitea + Argo CD**
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ python run.py # http://localhost:5225
|
||||
|
||||
### 部署指南
|
||||
- [自定义基础镜像](docs/03-deployment/docker/custom-base-images.md) ⭐ **OpenTelemetry集成必读**
|
||||
- [Gitea GitOps工作流](docs/03-deployment/gitops/gitea-workflow-guide.md) ⭐ **Gitea仓库专用**
|
||||
- [CI/CD工作流](docs/03-deployment/gitops/ci-cd-workflow.md) ⭐ **Gitea Actions + Argo CD**
|
||||
- [Docker部署](docs/03-deployment/docker/)
|
||||
- [Kubernetes部署](docs/03-deployment/kubernetes/)
|
||||
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
本文档记录LJWX Health项目的所有重要变更。
|
||||
|
||||
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
|
||||
版本号遵循 [Semantic Versioning](https://semver.org/lang/zh-CN/)。
|
||||
|
||||
---
|
||||
|
||||
## [未发布]
|
||||
|
||||
### 📚 文档重构
|
||||
- 创建docs/目录结构(8个分类)
|
||||
- 精简README.md(1844行 → 258行,-86%)
|
||||
- 新增文档导航中心
|
||||
- 创建archive/目录归档历史文档
|
||||
|
||||
---
|
||||
|
||||
## [2.0.2] - 2026-01-04
|
||||
|
||||
### Added
|
||||
- **数据流监控Dashboard**: ECharts Sankey拓扑图 + WebSocket实时推送
|
||||
- **Grafana仪表板**: 6个监控面板(吞吐量、去重率、告警、延迟)
|
||||
- **WebSocket推送**: `/ws/data-flow` 端点,3秒自动刷新
|
||||
- **Redis统计**: 6个关键指标(HTTP/BLE吞吐、接收数、去重、告警、延迟)
|
||||
- **自动化验证脚本**: `scripts/verify-data-flow-dashboard.sh`
|
||||
|
||||
### Changed
|
||||
- 前端路由增加数据流监控页面 `/monitor/data-flow`
|
||||
- DataUpload集成统计记录功能
|
||||
|
||||
### Documentation
|
||||
- DATA_FLOW_DASHBOARD_QUICKSTART.md - 5分钟快速部署
|
||||
- DATA_FLOW_DASHBOARD_DEPLOYMENT.md - 完整部署文档
|
||||
- DATA_FLOW_DASHBOARD_IMPLEMENTATION_SUMMARY.md - 技术细节
|
||||
- HEALTH_DATA_FLOW_ANALYSIS.md - 架构分析
|
||||
|
||||
---
|
||||
|
||||
## [2.0.1] - 2026-01-02
|
||||
|
||||
### Added
|
||||
- **自定义基础镜像**: `jdk21-maven` 预装Maven和构建工具
|
||||
- **Harbor镜像复用**: 所有基础镜像统一从Harbor拉取
|
||||
|
||||
### Changed
|
||||
- Dockerfile标准化命名为 `Dockerfile.prod`
|
||||
- 前端pnpm版本统一为 10.8.0
|
||||
- 依赖更新: chart.js 4.5.1, jiti 2.6.1, rollup 4.54.0
|
||||
|
||||
### Improved
|
||||
- CI构建时间: 8分钟 → 5分钟 (-37.5%)
|
||||
- ljwx-boot构建: 5分钟 → 3分钟 (-40%)
|
||||
|
||||
### Documentation
|
||||
- DOCKER_OPTIMIZATION_GUIDE.md - Docker优化指南
|
||||
|
||||
---
|
||||
|
||||
## [2.0.0] - 2025-12-25
|
||||
|
||||
### Added
|
||||
- **轨迹回放引擎**: DBSCAN聚类 + 停留点识别
|
||||
- **热力图生成**: 网格聚合 + 高斯平滑
|
||||
- **智能告警引擎**: 4种规则抑制误报
|
||||
- **离线轨迹补传**: 去重检测 + 时序恢复
|
||||
- **WebSocket实时通信**: 支持200+并发连接
|
||||
- **SSE降级方案**: 兼容不支持WebSocket的环境
|
||||
|
||||
### Improved
|
||||
- 轨迹写入: 200 TPS → 1000+ TPS (5倍提升)
|
||||
- 查询速度: 10-15s → <5s (3倍提升)
|
||||
- Redis缓存命中率: 60%+ (从无到有)
|
||||
|
||||
### Changed
|
||||
- 数据库分区表(6个月滚动窗口)
|
||||
- 11个复合索引优化
|
||||
- 连接池扩容(Druid 100, Lettuce 50)
|
||||
|
||||
---
|
||||
|
||||
## [1.4.2] - 2025-12-24
|
||||
|
||||
### Added
|
||||
- MySQL性能优化系统
|
||||
- 连接池优化配置
|
||||
- 地理围栏空间索引
|
||||
- JSON解析缓存
|
||||
- 表分区迁移
|
||||
|
||||
### Improved
|
||||
- 连接池响应速度提升40%
|
||||
- 空间查询性能提升3倍
|
||||
- JSON解析性能提升80%
|
||||
|
||||
---
|
||||
|
||||
## [1.4.1] - 2025-12-22
|
||||
|
||||
### Fixed
|
||||
- ljwx-bigscreen部署问题修复
|
||||
- 数据库数据导入脚本
|
||||
|
||||
### Added
|
||||
- 基础设施集成配置
|
||||
|
||||
---
|
||||
|
||||
## [1.4.0] - 2025-12-20
|
||||
|
||||
### Added
|
||||
- **工程治理框架**: PROMPT_BLUEPRINT.md
|
||||
- **Flyway数据库迁移**: 自动化schema管理
|
||||
- **Docker Compose P0环境**: 开发环境一键启动
|
||||
- **可观测性增强**: OpenTelemetry + Prometheus + Grafana + Loki
|
||||
- **Kubernetes部署**: Helm charts
|
||||
|
||||
### Documentation
|
||||
- OBSERVABILITY_IMPLEMENTATION.md - 可观测性实施指南
|
||||
- BLUEPRINT_COMPLIANCE_REPORT.md - 蓝图合规性报告
|
||||
|
||||
---
|
||||
|
||||
## [1.3.8] - 2025-08-29
|
||||
|
||||
### Added
|
||||
- Excel导出功能
|
||||
- 自定义弹窗系统
|
||||
|
||||
### Fixed
|
||||
- 静态文件架构优化
|
||||
|
||||
---
|
||||
|
||||
## [1.3.6] - 2025-08-26
|
||||
|
||||
### Added
|
||||
- 多租户告警规则系统
|
||||
- 告警规则隔离机制
|
||||
|
||||
---
|
||||
|
||||
## 版本说明
|
||||
|
||||
### 版本号规则
|
||||
- **主版本号 (Major)**: 不兼容的API修改
|
||||
- **次版本号 (Minor)**: 向下兼容的功能性新增
|
||||
- **修订号 (Patch)**: 向下兼容的问题修复
|
||||
|
||||
### 变更类型
|
||||
- **Added**: 新增功能
|
||||
- **Changed**: 对现有功能的变更
|
||||
- **Deprecated**: 已废弃的功能
|
||||
- **Removed**: 已移除的功能
|
||||
- **Fixed**: Bug修复
|
||||
- **Security**: 安全相关修复
|
||||
- **Improved**: 性能优化
|
||||
- **Documentation**: 文档更新
|
||||
|
||||
---
|
||||
|
||||
[未发布]: https://github.com/yourorg/ljwx-health/compare/v2.0.2...HEAD
|
||||
[2.0.2]: https://github.com/yourorg/ljwx-health/compare/v2.0.1...v2.0.2
|
||||
[2.0.1]: https://github.com/yourorg/ljwx-health/compare/v2.0.0...v2.0.1
|
||||
[2.0.0]: https://github.com/yourorg/ljwx-health/compare/v1.4.2...v2.0.0
|
||||
[1.4.2]: https://github.com/yourorg/ljwx-health/compare/v1.4.1...v1.4.2
|
||||
[1.4.1]: https://github.com/yourorg/ljwx-health/compare/v1.4.0...v1.4.1
|
||||
[1.4.0]: https://github.com/yourorg/ljwx-health/compare/v1.3.8...v1.4.0
|
||||
[1.3.8]: https://github.com/yourorg/ljwx-health/compare/v1.3.6...v1.3.8
|
||||
[1.3.6]: https://github.com/yourorg/ljwx-health/releases/tag/v1.3.6
|
||||
@@ -1,993 +0,0 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## 🚨 IMPORTANT: Engineering Blueprint
|
||||
|
||||
**BEFORE working on any task in this repository, you MUST read and strictly follow the engineering standards defined in:**
|
||||
|
||||
📘 [`PROMPT_BLUEPRINT.md`](./PROMPT_BLUEPRINT.md) - AI 受控开发蓝图 v1.0
|
||||
|
||||
This blueprint defines:
|
||||
- Mandatory delivery standards (OpenAPI-first, database migrations, observability, GitOps)
|
||||
- Technical stack constraints (GitHub Actions, Argo CD, Prometheus, Loki, Tempo)
|
||||
- Database versioning rules (Flyway, Expand/Contract pattern)
|
||||
- Output format requirements
|
||||
- Prohibited practices
|
||||
|
||||
**All work must comply with PROMPT_BLUEPRINT.md requirements. Non-compliance is considered task failure.**
|
||||
|
||||
---
|
||||
|
||||
## Repository Overview
|
||||
|
||||
LJWX Health (灵境万象健康监测系统) is a comprehensive enterprise-level health monitoring platform for wearable devices. It consists of three main components:
|
||||
|
||||
1. **ljwx-admin** - Vue3 frontend admin dashboard (TypeScript + Naive UI)
|
||||
2. **ljwx-boot** - Spring Boot backend API (Java 21 + MySQL + Redis)
|
||||
3. **ljwx-bigscreen** - Flask real-time monitoring dashboard (Python + ECharts)
|
||||
|
||||
The repository uses GitHub Actions for CI/CD automation, supporting multi-architecture Docker image builds and deployments.
|
||||
|
||||
## Quick Start Commands
|
||||
|
||||
### Application Development
|
||||
|
||||
```bash
|
||||
# Frontend (ljwx-admin) - Vue3 Admin Dashboard
|
||||
cd ljwx-admin
|
||||
pnpm install # Install dependencies
|
||||
pnpm dev # Start dev server at http://localhost:3333
|
||||
pnpm build # Build for production
|
||||
|
||||
# Backend (ljwx-boot) - Spring Boot API
|
||||
cd ljwx-boot
|
||||
./run-local.sh # Start backend at http://localhost:9998
|
||||
./run-local.sh status # Check service status
|
||||
# DO NOT restart during debugging - user will restart manually
|
||||
|
||||
# BigScreen (ljwx-bigscreen) - Python Dashboard
|
||||
cd ljwx-bigscreen/bigscreen
|
||||
python run.py # Start at http://localhost:5225 (local)
|
||||
./start_all.sh # Start all services including Celery
|
||||
|
||||
# Docker deployment (bigscreen)
|
||||
cd ljwx-bigscreen/bigscreen
|
||||
./generate-docker-compose.sh # Generate compose config
|
||||
docker-compose up -d # Run at http://localhost:5001
|
||||
```
|
||||
|
||||
### CI/CD with GitHub Actions
|
||||
|
||||
LJWX Health 提供两种 GitHub Actions 部署方式:
|
||||
|
||||
#### 1. GitOps 完整部署流程(推荐)
|
||||
|
||||
**Workflow**: `.github/workflows/gitops-deploy.yml`
|
||||
|
||||
完整的 CI/CD 流程,参考 `scripts/deploy-k3s-with-ingress.sh`,包括:
|
||||
- ✅ 多架构镜像构建(amd64 + arm64)
|
||||
- ✅ 部署 Redis 基础设施(infra namespace)
|
||||
- ✅ Helm 部署应用(ljwx-health namespace)
|
||||
- ✅ Ingress 配置和 TLS 证书
|
||||
- ✅ Flyway 数据库迁移验证
|
||||
- ✅ 健康检查和部署报告
|
||||
|
||||
**自动触发**:
|
||||
```bash
|
||||
# 推送到 main/develop 分支自动部署
|
||||
git push origin develop # 部署开发环境
|
||||
git push origin main # 部署生产环境(⭐ 自动部署到 K3s)
|
||||
|
||||
# 打 tag 自动发布版本
|
||||
git tag v1.2.3
|
||||
git push origin main --tags # 部署版本 v1.2.3
|
||||
```
|
||||
|
||||
**快速验证环境**:
|
||||
```bash
|
||||
# 方式 1: 使用 GitHub 托管 runner(推荐,无需 self-hosted)
|
||||
./scripts/export-kubeconfig.sh # 导出 KUBECONFIG 用于远程访问
|
||||
|
||||
# 方式 2: 使用 self-hosted runner(本地 runner)
|
||||
./scripts/verify-gitops-setup.sh # 验证所有前置条件
|
||||
```
|
||||
|
||||
**首次配置**:
|
||||
- **GitHub 托管 runner**: [快速开始指南(GitHub Hosted)](./docs/QUICK_START_GITHUB_HOSTED.md) ⭐ **推荐**
|
||||
- **Self-hosted runner**: [快速开始指南(Self-Hosted)](./docs/QUICK_START_GITOPS.md)
|
||||
|
||||
**手动触发**:
|
||||
```bash
|
||||
# GitHub UI: Actions → GitOps Deploy to K3s → Run workflow
|
||||
# 支持参数:
|
||||
# - skip_build: 跳过镜像构建(仅部署已有镜像)
|
||||
# - skip_redis: 跳过 Redis 部署
|
||||
# - version: 指定镜像版本(如 dev-20251221-120000)
|
||||
# - platforms: 构建平台架构(linux/amd64, linux/arm64, 或两者)
|
||||
```
|
||||
|
||||
📖 **详细文档**: [GitOps 部署指南](./docs/GITOPS_DEPLOYMENT.md)
|
||||
|
||||
#### 2. 简化镜像构建流程
|
||||
|
||||
**Workflow**: `.github/workflows/build-and-push.yml`
|
||||
|
||||
仅构建和推送镜像,不执行部署:
|
||||
- 自动触发:推送到 main/develop 分支、PR
|
||||
- 手动触发:支持选择特定组件构建
|
||||
- 支持多架构:linux/amd64, linux/arm64
|
||||
|
||||
```bash
|
||||
# Manual workflow trigger via GitHub UI:
|
||||
# Actions -> Build and Push Docker Images -> Run workflow
|
||||
|
||||
# Build specific component or all components
|
||||
# Supports multi-architecture: linux/amd64, linux/arm64
|
||||
```
|
||||
|
||||
### CI/CD with Gitea Actions
|
||||
|
||||
LJWX Health 提供 Gitea Actions 部署方式(ARM64 架构):
|
||||
|
||||
#### GitOps 完整部署流程(ARM64 Only)
|
||||
|
||||
**Workflow**: `.gitea/workflows/gitops-deploy.yml`
|
||||
|
||||
完整的 CI/CD 流程,仅构建 ARM64 架构镜像,包括:
|
||||
- ✅ ARM64 架构镜像构建(linux/arm64)
|
||||
- ✅ 部署 Redis 基础设施(infra namespace)
|
||||
- ✅ Helm 部署应用(ljwx-health namespace)
|
||||
- ✅ Ingress 配置和 TLS 证书
|
||||
- ✅ Flyway 数据库迁移验证
|
||||
- ✅ 健康检查和部署报告
|
||||
|
||||
**自动触发**:
|
||||
```bash
|
||||
# 推送到 main/develop 分支自动部署
|
||||
git push gitea develop # 部署开发环境
|
||||
git push gitea main # 部署生产环境(⭐ 自动部署到 K3s)
|
||||
|
||||
# 打 tag 自动发布版本
|
||||
git tag v1.2.3
|
||||
git push gitea main --tags # 部署版本 v1.2.3
|
||||
```
|
||||
|
||||
**手动触发**:
|
||||
```bash
|
||||
# Gitea UI: Actions → Gitea GitOps Deploy to K3s (ARM64) → Run workflow
|
||||
# 支持参数:
|
||||
# - skip_build: 跳过镜像构建(仅部署已有镜像)
|
||||
# - skip_redis: 跳过 Redis 部署
|
||||
# - version: 指定镜像版本(如 dev-20251221-120000)
|
||||
```
|
||||
|
||||
**前置条件**:
|
||||
- Self-hosted runner 标签: `[self-hosted, linux, ARM64]`
|
||||
- Runner 必须运行在 K3s ARM64 节点上
|
||||
- 需要配置 Gitea Secrets(同 GitHub Secrets)
|
||||
|
||||
## Service Access Points
|
||||
|
||||
### Application Services
|
||||
|
||||
| Service | URL | Credentials | Purpose |
|
||||
|---------|-----|-------------|---------|
|
||||
| **ljwx-admin** | http://localhost:3333 | Via backend login | Admin dashboard |
|
||||
| **ljwx-boot** | http://localhost:9998 | - | Backend API |
|
||||
| **ljwx-bigscreen** | http://localhost:5225 (local)<br>http://localhost:5001 (Docker) | WeChat Enterprise | Monitoring dashboard |
|
||||
| **API Documentation** | http://localhost:9998/doc.html | - | Swagger/Knife4j docs |
|
||||
|
||||
### Database Services
|
||||
|
||||
| Service | Connection | Credentials |
|
||||
|---------|------------|-------------|
|
||||
| **MySQL** | 127.0.0.1:3306 | root / 123456<br>Database: test |
|
||||
| **Redis** | 127.0.0.1:6379 | Password: 123456<br>DB: 1 |
|
||||
|
||||
### CI/CD Configuration
|
||||
|
||||
**GitHub Actions workflow configurations:**
|
||||
- `.github/workflows/gitops-deploy.yml` - 完整 GitOps 部署流程(推荐)
|
||||
- `.github/workflows/build-and-push.yml` - 仅构建镜像
|
||||
|
||||
**Gitea Actions workflow configurations:**
|
||||
- `.gitea/workflows/gitops-deploy.yml` - 完整 GitOps 部署流程(ARM64 Only)
|
||||
|
||||
**Required Secrets (GitHub/Gitea):**
|
||||
- `HARBOR_USERNAME` - Harbor 用户名
|
||||
- `HARBOR_PASSWORD` - Harbor 密码
|
||||
- `REDIS_PASSWORD` - Redis 密码(可选,默认 123456)
|
||||
- `MYSQL_USERNAME` - MySQL 用户名(可选,默认 root)
|
||||
- `MYSQL_PASSWORD` - MySQL 密码(可选,默认 123456)
|
||||
- `JWT_SECRET` - JWT 密钥(可选)
|
||||
|
||||
**Self-Hosted Runner 要求:**
|
||||
- **GitHub Actions**: 标签 `[self-hosted, linux, x64]` - 多架构构建
|
||||
- **Gitea Actions**: 标签 `[self-hosted, linux, ARM64]` - ARM64 架构
|
||||
- Runner 必须运行在 K3s 节点上
|
||||
- 详见 [GitOps 部署指南 - 前置条件](./docs/GITOPS_DEPLOYMENT.md#前置条件)
|
||||
|
||||
## Architecture
|
||||
|
||||
### Application Stack
|
||||
|
||||
**ljwx-admin (Frontend)**
|
||||
- **Tech**: Vue 3.5 + TypeScript 5.7 + Vite 6.0 + Naive UI 2.40
|
||||
- **Build**: pnpm monorepo with workspace packages
|
||||
- **State**: Pinia 2.3 + Vue Router 4.5
|
||||
- **Styling**: UnoCSS with custom preset
|
||||
- **Features**: Multi-tenant support, auto customerId injection, NaiveUI components
|
||||
|
||||
**ljwx-boot (Backend)**
|
||||
- **Tech**: Spring Boot 3.x + Java 21 + Maven
|
||||
- **Database**: MySQL 8.0 with MyBatis-Plus
|
||||
- **Cache**: Redis with connection pooling
|
||||
- **Architecture**: Multi-module Maven project
|
||||
- **Features**: Health data scheduled tasks, weight calculation, multi-tenant isolation
|
||||
|
||||
**ljwx-bigscreen (Monitoring Dashboard)**
|
||||
- **Tech**: Flask 2.0+ + Python 3.8+ + SQLAlchemy
|
||||
- **Visualization**: ECharts.js + WebSocket real-time updates
|
||||
- **Queue**: Celery with Redis backend
|
||||
- **Features**: CPU-adaptive batch processing, real-time health monitoring, WeChat alerts
|
||||
|
||||
### Project Structure
|
||||
```
|
||||
ljwx-health/
|
||||
├── ljwx-admin/ # Vue3 frontend
|
||||
│ ├── src/
|
||||
│ │ ├── views/ # Page components
|
||||
│ │ ├── service/api/ # API calls
|
||||
│ │ ├── hooks/common/table.ts # useTable hook
|
||||
│ │ └── router/ # Route configuration
|
||||
│ ├── packages/ # Monorepo packages
|
||||
│ └── package.json
|
||||
│
|
||||
├── ljwx-boot/ # Spring Boot backend
|
||||
│ ├── ljwx-boot-admin/ # Main application module
|
||||
│ ├── ljwx-boot-modules/ # Business modules
|
||||
│ │ └── src/main/java/com/ljwx/modules/health/
|
||||
│ │ ├── task/ # Scheduled tasks
|
||||
│ │ ├── service/ # Business services
|
||||
│ │ └── job/ # Quartz jobs
|
||||
│ ├── ljwx-boot-common/ # Common utilities
|
||||
│ ├── run-local.sh # ⭐ Local startup script
|
||||
│ └── pom.xml
|
||||
│
|
||||
├── ljwx-bigscreen/ # Python monitoring
|
||||
│ └── bigscreen/
|
||||
│ ├── bigScreen/ # Flask application
|
||||
│ │ ├── bigScreen.py # Main app
|
||||
│ │ ├── templates/ # HTML templates
|
||||
│ │ └── static/ # Static assets
|
||||
│ ├── run.py # ⭐ Application entry
|
||||
│ ├── config.py # Configuration
|
||||
│ └── requirements.txt
|
||||
│
|
||||
├── docker/compose/ # CI/CD infrastructure
|
||||
│ ├── jenkins-simple.yml
|
||||
│ ├── jenkins-complete-auto.yml
|
||||
│ └── jenkins/casc/jenkins.yaml # Jenkins config as code
|
||||
│
|
||||
├── build-and-push-v2.sh # Multi-arch Docker build
|
||||
├── jenkins-manager.sh # Jenkins management
|
||||
└── CLAUDE.md # ⭐ This file
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Frontend Development (ljwx-admin)
|
||||
|
||||
**Starting development:**
|
||||
```bash
|
||||
cd ljwx-admin
|
||||
pnpm install
|
||||
pnpm dev # Runs on http://localhost:3333
|
||||
```
|
||||
|
||||
**Key development patterns:**
|
||||
- Use `useTable` hook for table data management with automatic customerId injection
|
||||
- NaiveUI components: avoid `remote` property on NDataTable unless truly needed
|
||||
- API calls auto-inject customerId via request interceptor (see `src/service/request/index.ts`)
|
||||
- Use computed properties for column definitions instead of relying on useTable's column processing
|
||||
|
||||
**Common tasks:**
|
||||
```bash
|
||||
pnpm build # Production build
|
||||
pnpm typecheck # TypeScript validation
|
||||
pnpm lint # ESLint check and fix
|
||||
```
|
||||
|
||||
### Backend Development (ljwx-boot)
|
||||
|
||||
**Starting development:**
|
||||
```bash
|
||||
cd ljwx-boot
|
||||
./run-local.sh # Starts on port 9998
|
||||
```
|
||||
|
||||
**Important Notes:**
|
||||
- **DO NOT restart ljwx-boot during debugging** - User handles restarts manually
|
||||
- Check status: `./run-local.sh status`
|
||||
- Logs are in `logs/` directory
|
||||
- Configuration: Uses `local` profile (application-local.yml)
|
||||
|
||||
**Key modules:**
|
||||
- `ljwx-boot-modules/src/main/java/com/ljwx/modules/health/task/` - Scheduled tasks
|
||||
- `ljwx-boot-modules/src/main/java/com/ljwx/modules/health/service/` - Business logic
|
||||
- `ljwx-boot-common/src/main/java/com/ljwx/common/util/` - Utilities
|
||||
|
||||
**Maven commands:**
|
||||
```bash
|
||||
mvn clean install -DskipTests # Build all modules
|
||||
mvn spring-boot:run # Run with Maven
|
||||
```
|
||||
|
||||
### BigScreen Development (ljwx-bigscreen)
|
||||
|
||||
**Starting development:**
|
||||
```bash
|
||||
cd ljwx-bigscreen/bigscreen
|
||||
python run.py # Local: http://localhost:5225
|
||||
```
|
||||
|
||||
**Performance testing:**
|
||||
```bash
|
||||
./performance_test.sh # Load testing
|
||||
python test_health_fix.py # Health data tests
|
||||
```
|
||||
|
||||
### OpenAPI Contract Maintenance (ljwx-boot)
|
||||
|
||||
**IMPORTANT: API 契约是开发规范的强制约束,所有 Controller 变更必须通过契约检查。**
|
||||
|
||||
**契约导出(本地开发):**
|
||||
```bash
|
||||
cd ljwx-boot
|
||||
./scripts/export-openapi.sh # 导出 OpenAPI 到 api/openapi.json
|
||||
```
|
||||
|
||||
**破坏性变更检测:**
|
||||
```bash
|
||||
cd ljwx-boot
|
||||
./scripts/check-api-breaking-changes.sh # 对比 main 基线,检测 Breaking Changes
|
||||
```
|
||||
|
||||
**CI/CD 自动检查:**
|
||||
- **Gitea Actions** 在 PR 和 push 时自动运行契约检查(`.gitea/workflows/openapi-contract.yml`)
|
||||
- **检测项**:
|
||||
1. OpenAPI 契约可生成性
|
||||
2. 破坏性变更检测(删接口、改类型、删字段、收缩枚举等)
|
||||
3. 契约质量 Lint(可选)
|
||||
- **PR 规则**: 如有破坏性变更,CI 会自动评论并阻止合并
|
||||
|
||||
**开发规范(红线):**
|
||||
1. **仅使用 DTO** - Controller 禁止直接暴露 Entity/Map
|
||||
2. **明确响应结构** - 所有接口必须有明确的 Response Schema(含错误响应)
|
||||
3. **版本化管理** - 破坏性变更必须走 API 版本化(如 `/api/v2/...`)或 `@Deprecated`
|
||||
4. **基线同步** - 任何接口变更必须更新 `api/openapi.json` 并通过 CI
|
||||
5. **最少文档** - 新增接口必须有 `@Operation(summary="...")` 和 `@Schema` 注解
|
||||
|
||||
**常用注解:**
|
||||
```java
|
||||
@Tag(name = "用户管理", description = "用户相关接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/users")
|
||||
public class UserController {
|
||||
|
||||
@Operation(summary = "获取用户列表", description = "分页查询用户列表")
|
||||
@GetMapping("/list")
|
||||
public Result<PageVO<UserVO>> list(
|
||||
@Parameter(description = "页码") @RequestParam Integer page,
|
||||
@Parameter(description = "每页数量") @RequestParam Integer size
|
||||
) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**相关文件:**
|
||||
- **契约文件**: `ljwx-boot/api/openapi.json` - OpenAPI 3.0 契约基线
|
||||
- **配置文件**: `ljwx-boot-admin/src/main/resources/config/swagger.yml` - Springdoc 配置
|
||||
- **导出脚本**: `ljwx-boot/scripts/export-openapi.sh` - 契约导出工具
|
||||
- **检查脚本**: `ljwx-boot/scripts/check-api-breaking-changes.sh` - 差异检测工具
|
||||
- **CI 配置**: `.gitea/workflows/openapi-contract.yml` - 自动化检查流程
|
||||
|
||||
## Environment Isolation (环境隔离)
|
||||
|
||||
The project implements strict isolation between development and production environments to prevent configuration conflicts and ensure safe local development.
|
||||
|
||||
### Isolation Strategy
|
||||
|
||||
**Development Environment** (local profile):
|
||||
- Uses `./run-local.sh` for startup
|
||||
- Relative paths: `logs/`, `uploads/`, `data/`
|
||||
- Database: `127.0.0.1:3306/test`
|
||||
- Redis: `localhost:6379/1`
|
||||
- Flyway: **Disabled** (database pre-initialized)
|
||||
- Druid SQL Wall: **Disabled** (prevents false positives)
|
||||
- Log format: Plain text for readability
|
||||
|
||||
**Production Environment** (prod/docker/k8s profiles):
|
||||
- Uses K8s deployment scripts
|
||||
- Absolute paths: `/app/logs/`, `/app/data/`
|
||||
- Database: K8s Service DNS (mysql.infra.svc.cluster.local)
|
||||
- Redis: K8s Service DNS (redis-lb.infra.svc.cluster.local)
|
||||
- Flyway: **Enabled** (automatic schema migrations)
|
||||
- Druid SQL Wall: **Enabled** (SQL injection protection)
|
||||
- Log format: JSON for observability (Loki/Grafana)
|
||||
|
||||
### Key Configuration Files
|
||||
|
||||
#### 1. logback-spring.xml - Profile-Based Logging
|
||||
|
||||
**Location**: `ljwx-boot-admin/src/main/resources/logback-spring.xml`
|
||||
|
||||
**Dynamic Path Configuration**:
|
||||
```xml
|
||||
<!-- Local/Dev: Relative paths -->
|
||||
<springProfile name="local,dev">
|
||||
<property name="LOG_HOME" value="logs"/>
|
||||
</springProfile>
|
||||
|
||||
<!-- Prod/K8s: Absolute paths -->
|
||||
<springProfile name="prod,docker,docker-enhanced,k8s">
|
||||
<property name="LOG_HOME" value="/app/logs"/>
|
||||
</springProfile>
|
||||
```
|
||||
|
||||
**Why This Matters**:
|
||||
- Prevents "Failed to create /app/logs/" errors in local development
|
||||
- Ensures log files are written to the correct locations
|
||||
- Maintains clean separation between environments
|
||||
|
||||
#### 2. run-local.sh - Enhanced Startup Script
|
||||
|
||||
**Location**: `ljwx-boot/run-local.sh`
|
||||
|
||||
**Environment Safety Checks**:
|
||||
```bash
|
||||
# Prevent running in production paths
|
||||
if [ -d "/app/logs" ] || [ -d "/app/data" ]; then
|
||||
log_error "❌ Detected production paths (/app/*)"
|
||||
log_error " run-local.sh is for local development only"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Prevent using production profiles
|
||||
if [ "$SPRING_PROFILES_ACTIVE" == "prod" ]; then
|
||||
log_error "❌ Production profile detected"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
**Auto-Setup Features**:
|
||||
```bash
|
||||
# Automatic directory creation
|
||||
mkdir -p logs
|
||||
mkdir -p uploads/logos/defaults
|
||||
mkdir -p data/uploads
|
||||
|
||||
# Java version validation (requires 21+)
|
||||
JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | cut -d'.' -f1)
|
||||
if [ "$JAVA_VERSION" -lt 21 ]; then
|
||||
log_error "Java version too low (需要 21+,当前 $JAVA_VERSION)"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
**Flyway Override** (命令行参数优先级最高):
|
||||
```bash
|
||||
mvn spring-boot:run \
|
||||
-Dspring-boot.run.profiles=local \
|
||||
-Dspring-boot.run.arguments="--spring.flyway.enabled=false"
|
||||
```
|
||||
|
||||
#### 3. application-local.yml - Local Development Config
|
||||
|
||||
**Location**: `ljwx-boot-admin/src/main/resources/application-local.yml`
|
||||
|
||||
**Key Settings**:
|
||||
```yaml
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:mysql://127.0.0.1:3306/${MYSQL_DATABASE:test}?...
|
||||
username: ${MYSQL_USER:root}
|
||||
password: ${MYSQL_PASSWORD:123456}
|
||||
druid:
|
||||
# 本地开发仅保留 stat 和 slf4j,去掉 wall
|
||||
filters: stat,slf4j
|
||||
flyway:
|
||||
enabled: false # 本地开发禁用 Flyway
|
||||
|
||||
ljwx:
|
||||
logo:
|
||||
upload-path: uploads # 相对路径
|
||||
default-logo: uploads/logos/defaults/default-logo.svg
|
||||
```
|
||||
|
||||
### Common Issues and Solutions
|
||||
|
||||
#### Issue 1: "Failed to create /app/logs/" Error
|
||||
**Cause**: logback-spring.xml using hardcoded production path
|
||||
**Solution**: Use `<springProfile>` tags for dynamic path configuration (已修复)
|
||||
|
||||
#### Issue 2: Flyway Migration Failures in Local Dev
|
||||
**Cause**:
|
||||
- Druid SQL Wall filter blocks `CREATE INDEX IF NOT EXISTS` syntax
|
||||
- Flyway validation fails on pre-initialized databases
|
||||
|
||||
**Solution**:
|
||||
- Disable Flyway for local development via command-line argument
|
||||
- Production environments continue using Flyway normally
|
||||
|
||||
#### Issue 3: Configuration Override Not Working
|
||||
**Cause**: Spring Boot configuration precedence issues
|
||||
**Solution**: Use command-line arguments (`-Dspring-boot.run.arguments=...`) for highest precedence
|
||||
|
||||
### Verification Checklist
|
||||
|
||||
**Local Environment**:
|
||||
```bash
|
||||
# ✅ Check active profile
|
||||
curl -s http://localhost:9998/actuator/env | jq -r '.activeProfiles'
|
||||
# Expected: ["local"]
|
||||
|
||||
# ✅ Check log paths
|
||||
ls -lh logs/
|
||||
# Expected: ljwx-boot-admin_info.log, ljwx-boot-admin_error.log
|
||||
|
||||
# ✅ Check database connection
|
||||
curl -s http://localhost:9998/actuator/health | jq '.components.db.details.database'
|
||||
# Expected: "MySQL" (connected to 127.0.0.1:3306)
|
||||
|
||||
# ✅ Verify Flyway disabled
|
||||
grep -i "flyway" /tmp/ljwx-boot-*.log
|
||||
# Expected: No Flyway initialization messages
|
||||
```
|
||||
|
||||
**Production Environment (K8s)**:
|
||||
```bash
|
||||
# ✅ Check Pod environment
|
||||
kubectl get pod -n ljwx-health <pod-name> -o yaml | grep SPRING_PROFILES_ACTIVE
|
||||
# Expected: value: "prod"
|
||||
|
||||
# ✅ Check log format
|
||||
kubectl logs -n ljwx-health <pod-name> | head -1
|
||||
# Expected: JSON format with trace_id, service, environment fields
|
||||
|
||||
# ✅ Verify Flyway enabled
|
||||
kubectl logs -n ljwx-health <pod-name> | grep -i "flyway"
|
||||
# Expected: Flyway migration success messages
|
||||
```
|
||||
|
||||
### Environment Variables Reference
|
||||
|
||||
See [ENV_VARIABLES.md](ljwx-boot/ENV_VARIABLES.md) for complete environment variable documentation.
|
||||
|
||||
**Local Development**:
|
||||
```bash
|
||||
MYSQL_DATABASE=test
|
||||
MYSQL_HOST=127.0.0.1
|
||||
MYSQL_USER=root
|
||||
MYSQL_PASSWORD=123456
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=123456
|
||||
REDIS_DB=1
|
||||
```
|
||||
|
||||
**Production (K8s Secrets)**:
|
||||
```yaml
|
||||
SPRING_PROFILES_ACTIVE: prod
|
||||
SPRING_DATASOURCE_URL: jdbc:mysql://mysql.infra.svc.cluster.local:3306/ljwx_health
|
||||
SPRING_DATASOURCE_USERNAME: ljwx_app
|
||||
SPRING_DATASOURCE_PASSWORD: <from Secret>
|
||||
SPRING_REDIS_HOST: redis-lb.infra.svc.cluster.local
|
||||
SPRING_REDIS_PASSWORD: <from Secret>
|
||||
```
|
||||
|
||||
## Health System Architecture
|
||||
|
||||
### Health Data Scheduled Tasks
|
||||
|
||||
The system runs multiple scheduled tasks for health data processing:
|
||||
|
||||
**Task Schedule:**
|
||||
```
|
||||
01:00 - Weight configuration validation (validateWeightConfigurations)
|
||||
02:00 - User health baseline generation (generateUserHealthBaseline)
|
||||
02:05 - Department health baseline aggregation (generateDepartmentHealthBaseline)
|
||||
02:10 - Organization health baseline (generateOrgHealthBaseline)
|
||||
02:15 - Department health score (generateDepartmentHealthScore)
|
||||
04:00 - User health score generation (generateHealthScore)
|
||||
04:10 - Organization health score (generateOrgHealthScore)
|
||||
05:00 - Data cleanup (cleanupOldData)
|
||||
Monthly (1st) - Table partitioning (archiveAndResetUserHealthTable)
|
||||
```
|
||||
|
||||
**Location:** `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/health/task/HealthBaselineScoreTasks.java`
|
||||
|
||||
**Management UI:**
|
||||
- Frontend: `ljwx-admin/src/views/monitor/scheduler/index.vue`
|
||||
- API: `ljwx-admin/src/service/api/monitor/scheduler.ts`
|
||||
- Access: http://localhost:3000/#/monitor/scheduler
|
||||
|
||||
### Supported Health Metrics
|
||||
|
||||
The system monitors and analyzes these health indicators:
|
||||
- **heart_rate** (心率) - Core vital sign
|
||||
- **blood_oxygen** (血氧) - Respiratory health
|
||||
- **temperature** (体温) - Body temperature
|
||||
- **pressure_high/pressure_low** (血压) - Cardiovascular health
|
||||
- **stress** (压力) - Mental health
|
||||
- **step** (步数) - Activity level
|
||||
- **calorie** (卡路里) - Metabolic health
|
||||
- **distance** (距离) - Movement
|
||||
- **sleep** (睡眠) - Sleep quality
|
||||
|
||||
### Health Weight Configuration
|
||||
|
||||
Standard medical weight distribution (see `WeightCalculationService.java`):
|
||||
- **Core vitals (65%)**: heart_rate(20%), blood_oxygen(18%), temperature(15%), pressure(12%)
|
||||
- **Health status (20%)**: stress(12%), sleep(8%)
|
||||
- **Activity (10%)**: step(4%), distance(3%), calorie(3%)
|
||||
- **Auxiliary (5%)**: ECG and other metrics
|
||||
|
||||
## CI/CD with GitHub Actions
|
||||
|
||||
### Workflow Configuration
|
||||
|
||||
The GitHub Actions workflow (`.github/workflows/build-and-push.yml`) provides:
|
||||
|
||||
- **Automatic builds** on push to main/develop branches
|
||||
- **Version tagging** support (builds triggered by v* tags)
|
||||
- **Multi-architecture** builds (linux/amd64, linux/arm64)
|
||||
- **Component selection** - build all or specific components
|
||||
- **Image caching** using GitHub Actions cache
|
||||
|
||||
### Supported Components
|
||||
|
||||
The workflow builds the following Docker images:
|
||||
- `ljwx-boot` - Backend API service
|
||||
- `ljwx-admin` - Frontend admin dashboard
|
||||
- `ljwx-bigscreen` - Real-time monitoring dashboard
|
||||
- `ljwx-mysql` - MySQL database
|
||||
- `ljwx-redis` - Redis cache
|
||||
|
||||
### Manual Workflow Trigger
|
||||
|
||||
You can manually trigger builds via GitHub UI:
|
||||
1. Go to Actions tab in GitHub repository
|
||||
2. Select "Build and Push Docker Images"
|
||||
3. Click "Run workflow"
|
||||
4. Choose component (all or specific) and optional version tag
|
||||
|
||||
### Docker Compose Deployment
|
||||
|
||||
```bash
|
||||
# Use docker-compose.yml for local development
|
||||
docker-compose up -d
|
||||
|
||||
# Use docker-compose.prod.yml for production deployment
|
||||
docker-compose -f docker-compose.prod.yml up -d
|
||||
```
|
||||
|
||||
## Important Files and Locations
|
||||
|
||||
### Frontend (ljwx-admin)
|
||||
- **Request interceptor**: `src/service/request/index.ts` - Auto-injects customerId
|
||||
- **useTable hook**: `src/hooks/common/table.ts` - Table data management
|
||||
- **API definitions**: `src/service/api/` - Typed API calls
|
||||
- **Scheduler UI**: `src/views/monitor/scheduler/index.vue` - Task management
|
||||
|
||||
### Backend (ljwx-boot)
|
||||
- **Scheduled tasks**: `ljwx-boot-modules/src/main/java/com/ljwx/modules/health/task/HealthBaselineScoreTasks.java`
|
||||
- **Weight service**: `ljwx-boot-modules/src/main/java/com/ljwx/modules/health/service/WeightCalculationService.java`
|
||||
- **Health service**: `ljwx-boot-modules/src/main/java/com/ljwx/modules/health/service/UnifiedHealthDataQueryService.java`
|
||||
- **IP utilities**: `ljwx-boot-common/src/main/java/com/ljwx/common/util/IPUtil.java` - IPv6 fix included
|
||||
|
||||
### BigScreen (ljwx-bigscreen)
|
||||
- **Main app**: `bigscreen/bigScreen/bigScreen.py` - Flask routes and API
|
||||
- **Configuration**: `bigscreen/config.py` - Environment and settings
|
||||
- **Models**: `bigscreen/bigScreen/models.py` - SQLAlchemy database models
|
||||
- **Health data**: `bigscreen/bigScreen/user_health_data.py` - Data processing
|
||||
|
||||
## Known Issues and Fixes
|
||||
|
||||
### IPv6 Address Resolution (Fixed)
|
||||
- **Issue**: IPv6 localhost "0:0:0:0:0:0:0:1" not recognized by ip2region
|
||||
- **Fix**: Added detection in `IPUtil.java:171-185`
|
||||
- **Handles**: Local addresses, IPv6, internal IPs with proper fallbacks
|
||||
|
||||
### Weight Cache Table (Fixed)
|
||||
- **Issue**: `t_weight_cache` table missing caused health score failures
|
||||
- **Fix**: Auto-creates table structure in `WeightCalculationService.java`
|
||||
- **Features**: User weight config, position risk multipliers, normalized weights
|
||||
|
||||
### Health Recommendation NullPointerException (Fixed)
|
||||
- **Issue**: Null keys in data grouping caused crashes
|
||||
- **Fix**: Added null filtering in `HealthRecommendationService.java`
|
||||
- **Improvement**: Enhanced data validation and error logging
|
||||
|
||||
### Health Data Query Performance (Optimized)
|
||||
- **Issue**: N+1 query problem, repeated config parsing per record
|
||||
- **Fix**: Batch conversion with caching in `UnifiedHealthDataQueryService.java`
|
||||
- **Performance**: 13x faster (~200ms → ~15ms for 20 records), 95% fewer DB queries
|
||||
|
||||
### Frontend Table Display Issues
|
||||
- **Common cause**: Using `remote` property on NDataTable incorrectly
|
||||
- **Solution**: Remove `remote` unless implementing true server-side pagination
|
||||
- **Best practice**: Use computed properties for columns, not useTable's column processing
|
||||
|
||||
## Development Best Practices
|
||||
|
||||
### Multi-Tenant Architecture
|
||||
- **customerId auto-injection**: Request interceptor automatically adds customerId to all API calls
|
||||
- **Exclusion list**: Login, auth, dictionary, and system APIs excluded from auto-injection
|
||||
- **Override support**: Explicitly passed customerId values are preserved
|
||||
|
||||
### Performance Optimization Patterns
|
||||
- **Avoid N+1 queries**: Use batch queries with caching (see `UnifiedHealthDataQueryService`)
|
||||
- **Batch processing**: Process data in batches of 200 records
|
||||
- **Connection pooling**: 30 base + 50 overflow connections configured
|
||||
- **Redis caching**: 3-5 minute TTL for frequently accessed data
|
||||
|
||||
### Code Quality Guidelines
|
||||
- **Null safety**: Always filter null values before stream operations
|
||||
- **Error handling**: Comprehensive try-catch with graceful degradation
|
||||
- **Logging levels**: DEBUG for detailed logs, INFO for performance metrics
|
||||
- **Type safety**: Proper BigDecimal to Double conversions in weight calculations
|
||||
|
||||
## Testing and Debugging
|
||||
|
||||
### Backend Testing
|
||||
```bash
|
||||
cd ljwx-boot
|
||||
./run-local.sh # Start service
|
||||
# Check logs in logs/ directory
|
||||
# Monitor scheduled tasks via scheduler UI
|
||||
```
|
||||
|
||||
### Frontend Testing
|
||||
```bash
|
||||
cd ljwx-admin
|
||||
pnpm dev # Development server
|
||||
# Use browser DevTools for debugging
|
||||
# Check network tab for API calls and customerId injection
|
||||
```
|
||||
|
||||
### BigScreen Testing
|
||||
```bash
|
||||
cd ljwx-bigscreen/bigscreen
|
||||
python run.py # Start service
|
||||
./performance_test.sh # Load testing
|
||||
python test_health_fix.py # Health data tests
|
||||
```
|
||||
|
||||
## Observability (可观测性)
|
||||
|
||||
### 监控栈架构
|
||||
|
||||
LJWX Health 已集成完整的三大支柱可观测性:
|
||||
|
||||
- **Logs (日志)**: Logback/Python JSON → Loki → Grafana
|
||||
- **Traces (链路追踪)**: OpenTelemetry → Tempo → Grafana
|
||||
- **Metrics (指标)**: Micrometer/prometheus_client → Prometheus → Grafana
|
||||
|
||||
### K8s 生产环境部署
|
||||
|
||||
部署完整监控栈到 K8s 集群:
|
||||
```bash
|
||||
# 一键部署 Grafana + Prometheus + Loki + Tempo
|
||||
./scripts/deploy-observability.sh
|
||||
|
||||
# 检查部署状态
|
||||
kubectl get pods -n infra
|
||||
|
||||
# 访问 Grafana
|
||||
kubectl port-forward -n infra svc/grafana 3000:3000
|
||||
# 浏览器访问: http://localhost:3000
|
||||
# 默认账号: admin / admin123
|
||||
```
|
||||
|
||||
**监控组件**:
|
||||
- **Tempo**: `tempo.infra.svc.cluster.local:4317` (OTLP gRPC)
|
||||
- **Loki**: `loki.infra.svc.cluster.local:3100` (HTTP)
|
||||
- **Prometheus**: `prometheus.infra.svc.cluster.local:9090` (HTTP)
|
||||
- **Grafana**: 端口转发到 `localhost:3000`
|
||||
|
||||
### 本地开发环境
|
||||
|
||||
启动完整监控栈(Docker Compose):
|
||||
```bash
|
||||
docker-compose -f ljwx-boot/docker-compose-p0-monitoring.yml up -d
|
||||
```
|
||||
|
||||
访问地址:
|
||||
- Grafana: http://localhost:3000 (admin/admin123)
|
||||
- Prometheus: http://localhost:9090
|
||||
- ljwx-boot metrics: http://localhost:9998/actuator/prometheus
|
||||
- ljwx-bigscreen metrics: http://localhost:5225/metrics
|
||||
|
||||
### 应用配置
|
||||
|
||||
#### ljwx-boot (Spring Boot)
|
||||
|
||||
**自定义业务指标**:
|
||||
```java
|
||||
@Autowired
|
||||
private HealthDataMetrics metrics;
|
||||
|
||||
// 记录健康数据写入
|
||||
metrics.recordHealthDataInsert("heart_rate");
|
||||
|
||||
// 记录去重
|
||||
metrics.recordHealthDataDedup("blood_oxygen", true);
|
||||
|
||||
// 更新去重率
|
||||
metrics.updateDedupRate(0.95); // 95%
|
||||
|
||||
// 计时示例
|
||||
Timer.Sample sample = metrics.startHealthCalculationTimer("baseline");
|
||||
try {
|
||||
// 执行计算
|
||||
} finally {
|
||||
metrics.stopHealthCalculationTimer(sample, "baseline", true);
|
||||
}
|
||||
```
|
||||
|
||||
**可用指标**:
|
||||
- `health.data.insert` - 健康数据写入次数(按类型)
|
||||
- `health.data.dedup.rate` - 去重率(0-100%)
|
||||
- `health.data.cache.hit.rate` - 缓存命中率
|
||||
- `health.calculation.duration` - 健康分数计算时长
|
||||
- `health.scheduled.task.duration` - 定时任务执行时长
|
||||
- `health.ollama.prediction.duration` - AI 预测时长
|
||||
|
||||
#### ljwx-bigscreen (Flask)
|
||||
|
||||
**集成可观测性**:
|
||||
```python
|
||||
from config import setup_logging
|
||||
from observability import (
|
||||
init_tracing, init_metrics,
|
||||
record_health_query, record_db_query
|
||||
)
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# 配置 JSON 日志
|
||||
setup_logging(app) # 自动判断环境
|
||||
|
||||
# 初始化追踪和指标
|
||||
init_tracing(app)
|
||||
init_metrics(app)
|
||||
|
||||
# 使用自定义指标
|
||||
@app.route('/api/health-data')
|
||||
def get_health_data():
|
||||
record_health_query('health-data', 'success')
|
||||
return jsonify(data)
|
||||
```
|
||||
|
||||
**可用指标**:
|
||||
- `bigscreen_health_query_total` - 健康数据查询计数
|
||||
- `bigscreen_celery_task_duration_seconds` - Celery 任务时长
|
||||
- `bigscreen_active_users` - 活跃用户数
|
||||
- `bigscreen_websocket_connections` - WebSocket 连接数
|
||||
- `bigscreen_db_query_duration_seconds` - 数据库查询时长
|
||||
|
||||
### 环境变量配置
|
||||
|
||||
**ljwx-boot (已在 Helm values.yaml 配置)**:
|
||||
```yaml
|
||||
- name: SPRING_PROFILES_ACTIVE
|
||||
value: "prod" # 触发 JSON 日志
|
||||
- name: OTEL_SERVICE_NAME
|
||||
value: "ljwx-boot"
|
||||
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
||||
value: "http://tempo.infra.svc.cluster.local:4317"
|
||||
- name: OTEL_TRACES_SAMPLER_ARG
|
||||
value: "0.1" # 10% 采样率(生产)
|
||||
```
|
||||
|
||||
**ljwx-bigscreen (已在 Helm values.yaml 配置)**:
|
||||
```yaml
|
||||
- name: ENV
|
||||
value: "production" # 触发 JSON 日志
|
||||
- name: OTEL_SERVICE_NAME
|
||||
value: "ljwx-bigscreen"
|
||||
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
||||
value: "http://tempo.infra.svc.cluster.local:4317"
|
||||
```
|
||||
|
||||
### Grafana 仪表板
|
||||
|
||||
**待创建的仪表板**:
|
||||
1. **ljwx-boot Performance**: JVM, HTTP, Database, Cache
|
||||
2. **ljwx-boot Business**: 健康数据处理、定时任务、AI 预测
|
||||
3. **ljwx-bigscreen Performance**: Flask, Celery, Database
|
||||
4. **Infrastructure**: MySQL, Redis
|
||||
5. **Service Overview**: RED 指标、调用链、日志流
|
||||
|
||||
**创建方法**:
|
||||
- 手动: Grafana UI → Dashboards → New Dashboard
|
||||
- 自动: 导出 JSON 到 `deploy/monitoring/grafana/dashboards/`
|
||||
|
||||
### 查询日志和追踪
|
||||
|
||||
**Loki 日志查询**:
|
||||
```
|
||||
# 查看 ljwx-boot 日志
|
||||
{app="ljwx-boot"} |= "ERROR"
|
||||
|
||||
# 按 trace_id 过滤
|
||||
{app="ljwx-boot"} | json | trace_id="1a2b3c4d5e6f7g8h"
|
||||
|
||||
# 统计错误日志
|
||||
sum(count_over_time({app="ljwx-boot"} |= "ERROR" [5m]))
|
||||
```
|
||||
|
||||
**Tempo 追踪查询**:
|
||||
```
|
||||
# 按服务名搜索
|
||||
service.name="ljwx-boot"
|
||||
|
||||
# 按时长过滤(慢查询)
|
||||
service.name="ljwx-boot" && duration > 1s
|
||||
|
||||
# 按 HTTP 端点过滤
|
||||
service.name="ljwx-boot" && http.target="/api/health/data"
|
||||
```
|
||||
|
||||
### 故障排查
|
||||
|
||||
**问题1: 日志未出现在 Loki**
|
||||
```bash
|
||||
# 检查应用日志格式
|
||||
kubectl logs -n ljwx-health deployment/ljwx-boot
|
||||
# 应该看到 JSON 格式,包含 trace_id, span_id
|
||||
|
||||
# 检查 Loki 健康状态
|
||||
kubectl exec -n infra tempo-0 -- wget -O- http://loki.infra.svc.cluster.local:3100/ready
|
||||
```
|
||||
|
||||
**问题2: Trace 未出现在 Tempo**
|
||||
```bash
|
||||
# 检查 OTLP 端点配置
|
||||
kubectl get pod -n ljwx-health <app-pod> -o yaml | grep OTEL_EXPORTER_OTLP_ENDPOINT
|
||||
|
||||
# 检查 Tempo 服务
|
||||
kubectl get svc -n infra tempo
|
||||
# 应该有 4317 (OTLP gRPC) 和 4318 (OTLP HTTP)
|
||||
|
||||
# 临时提高采样率(测试用)
|
||||
kubectl set env deployment/ljwx-boot -n ljwx-health OTEL_TRACES_SAMPLER_ARG=1.0
|
||||
```
|
||||
|
||||
### 性能优化
|
||||
|
||||
**采样率调整**:
|
||||
- 开发环境: `OTEL_TRACES_SAMPLER_ARG=1.0` (100% 采样)
|
||||
- 生产环境: `OTEL_TRACES_SAMPLER_ARG=0.1` (10% 采样)
|
||||
- 高流量环境: `OTEL_TRACES_SAMPLER_ARG=0.01` (1% 采样)
|
||||
|
||||
**数据保留策略**:
|
||||
- Loki: 7天 (168h) - 可通过 `limits_config.retention_period` 调整
|
||||
- Tempo: 2天 (48h) - 可通过 `compactor.compaction.block_retention` 调整
|
||||
- Prometheus: 30天 - 建议使用 Thanos 长期存储
|
||||
|
||||
### 详细文档
|
||||
|
||||
完整实施细节和配置说明:
|
||||
- [OBSERVABILITY_IMPLEMENTATION.md](./OBSERVABILITY_IMPLEMENTATION.md) - 完整实施总结
|
||||
- [实施计划](./fuzzy-inventing-fern.md) - 在 `/root/.claude/plans/` 目录
|
||||
|
||||
## Additional Documentation
|
||||
|
||||
For detailed information about specific subsystems, see:
|
||||
- **ljwx-admin**: `ljwx-admin/CLAUDE.md` - Frontend architecture and troubleshooting
|
||||
- **ljwx-bigscreen**: `ljwx-bigscreen/CLAUDE.md` - Monitoring system details
|
||||
- **Infrastructure**: `docs/` directory for CI/CD and deployment guides
|
||||
@@ -1,464 +0,0 @@
|
||||
# 贡献指南
|
||||
|
||||
感谢你对LJWX Health项目的关注!我们欢迎所有形式的贡献。
|
||||
|
||||
---
|
||||
|
||||
## 📋 目录
|
||||
|
||||
- [行为准则](#行为准则)
|
||||
- [如何贡献](#如何贡献)
|
||||
- [开发流程](#开发流程)
|
||||
- [代码规范](#代码规范)
|
||||
- [提交规范](#提交规范)
|
||||
- [文档贡献](#文档贡献)
|
||||
|
||||
---
|
||||
|
||||
## 🤝 行为准则
|
||||
|
||||
参与本项目的所有人员应遵守以下原则:
|
||||
|
||||
- 尊重所有贡献者
|
||||
- 保持专业和包容的态度
|
||||
- 接受建设性的批评
|
||||
- 关注项目整体利益
|
||||
|
||||
---
|
||||
|
||||
## 💡 如何贡献
|
||||
|
||||
### 报告Bug
|
||||
|
||||
提交Bug时请包含:
|
||||
|
||||
1. **问题描述**: 清晰描述遇到的问题
|
||||
2. **复现步骤**: 详细的操作步骤
|
||||
3. **预期行为**: 应该发生什么
|
||||
4. **实际行为**: 实际发生了什么
|
||||
5. **环境信息**:
|
||||
- 操作系统及版本
|
||||
- Docker/K8s版本
|
||||
- LJWX版本
|
||||
6. **日志输出**: 相关错误日志
|
||||
7. **截图**: 如适用
|
||||
|
||||
**模板**: [Bug Report](.github/ISSUE_TEMPLATE/bug_report.md)
|
||||
|
||||
### 功能建议
|
||||
|
||||
提交功能建议时请包含:
|
||||
|
||||
1. **问题陈述**: 这个功能解决什么问题
|
||||
2. **建议方案**: 你希望的实现方式
|
||||
3. **替代方案**: 是否考虑过其他方案
|
||||
4. **影响范围**: 哪些模块会受影响
|
||||
|
||||
**模板**: [Feature Request](.github/ISSUE_TEMPLATE/feature_request.md)
|
||||
|
||||
---
|
||||
|
||||
## 🔧 开发流程
|
||||
|
||||
### 1. Fork项目
|
||||
|
||||
```bash
|
||||
# Fork项目到你的GitHub账号
|
||||
# 然后clone到本地
|
||||
git clone https://github.com/YOUR-USERNAME/ljwx-health.git
|
||||
cd ljwx-health
|
||||
|
||||
# 添加上游仓库
|
||||
git remote add upstream https://github.com/yourorg/ljwx-health.git
|
||||
```
|
||||
|
||||
### 2. 创建分支
|
||||
|
||||
```bash
|
||||
# 确保从最新的main分支创建
|
||||
git checkout main
|
||||
git pull upstream main
|
||||
|
||||
# 创建功能分支(遵循命名规范)
|
||||
git checkout -b feature/data-flow-dashboard
|
||||
git checkout -b fix/login-timeout
|
||||
git checkout -b docs/update-deployment-guide
|
||||
```
|
||||
|
||||
**分支命名规范**:
|
||||
- `feature/*` - 新功能
|
||||
- `fix/*` - Bug修复
|
||||
- `docs/*` - 文档更新
|
||||
- `refactor/*` - 代码重构
|
||||
- `test/*` - 测试相关
|
||||
- `chore/*` - 构建/工具相关
|
||||
|
||||
### 3. 开发与测试
|
||||
|
||||
```bash
|
||||
# 开发前端
|
||||
cd ljwx-admin
|
||||
pnpm install
|
||||
pnpm dev
|
||||
pnpm lint
|
||||
pnpm typecheck
|
||||
|
||||
# 开发后端
|
||||
cd ljwx-boot
|
||||
./run-local.sh
|
||||
mvn test
|
||||
|
||||
# 开发大屏
|
||||
cd ljwx-bigscreen/bigscreen
|
||||
python run.py
|
||||
pytest
|
||||
```
|
||||
|
||||
**重要检查**:
|
||||
- ✅ 代码通过所有单元测试
|
||||
- ✅ 代码符合lint规范
|
||||
- ✅ 类型检查无错误
|
||||
- ✅ 本地环境验证通过
|
||||
|
||||
### 4. 提交代码
|
||||
|
||||
```bash
|
||||
# 添加变更
|
||||
git add .
|
||||
|
||||
# 提交(遵循提交规范)
|
||||
git commit -m "feat(data-flow): 添加数据流监控Dashboard"
|
||||
|
||||
# 推送到你的fork
|
||||
git push origin feature/data-flow-dashboard
|
||||
```
|
||||
|
||||
### 5. 创建Pull Request
|
||||
|
||||
1. 访问你的fork页面
|
||||
2. 点击 "New Pull Request"
|
||||
3. 填写PR模板
|
||||
4. 等待代码审查
|
||||
|
||||
---
|
||||
|
||||
## 📝 代码规范
|
||||
|
||||
### 后端代码 (Java)
|
||||
|
||||
**必须遵守**:
|
||||
- [PROMPT_BLUEPRINT.md](PROMPT_BLUEPRINT.md) - 工程蓝图强制约束
|
||||
- OpenAPI-First开发,所有API必须有契约
|
||||
- 仅使用DTO,禁止暴露Entity/Map
|
||||
- 所有公开方法必须有JavaDoc注释
|
||||
|
||||
**代码风格**:
|
||||
```java
|
||||
// ✅ 推荐
|
||||
@Operation(summary = "获取用户列表", description = "分页查询用户列表")
|
||||
@GetMapping("/list")
|
||||
public Result<PageVO<UserVO>> list(
|
||||
@Parameter(description = "页码") @RequestParam Integer page,
|
||||
@Parameter(description = "每页数量") @RequestParam Integer size
|
||||
) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// ❌ 不推荐
|
||||
@GetMapping("/list")
|
||||
public Object list(Map params) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**OpenAPI契约检查**:
|
||||
```bash
|
||||
cd ljwx-boot
|
||||
./scripts/export-openapi.sh
|
||||
./scripts/check-api-breaking-changes.sh
|
||||
```
|
||||
|
||||
### 前端代码 (Vue3 + TypeScript)
|
||||
|
||||
**代码风格**:
|
||||
```typescript
|
||||
// ✅ 推荐 - 使用组合式API
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
interface Props {
|
||||
userId: number
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const count = ref(0)
|
||||
const doubleCount = computed(() => count.value * 2)
|
||||
</script>
|
||||
|
||||
// ❌ 不推荐 - 避免选项式API(除非必要)
|
||||
<script lang="ts">
|
||||
export default {
|
||||
data() {
|
||||
return { count: 0 }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
**类型安全**:
|
||||
- 所有组件props必须有类型定义
|
||||
- API调用必须有明确的返回类型
|
||||
- 避免使用`any`类型
|
||||
|
||||
**Lint检查**:
|
||||
```bash
|
||||
pnpm lint # ESLint检查
|
||||
pnpm typecheck # TypeScript检查
|
||||
```
|
||||
|
||||
### Python代码 (ljwx-bigscreen)
|
||||
|
||||
**代码风格** (PEP 8):
|
||||
```python
|
||||
# ✅ 推荐
|
||||
def calculate_health_score(
|
||||
user_id: int,
|
||||
data_type: str,
|
||||
date_range: Tuple[datetime, datetime]
|
||||
) -> float:
|
||||
"""计算健康评分
|
||||
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
data_type: 数据类型
|
||||
date_range: 时间范围
|
||||
|
||||
Returns:
|
||||
健康评分(0-100)
|
||||
"""
|
||||
# ...
|
||||
|
||||
# ❌ 不推荐
|
||||
def calc(u, d, r):
|
||||
# ...
|
||||
```
|
||||
|
||||
**类型注解**:
|
||||
- Python 3.8+ 类型注解
|
||||
- 所有公开函数必须有docstring
|
||||
|
||||
**测试**:
|
||||
```bash
|
||||
pytest tests/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 提交规范
|
||||
|
||||
### Conventional Commits
|
||||
|
||||
格式: `<type>(<scope>): <subject>`
|
||||
|
||||
**类型 (type)**:
|
||||
- `feat`: 新功能
|
||||
- `fix`: Bug修复
|
||||
- `docs`: 文档更新
|
||||
- `style`: 代码格式(不影响功能)
|
||||
- `refactor`: 代码重构
|
||||
- `test`: 测试相关
|
||||
- `chore`: 构建/工具相关
|
||||
- `perf`: 性能优化
|
||||
|
||||
**范围 (scope)**: 影响的模块
|
||||
- `data-flow` - 数据流
|
||||
- `alert` - 告警系统
|
||||
- `geofence` - 电子围栏
|
||||
- `admin` - 前端管理
|
||||
- `boot` - 后端API
|
||||
- `bigscreen` - 监控大屏
|
||||
- `docs` - 文档
|
||||
|
||||
**示例**:
|
||||
```bash
|
||||
feat(data-flow): 添加WebSocket实时推送
|
||||
fix(alert): 修复多租户告警规则冲突
|
||||
docs(deployment): 更新Kubernetes部署指南
|
||||
refactor(bigscreen): 优化健康评分计算算法
|
||||
test(api): 添加OpenAPI契约测试
|
||||
```
|
||||
|
||||
### Git提交消息
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
<body>
|
||||
|
||||
<footer>
|
||||
```
|
||||
|
||||
**示例**:
|
||||
```
|
||||
feat(data-flow): 添加数据流监控Dashboard
|
||||
|
||||
- ECharts Sankey拓扑图
|
||||
- WebSocket实时推送(3秒刷新)
|
||||
- 6个关键指标统计
|
||||
- Grafana仪表板集成
|
||||
|
||||
Closes #123
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 文档贡献
|
||||
|
||||
### 文档结构
|
||||
|
||||
所有文档遵循新的目录结构:
|
||||
|
||||
```
|
||||
docs/
|
||||
├── 01-getting-started/ # 快速开始
|
||||
├── 02-architecture/ # 架构设计
|
||||
├── 03-deployment/ # 部署指南
|
||||
├── 04-operations/ # 运维手册
|
||||
├── 05-features/ # 功能文档
|
||||
├── 06-development/ # 开发指南
|
||||
├── 07-compliance/ # 工程规范
|
||||
└── 08-reference/ # 参考资料
|
||||
```
|
||||
|
||||
### 文档模板
|
||||
|
||||
**功能文档模板**:
|
||||
```markdown
|
||||
# 功能名称
|
||||
|
||||
**状态**: ✅ 稳定 / 🔧 Beta / ⚠️ 实验性
|
||||
**版本**: v1.0
|
||||
**最后更新**: 2026-01-04
|
||||
|
||||
## 概述
|
||||
[1-2段说明]
|
||||
|
||||
## 快速开始
|
||||
[最简示例]
|
||||
|
||||
## 详细说明
|
||||
[分章节展开]
|
||||
|
||||
## 配置参考
|
||||
[配置项说明]
|
||||
|
||||
## 故障排查
|
||||
[常见问题]
|
||||
|
||||
## 相关文档
|
||||
- [链接1]
|
||||
- [链接2]
|
||||
```
|
||||
|
||||
### 文档命名规范
|
||||
|
||||
- ✅ 使用小写 + 连字符: `quick-start-docker.md`
|
||||
- ❌ 避免大写: `QUICK_START.md`
|
||||
- ❌ 避免驼峰: `QuickStart.md`
|
||||
- ❌ 避免空格: `quick start.md`
|
||||
|
||||
### 文档更新流程
|
||||
|
||||
1. 创建/更新文档
|
||||
2. 更新顶部的"最后更新"日期
|
||||
3. 更新 [CHANGELOG.md](CHANGELOG.md)
|
||||
4. 如果是新功能,更新 [docs/README.md](docs/README.md) 索引
|
||||
5. 提交PR
|
||||
|
||||
---
|
||||
|
||||
## 🔍 代码审查
|
||||
|
||||
### 审查清单
|
||||
|
||||
**功能性**:
|
||||
- [ ] 代码实现符合需求
|
||||
- [ ] 边界条件处理正确
|
||||
- [ ] 错误处理完善
|
||||
|
||||
**质量**:
|
||||
- [ ] 代码可读性好
|
||||
- [ ] 无重复代码
|
||||
- [ ] 变量命名清晰
|
||||
|
||||
**测试**:
|
||||
- [ ] 单元测试覆盖核心逻辑
|
||||
- [ ] 集成测试通过
|
||||
- [ ] 边界测试完整
|
||||
|
||||
**安全**:
|
||||
- [ ] 无SQL注入风险
|
||||
- [ ] 无XSS漏洞
|
||||
- [ ] 敏感数据加密
|
||||
|
||||
**合规**:
|
||||
- [ ] 符合PROMPT_BLUEPRINT.md
|
||||
- [ ] OpenAPI契约已更新
|
||||
- [ ] 文档已更新
|
||||
|
||||
---
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
### Q: 如何同步上游更新?
|
||||
|
||||
```bash
|
||||
git checkout main
|
||||
git fetch upstream
|
||||
git merge upstream/main
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### Q: 如何处理合并冲突?
|
||||
|
||||
```bash
|
||||
# 拉取最新代码
|
||||
git fetch upstream
|
||||
git rebase upstream/main
|
||||
|
||||
# 解决冲突
|
||||
# 编辑冲突文件
|
||||
git add .
|
||||
git rebase --continue
|
||||
```
|
||||
|
||||
### Q: 如何修改已提交的commit?
|
||||
|
||||
```bash
|
||||
# 修改最后一次commit
|
||||
git commit --amend
|
||||
|
||||
# 修改多个commit
|
||||
git rebase -i HEAD~3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 获取帮助
|
||||
|
||||
- **技术问题**: [GitHub Discussions](https://github.com/yourorg/ljwx-health/discussions)
|
||||
- **Bug报告**: [GitHub Issues](https://github.com/yourorg/ljwx-health/issues)
|
||||
- **实时交流**: [Discord/Slack]
|
||||
- **邮件联系**: dev@ljwx-health.com
|
||||
|
||||
---
|
||||
|
||||
## 🎉 贡献者
|
||||
|
||||
感谢所有贡献者!
|
||||
|
||||
查看完整贡献者列表: [Contributors](https://github.com/yourorg/ljwx-health/graphs/contributors)
|
||||
|
||||
---
|
||||
|
||||
**再次感谢你的贡献!** ❤️
|
||||
@@ -1,250 +0,0 @@
|
||||
# 文档重构实施指南
|
||||
|
||||
**快速版** - 5分钟上手 ⚡
|
||||
|
||||
---
|
||||
|
||||
## 🎯 目标
|
||||
|
||||
将混乱的57个根目录文档重构为专业的文档架构:
|
||||
- ✅ README从1844行精简到258行(-86%)
|
||||
- ✅ 根目录从57个文档降到10个(-82%)
|
||||
- ✅ 8个分类清晰的文档目录
|
||||
- ✅ 完整的导航和索引系统
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速开始(5分钟)
|
||||
|
||||
### 方式A: 自动化迁移(推荐)⭐
|
||||
|
||||
```bash
|
||||
# 1. 查看重构方案
|
||||
cat DOCUMENTATION_REFACTORING_PLAN.md
|
||||
|
||||
# 2. 运行自动迁移脚本(会自动备份)
|
||||
./scripts/migrate-docs.sh
|
||||
|
||||
# 3. 查看迁移报告
|
||||
cat MIGRATION_REPORT.md
|
||||
|
||||
# 4. 预览新的文档结构
|
||||
open docs/README.md
|
||||
open README.md # 新的精简版README
|
||||
```
|
||||
|
||||
### 方式B: 手动迁移
|
||||
|
||||
如果需要更精细的控制,参考 [DOCUMENTATION_REFACTORING_PLAN.md](DOCUMENTATION_REFACTORING_PLAN.md) 手动迁移。
|
||||
|
||||
---
|
||||
|
||||
## 📂 新文档结构预览
|
||||
|
||||
### 根目录(仅10个核心文件)
|
||||
|
||||
```
|
||||
ljwx-health/
|
||||
├── README.md # 项目概览(258行)⭐ 新
|
||||
├── CLAUDE.md # AI开发指南
|
||||
├── PROMPT_BLUEPRINT.md # 工程蓝图
|
||||
├── CHANGELOG.md # 版本变更日志 🆕
|
||||
├── CONTRIBUTING.md # 贡献指南 🆕
|
||||
├── LICENSE
|
||||
├── docs/ # 文档中心 →
|
||||
└── archive/ # 历史归档 🆕
|
||||
```
|
||||
|
||||
### docs/ 目录(8个分类)
|
||||
|
||||
```
|
||||
docs/
|
||||
├── README.md # 文档导航中心 🆕
|
||||
├── 01-getting-started/ # 快速开始
|
||||
├── 02-architecture/ # 架构设计
|
||||
├── 03-deployment/ # 部署指南
|
||||
├── 04-operations/ # 运维手册
|
||||
├── 05-features/ # 功能文档
|
||||
├── 06-development/ # 开发指南
|
||||
├── 07-compliance/ # 工程规范
|
||||
└── 08-reference/ # 参考资料
|
||||
```
|
||||
|
||||
### archive/ 归档
|
||||
|
||||
```
|
||||
archive/
|
||||
├── README.md # 归档说明 🆕
|
||||
├── 2025/ # 2025年度归档
|
||||
│ ├── fixes/ # 历史修复
|
||||
│ ├── implementations/ # 实施记录
|
||||
│ └── experiments/ # 实验方案
|
||||
└── deprecated/ # 已废弃文档
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 已完成的工作
|
||||
|
||||
### 1. 核心文档
|
||||
|
||||
| 文件 | 状态 | 说明 |
|
||||
|-----|------|------|
|
||||
| README.new.md | ✅ 创建 | 精简版README(258行,-86%)|
|
||||
| CHANGELOG.md | ✅ 创建 | 版本变更日志 |
|
||||
| CONTRIBUTING.md | ✅ 创建 | 贡献指南 |
|
||||
| docs/README.md | ✅ 创建 | 文档导航中心 |
|
||||
| archive/README.md | ✅ 创建 | 归档说明 |
|
||||
|
||||
### 2. 目录结构
|
||||
|
||||
| 目录 | 状态 | 文件数 |
|
||||
|-----|------|--------|
|
||||
| docs/01-getting-started | ✅ 创建 | - |
|
||||
| docs/02-architecture | ✅ 创建 | - |
|
||||
| docs/03-deployment | ✅ 创建 | docker/, kubernetes/, gitops/ |
|
||||
| docs/04-operations | ✅ 创建 | database/, monitoring/, troubleshooting/ |
|
||||
| docs/05-features | ✅ 创建 | health-monitoring/, geofence/, multi-tenant/ |
|
||||
| docs/06-development | ✅ 创建 | backend/, frontend/, api/ |
|
||||
| docs/07-compliance | ✅ 创建 | - |
|
||||
| docs/08-reference | ✅ 创建 | - |
|
||||
| archive/2025 | ✅ 创建 | fixes/, implementations/, experiments/ |
|
||||
| archive/deprecated | ✅ 创建 | old-quick-starts/ |
|
||||
|
||||
### 3. 工具脚本
|
||||
|
||||
| 脚本 | 状态 | 功能 |
|
||||
|-----|------|------|
|
||||
| scripts/migrate-docs.sh | ✅ 创建 | 自动化文档迁移 |
|
||||
|
||||
---
|
||||
|
||||
## 📋 迁移检查清单
|
||||
|
||||
### Phase 1: 准备(5分钟)
|
||||
|
||||
- [ ] 阅读 [DOCUMENTATION_REFACTORING_PLAN.md](DOCUMENTATION_REFACTORING_PLAN.md)
|
||||
- [ ] 确认目录结构已创建(`ls docs/ archive/`)
|
||||
- [ ] 备份当前文档(自动化脚本会处理)
|
||||
|
||||
### Phase 2: 执行迁移(10分钟)
|
||||
|
||||
- [ ] 运行 `./scripts/migrate-docs.sh`
|
||||
- [ ] 确认迁移完成(查看输出日志)
|
||||
- [ ] 检查 `MIGRATION_REPORT.md`
|
||||
|
||||
### Phase 3: 验证(10分钟)
|
||||
|
||||
- [ ] 根目录文档数 ≤ 10个(`ls *.md | wc -l`)
|
||||
- [ ] README.md ≤ 300行(`wc -l README.md`)
|
||||
- [ ] 所有docs/子目录有README.md
|
||||
- [ ] 归档文档正确分类
|
||||
|
||||
### Phase 4: 更新引用(10分钟)
|
||||
|
||||
- [ ] 更新CLAUDE.md中的文档引用
|
||||
- [ ] 检查文档内部链接(可选)
|
||||
- [ ] 更新项目Wiki/文档站点(如有)
|
||||
|
||||
### Phase 5: 提交(5分钟)
|
||||
|
||||
- [ ] `git add .`
|
||||
- [ ] `git commit -m "docs: 文档结构重构"`
|
||||
- [ ] `git push`
|
||||
|
||||
---
|
||||
|
||||
## 🔍 迁移映射表
|
||||
|
||||
### 重要文档迁移路径
|
||||
|
||||
| 原文件 | 新位置 | 说明 |
|
||||
|--------|--------|------|
|
||||
| QUICK_START.md | archive/deprecated/ | 已废弃,使用新版 |
|
||||
| K8S-DEPLOYMENT-GUIDE.md | docs/03-deployment/kubernetes/ | 重命名为helm-deployment.md |
|
||||
| DATA_FLOW_DASHBOARD_*.md | docs/05-features/health-monitoring/ | 数据流监控文档 |
|
||||
| OBSERVABILITY_IMPLEMENTATION.md | docs/02-architecture/observability.md | 架构文档 |
|
||||
| *FIX*.md | archive/2025/fixes/ | 历史修复记录 |
|
||||
| *IMPLEMENTATION*.md | archive/2025/implementations/ | 实施记录 |
|
||||
|
||||
### 完整映射
|
||||
|
||||
详见 `scripts/migrate-docs.sh` 中的迁移规则。
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 迁移前
|
||||
|
||||
1. **备份**: 脚本会自动备份,但建议手动备份重要文档
|
||||
2. **Git提交**: 建议在干净的工作区执行(无未提交变更)
|
||||
3. **团队通知**: 如果多人协作,通知团队成员文档结构变更
|
||||
|
||||
### 迁移后
|
||||
|
||||
1. **链接检查**: 检查文档内部链接是否需要更新
|
||||
2. **外部链接**: 更新外部引用(Wiki、文档站点、README badges等)
|
||||
3. **搜索引擎**: 如有文档站点,提交新的sitemap
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 故障排查
|
||||
|
||||
### Q1: 迁移脚本报错"目录不存在"
|
||||
|
||||
```bash
|
||||
# 手动创建目录结构
|
||||
mkdir -p docs/{01-getting-started,02-architecture,03-deployment/{docker,kubernetes,gitops},04-operations/{database,monitoring,troubleshooting},05-features/{health-monitoring,geofence,multi-tenant},06-development/{backend,frontend,api},07-compliance,08-reference}
|
||||
mkdir -p archive/{2025/{fixes,implementations,experiments},deprecated/old-quick-starts}
|
||||
|
||||
# 重新运行迁移
|
||||
./scripts/migrate-docs.sh
|
||||
```
|
||||
|
||||
### Q2: 某些文档没有迁移
|
||||
|
||||
检查 `backup_docs_*` 目录中的备份,手动移动到正确位置。
|
||||
|
||||
### Q3: 链接失效
|
||||
|
||||
更新文档内的相对链接路径,例如:
|
||||
- `[链接](QUICK_START.md)` → `[链接](docs/01-getting-started/quick-start-docker.md)`
|
||||
|
||||
---
|
||||
|
||||
## 📊 预期效果
|
||||
|
||||
| 指标 | 迁移前 | 迁移后 | 改善 |
|
||||
|-----|--------|--------|------|
|
||||
| 根目录文档 | 57 | ≤10 | -82% |
|
||||
| README行数 | 1844 | 258 | -86% |
|
||||
| 文档分类 | 混乱 | 8个清晰分类 | ✅ |
|
||||
| 查找时间 | 5-10分钟 | <1分钟 | -80% |
|
||||
| 维护成本 | 高 | 低 | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 📞 获取帮助
|
||||
|
||||
- **迁移问题**: 查看 [DOCUMENTATION_REFACTORING_PLAN.md](DOCUMENTATION_REFACTORING_PLAN.md)
|
||||
- **脚本问题**: 查看 `scripts/migrate-docs.sh` 源码
|
||||
- **文档规范**: 查看 [CONTRIBUTING.md](CONTRIBUTING.md)
|
||||
|
||||
---
|
||||
|
||||
## ✅ 验收标准
|
||||
|
||||
- [ ] 根目录≤10个markdown文件
|
||||
- [ ] README.md ≤300行
|
||||
- [ ] docs/目录有8个分类
|
||||
- [ ] 每个分类有README.md导航
|
||||
- [ ] archive/目录包含历史文档
|
||||
- [ ] CHANGELOG.md记录迁移
|
||||
- [ ] 文档链接可达(无404)
|
||||
|
||||
---
|
||||
|
||||
**开始迁移**: `./scripts/migrate-docs.sh` 🚀
|
||||
|
||||
**预计时间**: 40分钟(自动化5分钟 + 验证10分钟 + 更新25分钟)
|
||||
@@ -1,191 +0,0 @@
|
||||
# AI 受控开发蓝图 Prompt v1.0
|
||||
|
||||
> **适用范围**:本蓝图主要面向全栈/后端开发场景(Spring Boot/Python + K8s + GitOps)。
|
||||
>
|
||||
> 当前项目为纯前端 Vue3 应用,如需扩展后端服务时请参考本蓝图。
|
||||
|
||||
---
|
||||
|
||||
你是一名"可落地的资深全栈/平台工程师",在一个已经具备 GitOps 和可观测性的工程体系中交付功能。你必须遵循以下工程规则与交付标准。
|
||||
|
||||
## 0. 项目目标
|
||||
|
||||
- 在不破坏现网稳定性的前提下,快速交付业务功能。
|
||||
- 所有变更必须可追溯、可回滚、可观测。
|
||||
- 研发流程以 **OpenAPI 契约** 为事实源,以 **GitOps(Argo CD)** 为发布入口。
|
||||
|
||||
---
|
||||
|
||||
## 1. 技术栈与运行环境(不可更改)
|
||||
|
||||
- **CD**:Argo CD(GitOps),部署目标为欧洲节点或 Mac Studio 的 k3s 集群
|
||||
- **CI**:GitHub Actions(优先 hosted runner),除非明确要求使用 self-host/ARC
|
||||
- **可观测性**:Grafana + Loki + Tempo + 原生 Prometheus(K8s 部署,ConfigMap 挂载 prometheus.yml)
|
||||
- **数据库**:Postgres 自建(推荐)或 MySQL 8.0+(**例外说明**:已有项目可豁免,需满足迁移成本过高 >40h 且现有技术栈满足需求的条件),统一在 infra namespace 复用(应用侧"独立 DB + 独立用户 + Secret"隔离)
|
||||
- **缓存/队列**:Redis(统一监控,应用使用独立前缀/库/ACL 或独立实例,按规范)
|
||||
- **后端**:Spring Boot 或 Python(FastAPI/Flask)
|
||||
- **前端**:Vue3 + Vite(或现有栈不改变)
|
||||
|
||||
---
|
||||
|
||||
## 2. 工作方式(强制)
|
||||
|
||||
### 2.1 OpenAPI 是接口事实源
|
||||
|
||||
- 新增/修改接口必须同时更新 `openapi.yaml`(或等价文件)。
|
||||
- 后端实现必须严格符合 OpenAPI:字段名、类型、枚举、错误码、分页等。
|
||||
- 不允许"实现先行、文档滞后"。
|
||||
|
||||
### 2.2 交付必须包含(缺一不可)
|
||||
|
||||
对任何一个功能需求,你的输出必须包含:
|
||||
|
||||
1. **OpenAPI 变更**(如有)
|
||||
2. **后端实现**(controller/service/repository 等)
|
||||
3. **数据库迁移脚本**(如涉及数据结构变更)
|
||||
4. **最低限度的测试**(单测/集成测试二选一,按模块合理)
|
||||
5. **可观测性改造**(日志 + 链路 + 指标,至少做到可定位)
|
||||
6. **GitOps 部署变更**(helm values/kustomize/manifests)
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据库版本化与发布规则(强制)
|
||||
|
||||
### 3.1 迁移工具
|
||||
|
||||
- 使用 **Flyway**(默认)或 **Liquibase**(如项目已用且不能改)。
|
||||
- 迁移脚本只允许 **追加**,禁止修改已发布脚本。
|
||||
|
||||
### 3.2 迁移流程(必须)
|
||||
|
||||
- 发布顺序固定:**Migration Job(PreSync)→ 应用部署(rollout)**
|
||||
- 迁移必须幂等、可重试,并避免并发(加锁)。
|
||||
|
||||
### 3.3 平滑升级铁律(Expand / Contract)
|
||||
|
||||
线上结构变更必须向后兼容:
|
||||
|
||||
- **新增列**:先允许 NULL → 应用兼容读写 → 回填 → 最后加约束/NOT NULL
|
||||
- **改类型/语义**:新列 + 双写 + 回填 + 切读 + 删除旧列(最后)
|
||||
- **删除字段/表**:永远最后做(Contract)
|
||||
- **生产回滚策略默认**:回滚应用版本 + 前滚修复,不依赖 down SQL。
|
||||
- **必须假设**:Postgres 已具备备份与 PITR(时间点恢复)兜底。
|
||||
|
||||
---
|
||||
|
||||
## 4. 可观测性硬性要求(强制)
|
||||
|
||||
### 4.1 日志(Logs)
|
||||
|
||||
- 所有服务输出结构化日志(建议 JSON)。
|
||||
- 日志必须包含:
|
||||
- `trace_id`(统一字段名)
|
||||
- `service`、`env`、`namespace`、`pod`(至少 service/env)
|
||||
- 关键业务字段(如 tenant/org/user)需审慎,避免敏感信息泄露
|
||||
- 任何错误必须有明确 `error message + stacktrace`(可控脱敏)。
|
||||
|
||||
### 4.2 链路(Traces)
|
||||
|
||||
- 所有入口请求必须产生 trace。
|
||||
- trace 必须包含关键 spans:
|
||||
- HTTP server span
|
||||
- DB spans(SQL/JDBC)
|
||||
- Redis spans
|
||||
- 外部调用 spans(HTTP client 等)
|
||||
- **目标**:能从一条错误日志跳到对应 trace(Grafana Loki ↔ Tempo 已联动)。
|
||||
|
||||
### 4.3 指标(Metrics)
|
||||
|
||||
- 必须暴露 Prometheus metrics endpoint:
|
||||
- Spring Boot:`/actuator/prometheus`
|
||||
- Python:`/metrics`
|
||||
- 必须具备 **Golden Signals**:
|
||||
- RPS、错误率、延迟(p95/p99)、饱和度(连接池/线程池/队列)
|
||||
- **严禁引入高基数 labels**(tenant_id/user_id 默认不能作为 metrics label)。
|
||||
|
||||
---
|
||||
|
||||
## 5. 部署与配置规则(强制)
|
||||
|
||||
- 应用配置通过 ConfigMap/Secret 注入(12-factor 风格)。
|
||||
- 生产环境敏感信息只放 Secret,不写进镜像、不写进 repo。
|
||||
- 发布只允许通过 **GitOps(Argo CD)**,CI 不直接操作生产集群 kubeconfig(避免越权与 approve 地狱)。
|
||||
- 数据库/Redis 属于 infra:应用不负责部署 infra(除非明确要求)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 输出格式规范(你必须这样交付)
|
||||
|
||||
当我给你一个需求时,你的输出必须按以下结构:
|
||||
|
||||
### 1. 变更概览
|
||||
- 涉及模块、接口、数据库、配置、部署、监控点
|
||||
|
||||
### 2. 文件级变更清单
|
||||
- 逐文件列出新增/修改/删除(含路径)
|
||||
|
||||
### 3. OpenAPI
|
||||
- 贴出新增/修改片段(或完整文件差异)
|
||||
|
||||
### 4. 数据库迁移
|
||||
- `db/migration/...sql` 内容
|
||||
- Expand/Contract 说明(如涉及破坏性风险)
|
||||
|
||||
### 5. 后端代码
|
||||
- 关键类/函数代码(可贴完整文件或明确 diff)
|
||||
|
||||
### 6. 测试
|
||||
- 至少一条可运行的测试(含命令)
|
||||
|
||||
### 7. 可观测性
|
||||
- 日志字段、trace spans、metrics 名称与标签策略
|
||||
|
||||
### 8. 部署(GitOps)
|
||||
- manifests/values 变更
|
||||
|
||||
### 9. 验收步骤
|
||||
- 本地/CI/集群三段验证方法(含 PromQL/日志查询关键词/trace 验证)
|
||||
|
||||
---
|
||||
|
||||
## 7. 禁止事项(踩了就算失败)
|
||||
|
||||
- ❌ 不允许绕过 OpenAPI 直接改接口
|
||||
- ❌ 不允许上线破坏性 DB 变更(删列、改类型、强制 NOT NULL)且未走 Expand/Contract
|
||||
- ❌ 不允许在 CI 里拿生产 kubeconfig 直接部署
|
||||
- ❌ 不允许输出"待补充/ TODO / 以后再说"
|
||||
- ❌ 不允许把敏感信息写进代码仓库
|
||||
- ❌ 不允许为了方便把 metrics label 加成 tenant_id/user_id 这类高基数字段
|
||||
|
||||
---
|
||||
|
||||
## 8. 任务执行模式(你要像这样做)
|
||||
|
||||
- 如果信息不足:优先给出合理默认,并明确写出默认假设;不要反复提问拖慢节奏。
|
||||
- 先产出可落地的最小闭环(接口→实现→迁移→观测→部署→验收),再做增强项。
|
||||
|
||||
---
|
||||
|
||||
## 结束:等待需求输入
|
||||
|
||||
现在请我提供:
|
||||
|
||||
- 需求描述(用户故事/功能点)
|
||||
- 相关仓库目录结构(或关键文件)
|
||||
- 现有 `openapi.yaml`(如已存在)
|
||||
|
||||
你将按上述规范一次性产出交付内容。
|
||||
|
||||
---
|
||||
|
||||
## 建议用法(实际怎么贴给 Claude/Codex)
|
||||
|
||||
1. 先贴上面这份 Prompt(v1.0)
|
||||
2. 再贴本次任务(例如:"新增接口 /health_data/all 的过滤参数…")
|
||||
3. 再贴你给它的上下文(openapi.yaml、相关代码片段、目录树、部署目录)
|
||||
|
||||
---
|
||||
|
||||
## 版本历史
|
||||
|
||||
- **v1.0** (2025-12-20): 初始版本,定义全栈开发规范与交付标准
|
||||
File diff suppressed because it is too large
Load Diff
Executable
+98
@@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
# 重新标记并推送 java-maven-otel 基础镜像到统一路径
|
||||
# 用途:将已构建的 ljwx/java-maven-otel 镜像重新标记为 ljwx-base-images/java-maven-otel
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 配置
|
||||
REGISTRY="${PRIVATE_REGISTRY:-harbor.omniverseai.net}"
|
||||
OLD_PATH="ljwx/java-maven-otel"
|
||||
NEW_PATH="ljwx-base-images/java-maven-otel"
|
||||
OTEL_VERSION="2.11.0"
|
||||
|
||||
echo -e "${BLUE}=========================================${NC}"
|
||||
echo -e "${BLUE}🏷️ 重新标记 Java Maven + OpenTelemetry 基础镜像${NC}"
|
||||
echo -e "${BLUE}=========================================${NC}"
|
||||
echo -e "${YELLOW}旧路径: $REGISTRY/$OLD_PATH${NC}"
|
||||
echo -e "${YELLOW}新路径: $REGISTRY/$NEW_PATH${NC}"
|
||||
echo ""
|
||||
|
||||
# 检测当前架构
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64)
|
||||
ARCH_TAG="amd64"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
ARCH_TAG="arm64"
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}❌ 不支持的架构: $ARCH${NC}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo -e "${YELLOW}📊 当前架构: $ARCH → $ARCH_TAG${NC}"
|
||||
echo ""
|
||||
|
||||
# 检查本地是否有镜像
|
||||
echo -e "${BLUE}🔍 检查本地镜像...${NC}"
|
||||
if ! docker images "$REGISTRY/$OLD_PATH" | grep -q "21-alpine"; then
|
||||
echo -e "${RED}❌ 本地未找到镜像: $REGISTRY/$OLD_PATH:21-alpine${NC}"
|
||||
echo -e "${YELLOW}提示: 请先运行 ./build-java-maven-otel.sh 构建镜像${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ 找到本地镜像${NC}"
|
||||
echo ""
|
||||
|
||||
# 重新标记镜像
|
||||
echo -e "${BLUE}🏷️ 重新标记镜像...${NC}"
|
||||
|
||||
docker tag $REGISTRY/$OLD_PATH:21-alpine $REGISTRY/$NEW_PATH:21-alpine
|
||||
docker tag $REGISTRY/$OLD_PATH:21-alpine $REGISTRY/$NEW_PATH:21-alpine-${ARCH_TAG}
|
||||
docker tag $REGISTRY/$OLD_PATH:21-alpine $REGISTRY/$NEW_PATH:21-otel-${OTEL_VERSION}
|
||||
docker tag $REGISTRY/$OLD_PATH:21-alpine $REGISTRY/$NEW_PATH:latest
|
||||
|
||||
echo -e "${GREEN}✅ 镜像重新标记完成${NC}"
|
||||
echo ""
|
||||
|
||||
# 推送镜像到 Harbor
|
||||
echo -e "${BLUE}📤 推送镜像到 Harbor...${NC}"
|
||||
|
||||
docker push $REGISTRY/$NEW_PATH:21-alpine
|
||||
docker push $REGISTRY/$NEW_PATH:21-alpine-${ARCH_TAG}
|
||||
docker push $REGISTRY/$NEW_PATH:21-otel-${OTEL_VERSION}
|
||||
docker push $REGISTRY/$NEW_PATH:latest
|
||||
|
||||
echo -e "${GREEN}✅ 镜像推送完成${NC}"
|
||||
echo ""
|
||||
|
||||
echo -e "${GREEN}=========================================${NC}"
|
||||
echo -e "${GREEN}🎉 基础镜像重新标记并推送完成!${NC}"
|
||||
echo -e "${GREEN}=========================================${NC}"
|
||||
echo ""
|
||||
echo "镜像信息 (架构: $ARCH_TAG):"
|
||||
echo " - $REGISTRY/$NEW_PATH:21-alpine"
|
||||
echo " - $REGISTRY/$NEW_PATH:21-alpine-${ARCH_TAG}"
|
||||
echo " - $REGISTRY/$NEW_PATH:21-otel-${OTEL_VERSION}"
|
||||
echo " - $REGISTRY/$NEW_PATH:latest"
|
||||
echo ""
|
||||
echo "OpenTelemetry Java Agent:"
|
||||
echo " - 版本: $OTEL_VERSION"
|
||||
echo " - 路径: /opt/opentelemetry-javaagent.jar"
|
||||
echo ""
|
||||
echo "使用方法(在业务 Dockerfile 中):"
|
||||
echo " FROM $REGISTRY/$NEW_PATH:21-alpine AS builder"
|
||||
echo " # OpenTelemetry Agent 已预置在 /opt/opentelemetry-javaagent.jar"
|
||||
echo ""
|
||||
echo "验证镜像:"
|
||||
echo " docker pull $REGISTRY/$NEW_PATH:21-alpine"
|
||||
echo ""
|
||||
@@ -0,0 +1,551 @@
|
||||
# LJWX Health CI/CD 工作流
|
||||
|
||||
**适用范围**:本地 Gitea 仓库 + Argo CD 部署
|
||||
|
||||
---
|
||||
|
||||
## 📋 架构概述
|
||||
|
||||
LJWX Health 使用 **Gitea Actions + Argo CD** 实现 GitOps 工作流:
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ 开发者 │
|
||||
│ git push │
|
||||
│ local main │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ Gitea Actions │
|
||||
│ (.gitea/workflows/ci.yml) │
|
||||
│ │
|
||||
│ 1. 测试 (test-*) │
|
||||
│ 2. 构建镜像 (build-push) │
|
||||
│ 3. 推送到Harbor │
|
||||
│ 4. 更新ljwx-deploy仓库 │
|
||||
└────────┬────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ ljwx-deploy 仓库 │
|
||||
│ (GitOps配置仓库) │
|
||||
│ │
|
||||
│ apps/ljwx-health/overlays/ │
|
||||
│ ├── ljwx-boot/ │
|
||||
│ ├── ljwx-admin/ │
|
||||
│ └── ljwx-bigscreen/ │
|
||||
│ └── kustomization.yaml │
|
||||
└────────┬────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ Argo CD │
|
||||
│ (监控ljwx-deploy仓库) │
|
||||
│ │
|
||||
│ 检测到kustomization.yaml │
|
||||
│ 变更后自动同步到K3s │
|
||||
└────────┬────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ K3s Cluster │
|
||||
│ (ljwx-health namespace) │
|
||||
│ │
|
||||
│ Deployments更新 │
|
||||
│ └── 滚动部署新镜像 │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
**关键分离**:
|
||||
- **CI(Gitea Actions)**:代码测试、镜像构建、GitOps仓库更新
|
||||
- **CD(Argo CD)**:监控GitOps仓库、自动部署到K3s
|
||||
|
||||
---
|
||||
|
||||
## 🚀 开发者工作流
|
||||
|
||||
### 日常开发
|
||||
|
||||
```bash
|
||||
# 1. 在 feature 分支开发
|
||||
git checkout -b feature/new-feature
|
||||
|
||||
# 2. 本地测试
|
||||
cd ljwx-boot && ./run-local.sh
|
||||
cd ljwx-admin && pnpm dev
|
||||
cd ljwx-bigscreen && python run.py
|
||||
|
||||
# 3. 提交代码
|
||||
git add .
|
||||
git commit -m "feat: add new feature"
|
||||
|
||||
# 4. 推送到 Gitea(触发 CI/CD)
|
||||
git push local main
|
||||
```
|
||||
|
||||
**自动触发**:
|
||||
- ✅ Gitea Actions 自动运行 CI Pipeline
|
||||
- ✅ 测试通过后构建镜像推送到 Harbor
|
||||
- ✅ 更新 ljwx-deploy 仓库的镜像标签
|
||||
- ✅ Argo CD 检测到变更,自动部署到 K3s
|
||||
|
||||
---
|
||||
|
||||
## 📝 CI Pipeline 详解
|
||||
|
||||
### Workflow 文件
|
||||
|
||||
**位置**:`.gitea/workflows/ci.yml`
|
||||
|
||||
### 触发条件
|
||||
|
||||
```yaml
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
```
|
||||
|
||||
**说明**:
|
||||
- `push` 到 `main` 分支:完整 CI/CD(测试 + 构建 + 部署)
|
||||
- `pull_request`:仅测试和构建验证(不推送镜像)
|
||||
|
||||
### Job 1: 测试 ljwx-boot
|
||||
|
||||
**Runner**: `ubuntu-latest` (容器)
|
||||
**基础镜像**: `harbor.omniverseai.net/ljwx-base-images/maven3.9-jdk21:latest`
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- 构建 ljwx-boot-starter(依赖)
|
||||
- 运行 Checkstyle(代码质量检查)
|
||||
- 运行单元测试 + JaCoCo 覆盖率
|
||||
- 构建 JAR 包
|
||||
```
|
||||
|
||||
### Job 2: 测试 ljwx-admin
|
||||
|
||||
**Runner**: `ubuntu-latest` (容器)
|
||||
**基础镜像**: `harbor.omniverseai.net/ljwx-base-images/node20-pnpm:latest`
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- pnpm install(依赖安装)
|
||||
- ESLint(代码检查)
|
||||
- TypeScript类型检查
|
||||
- 单元测试 + 覆盖率报告
|
||||
```
|
||||
|
||||
### Job 3: 测试 ljwx-bigscreen
|
||||
|
||||
**Runner**: `ubuntu-latest` (容器)
|
||||
**基础镜像**: `harbor.omniverseai.net/ljwx-base-images/python3.12-pip:latest`
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uv pip install(依赖安装)
|
||||
- Ruff Linter(代码检查)
|
||||
- Black格式化检查
|
||||
- Pytest + 覆盖率报告
|
||||
- Safety安全检查
|
||||
```
|
||||
|
||||
### Job 4: 安全扫描
|
||||
|
||||
**Runner**: `docker-builder` (self-hosted)
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- Trivy扫描 ljwx-boot
|
||||
- Trivy扫描 ljwx-admin
|
||||
- Trivy扫描 ljwx-bigscreen
|
||||
- 生成安全报告(JSON格式)
|
||||
```
|
||||
|
||||
### Job 5: 构建并推送镜像
|
||||
|
||||
**Runner**: `docker-builder` (self-hosted)
|
||||
**依赖**: 所有测试 Job 必须通过
|
||||
**触发条件**: 仅 `push` 到 `main` 分支
|
||||
|
||||
```yaml
|
||||
strategy:
|
||||
matrix:
|
||||
component:
|
||||
- ljwx-boot
|
||||
- ljwx-admin
|
||||
- ljwx-bigscreen
|
||||
```
|
||||
|
||||
**镜像标签**:
|
||||
```bash
|
||||
main-<short_sha> # 例如: main-a1b2c3d
|
||||
latest # 始终指向最新 main 分支构建
|
||||
```
|
||||
|
||||
**Dockerfile 路径**:
|
||||
- ljwx-boot: `ljwx-boot/ljwx-boot-admin/Dockerfile.gitea`
|
||||
- ljwx-admin: `ljwx-admin/Dockerfile.gitea`
|
||||
- ljwx-bigscreen: `ljwx-bigscreen/Dockerfile.gitea`
|
||||
|
||||
**推送目标**:
|
||||
```
|
||||
harbor.omniverseai.net/ljwx-health/ljwx-boot:main-a1b2c3d
|
||||
harbor.omniverseai.net/ljwx-health/ljwx-admin:main-a1b2c3d
|
||||
harbor.omniverseai.net/ljwx-health/ljwx-bigscreen:main-a1b2c3d
|
||||
```
|
||||
|
||||
### Job 6: 更新 GitOps 仓库
|
||||
|
||||
**Runner**: `ubuntu-latest`
|
||||
**依赖**: 构建推送 Job 完成
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- 克隆 ljwx-deploy 仓库
|
||||
- 更新所有组件的 kustomization.yaml:
|
||||
* apps/ljwx-health/overlays/ljwx-boot/kustomization.yaml
|
||||
* apps/ljwx-health/overlays/ljwx-admin/kustomization.yaml
|
||||
* apps/ljwx-health/overlays/ljwx-bigscreen/kustomization.yaml
|
||||
- 提交并推送到 ljwx-deploy 仓库
|
||||
```
|
||||
|
||||
**kustomization.yaml 示例**:
|
||||
```yaml
|
||||
# apps/ljwx-health/overlays/ljwx-boot/kustomization.yaml
|
||||
images:
|
||||
- name: harbor.omniverseai.net/ljwx-health/ljwx-boot
|
||||
newTag: "main-a1b2c3d" # CI 自动更新这一行
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Argo CD 部署流程
|
||||
|
||||
### Argo CD 职责
|
||||
|
||||
1. **监控 ljwx-deploy 仓库**:
|
||||
- 检测到 `kustomization.yaml` 变更
|
||||
- 自动触发同步
|
||||
|
||||
2. **自动部署到 K3s**:
|
||||
- 拉取新镜像标签
|
||||
- 滚动更新 Deployment
|
||||
- 健康检查
|
||||
|
||||
3. **状态同步**:
|
||||
- 确保集群状态与 Git 仓库一致
|
||||
- 自动修复配置漂移
|
||||
|
||||
### Argo CD 配置
|
||||
|
||||
**Application 配置位置**:
|
||||
```
|
||||
ljwx-deploy/apps/ljwx-health/application.yaml
|
||||
```
|
||||
|
||||
**自动同步策略**:
|
||||
```yaml
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true # 自动删除不再需要的资源
|
||||
selfHeal: true # 自动修复配置漂移
|
||||
allowEmpty: false
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
```
|
||||
|
||||
### 查看 Argo CD 状态
|
||||
|
||||
**方法 1: Argo CD UI**
|
||||
```bash
|
||||
# 访问 Argo CD Web 界面
|
||||
# URL: https://argocd.your-domain.com
|
||||
# 查看 ljwx-health Application 状态
|
||||
```
|
||||
|
||||
**方法 2: CLI**
|
||||
```bash
|
||||
# 查看应用状态
|
||||
argocd app get ljwx-health
|
||||
|
||||
# 查看同步历史
|
||||
argocd app history ljwx-health
|
||||
|
||||
# 手动触发同步(通常不需要)
|
||||
argocd app sync ljwx-health
|
||||
```
|
||||
|
||||
**方法 3: kubectl**
|
||||
```bash
|
||||
# 检查 Deployment 状态
|
||||
kubectl get deployments -n ljwx-health
|
||||
|
||||
# 查看 Pod 状态
|
||||
kubectl get pods -n ljwx-health
|
||||
|
||||
# 查看部署历史
|
||||
kubectl rollout history deployment/ljwx-boot -n ljwx-health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 必需的 Secrets
|
||||
|
||||
在 Gitea 仓库中配置以下 Secrets:
|
||||
|
||||
**配置路径**:
|
||||
```
|
||||
Gitea仓库 → Settings → Secrets → Add secret
|
||||
```
|
||||
|
||||
| Secret Name | 描述 | 用途 |
|
||||
|------------|------|------|
|
||||
| `HARBOR_USERNAME` | Harbor用户名 | 推送镜像到Harbor |
|
||||
| `HARBOR_PASSWORD` | Harbor密码 | 推送镜像到Harbor |
|
||||
| `DEPLOY_REPO_TOKEN` | ljwx-deploy仓库访问token | 更新GitOps仓库 |
|
||||
|
||||
**生成 DEPLOY_REPO_TOKEN**:
|
||||
```bash
|
||||
# Gitea UI:
|
||||
# Settings → Applications → Generate New Token
|
||||
# Scopes: repo (read/write)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 版本命名规则
|
||||
|
||||
### 镜像标签格式
|
||||
|
||||
```bash
|
||||
main-<short_sha> # 基于 git commit SHA
|
||||
```
|
||||
|
||||
**示例**:
|
||||
```bash
|
||||
# Git commit: a1b2c3d4e5f6g7h8i9j0
|
||||
# 镜像标签: main-a1b2c3d
|
||||
harbor.omniverseai.net/ljwx-health/ljwx-boot:main-a1b2c3d
|
||||
```
|
||||
|
||||
**优势**:
|
||||
- ✅ 唯一标识每次构建
|
||||
- ✅ 可追溯到具体 commit
|
||||
- ✅ 支持回滚到任意版本
|
||||
|
||||
---
|
||||
|
||||
## 🐛 常见问题排查
|
||||
|
||||
### 问题 1: CI 构建失败 - 基础镜像拉取失败
|
||||
|
||||
**症状**:
|
||||
```
|
||||
Error response from daemon: pull access denied for harbor.omniverseai.net/ljwx-base-images/java-maven-otel
|
||||
```
|
||||
|
||||
**原因**:基础镜像不存在或 Harbor 认证失败
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 验证基础镜像是否存在
|
||||
docker pull harbor.omniverseai.net/ljwx-base-images/java-maven-otel:21-alpine
|
||||
|
||||
# 2. 检查 Harbor Secrets
|
||||
# Gitea UI → Settings → Secrets
|
||||
|
||||
# 3. 重新推送基础镜像
|
||||
cd docker/base-images
|
||||
./build-java-maven-otel.sh
|
||||
```
|
||||
|
||||
### 问题 2: Argo CD 未自动部署
|
||||
|
||||
**症状**:ljwx-deploy 仓库已更新,但 K3s 未部署新镜像
|
||||
|
||||
**排查步骤**:
|
||||
```bash
|
||||
# 1. 检查 Argo CD Application 状态
|
||||
argocd app get ljwx-health
|
||||
|
||||
# 2. 查看同步状态
|
||||
kubectl get application ljwx-health -n argocd -o yaml
|
||||
|
||||
# 3. 检查 Argo CD Controller 日志
|
||||
kubectl logs -n argocd deployment/argocd-application-controller
|
||||
|
||||
# 4. 手动触发同步
|
||||
argocd app sync ljwx-health --force
|
||||
```
|
||||
|
||||
**常见原因**:
|
||||
- Argo CD 自动同步被禁用
|
||||
- ljwx-deploy 仓库访问权限问题
|
||||
- kustomization.yaml 语法错误
|
||||
|
||||
### 问题 3: 镜像构建成功但部署失败
|
||||
|
||||
**症状**:镜像推送到 Harbor 成功,但 Pod 无法拉取镜像
|
||||
|
||||
**排查步骤**:
|
||||
```bash
|
||||
# 1. 检查 Pod 事件
|
||||
kubectl describe pod <pod-name> -n ljwx-health
|
||||
|
||||
# 2. 检查 ImagePullSecrets
|
||||
kubectl get secret -n ljwx-health | grep harbor
|
||||
|
||||
# 3. 验证镜像存在
|
||||
docker pull harbor.omniverseai.net/ljwx-health/ljwx-boot:main-a1b2c3d
|
||||
|
||||
# 4. 检查 Harbor 仓库权限
|
||||
# Harbor UI → ljwx-health project → Members
|
||||
```
|
||||
|
||||
### 问题 4: 测试 Job 失败
|
||||
|
||||
**ljwx-boot 测试失败**:
|
||||
```bash
|
||||
# 检查 Maven 依赖
|
||||
cd ljwx-boot
|
||||
mvn dependency:tree
|
||||
|
||||
# 清理本地缓存重试
|
||||
mvn clean test -U
|
||||
```
|
||||
|
||||
**ljwx-admin 测试失败**:
|
||||
```bash
|
||||
# 检查 pnpm lock 文件
|
||||
cd ljwx-admin
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
# 类型检查
|
||||
pnpm typecheck
|
||||
```
|
||||
|
||||
**ljwx-bigscreen 测试失败**:
|
||||
```bash
|
||||
# 检查 Python 依赖
|
||||
cd ljwx-bigscreen
|
||||
uv pip install -r requirements.txt
|
||||
|
||||
# 运行测试
|
||||
pytest -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 部署回滚
|
||||
|
||||
### 方法 1: 通过 Argo CD
|
||||
|
||||
```bash
|
||||
# 1. 查看部署历史
|
||||
argocd app history ljwx-health
|
||||
|
||||
# 2. 回滚到指定版本
|
||||
argocd app rollback ljwx-health <revision-id>
|
||||
```
|
||||
|
||||
### 方法 2: 通过 kubectl
|
||||
|
||||
```bash
|
||||
# 1. 查看 Deployment 历史
|
||||
kubectl rollout history deployment/ljwx-boot -n ljwx-health
|
||||
|
||||
# 2. 回滚到上一个版本
|
||||
kubectl rollout undo deployment/ljwx-boot -n ljwx-health
|
||||
|
||||
# 3. 回滚到指定版本
|
||||
kubectl rollout undo deployment/ljwx-boot -n ljwx-health --to-revision=2
|
||||
```
|
||||
|
||||
### 方法 3: 通过 Git(推荐)
|
||||
|
||||
```bash
|
||||
# 1. 克隆 ljwx-deploy 仓库
|
||||
git clone http://192.168.1.83:33000/gao/ljwx-deploy.git
|
||||
|
||||
# 2. 回滚 kustomization.yaml 到旧版本
|
||||
cd ljwx-deploy/apps/ljwx-health/overlays/ljwx-boot
|
||||
git log kustomization.yaml # 查看历史提交
|
||||
|
||||
# 3. 恢复到指定版本
|
||||
git checkout <commit-hash> kustomization.yaml
|
||||
|
||||
# 4. 提交并推送
|
||||
git commit -m "rollback: revert ljwx-boot to main-abc1234"
|
||||
git push origin main
|
||||
|
||||
# 5. Argo CD 会自动检测并部署旧版本
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
### 核心文档
|
||||
- [自定义基础镜像指南](../docker/custom-base-images.md)
|
||||
- [Kubernetes 部署指南](../kubernetes/deployment-guide.md)
|
||||
|
||||
### CI/CD 配置
|
||||
- `.gitea/workflows/ci.yml` - CI Pipeline 配置
|
||||
- `.gitea/workflows/README.md` - Workflow 说明
|
||||
|
||||
### Argo CD
|
||||
- `ljwx-deploy` 仓库 - GitOps 配置仓库
|
||||
- Argo CD Application 配置
|
||||
|
||||
### 故障排查
|
||||
- [OpenTelemetry 集成修复](../../09-fixes/opentelemetry-tempo-integration-fix.md)
|
||||
- [常见问题解答](../../04-operations/troubleshooting/common-issues.md)
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 重要注意事项
|
||||
|
||||
### 1. 远程仓库名称
|
||||
|
||||
**正确**:
|
||||
```bash
|
||||
git push local main ✅
|
||||
```
|
||||
|
||||
**错误**:
|
||||
```bash
|
||||
git push gitea main ❌ # 远程仓库名不是 gitea
|
||||
git push origin main ❌ # 远程仓库名不是 origin
|
||||
```
|
||||
|
||||
### 2. GitOps 仓库分离
|
||||
|
||||
- **ljwx-health**: 应用代码仓库(本仓库)
|
||||
- **ljwx-deploy**: GitOps 配置仓库(Argo CD 监控)
|
||||
|
||||
**不要**在 ljwx-health 仓库中直接修改 K8s 配置。
|
||||
|
||||
### 3. 镜像标签不可变
|
||||
|
||||
镜像标签格式 `main-<sha>` 确保不可变性:
|
||||
- ✅ 每次构建生成唯一标签
|
||||
- ✅ 避免 `:latest` 标签的不确定性
|
||||
- ✅ 支持精确回滚
|
||||
|
||||
### 4. Argo CD 自动同步
|
||||
|
||||
Argo CD 配置了自动同步,**通常不需要手动触发部署**。
|
||||
|
||||
如果需要立即部署:
|
||||
```bash
|
||||
argocd app sync ljwx-health --force
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**维护者**:运维团队
|
||||
**最后更新**:2026-01-05
|
||||
**基于 CI/CD 版本**:`.gitea/workflows/ci.yml` (真实配置)
|
||||
@@ -1,575 +0,0 @@
|
||||
# Gitea GitOps 工作流指南
|
||||
|
||||
**⚠️ 重要说明**:本文档描述的 GitOps 流程**仅适用于**:
|
||||
- ✅ **Gitea Actions** workflow(`.gitea/workflows/gitops-deploy.yml`)
|
||||
- ✅ **本地 Gitea 仓库**:`http://192.168.1.83:33000/gao/ljwx-health`
|
||||
|
||||
**不适用于**:
|
||||
- ❌ GitHub Actions(GitHub 使用不同的 workflow 配置)
|
||||
- ❌ 其他 Git 托管平台
|
||||
|
||||
---
|
||||
|
||||
## 📋 概述
|
||||
|
||||
LJWX Health 使用 Gitea Actions 实现完整的 GitOps 工作流,从代码提交到 Kubernetes 部署全自动化。
|
||||
|
||||
### 核心优势
|
||||
|
||||
- ✅ **全自动部署**:git push 触发完整 CI/CD 流程
|
||||
- ✅ **ARM64 优化**:针对本地 ARM64 集群优化构建
|
||||
- ✅ **基础设施集成**:自动部署 Redis、MySQL、Grafana
|
||||
- ✅ **健康检查**:部署后自动验证服务状态
|
||||
- ✅ **数据库迁移**:Flyway 自动化 schema 管理
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ 架构图
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Git Push │
|
||||
│ (Gitea) │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Gitea Actions │
|
||||
│ (Self-hosted │
|
||||
│ ARM64 Runner) │
|
||||
└────────┬────────┘
|
||||
│
|
||||
├─────────────────────────────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│ Build Images │ │ Deploy to K3s │
|
||||
│ (ARM64 Only) │ │ (Helm) │
|
||||
│ │ │ │
|
||||
│ - ljwx-boot │ │ - Redis (infra) │
|
||||
│ - ljwx-admin │ │ - MySQL (infra) │
|
||||
│ - ljwx-bigscreen│ │ - ljwx-health │
|
||||
└────────┬────────┘ └────────┬────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│ Push to Harbor │ │ Health Check │
|
||||
│ (ARM64 Images) │ │ + Report │
|
||||
└─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 使用方法
|
||||
|
||||
### 方式 1: 自动触发(推荐)
|
||||
|
||||
**推送到 main 分支触发生产部署**:
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat: add new feature"
|
||||
git push gitea main # 自动触发 GitOps 部署
|
||||
```
|
||||
|
||||
**推送到 develop 分支触发开发环境部署**:
|
||||
```bash
|
||||
git push gitea develop # 部署到开发环境
|
||||
```
|
||||
|
||||
**打 tag 触发版本发布**:
|
||||
```bash
|
||||
git tag v2.0.4
|
||||
git push gitea main --tags # 自动部署版本 v2.0.4
|
||||
```
|
||||
|
||||
### 方式 2: 手动触发
|
||||
|
||||
1. 访问 Gitea 仓库:`http://192.168.1.83:33000/gao/ljwx-health`
|
||||
2. 点击 **Actions** 标签
|
||||
3. 选择 **Gitea GitOps Deploy to K3s (ARM64)**
|
||||
4. 点击 **Run workflow**
|
||||
5. 可选参数:
|
||||
- `skip_build`: 跳过镜像构建(仅部署已有镜像)
|
||||
- `skip_redis`: 跳过 Redis 部署
|
||||
- `version`: 指定镜像版本(如 `dev-20260105-120000`)
|
||||
|
||||
---
|
||||
|
||||
## 📝 Workflow 配置
|
||||
|
||||
### 文件位置
|
||||
|
||||
```
|
||||
.gitea/workflows/gitops-deploy.yml
|
||||
```
|
||||
|
||||
### 触发条件
|
||||
|
||||
```yaml
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
skip_build:
|
||||
description: '跳过镜像构建'
|
||||
required: false
|
||||
default: 'false'
|
||||
skip_redis:
|
||||
description: '跳过Redis部署'
|
||||
required: false
|
||||
default: 'false'
|
||||
version:
|
||||
description: '镜像版本(如 dev-20260105-120000)'
|
||||
required: false
|
||||
default: ''
|
||||
```
|
||||
|
||||
### Runner 要求
|
||||
|
||||
**必须使用 self-hosted ARM64 runner**:
|
||||
```yaml
|
||||
runs-on: [self-hosted, linux, ARM64]
|
||||
```
|
||||
|
||||
**为什么必须是 ARM64**:
|
||||
- ✅ 本地 K3s 集群运行在 ARM64 架构
|
||||
- ✅ 避免跨架构镜像问题
|
||||
- ✅ 优化构建速度(本地缓存)
|
||||
|
||||
---
|
||||
|
||||
## 🔧 核心构建步骤
|
||||
|
||||
### 1. 准备阶段
|
||||
|
||||
**检出代码**:
|
||||
```yaml
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # 获取完整历史(用于版本标签)
|
||||
```
|
||||
|
||||
**登录 Harbor**:
|
||||
```yaml
|
||||
- name: Login to Harbor
|
||||
run: |
|
||||
echo "${{ secrets.HARBOR_PASSWORD }}" | docker login harbor.omniverseai.net \
|
||||
-u "${{ secrets.HARBOR_USERNAME }}" --password-stdin
|
||||
```
|
||||
|
||||
### 2. 镜像构建
|
||||
|
||||
**ljwx-boot(Spring Boot)**:
|
||||
```yaml
|
||||
- name: Build ljwx-boot
|
||||
run: |
|
||||
docker build \
|
||||
-f ljwx-boot/ljwx-boot-admin/Dockerfile.gitea \
|
||||
-t harbor.omniverseai.net/ljwx-health/ljwx-boot:${VERSION} \
|
||||
--platform linux/arm64 \
|
||||
.
|
||||
docker push harbor.omniverseai.net/ljwx-health/ljwx-boot:${VERSION}
|
||||
```
|
||||
|
||||
**关键配置**:
|
||||
- ✅ 使用 `Dockerfile.gitea`(针对 Gitea 优化)
|
||||
- ✅ 基础镜像:`harbor.omniverseai.net/ljwx-base-images/java-maven-otel:21-alpine`
|
||||
- ✅ 包含 OpenTelemetry Java Agent(分布式追踪必需)
|
||||
- ✅ 仅构建 ARM64 架构
|
||||
|
||||
**ljwx-admin(Vue3 前端)**:
|
||||
```yaml
|
||||
- name: Build ljwx-admin
|
||||
run: |
|
||||
docker build \
|
||||
-f ljwx-admin/Dockerfile.gitea \
|
||||
-t harbor.omniverseai.net/ljwx-health/ljwx-admin:${VERSION} \
|
||||
--platform linux/arm64 \
|
||||
ljwx-admin/
|
||||
docker push harbor.omniverseai.net/ljwx-health/ljwx-admin:${VERSION}
|
||||
```
|
||||
|
||||
**ljwx-bigscreen(Flask 大屏)**:
|
||||
```yaml
|
||||
- name: Build ljwx-bigscreen
|
||||
run: |
|
||||
docker build \
|
||||
-f ljwx-bigscreen/Dockerfile.gitea \
|
||||
-t harbor.omniverseai.net/ljwx-health/ljwx-bigscreen:${VERSION} \
|
||||
--platform linux/arm64 \
|
||||
ljwx-bigscreen/
|
||||
docker push harbor.omniverseai.net/ljwx-health/ljwx-bigscreen:${VERSION}
|
||||
```
|
||||
|
||||
### 3. 基础设施部署
|
||||
|
||||
**部署 Redis(infra namespace)**:
|
||||
```yaml
|
||||
- name: Deploy Redis Infrastructure
|
||||
if: inputs.skip_redis != 'true'
|
||||
run: |
|
||||
kubectl create namespace infra --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# 创建 Secret
|
||||
kubectl create secret generic redis-secret \
|
||||
--from-literal=redis-password=${{ secrets.REDIS_PASSWORD }} \
|
||||
-n infra --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# 部署 Redis
|
||||
kubectl apply -f deploy/k8s/infra/redis-deployment.yaml
|
||||
kubectl apply -f deploy/k8s/infra/redis-service.yaml
|
||||
|
||||
# 等待 Ready
|
||||
kubectl wait --for=condition=ready pod -l app=redis -n infra --timeout=120s
|
||||
```
|
||||
|
||||
### 4. 应用部署(Helm)
|
||||
|
||||
**更新 values.yaml**:
|
||||
```yaml
|
||||
- name: Update Helm values
|
||||
run: |
|
||||
sed -i "s|tag:.*|tag: \"${VERSION}\"|g" deploy/helm/ljwx-health/values.yaml
|
||||
```
|
||||
|
||||
**Helm 部署**:
|
||||
```yaml
|
||||
- name: Deploy via Helm
|
||||
run: |
|
||||
helm upgrade --install ljwx-health deploy/helm/ljwx-health/ \
|
||||
--namespace ljwx-health \
|
||||
--create-namespace \
|
||||
--set ljwxBoot.image.tag=${VERSION} \
|
||||
--set ljwxAdmin.image.tag=${VERSION} \
|
||||
--set ljwxBigscreen.image.tag=${VERSION} \
|
||||
--set global.env=production \
|
||||
--wait \
|
||||
--timeout=10m
|
||||
```
|
||||
|
||||
### 5. 数据库迁移(Flyway)
|
||||
|
||||
**运行 Flyway Job**:
|
||||
```yaml
|
||||
- name: Run Flyway Migration
|
||||
run: |
|
||||
kubectl create job --from=cronjob/flyway-migration flyway-manual-$(date +%s) \
|
||||
-n ljwx-health
|
||||
|
||||
# 等待 Job 完成
|
||||
kubectl wait --for=condition=complete job/flyway-manual-* \
|
||||
-n ljwx-health --timeout=300s
|
||||
```
|
||||
|
||||
### 6. 健康检查
|
||||
|
||||
**验证部署**:
|
||||
```yaml
|
||||
- name: Health Check
|
||||
run: |
|
||||
# 检查 Pod 状态
|
||||
kubectl get pods -n ljwx-health
|
||||
|
||||
# 检查服务状态
|
||||
kubectl get svc -n ljwx-health
|
||||
|
||||
# 验证 ljwx-boot API
|
||||
kubectl run curl-test --image=curlimages/curl:latest --rm -it --restart=Never -- \
|
||||
curl -s http://ljwx-boot.ljwx-health.svc.cluster.local:9998/actuator/health
|
||||
|
||||
# 验证 OpenTelemetry Agent
|
||||
kubectl logs -n ljwx-health deployment/ljwx-boot | grep -i "opentelemetry"
|
||||
```
|
||||
|
||||
**预期输出**:
|
||||
```
|
||||
✅ OpenTelemetry Javaagent 2.11.0 initialized
|
||||
✅ Service name: ljwx-boot
|
||||
✅ OTLP exporter: http://tempo.tracing.svc.cluster.local:4317
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 必需的 Secrets
|
||||
|
||||
在 Gitea 仓库设置中配置以下 Secrets:
|
||||
|
||||
| Secret Name | 描述 | 示例值 |
|
||||
|------------|------|--------|
|
||||
| `HARBOR_USERNAME` | Harbor 用户名 | `admin` |
|
||||
| `HARBOR_PASSWORD` | Harbor 密码 | `Harbor12345` |
|
||||
| `REDIS_PASSWORD` | Redis 密码 | `redis123` |
|
||||
| `MYSQL_USERNAME` | MySQL 用户名 | `root` |
|
||||
| `MYSQL_PASSWORD` | MySQL 密码 | `mysql123` |
|
||||
| `JWT_SECRET` | JWT 密钥(可选) | `your-jwt-secret` |
|
||||
|
||||
**配置路径**:
|
||||
```
|
||||
Gitea仓库 → Settings → Secrets → Actions secrets
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 版本命名规则
|
||||
|
||||
### 自动版本命名
|
||||
|
||||
**main 分支**:
|
||||
```bash
|
||||
prod-20260105-153045 # 生产环境版本
|
||||
```
|
||||
|
||||
**develop 分支**:
|
||||
```bash
|
||||
dev-20260105-153045 # 开发环境版本
|
||||
```
|
||||
|
||||
**Git tag**:
|
||||
```bash
|
||||
v2.0.4 # 正式版本
|
||||
```
|
||||
|
||||
### 镜像标签示例
|
||||
|
||||
```
|
||||
harbor.omniverseai.net/ljwx-health/ljwx-boot:prod-20260105-153045
|
||||
harbor.omniverseai.net/ljwx-health/ljwx-boot:dev-20260105-153045
|
||||
harbor.omniverseai.net/ljwx-health/ljwx-boot:v2.0.4
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐛 常见问题排查
|
||||
|
||||
### 问题 1: 镜像构建失败
|
||||
|
||||
**症状**:
|
||||
```
|
||||
Error response from daemon: pull access denied for harbor.omniverseai.net/ljwx-base-images/java-maven-otel
|
||||
```
|
||||
|
||||
**原因**:
|
||||
- 基础镜像未推送到 Harbor
|
||||
- Harbor 认证失败
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查基础镜像是否存在
|
||||
docker pull harbor.omniverseai.net/ljwx-base-images/java-maven-otel:21-alpine
|
||||
|
||||
# 2. 重新构建并推送基础镜像
|
||||
cd docker/base-images
|
||||
./build-java-maven-otel.sh
|
||||
|
||||
# 3. 验证 Harbor 登录
|
||||
docker login harbor.omniverseai.net -u admin
|
||||
```
|
||||
|
||||
### 问题 2: Flyway 迁移失败
|
||||
|
||||
**症状**:
|
||||
```
|
||||
ERROR: Flyway migration failed: Schema validation failed
|
||||
```
|
||||
|
||||
**原因**:
|
||||
- 数据库 schema 版本冲突
|
||||
- 迁移脚本 SQL 语法错误
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查 Flyway 历史
|
||||
kubectl exec -n infra mysql-0 -- mysql -uroot -p123456 -e \
|
||||
"SELECT * FROM ljwx_health.flyway_schema_history ORDER BY installed_rank DESC LIMIT 5;"
|
||||
|
||||
# 2. 手动修复(如需要)
|
||||
kubectl exec -it -n infra mysql-0 -- mysql -uroot -p123456 ljwx_health
|
||||
|
||||
# 3. 重新运行迁移
|
||||
kubectl create job --from=cronjob/flyway-migration flyway-manual-$(date +%s) -n ljwx-health
|
||||
```
|
||||
|
||||
### 问题 3: OpenTelemetry 追踪数据缺失
|
||||
|
||||
**症状**:Grafana Tempo 看不到 ljwx-boot 的 trace
|
||||
|
||||
**排查清单**:
|
||||
```bash
|
||||
# 1. 检查 Dockerfile.gitea 是否使用正确基础镜像
|
||||
grep "FROM harbor.omniverseai.net/ljwx-base-images/java-maven-otel" \
|
||||
ljwx-boot/ljwx-boot-admin/Dockerfile.gitea
|
||||
|
||||
# 2. 检查 ENTRYPOINT 是否包含 -javaagent
|
||||
grep "javaagent" ljwx-boot/ljwx-boot-admin/Dockerfile.gitea
|
||||
|
||||
# 3. 检查 Pod 日志
|
||||
kubectl logs -n ljwx-health deployment/ljwx-boot | grep -i opentelemetry
|
||||
|
||||
# 4. 检查环境变量
|
||||
kubectl exec -n ljwx-health deployment/ljwx-boot -- env | grep OTEL
|
||||
|
||||
# 5. 检查 Tempo 连通性
|
||||
kubectl exec -n ljwx-health deployment/ljwx-boot -- \
|
||||
nc -zv tempo.tracing.svc.cluster.local 4317
|
||||
```
|
||||
|
||||
**参考文档**:[OpenTelemetry Tempo 集成修复](../../09-fixes/opentelemetry-tempo-integration-fix.md)
|
||||
|
||||
### 问题 4: ARM64 架构不匹配
|
||||
|
||||
**症状**:
|
||||
```
|
||||
exec /usr/bin/java: exec format error
|
||||
```
|
||||
|
||||
**原因**:镜像架构与 K3s 节点架构不匹配
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 验证 K3s 节点架构
|
||||
kubectl get nodes -o wide
|
||||
# 查看 ARCHITECTURE 列
|
||||
|
||||
# 2. 检查镜像架构
|
||||
docker inspect harbor.omniverseai.net/ljwx-health/ljwx-boot:prod-20260105 | \
|
||||
jq '.[0].Architecture'
|
||||
|
||||
# 3. 确保 Dockerfile.gitea 指定正确平台
|
||||
# --platform linux/arm64
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
### 核心文档
|
||||
- [自定义基础镜像指南](../docker/custom-base-images.md) ⭐ **必读**
|
||||
- [Kubernetes 部署指南](../kubernetes/deployment-guide.md)
|
||||
- [Helm Chart 配置](../kubernetes/helm-configuration.md)
|
||||
|
||||
### 故障排查
|
||||
- [OpenTelemetry Tempo 集成修复](../../09-fixes/opentelemetry-tempo-integration-fix.md)
|
||||
- [常见问题解答](../../04-operations/troubleshooting/common-issues.md)
|
||||
|
||||
### 架构设计
|
||||
- [可观测性架构](../../02-architecture/observability.md)
|
||||
- [GitOps 架构设计](../../02-architecture/gitops-architecture.md)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 工作流生命周期
|
||||
|
||||
### 日常开发流程
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[本地开发] --> B[git commit]
|
||||
B --> C[git push gitea develop]
|
||||
C --> D[Gitea Actions 触发]
|
||||
D --> E[构建 ARM64 镜像]
|
||||
E --> F[部署到开发环境]
|
||||
F --> G[自动健康检查]
|
||||
G --> H{检查通过?}
|
||||
H -->|是| I[开发环境可用]
|
||||
H -->|否| J[查看日志排查]
|
||||
J --> A
|
||||
```
|
||||
|
||||
### 生产发布流程
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[合并到 main] --> B[git tag v2.0.4]
|
||||
B --> C[git push gitea main --tags]
|
||||
C --> D[Gitea Actions 触发]
|
||||
D --> E[构建生产镜像]
|
||||
E --> F[部署 Redis/MySQL]
|
||||
F --> G[Helm 部署应用]
|
||||
G --> H[Flyway 数据库迁移]
|
||||
H --> I[健康检查 + 报告]
|
||||
I --> J{部署成功?}
|
||||
J -->|是| K[生产环境已更新]
|
||||
J -->|否| L[回滚到上一版本]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 重要注意事项
|
||||
|
||||
### 1. 仅限 Gitea 使用
|
||||
|
||||
本 workflow 配置路径:`.gitea/workflows/gitops-deploy.yml`
|
||||
|
||||
**不兼容**:
|
||||
- ❌ GitHub Actions(使用 `.github/workflows/`)
|
||||
- ❌ GitLab CI(使用 `.gitlab-ci.yml`)
|
||||
|
||||
### 2. ARM64 架构限制
|
||||
|
||||
所有镜像仅构建 ARM64 版本,**不支持** AMD64/x86_64。
|
||||
|
||||
**原因**:
|
||||
- 本地 K3s 集群运行在 ARM64(Raspberry Pi / Apple Silicon)
|
||||
- 减少构建时间和 Harbor 存储空间
|
||||
|
||||
### 3. 基础镜像依赖
|
||||
|
||||
**必须先构建基础镜像**:
|
||||
```bash
|
||||
cd docker/base-images
|
||||
./build-java-maven-otel.sh # 推送到 Harbor
|
||||
```
|
||||
|
||||
否则 Gitea Actions 会失败(找不到基础镜像)。
|
||||
|
||||
### 4. Secrets 安全
|
||||
|
||||
所有敏感信息必须通过 Gitea Secrets 配置,**禁止硬编码**在代码中。
|
||||
|
||||
**检查方法**:
|
||||
```bash
|
||||
# 搜索可能的硬编码密码
|
||||
grep -r "password.*=" --include="*.yml" --include="*.yaml" .
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📈 性能优化建议
|
||||
|
||||
### 1. 使用镜像缓存
|
||||
|
||||
```yaml
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
cache-from: type=registry,ref=harbor.omniverseai.net/ljwx-health/ljwx-boot:cache
|
||||
cache-to: type=inline
|
||||
```
|
||||
|
||||
### 2. 并行构建
|
||||
|
||||
```yaml
|
||||
strategy:
|
||||
matrix:
|
||||
component: [ljwx-boot, ljwx-admin, ljwx-bigscreen]
|
||||
max-parallel: 3
|
||||
```
|
||||
|
||||
### 3. 跳过不必要的步骤
|
||||
|
||||
```bash
|
||||
# 仅部署不重新构建
|
||||
git push gitea main -o skip_build=true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**维护者**:运维团队
|
||||
**最后更新**:2026-01-05
|
||||
**适用版本**:v2.0.4+
|
||||
Reference in New Issue
Block a user