pipecraft 0.28.2 → 0.29.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.
Files changed (62) hide show
  1. package/README.md +5 -2
  2. package/dist/cli/index.js +1 -9
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/generators/init.tpl.d.ts.map +1 -1
  5. package/dist/generators/init.tpl.js +140 -67
  6. package/dist/generators/init.tpl.js.map +1 -1
  7. package/dist/generators/workflows.tpl.d.ts.map +1 -1
  8. package/dist/generators/workflows.tpl.js +18 -5
  9. package/dist/generators/workflows.tpl.js.map +1 -1
  10. package/dist/templates/actions/detect-changes-nx.yml.tpl.d.ts +32 -0
  11. package/dist/templates/actions/detect-changes-nx.yml.tpl.d.ts.map +1 -0
  12. package/dist/templates/actions/detect-changes-nx.yml.tpl.js +227 -0
  13. package/dist/templates/actions/detect-changes-nx.yml.tpl.js.map +1 -0
  14. package/dist/templates/workflows/pipeline-nx.yml.tpl.d.ts +22 -0
  15. package/dist/templates/workflows/pipeline-nx.yml.tpl.d.ts.map +1 -0
  16. package/dist/templates/workflows/pipeline-nx.yml.tpl.js +196 -0
  17. package/dist/templates/workflows/pipeline-nx.yml.tpl.js.map +1 -0
  18. package/dist/templates/workflows/pipeline.yml.tpl.d.ts +22 -0
  19. package/dist/templates/workflows/pipeline.yml.tpl.d.ts.map +1 -0
  20. package/dist/templates/workflows/pipeline.yml.tpl.js +136 -0
  21. package/dist/templates/workflows/pipeline.yml.tpl.js.map +1 -0
  22. package/dist/templates/workflows/shared/index.d.ts +11 -0
  23. package/dist/templates/workflows/shared/index.d.ts.map +1 -0
  24. package/dist/templates/workflows/shared/index.js +11 -0
  25. package/dist/templates/workflows/shared/index.js.map +1 -0
  26. package/dist/templates/workflows/shared/operations-changes.d.ts +17 -0
  27. package/dist/templates/workflows/shared/operations-changes.d.ts.map +1 -0
  28. package/dist/templates/workflows/shared/operations-changes.js +49 -0
  29. package/dist/templates/workflows/shared/operations-changes.js.map +1 -0
  30. package/dist/templates/workflows/shared/operations-domain-jobs.d.ts +31 -0
  31. package/dist/templates/workflows/shared/operations-domain-jobs.d.ts.map +1 -0
  32. package/dist/templates/workflows/shared/operations-domain-jobs.js +139 -0
  33. package/dist/templates/workflows/shared/operations-domain-jobs.js.map +1 -0
  34. package/dist/templates/workflows/shared/operations-header.d.ts +15 -0
  35. package/dist/templates/workflows/shared/operations-header.d.ts.map +1 -0
  36. package/dist/templates/workflows/shared/operations-header.js +158 -0
  37. package/dist/templates/workflows/shared/operations-header.js.map +1 -0
  38. package/dist/templates/workflows/shared/operations-tag-promote.d.ts +16 -0
  39. package/dist/templates/workflows/shared/operations-tag-promote.d.ts.map +1 -0
  40. package/dist/templates/workflows/shared/operations-tag-promote.js +115 -0
  41. package/dist/templates/workflows/shared/operations-tag-promote.js.map +1 -0
  42. package/dist/templates/workflows/shared/operations-version.d.ts +16 -0
  43. package/dist/templates/workflows/shared/operations-version.d.ts.map +1 -0
  44. package/dist/templates/workflows/shared/operations-version.js +57 -0
  45. package/dist/templates/workflows/shared/operations-version.js.map +1 -0
  46. package/dist/templates/yaml-format-utils.d.ts +24 -0
  47. package/dist/templates/yaml-format-utils.d.ts.map +1 -0
  48. package/dist/templates/yaml-format-utils.js +50 -0
  49. package/dist/templates/yaml-format-utils.js.map +1 -0
  50. package/dist/types/index.d.ts +53 -0
  51. package/dist/types/index.d.ts.map +1 -1
  52. package/package.json +3 -1
  53. package/src/generators/init.tpl.ts +151 -73
  54. package/src/generators/workflows.tpl.ts +19 -5
  55. package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts +0 -129
  56. package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts.map +0 -1
  57. package/dist/templates/workflows/pipeline-path-based.yml.tpl.js +0 -1057
  58. package/dist/templates/workflows/pipeline-path-based.yml.tpl.js.map +0 -1
  59. package/dist/utils/github-setup-v2.d.ts +0 -15
  60. package/dist/utils/github-setup-v2.d.ts.map +0 -1
  61. package/dist/utils/github-setup-v2.js +0 -217
  62. package/dist/utils/github-setup-v2.js.map +0 -1
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Shared Version Job Operation
3
+ *
4
+ * Generates the version calculation job that determines the next semantic version.
5
+ */
6
+ import { createValueFromString } from '../../../utils/ast-path-operations.js';
7
+ /**
8
+ * Create the version calculation job operation
9
+ */
10
+ export function createVersionJobOperation(ctx) {
11
+ const { testJobNames, nxEnabled = false, baseRef = 'main' } = ctx;
12
+ // Build the needs array
13
+ const nxJobName = nxEnabled ? 'nx-ci' : null;
14
+ const needsArray = ['changes', nxJobName, ...testJobNames].filter(Boolean);
15
+ // Build the conditional logic
16
+ const nxCondition = nxEnabled ? 'needs.nx-ci.result == \'success\'' : '';
17
+ const testConditions = testJobNames.length > 0
18
+ ? [
19
+ `(${testJobNames.map(job => `needs.${job}.result == 'success'`).join(' || ')})`,
20
+ testJobNames.map(job => `needs.${job}.result != 'failure'`).join(' && ')
21
+ ]
22
+ : [];
23
+ const allConditions = [
24
+ 'always()',
25
+ 'github.event_name != \'pull_request\'',
26
+ nxCondition,
27
+ ...testConditions
28
+ ].filter(Boolean).join(' && ');
29
+ return {
30
+ path: 'jobs.version',
31
+ operation: 'overwrite',
32
+ commentBefore: `
33
+ =============================================================================
34
+ VERSIONING (⚠️ Managed by Pipecraft - do not modify)
35
+ =============================================================================
36
+ Calculates the next semantic version based on conventional commits.
37
+ Only runs on push events (skipped on pull requests).
38
+ `,
39
+ value: createValueFromString(`
40
+ if: \${{ ${allConditions} }}
41
+ needs: [ ${needsArray.join(', ')} ]
42
+ runs-on: ubuntu-latest
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+ with:
46
+ ref: \${{ inputs.commitSha || github.sha }}
47
+ - uses: ./.github/actions/calculate-version
48
+ id: version
49
+ with:
50
+ baseRef: \${{ inputs.baseRef || '${baseRef}' }}
51
+ commitSha: \${{ inputs.commitSha || github.sha }}
52
+ outputs:
53
+ version: \${{ steps.version.outputs.version }}
54
+ `)
55
+ };
56
+ }
57
+ //# sourceMappingURL=operations-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations-version.js","sourceRoot":"","sources":["../../../../src/templates/workflows/shared/operations-version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAuB,qBAAqB,EAAE,MAAM,uCAAuC,CAAA;AAQlG;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,GAAmB;IAC3D,MAAM,EAAE,YAAY,EAAE,SAAS,GAAG,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,GAAG,CAAA;IAEjE,wBAAwB;IACxB,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA;IAC5C,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,YAAY,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAE1E,8BAA8B;IAC9B,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,EAAE,CAAA;IACxE,MAAM,cAAc,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC;QAC5C,CAAC,CAAC;YACE,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,GAAG,sBAAsB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG;YAC/E,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,GAAG,sBAAsB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;SACzE;QACH,CAAC,CAAC,EAAE,CAAA;IAEN,MAAM,aAAa,GAAG;QACpB,UAAU;QACV,uCAAuC;QACvC,WAAW;QACX,GAAG,cAAc;KAClB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAE9B,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,SAAS,EAAE,WAAW;QACtB,aAAa,EAAE;;;;;;CAMlB;QACG,KAAK,EAAE,qBAAqB,CAAC;eAClB,aAAa;eACb,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;6CASS,OAAO;;;;GAIjD,CAAC;KACD,CAAA;AACH,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Utility functions for formatting YAML content in GitHub Actions workflows
3
+ */
4
+ /**
5
+ * Formats long GitHub Actions conditional expressions for better readability.
6
+ * Takes a YAML string and formats multi-line `if:` conditions with proper indentation.
7
+ *
8
+ * @param yamlContent - The YAML content to format
9
+ * @param minLength - Minimum length threshold for formatting (default: 80 characters)
10
+ * @returns Formatted YAML content
11
+ *
12
+ * @example
13
+ * Input:
14
+ * if: ${{ always() && github.event_name != 'pull_request' && needs.test.result == 'success' }}
15
+ *
16
+ * Output:
17
+ * if: ${{
18
+ * always() &&
19
+ * github.event_name != 'pull_request' &&
20
+ * needs.test.result == 'success'
21
+ * }}
22
+ */
23
+ export declare function formatIfConditions(yamlContent: string, minLength?: number): string;
24
+ //# sourceMappingURL=yaml-format-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml-format-utils.d.ts","sourceRoot":"","sources":["../../src/templates/yaml-format-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,GAAE,MAAW,GAAG,MAAM,CAkCtF"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Utility functions for formatting YAML content in GitHub Actions workflows
3
+ */
4
+ /**
5
+ * Formats long GitHub Actions conditional expressions for better readability.
6
+ * Takes a YAML string and formats multi-line `if:` conditions with proper indentation.
7
+ *
8
+ * @param yamlContent - The YAML content to format
9
+ * @param minLength - Minimum length threshold for formatting (default: 80 characters)
10
+ * @returns Formatted YAML content
11
+ *
12
+ * @example
13
+ * Input:
14
+ * if: ${{ always() && github.event_name != 'pull_request' && needs.test.result == 'success' }}
15
+ *
16
+ * Output:
17
+ * if: ${{
18
+ * always() &&
19
+ * github.event_name != 'pull_request' &&
20
+ * needs.test.result == 'success'
21
+ * }}
22
+ */
23
+ export function formatIfConditions(yamlContent, minLength = 80) {
24
+ return yamlContent.replace(/if: \$\{\{([^}]+)\}\}/g, (match, condition) => {
25
+ // Only format if the condition is long enough to benefit from formatting
26
+ if (condition.length < minLength)
27
+ return match;
28
+ let formatted = condition.trim();
29
+ // Step 1: Protect function calls like always() by replacing with placeholders
30
+ const functionCalls = [];
31
+ formatted = formatted.replace(/(\w+)\(\)/g, (match) => {
32
+ const placeholder = `__FUNC_${functionCalls.length}__`;
33
+ functionCalls.push(match);
34
+ return placeholder;
35
+ });
36
+ // Step 2: Add line breaks for logical operators
37
+ formatted = formatted.replace(/\s+&&\s+/g, ' &&\n ');
38
+ formatted = formatted.replace(/\s+\|\|\s+/g, ' ||\n ');
39
+ // Step 3: Format grouping parentheses (now that function calls are protected)
40
+ formatted = formatted.replace(/\(\s*/g, '(\n ');
41
+ formatted = formatted.replace(/\s*\)\s*(&&|\|\|)/g, '\n ) $1');
42
+ formatted = formatted.replace(/\s*\)(\s*)$/g, '\n )');
43
+ // Step 4: Restore function calls
44
+ functionCalls.forEach((funcCall, index) => {
45
+ formatted = formatted.replace(`__FUNC_${index}__`, funcCall);
46
+ });
47
+ return `if: $\{{\n ${formatted}\n }}`;
48
+ });
49
+ }
50
+ //# sourceMappingURL=yaml-format-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml-format-utils.js","sourceRoot":"","sources":["../../src/templates/yaml-format-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,kBAAkB,CAAC,WAAmB,EAAE,YAAoB,EAAE;IAC5E,OAAO,WAAW,CAAC,OAAO,CACxB,wBAAwB,EACxB,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE;QACnB,yEAAyE;QACzE,IAAI,SAAS,CAAC,MAAM,GAAG,SAAS;YAAE,OAAO,KAAK,CAAA;QAE9C,IAAI,SAAS,GAAG,SAAS,CAAC,IAAI,EAAE,CAAA;QAEhC,8EAA8E;QAC9E,MAAM,aAAa,GAAa,EAAE,CAAA;QAClC,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,KAAa,EAAE,EAAE;YAC5D,MAAM,WAAW,GAAG,UAAU,aAAa,CAAC,MAAM,IAAI,CAAA;YACtD,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACzB,OAAO,WAAW,CAAA;QACpB,CAAC,CAAC,CAAA;QAEF,gDAAgD;QAChD,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,eAAe,CAAC,CAAA;QAC3D,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,eAAe,CAAC,CAAA;QAE7D,8EAA8E;QAC9E,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;QACtD,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,oBAAoB,EAAE,cAAc,CAAC,CAAA;QACnE,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,cAAc,EAAE,WAAW,CAAC,CAAA;QAE1D,iCAAiC;QACjC,aAAa,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE;YACxC,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,UAAU,KAAK,IAAI,EAAE,QAAQ,CAAC,CAAA;QAC9D,CAAC,CAAC,CAAA;QAEF,OAAO,qBAAqB,SAAS,YAAY,CAAA;IACnD,CAAC,CACF,CAAA;AACH,CAAC"}
@@ -166,6 +166,59 @@ export interface PipecraftConfig {
166
166
  * test and deployment requirements.
167
167
  */
168
168
  domains: Record<string, DomainConfig>;
169
+ /**
170
+ * Package manager used for dependency installation.
171
+ * Auto-detected during init based on lockfile presence.
172
+ *
173
+ * - 'npm': Uses npm (with package-lock.json)
174
+ * - 'yarn': Uses yarn (with yarn.lock)
175
+ * - 'pnpm': Uses pnpm (with pnpm-lock.yaml)
176
+ *
177
+ * @default 'npm'
178
+ */
179
+ packageManager?: 'npm' | 'yarn' | 'pnpm';
180
+ /**
181
+ * Nx monorepo integration configuration.
182
+ * When enabled, PipeCraft generates workflows that leverage Nx's dependency graph
183
+ * and affected detection for intelligent change-based testing.
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * nx: {
188
+ * enabled: true,
189
+ * tasks: ['lint', 'test', 'build', 'integration-test'],
190
+ * baseRef: 'origin/main'
191
+ * }
192
+ * ```
193
+ */
194
+ nx?: {
195
+ /**
196
+ * Whether Nx integration is enabled for this project.
197
+ * Auto-detected if nx.json exists in project root.
198
+ */
199
+ enabled: boolean;
200
+ /**
201
+ * Ordered list of Nx tasks to run sequentially.
202
+ * Tasks are executed using `nx affected --target=<task>`.
203
+ *
204
+ * @example ['lint', 'test', 'build', 'e2e']
205
+ */
206
+ tasks: string[];
207
+ /**
208
+ * Base git reference for affected detection.
209
+ * Used in `nx affected --base=<baseRef>`.
210
+ *
211
+ * @default 'origin/main'
212
+ */
213
+ baseRef?: string;
214
+ /**
215
+ * Whether to include Nx cache management in workflows.
216
+ * Speeds up subsequent runs by caching build outputs.
217
+ *
218
+ * @default true
219
+ */
220
+ enableCache?: boolean;
221
+ };
169
222
  /**
170
223
  * Idempotency and rebuild configuration.
171
224
  * Controls when workflows should be regenerated based on config/template changes.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,KAAK,EAAE,MAAM,EAAE,CAAA;IAEf;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IAEpB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,UAAU,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAE/B;;;;OAIG;IACH,aAAa,EAAE,cAAc,GAAG,OAAO,CAAA;IAEvC;;;;OAIG;IACH,0BAA0B,EAAE,OAAO,CAAA;IAEnC;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAA;IAErB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB;;;;;OAKG;IACH,UAAU,EAAE,MAAM,EAAE,CAAA;IAEpB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAE7C;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC,CAAA;IAE7G;;;;;;;;;;;;;;OAcG;IACH,MAAM,EAAE;QACN;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAClC,CAAA;IAED;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IAErC;;;OAGG;IACH,OAAO,CAAC,EAAE;QACR;;;WAGG;QACH,OAAO,EAAE,OAAO,CAAA;QAEhB;;WAEG;QACH,eAAe,EAAE,OAAO,CAAA;QAExB;;;WAGG;QACH,eAAe,EAAE,OAAO,CAAA;QAExB;;WAEG;QACH,SAAS,EAAE,OAAO,CAAA;QAElB;;WAEG;QACH,aAAa,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;QAExC;;WAEG;QACH,SAAS,EAAE,MAAM,CAAA;QAEjB;;WAEG;QACH,cAAc,EAAE,MAAM,EAAE,CAAA;KACzB,CAAA;IAED;;;OAGG;IACH,UAAU,CAAC,EAAE;QACX;;WAEG;QACH,OAAO,EAAE,OAAO,CAAA;QAEhB;;WAEG;QACH,eAAe,EAAE,MAAM,CAAA;QAEvB;;WAEG;QACH,mBAAmB,EAAE,OAAO,CAAA;QAE5B;;WAEG;QACH,OAAO,EAAE,OAAO,CAAA;QAEhB;;WAEG;QACH,QAAQ,EAAE,OAAO,CAAA;QAEjB;;WAEG;QACH,SAAS,EAAE,OAAO,CAAA;QAElB;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAClC,CAAA;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,UAAU,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAE/B;;OAEG;IACH,aAAa,EAAE,cAAc,GAAG,OAAO,CAAA;IAEvC;;OAEG;IACH,0BAA0B,EAAE,OAAO,CAAA;IAEnC;;OAEG;IACH,aAAa,EAAE,MAAM,CAAA;IAErB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,UAAU,EAAE,MAAM,EAAE,CAAA;IAEpB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IAErI;;OAEG;IACH,MAAM,EAAE;QACN,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAClC,CAAA;CAEF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pipecraft",
3
- "version": "0.28.2",
3
+ "version": "0.29.0",
4
4
  "description": "Automated CI/CD pipeline generator for trunk-based development. Generates intelligent GitHub Actions workflows with domain-based change detection, semantic versioning, and branch flow management. Full documentation: https://pipecraft.thecraftlab.dev",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -68,6 +68,7 @@
68
68
  "@eslint/eslintrc": "^3.3.1",
69
69
  "@eslint/js": "^9.24.0",
70
70
  "@release-it/conventional-changelog": "^10.0.0",
71
+ "@types/inquirer": "^9.0.9",
71
72
  "@typescript-eslint/eslint-plugin": "^8.30.1",
72
73
  "@typescript-eslint/parser": "^8.30.1",
73
74
  "@vitest/coverage-c8": "^0.33.0",
@@ -82,6 +83,7 @@
82
83
  "eslint-plugin-react": "^7.37.5",
83
84
  "eslint-plugin-react-hooks": "^5.2.0",
84
85
  "globals": "^16.0.0",
86
+ "inquirer": "^12.10.0",
85
87
  "prettier": "^2.8.8",
86
88
  "release-it": "^18.1.2",
87
89
  "typedoc": "^0.28.14",
@@ -28,8 +28,9 @@
28
28
  * respect user input and allow customization.
29
29
  */
30
30
 
31
- import { PinionContext, toFile, renderTemplate, prompt, when, writeJSON } from '@featherscloud/pinion'
32
- import { existsSync } from 'fs'
31
+ import { PinionContext, toFile, renderTemplate, writeJSON } from '@featherscloud/pinion'
32
+ import { existsSync, readFileSync } from 'fs'
33
+ import inquirer from 'inquirer'
33
34
  import { IdempotencyManager } from '../utils/idempotency.js'
34
35
  import { VersionManager } from '../utils/versioning.js'
35
36
  import { PipecraftConfig } from '../types/index.js'
@@ -98,7 +99,7 @@ const defaultConfig = {
98
99
  * only valid configuration properties are included in the output file.
99
100
  */
100
101
  const configTemplate = (ctx: PipecraftConfig) => {
101
- const config = {
102
+ const config: any = {
102
103
  ciProvider: ctx.ciProvider,
103
104
  mergeStrategy: ctx.mergeStrategy,
104
105
  requireConventionalCommits: ctx.requireConventionalCommits,
@@ -112,6 +113,11 @@ const configTemplate = (ctx: PipecraftConfig) => {
112
113
  domains: ctx.domains
113
114
  }
114
115
 
116
+ // Include Nx configuration if detected
117
+ if (ctx.nx) {
118
+ config.nx = ctx.nx
119
+ }
120
+
115
121
  return JSON.stringify(config, null, 2)
116
122
  }
117
123
 
@@ -156,75 +162,147 @@ const configTemplate = (ctx: PipecraftConfig) => {
156
162
  * - Production branch name
157
163
  * - Branch flow sequence
158
164
  */
159
- export const generate = (ctx: PinionContext) =>
160
- Promise.resolve(ctx)
161
- .then(prompt([
162
- {
163
- type: 'input',
164
- name: 'projectName',
165
- message: 'What is your project name?',
166
- default: 'my-project'
167
- },
168
- {
169
- type: 'list',
170
- name: 'ciProvider',
171
- message: 'Which CI provider are you using?',
172
- choices: [
173
- { name: 'GitHub Actions', value: 'github' },
174
- { name: 'GitLab CI/CD', value: 'gitlab' }
175
- ],
176
- default: 'github'
177
- },
178
- {
179
- type: 'list',
180
- name: 'mergeStrategy',
181
- message: 'What merge strategy do you prefer?',
182
- choices: [
183
- { name: 'Fast-forward only (recommended)', value: 'fast-forward' },
184
- { name: 'Merge commits', value: 'merge' }
185
- ],
186
- default: 'fast-forward'
187
- },
188
- {
189
- type: 'confirm',
190
- name: 'requireConventionalCommits',
191
- message: 'Require conventional commit format for PR titles?',
192
- default: true
193
- },
194
- {
195
- type: 'input',
196
- name: 'initialBranch',
197
- message: 'What is your development branch name?',
198
- default: 'develop'
199
- },
200
- {
201
- type: 'input',
202
- name: 'finalBranch',
203
- message: 'What is your production branch name?',
204
- default: 'main'
205
- },
206
- {
207
- type: 'input',
208
- name: 'branchFlow',
209
- message: 'Enter your branch flow (comma-separated)',
210
- default: 'develop,staging,main',
211
- filter: (input: string) => input.split(',').map(b => b.trim())
165
+ export const generate = async (ctx: PinionContext) => {
166
+ const cwd = ctx.cwd || process.cwd()
167
+
168
+ // Detect package manager before prompting
169
+ let detectedPackageManager: 'npm' | 'yarn' | 'pnpm' = 'npm'
170
+ if (existsSync(`${cwd}/pnpm-lock.yaml`)) {
171
+ detectedPackageManager = 'pnpm'
172
+ } else if (existsSync(`${cwd}/yarn.lock`)) {
173
+ detectedPackageManager = 'yarn'
174
+ } else if (existsSync(`${cwd}/package-lock.json`)) {
175
+ detectedPackageManager = 'npm'
176
+ }
177
+
178
+ // Run inquirer prompts
179
+ const answers = await inquirer.prompt([
180
+ {
181
+ type: 'input',
182
+ name: 'projectName',
183
+ message: 'What is your project name?',
184
+ default: 'my-project'
185
+ },
186
+ {
187
+ type: 'list',
188
+ name: 'ciProvider',
189
+ message: 'Which CI provider are you using?',
190
+ choices: [
191
+ { name: 'GitHub Actions', value: 'github' },
192
+ { name: 'GitLab CI/CD', value: 'gitlab' }
193
+ ],
194
+ default: 'github'
195
+ },
196
+ {
197
+ type: 'list',
198
+ name: 'mergeStrategy',
199
+ message: 'What merge strategy do you prefer?',
200
+ choices: [
201
+ { name: 'Fast-forward only (recommended)', value: 'fast-forward' },
202
+ { name: 'Merge commits', value: 'merge' }
203
+ ],
204
+ default: 'fast-forward'
205
+ },
206
+ {
207
+ type: 'confirm',
208
+ name: 'requireConventionalCommits',
209
+ message: 'Require conventional commit format for PR titles?',
210
+ default: true
211
+ },
212
+ {
213
+ type: 'input',
214
+ name: 'initialBranch',
215
+ message: 'What is your development branch name?',
216
+ default: 'develop'
217
+ },
218
+ {
219
+ type: 'input',
220
+ name: 'finalBranch',
221
+ message: 'What is your production branch name?',
222
+ default: 'main'
223
+ },
224
+ {
225
+ type: 'input',
226
+ name: 'branchFlow',
227
+ message: 'Enter your branch flow (comma-separated)',
228
+ default: 'develop,staging,main',
229
+ filter: (input: string) => input.split(',').map(b => b.trim())
230
+ },
231
+ {
232
+ type: 'list',
233
+ name: 'packageManager',
234
+ message: `Which package manager do you use? (detected: ${detectedPackageManager})`,
235
+ choices: ['npm', 'yarn', 'pnpm'],
236
+ default: detectedPackageManager
237
+ }
238
+ ])
239
+
240
+ // Merge answers with context and defaults
241
+ const mergedCtx = { ...ctx, ...defaultConfig, ...answers } as any
242
+
243
+ // Detect Nx workspace
244
+ const nxJsonPath = `${cwd}/nx.json`
245
+ let nxConfig = undefined
246
+
247
+ if (existsSync(nxJsonPath)) {
248
+ try {
249
+ const nxJsonContent = readFileSync(nxJsonPath, 'utf8')
250
+ const nxJson = JSON.parse(nxJsonContent)
251
+
252
+ // Extract tasks from targetDefaults
253
+ const tasks = nxJson.targetDefaults ? Object.keys(nxJson.targetDefaults) : []
254
+
255
+ // Sort tasks in a logical order (quality → test → build → e2e)
256
+ const taskOrder = ['lint', 'typecheck', 'test', 'unit-test', 'build', 'integration-test', 'e2e', 'e2e-ci']
257
+ const sortedTasks = tasks.sort((a, b) => {
258
+ const aIdx = taskOrder.indexOf(a)
259
+ const bIdx = taskOrder.indexOf(b)
260
+ if (aIdx === -1 && bIdx === -1) return 0
261
+ if (aIdx === -1) return 1
262
+ if (bIdx === -1) return -1
263
+ return aIdx - bIdx
264
+ })
265
+
266
+ console.log('✅ Nx workspace detected - enabling Nx integration')
267
+ console.log(` Detected tasks: ${sortedTasks.join(', ')}`)
268
+
269
+ nxConfig = {
270
+ enabled: true,
271
+ tasks: sortedTasks,
272
+ baseRef: 'origin/main',
273
+ enableCache: true
212
274
  }
213
- ]))
214
- .then((ctx) => ({ ...ctx, ...defaultConfig } as PipecraftConfig))
215
- .then((config) => {
216
- const configData = {
217
- ciProvider: config.ciProvider,
218
- mergeStrategy: config.mergeStrategy,
219
- requireConventionalCommits: config.requireConventionalCommits,
220
- initialBranch: config.initialBranch,
221
- finalBranch: config.finalBranch,
222
- branchFlow: config.branchFlow,
223
- autoMerge: config.autoMerge,
224
- semver: {
225
- bumpRules: config.semver.bumpRules
226
- },
227
- domains: config.domains
275
+ } catch (error) {
276
+ console.warn('⚠️ Found nx.json but could not parse it:', error)
277
+ console.log(' Using default Nx configuration')
278
+ nxConfig = {
279
+ enabled: true,
280
+ tasks: ['lint', 'test', 'build', 'integration-test'],
281
+ baseRef: 'origin/main',
282
+ enableCache: true
228
283
  }
229
- return writeJSON(() => configData, toFile('.pipecraftrc.json'))(ctx)
230
- })
284
+ }
285
+ }
286
+
287
+ const configData: any = {
288
+ ciProvider: mergedCtx.ciProvider,
289
+ mergeStrategy: mergedCtx.mergeStrategy,
290
+ requireConventionalCommits: mergedCtx.requireConventionalCommits,
291
+ initialBranch: mergedCtx.initialBranch,
292
+ finalBranch: mergedCtx.finalBranch,
293
+ branchFlow: mergedCtx.branchFlow,
294
+ autoMerge: mergedCtx.autoMerge,
295
+ packageManager: mergedCtx.packageManager,
296
+ semver: {
297
+ bumpRules: mergedCtx.semver.bumpRules
298
+ },
299
+ domains: mergedCtx.domains
300
+ }
301
+
302
+ // Add Nx config if detected
303
+ if (nxConfig) {
304
+ configData.nx = nxConfig
305
+ }
306
+
307
+ return writeJSON(() => configData, toFile('.pipecraftrc.json'))(mergedCtx)
308
+ }
@@ -51,12 +51,14 @@ import { logger } from '../utils/logger.js'
51
51
  // Import individual workflow templates
52
52
  import { generate as generateTagWorkflow } from '../templates/actions/create-tag.yml.tpl.js'
53
53
  import { generate as generateChangesWorkflow } from '../templates/actions/detect-changes.yml.tpl.js'
54
+ import { generate as generateChangesNxWorkflow } from '../templates/actions/detect-changes-nx.yml.tpl.js'
54
55
  import { generate as generateVersionWorkflow } from '../templates/actions/calculate-version.yml.tpl.js'
55
56
  import { generate as generateCreatePRWorkflow } from '../templates/actions/create-pr.yml.tpl.js'
56
57
  import { generate as generateBranchWorkflow } from '../templates/actions/manage-branch.yml.tpl.js'
57
58
  import { generate as generatePromoteBranchWorkflow } from '../templates/actions/promote-branch.yml.tpl.js'
58
59
  import { generate as generateReleaseWorkflow } from '../templates/actions/create-release.yml.tpl.js'
59
- import { generate as generatePathBasedPipeline } from '../templates/workflows/pipeline-path-based.yml.tpl.js'
60
+ import { generate as generatePathBasedPipeline } from '../templates/workflows/pipeline.yml.tpl.js'
61
+ import { generate as generateNxPipeline } from '../templates/workflows/pipeline-nx.yml.tpl.js'
60
62
  import { generate as generateEnforcePRTarget } from '../templates/workflows/enforce-pr-target.yml.tpl.js'
61
63
  import { generate as generatePRTitleCheck } from '../templates/workflows/pr-title-check.yml.tpl.js'
62
64
  import { generate as generateReleaseItConfig } from '../templates/release-it.cjs.tpl.js'
@@ -158,7 +160,7 @@ export const generate = (ctx: PinionContext & { pipelinePath?: string, outputPip
158
160
  })
159
161
  .then((ctx) => {
160
162
  // Generate individual GitHub Actions and release-it config
161
- return Promise.all([
163
+ const generators = [
162
164
  generateChangesWorkflow(ctx),
163
165
  generateTagWorkflow(ctx),
164
166
  generateVersionWorkflow(ctx),
@@ -167,11 +169,23 @@ export const generate = (ctx: PinionContext & { pipelinePath?: string, outputPip
167
169
  generatePromoteBranchWorkflow(ctx),
168
170
  generateReleaseWorkflow(ctx),
169
171
  generateReleaseItConfig(ctx)
170
- ]).then(() => ctx)
172
+ ]
173
+
174
+ // Add Nx-specific action if Nx is enabled
175
+ if (ctx.config?.nx?.enabled) {
176
+ generators.push(generateChangesNxWorkflow(ctx))
177
+ }
178
+
179
+ return Promise.all(generators).then(() => ctx)
171
180
  })
172
181
  .then((ctx) => {
173
- // Generate the main pipeline
174
- return generatePathBasedPipeline(ctx)
182
+ // Generate the main pipeline (Nx or path-based)
183
+ if (ctx.config?.nx?.enabled) {
184
+ logger.info('🔧 Generating Nx-optimized pipeline...')
185
+ return generateNxPipeline(ctx as any)
186
+ } else {
187
+ return generatePathBasedPipeline(ctx)
188
+ }
175
189
  })
176
190
  .then((ctx) => {
177
191
  // Generate the enforce PR target workflow