super-dev 2.0.0__py3-none-any.whl

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.
Files changed (61) hide show
  1. super_dev/__init__.py +11 -0
  2. super_dev/analyzer/__init__.py +34 -0
  3. super_dev/analyzer/analyzer.py +440 -0
  4. super_dev/analyzer/detectors.py +511 -0
  5. super_dev/analyzer/models.py +285 -0
  6. super_dev/cli.py +3257 -0
  7. super_dev/config/__init__.py +11 -0
  8. super_dev/config/frontend.py +557 -0
  9. super_dev/config/manager.py +281 -0
  10. super_dev/creators/__init__.py +26 -0
  11. super_dev/creators/creator.py +134 -0
  12. super_dev/creators/document_generator.py +2473 -0
  13. super_dev/creators/frontend_builder.py +371 -0
  14. super_dev/creators/implementation_builder.py +789 -0
  15. super_dev/creators/prompt_generator.py +289 -0
  16. super_dev/creators/requirement_parser.py +354 -0
  17. super_dev/creators/spec_builder.py +195 -0
  18. super_dev/deployers/__init__.py +20 -0
  19. super_dev/deployers/cicd.py +1269 -0
  20. super_dev/deployers/delivery.py +229 -0
  21. super_dev/deployers/migration.py +1032 -0
  22. super_dev/design/__init__.py +74 -0
  23. super_dev/design/aesthetics.py +530 -0
  24. super_dev/design/charts.py +396 -0
  25. super_dev/design/codegen.py +379 -0
  26. super_dev/design/engine.py +528 -0
  27. super_dev/design/generator.py +395 -0
  28. super_dev/design/landing.py +422 -0
  29. super_dev/design/tech_stack.py +524 -0
  30. super_dev/design/tokens.py +269 -0
  31. super_dev/design/ux_guide.py +391 -0
  32. super_dev/exceptions.py +119 -0
  33. super_dev/experts/__init__.py +19 -0
  34. super_dev/experts/service.py +161 -0
  35. super_dev/integrations/__init__.py +7 -0
  36. super_dev/integrations/manager.py +264 -0
  37. super_dev/orchestrator/__init__.py +12 -0
  38. super_dev/orchestrator/engine.py +958 -0
  39. super_dev/orchestrator/experts.py +423 -0
  40. super_dev/orchestrator/knowledge.py +352 -0
  41. super_dev/orchestrator/quality.py +356 -0
  42. super_dev/reviewers/__init__.py +17 -0
  43. super_dev/reviewers/code_review.py +471 -0
  44. super_dev/reviewers/quality_gate.py +964 -0
  45. super_dev/reviewers/redteam.py +881 -0
  46. super_dev/skills/__init__.py +7 -0
  47. super_dev/skills/manager.py +307 -0
  48. super_dev/specs/__init__.py +44 -0
  49. super_dev/specs/generator.py +264 -0
  50. super_dev/specs/manager.py +428 -0
  51. super_dev/specs/models.py +348 -0
  52. super_dev/specs/validator.py +415 -0
  53. super_dev/utils/__init__.py +11 -0
  54. super_dev/utils/logger.py +133 -0
  55. super_dev/web/api.py +1402 -0
  56. super_dev-2.0.0.dist-info/METADATA +252 -0
  57. super_dev-2.0.0.dist-info/RECORD +61 -0
  58. super_dev-2.0.0.dist-info/WHEEL +5 -0
  59. super_dev-2.0.0.dist-info/entry_points.txt +2 -0
  60. super_dev-2.0.0.dist-info/licenses/LICENSE +21 -0
  61. super_dev-2.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1269 @@
1
+ """
2
+ CI/CD 生成器 - 自动生成 CI/CD 流水线配置
3
+
4
+ 开发:Excellent(11964948@qq.com)
5
+ 功能:生成 GitHub Actions / GitLab CI / Jenkins / Azure DevOps / Bitbucket 配置
6
+ 作用:实现自动化构建、测试、部署
7
+ 创建时间:2025-12-30
8
+ """
9
+
10
+ import re
11
+ from pathlib import Path
12
+ from typing import Literal
13
+
14
+
15
+ class CICDGenerator:
16
+ """CI/CD 配置生成器"""
17
+
18
+ def __init__(
19
+ self,
20
+ project_dir: Path,
21
+ name: str,
22
+ tech_stack: dict,
23
+ platform: Literal["github", "gitlab", "jenkins", "azure", "bitbucket", "all"] = "github"
24
+ ):
25
+ self.project_dir = Path(project_dir).resolve()
26
+ self.display_name = name
27
+ self.name = self._sanitize_resource_name(name)
28
+ self.tech_stack = tech_stack
29
+ self.platform = platform
30
+ self.frontend = tech_stack.get("frontend", "react")
31
+ self.backend = tech_stack.get("backend", "node")
32
+
33
+ def _sanitize_resource_name(self, name: str) -> str:
34
+ lowered = name.strip().lower()
35
+ sanitized = re.sub(r"[^a-z0-9-]+", "-", lowered)
36
+ sanitized = re.sub(r"-{2,}", "-", sanitized).strip("-")
37
+ if not sanitized:
38
+ return "super-dev-app"
39
+ return sanitized[:63]
40
+
41
+ def generate(self) -> dict[str, str]:
42
+ """生成所有 CI/CD 配置文件"""
43
+ files = {}
44
+
45
+ if self.platform in {"github", "all"}:
46
+ files[".github/workflows/ci.yml"] = self._generate_github_ci()
47
+ files[".github/workflows/cd.yml"] = self._generate_github_cd()
48
+ if self.platform in {"gitlab", "all"}:
49
+ files[".gitlab-ci.yml"] = self._generate_gitlab_ci()
50
+ if self.platform in {"jenkins", "all"}:
51
+ files["Jenkinsfile"] = self._generate_jenkins()
52
+ if self.platform in {"azure", "all"}:
53
+ files[".azure-pipelines.yml"] = self._generate_azure()
54
+ if self.platform in {"bitbucket", "all"}:
55
+ files["bitbucket-pipelines.yml"] = self._generate_bitbucket()
56
+
57
+ # Docker 配置
58
+ files["Dockerfile"] = self._generate_dockerfile()
59
+ files["docker-compose.yml"] = self._generate_docker_compose()
60
+ files[".dockerignore"] = self._generate_dockerignore()
61
+
62
+ # Kubernetes 配置
63
+ files["k8s/deployment.yaml"] = self._generate_k8s_deployment()
64
+ files["k8s/service.yaml"] = self._generate_k8s_service()
65
+ files["k8s/ingress.yaml"] = self._generate_k8s_ingress()
66
+ files["k8s/configmap.yaml"] = self._generate_k8s_configmap()
67
+ files["k8s/secret.yaml"] = self._generate_k8s_secret()
68
+
69
+ return files
70
+
71
+ def _generate_github_ci(self) -> str:
72
+ """生成 GitHub Actions CI 配置"""
73
+ return f"""name: CI
74
+
75
+ on:
76
+ push:
77
+ branches: [main, develop]
78
+ pull_request:
79
+ branches: [main, develop]
80
+
81
+ jobs:
82
+ quality:
83
+ name: Quality
84
+ runs-on: ubuntu-latest
85
+ steps:
86
+ - uses: actions/checkout@v3
87
+
88
+ - name: Setup Node.js
89
+ uses: actions/setup-node@v3
90
+ with:
91
+ node-version: '18'
92
+
93
+ - name: Setup Python
94
+ uses: actions/setup-python@v4
95
+ with:
96
+ python-version: '3.11'
97
+
98
+ - name: Install frontend dependencies
99
+ if: ${{{{ hashFiles('frontend/package.json') != '' }}}}
100
+ run: npm --prefix frontend ci
101
+
102
+ - name: Install backend node dependencies
103
+ if: ${{{{ hashFiles('backend/package.json') != '' }}}}
104
+ run: npm --prefix backend ci
105
+
106
+ - name: Install Python dependencies
107
+ run: |
108
+ if [ -f backend/requirements.txt ] || [ -f requirements.txt ] || [ -f pyproject.toml ] || [ -f backend/pyproject.toml ]; then
109
+ pip install -e ".[dev]"
110
+ fi
111
+
112
+ - name: Run linters
113
+ run: |
114
+ if [ -f frontend/package.json ]; then
115
+ npm --prefix frontend run lint --if-present
116
+ fi
117
+ if [ -f backend/package.json ]; then
118
+ npm --prefix backend run lint --if-present
119
+ fi
120
+ if [ -d super_dev ]; then
121
+ ruff check super_dev tests
122
+ fi
123
+
124
+ - name: Run type checks
125
+ run: |
126
+ if [ -f frontend/package.json ]; then
127
+ npm --prefix frontend run type-check --if-present
128
+ fi
129
+ if [ -f backend/package.json ]; then
130
+ npm --prefix backend run type-check --if-present
131
+ fi
132
+ if [ -d super_dev ]; then
133
+ mypy .
134
+ fi
135
+
136
+ - name: Run tests
137
+ run: |
138
+ if [ -f frontend/package.json ]; then
139
+ npm --prefix frontend run test --if-present
140
+ fi
141
+ if [ -f backend/package.json ]; then
142
+ npm --prefix backend run test --if-present
143
+ fi
144
+ if [ -d tests ]; then
145
+ pytest -q
146
+ fi
147
+
148
+ - name: Upload coverage
149
+ if: ${{{{ hashFiles('coverage.xml', 'frontend/coverage/cobertura-coverage.xml', 'backend/coverage/cobertura-coverage.xml') != '' }}}}
150
+ uses: codecov/codecov-action@v3
151
+ with:
152
+ files: ./coverage.xml,./frontend/coverage/cobertura-coverage.xml,./backend/coverage/cobertura-coverage.xml
153
+ flags: unittests
154
+ name: codecov-umbrella
155
+
156
+ security:
157
+ name: Security Scan
158
+ runs-on: ubuntu-latest
159
+ steps:
160
+ - uses: actions/checkout@v3
161
+
162
+ - name: Run Trivy vulnerability scanner
163
+ uses: aquasecurity/trivy-action@master
164
+ with:
165
+ scan-type: 'fs'
166
+ scan-ref: '.'
167
+ format: 'sarif'
168
+ output: 'trivy-results.sarif'
169
+
170
+ - name: Upload Trivy results to GitHub Security tab
171
+ uses: github/codeql-action/upload-sarif@v2
172
+ with:
173
+ sarif_file: 'trivy-results.sarif'
174
+
175
+ - name: Run npm audit
176
+ run: |
177
+ if [ -f frontend/package.json ]; then
178
+ (cd frontend && npm audit --audit-level=moderate || true)
179
+ fi
180
+ if [ -f backend/package.json ]; then
181
+ (cd backend && npm audit --audit-level=moderate || true)
182
+ fi
183
+ continue-on-error: true
184
+
185
+ build:
186
+ name: Build Docker Image
187
+ runs-on: ubuntu-latest
188
+ needs: [quality, security]
189
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
190
+ steps:
191
+ - uses: actions/checkout@v3
192
+
193
+ - name: Set up Docker Buildx
194
+ uses: docker/setup-buildx-action@v2
195
+
196
+ - name: Login to Docker Hub
197
+ uses: docker/login-action@v2
198
+ with:
199
+ username: ${{{{ secrets.DOCKER_USERNAME }}}}
200
+ password: ${{{{ secrets.DOCKER_PASSWORD }}}}
201
+
202
+ - name: Build and push
203
+ uses: docker/build-push-action@v4
204
+ with:
205
+ context: .
206
+ push: true
207
+ tags: |
208
+ ${{{{ secrets.DOCKER_USERNAME }}}}/{self.name}:latest
209
+ ${{{{ secrets.DOCKER_USERNAME }}}}/{self.name}:${{{{ github.sha }}}}
210
+ cache-from: type=gha
211
+ cache-to: type=gha,mode=max
212
+ """
213
+
214
+ def _generate_github_cd(self) -> str:
215
+ """生成 GitHub Actions CD 配置"""
216
+ return f"""name: CD
217
+
218
+ on:
219
+ push:
220
+ branches: [main, develop]
221
+ workflow_dispatch:
222
+
223
+ jobs:
224
+ # ========== 部署到开发环境 ==========
225
+ deploy-dev:
226
+ name: Deploy to Development
227
+ runs-on: ubuntu-latest
228
+ if: github.ref == 'refs/heads/develop'
229
+ environment:
230
+ name: development
231
+ url: https://dev.{self.name}.example.com
232
+ steps:
233
+ - uses: actions/checkout@v3
234
+
235
+ - name: Configure kubectl
236
+ uses: azure/k8s-set-context@v3
237
+ with:
238
+ method: kubeconfig
239
+ kubeconfig: ${{{{ secrets.KUBE_CONFIG_DEV }}}}
240
+
241
+ - name: Deploy to Kubernetes
242
+ run: |
243
+ kubectl apply -f k8s/ -n dev
244
+ kubectl rollout restart deployment/{self.name} -n dev
245
+
246
+ - name: Verify deployment
247
+ run: |
248
+ kubectl rollout status deployment/{self.name} -n dev
249
+
250
+ # ========== 部署到生产环境 ==========
251
+ deploy-prod:
252
+ name: Deploy to Production
253
+ runs-on: ubuntu-latest
254
+ if: github.ref == 'refs/heads/main'
255
+ environment:
256
+ name: production
257
+ url: https://{self.name}.example.com
258
+ steps:
259
+ - uses: actions/checkout@v3
260
+
261
+ - name: Configure kubectl
262
+ uses: azure/k8s-set-context@v3
263
+ with:
264
+ method: kubeconfig
265
+ kubeconfig: ${{{{ secrets.KUBE_CONFIG_PROD }}}}
266
+
267
+ - name: Create backup
268
+ run: |
269
+ kubectl get deployment {self.name} -n prod -o yaml > backup-${{{{ github.sha }}}}.yaml
270
+
271
+ - name: Deploy to Kubernetes
272
+ run: |
273
+ kubectl apply -f k8s/ -n prod
274
+ kubectl rollout restart deployment/{self.name} -n prod
275
+
276
+ - name: Verify deployment
277
+ run: |
278
+ kubectl rollout status deployment/{self.name} -n prod
279
+
280
+ - name: Health check
281
+ run: |
282
+ for i in {{1..30}}; do
283
+ if curl -f https://{self.name}.example.com/health; then
284
+ echo "Health check passed"
285
+ exit 0
286
+ fi
287
+ echo "Waiting for health check... ($i/30)"
288
+ sleep 10
289
+ done
290
+ echo "Health check failed"
291
+ exit 1
292
+
293
+ - name: Rollback on failure
294
+ if: failure()
295
+ run: |
296
+ kubectl apply -f backup-${{{{ github.sha }}}}.yaml
297
+ kubectl rollout undo deployment/{self.name} -n prod
298
+ """
299
+
300
+ def _generate_gitlab_ci(self) -> str:
301
+ """生成 GitLab CI 配置"""
302
+ return f"""stages:
303
+ - quality
304
+ - test
305
+ - build
306
+ - deploy
307
+
308
+ variables:
309
+ DOCKER_IMAGE: ${{CI_REGISTRY_IMAGE}}/{self.name}
310
+ DOCKER_TLS_CERTDIR: "/certs"
311
+
312
+ # ========== 质量检查 ==========
313
+ quality:
314
+ stage: quality
315
+ image: python:3.11-alpine
316
+ before_script:
317
+ - apk add --no-cache nodejs npm git
318
+ script:
319
+ - |
320
+ if [ -f frontend/package.json ]; then
321
+ npm --prefix frontend ci
322
+ fi
323
+ if [ -f backend/package.json ]; then
324
+ npm --prefix backend ci
325
+ fi
326
+ if [ -f backend/requirements.txt ] || [ -f requirements.txt ] || [ -f pyproject.toml ]; then
327
+ pip install -e ".[dev]"
328
+ fi
329
+ - |
330
+ if [ -f frontend/package.json ]; then
331
+ npm --prefix frontend run lint --if-present
332
+ npm --prefix frontend run type-check --if-present
333
+ fi
334
+ if [ -f backend/package.json ]; then
335
+ npm --prefix backend run lint --if-present
336
+ fi
337
+ if [ -d super_dev ]; then
338
+ ruff check super_dev tests
339
+ mypy super_dev
340
+ fi
341
+ cache:
342
+ paths:
343
+ - frontend/node_modules/
344
+ - backend/node_modules/
345
+ only:
346
+ - merge_requests
347
+ - main
348
+ - develop
349
+
350
+ # ========== 单元测试 ==========
351
+ test:
352
+ stage: test
353
+ image: python:3.11-alpine
354
+ before_script:
355
+ - apk add --no-cache nodejs npm
356
+ services:
357
+ - postgres:15-alpine
358
+ - redis:7-alpine
359
+ variables:
360
+ POSTGRES_HOST: postgres
361
+ POSTGRES_PASSWORD: postgres
362
+ POSTGRES_DB: test_db
363
+ REDIS_HOST: redis
364
+ script:
365
+ - |
366
+ if [ -f frontend/package.json ]; then
367
+ npm --prefix frontend ci
368
+ npm --prefix frontend run test --if-present
369
+ fi
370
+ if [ -f backend/package.json ]; then
371
+ npm --prefix backend ci
372
+ npm --prefix backend run test --if-present
373
+ fi
374
+ if [ -d tests ]; then
375
+ pip install -e ".[dev]"
376
+ pytest -q
377
+ fi
378
+ cache:
379
+ paths:
380
+ - frontend/node_modules/
381
+ - backend/node_modules/
382
+ artifacts:
383
+ reports:
384
+ coverage_report:
385
+ coverage_format: cobertura
386
+ path: frontend/coverage/cobertura-coverage.xml
387
+ paths:
388
+ - coverage/
389
+ - frontend/coverage/
390
+ - backend/coverage/
391
+ expire_in: 1 week
392
+ only:
393
+ - merge_requests
394
+ - main
395
+ - develop
396
+
397
+ # ========== 安全扫描 ==========
398
+ security:
399
+ stage: test
400
+ image: aquasec/trivy:latest
401
+ script:
402
+ - trivy fs --format sarif --output trivy-results.sarif .
403
+ artifacts:
404
+ reports:
405
+ sast: trivy-results.sarif
406
+ expire_in: 1 week
407
+ only:
408
+ - merge_requests
409
+ - main
410
+ - develop
411
+
412
+ # ========== 构建镜像 ==========
413
+ build:
414
+ stage: build
415
+ image: docker:24-dind
416
+ services:
417
+ - docker:24-dind
418
+ before_script:
419
+ - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
420
+ script:
421
+ - docker build -t $DOCKER_IMAGE:$CI_COMMIT_SHA .
422
+ - docker push $DOCKER_IMAGE:$CI_COMMIT_SHA
423
+ - docker tag $DOCKER_IMAGE:$CI_COMMIT_SHA $DOCKER_IMAGE:latest
424
+ - docker push $DOCKER_IMAGE:latest
425
+ only:
426
+ - main
427
+ - develop
428
+
429
+ # ========== 部署到开发环境 ==========
430
+ deploy:dev:
431
+ stage: deploy
432
+ image: bitnami/kubectl:latest
433
+ script:
434
+ - kubectl config use-context $KUBE_CONTEXT_DEV
435
+ - kubectl apply -f k8s/ -n dev
436
+ - kubectl set image deployment/{self.name} {self.name}=$DOCKER_IMAGE:$CI_COMMIT_SHA -n dev
437
+ - kubectl rollout status deployment/{self.name} -n dev
438
+ environment:
439
+ name: development
440
+ url: https://dev.{self.name}.example.com
441
+ only:
442
+ - develop
443
+
444
+ # ========== 部署到生产环境 ==========
445
+ deploy:prod:
446
+ stage: deploy
447
+ image: bitnami/kubectl:latest
448
+ script:
449
+ - kubectl config use-context $KUBE_CONTEXT_PROD
450
+ - kubectl apply -f k8s/ -n prod
451
+ - kubectl set image deployment/{self.name} {self.name}=$DOCKER_IMAGE:$CI_COMMIT_SHA -n prod
452
+ - kubectl rollout status deployment/{self.name} -n prod
453
+ environment:
454
+ name: production
455
+ url: https://{self.name}.example.com
456
+ when: manual
457
+ only:
458
+ - main
459
+ """
460
+
461
+ def _generate_jenkins(self) -> str:
462
+ """生成 Jenkinsfile"""
463
+ return f"""pipeline {{
464
+ agent any
465
+
466
+ environment {{
467
+ DOCKER_IMAGE = "your-registry/{self.name}"
468
+ DOCKER_TAG = "${{sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()}}"
469
+ KUBECONFIG_DEV = credentials('kubeconfig-dev')
470
+ KUBECONFIG_PROD = credentials('kubeconfig-prod')
471
+ }}
472
+
473
+ stages {{
474
+ stage('Checkout') {{
475
+ steps {{
476
+ checkout scm
477
+ }}
478
+ }}
479
+
480
+ stage('Install Dependencies') {{
481
+ parallel {{
482
+ stage('Frontend') {{
483
+ steps {{
484
+ script {{
485
+ if (fileExists('frontend/package.json')) {{
486
+ sh 'npm --prefix frontend ci'
487
+ }}
488
+ }}
489
+ }}
490
+ }}
491
+ stage('Backend') {{
492
+ steps {{
493
+ script {{
494
+ if (fileExists('backend/package.json')) {{
495
+ sh 'npm --prefix backend ci'
496
+ }}
497
+ if (fileExists('requirements.txt') || fileExists('backend/requirements.txt') || fileExists('pyproject.toml')) {{
498
+ sh 'pip install -e ".[dev]"'
499
+ }}
500
+ }}
501
+ }}
502
+ }}
503
+ }}
504
+ }}
505
+
506
+ stage('Lint') {{
507
+ steps {{
508
+ script {{
509
+ if (fileExists('frontend/package.json')) {{
510
+ sh 'npm --prefix frontend run lint --if-present'
511
+ }}
512
+ if (fileExists('backend/package.json')) {{
513
+ sh 'npm --prefix backend run lint --if-present'
514
+ }}
515
+ if (fileExists('super_dev')) {{
516
+ sh 'ruff check super_dev tests'
517
+ }}
518
+ }}
519
+ }}
520
+ }}
521
+
522
+ stage('Type Check') {{
523
+ steps {{
524
+ script {{
525
+ if (fileExists('frontend/package.json')) {{
526
+ sh 'npm --prefix frontend run type-check --if-present'
527
+ }}
528
+ if (fileExists('backend/package.json')) {{
529
+ sh 'npm --prefix backend run type-check --if-present'
530
+ }}
531
+ if (fileExists('super_dev')) {{
532
+ sh 'mypy super_dev'
533
+ }}
534
+ }}
535
+ }}
536
+ }}
537
+
538
+ stage('Test') {{
539
+ steps {{
540
+ script {{
541
+ if (fileExists('frontend/package.json')) {{
542
+ sh 'npm --prefix frontend run test --if-present'
543
+ }}
544
+ if (fileExists('backend/package.json')) {{
545
+ sh 'npm --prefix backend run test --if-present'
546
+ }}
547
+ if (fileExists('tests')) {{
548
+ sh 'pytest -q'
549
+ }}
550
+ }}
551
+ }}
552
+ post {{
553
+ always {{
554
+ echo 'Tests finished'
555
+ }}
556
+ }}
557
+ }}
558
+
559
+ stage('Security Scan') {{
560
+ steps {{
561
+ sh 'trivy fs --format json --output trivy-results.json .'
562
+ recordIssues toolexpression: [tool: 'trivy'])
563
+ }}
564
+ }}
565
+
566
+ stage('Build Docker Image') {{
567
+ when {{
568
+ anyOf {{
569
+ branch 'main'
570
+ branch 'develop'
571
+ }}
572
+ }}
573
+ steps {{
574
+ script {{
575
+ docker.build("${{DOCKER_IMAGE}}:${{DOCKER_TAG}}")
576
+ docker.withRegistry("https://your-registry", "docker-credentials") {{
577
+ docker.image("${{DOCKER_IMAGE}}:${{DOCKER_TAG}}").push()
578
+ docker.image("${{DOCKER_IMAGE}}:${{DOCKER_TAG}}").push("latest")
579
+ }}
580
+ }}
581
+ }}
582
+ }}
583
+
584
+ stage('Deploy to Dev') {{
585
+ when {{
586
+ branch 'develop'
587
+ }}
588
+ steps {{
589
+ sh '''
590
+ echo ${{KUBECONFIG_DEV}} > kubeconfig
591
+ kubectl --kubeconfig=kubeconfig apply -f k8s/ -n dev
592
+ kubectl --kubeconfig=kubeconfig set image deployment/{self.name} {self.name}=${{DOCKER_IMAGE}}:${{DOCKER_TAG}} -n dev
593
+ kubectl --kubeconfig=kubeconfig rollout status deployment/{self.name} -n dev
594
+ '''
595
+ }}
596
+ }}
597
+
598
+ stage('Deploy to Prod') {{
599
+ when {{
600
+ branch 'main'
601
+ }}
602
+ steps {{
603
+ input message: 'Deploy to production?', ok: 'Deploy'
604
+ sh '''
605
+ echo ${{KUBECONFIG_PROD}} > kubeconfig
606
+ kubectl --kubeconfig=kubeconfig apply -f k8s/ -n prod
607
+ kubectl --kubeconfig=kubeconfig set image deployment/{self.name} {self.name}=${{DOCKER_IMAGE}}:${{DOCKER_TAG}} -n prod
608
+ kubectl --kubeconfig=kubeconfig rollout status deployment/{self.name} -n prod
609
+ '''
610
+ }}
611
+ }}
612
+ }}
613
+
614
+ post {{
615
+ always {{
616
+ cleanWs()
617
+ }}
618
+ success {{
619
+ emailext(
620
+ subject: "Success: ${{env.JOB_NAME}} - ${{env.BUILD_NUMBER}}",
621
+ body: "Build succeeded!\\n\\n${{env.BUILD_URL}}",
622
+ to: "${{env.CHANGE_AUTHOR_EMAIL}}"
623
+ )
624
+ }}
625
+ failure {{
626
+ emailext(
627
+ subject: "Failed: ${{env.JOB_NAME}} - ${{env.BUILD_NUMBER}}",
628
+ body: "Build failed!\\n\\n${{env.BUILD_URL}}console",
629
+ to: "${{env.CHANGE_AUTHOR_EMAIL}}"
630
+ )
631
+ }}
632
+ }}
633
+ }}
634
+ """
635
+
636
+ def _generate_dockerfile(self) -> str:
637
+ """生成 Dockerfile"""
638
+ return f"""# Multi-stage build for {self.name}
639
+
640
+ # ========== Build stage ==========
641
+ FROM node:18-alpine AS builder
642
+
643
+ WORKDIR /app
644
+
645
+ # Install dependencies
646
+ COPY package*.json ./
647
+ RUN npm ci
648
+
649
+ # Copy source and build
650
+ COPY . .
651
+ RUN npm run build
652
+
653
+ # ========== Production stage ==========
654
+ FROM node:18-alpine AS production
655
+
656
+ WORKDIR /app
657
+
658
+ # Install dumb-init for proper signal handling
659
+ RUN apk add --no-cache dumb-init
660
+
661
+ # Create non-root user
662
+ RUN addgroup -g 1001 -S nodejs && \\
663
+ adduser -S nodejs -u 1001
664
+
665
+ # Copy package files and install production dependencies
666
+ COPY package*.json ./
667
+ RUN npm ci --only=production && npm cache clean --force
668
+
669
+ # Copy built assets from builder
670
+ COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
671
+ COPY --from=builder --chown=nodejs:nodejs /app/public ./public
672
+
673
+ # Switch to non-root user
674
+ USER nodejs
675
+
676
+ EXPOSE 3000
677
+
678
+ # Use dumb-init to handle signals properly
679
+ ENTRYPOINT ["dumb-init", "--"]
680
+
681
+ # Start the application
682
+ CMD ["node", "dist/main.js"]
683
+
684
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \\
685
+ CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
686
+ """
687
+
688
+ def _generate_docker_compose(self) -> str:
689
+ """生成 docker-compose.yml"""
690
+ return f"""version: '3.8'
691
+
692
+ services:
693
+ # ========== Frontend ==========
694
+ frontend:
695
+ build:
696
+ context: .
697
+ dockerfile: Dockerfile
698
+ target: production
699
+ ports:
700
+ - "3000:3000"
701
+ environment:
702
+ - NODE_ENV=production
703
+ - API_URL=http://api:8080
704
+ depends_on:
705
+ - api
706
+ networks:
707
+ - app-network
708
+ restart: unless-stopped
709
+
710
+ # ========== Backend API ==========
711
+ api:
712
+ build:
713
+ context: ./backend
714
+ dockerfile: Dockerfile
715
+ ports:
716
+ - "8080:8080"
717
+ environment:
718
+ - NODE_ENV=production
719
+ - DATABASE_URL=postgresql://postgres:password@postgres:5432/{self.name}
720
+ - REDIS_URL=redis://redis:6379
721
+ depends_on:
722
+ - postgres
723
+ - redis
724
+ networks:
725
+ - app-network
726
+ restart: unless-stopped
727
+
728
+ # ========== PostgreSQL ==========
729
+ postgres:
730
+ image: postgres:15-alpine
731
+ volumes:
732
+ - postgres-data:/var/lib/postgresql/data
733
+ environment:
734
+ - POSTGRES_DB={self.name}
735
+ - POSTGRES_USER=postgres
736
+ - POSTGRES_PASSWORD=password
737
+ networks:
738
+ - app-network
739
+ restart: unless-stopped
740
+
741
+ # ========== Redis ==========
742
+ redis:
743
+ image: redis:7-alpine
744
+ volumes:
745
+ - redis-data:/data
746
+ networks:
747
+ - app-network
748
+ restart: unless-stopped
749
+
750
+ # ========== Nginx ==========
751
+ nginx:
752
+ image: nginx:alpine
753
+ ports:
754
+ - "80:80"
755
+ - "443:443"
756
+ volumes:
757
+ - ./nginx.conf:/etc/nginx/nginx.conf:ro
758
+ - ./ssl:/etc/nginx/ssl:ro
759
+ depends_on:
760
+ - frontend
761
+ - api
762
+ networks:
763
+ - app-network
764
+ restart: unless-stopped
765
+
766
+ networks:
767
+ app-network:
768
+ driver: bridge
769
+
770
+ volumes:
771
+ postgres-data:
772
+ redis-data:
773
+ """
774
+
775
+ def _generate_dockerignore(self) -> str:
776
+ """生成 .dockerignore"""
777
+ return """# Dependencies
778
+ node_modules/
779
+ __pycache__/
780
+ *.pyc
781
+ *.pyo
782
+ *.pyd
783
+ .Python
784
+
785
+ # Testing
786
+ .coverage
787
+ .pytest_cache/
788
+ .tox/
789
+ .nox/
790
+
791
+ # Environments
792
+ .env
793
+ .env.local
794
+ .env.*.local
795
+ venv/
796
+ ENV/
797
+ env/
798
+
799
+ # IDE
800
+ .idea/
801
+ .vscode/
802
+ *.swp
803
+ *.swo
804
+ *~
805
+ .DS_Store
806
+
807
+ # Git
808
+ .git/
809
+ .gitignore
810
+ .gitattributes
811
+
812
+ # Documentation
813
+ *.md
814
+ docs/
815
+
816
+ # CI/CD
817
+ .github/
818
+ .gitlab-ci.yml
819
+ Jenkinsfile
820
+
821
+ # Tests
822
+ tests/
823
+ test_*
824
+ *_test.py
825
+ *.test.ts
826
+ *.spec.ts
827
+
828
+ # Logs
829
+ logs/
830
+ *.log
831
+ npm-debug.log*
832
+
833
+ # Misc
834
+ *.bak
835
+ *.tmp
836
+ .cache/
837
+ """
838
+
839
+ def _generate_k8s_deployment(self) -> str:
840
+ """生成 Kubernetes Deployment 配置"""
841
+ return f"""apiVersion: apps/v1
842
+ kind: Deployment
843
+ metadata:
844
+ name: {self.name}
845
+ labels:
846
+ app: {self.name}
847
+ version: v1
848
+ spec:
849
+ replicas: 3
850
+ strategy:
851
+ type: RollingUpdate
852
+ rollingUpdate:
853
+ maxSurge: 1
854
+ maxUnavailable: 0
855
+ selector:
856
+ matchLabels:
857
+ app: {self.name}
858
+ template:
859
+ metadata:
860
+ labels:
861
+ app: {self.name}
862
+ version: v1
863
+ spec:
864
+ containers:
865
+ - name: {self.name}
866
+ image: your-registry/{self.name}:latest
867
+ ports:
868
+ - containerPort: 3000
869
+ name: http
870
+ protocol: TCP
871
+ env:
872
+ - name: NODE_ENV
873
+ value: "production"
874
+ - name: DATABASE_URL
875
+ valueFrom:
876
+ secretKeyRef:
877
+ name: {self.name}-secret
878
+ key: database-url
879
+ - name: REDIS_URL
880
+ valueFrom:
881
+ configMapKeyRef:
882
+ name: {self.name}-config
883
+ key: redis-url
884
+ resources:
885
+ requests:
886
+ memory: "256Mi"
887
+ cpu: "250m"
888
+ limits:
889
+ memory: "512Mi"
890
+ cpu: "500m"
891
+ livenessProbe:
892
+ httpGet:
893
+ path: /health
894
+ port: http
895
+ initialDelaySeconds: 30
896
+ periodSeconds: 10
897
+ timeoutSeconds: 5
898
+ failureThreshold: 3
899
+ readinessProbe:
900
+ httpGet:
901
+ path: /ready
902
+ port: http
903
+ initialDelaySeconds: 5
904
+ periodSeconds: 5
905
+ timeoutSeconds: 3
906
+ failureThreshold: 3
907
+ securityContext:
908
+ runAsNonRoot: true
909
+ runAsUser: 1001
910
+ allowPrivilegeEscalation: false
911
+ readOnlyRootFilesystem: true
912
+ capabilities:
913
+ drop:
914
+ - ALL
915
+ """
916
+
917
+ def _generate_k8s_service(self) -> str:
918
+ """生成 Kubernetes Service 配置"""
919
+ return f"""apiVersion: v1
920
+ kind: Service
921
+ metadata:
922
+ name: {self.name}
923
+ labels:
924
+ app: {self.name}
925
+ spec:
926
+ type: ClusterIP
927
+ ports:
928
+ - port: 80
929
+ targetPort: http
930
+ protocol: TCP
931
+ name: http
932
+ selector:
933
+ app: {self.name}
934
+ """
935
+
936
+ def _generate_k8s_ingress(self) -> str:
937
+ """生成 Kubernetes Ingress 配置"""
938
+ return f"""apiVersion: networking.k8s.io/v1
939
+ kind: Ingress
940
+ metadata:
941
+ name: {self.name}
942
+ annotations:
943
+ cert-manager.io/cluster-issuer: "letsencrypt-prod"
944
+ nginx.ingress.kubernetes.io/ssl-redirect: "true"
945
+ nginx.ingress.kubernetes.io/proxy-body-size: "10m"
946
+ spec:
947
+ ingressClassName: nginx
948
+ tls:
949
+ - hosts:
950
+ - {self.name}.example.com
951
+ secretName: {self.name}-tls
952
+ rules:
953
+ - host: {self.name}.example.com
954
+ http:
955
+ paths:
956
+ - path: /
957
+ pathType: Prefix
958
+ backend:
959
+ service:
960
+ name: {self.name}
961
+ port:
962
+ number: 80
963
+ """
964
+
965
+ def _generate_k8s_configmap(self) -> str:
966
+ """生成 Kubernetes ConfigMap 配置"""
967
+ return f"""apiVersion: v1
968
+ kind: ConfigMap
969
+ metadata:
970
+ name: {self.name}-config
971
+ data:
972
+ log-level: "info"
973
+ redis-url: "redis://redis:6379"
974
+ api-timeout: "30s"
975
+ max-upload-size: "10M"
976
+ """
977
+
978
+ def _generate_k8s_secret(self) -> str:
979
+ """生成 Kubernetes Secret 配置"""
980
+ return f"""apiVersion: v1
981
+ kind: Secret
982
+ metadata:
983
+ name: {self.name}-secret
984
+ type: Opaque
985
+ stringData:
986
+ database-url: "postgresql://user:password@postgres:5432/{self.name}"
987
+ jwt-secret: "your-jwt-secret-here"
988
+ api-key: "your-api-key-here"
989
+ """
990
+
991
+ def _generate_azure(self) -> str:
992
+ """生成 Azure DevOps Pipelines 配置"""
993
+ return f"""# Azure Pipelines CI/CD for {self.name}
994
+ trigger:
995
+ branches:
996
+ include:
997
+ - main
998
+ - develop
999
+
1000
+ pr:
1001
+ branches:
1002
+ include:
1003
+ - main
1004
+ - develop
1005
+
1006
+ pool:
1007
+ vmImage: 'ubuntu-latest'
1008
+
1009
+ variables:
1010
+ imageName: '{self.name}'
1011
+ dockerRegistry: 'your-registry.azurecr.io'
1012
+ NODE_VERSION: '18'
1013
+
1014
+ stages:
1015
+ # ========== Build and Test ==========
1016
+ - stage: Build
1017
+ displayName: 'Build and Test'
1018
+ jobs:
1019
+ - job: Build
1020
+ displayName: 'Build Job'
1021
+ steps:
1022
+ - checkout: self
1023
+
1024
+ - task: NodeTool@0
1025
+ inputs:
1026
+ versionSpec: '$(NODE_VERSION)'
1027
+ displayName: 'Install Node.js'
1028
+
1029
+ - script: |
1030
+ if [ -f frontend/package.json ]; then
1031
+ npm --prefix frontend ci
1032
+ fi
1033
+ if [ -f backend/package.json ]; then
1034
+ npm --prefix backend ci
1035
+ fi
1036
+ if [ -f requirements.txt ] || [ -f backend/requirements.txt ] || [ -f pyproject.toml ]; then
1037
+ python -m pip install -e ".[dev]"
1038
+ fi
1039
+ displayName: 'Install dependencies'
1040
+
1041
+ - script: |
1042
+ if [ -f frontend/package.json ]; then
1043
+ npm --prefix frontend run lint --if-present
1044
+ npm --prefix frontend run type-check --if-present
1045
+ fi
1046
+ if [ -f backend/package.json ]; then
1047
+ npm --prefix backend run lint --if-present
1048
+ fi
1049
+ if [ -d super_dev ]; then
1050
+ ruff check super_dev tests
1051
+ mypy super_dev
1052
+ fi
1053
+ displayName: 'Run quality checks'
1054
+
1055
+ - script: |
1056
+ if [ -f frontend/package.json ]; then
1057
+ npm --prefix frontend run test --if-present
1058
+ fi
1059
+ if [ -f backend/package.json ]; then
1060
+ npm --prefix backend run test --if-present
1061
+ fi
1062
+ if [ -d tests ]; then
1063
+ pytest -q
1064
+ fi
1065
+ displayName: 'Run tests'
1066
+
1067
+ - task: PublishCodeCoverageResults@1
1068
+ inputs:
1069
+ codeCoverageTool: 'Cobertura'
1070
+ summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage/cobertura-coverage.xml'
1071
+ displayName: 'Publish coverage'
1072
+
1073
+ - task: PublishTestResults@2
1074
+ inputs:
1075
+ testResultsFiles: '**/junit.xml'
1076
+ testRunTitle: 'Test Results'
1077
+ displayName: 'Publish test results'
1078
+
1079
+ - script: |
1080
+ docker build -t $(dockerRegistry)/$(imageName):$(Build.BuildId) .
1081
+ docker tag $(dockerRegistry)/$(imageName):$(Build.BuildId) $(dockerRegistry)/$(imageName):latest
1082
+ displayName: 'Build Docker image'
1083
+
1084
+ - task: Docker@2
1085
+ displayName: 'Push to ACR'
1086
+ inputs:
1087
+ command: push
1088
+ repository: $(imageName)
1089
+ dockerfile: Dockerfile
1090
+ containerRegistry: 'your-acr-service-connection'
1091
+ tags: |
1092
+ $(Build.BuildId)
1093
+ latest
1094
+
1095
+ # ========== Deploy to Dev ==========
1096
+ - stage: DeployDev
1097
+ displayName: 'Deploy to Dev'
1098
+ dependsOn: Build
1099
+ condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop'))
1100
+ jobs:
1101
+ - deployment: DeployDev
1102
+ environment: 'dev'
1103
+ strategy:
1104
+ runOnce:
1105
+ deploy:
1106
+ steps:
1107
+ - task: KubernetesManifest@0
1108
+ displayName: 'Deploy to Dev'
1109
+ inputs:
1110
+ action: 'deploy'
1111
+ kubernetesServiceConnection: 'dev-k8s-connection'
1112
+ manifests: |
1113
+ k8s/deployment.yaml
1114
+ k8s/service.yaml
1115
+ containers: |
1116
+ $(imageName):$(Build.BuildId)
1117
+
1118
+ # ========== Deploy to Prod ==========
1119
+ - stage: DeployProd
1120
+ displayName: 'Deploy to Production'
1121
+ dependsOn: Build
1122
+ condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
1123
+ jobs:
1124
+ - deployment: DeployProd
1125
+ environment: 'production'
1126
+ strategy:
1127
+ runOnce:
1128
+ deploy:
1129
+ steps:
1130
+ - task: KubernetesManifest@0
1131
+ displayName: 'Deploy to Production'
1132
+ inputs:
1133
+ action: 'deploy'
1134
+ kubernetesServiceConnection: 'prod-k8s-connection'
1135
+ manifests: |
1136
+ k8s/deployment.yaml
1137
+ k8s/service.yaml
1138
+ k8s/ingress.yaml
1139
+ containers: |
1140
+ $(imageName):$(Build.BuildId)
1141
+ """
1142
+
1143
+
1144
+ def _generate_bitbucket(self) -> str:
1145
+ """生成 Bitbucket Pipelines 配置"""
1146
+ return f"""# Bitbucket Pipelines CI/CD for {self.name}
1147
+ image: node:18
1148
+
1149
+ definitions:
1150
+ services:
1151
+ postgres:
1152
+ image: postgres:15
1153
+ variables:
1154
+ POSTGRES_DB: test_db
1155
+ POSTGRES_PASSWORD: postgres
1156
+ redis:
1157
+ image: redis:7
1158
+
1159
+ caches:
1160
+ node_frontend: frontend/node_modules
1161
+ node_backend: backend/node_modules
1162
+
1163
+ pipelines:
1164
+ branches:
1165
+ main:
1166
+ - step:
1167
+ name: 'Build and Test'
1168
+ caches:
1169
+ - node_frontend
1170
+ - node_backend
1171
+ services:
1172
+ - postgres
1173
+ - redis
1174
+ script:
1175
+ - if [ -f frontend/package.json ]; then npm --prefix frontend ci; fi
1176
+ - if [ -f backend/package.json ]; then npm --prefix backend ci; fi
1177
+ - if [ -f frontend/package.json ]; then npm --prefix frontend run lint --if-present; npm --prefix frontend run type-check --if-present; fi
1178
+ - if [ -f backend/package.json ]; then npm --prefix backend run lint --if-present; fi
1179
+ - if [ -f frontend/package.json ]; then npm --prefix frontend run test --if-present; fi
1180
+ - if [ -f backend/package.json ]; then npm --prefix backend run test --if-present; fi
1181
+ after-script:
1182
+ - pipe: atlassian/code-insights:0.5.0
1183
+ variables:
1184
+ REPORT_TYPE: 'coverage'
1185
+ FORMAT: 'cobertura'
1186
+ FILE: 'coverage/cobertura-coverage.xml'
1187
+
1188
+ - step:
1189
+ name: 'Build Docker Image'
1190
+ script:
1191
+ - docker build -t ${{REGISTRY_URL}}/{self.name}:${{BITBUCKET_BUILD_NUMBER}} .
1192
+ - docker push ${{REGISTRY_URL}}/{self.name}:${{BITBUCKET_BUILD_NUMBER}}
1193
+ services:
1194
+ - docker
1195
+
1196
+ - step:
1197
+ name: 'Deploy to Production'
1198
+ deployment: production
1199
+ script:
1200
+ - pipe: atlassian/kubectl-deploy:1.7.0
1201
+ variables:
1202
+ KUBE_CONFIG: ${{KUBE_CONFIG_PROD}}
1203
+ KUBECTL_VERSION: '1.28.0'
1204
+ RESOURCE_PATH: 'k8s/'
1205
+ SELECTOR: 'app={self.name}'
1206
+ CONTAINER: '{self.name}'
1207
+ IMAGE: ${{REGISTRY_URL}}/{self.name}:${{BITBUCKET_BUILD_NUMBER}}
1208
+
1209
+ develop:
1210
+ - step:
1211
+ name: 'Build and Test'
1212
+ caches:
1213
+ - node_frontend
1214
+ - node_backend
1215
+ services:
1216
+ - postgres
1217
+ - redis
1218
+ script:
1219
+ - if [ -f frontend/package.json ]; then npm --prefix frontend ci; fi
1220
+ - if [ -f backend/package.json ]; then npm --prefix backend ci; fi
1221
+ - if [ -f frontend/package.json ]; then npm --prefix frontend run lint --if-present; npm --prefix frontend run type-check --if-present; fi
1222
+ - if [ -f backend/package.json ]; then npm --prefix backend run lint --if-present; fi
1223
+ - if [ -f frontend/package.json ]; then npm --prefix frontend run test --if-present; fi
1224
+ - if [ -f backend/package.json ]; then npm --prefix backend run test --if-present; fi
1225
+
1226
+ - step:
1227
+ name: 'Build Docker Image'
1228
+ script:
1229
+ - docker build -t ${{REGISTRY_URL}}/{self.name}:${{BITBUCKET_BUILD_NUMBER}} .
1230
+ - docker push ${{REGISTRY_URL}}/{self.name}:${{BITBUCKET_BUILD_NUMBER}}
1231
+ services:
1232
+ - docker
1233
+
1234
+ - step:
1235
+ name: 'Deploy to Dev'
1236
+ deployment: development
1237
+ script:
1238
+ - pipe: atlassian/kubectl-deploy:1.7.0
1239
+ variables:
1240
+ KUBE_CONFIG: ${{KUBE_CONFIG_DEV}}
1241
+ KUBECTL_VERSION: '1.28.0'
1242
+ RESOURCE_PATH: 'k8s/'
1243
+ SELECTOR: 'app={self.name}'
1244
+ CONTAINER: '{self.name}'
1245
+ IMAGE: ${{REGISTRY_URL}}/{self.name}:${{BITBUCKET_BUILD_NUMBER}}
1246
+
1247
+ pull-requests:
1248
+ - step:
1249
+ name: 'PR Build and Test'
1250
+ caches:
1251
+ - node_frontend
1252
+ - node_backend
1253
+ services:
1254
+ - postgres
1255
+ - redis
1256
+ script:
1257
+ - if [ -f frontend/package.json ]; then npm --prefix frontend ci; fi
1258
+ - if [ -f backend/package.json ]; then npm --prefix backend ci; fi
1259
+ - if [ -f frontend/package.json ]; then npm --prefix frontend run lint --if-present; npm --prefix frontend run type-check --if-present; fi
1260
+ - if [ -f backend/package.json ]; then npm --prefix backend run lint --if-present; fi
1261
+ - if [ -f frontend/package.json ]; then npm --prefix frontend run test --if-present; fi
1262
+ - if [ -f backend/package.json ]; then npm --prefix backend run test --if-present; fi
1263
+ after-script:
1264
+ - pipe: atlassian/code-insights:0.5.0
1265
+ variables:
1266
+ REPORT_TYPE: 'coverage'
1267
+ FORMAT: 'cobertura'
1268
+ FILE: 'coverage/cobertura-coverage.xml'
1269
+ """