@wneng/create-keel 0.3.0 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -1
- package/dist/index.js +118 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/templates/ci-gitee/files/PULL_REQUEST_TEMPLATE.md +62 -0
- package/src/templates/ci-gitee/files/pipeline.yml +150 -16
- package/src/templates/ci-gitee/fragment.yaml +4 -1
- package/src/templates/ci-github/files/PULL_REQUEST_TEMPLATE.md +62 -0
- package/src/templates/ci-github/files/ci.yml +199 -6
- package/src/templates/ci-github/fragment.yaml +4 -1
- package/src/templates/contracts-base/files/_spectral.yaml +21 -0
- package/src/templates/contracts-base/fragment.yaml +4 -1
- package/src/templates/docs-skeleton/files/README.md +3 -3
- package/src/templates/docs-skeleton/files/governance-checklists.md +3 -3
- package/src/templates/docs-skeleton/files/governance-security.md +6 -2
- package/src/templates/root-files/files/CODEOWNERS +40 -0
- package/src/templates/root-files/fragment.yaml +3 -0
- package/src/templates/server-go/files/_golangci.yml +41 -0
- package/src/templates/server-go/fragment.yaml +4 -1
- package/src/templates/server-java/files/checkstyle.xml +62 -0
- package/src/templates/server-java/files/pom.xml +57 -0
- package/src/templates/server-java/fragment.yaml +4 -1
- package/src/templates/server-node/files/_eslintrc.cjs +20 -0
- package/src/templates/server-node/files/_prettierrc +12 -0
- package/src/templates/server-node/files/package.json +14 -1
- package/src/templates/server-node/fragment.yaml +7 -1
- package/src/templates/server-python/files/pyproject.toml +44 -0
- package/src/templates/web-react/files/_eslintrc.cjs +34 -0
- package/src/templates/web-react/files/_prettierrc +12 -0
- package/src/templates/web-react/files/package.json +11 -1
- package/src/templates/web-react/fragment.yaml +7 -1
- package/src/templates/web-vue/files/_eslintrc.cjs +28 -0
- package/src/templates/web-vue/files/_prettierrc +12 -0
- package/src/templates/web-vue/fragment.yaml +7 -1
package/package.json
CHANGED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Pull Request
|
|
2
|
+
|
|
3
|
+
> 来自 keel scaffolder(@wneng/create-keel <%= it.scaffolderVersion %>)
|
|
4
|
+
> 完整规则见 [`docs/governance/git-workflow.md`](../docs/governance/git-workflow.md)
|
|
5
|
+
|
|
6
|
+
## 概述(What & Why)
|
|
7
|
+
|
|
8
|
+
<!-- 一句话讲清楚这个 PR 改了什么、为什么 -->
|
|
9
|
+
|
|
10
|
+
## 关联引用
|
|
11
|
+
|
|
12
|
+
<!-- 至少填一项;契约 / 设计 / spec 三选一 -->
|
|
13
|
+
|
|
14
|
+
- 契约锚点:`contracts/openapi/api.yaml#/paths/...` 或 `contracts/events/event-catalog.yaml#/events/...`
|
|
15
|
+
- 设计文档:`docs/04-后端详细设计/<slug>.md` 或 `docs/05-前端客户端详细设计/<slug>-<platform>.md`
|
|
16
|
+
- spec:`.kiro/specs/<feature>/`(如适用)
|
|
17
|
+
|
|
18
|
+
## 变更类型
|
|
19
|
+
|
|
20
|
+
- [ ] feat — 新增能力
|
|
21
|
+
- [ ] fix — 缺陷修复
|
|
22
|
+
- [ ] docs — 文档变更
|
|
23
|
+
- [ ] refactor — 重构(无行为变化)
|
|
24
|
+
- [ ] chore — 维护性变更
|
|
25
|
+
- [ ] spike — 临时探索(必须在合入前补齐契约 / 文档)
|
|
26
|
+
|
|
27
|
+
## 自检清单(Pre-merge)
|
|
28
|
+
|
|
29
|
+
完整 checklist 见 [`docs/governance/checklists.md`](../docs/governance/checklists.md)。最常踩的 5 个坑:
|
|
30
|
+
|
|
31
|
+
- [ ] 改了 `contracts/` → `contracts/CHANGELOG.md` 已同步更新
|
|
32
|
+
- [ ] 触了 on-demand 目录 → 用户已说出 trigger keyword("更新部署手册" / "更新合规证据" / "更新宣发" / "更新设计稿")
|
|
33
|
+
- [ ] **未**直接写 `docs/11-市场与对外材料/published/` 或 `docs/10-合规与安全/evidence/`(read-only)
|
|
34
|
+
- [ ] AI 生成代码 → commit 用 `feat(ai): ...` / `chore(ai): ...` 前缀;PR 打 `ai-generated` 标签
|
|
35
|
+
- [ ] 改了 `docs/governance/<file>.md` → AGENTS.md §7 对应摘要已同步
|
|
36
|
+
|
|
37
|
+
## CI
|
|
38
|
+
|
|
39
|
+
- [ ] 本地 `npm test` / `mvn test` / `pytest` 等已通过
|
|
40
|
+
- [ ] `governance-lint` 本地通过:`node tools/governance-lint/index.js --strict`
|
|
41
|
+
- [ ] 没有提交 secret / 私钥 / 真实 PII
|
|
42
|
+
|
|
43
|
+
## 影响范围
|
|
44
|
+
|
|
45
|
+
<!-- 列出受影响的执行环境 / 模块 / 服务 -->
|
|
46
|
+
|
|
47
|
+
- [ ] `server/`(后端)
|
|
48
|
+
- [ ] `web/`(前端)
|
|
49
|
+
- [ ] `mobile/`(移动端)
|
|
50
|
+
- [ ] `miniapp/`(小程序)
|
|
51
|
+
- [ ] `agent/`(桌面 / CLI)
|
|
52
|
+
- [ ] `contracts/`(契约)
|
|
53
|
+
- [ ] `deploy/` / `ops/`(部署 / 基础设施)
|
|
54
|
+
- [ ] 仅 docs
|
|
55
|
+
|
|
56
|
+
## 回滚预案
|
|
57
|
+
|
|
58
|
+
<!-- 如果合入后发现问题,怎么回滚?哪些数据 / 配置需要清理? -->
|
|
59
|
+
|
|
60
|
+
## 备注 / 截图
|
|
61
|
+
|
|
62
|
+
<!-- 可选 -->
|
|
@@ -1,18 +1,152 @@
|
|
|
1
|
+
# Gitee Pipelines for <%= it.options.projectName %>
|
|
2
|
+
#
|
|
3
|
+
# Generated by `@wneng/create-keel` (Contract First + Vibe Coding).
|
|
4
|
+
#
|
|
5
|
+
# Gitee Pipelines and GitHub Actions speak different YAML dialects;
|
|
6
|
+
# this file uses the documented `stages + jobs` shape supported by
|
|
7
|
+
# Gitee. If your team migrates to GitHub Actions, regenerate with
|
|
8
|
+
# `--ci github` instead of porting by hand.
|
|
9
|
+
#
|
|
10
|
+
# Each stage runs sequentially; jobs within a stage run in parallel.
|
|
11
|
+
# Failure in any stage aborts the pipeline.
|
|
12
|
+
|
|
1
13
|
name: ci
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
14
|
+
|
|
15
|
+
stages:
|
|
16
|
+
- lint
|
|
17
|
+
- test
|
|
18
|
+
- scan
|
|
19
|
+
|
|
7
20
|
jobs:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
governance-lint:
|
|
22
|
+
stage: lint
|
|
23
|
+
image: node:20-alpine
|
|
24
|
+
script:
|
|
25
|
+
- |
|
|
26
|
+
if [ -f tools/governance-lint/index.js ]; then
|
|
27
|
+
node tools/governance-lint/index.js --strict
|
|
28
|
+
else
|
|
29
|
+
echo "tools/governance-lint/ not present; skipping"
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
contract-lint:
|
|
33
|
+
stage: lint
|
|
34
|
+
image: node:20-alpine
|
|
35
|
+
script:
|
|
36
|
+
<% if (it.options.contract === 'rest' || it.options.contract === 'rest+events') { %> - npx --yes @stoplight/spectral-cli lint contracts/openapi/api.yaml
|
|
37
|
+
<% } %><% if (it.options.contract === 'rest+events' || it.options.contract === 'events-only') { %> - |
|
|
38
|
+
if [ -f contracts/asyncapi/asyncapi.yaml ]; then
|
|
39
|
+
npx --yes @stoplight/spectral-cli lint contracts/asyncapi/asyncapi.yaml
|
|
40
|
+
fi
|
|
41
|
+
<% } %> - |
|
|
42
|
+
for s in contracts/**/*.schema.json; do
|
|
43
|
+
[ -e "$s" ] || continue
|
|
44
|
+
npx --yes ajv-cli compile -s "$s"
|
|
45
|
+
done
|
|
46
|
+
|
|
47
|
+
<% if (it.options.backend === 'node') { %> server-node:
|
|
48
|
+
stage: test
|
|
49
|
+
image: node:20-alpine
|
|
50
|
+
script:
|
|
51
|
+
- cd server
|
|
52
|
+
- npm ci
|
|
53
|
+
- npm run lint --if-present
|
|
54
|
+
- npm run typecheck --if-present
|
|
55
|
+
- npm test --if-present
|
|
56
|
+
<% } %><% if (it.options.backend === 'java') { %> server-java:
|
|
57
|
+
stage: test
|
|
58
|
+
image: maven:3.9-eclipse-temurin-21
|
|
59
|
+
script:
|
|
60
|
+
- cd server
|
|
61
|
+
- mvn -B verify
|
|
62
|
+
<% } %><% if (it.options.backend === 'go') { %> server-go:
|
|
63
|
+
stage: test
|
|
64
|
+
image: golang:1.22-alpine
|
|
65
|
+
script:
|
|
66
|
+
- cd server
|
|
67
|
+
- go vet ./...
|
|
68
|
+
- go test ./...
|
|
69
|
+
<% } %><% if (it.options.backend === 'python') { %> server-python:
|
|
70
|
+
stage: test
|
|
71
|
+
image: python:3.12-slim
|
|
72
|
+
script:
|
|
73
|
+
- cd server
|
|
74
|
+
- pip install -e .[dev] || pip install -e .
|
|
75
|
+
- ruff check .
|
|
76
|
+
- ruff format --check .
|
|
77
|
+
- pytest -q
|
|
78
|
+
<% } %>
|
|
79
|
+
<% if (it.options.frontend === 'react' || it.options.frontend === 'vue') { %> web:
|
|
80
|
+
stage: test
|
|
81
|
+
image: node:20-alpine
|
|
82
|
+
script:
|
|
83
|
+
- cd web
|
|
84
|
+
- npm ci
|
|
85
|
+
- npm run lint --if-present
|
|
86
|
+
- npm run typecheck --if-present || npx tsc --noEmit
|
|
87
|
+
- npm test --if-present
|
|
88
|
+
- npm run build
|
|
89
|
+
<% } %>
|
|
90
|
+
<% if (it.options.mobile === 'flutter') { %> mobile-flutter:
|
|
91
|
+
stage: test
|
|
92
|
+
image: cirrusci/flutter:stable
|
|
93
|
+
script:
|
|
94
|
+
- cd mobile
|
|
95
|
+
- flutter pub get
|
|
96
|
+
- flutter analyze
|
|
97
|
+
- flutter test
|
|
98
|
+
<% } %><% if (it.options.mobile === 'react-native') { %> mobile-react-native:
|
|
99
|
+
stage: test
|
|
100
|
+
image: node:20-alpine
|
|
101
|
+
script:
|
|
102
|
+
- cd mobile
|
|
103
|
+
- npm ci
|
|
104
|
+
- npm run lint --if-present
|
|
105
|
+
- npm test --if-present
|
|
106
|
+
<% } %>
|
|
107
|
+
<% if (it.options.miniapp === 'wechat') { %> miniapp-wechat:
|
|
108
|
+
stage: test
|
|
109
|
+
image: node:20-alpine
|
|
110
|
+
script:
|
|
111
|
+
- cd miniapp
|
|
112
|
+
- |
|
|
113
|
+
if [ -f tsconfig.json ]; then npx tsc --noEmit; else echo "no tsconfig"; fi
|
|
114
|
+
<% } %>
|
|
115
|
+
<% if (it.options.agent === 'rust-desktop') { %> agent-rust:
|
|
116
|
+
stage: test
|
|
117
|
+
image: rust:1.78
|
|
118
|
+
script:
|
|
119
|
+
- cd agent
|
|
120
|
+
- cargo fmt --check
|
|
121
|
+
- cargo clippy --all-targets -- -D warnings
|
|
122
|
+
- cargo test
|
|
123
|
+
<% } %>
|
|
124
|
+
secret-scan:
|
|
125
|
+
stage: scan
|
|
126
|
+
image: zricethezav/gitleaks:latest
|
|
127
|
+
script:
|
|
128
|
+
- gitleaks detect --redact --no-git -v
|
|
129
|
+
|
|
130
|
+
<% if (it.options.backend === 'node' || it.options.frontend === 'react' || it.options.frontend === 'vue' || it.options.mobile === 'react-native' || it.options.miniapp === 'wechat') { %> npm-audit:
|
|
131
|
+
stage: scan
|
|
132
|
+
image: node:20-alpine
|
|
133
|
+
script:
|
|
134
|
+
<% if (it.options.backend === 'node') { %> - cd server && npm audit --audit-level=high && cd ..
|
|
135
|
+
<% } %><% if (it.options.frontend === 'react' || it.options.frontend === 'vue') { %> - cd web && npm audit --audit-level=high && cd ..
|
|
136
|
+
<% } %><% if (it.options.mobile === 'react-native') { %> - cd mobile && npm audit --audit-level=high && cd ..
|
|
137
|
+
<% } %><% } %>
|
|
138
|
+
<% if (it.options.backend === 'go') { %> go-vulncheck:
|
|
139
|
+
stage: scan
|
|
140
|
+
image: golang:1.22-alpine
|
|
141
|
+
script:
|
|
142
|
+
- cd server
|
|
143
|
+
- go install golang.org/x/vuln/cmd/govulncheck@latest
|
|
144
|
+
- govulncheck ./...
|
|
145
|
+
<% } %><% if (it.options.backend === 'python') { %> pip-audit:
|
|
146
|
+
stage: scan
|
|
147
|
+
image: python:3.12-slim
|
|
148
|
+
script:
|
|
149
|
+
- cd server
|
|
150
|
+
- pip install pip-audit
|
|
151
|
+
- pip-audit
|
|
152
|
+
<% } %>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name: ci-gitee
|
|
2
|
-
version: 1.
|
|
2
|
+
version: 1.2.0
|
|
3
3
|
appliesWhen:
|
|
4
4
|
ci: gitee
|
|
5
5
|
priority: 20
|
|
@@ -7,3 +7,6 @@ files:
|
|
|
7
7
|
- from: files/pipeline.yml
|
|
8
8
|
to: .gitee/pipelines/ci.yml
|
|
9
9
|
render: true
|
|
10
|
+
- from: files/PULL_REQUEST_TEMPLATE.md
|
|
11
|
+
to: .gitee/PULL_REQUEST_TEMPLATE.md
|
|
12
|
+
render: true
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Pull Request
|
|
2
|
+
|
|
3
|
+
> 来自 keel scaffolder(@wneng/create-keel <%= it.scaffolderVersion %>)
|
|
4
|
+
> 完整规则见 [`docs/governance/git-workflow.md`](../docs/governance/git-workflow.md)
|
|
5
|
+
|
|
6
|
+
## 概述(What & Why)
|
|
7
|
+
|
|
8
|
+
<!-- 一句话讲清楚这个 PR 改了什么、为什么 -->
|
|
9
|
+
|
|
10
|
+
## 关联引用
|
|
11
|
+
|
|
12
|
+
<!-- 至少填一项;契约 / 设计 / spec 三选一 -->
|
|
13
|
+
|
|
14
|
+
- 契约锚点:`contracts/openapi/api.yaml#/paths/...` 或 `contracts/events/event-catalog.yaml#/events/...`
|
|
15
|
+
- 设计文档:`docs/04-后端详细设计/<slug>.md` 或 `docs/05-前端客户端详细设计/<slug>-<platform>.md`
|
|
16
|
+
- spec:`.kiro/specs/<feature>/`(如适用)
|
|
17
|
+
|
|
18
|
+
## 变更类型
|
|
19
|
+
|
|
20
|
+
- [ ] feat — 新增能力
|
|
21
|
+
- [ ] fix — 缺陷修复
|
|
22
|
+
- [ ] docs — 文档变更
|
|
23
|
+
- [ ] refactor — 重构(无行为变化)
|
|
24
|
+
- [ ] chore — 维护性变更
|
|
25
|
+
- [ ] spike — 临时探索(必须在合入前补齐契约 / 文档)
|
|
26
|
+
|
|
27
|
+
## 自检清单(Pre-merge)
|
|
28
|
+
|
|
29
|
+
完整 checklist 见 [`docs/governance/checklists.md`](../docs/governance/checklists.md)。最常踩的 5 个坑:
|
|
30
|
+
|
|
31
|
+
- [ ] 改了 `contracts/` → `contracts/CHANGELOG.md` 已同步更新
|
|
32
|
+
- [ ] 触了 on-demand 目录 → 用户已说出 trigger keyword("更新部署手册" / "更新合规证据" / "更新宣发" / "更新设计稿")
|
|
33
|
+
- [ ] **未**直接写 `docs/11-市场与对外材料/published/` 或 `docs/10-合规与安全/evidence/`(read-only)
|
|
34
|
+
- [ ] AI 生成代码 → commit 用 `feat(ai): ...` / `chore(ai): ...` 前缀;PR 打 `ai-generated` 标签
|
|
35
|
+
- [ ] 改了 `docs/governance/<file>.md` → AGENTS.md §7 对应摘要已同步
|
|
36
|
+
|
|
37
|
+
## CI
|
|
38
|
+
|
|
39
|
+
- [ ] 本地 `npm test` / `mvn test` / `pytest` 等已通过
|
|
40
|
+
- [ ] `governance-lint` 本地通过:`node tools/governance-lint/index.js --strict`
|
|
41
|
+
- [ ] 没有提交 secret / 私钥 / 真实 PII
|
|
42
|
+
|
|
43
|
+
## 影响范围
|
|
44
|
+
|
|
45
|
+
<!-- 列出受影响的执行环境 / 模块 / 服务 -->
|
|
46
|
+
|
|
47
|
+
- [ ] `server/`(后端)
|
|
48
|
+
- [ ] `web/`(前端)
|
|
49
|
+
- [ ] `mobile/`(移动端)
|
|
50
|
+
- [ ] `miniapp/`(小程序)
|
|
51
|
+
- [ ] `agent/`(桌面 / CLI)
|
|
52
|
+
- [ ] `contracts/`(契约)
|
|
53
|
+
- [ ] `deploy/` / `ops/`(部署 / 基础设施)
|
|
54
|
+
- [ ] 仅 docs
|
|
55
|
+
|
|
56
|
+
## 回滚预案
|
|
57
|
+
|
|
58
|
+
<!-- 如果合入后发现问题,怎么回滚?哪些数据 / 配置需要清理? -->
|
|
59
|
+
|
|
60
|
+
## 备注 / 截图
|
|
61
|
+
|
|
62
|
+
<!-- 可选 -->
|
|
@@ -4,14 +4,207 @@ on:
|
|
|
4
4
|
branches: [main]
|
|
5
5
|
pull_request:
|
|
6
6
|
branches: [main]
|
|
7
|
+
|
|
8
|
+
# CI for <%= it.options.projectName %>
|
|
9
|
+
#
|
|
10
|
+
# Generated by `@wneng/create-keel` (Contract First + Vibe Coding).
|
|
11
|
+
# Each job below is independent so a failure in one (e.g. server) does
|
|
12
|
+
# not skip the others. The `governance-lint` and `contract-lint` jobs
|
|
13
|
+
# are always present; per-environment jobs are conditionally included
|
|
14
|
+
# based on the project's options.
|
|
15
|
+
#
|
|
16
|
+
# Tweak version pins / cache keys / extra steps freely; do not delete
|
|
17
|
+
# governance-lint or contract-lint without an ADR.
|
|
18
|
+
|
|
7
19
|
jobs:
|
|
8
|
-
|
|
20
|
+
governance-lint:
|
|
9
21
|
runs-on: ubuntu-latest
|
|
10
22
|
steps:
|
|
11
23
|
- uses: actions/checkout@v4
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
24
|
+
- uses: actions/setup-node@v4
|
|
25
|
+
with:
|
|
26
|
+
node-version: '20'
|
|
27
|
+
- name: governance-lint
|
|
28
|
+
run: |
|
|
29
|
+
if [ -f tools/governance-lint/index.js ]; then
|
|
30
|
+
node tools/governance-lint/index.js --strict
|
|
31
|
+
else
|
|
32
|
+
echo "tools/governance-lint/ not present; skipping"
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
secret-scan:
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
with:
|
|
40
|
+
fetch-depth: 0
|
|
41
|
+
- name: gitleaks
|
|
42
|
+
uses: gitleaks/gitleaks-action@v2
|
|
43
|
+
env:
|
|
44
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
45
|
+
|
|
46
|
+
contract-lint:
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v4
|
|
50
|
+
- uses: actions/setup-node@v4
|
|
51
|
+
with:
|
|
52
|
+
node-version: '20'
|
|
53
|
+
<% if (it.options.contract === 'rest' || it.options.contract === 'rest+events') { %> - name: spectral lint (OpenAPI)
|
|
54
|
+
run: npx --yes @stoplight/spectral-cli lint contracts/openapi/api.yaml
|
|
55
|
+
<% } %><% if (it.options.contract === 'rest+events' || it.options.contract === 'events-only') { %> - name: spectral lint (AsyncAPI)
|
|
56
|
+
run: |
|
|
57
|
+
if [ -f contracts/asyncapi/asyncapi.yaml ]; then
|
|
58
|
+
npx --yes @stoplight/spectral-cli lint contracts/asyncapi/asyncapi.yaml
|
|
59
|
+
else
|
|
60
|
+
echo "no asyncapi.yaml; skipping"
|
|
61
|
+
fi
|
|
62
|
+
<% } %> - name: json-schema validate
|
|
63
|
+
run: |
|
|
64
|
+
shopt -s nullglob
|
|
65
|
+
for s in contracts/**/*.schema.json; do
|
|
66
|
+
npx --yes ajv-cli compile -s "$s"
|
|
67
|
+
done
|
|
68
|
+
|
|
69
|
+
<% if (it.options.backend === 'node') { %> server-node:
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
defaults:
|
|
72
|
+
run:
|
|
73
|
+
working-directory: server
|
|
74
|
+
steps:
|
|
75
|
+
- uses: actions/checkout@v4
|
|
76
|
+
- uses: actions/setup-node@v4
|
|
77
|
+
with:
|
|
78
|
+
node-version: '20'
|
|
79
|
+
cache: npm
|
|
80
|
+
cache-dependency-path: server/package-lock.json
|
|
81
|
+
- run: npm ci
|
|
82
|
+
- run: npm run lint --if-present
|
|
83
|
+
- run: npm run typecheck --if-present
|
|
84
|
+
- run: npm test --if-present
|
|
85
|
+
- name: dependency scan
|
|
86
|
+
run: npm audit --audit-level=high
|
|
87
|
+
<% } %><% if (it.options.backend === 'java') { %> server-java:
|
|
88
|
+
runs-on: ubuntu-latest
|
|
89
|
+
defaults:
|
|
90
|
+
run:
|
|
91
|
+
working-directory: server
|
|
92
|
+
steps:
|
|
93
|
+
- uses: actions/checkout@v4
|
|
94
|
+
- uses: actions/setup-java@v4
|
|
95
|
+
with:
|
|
96
|
+
distribution: temurin
|
|
97
|
+
java-version: '21'
|
|
98
|
+
cache: maven
|
|
99
|
+
- run: mvn -B verify
|
|
100
|
+
<% } %><% if (it.options.backend === 'go') { %> server-go:
|
|
101
|
+
runs-on: ubuntu-latest
|
|
102
|
+
defaults:
|
|
103
|
+
run:
|
|
104
|
+
working-directory: server
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@v4
|
|
107
|
+
- uses: actions/setup-go@v5
|
|
108
|
+
with:
|
|
109
|
+
go-version: '1.22'
|
|
110
|
+
- run: go vet ./...
|
|
111
|
+
- run: go test ./...
|
|
112
|
+
- name: govulncheck
|
|
113
|
+
run: |
|
|
114
|
+
go install golang.org/x/vuln/cmd/govulncheck@latest
|
|
115
|
+
govulncheck ./...
|
|
116
|
+
<% } %><% if (it.options.backend === 'python') { %> server-python:
|
|
117
|
+
runs-on: ubuntu-latest
|
|
118
|
+
defaults:
|
|
119
|
+
run:
|
|
120
|
+
working-directory: server
|
|
121
|
+
steps:
|
|
122
|
+
- uses: actions/checkout@v4
|
|
123
|
+
- uses: actions/setup-python@v5
|
|
124
|
+
with:
|
|
125
|
+
python-version: '3.12'
|
|
126
|
+
- run: pip install -e .[dev] || pip install -e .
|
|
127
|
+
- run: ruff check .
|
|
128
|
+
- run: ruff format --check .
|
|
129
|
+
- run: mypy . || true
|
|
130
|
+
- run: pytest -q
|
|
131
|
+
- name: pip-audit
|
|
132
|
+
run: pip install pip-audit && pip-audit
|
|
133
|
+
<% } %>
|
|
134
|
+
<% if (it.options.frontend === 'react' || it.options.frontend === 'vue') { %> web:
|
|
135
|
+
runs-on: ubuntu-latest
|
|
136
|
+
defaults:
|
|
137
|
+
run:
|
|
138
|
+
working-directory: web
|
|
139
|
+
steps:
|
|
140
|
+
- uses: actions/checkout@v4
|
|
141
|
+
- uses: actions/setup-node@v4
|
|
142
|
+
with:
|
|
143
|
+
node-version: '20'
|
|
144
|
+
cache: npm
|
|
145
|
+
cache-dependency-path: web/package-lock.json
|
|
146
|
+
- run: npm ci
|
|
147
|
+
- run: npm run lint --if-present
|
|
148
|
+
- run: npm run typecheck --if-present || npx tsc --noEmit
|
|
149
|
+
- run: npm test --if-present
|
|
150
|
+
- run: npm run build
|
|
16
151
|
- name: dependency scan
|
|
17
|
-
run:
|
|
152
|
+
run: npm audit --audit-level=high
|
|
153
|
+
<% } %>
|
|
154
|
+
<% if (it.options.mobile === 'flutter') { %> mobile-flutter:
|
|
155
|
+
runs-on: ubuntu-latest
|
|
156
|
+
defaults:
|
|
157
|
+
run:
|
|
158
|
+
working-directory: mobile
|
|
159
|
+
steps:
|
|
160
|
+
- uses: actions/checkout@v4
|
|
161
|
+
- uses: subosito/flutter-action@v2
|
|
162
|
+
with:
|
|
163
|
+
channel: stable
|
|
164
|
+
- run: flutter pub get
|
|
165
|
+
- run: flutter analyze
|
|
166
|
+
- run: flutter test
|
|
167
|
+
<% } %><% if (it.options.mobile === 'react-native') { %> mobile-react-native:
|
|
168
|
+
runs-on: ubuntu-latest
|
|
169
|
+
defaults:
|
|
170
|
+
run:
|
|
171
|
+
working-directory: mobile
|
|
172
|
+
steps:
|
|
173
|
+
- uses: actions/checkout@v4
|
|
174
|
+
- uses: actions/setup-node@v4
|
|
175
|
+
with:
|
|
176
|
+
node-version: '20'
|
|
177
|
+
cache: npm
|
|
178
|
+
cache-dependency-path: mobile/package-lock.json
|
|
179
|
+
- run: npm ci
|
|
180
|
+
- run: npm run lint --if-present
|
|
181
|
+
- run: npm test --if-present
|
|
182
|
+
<% } %>
|
|
183
|
+
<% if (it.options.miniapp === 'wechat') { %> miniapp-wechat:
|
|
184
|
+
runs-on: ubuntu-latest
|
|
185
|
+
defaults:
|
|
186
|
+
run:
|
|
187
|
+
working-directory: miniapp
|
|
188
|
+
steps:
|
|
189
|
+
- uses: actions/checkout@v4
|
|
190
|
+
- uses: actions/setup-node@v4
|
|
191
|
+
with:
|
|
192
|
+
node-version: '20'
|
|
193
|
+
- name: typecheck
|
|
194
|
+
run: |
|
|
195
|
+
if [ -f tsconfig.json ]; then npx tsc --noEmit; else echo "no tsconfig"; fi
|
|
196
|
+
<% } %>
|
|
197
|
+
<% if (it.options.agent === 'rust-desktop') { %> agent-rust:
|
|
198
|
+
runs-on: ubuntu-latest
|
|
199
|
+
defaults:
|
|
200
|
+
run:
|
|
201
|
+
working-directory: agent
|
|
202
|
+
steps:
|
|
203
|
+
- uses: actions/checkout@v4
|
|
204
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
205
|
+
with:
|
|
206
|
+
components: clippy, rustfmt
|
|
207
|
+
- run: cargo fmt --check
|
|
208
|
+
- run: cargo clippy --all-targets -- -D warnings
|
|
209
|
+
- run: cargo test
|
|
210
|
+
<% } %>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name: ci-github
|
|
2
|
-
version: 1.
|
|
2
|
+
version: 1.2.0
|
|
3
3
|
appliesWhen:
|
|
4
4
|
ci: github
|
|
5
5
|
priority: 20
|
|
@@ -7,3 +7,6 @@ files:
|
|
|
7
7
|
- from: files/ci.yml
|
|
8
8
|
to: .github/workflows/ci.yml
|
|
9
9
|
render: true
|
|
10
|
+
- from: files/PULL_REQUEST_TEMPLATE.md
|
|
11
|
+
to: .github/PULL_REQUEST_TEMPLATE.md
|
|
12
|
+
render: true
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Spectral lint config for OpenAPI / AsyncAPI contracts.
|
|
2
|
+
#
|
|
3
|
+
# Source of truth referenced by docs/governance/integrations.md.
|
|
4
|
+
# CI runs `npx @stoplight/spectral-cli lint contracts/openapi/api.yaml`
|
|
5
|
+
# and aborts on errors.
|
|
6
|
+
|
|
7
|
+
extends:
|
|
8
|
+
- 'spectral:oas'
|
|
9
|
+
|
|
10
|
+
rules:
|
|
11
|
+
# Make these MUST-have for keel projects.
|
|
12
|
+
operation-operationId: error
|
|
13
|
+
operation-tag-defined: error
|
|
14
|
+
contact-properties: warn
|
|
15
|
+
info-contact: warn
|
|
16
|
+
info-license: warn
|
|
17
|
+
|
|
18
|
+
# Don't enforce description on every parameter — too noisy on first
|
|
19
|
+
# commit. Re-enable per project once the API stabilises.
|
|
20
|
+
operation-description: off
|
|
21
|
+
operation-parameters: warn
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name: contracts-base
|
|
2
|
-
version: 1.
|
|
2
|
+
version: 1.1.0
|
|
3
3
|
appliesWhen: {}
|
|
4
4
|
priority: 10
|
|
5
5
|
files:
|
|
@@ -12,6 +12,9 @@ files:
|
|
|
12
12
|
- from: files/CHANGELOG.md
|
|
13
13
|
to: contracts/CHANGELOG.md
|
|
14
14
|
render: false
|
|
15
|
+
- from: files/_spectral.yaml
|
|
16
|
+
to: contracts/.spectral.yaml
|
|
17
|
+
render: false
|
|
15
18
|
- from: files/dictionaries/domain-models.yaml
|
|
16
19
|
to: contracts/dictionaries/domain-models.yaml
|
|
17
20
|
render: false
|
|
@@ -66,7 +66,7 @@ docs/
|
|
|
66
66
|
| `governance/` | 11 个固定文件名 | ADR-0001 + governance-lint |
|
|
67
67
|
| `assets/` | `diagrams/` + `images/` + `design/` | [`governance/assets.md`](governance/assets.md) 引用约定 |
|
|
68
68
|
| `references/` | `standards/` + `vendors/` + `legal/` | [`governance/docs-references.md`](governance/docs-references.md) 元数据规则 |
|
|
69
|
-
| `过程文档/` | `drafts/` + `meeting-notes/` + `spike-investigations/`
|
|
69
|
+
| `过程文档/` | `drafts/` + `meeting-notes/` + `spike-investigations/` | AGENTS.md §5 |
|
|
70
70
|
|
|
71
71
|
### 5.2 软建议(按项目实际调整)
|
|
72
72
|
|
|
@@ -125,10 +125,10 @@ warning 不是 error——允许"有 PRD 但还没开始设计"的过渡状态
|
|
|
125
125
|
|
|
126
126
|
`docs/governance/` 承载从 AGENTS.md 拆出的专项规则(CI、安全、Git、资产、集成、ops/deploy、tools/scripts、checklist 等)。索引见 [`governance/README.md`](governance/README.md)。
|
|
127
127
|
|
|
128
|
-
<% if (it.options.integrations) { %>##
|
|
128
|
+
<% if (it.options.integrations) { %>## 8. 集成对接入口
|
|
129
129
|
|
|
130
130
|
`docs/06-集成对接/` 已通过 `integrations=true` 启用。完整规则见 [`governance/integrations.md`](governance/integrations.md)。
|
|
131
|
-
<% } else { %>##
|
|
131
|
+
<% } else { %>## 8. 集成对接
|
|
132
132
|
|
|
133
133
|
本仓库未启用 `integrations`。如果未来需要与外部仓库 / 团队对接(例如本仓库只做后端,前端在另一仓库),手动建立 `docs/06-集成对接/` 并参考 [`governance/integrations.md`](governance/integrations.md)。
|
|
134
134
|
<% } %>
|
|
@@ -4,7 +4,7 @@ last-reviewed: <%= it.generatedAt.slice(0, 10) %>
|
|
|
4
4
|
|
|
5
5
|
# 完整检查清单
|
|
6
6
|
|
|
7
|
-
> 入口摘要在 `AGENTS.md` §
|
|
7
|
+
> 入口摘要在 `AGENTS.md` §9。本文件提供完整可勾选清单。
|
|
8
8
|
|
|
9
9
|
## 1. 开发前核对(功能开发启动前)
|
|
10
10
|
|
|
@@ -19,7 +19,7 @@ last-reviewed: <%= it.generatedAt.slice(0, 10) %>
|
|
|
19
19
|
## 2. 提交前核对(PR 发起前)
|
|
20
20
|
|
|
21
21
|
- [ ] `contracts/CHANGELOG.md` 已同步更新
|
|
22
|
-
- [ ] 破坏性变更已按
|
|
22
|
+
- [ ] 破坏性变更已按 [`contracts/README.md`](../../contracts/README.md) 的 SemVer 规则升级 MAJOR
|
|
23
23
|
- [ ] 生成代码已重新生成且 `git diff` 为空
|
|
24
24
|
- [ ] `docs/README.md` 已按需同步(目录地图 / 分类入口 / 子目录约定)
|
|
25
25
|
- [ ] 若启用 `integrations` 且契约变更影响某 pair,该 pair 已同步
|
|
@@ -48,7 +48,7 @@ last-reviewed: <%= it.generatedAt.slice(0, 10) %>
|
|
|
48
48
|
|
|
49
49
|
## 5. 新增脚本 / 工具核对
|
|
50
50
|
|
|
51
|
-
- [ ] 已按
|
|
51
|
+
- [ ] 已按 [`tools-scripts.md`](tools-scripts.md) 判定归属(`scripts/` 或 `tools/`)
|
|
52
52
|
- [ ] `scripts/` 脚本顶部注释包含用途、参数、幂等性、危险级别
|
|
53
53
|
- [ ] `scripts/README.md` 索引已更新
|
|
54
54
|
- [ ] `tools/` 工具含独立 `README.md` 与版本号
|
|
@@ -10,8 +10,12 @@ last-reviewed: <%= it.generatedAt.slice(0, 10) %>
|
|
|
10
10
|
|
|
11
11
|
### 1.1 版本管理
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
13
|
+
- **建议**新增依赖使用精确版本(pinned),尤其是安全敏感库(加密、token、SSO)
|
|
14
|
+
- 实操中允许两种策略:
|
|
15
|
+
- **lockfile-based**(默认):`package.json` 用 `^` 范围 + 提交 `package-lock.json` / `yarn.lock`,CI 跑 `npm ci`(严格按 lockfile)。Node / npm 生态的事实标准
|
|
16
|
+
- **fully-pinned**:`package.json` 用 `=` 精确版本。安全敏感项目或需要 SBOM 严格匹配时使用
|
|
17
|
+
- 真值:lockfile(不是 `package.json`)。`package-lock.json` / `yarn.lock` / `pnpm-lock.yaml` 必须提交
|
|
18
|
+
- 工程规范的 `tech-stack-<env>.md` 钉死表 + `governance-lint stack-pinning` 是更细粒度的版本守门(参见 ADR-0004)
|
|
15
19
|
- 升级依赖独立 PR,便于回滚
|
|
16
20
|
|
|
17
21
|
### 1.2 漏洞扫描
|