create-sdd-project 0.6.0 → 0.6.1

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 CHANGED
@@ -168,6 +168,17 @@ npx create-sdd-project --doctor
168
168
 
169
169
  Exit code 1 if errors found — useful for CI pipelines.
170
170
 
171
+ ### CI/CD (Auto-Generated)
172
+
173
+ Every project gets a GitHub Actions CI workflow at `.github/workflows/ci.yml`, adapted to your stack:
174
+
175
+ - **PostgreSQL** projects get a `postgres:16` service with health checks
176
+ - **MongoDB** projects get a `mongo:7` service with health checks
177
+ - **Frontend-only** projects get a lightweight workflow without DB services
178
+ - **GitFlow** projects trigger on both `main` and `develop` branches
179
+
180
+ Customize the generated workflow as your project grows.
181
+
171
182
  ### After Setup
172
183
 
173
184
  Open your project in Claude Code or Gemini and start building:
@@ -313,6 +324,9 @@ project/
313
324
  ├── GEMINI.md # Gemini config (autonomy)
314
325
  ├── .env.example # Environment variables template
315
326
 
327
+ ├── .github/
328
+ │ └── workflows/ci.yml # CI pipeline (adapted to your stack)
329
+
316
330
  ├── .claude/
317
331
  │ ├── agents/ # 9 specialized agents
318
332
  │ ├── skills/
package/lib/generator.js CHANGED
@@ -66,6 +66,10 @@ function generate(config) {
66
66
  adaptAgentContent(dest, config);
67
67
  }
68
68
 
69
+ // 7c. Adapt CI workflow for project type and stack
70
+ step('Configuring CI workflow');
71
+ adaptCiWorkflow(dest, config);
72
+
69
73
  // 8. Remove AI tool config if single tool selected
70
74
  if (config.aiTools === 'claude') {
71
75
  step('Removing Gemini config (Claude only)');
@@ -350,4 +354,46 @@ function adaptAgentContent(dest, config) {
350
354
  adaptAgentContentForProjectType(dest, config, replaceInFile);
351
355
  }
352
356
 
357
+ function adaptCiWorkflow(dest, config) {
358
+ const ciPath = path.join(dest, '.github', 'workflows', 'ci.yml');
359
+ if (!fs.existsSync(ciPath)) return;
360
+
361
+ const bPreset = config.backendPreset || BACKEND_STACKS[0];
362
+
363
+ // Adapt branches for gitflow
364
+ if (config.branching === 'gitflow') {
365
+ replaceInFile(ciPath, [
366
+ ['branches: [main]', 'branches: [main, develop]'],
367
+ ]);
368
+ }
369
+
370
+ // Adapt DB services based on stack
371
+ if (config.projectType === 'frontend') {
372
+ // Frontend-only: remove services and DATABASE_URL
373
+ replaceInFile(ciPath, [
374
+ [/\n # -- Database service.*?--health-retries=5\n/s, ''],
375
+ [/\n DATABASE_URL:.*\n/, '\n'],
376
+ ]);
377
+ } else if (bPreset.db === 'MongoDB') {
378
+ // MongoDB: replace postgres service with mongo
379
+ replaceInFile(ciPath, [
380
+ [/ # -- Database service.*?--health-retries=5\n/s,
381
+ ` # -- Database service (remove if not needed) --\n` +
382
+ ` services:\n` +
383
+ ` mongodb:\n` +
384
+ ` image: mongo:7\n` +
385
+ ` ports:\n` +
386
+ ` - 27017:27017\n` +
387
+ ` options: >-\n` +
388
+ ` --health-cmd="mongosh --eval 'db.runCommand({ping:1})'"\n` +
389
+ ` --health-interval=10s\n` +
390
+ ` --health-timeout=5s\n` +
391
+ ` --health-retries=5\n`],
392
+ ['DATABASE_URL: postgresql://test:test@localhost:5432/testdb',
393
+ 'MONGODB_URI: mongodb://localhost:27017/testdb'],
394
+ ]);
395
+ }
396
+ // Default (PostgreSQL) — template already has correct services
397
+ }
398
+
353
399
  module.exports = { generate };
@@ -184,7 +184,20 @@ function generateInit(config) {
184
184
  // 8. Append to .gitignore
185
185
  appendGitignore(dest, skipped);
186
186
 
187
- // 9. Copy and adapt .env.example if not present
187
+ // 9. Copy CI workflow if not present
188
+ const githubDir = path.join(dest, '.github', 'workflows');
189
+ const ciPath = path.join(githubDir, 'ci.yml');
190
+ if (!fs.existsSync(ciPath)) {
191
+ step('Creating .github/workflows/ci.yml');
192
+ ensureDir(githubDir);
193
+ let ciContent = fs.readFileSync(path.join(templateDir, '.github', 'workflows', 'ci.yml'), 'utf8');
194
+ ciContent = adaptCiWorkflowContent(ciContent, config, scan);
195
+ fs.writeFileSync(ciPath, ciContent, 'utf8');
196
+ } else {
197
+ skipped.push('.github/workflows/ci.yml');
198
+ }
199
+
200
+ // 10. Copy and adapt .env.example if not present
188
201
  const envExamplePath = path.join(dest, '.env.example');
189
202
  if (!fs.existsSync(envExamplePath)) {
190
203
  let envContent = fs.readFileSync(path.join(templateDir, '.env.example'), 'utf8');
@@ -950,6 +963,47 @@ function updateAutonomy(dest, config) {
950
963
  }
951
964
  }
952
965
 
966
+ // --- CI Workflow Adaptation ---
967
+
968
+ function adaptCiWorkflowContent(template, config, scan) {
969
+ let content = template;
970
+
971
+ // Adapt branches for gitflow
972
+ if (config.branching === 'gitflow') {
973
+ content = content.replaceAll('branches: [main]', 'branches: [main, develop]');
974
+ }
975
+
976
+ // Adapt DB services based on detected stack
977
+ if (!scan.backend.detected) {
978
+ // Frontend-only: remove services block and DATABASE_URL
979
+ content = content.replace(/\n # -- Database service.*?--health-retries=5\n/s, '');
980
+ content = content.replace(/\n DATABASE_URL:.*\n/, '\n');
981
+ } else if (scan.backend.db === 'MongoDB') {
982
+ // MongoDB: replace postgres service with mongo
983
+ content = content.replace(
984
+ / # -- Database service.*?--health-retries=5\n/s,
985
+ ` # -- Database service (remove if not needed) --\n` +
986
+ ` services:\n` +
987
+ ` mongodb:\n` +
988
+ ` image: mongo:7\n` +
989
+ ` ports:\n` +
990
+ ` - 27017:27017\n` +
991
+ ` options: >-\n` +
992
+ ` --health-cmd="mongosh --eval 'db.runCommand({ping:1})'"\n` +
993
+ ` --health-interval=10s\n` +
994
+ ` --health-timeout=5s\n` +
995
+ ` --health-retries=5\n`
996
+ );
997
+ content = content.replace(
998
+ 'DATABASE_URL: postgresql://test:test@localhost:5432/testdb',
999
+ 'MONGODB_URI: mongodb://localhost:27017/testdb'
1000
+ );
1001
+ }
1002
+ // Default (PostgreSQL) — template already has correct services
1003
+
1004
+ return content;
1005
+ }
1006
+
953
1007
  // --- .env.example Adaptation ---
954
1008
 
955
1009
  function adaptEnvExample(template, config, scan) {
@@ -1008,6 +1062,7 @@ module.exports = {
1008
1062
  adaptAgentsMd,
1009
1063
  adaptCopiedFiles,
1010
1064
  adaptEnvExample,
1065
+ adaptCiWorkflowContent,
1011
1066
  updateAutonomy,
1012
1067
  regexReplaceInFile,
1013
1068
  };
@@ -16,6 +16,7 @@ const {
16
16
  adaptAgentsMd,
17
17
  adaptCopiedFiles,
18
18
  adaptEnvExample,
19
+ adaptCiWorkflowContent,
19
20
  updateAutonomy,
20
21
  regexReplaceInFile,
21
22
  } = require('./init-generator');
@@ -408,6 +409,17 @@ function generateUpgrade(config) {
408
409
 
409
410
  step('Replaced AGENTS.md, CLAUDE.md/GEMINI.md, .env.example');
410
411
 
412
+ // --- e2) CI workflow — only add if not present (user may have customized) ---
413
+ const ciPath = path.join(dest, '.github', 'workflows', 'ci.yml');
414
+ if (!fs.existsSync(ciPath)) {
415
+ fs.mkdirSync(path.join(dest, '.github', 'workflows'), { recursive: true });
416
+ let ciContent = fs.readFileSync(path.join(templateDir, '.github', 'workflows', 'ci.yml'), 'utf8');
417
+ ciContent = adaptCiWorkflowContent(ciContent, config, scan);
418
+ fs.writeFileSync(ciPath, ciContent, 'utf8');
419
+ step('Added .github/workflows/ci.yml');
420
+ replaced++;
421
+ }
422
+
411
423
  // --- f) Adapt for project type ---
412
424
  // Remove agents for single-stack projects
413
425
  if (projectType === 'backend') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-sdd-project",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Create a new SDD DevFlow project with AI-assisted development workflow",
5
5
  "bin": {
6
6
  "create-sdd-project": "bin/cli.js"
@@ -0,0 +1,56 @@
1
+ # ===========================================
2
+ # CI Pipeline — Generated by SDD DevFlow
3
+ # ===========================================
4
+ # Runs on pushes and PRs to main branch.
5
+ # Customize steps as your project grows.
6
+
7
+ name: CI
8
+
9
+ on:
10
+ push:
11
+ branches: [main]
12
+ pull_request:
13
+ branches: [main]
14
+
15
+ jobs:
16
+ ci:
17
+ runs-on: ubuntu-latest
18
+
19
+ # -- Database service (remove if not needed) --
20
+ services:
21
+ postgres:
22
+ image: postgres:16
23
+ env:
24
+ POSTGRES_USER: test
25
+ POSTGRES_PASSWORD: test
26
+ POSTGRES_DB: testdb
27
+ ports:
28
+ - 5432:5432
29
+ options: >-
30
+ --health-cmd="pg_isready"
31
+ --health-interval=10s
32
+ --health-timeout=5s
33
+ --health-retries=5
34
+
35
+ env:
36
+ NODE_ENV: test
37
+ DATABASE_URL: postgresql://test:test@localhost:5432/testdb
38
+
39
+ steps:
40
+ - uses: actions/checkout@v4
41
+
42
+ - uses: actions/setup-node@v4
43
+ with:
44
+ node-version: 20
45
+ cache: npm
46
+
47
+ - run: npm ci
48
+
49
+ - name: Lint
50
+ run: npm run lint --if-present
51
+
52
+ - name: Test
53
+ run: npm test --if-present
54
+
55
+ - name: Build
56
+ run: npm run build --if-present