@wneng/create-keel 0.3.6 → 0.4.0
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/dist/index.js +206 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/templates/ci-gitee/files/pipeline.yml +62 -0
- package/src/templates/ci-github/files/ci.yml +160 -0
- package/src/templates/db-go-elasticsearch/files/Makefile +18 -0
- package/src/templates/db-go-elasticsearch/files/apply_templates.go +80 -0
- package/src/templates/db-go-elasticsearch/files/db-README.md +57 -0
- package/src/templates/db-go-elasticsearch/files/go.mod +7 -0
- package/src/templates/db-go-elasticsearch/files/index-template-init.json +25 -0
- package/src/templates/db-go-elasticsearch/fragment.yaml +22 -0
- package/src/templates/db-go-migrate-mysql/files/000001_init.down.sql +3 -0
- package/src/templates/db-go-migrate-mysql/files/000001_init.up.sql +35 -0
- package/src/templates/db-go-migrate-mysql/files/Makefile +33 -0
- package/src/templates/db-go-migrate-mysql/files/db-README.md +77 -0
- package/src/templates/db-go-migrate-mysql/files/go.mod +8 -0
- package/src/templates/db-go-migrate-mysql/fragment.yaml +22 -0
- package/src/templates/db-go-migrate-postgres/files/000001_init.down.sql +3 -0
- package/src/templates/db-go-migrate-postgres/files/000001_init.up.sql +32 -0
- package/src/templates/db-go-migrate-postgres/files/Makefile +31 -0
- package/src/templates/db-go-migrate-postgres/files/db-README.md +71 -0
- package/src/templates/db-go-migrate-postgres/files/go.mod +8 -0
- package/src/templates/db-go-migrate-postgres/fragment.yaml +22 -0
- package/src/templates/db-java-elasticsearch/files/EsTemplateApplier.java +86 -0
- package/src/templates/db-java-elasticsearch/files/db-README.md +63 -0
- package/src/templates/db-java-elasticsearch/files/index-template-init.json +25 -0
- package/src/templates/db-java-elasticsearch/files/pom.xml +134 -0
- package/src/templates/db-java-elasticsearch/fragment.yaml +19 -0
- package/src/templates/db-java-flyway-mysql/files/V1__init.sql +44 -0
- package/src/templates/db-java-flyway-mysql/files/application.yaml +39 -0
- package/src/templates/db-java-flyway-mysql/files/db-README.md +102 -0
- package/src/templates/db-java-flyway-mysql/files/pom.xml +172 -0
- package/src/templates/db-java-flyway-mysql/fragment.yaml +19 -0
- package/src/templates/db-java-flyway-postgres/files/V1__init.sql +40 -0
- package/src/templates/db-java-flyway-postgres/files/application.yaml +37 -0
- package/src/templates/db-java-flyway-postgres/files/db-README.md +75 -0
- package/src/templates/db-java-flyway-postgres/files/pom.xml +166 -0
- package/src/templates/db-java-flyway-postgres/fragment.yaml +19 -0
- package/src/templates/db-node-elasticsearch/files/apply-templates.cjs +60 -0
- package/src/templates/db-node-elasticsearch/files/db-README.md +76 -0
- package/src/templates/db-node-elasticsearch/files/index-template-init.json +26 -0
- package/src/templates/db-node-elasticsearch/files/package.json +26 -0
- package/src/templates/db-node-elasticsearch/fragment.yaml +19 -0
- package/src/templates/db-node-knex-mysql/files/db-README.md +90 -0
- package/src/templates/db-node-knex-mysql/files/knexfile.cjs +72 -0
- package/src/templates/db-node-knex-mysql/files/migrations-init.cjs +42 -0
- package/src/templates/db-node-knex-mysql/files/package.json +31 -0
- package/src/templates/db-node-knex-mysql/files/seeds-dev-fixtures.cjs +38 -0
- package/src/templates/db-node-knex-mysql/files/seeds-prod-dictionaries.cjs +25 -0
- package/src/templates/db-node-knex-mysql/fragment.yaml +25 -0
- package/src/templates/db-node-knex-postgres/files/db-README.md +81 -0
- package/src/templates/db-node-knex-postgres/files/knexfile.cjs +67 -0
- package/src/templates/db-node-knex-postgres/files/migrations-init.cjs +42 -0
- package/src/templates/db-node-knex-postgres/files/package.json +31 -0
- package/src/templates/db-node-knex-postgres/files/seeds-dev-fixtures.cjs +36 -0
- package/src/templates/db-node-knex-postgres/files/seeds-prod-dictionaries.cjs +26 -0
- package/src/templates/db-node-knex-postgres/fragment.yaml +25 -0
- package/src/templates/db-python-alembic-mysql/files/0001_init.py +70 -0
- package/src/templates/db-python-alembic-mysql/files/alembic.ini +47 -0
- package/src/templates/db-python-alembic-mysql/files/db-README.md +87 -0
- package/src/templates/db-python-alembic-mysql/files/env.py +71 -0
- package/src/templates/db-python-alembic-mysql/files/pyproject.toml +52 -0
- package/src/templates/db-python-alembic-mysql/files/script.py.mako +26 -0
- package/src/templates/db-python-alembic-mysql/fragment.yaml +25 -0
- package/src/templates/db-python-alembic-postgres/files/0001_init.py +62 -0
- package/src/templates/db-python-alembic-postgres/files/alembic.ini +45 -0
- package/src/templates/db-python-alembic-postgres/files/db-README.md +70 -0
- package/src/templates/db-python-alembic-postgres/files/env.py +62 -0
- package/src/templates/db-python-alembic-postgres/files/pyproject.toml +52 -0
- package/src/templates/db-python-alembic-postgres/files/script.py.mako +25 -0
- package/src/templates/db-python-alembic-postgres/fragment.yaml +25 -0
- package/src/templates/db-python-elasticsearch/files/apply_templates.py +55 -0
- package/src/templates/db-python-elasticsearch/files/db-README.md +57 -0
- package/src/templates/db-python-elasticsearch/files/index-template-init.json +25 -0
- package/src/templates/db-python-elasticsearch/files/pyproject.toml +50 -0
- package/src/templates/db-python-elasticsearch/fragment.yaml +19 -0
- package/src/templates/docs-skeleton/files/governance-database.md +150 -0
- package/src/templates/docs-skeleton/fragment.yaml +3 -0
- package/src/templates/root-files/files/AGENTS.md +6 -2
- package/src/templates/server-python/files/README.md +75 -2
- package/src/templates/server-python/files/app-init.py +11 -1
- package/src/templates/server-python/files/config.py +40 -0
- package/src/templates/server-python/files/main.py +62 -0
- package/src/templates/server-python/files/pyproject.toml +14 -1
- package/src/templates/server-python/files/test_healthz.py +36 -0
- package/src/templates/server-python/fragment.yaml +10 -1
package/package.json
CHANGED
|
@@ -136,6 +136,68 @@ jobs:
|
|
|
136
136
|
script:
|
|
137
137
|
- gitleaks detect --redact --no-git -v
|
|
138
138
|
|
|
139
|
+
<% if (it.options.database === 'mysql' || it.options.database === 'postgres') { %> db-migrate-smoke:
|
|
140
|
+
stage: test
|
|
141
|
+
<% if (it.options.database === 'postgres') { %> image: postgres:16-alpine
|
|
142
|
+
services:
|
|
143
|
+
- name: postgres:16-alpine
|
|
144
|
+
alias: postgres
|
|
145
|
+
env:
|
|
146
|
+
POSTGRES_PASSWORD: postgres
|
|
147
|
+
POSTGRES_DB: ci_smoke
|
|
148
|
+
<% } else { %> image: mysql:8
|
|
149
|
+
services:
|
|
150
|
+
- name: mysql:8
|
|
151
|
+
alias: mysql
|
|
152
|
+
env:
|
|
153
|
+
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
|
|
154
|
+
MYSQL_DATABASE: ci_smoke
|
|
155
|
+
<% } %> script:
|
|
156
|
+
- cd server
|
|
157
|
+
<% if (it.options.backend === 'node') { %> - apk add --no-cache nodejs npm || true
|
|
158
|
+
- npm ci
|
|
159
|
+
<% if (it.options.database === 'postgres') { %> - DB_HOST=postgres DB_PORT=5432 DB_USER=postgres DB_PASSWORD=postgres DB_NAME=ci_smoke npm run db:migrate
|
|
160
|
+
- DB_HOST=postgres DB_PORT=5432 DB_USER=postgres DB_PASSWORD=postgres DB_NAME=ci_smoke npm run db:rollback
|
|
161
|
+
<% } else { %> - DB_HOST=mysql DB_PORT=3306 DB_USER=root DB_PASSWORD= DB_NAME=ci_smoke npm run db:migrate
|
|
162
|
+
- DB_HOST=mysql DB_PORT=3306 DB_USER=root DB_PASSWORD= DB_NAME=ci_smoke npm run db:rollback
|
|
163
|
+
<% } %><% } %><% if (it.options.backend === 'java') { %> - apk add --no-cache maven openjdk21 || true
|
|
164
|
+
<% if (it.options.database === 'postgres') { %> - SPRING_DATASOURCE_URL='jdbc:postgresql://postgres:5432/ci_smoke' SPRING_DATASOURCE_USERNAME=postgres SPRING_DATASOURCE_PASSWORD=postgres mvn -B flyway:migrate
|
|
165
|
+
- SPRING_DATASOURCE_URL='jdbc:postgresql://postgres:5432/ci_smoke' SPRING_DATASOURCE_USERNAME=postgres SPRING_DATASOURCE_PASSWORD=postgres mvn -B flyway:validate
|
|
166
|
+
<% } else { %> - SPRING_DATASOURCE_URL='jdbc:mysql://mysql:3306/ci_smoke?useSSL=false&serverTimezone=UTC' SPRING_DATASOURCE_USERNAME=root SPRING_DATASOURCE_PASSWORD= mvn -B flyway:migrate
|
|
167
|
+
- SPRING_DATASOURCE_URL='jdbc:mysql://mysql:3306/ci_smoke?useSSL=false&serverTimezone=UTC' SPRING_DATASOURCE_USERNAME=root SPRING_DATASOURCE_PASSWORD= mvn -B flyway:validate
|
|
168
|
+
<% } %><% } %><% if (it.options.backend === 'python') { %> - apk add --no-cache python3 py3-pip || true
|
|
169
|
+
- pip install -e .
|
|
170
|
+
<% if (it.options.database === 'postgres') { %> - DATABASE_URL='postgresql+psycopg://postgres:postgres@postgres:5432/ci_smoke' alembic upgrade head
|
|
171
|
+
- DATABASE_URL='postgresql+psycopg://postgres:postgres@postgres:5432/ci_smoke' alembic downgrade base
|
|
172
|
+
<% } else { %> - DATABASE_URL='mysql+pymysql://root:@mysql:3306/ci_smoke' alembic upgrade head
|
|
173
|
+
- DATABASE_URL='mysql+pymysql://root:@mysql:3306/ci_smoke' alembic downgrade base
|
|
174
|
+
<% } %><% } %><% if (it.options.backend === 'go') { %> - apk add --no-cache go || true
|
|
175
|
+
- go install -tags '<%= it.options.database %>' github.com/golang-migrate/migrate/v4/cmd/migrate@v4.18.1
|
|
176
|
+
<% if (it.options.database === 'postgres') { %> - DATABASE_URL='postgres://postgres:postgres@postgres:5432/ci_smoke?sslmode=disable' migrate -path db/migrations -database "$DATABASE_URL" up
|
|
177
|
+
- DATABASE_URL='postgres://postgres:postgres@postgres:5432/ci_smoke?sslmode=disable' migrate -path db/migrations -database "$DATABASE_URL" down -all
|
|
178
|
+
<% } else { %> - DATABASE_URL='mysql://root:@tcp(mysql:3306)/ci_smoke?multiStatements=true' migrate -path db/migrations -database "$DATABASE_URL" up
|
|
179
|
+
- DATABASE_URL='mysql://root:@tcp(mysql:3306)/ci_smoke?multiStatements=true' migrate -path db/migrations -database "$DATABASE_URL" down -all
|
|
180
|
+
<% } %><% } %><% } %>
|
|
181
|
+
<% if (it.options.database === 'elasticsearch') { %> db-es-template-apply:
|
|
182
|
+
stage: test
|
|
183
|
+
image: <%= it.options.backend === 'node' ? 'node:20-alpine' : it.options.backend === 'java' ? 'maven:3.9-eclipse-temurin-21' : it.options.backend === 'python' ? 'python:3.12-slim' : 'golang:1.22-alpine' %>
|
|
184
|
+
services:
|
|
185
|
+
- name: elasticsearch:8.15.1
|
|
186
|
+
alias: elasticsearch
|
|
187
|
+
env:
|
|
188
|
+
discovery.type: single-node
|
|
189
|
+
xpack.security.enabled: 'false'
|
|
190
|
+
ES_JAVA_OPTS: '-Xms512m -Xmx512m'
|
|
191
|
+
script:
|
|
192
|
+
- cd server
|
|
193
|
+
<% if (it.options.backend === 'node') { %> - npm ci
|
|
194
|
+
- ELASTICSEARCH_URL=http://elasticsearch:9200 npm run es:apply
|
|
195
|
+
<% } %><% if (it.options.backend === 'java') { %> - SPRING_ELASTICSEARCH_URIS=http://elasticsearch:9200 mvn -B test -Dtest=*ApplicationTests
|
|
196
|
+
<% } %><% if (it.options.backend === 'python') { %> - pip install -e .
|
|
197
|
+
- ELASTICSEARCH_URL=http://elasticsearch:9200 python db/apply_templates.py
|
|
198
|
+
<% } %><% if (it.options.backend === 'go') { %> - go mod download
|
|
199
|
+
- ELASTICSEARCH_URL=http://elasticsearch:9200 make es-apply
|
|
200
|
+
<% } %><% } %>
|
|
139
201
|
<% if (it.options.backend === 'node' || it.options.frontend === 'react' || it.options.frontend === 'vue' || it.options.mobile === 'react-native' || it.options.miniapp === 'wechat') { %> npm-audit:
|
|
140
202
|
stage: scan
|
|
141
203
|
image: node:20-alpine
|
|
@@ -217,3 +217,163 @@ jobs:
|
|
|
217
217
|
- run: cargo clippy --all-targets -- -D warnings
|
|
218
218
|
- run: cargo test
|
|
219
219
|
<% } %>
|
|
220
|
+
<% if (it.options.database === 'mysql' || it.options.database === 'postgres') { %> db-migrate-smoke:
|
|
221
|
+
runs-on: ubuntu-latest
|
|
222
|
+
defaults:
|
|
223
|
+
run:
|
|
224
|
+
working-directory: server
|
|
225
|
+
services:
|
|
226
|
+
<% if (it.options.database === 'postgres') { %> postgres:
|
|
227
|
+
image: postgres:16-alpine
|
|
228
|
+
env:
|
|
229
|
+
POSTGRES_PASSWORD: postgres
|
|
230
|
+
POSTGRES_DB: ci_smoke
|
|
231
|
+
ports: ['5432:5432']
|
|
232
|
+
options: >-
|
|
233
|
+
--health-cmd pg_isready
|
|
234
|
+
--health-interval 10s
|
|
235
|
+
--health-timeout 5s
|
|
236
|
+
--health-retries 5
|
|
237
|
+
<% } else { %> mysql:
|
|
238
|
+
image: mysql:8
|
|
239
|
+
env:
|
|
240
|
+
MYSQL_ROOT_PASSWORD: ''
|
|
241
|
+
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
|
|
242
|
+
MYSQL_DATABASE: ci_smoke
|
|
243
|
+
ports: ['3306:3306']
|
|
244
|
+
options: >-
|
|
245
|
+
--health-cmd "mysqladmin ping -h localhost"
|
|
246
|
+
--health-interval 10s
|
|
247
|
+
--health-timeout 5s
|
|
248
|
+
--health-retries 5
|
|
249
|
+
<% } %> steps:
|
|
250
|
+
- uses: actions/checkout@v4
|
|
251
|
+
<% if (it.options.backend === 'node') { %> - uses: actions/setup-node@v4
|
|
252
|
+
with:
|
|
253
|
+
node-version: '20'
|
|
254
|
+
cache: npm
|
|
255
|
+
cache-dependency-path: server/package-lock.json
|
|
256
|
+
- run: npm ci
|
|
257
|
+
- name: migrate up
|
|
258
|
+
env:
|
|
259
|
+
<% if (it.options.database === 'postgres') { %> DB_HOST: 127.0.0.1
|
|
260
|
+
DB_PORT: '5432'
|
|
261
|
+
DB_USER: postgres
|
|
262
|
+
DB_PASSWORD: postgres
|
|
263
|
+
DB_NAME: ci_smoke
|
|
264
|
+
<% } else { %> DB_HOST: 127.0.0.1
|
|
265
|
+
DB_PORT: '3306'
|
|
266
|
+
DB_USER: root
|
|
267
|
+
DB_PASSWORD: ''
|
|
268
|
+
DB_NAME: ci_smoke
|
|
269
|
+
<% } %> run: npm run db:migrate
|
|
270
|
+
- name: migrate down
|
|
271
|
+
env:
|
|
272
|
+
<% if (it.options.database === 'postgres') { %> DB_HOST: 127.0.0.1
|
|
273
|
+
DB_PORT: '5432'
|
|
274
|
+
DB_USER: postgres
|
|
275
|
+
DB_PASSWORD: postgres
|
|
276
|
+
DB_NAME: ci_smoke
|
|
277
|
+
<% } else { %> DB_HOST: 127.0.0.1
|
|
278
|
+
DB_PORT: '3306'
|
|
279
|
+
DB_USER: root
|
|
280
|
+
DB_PASSWORD: ''
|
|
281
|
+
DB_NAME: ci_smoke
|
|
282
|
+
<% } %> run: npm run db:rollback
|
|
283
|
+
<% } %><% if (it.options.backend === 'java') { %> - uses: actions/setup-java@v4
|
|
284
|
+
with:
|
|
285
|
+
distribution: temurin
|
|
286
|
+
java-version: '21'
|
|
287
|
+
cache: maven
|
|
288
|
+
- name: flyway migrate + validate
|
|
289
|
+
env:
|
|
290
|
+
<% if (it.options.database === 'postgres') { %> SPRING_DATASOURCE_URL: jdbc:postgresql://127.0.0.1:5432/ci_smoke
|
|
291
|
+
SPRING_DATASOURCE_USERNAME: postgres
|
|
292
|
+
SPRING_DATASOURCE_PASSWORD: postgres
|
|
293
|
+
<% } else { %> SPRING_DATASOURCE_URL: jdbc:mysql://127.0.0.1:3306/ci_smoke?useSSL=false&serverTimezone=UTC
|
|
294
|
+
SPRING_DATASOURCE_USERNAME: root
|
|
295
|
+
SPRING_DATASOURCE_PASSWORD: ''
|
|
296
|
+
<% } %> run: |
|
|
297
|
+
mvn -B flyway:migrate
|
|
298
|
+
mvn -B flyway:validate
|
|
299
|
+
<% } %><% if (it.options.backend === 'python') { %> - uses: actions/setup-python@v5
|
|
300
|
+
with:
|
|
301
|
+
python-version: '3.12'
|
|
302
|
+
- run: pip install -e .
|
|
303
|
+
- name: alembic upgrade head + downgrade base
|
|
304
|
+
env:
|
|
305
|
+
<% if (it.options.database === 'postgres') { %> DATABASE_URL: postgresql+psycopg://postgres:postgres@127.0.0.1:5432/ci_smoke
|
|
306
|
+
<% } else { %> DATABASE_URL: mysql+pymysql://root:@127.0.0.1:3306/ci_smoke
|
|
307
|
+
<% } %> run: |
|
|
308
|
+
alembic upgrade head
|
|
309
|
+
alembic downgrade base
|
|
310
|
+
<% } %><% if (it.options.backend === 'go') { %> - uses: actions/setup-go@v5
|
|
311
|
+
with:
|
|
312
|
+
go-version: '1.22'
|
|
313
|
+
- name: install golang-migrate
|
|
314
|
+
run: |
|
|
315
|
+
go install -tags '<%= it.options.database %>' github.com/golang-migrate/migrate/v4/cmd/migrate@v4.18.1
|
|
316
|
+
- name: migrate up + down
|
|
317
|
+
env:
|
|
318
|
+
<% if (it.options.database === 'postgres') { %> DATABASE_URL: postgres://postgres:postgres@127.0.0.1:5432/ci_smoke?sslmode=disable
|
|
319
|
+
<% } else { %> DATABASE_URL: mysql://root:@tcp(127.0.0.1:3306)/ci_smoke?multiStatements=true
|
|
320
|
+
<% } %> run: |
|
|
321
|
+
migrate -path db/migrations -database "$DATABASE_URL" up
|
|
322
|
+
migrate -path db/migrations -database "$DATABASE_URL" down -all
|
|
323
|
+
<% } %><% } %>
|
|
324
|
+
<% if (it.options.database === 'elasticsearch') { %> db-es-template-apply:
|
|
325
|
+
runs-on: ubuntu-latest
|
|
326
|
+
defaults:
|
|
327
|
+
run:
|
|
328
|
+
working-directory: server
|
|
329
|
+
services:
|
|
330
|
+
elasticsearch:
|
|
331
|
+
image: elasticsearch:8.15.1
|
|
332
|
+
env:
|
|
333
|
+
discovery.type: single-node
|
|
334
|
+
xpack.security.enabled: 'false'
|
|
335
|
+
ES_JAVA_OPTS: '-Xms512m -Xmx512m'
|
|
336
|
+
ports: ['9200:9200']
|
|
337
|
+
options: >-
|
|
338
|
+
--health-cmd "curl -fsS http://localhost:9200/_cluster/health"
|
|
339
|
+
--health-interval 10s
|
|
340
|
+
--health-timeout 5s
|
|
341
|
+
--health-retries 12
|
|
342
|
+
steps:
|
|
343
|
+
- uses: actions/checkout@v4
|
|
344
|
+
<% if (it.options.backend === 'node') { %> - uses: actions/setup-node@v4
|
|
345
|
+
with:
|
|
346
|
+
node-version: '20'
|
|
347
|
+
cache: npm
|
|
348
|
+
cache-dependency-path: server/package-lock.json
|
|
349
|
+
- run: npm ci
|
|
350
|
+
- name: apply index templates
|
|
351
|
+
env:
|
|
352
|
+
ELASTICSEARCH_URL: http://127.0.0.1:9200
|
|
353
|
+
run: npm run es:apply
|
|
354
|
+
<% } %><% if (it.options.backend === 'java') { %> - uses: actions/setup-java@v4
|
|
355
|
+
with:
|
|
356
|
+
distribution: temurin
|
|
357
|
+
java-version: '21'
|
|
358
|
+
cache: maven
|
|
359
|
+
- name: spring boot starts and applies templates
|
|
360
|
+
env:
|
|
361
|
+
SPRING_ELASTICSEARCH_URIS: http://127.0.0.1:9200
|
|
362
|
+
run: mvn -B test -Dtest=*ApplicationTests
|
|
363
|
+
<% } %><% if (it.options.backend === 'python') { %> - uses: actions/setup-python@v5
|
|
364
|
+
with:
|
|
365
|
+
python-version: '3.12'
|
|
366
|
+
- run: pip install -e .
|
|
367
|
+
- name: apply index templates
|
|
368
|
+
env:
|
|
369
|
+
ELASTICSEARCH_URL: http://127.0.0.1:9200
|
|
370
|
+
run: python db/apply_templates.py
|
|
371
|
+
<% } %><% if (it.options.backend === 'go') { %> - uses: actions/setup-go@v5
|
|
372
|
+
with:
|
|
373
|
+
go-version: '1.22'
|
|
374
|
+
- run: go mod download
|
|
375
|
+
- name: apply index templates
|
|
376
|
+
env:
|
|
377
|
+
ELASTICSEARCH_URL: http://127.0.0.1:9200
|
|
378
|
+
run: make es-apply
|
|
379
|
+
<% } %><% } %>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
.PHONY: build test lint run es-apply
|
|
2
|
+
|
|
3
|
+
ELASTICSEARCH_URL ?= http://127.0.0.1:9200
|
|
4
|
+
|
|
5
|
+
build:
|
|
6
|
+
go build -o ./bin/server ./cmd/server
|
|
7
|
+
|
|
8
|
+
run:
|
|
9
|
+
go run ./cmd/server
|
|
10
|
+
|
|
11
|
+
test:
|
|
12
|
+
go test ./...
|
|
13
|
+
|
|
14
|
+
lint:
|
|
15
|
+
golangci-lint run
|
|
16
|
+
|
|
17
|
+
es-apply:
|
|
18
|
+
go run ./cmd/apply-templates
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Idempotent Elasticsearch index-template applier (Go).
|
|
2
|
+
//
|
|
3
|
+
// ES 没有事务性 DDL;"migration" 退化为把 db/index-templates/*.json 全部 PUT 一次。
|
|
4
|
+
// ES 自身保证 PUT 同名 template 的幂等性。
|
|
5
|
+
//
|
|
6
|
+
// 改动 tier(参见 docs/governance/change-tiers.md):
|
|
7
|
+
// - 新增 template 文件:Tier 3
|
|
8
|
+
// - 修改既有 template 的 mapping:Tier 4(破坏性 - 可能 reindex)
|
|
9
|
+
// - 仅改 priority / 新增 alias:Tier 2
|
|
10
|
+
package main
|
|
11
|
+
|
|
12
|
+
import (
|
|
13
|
+
"bytes"
|
|
14
|
+
"context"
|
|
15
|
+
"fmt"
|
|
16
|
+
"log"
|
|
17
|
+
"os"
|
|
18
|
+
"path/filepath"
|
|
19
|
+
"sort"
|
|
20
|
+
"strings"
|
|
21
|
+
"time"
|
|
22
|
+
|
|
23
|
+
"github.com/elastic/go-elasticsearch/v8"
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
const templateDir = "db/index-templates"
|
|
27
|
+
|
|
28
|
+
func main() {
|
|
29
|
+
url := os.Getenv("ELASTICSEARCH_URL")
|
|
30
|
+
if url == "" {
|
|
31
|
+
url = "http://127.0.0.1:9200"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
cfg := elasticsearch.Config{Addresses: []string{url}}
|
|
35
|
+
if u := os.Getenv("ELASTICSEARCH_USERNAME"); u != "" {
|
|
36
|
+
cfg.Username = u
|
|
37
|
+
cfg.Password = os.Getenv("ELASTICSEARCH_PASSWORD")
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
es, err := elasticsearch.NewClient(cfg)
|
|
41
|
+
if err != nil {
|
|
42
|
+
log.Fatalf("✗ es client: %v", err)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 简易健康检查
|
|
46
|
+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
47
|
+
defer cancel()
|
|
48
|
+
if _, err := es.Cluster.Health(es.Cluster.Health.WithContext(ctx)); err != nil {
|
|
49
|
+
log.Fatalf("✗ es health: %v", err)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
files, err := filepath.Glob(filepath.Join(templateDir, "*.json"))
|
|
53
|
+
if err != nil {
|
|
54
|
+
log.Fatalf("✗ glob: %v", err)
|
|
55
|
+
}
|
|
56
|
+
sort.Strings(files)
|
|
57
|
+
if len(files) == 0 {
|
|
58
|
+
fmt.Println("no index templates found in", templateDir)
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
for _, path := range files {
|
|
63
|
+
body, err := os.ReadFile(path)
|
|
64
|
+
if err != nil {
|
|
65
|
+
log.Fatalf("✗ read %s: %v", path, err)
|
|
66
|
+
}
|
|
67
|
+
name := strings.TrimSuffix(filepath.Base(path), ".json")
|
|
68
|
+
res, err := es.Indices.PutIndexTemplate(name, bytes.NewReader(body))
|
|
69
|
+
if err != nil {
|
|
70
|
+
log.Fatalf("✗ apply %s: %v", name, err)
|
|
71
|
+
}
|
|
72
|
+
if res.IsError() {
|
|
73
|
+
log.Fatalf("✗ apply %s: %s", name, res.String())
|
|
74
|
+
}
|
|
75
|
+
_ = res.Body.Close()
|
|
76
|
+
fmt.Printf("✓ applied %s\n", name)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
fmt.Printf("done; %d template(s) applied to %s\n", len(files), url)
|
|
80
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# server/db/
|
|
2
|
+
|
|
3
|
+
Elasticsearch index-template 入口(Go 后端)。
|
|
4
|
+
|
|
5
|
+
> 跨项目的数据库归属规则见 [`docs/governance/database.md`](../../docs/governance/database.md)。
|
|
6
|
+
|
|
7
|
+
## "Migration" 的语义
|
|
8
|
+
|
|
9
|
+
**Elasticsearch 没有事务性 DDL,本目录里的 JSON 不是迁移文件。**
|
|
10
|
+
|
|
11
|
+
每个 `db/index-templates/*.json` 是一个 [Index Template v2](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-templates.html)。`cmd/apply-templates/main.go` 按文件名字典序遍历目录,对每个文件 PUT;ES 自身保证幂等。
|
|
12
|
+
|
|
13
|
+
## 工具与版本
|
|
14
|
+
|
|
15
|
+
| 项 | 值 |
|
|
16
|
+
|---|---|
|
|
17
|
+
| Elasticsearch | 8.15+ |
|
|
18
|
+
| Go 客户端 | `github.com/elastic/go-elasticsearch/v8` `8.15.0` |
|
|
19
|
+
|
|
20
|
+
## 目录布局
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
server/
|
|
24
|
+
├── go.mod
|
|
25
|
+
├── Makefile # `make es-apply` 入口
|
|
26
|
+
├── cmd/apply-templates/
|
|
27
|
+
│ └── main.go # 幂等 applier
|
|
28
|
+
└── db/
|
|
29
|
+
├── README.md
|
|
30
|
+
└── index-templates/
|
|
31
|
+
└── <NNNNNN>_<description>.json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 常用命令
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
make es-apply # 把 db/index-templates/*.json 全部 PUT 一次
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
环境变量 `ELASTICSEARCH_URL`(默认 `http://127.0.0.1:9200`)、`ELASTICSEARCH_USERNAME` / `ELASTICSEARCH_PASSWORD`(可选)。
|
|
41
|
+
|
|
42
|
+
## 改动分级(参见 `docs/governance/change-tiers.md`)
|
|
43
|
+
|
|
44
|
+
| 改动 | Tier |
|
|
45
|
+
|---|---|
|
|
46
|
+
| 新增 template 文件 | 3 |
|
|
47
|
+
| 修改既有 template 的 mapping 字段 | 4(破坏性 - 可能 reindex) |
|
|
48
|
+
| 仅改 priority / 新增 alias / 改 settings.refresh_interval | 2 |
|
|
49
|
+
| 删除 template | 4 |
|
|
50
|
+
|
|
51
|
+
## 与 `contracts/asyncapi/` 的同步
|
|
52
|
+
|
|
53
|
+
事件 ingest 的 schema 真值在 `contracts/asyncapi/asyncapi.yaml`;index-template 的 mapping 应当与之**对齐**。当前手动同步。
|
|
54
|
+
|
|
55
|
+
## CI 行为
|
|
56
|
+
|
|
57
|
+
CI 起一个 ES 8 service container;`make es-apply` 失败 = CI 红。
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"index_patterns": ["events-*"],
|
|
3
|
+
"priority": 100,
|
|
4
|
+
"template": {
|
|
5
|
+
"settings": {
|
|
6
|
+
"number_of_shards": 1,
|
|
7
|
+
"number_of_replicas": 1,
|
|
8
|
+
"refresh_interval": "5s"
|
|
9
|
+
},
|
|
10
|
+
"mappings": {
|
|
11
|
+
"properties": {
|
|
12
|
+
"@timestamp": { "type": "date" },
|
|
13
|
+
"tenant_id": { "type": "keyword" },
|
|
14
|
+
"event_type": { "type": "keyword" },
|
|
15
|
+
"user_id": { "type": "keyword" },
|
|
16
|
+
"payload": { "type": "object", "dynamic": true },
|
|
17
|
+
"trace_id": { "type": "keyword" }
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"_meta": {
|
|
22
|
+
"description": "Sample event-stream template. Replace mappings with your domain fields.",
|
|
23
|
+
"managed_by": "@wneng/create-keel"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: db-go-elasticsearch
|
|
2
|
+
version: 1.0.0
|
|
3
|
+
appliesWhen:
|
|
4
|
+
backend: go
|
|
5
|
+
database: elasticsearch
|
|
6
|
+
priority: 40
|
|
7
|
+
files:
|
|
8
|
+
- from: files/go.mod
|
|
9
|
+
to: server/go.mod
|
|
10
|
+
render: true
|
|
11
|
+
- from: files/Makefile
|
|
12
|
+
to: server/Makefile
|
|
13
|
+
render: true
|
|
14
|
+
- from: files/apply_templates.go
|
|
15
|
+
to: server/cmd/apply-templates/main.go
|
|
16
|
+
render: false
|
|
17
|
+
- from: files/index-template-init.json
|
|
18
|
+
to: server/db/index-templates/000001_init.json
|
|
19
|
+
render: false
|
|
20
|
+
- from: files/db-README.md
|
|
21
|
+
to: server/db/README.md
|
|
22
|
+
render: true
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
-- 000001_init.up.sql — 初始化迁移
|
|
2
|
+
--
|
|
3
|
+
-- 命名规则:<NNNNNN>_<description>.up.sql / .down.sql。
|
|
4
|
+
-- 已合入 main 不可修改;改 schema 写新文件 NNNNNN+1。
|
|
5
|
+
|
|
6
|
+
CREATE TABLE IF NOT EXISTS roles (
|
|
7
|
+
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
8
|
+
code VARCHAR(64) NOT NULL,
|
|
9
|
+
name VARCHAR(128) NOT NULL,
|
|
10
|
+
description TEXT NULL,
|
|
11
|
+
created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
|
12
|
+
updated_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
|
13
|
+
PRIMARY KEY (id),
|
|
14
|
+
UNIQUE KEY uk_roles_code (code)
|
|
15
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
16
|
+
|
|
17
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
18
|
+
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
19
|
+
email VARCHAR(255) NOT NULL,
|
|
20
|
+
password_hash VARCHAR(255) NOT NULL,
|
|
21
|
+
display_name VARCHAR(128) NULL,
|
|
22
|
+
role_id BIGINT UNSIGNED NOT NULL,
|
|
23
|
+
created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
|
24
|
+
updated_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
|
25
|
+
deleted_at TIMESTAMP(6) NULL,
|
|
26
|
+
PRIMARY KEY (id),
|
|
27
|
+
UNIQUE KEY uk_users_email (email),
|
|
28
|
+
KEY idx_users_role_id (role_id),
|
|
29
|
+
KEY idx_users_deleted_at (deleted_at),
|
|
30
|
+
CONSTRAINT fk_users_role FOREIGN KEY (role_id) REFERENCES roles (id)
|
|
31
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
32
|
+
|
|
33
|
+
INSERT IGNORE INTO roles (code, name, description) VALUES
|
|
34
|
+
('admin', '系统管理员', '可执行所有管理操作'),
|
|
35
|
+
('user', '普通用户', '默认注册角色');
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
.PHONY: build test lint run db-up db-down db-status db-create
|
|
2
|
+
|
|
3
|
+
# Default DSN: localhost MySQL with the project name as DB. Production
|
|
4
|
+
# overrides via DATABASE_URL env var.
|
|
5
|
+
DATABASE_URL ?= mysql://root:@tcp(127.0.0.1:3306)/<%= it.options.projectName %>_dev?multiStatements=true
|
|
6
|
+
|
|
7
|
+
# golang-migrate CLI: install with `go install github.com/golang-migrate/migrate/v4/cmd/migrate@v4.18.1`
|
|
8
|
+
MIGRATE := migrate -path db/migrations -database "$(DATABASE_URL)"
|
|
9
|
+
|
|
10
|
+
build:
|
|
11
|
+
go build -o ./bin/server ./cmd/server
|
|
12
|
+
|
|
13
|
+
run:
|
|
14
|
+
go run ./cmd/server
|
|
15
|
+
|
|
16
|
+
test:
|
|
17
|
+
go test ./...
|
|
18
|
+
|
|
19
|
+
lint:
|
|
20
|
+
golangci-lint run
|
|
21
|
+
|
|
22
|
+
db-up:
|
|
23
|
+
$(MIGRATE) up
|
|
24
|
+
|
|
25
|
+
db-down:
|
|
26
|
+
$(MIGRATE) down 1
|
|
27
|
+
|
|
28
|
+
db-status:
|
|
29
|
+
$(MIGRATE) version
|
|
30
|
+
|
|
31
|
+
# Usage: make db-create name=create_orders
|
|
32
|
+
db-create:
|
|
33
|
+
$(MIGRATE) create -ext sql -dir db/migrations -seq $(name)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# server/db/
|
|
2
|
+
|
|
3
|
+
数据库迁移、种子数据、本地数据库工具的入口。
|
|
4
|
+
|
|
5
|
+
> 跨项目的数据库归属规则见 [`docs/governance/database.md`](../../docs/governance/database.md)。
|
|
6
|
+
|
|
7
|
+
## 工具与版本
|
|
8
|
+
|
|
9
|
+
| 项 | 值 |
|
|
10
|
+
|---|---|
|
|
11
|
+
| 数据库 | MySQL 8 / MariaDB 10.6+ |
|
|
12
|
+
| 迁移工具 | [golang-migrate](https://github.com/golang-migrate/migrate) `v4.18.1` |
|
|
13
|
+
| 驱动 | `github.com/go-sql-driver/mysql` `v1.8.1` |
|
|
14
|
+
|
|
15
|
+
需要本地安装 CLI:
|
|
16
|
+
```bash
|
|
17
|
+
go install -tags 'mysql' github.com/golang-migrate/migrate/v4/cmd/migrate@v4.18.1
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
工具版本在 `go.mod` 钉死,并镜像到 `docs/03-工程规范与研发基础设施/tech-stack-server.md`。
|
|
21
|
+
|
|
22
|
+
## 目录布局
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
server/
|
|
26
|
+
├── go.mod
|
|
27
|
+
├── Makefile # db-up / db-down / db-create 入口
|
|
28
|
+
└── db/
|
|
29
|
+
├── README.md
|
|
30
|
+
└── migrations/
|
|
31
|
+
├── <NNNNNN>_<description>.up.sql
|
|
32
|
+
└── <NNNNNN>_<description>.down.sql
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 文件命名规则
|
|
36
|
+
|
|
37
|
+
- 迁移成对出现:`<NNNNNN>_<description>.up.sql` + `.down.sql`
|
|
38
|
+
- 6 位序号,`make db-create name=...` 自动递增
|
|
39
|
+
- 已合入 main 不可修改;改 schema 写新成对文件
|
|
40
|
+
|
|
41
|
+
## 常用命令
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
make db-create name=create_orders # 新建迁移成对文件
|
|
45
|
+
make db-up # 升到最新
|
|
46
|
+
make db-down # 回滚最近一条
|
|
47
|
+
make db-status # 查看当前版本
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
环境变量 `DATABASE_URL`(默认 `mysql://root:@tcp(127.0.0.1:3306)/<project>_dev?multiStatements=true`)。
|
|
51
|
+
|
|
52
|
+
## prod vs dev seeds
|
|
53
|
+
|
|
54
|
+
| 类型 | 位置 |
|
|
55
|
+
|---|---|
|
|
56
|
+
| 生产字典(必装) | 写进迁移文件的 INSERT IGNORE 语句 |
|
|
57
|
+
| 开发样例 | `server/db/seeds/dev/` 下手动执行 |
|
|
58
|
+
|
|
59
|
+
字典类生产种子真值在 `contracts/dictionaries/enums.yaml`;当前手动同步。
|
|
60
|
+
|
|
61
|
+
## 改动分级(参见 `docs/governance/change-tiers.md`)
|
|
62
|
+
|
|
63
|
+
| 改动 | Tier |
|
|
64
|
+
|---|---|
|
|
65
|
+
| 新增迁移加表 / 加字段 | 3 |
|
|
66
|
+
| 修改既有迁移 | **不允许** |
|
|
67
|
+
| 删字段 / 改类型(破坏性) | 4 |
|
|
68
|
+
| 改 dev seed | 1/2 |
|
|
69
|
+
| 改字典数据 | 3(同步 contracts/dictionaries/) |
|
|
70
|
+
| 升级 golang-migrate / 驱动 | 2,但同步改 tech-stack-server.md |
|
|
71
|
+
|
|
72
|
+
## CI 行为
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
make db-up
|
|
76
|
+
make db-down
|
|
77
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: db-go-migrate-mysql
|
|
2
|
+
version: 1.0.0
|
|
3
|
+
appliesWhen:
|
|
4
|
+
backend: go
|
|
5
|
+
database: mysql
|
|
6
|
+
priority: 40
|
|
7
|
+
files:
|
|
8
|
+
- from: files/go.mod
|
|
9
|
+
to: server/go.mod
|
|
10
|
+
render: true
|
|
11
|
+
- from: files/Makefile
|
|
12
|
+
to: server/Makefile
|
|
13
|
+
render: true
|
|
14
|
+
- from: files/000001_init.up.sql
|
|
15
|
+
to: server/db/migrations/000001_init.up.sql
|
|
16
|
+
render: false
|
|
17
|
+
- from: files/000001_init.down.sql
|
|
18
|
+
to: server/db/migrations/000001_init.down.sql
|
|
19
|
+
render: false
|
|
20
|
+
- from: files/db-README.md
|
|
21
|
+
to: server/db/README.md
|
|
22
|
+
render: true
|