chore: add CI pipeline, docs gate, OpenAPI snapshot, PR template, docs skeleton
This commit is contained in:
@@ -1,42 +1,38 @@
|
||||
## PR 信息
|
||||
## 变更摘要
|
||||
- [ ] feat
|
||||
- [ ] fix
|
||||
- [ ] refactor
|
||||
- [ ] chore
|
||||
- [ ] docs
|
||||
- [ ] perf
|
||||
- [ ] test
|
||||
|
||||
### 需求号
|
||||
<!-- 填写关联的需求编号,如 R-001。如无需求关联,写"无"并说明原因。 -->
|
||||
## 影响模块(可多选)
|
||||
- [ ] module: dict
|
||||
- [ ] module: sysconfig
|
||||
- [ ] module: department
|
||||
- [ ] module: menu
|
||||
- [ ] module: user
|
||||
- [ ] module: role
|
||||
- [ ] module: auth
|
||||
- [ ] module: log
|
||||
- [ ] module: other
|
||||
|
||||
## Doc Impact(必选其一,否则不允许合并)
|
||||
- [ ] docs:updated (已更新文档,列出文件)
|
||||
- [ ] docs:not-needed (不需要文档,写一句理由)
|
||||
- [ ] docs:todo (需要但尚未补齐:禁止合并,除非标记 hotfix)
|
||||
|
||||
### 契约变更说明
|
||||
<!-- 本次 PR 是否涉及以下契约变更?如有,请详细说明变更内容。 -->
|
||||
- [ ] OpenAPI 接口变更(新增/修改/删除端点、字段、错误码)
|
||||
- [ ] 数据库 Schema 变更(新增 Flyway migration)
|
||||
- [ ] 权限变更(新增/修改 permission 字符串)
|
||||
- [ ] 租户隔离策略变更
|
||||
### 文档变更清单/理由
|
||||
- docs files:
|
||||
- `docs/CHANGELOG.md`
|
||||
- `docs/MODULES/xxx.md`
|
||||
- `docs/API/overview.md`
|
||||
- `docs/ADR/xxxx.md`
|
||||
- reason:
|
||||
|
||||
变更详情:
|
||||
## OpenAPI(如有接口/DTO/权限变更)
|
||||
- [ ] openapi:changed(会影响合约)
|
||||
- [ ] openapi:not-changed
|
||||
|
||||
|
||||
### 控制面影响
|
||||
<!-- 本次变更是否影响以下控制面? -->
|
||||
- [ ] 认证/鉴权流程
|
||||
- [ ] 租户隔离逻辑
|
||||
- [ ] 日志/可观测性
|
||||
- [ ] CI Gate 脚本
|
||||
- [ ] 配置项(application.yml / 环境变量)
|
||||
|
||||
影响详情:
|
||||
|
||||
|
||||
### 测试证据
|
||||
<!-- 请列出本次变更对应的测试用例。 -->
|
||||
- [ ] 单元测试通过(./mvnw test)
|
||||
- [ ] 集成测试通过(./mvnw -PIT verify)
|
||||
- [ ] 手动验证(如适用,描述步骤)
|
||||
|
||||
测试详情:
|
||||
|
||||
|
||||
### 自检清单
|
||||
- [ ] 代码遵循分层约定(controller→facade→appservice→domain←infra)
|
||||
- [ ] tenant_id 来自 SecurityContext,未从 DTO/请求参数获取
|
||||
- [ ] @PreAuthorize 使用的权限字符串已在 seed 数据中定义
|
||||
- [ ] Flyway migration 版本号不冲突(MVP: V001-V099)
|
||||
- [ ] 无"省略/TODO/自行补充"的代码提交
|
||||
## 其他说明
|
||||
|
||||
+77
-26
@@ -1,51 +1,102 @@
|
||||
name: LJWX Platform CI
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches: ["main"]
|
||||
|
||||
env:
|
||||
JAVA_VERSION: "21"
|
||||
|
||||
jobs:
|
||||
gate-all:
|
||||
build-and-gate:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
image: postgres:16
|
||||
env:
|
||||
POSTGRES_DB: ljwx_platform_test
|
||||
POSTGRES_USER: test
|
||||
POSTGRES_PASSWORD: test
|
||||
POSTGRES_USER: ljwx
|
||||
POSTGRES_PASSWORD: ljwx123
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd="pg_isready -U test"
|
||||
--health-interval=10s
|
||||
--health-timeout=5s
|
||||
--health-retries=5
|
||||
--health-cmd "pg_isready -U ljwx"
|
||||
--health-interval 5s
|
||||
--health-timeout 5s
|
||||
--health-retries 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout @v4
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Java 21
|
||||
uses: actions/setup-java @v4
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
cache: 'maven'
|
||||
distribution: "temurin"
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
cache: "maven"
|
||||
|
||||
- name: Make scripts executable
|
||||
run: |
|
||||
chmod +x mvnw
|
||||
find scripts/ -name "*.sh" -exec chmod +x {} \;
|
||||
run: chmod +x scripts/ci/*.sh
|
||||
|
||||
- name: Run gate-all
|
||||
run: bash scripts/gates/gate-all.sh
|
||||
# ── Build ──
|
||||
- name: Compile
|
||||
run: ./mvnw -q -DskipTests package
|
||||
|
||||
# ── Unit Tests ──
|
||||
- name: Unit tests
|
||||
run: ./mvnw -q test
|
||||
|
||||
# ── Integration Tests ──
|
||||
- name: Integration tests
|
||||
env:
|
||||
DB_URL: jdbc:postgresql://localhost:5432/ljwx_platform_test
|
||||
DB_USERNAME: test
|
||||
DB_PASSWORD: test
|
||||
SPRING_PROFILES_ACTIVE: test
|
||||
SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/ljwx_platform_test
|
||||
SPRING_DATASOURCE_USERNAME: ljwx
|
||||
SPRING_DATASOURCE_PASSWORD: ljwx123
|
||||
run: ./mvnw -q -PIT verify
|
||||
|
||||
# ── Export OpenAPI snapshot ──
|
||||
- name: Export OpenAPI snapshot
|
||||
env:
|
||||
PORT: "18080"
|
||||
PROFILE: "test"
|
||||
SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/ljwx_platform_test
|
||||
SPRING_DATASOURCE_USERNAME: ljwx
|
||||
SPRING_DATASOURCE_PASSWORD: ljwx123
|
||||
run: scripts/ci/export-openapi.sh
|
||||
|
||||
# ── Docs Gate ──
|
||||
- name: Docs gate
|
||||
if: github.event_name == 'pull_request'
|
||||
env:
|
||||
BASE_REF: "origin/main"
|
||||
run: scripts/ci/docs-gate.sh
|
||||
|
||||
# ── OpenAPI Diff Gate ──
|
||||
- name: OpenAPI diff gate
|
||||
if: github.event_name == 'pull_request'
|
||||
env:
|
||||
BASE_REF: "origin/main"
|
||||
run: scripts/ci/openapi-diff.sh
|
||||
|
||||
# ── Ensure snapshot committed ──
|
||||
- name: Ensure OpenAPI snapshot committed
|
||||
run: |
|
||||
if git diff --exit-code docs/API/openapi.snapshot.yaml 2>/dev/null; then
|
||||
echo "[openapi] snapshot clean or not yet generated. PASS."
|
||||
else
|
||||
echo "============================================"
|
||||
echo "[openapi] FAIL: openapi.snapshot.yaml changed during CI but not committed."
|
||||
echo ""
|
||||
echo "Please run locally:"
|
||||
echo " scripts/ci/export-openapi.sh"
|
||||
echo " git add docs/API/openapi.snapshot.yaml"
|
||||
echo " git commit -m 'chore: update openapi snapshot'"
|
||||
echo "============================================"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# Breaking Changes
|
||||
|
||||
> Update this file whenever `docs/API/openapi.snapshot.yaml` changes.
|
||||
> CI will reject PRs that change the snapshot without updating this file.
|
||||
|
||||
## Format
|
||||
- YYYY-MM-DD: <describe change> (BREAKING | non-breaking)
|
||||
|
||||
## Log
|
||||
- 2026-02-15: Initial API surface established (non-breaking)
|
||||
@@ -0,0 +1,14 @@
|
||||
# OpenAPI snapshot placeholder
|
||||
# This file is auto-generated by scripts/ci/export-openapi.sh
|
||||
# Do not edit manually unless export is not yet available.
|
||||
#
|
||||
# To generate:
|
||||
# scripts/ci/export-openapi.sh
|
||||
#
|
||||
# CI will fail if this file changes but is not committed.
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
title: ljwx-platform API
|
||||
version: 0.0.0-snapshot
|
||||
description: Placeholder - run export-openapi.sh to generate actual spec
|
||||
paths: {}
|
||||
@@ -0,0 +1,65 @@
|
||||
# API Overview
|
||||
|
||||
Base URL: `/api/v1`
|
||||
|
||||
## Auth
|
||||
| Method | Path | Permission | Description |
|
||||
|--------|------|------------|-------------|
|
||||
| POST | /auth/login | - | 登录 |
|
||||
| POST | /auth/refresh | - | 刷新 Token |
|
||||
| POST | /auth/logout | - | 登出 |
|
||||
|
||||
## Menu
|
||||
| Method | Path | Permission | Description |
|
||||
|--------|------|------------|-------------|
|
||||
| GET | /menus | menu:read | 菜单列表 |
|
||||
| GET | /menus/{id} | menu:read | 菜单详情 |
|
||||
| POST | /menus | menu:write | 创建菜单 |
|
||||
| PUT | /menus/{id} | menu:write | 更新菜单 |
|
||||
| DELETE | /menus/{id} | menu:write | 删除菜单 |
|
||||
| GET | /menus/me | (any auth) | 当前用户菜单树 |
|
||||
|
||||
## Role
|
||||
| Method | Path | Permission | Description |
|
||||
|--------|------|------------|-------------|
|
||||
| GET | /roles | role:read | 角色列表 |
|
||||
| GET | /roles/{id} | role:read | 角色详情 |
|
||||
| POST | /roles | role:write | 创建角色 |
|
||||
| PUT | /roles/{id} | role:write | 更新角色 |
|
||||
| DELETE | /roles/{id} | role:write | 删除角色 |
|
||||
| PUT | /roles/{id}/permissions | role:write | 分配权限 |
|
||||
| PUT | /roles/user-roles | role:write | 分配用户角色 |
|
||||
| GET | /roles/user-roles/{userId} | role:read | 查询用户角色 |
|
||||
|
||||
## Dict
|
||||
| Method | Path | Permission | Description |
|
||||
|--------|------|------------|-------------|
|
||||
| GET | /dict-types | dict:read | 字典类型列表 |
|
||||
| GET | /dict-data | dict:read | 字典数据列表 |
|
||||
|
||||
## SysConfig
|
||||
| Method | Path | Permission | Description |
|
||||
|--------|------|------------|-------------|
|
||||
| GET | /sys-configs | config:read | 配置列表 |
|
||||
| GET | /sys-configs/{id} | config:read | 配置详情 |
|
||||
|
||||
## Department
|
||||
| Method | Path | Permission | Description |
|
||||
|--------|------|------------|-------------|
|
||||
| GET | /departments | dept:read | 部门列表 |
|
||||
| GET | /departments/{id} | dept:read | 部门详情 |
|
||||
| POST | /departments | dept:write | 创建部门 |
|
||||
| PUT | /departments/{id} | dept:write | 更新部门 |
|
||||
| DELETE | /departments/{id} | dept:write | 删除部门 |
|
||||
|
||||
## User (Phase 2 - planned)
|
||||
| Method | Path | Permission | Description |
|
||||
|--------|------|------------|-------------|
|
||||
| GET | /users | user:read | 用户列表 |
|
||||
| GET | /users/{id} | user:read | 用户详情 |
|
||||
| POST | /users | user:write | 创建用户 |
|
||||
| PUT | /users/{id} | user:write | 更新用户 |
|
||||
| DELETE | /users/{id} | user:write | 删除用户 |
|
||||
| GET | /users/me | (any auth) | 当前用户信息 |
|
||||
| PUT | /users/{id}/reset-password | user:write | 重置密码 |
|
||||
| PUT | /users/{id}/status | user:write | 切换状态 |
|
||||
@@ -0,0 +1,29 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
Format based on [Keep a Changelog](https://keepachangelog.com/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- Dict module (V101-V102)
|
||||
- SysConfig module (V103-V104)
|
||||
- Menu module (V107-V109)
|
||||
- User/Role enhancement (V110-V111)
|
||||
- Audit field alignment (V112)
|
||||
- Departments table (V113-V114)
|
||||
- SecurityUtil centralized auth extraction
|
||||
- Global exception handler
|
||||
- Role CRUD with tenant isolation
|
||||
- UserRole assignment with dedup
|
||||
- GET /api/v1/menus/me tree endpoint
|
||||
|
||||
### Fixed
|
||||
- V111 ADMIN permission binding across all tenants
|
||||
- UserRoleAppService duplicate roleId handling
|
||||
- Menu permission_key consistency for all 6 second-level menus
|
||||
- Bean naming conflicts between legacy and new infrastructure packages
|
||||
|
||||
### Changed
|
||||
- Standardized audit fields: create_* NOT NULL, update_* nullable, is_deleted SMALLINT DEFAULT 0
|
||||
- Replaced private currentUsername/currentUserId/currentTenantId with SecurityUtil.*
|
||||
@@ -0,0 +1,36 @@
|
||||
# <Module Name>
|
||||
|
||||
## 定位
|
||||
一句话说明模块职责。
|
||||
|
||||
## 数据库
|
||||
| 表 | 描述 | 租户级 |
|
||||
|----|------|--------|
|
||||
| xxx | ... | 是/否 |
|
||||
|
||||
## 实体
|
||||
- `XxxModel` → 字段列表
|
||||
|
||||
## 端点
|
||||
| Method | Path | Permission | Description |
|
||||
|--------|------|------------|-------------|
|
||||
| GET | /api/v1/xxx | xxx:read | ... |
|
||||
|
||||
## 权限
|
||||
| Key | 描述 |
|
||||
|-----|------|
|
||||
| xxx:read | 查看 |
|
||||
| xxx:write | 管理 |
|
||||
|
||||
## 迁移脚本
|
||||
| Version | 文件 | 描述 |
|
||||
|---------|------|------|
|
||||
| Vxxx | V...sql | ... |
|
||||
|
||||
## 特殊规则
|
||||
- 规则 1:...
|
||||
- 规则 2:...
|
||||
|
||||
## 依赖
|
||||
- 依赖模块:auth, tenant
|
||||
- 被依赖:user
|
||||
@@ -0,0 +1,29 @@
|
||||
# ADR-XXXX: <Title>
|
||||
|
||||
## Status
|
||||
Proposed | Accepted | Deprecated | Superseded by ADR-YYYY
|
||||
|
||||
## Date
|
||||
YYYY-MM-DD
|
||||
|
||||
## Context
|
||||
为什么要做这个决策?当前遇到了什么问题?
|
||||
|
||||
## Decision
|
||||
做了什么决策(明确、具体)。
|
||||
|
||||
## Alternatives Considered
|
||||
| 方案 | 优点 | 缺点 | 结论 |
|
||||
|------|------|------|------|
|
||||
| A | ... | ... | 不采用 |
|
||||
| B | ... | ... | 采用 |
|
||||
|
||||
## Consequences
|
||||
- 好处:
|
||||
- 代价:
|
||||
- 风险:
|
||||
|
||||
## References
|
||||
- PR: #xxx
|
||||
- Migration: Vxxx
|
||||
- Related ADR: ADR-xxxx
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
BASE_REF="${BASE_REF:-origin/main}"
|
||||
|
||||
echo "[docs-gate] base ref: ${BASE_REF}"
|
||||
|
||||
# 确保有 base ref
|
||||
git fetch origin main --depth=50 2>/dev/null || true
|
||||
|
||||
# 获取变更文件列表
|
||||
CHANGED="$(git diff --name-only "${BASE_REF}...HEAD" 2>/dev/null || git diff --name-only HEAD~1 || true)"
|
||||
|
||||
if [[ -z "${CHANGED}" ]]; then
|
||||
echo "[docs-gate] no changed files detected. PASS."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "[docs-gate] changed files:"
|
||||
echo "${CHANGED}"
|
||||
echo ""
|
||||
|
||||
# 1) 判断是否属于"必须带文档"的代码变更
|
||||
NEED_DOC=0
|
||||
echo "${CHANGED}" | grep -E -q \
|
||||
'(controller|facade|dto|security|exception)/.*\.java$|db/migration/.*\.sql$|.*(Controller|Facade|Request|Response)\.java$' \
|
||||
&& NEED_DOC=1 || true
|
||||
|
||||
if [[ "${NEED_DOC}" -eq 0 ]]; then
|
||||
echo "[docs-gate] no doc-required code changes detected. PASS."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "[docs-gate] doc-requiring code changes detected."
|
||||
|
||||
# 2) 检查 docs 是否有变化
|
||||
DOC_CHANGED=0
|
||||
echo "${CHANGED}" | grep -E -q \
|
||||
'^docs/CHANGELOG\.md$|^docs/MODULES/|^docs/API/overview\.md$|^docs/API/breaking-changes\.md$|^docs/ADR/|^docs/adr/' \
|
||||
&& DOC_CHANGED=1 || true
|
||||
|
||||
# 3) 检查 openapi snapshot 是否变化
|
||||
OPENAPI_CHANGED=0
|
||||
echo "${CHANGED}" | grep -E -q '^docs/API/openapi\.snapshot\.yaml$' && OPENAPI_CHANGED=1 || true
|
||||
|
||||
if [[ "${DOC_CHANGED}" -eq 1 || "${OPENAPI_CHANGED}" -eq 1 ]]; then
|
||||
echo "[docs-gate] docs or openapi snapshot updated. PASS."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cat <<'EOF2'
|
||||
|
||||
============================================
|
||||
[docs-gate] FAIL
|
||||
|
||||
You changed code that requires docs updates, but no docs were changed.
|
||||
|
||||
Fix options (choose at least one):
|
||||
1) Update docs/CHANGELOG.md (recommended, 1-3 lines)
|
||||
2) Update a module doc: docs/MODULES/<module>.md
|
||||
3) Update docs/API/overview.md or docs/ADR/* (docs/adr/*)
|
||||
4) If API changed, run scripts/ci/export-openapi.sh and commit the snapshot
|
||||
|
||||
============================================
|
||||
|
||||
EOF2
|
||||
|
||||
exit 1
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
OUT="docs/API/openapi.snapshot.yaml"
|
||||
PORT="${PORT:-8080}"
|
||||
PROFILE="${PROFILE:-test}"
|
||||
MAX_WAIT="${MAX_WAIT:-90}"
|
||||
|
||||
echo "[openapi] export to ${OUT}, port=${PORT}, profile=${PROFILE}"
|
||||
|
||||
# 1) 编译(如果 jar 不存在)
|
||||
JAR="$(find ljwx-platform-app/target -name '*.jar' -not -name '*-sources*' -not -name '*-javadoc*' 2>/dev/null | head -n1 || true)"
|
||||
if [[ -z "${JAR}" ]]; then
|
||||
echo "[openapi] jar not found, building..."
|
||||
./mvnw -q -DskipTests package
|
||||
JAR="$(find ljwx-platform-app/target -name '*.jar' -not -name '*-sources*' -not -name '*-javadoc*' | head -n1)"
|
||||
fi
|
||||
|
||||
echo "[openapi] using jar: ${JAR}"
|
||||
|
||||
# 2) 后台启动应用
|
||||
nohup java -jar "${JAR}" \
|
||||
--spring.profiles.active="${PROFILE}" \
|
||||
--server.port="${PORT}" \
|
||||
> /tmp/openapi-app.log 2>&1 &
|
||||
APP_PID=$!
|
||||
|
||||
cleanup() {
|
||||
echo "[openapi] stopping app pid=${APP_PID}"
|
||||
kill "${APP_PID}" 2>/dev/null || true
|
||||
wait "${APP_PID}" 2>/dev/null || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# 3) 等待应用就绪(先试 actuator,再试 OpenAPI 端点自身)
|
||||
echo "[openapi] waiting for app to start (max ${MAX_WAIT}s)..."
|
||||
READY=0
|
||||
for i in $(seq 1 "${MAX_WAIT}"); do
|
||||
# 优先 actuator
|
||||
if curl -fsS "http://127.0.0.1:${PORT}/actuator/health" >/dev/null 2>&1; then
|
||||
READY=1
|
||||
break
|
||||
fi
|
||||
# 回退:直接试 OpenAPI 端点
|
||||
if curl -fsS "http://127.0.0.1:${PORT}/v3/api-docs" >/dev/null 2>&1; then
|
||||
READY=1
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [[ "${READY}" -eq 0 ]]; then
|
||||
echo "[openapi] ERROR: app did not start within ${MAX_WAIT}s"
|
||||
echo "[openapi] last 50 lines of log:"
|
||||
tail -50 /tmp/openapi-app.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[openapi] app is ready"
|
||||
|
||||
# 4) 导出 OpenAPI
|
||||
mkdir -p "$(dirname "${OUT}")"
|
||||
|
||||
if curl -fsS "http://127.0.0.1:${PORT}/v3/api-docs.yaml" -o "${OUT}" 2>/dev/null; then
|
||||
echo "[openapi] exported yaml to ${OUT}"
|
||||
elif curl -fsS "http://127.0.0.1:${PORT}/v3/api-docs" -o "${OUT%.yaml}.json" 2>/dev/null; then
|
||||
echo "[openapi] yaml not available, exported json to ${OUT%.yaml}.json"
|
||||
else
|
||||
echo "[openapi] WARNING: could not export OpenAPI. Endpoint may not be configured."
|
||||
echo "[openapi] This is non-fatal. Skipping snapshot update."
|
||||
# 创建一个占位文件,避免后续 git diff 报错
|
||||
if [[ ! -f "${OUT}" ]]; then
|
||||
echo "# OpenAPI snapshot not yet available" > "${OUT}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "[openapi] done"
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SNAP="docs/API/openapi.snapshot.yaml"
|
||||
BREAKING="docs/API/breaking-changes.md"
|
||||
BASE_REF="${BASE_REF:-origin/main}"
|
||||
|
||||
echo "[openapi-diff] checking snapshot changes..."
|
||||
|
||||
git fetch origin main --depth=50 2>/dev/null || true
|
||||
|
||||
# 获取变更文件列表
|
||||
CHANGED="$(git diff --name-only "${BASE_REF}...HEAD" 2>/dev/null || git diff --name-only HEAD~1 || true)"
|
||||
|
||||
# 如果 snapshot 没变化,直接 pass
|
||||
if ! echo "${CHANGED}" | grep -q "^${SNAP}$"; then
|
||||
echo "[openapi-diff] snapshot not changed. PASS."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "[openapi-diff] snapshot changed."
|
||||
|
||||
# 要求 breaking-changes.md 也有变化
|
||||
if echo "${CHANGED}" | grep -q "^${BREAKING}$"; then
|
||||
echo "[openapi-diff] breaking-changes.md updated. PASS."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cat <<EOF2
|
||||
|
||||
============================================
|
||||
[openapi-diff] FAIL
|
||||
|
||||
OpenAPI snapshot changed but ${BREAKING} was not updated.
|
||||
|
||||
Please add a short note to ${BREAKING}, e.g.:
|
||||
- $(date +%Y-%m-%d): Added GET /api/v1/users/me endpoint (non-breaking)
|
||||
- $(date +%Y-%m-%d): Removed field xxx from YyyResponse (BREAKING)
|
||||
|
||||
============================================
|
||||
|
||||
EOF2
|
||||
|
||||
exit 1
|
||||
Reference in New Issue
Block a user