pipecraft 0.28.2 → 0.28.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/cli/index.js +1 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/generators/init.tpl.d.ts.map +1 -1
- package/dist/generators/init.tpl.js +63 -12
- package/dist/generators/init.tpl.js.map +1 -1
- package/dist/generators/workflows.tpl.d.ts.map +1 -1
- package/dist/generators/workflows.tpl.js +10 -3
- package/dist/generators/workflows.tpl.js.map +1 -1
- package/dist/templates/workflows/pipeline-nx.yml.tpl.d.ts +22 -0
- package/dist/templates/workflows/pipeline-nx.yml.tpl.d.ts.map +1 -0
- package/dist/templates/workflows/pipeline-nx.yml.tpl.js +179 -0
- package/dist/templates/workflows/pipeline-nx.yml.tpl.js.map +1 -0
- package/dist/templates/workflows/pipeline.yml.tpl.d.ts +22 -0
- package/dist/templates/workflows/pipeline.yml.tpl.d.ts.map +1 -0
- package/dist/templates/workflows/pipeline.yml.tpl.js +136 -0
- package/dist/templates/workflows/pipeline.yml.tpl.js.map +1 -0
- package/dist/templates/workflows/shared/index.d.ts +11 -0
- package/dist/templates/workflows/shared/index.d.ts.map +1 -0
- package/dist/templates/workflows/shared/index.js +11 -0
- package/dist/templates/workflows/shared/index.js.map +1 -0
- package/dist/templates/workflows/shared/operations-changes.d.ts +17 -0
- package/dist/templates/workflows/shared/operations-changes.d.ts.map +1 -0
- package/dist/templates/workflows/shared/operations-changes.js +49 -0
- package/dist/templates/workflows/shared/operations-changes.js.map +1 -0
- package/dist/templates/workflows/shared/operations-domain-jobs.d.ts +31 -0
- package/dist/templates/workflows/shared/operations-domain-jobs.d.ts.map +1 -0
- package/dist/templates/workflows/shared/operations-domain-jobs.js +139 -0
- package/dist/templates/workflows/shared/operations-domain-jobs.js.map +1 -0
- package/dist/templates/workflows/shared/operations-header.d.ts +15 -0
- package/dist/templates/workflows/shared/operations-header.d.ts.map +1 -0
- package/dist/templates/workflows/shared/operations-header.js +158 -0
- package/dist/templates/workflows/shared/operations-header.js.map +1 -0
- package/dist/templates/workflows/shared/operations-tag-promote.d.ts +16 -0
- package/dist/templates/workflows/shared/operations-tag-promote.d.ts.map +1 -0
- package/dist/templates/workflows/shared/operations-tag-promote.js +115 -0
- package/dist/templates/workflows/shared/operations-tag-promote.js.map +1 -0
- package/dist/templates/workflows/shared/operations-version.d.ts +16 -0
- package/dist/templates/workflows/shared/operations-version.d.ts.map +1 -0
- package/dist/templates/workflows/shared/operations-version.js +57 -0
- package/dist/templates/workflows/shared/operations-version.js.map +1 -0
- package/dist/templates/yaml-format-utils.d.ts +24 -0
- package/dist/templates/yaml-format-utils.d.ts.map +1 -0
- package/dist/templates/yaml-format-utils.js +50 -0
- package/dist/templates/yaml-format-utils.js.map +1 -0
- package/dist/types/index.d.ts +42 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/generators/init.tpl.ts +71 -15
- package/src/generators/workflows.tpl.ts +9 -3
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts +0 -129
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts.map +0 -1
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.js +0 -1057
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.js.map +0 -1
- package/dist/utils/github-setup-v2.d.ts +0 -15
- package/dist/utils/github-setup-v2.d.ts.map +0 -1
- package/dist/utils/github-setup-v2.js +0 -217
- package/dist/utils/github-setup-v2.js.map +0 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Tag, Promote, and Release Job Operations
|
|
3
|
+
*
|
|
4
|
+
* Generates the tag creation, branch promotion, and GitHub release jobs.
|
|
5
|
+
*/
|
|
6
|
+
import { createValueFromString } from '../../../utils/ast-path-operations.js';
|
|
7
|
+
/**
|
|
8
|
+
* Create tag, promote, and release job operations
|
|
9
|
+
*/
|
|
10
|
+
export function createTagPromoteReleaseOperations(ctx) {
|
|
11
|
+
const { branchFlow, deployJobNames, remoteTestJobNames } = ctx;
|
|
12
|
+
// Provide sensible defaults if branchFlow is invalid
|
|
13
|
+
const validBranchFlow = (branchFlow && Array.isArray(branchFlow) && branchFlow.length > 0) ? branchFlow : ['main'];
|
|
14
|
+
const allDeploymentJobs = [...deployJobNames, ...remoteTestJobNames];
|
|
15
|
+
const initialBranch = validBranchFlow[0];
|
|
16
|
+
// Build tag job conditional (should only run on initial branch, not on PRs)
|
|
17
|
+
const tagConditions = [
|
|
18
|
+
'always()',
|
|
19
|
+
'github.event_name != \'pull_request\'',
|
|
20
|
+
`github.ref_name == '${initialBranch}'`,
|
|
21
|
+
'needs.version.result == \'success\'',
|
|
22
|
+
'needs.version.outputs.version != \'\''
|
|
23
|
+
];
|
|
24
|
+
if (allDeploymentJobs.length > 0) {
|
|
25
|
+
const noFailures = allDeploymentJobs.map(job => `needs.${job}.result != 'failure'`).join(' && ');
|
|
26
|
+
const atLeastOneSuccess = allDeploymentJobs.map(job => `needs.${job}.result == 'success'`).join(' || ');
|
|
27
|
+
tagConditions.push(`(${noFailures})`);
|
|
28
|
+
tagConditions.push(`(${atLeastOneSuccess})`);
|
|
29
|
+
}
|
|
30
|
+
const tagNeedsArray = ['version', ...allDeploymentJobs];
|
|
31
|
+
return [
|
|
32
|
+
// TAG JOB
|
|
33
|
+
{
|
|
34
|
+
path: 'jobs.tag',
|
|
35
|
+
operation: 'overwrite',
|
|
36
|
+
commentBefore: `
|
|
37
|
+
=============================================================================
|
|
38
|
+
TAG & PROMOTE (⚠️ Managed by Pipecraft - do not modify)
|
|
39
|
+
=============================================================================
|
|
40
|
+
Creates git tags and promotes code through branch flow.
|
|
41
|
+
`,
|
|
42
|
+
value: createValueFromString(`
|
|
43
|
+
if: \${{ ${tagConditions.join(' && ')} }}
|
|
44
|
+
needs: [ ${tagNeedsArray.join(', ')} ]
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v4
|
|
48
|
+
with:
|
|
49
|
+
ref: \${{ inputs.commitSha || github.sha }}
|
|
50
|
+
- uses: ./.github/actions/create-tag
|
|
51
|
+
with:
|
|
52
|
+
version: \${{ needs.version.outputs.version }}
|
|
53
|
+
commitSha: \${{ inputs.commitSha || github.sha }}
|
|
54
|
+
`)
|
|
55
|
+
},
|
|
56
|
+
// PROMOTE JOB
|
|
57
|
+
{
|
|
58
|
+
path: 'jobs.promote',
|
|
59
|
+
operation: 'overwrite',
|
|
60
|
+
value: createValueFromString(`
|
|
61
|
+
if: \${{ always() && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && needs.version.result == 'success' && needs.version.outputs.version != '' && (needs.tag.result == 'success' || needs.tag.result == 'skipped') && (${buildPromotableBranchesCondition(validBranchFlow)}) }}
|
|
62
|
+
needs: [ version, tag ]
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@v4
|
|
66
|
+
with:
|
|
67
|
+
ref: \${{ inputs.commitSha || github.sha }}
|
|
68
|
+
- uses: ./.github/actions/promote-branch
|
|
69
|
+
with:
|
|
70
|
+
version: \${{ needs.version.outputs.version }}
|
|
71
|
+
currentBranch: \${{ github.ref_name }}
|
|
72
|
+
nextBranch: \${{ ${buildNextBranchExpression(validBranchFlow)} }}
|
|
73
|
+
runNumber: \${{ github.run_number }}
|
|
74
|
+
`)
|
|
75
|
+
},
|
|
76
|
+
// RELEASE JOB
|
|
77
|
+
{
|
|
78
|
+
path: 'jobs.release',
|
|
79
|
+
operation: 'overwrite',
|
|
80
|
+
value: createValueFromString(`
|
|
81
|
+
if: \${{ always() && github.ref_name == '${validBranchFlow[validBranchFlow.length - 1]}' && needs.version.result == 'success' && needs.version.outputs.version != '' && needs.tag.result == 'success' }}
|
|
82
|
+
needs: [ tag, version ]
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@v4
|
|
86
|
+
with:
|
|
87
|
+
ref: \${{ inputs.commitSha || github.sha }}
|
|
88
|
+
- uses: ./.github/actions/create-release
|
|
89
|
+
with:
|
|
90
|
+
version: \${{ needs.version.outputs.version }}
|
|
91
|
+
commitSha: \${{ inputs.commitSha || github.sha }}
|
|
92
|
+
`)
|
|
93
|
+
}
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Helper to build promotable branches condition
|
|
98
|
+
* Returns a condition that checks if current branch is promotable (all except final branch)
|
|
99
|
+
*/
|
|
100
|
+
function buildPromotableBranchesCondition(branchFlow) {
|
|
101
|
+
const promotableBranches = branchFlow.slice(0, -1); // All branches except the last one
|
|
102
|
+
return promotableBranches.map(branch => `github.ref_name == '${branch}'`).join(' || ');
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Helper to build the nextBranch expression
|
|
106
|
+
*/
|
|
107
|
+
function buildNextBranchExpression(branchFlow) {
|
|
108
|
+
if (branchFlow.length === 1)
|
|
109
|
+
return `''`;
|
|
110
|
+
if (branchFlow.length === 2)
|
|
111
|
+
return `'${branchFlow[1]}'`;
|
|
112
|
+
// For 3+ branches: develop → staging, staging → main
|
|
113
|
+
return `github.ref_name == '${branchFlow[0]}' && '${branchFlow[1]}' || '${branchFlow[branchFlow.length - 1]}'`;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=operations-tag-promote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations-tag-promote.js","sourceRoot":"","sources":["../../../../src/templates/workflows/shared/operations-tag-promote.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Version Job Operation
|
|
3
|
+
*
|
|
4
|
+
* Generates the version calculation job that determines the next semantic version.
|
|
5
|
+
*/
|
|
6
|
+
import { PathOperationConfig } from '../../../utils/ast-path-operations.js';
|
|
7
|
+
export interface VersionContext {
|
|
8
|
+
testJobNames: string[];
|
|
9
|
+
nxEnabled?: boolean;
|
|
10
|
+
baseRef?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Create the version calculation job operation
|
|
14
|
+
*/
|
|
15
|
+
export declare function createVersionJobOperation(ctx: VersionContext): PathOperationConfig;
|
|
16
|
+
//# sourceMappingURL=operations-version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations-version.d.ts","sourceRoot":"","sources":["../../../../src/templates/workflows/shared/operations-version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAyB,MAAM,uCAAuC,CAAA;AAElG,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,cAAc,GAAG,mBAAmB,CAkDlF"}
|
|
@@ -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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -166,6 +166,48 @@ export interface PipecraftConfig {
|
|
|
166
166
|
* test and deployment requirements.
|
|
167
167
|
*/
|
|
168
168
|
domains: Record<string, DomainConfig>;
|
|
169
|
+
/**
|
|
170
|
+
* Nx monorepo integration configuration.
|
|
171
|
+
* When enabled, PipeCraft generates workflows that leverage Nx's dependency graph
|
|
172
|
+
* and affected detection for intelligent change-based testing.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```typescript
|
|
176
|
+
* nx: {
|
|
177
|
+
* enabled: true,
|
|
178
|
+
* tasks: ['lint', 'test', 'build', 'integration-test'],
|
|
179
|
+
* baseRef: 'origin/main'
|
|
180
|
+
* }
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
nx?: {
|
|
184
|
+
/**
|
|
185
|
+
* Whether Nx integration is enabled for this project.
|
|
186
|
+
* Auto-detected if nx.json exists in project root.
|
|
187
|
+
*/
|
|
188
|
+
enabled: boolean;
|
|
189
|
+
/**
|
|
190
|
+
* Ordered list of Nx tasks to run sequentially.
|
|
191
|
+
* Tasks are executed using `nx affected --target=<task>`.
|
|
192
|
+
*
|
|
193
|
+
* @example ['lint', 'test', 'build', 'e2e']
|
|
194
|
+
*/
|
|
195
|
+
tasks: string[];
|
|
196
|
+
/**
|
|
197
|
+
* Base git reference for affected detection.
|
|
198
|
+
* Used in `nx affected --base=<baseRef>`.
|
|
199
|
+
*
|
|
200
|
+
* @default 'origin/main'
|
|
201
|
+
*/
|
|
202
|
+
baseRef?: string;
|
|
203
|
+
/**
|
|
204
|
+
* Whether to include Nx cache management in workflows.
|
|
205
|
+
* Speeds up subsequent runs by caching build outputs.
|
|
206
|
+
*
|
|
207
|
+
* @default true
|
|
208
|
+
*/
|
|
209
|
+
enableCache?: boolean;
|
|
210
|
+
};
|
|
169
211
|
/**
|
|
170
212
|
* Idempotency and rebuild configuration.
|
|
171
213
|
* 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":"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"}
|
|
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.
|
|
3
|
+
"version": "0.28.3",
|
|
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",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
31
|
import { PinionContext, toFile, renderTemplate, prompt, when, writeJSON } from '@featherscloud/pinion'
|
|
32
|
-
import { existsSync } from 'fs'
|
|
32
|
+
import { existsSync, readFileSync } from 'fs'
|
|
33
33
|
import { IdempotencyManager } from '../utils/idempotency.js'
|
|
34
34
|
import { VersionManager } from '../utils/versioning.js'
|
|
35
35
|
import { PipecraftConfig } from '../types/index.js'
|
|
@@ -98,7 +98,7 @@ const defaultConfig = {
|
|
|
98
98
|
* only valid configuration properties are included in the output file.
|
|
99
99
|
*/
|
|
100
100
|
const configTemplate = (ctx: PipecraftConfig) => {
|
|
101
|
-
const config = {
|
|
101
|
+
const config: any = {
|
|
102
102
|
ciProvider: ctx.ciProvider,
|
|
103
103
|
mergeStrategy: ctx.mergeStrategy,
|
|
104
104
|
requireConventionalCommits: ctx.requireConventionalCommits,
|
|
@@ -112,6 +112,11 @@ const configTemplate = (ctx: PipecraftConfig) => {
|
|
|
112
112
|
domains: ctx.domains
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
// Include Nx configuration if detected
|
|
116
|
+
if (ctx.nx) {
|
|
117
|
+
config.nx = ctx.nx
|
|
118
|
+
}
|
|
119
|
+
|
|
115
120
|
return JSON.stringify(config, null, 2)
|
|
116
121
|
}
|
|
117
122
|
|
|
@@ -211,20 +216,71 @@ export const generate = (ctx: PinionContext) =>
|
|
|
211
216
|
filter: (input: string) => input.split(',').map(b => b.trim())
|
|
212
217
|
}
|
|
213
218
|
]))
|
|
214
|
-
.then((ctx) =>
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
219
|
+
.then((ctx) => {
|
|
220
|
+
const mergedCtx = { ...ctx, ...defaultConfig } as any
|
|
221
|
+
|
|
222
|
+
// Detect Nx workspace
|
|
223
|
+
const nxJsonPath = `${mergedCtx.cwd || process.cwd()}/nx.json`
|
|
224
|
+
let nxConfig = undefined
|
|
225
|
+
|
|
226
|
+
if (existsSync(nxJsonPath)) {
|
|
227
|
+
try {
|
|
228
|
+
const nxJsonContent = readFileSync(nxJsonPath, 'utf8')
|
|
229
|
+
const nxJson = JSON.parse(nxJsonContent)
|
|
230
|
+
|
|
231
|
+
// Extract tasks from targetDefaults
|
|
232
|
+
const tasks = nxJson.targetDefaults ? Object.keys(nxJson.targetDefaults) : []
|
|
233
|
+
|
|
234
|
+
// Sort tasks in a logical order (quality → test → build → e2e)
|
|
235
|
+
const taskOrder = ['lint', 'typecheck', 'test', 'unit-test', 'build', 'integration-test', 'e2e', 'e2e-ci']
|
|
236
|
+
const sortedTasks = tasks.sort((a, b) => {
|
|
237
|
+
const aIdx = taskOrder.indexOf(a)
|
|
238
|
+
const bIdx = taskOrder.indexOf(b)
|
|
239
|
+
if (aIdx === -1 && bIdx === -1) return 0
|
|
240
|
+
if (aIdx === -1) return 1
|
|
241
|
+
if (bIdx === -1) return -1
|
|
242
|
+
return aIdx - bIdx
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
console.log('✅ Nx workspace detected - enabling Nx integration')
|
|
246
|
+
console.log(` Detected tasks: ${sortedTasks.join(', ')}`)
|
|
247
|
+
|
|
248
|
+
nxConfig = {
|
|
249
|
+
enabled: true,
|
|
250
|
+
tasks: sortedTasks,
|
|
251
|
+
baseRef: 'origin/main',
|
|
252
|
+
enableCache: true
|
|
253
|
+
}
|
|
254
|
+
} catch (error) {
|
|
255
|
+
console.warn('⚠️ Found nx.json but could not parse it:', error)
|
|
256
|
+
console.log(' Using default Nx configuration')
|
|
257
|
+
nxConfig = {
|
|
258
|
+
enabled: true,
|
|
259
|
+
tasks: ['lint', 'test', 'build', 'integration-test'],
|
|
260
|
+
baseRef: 'origin/main',
|
|
261
|
+
enableCache: true
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const configData: any = {
|
|
267
|
+
ciProvider: mergedCtx.ciProvider,
|
|
268
|
+
mergeStrategy: mergedCtx.mergeStrategy,
|
|
269
|
+
requireConventionalCommits: mergedCtx.requireConventionalCommits,
|
|
270
|
+
initialBranch: mergedCtx.initialBranch,
|
|
271
|
+
finalBranch: mergedCtx.finalBranch,
|
|
272
|
+
branchFlow: mergedCtx.branchFlow,
|
|
273
|
+
autoMerge: mergedCtx.autoMerge,
|
|
224
274
|
semver: {
|
|
225
|
-
bumpRules:
|
|
275
|
+
bumpRules: mergedCtx.semver.bumpRules
|
|
226
276
|
},
|
|
227
|
-
domains:
|
|
277
|
+
domains: mergedCtx.domains
|
|
228
278
|
}
|
|
229
|
-
|
|
279
|
+
|
|
280
|
+
// Add Nx config if detected
|
|
281
|
+
if (nxConfig) {
|
|
282
|
+
configData.nx = nxConfig
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return writeJSON(() => configData, toFile('.pipecraftrc.json'))(mergedCtx)
|
|
230
286
|
})
|
|
@@ -56,7 +56,8 @@ import { generate as generateCreatePRWorkflow } from '../templates/actions/creat
|
|
|
56
56
|
import { generate as generateBranchWorkflow } from '../templates/actions/manage-branch.yml.tpl.js'
|
|
57
57
|
import { generate as generatePromoteBranchWorkflow } from '../templates/actions/promote-branch.yml.tpl.js'
|
|
58
58
|
import { generate as generateReleaseWorkflow } from '../templates/actions/create-release.yml.tpl.js'
|
|
59
|
-
import { generate as generatePathBasedPipeline } from '../templates/workflows/pipeline
|
|
59
|
+
import { generate as generatePathBasedPipeline } from '../templates/workflows/pipeline.yml.tpl.js'
|
|
60
|
+
import { generate as generateNxPipeline } from '../templates/workflows/pipeline-nx.yml.tpl.js'
|
|
60
61
|
import { generate as generateEnforcePRTarget } from '../templates/workflows/enforce-pr-target.yml.tpl.js'
|
|
61
62
|
import { generate as generatePRTitleCheck } from '../templates/workflows/pr-title-check.yml.tpl.js'
|
|
62
63
|
import { generate as generateReleaseItConfig } from '../templates/release-it.cjs.tpl.js'
|
|
@@ -170,8 +171,13 @@ export const generate = (ctx: PinionContext & { pipelinePath?: string, outputPip
|
|
|
170
171
|
]).then(() => ctx)
|
|
171
172
|
})
|
|
172
173
|
.then((ctx) => {
|
|
173
|
-
// Generate the main pipeline
|
|
174
|
-
|
|
174
|
+
// Generate the main pipeline (Nx or path-based)
|
|
175
|
+
if (ctx.config?.nx?.enabled) {
|
|
176
|
+
logger.info('🔧 Generating Nx-optimized pipeline...')
|
|
177
|
+
return generateNxPipeline(ctx as any)
|
|
178
|
+
} else {
|
|
179
|
+
return generatePathBasedPipeline(ctx)
|
|
180
|
+
}
|
|
175
181
|
})
|
|
176
182
|
.then((ctx) => {
|
|
177
183
|
// Generate the enforce PR target workflow
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Path-Based Pipeline Template Generator
|
|
3
|
-
*
|
|
4
|
-
* The core template that generates the main CI/CD pipeline workflow for PipeCraft.
|
|
5
|
-
* This is the most complex template in the system, responsible for creating a
|
|
6
|
-
* GitHub Actions workflow that orchestrates the entire trunk-based development flow.
|
|
7
|
-
*
|
|
8
|
-
* ## Key Responsibilities
|
|
9
|
-
*
|
|
10
|
-
* 1. **Change Detection**: Generates jobs to detect which domains (api, web, libs, etc.) changed
|
|
11
|
-
* 2. **Test Execution**: Creates domain-specific test jobs based on changes
|
|
12
|
-
* 3. **Version Management**: Integrates semantic versioning for staging/production branches
|
|
13
|
-
* 4. **Branch Promotion**: Auto-promotes code through branch flow (develop → staging → main)
|
|
14
|
-
* 5. **User Job Preservation**: Maintains user-added custom jobs during regeneration
|
|
15
|
-
* 6. **Comment Preservation**: Retains user comments when updating workflows
|
|
16
|
-
*
|
|
17
|
-
* ## Intelligent Merging
|
|
18
|
-
*
|
|
19
|
-
* The generator distinguishes between:
|
|
20
|
-
* - **Pipecraft-owned jobs**: `changes`, `version`, `tag`, `promote`, `release`, `test-*`, `deploy-*`
|
|
21
|
-
* - **User jobs**: Any jobs not owned by Pipecraft
|
|
22
|
-
*
|
|
23
|
-
* During regeneration:
|
|
24
|
-
* - Pipecraft jobs are completely replaced with template versions
|
|
25
|
-
* - User jobs are preserved exactly as-is
|
|
26
|
-
* - User comments are maintained
|
|
27
|
-
* - Job order is intelligently managed (Pipecraft jobs first, then user jobs)
|
|
28
|
-
*
|
|
29
|
-
* ## Architecture
|
|
30
|
-
*
|
|
31
|
-
* Uses AST-based path operations for surgical YAML manipulation:
|
|
32
|
-
* - Parse existing workflow into AST
|
|
33
|
-
* - Apply precise path-based operations
|
|
34
|
-
* - Preserve formatting and comments
|
|
35
|
-
* - Rebuild YAML maintaining structure
|
|
36
|
-
*
|
|
37
|
-
* @module templates/workflows/pipeline-path-based.yml.tpl
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* ```typescript
|
|
41
|
-
* import { generate } from './templates/workflows/pipeline-path-based.yml.tpl.js'
|
|
42
|
-
*
|
|
43
|
-
* // Initial generation
|
|
44
|
-
* await generate({
|
|
45
|
-
* cwd: '/path/to/project',
|
|
46
|
-
* branchFlow: ['develop', 'staging', 'main'],
|
|
47
|
-
* domains: {
|
|
48
|
-
* api: { paths: ['src/api/**'], test: true },
|
|
49
|
-
* web: { paths: ['src/web/**'], test: true }
|
|
50
|
-
* }
|
|
51
|
-
* })
|
|
52
|
-
*
|
|
53
|
-
* // Incremental update (preserves user jobs)
|
|
54
|
-
* await generate({
|
|
55
|
-
* cwd: '/path/to/project',
|
|
56
|
-
* existingPipeline: parsedYAML,
|
|
57
|
-
* existingPipelineContent: rawYAMLString,
|
|
58
|
-
* branchFlow: ['develop', 'staging', 'main'],
|
|
59
|
-
* domains: { ... }
|
|
60
|
-
* })
|
|
61
|
-
* ```
|
|
62
|
-
*
|
|
63
|
-
* @see {@link module:utils/ast-path-operations} for YAML manipulation details
|
|
64
|
-
*/
|
|
65
|
-
import { PinionContext } from '@featherscloud/pinion';
|
|
66
|
-
/**
|
|
67
|
-
* Create path-based pipeline content
|
|
68
|
-
*/
|
|
69
|
-
export declare const createPathBasedPipeline: (ctx: any) => {
|
|
70
|
-
yamlContent: string;
|
|
71
|
-
mergeStatus: string;
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* Main pipeline generator entry point.
|
|
75
|
-
*
|
|
76
|
-
* Generates the complete GitHub Actions pipeline workflow with intelligent
|
|
77
|
-
* merging of existing user customizations.
|
|
78
|
-
*
|
|
79
|
-
* @param {PinionContext & { existingPipeline?: any, outputPipelinePath?: string }} ctx - Generator context
|
|
80
|
-
* @param {any} [ctx.existingPipeline] - Parsed existing pipeline YAML for merging
|
|
81
|
-
* @param {string} [ctx.existingPipelineContent] - Raw existing pipeline content for comment preservation
|
|
82
|
-
* @param {string} [ctx.outputPipelinePath] - Custom output path (default: .github/workflows/pipeline.yml)
|
|
83
|
-
* @param {string[]} ctx.branchFlow - Branch flow sequence (e.g., ['develop', 'staging', 'main'])
|
|
84
|
-
* @param {Record<string, DomainConfig>} ctx.domains - Domain configurations for change detection
|
|
85
|
-
* @param {string} [ctx.ciProvider] - CI provider ('github' or 'gitlab')
|
|
86
|
-
* @param {string} [ctx.mergeStrategy] - Merge strategy ('fast-forward' or 'merge')
|
|
87
|
-
* @returns {Promise<PinionContext>} Updated context with generated YAML
|
|
88
|
-
*
|
|
89
|
-
* @throws {Error} If pipeline file cannot be written
|
|
90
|
-
* @throws {Error} If existing pipeline cannot be parsed
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* ```typescript
|
|
94
|
-
* // Generate new pipeline
|
|
95
|
-
* await generate({
|
|
96
|
-
* cwd: '/path/to/project',
|
|
97
|
-
* branchFlow: ['develop', 'main'],
|
|
98
|
-
* domains: {
|
|
99
|
-
* api: { paths: ['src/api/**'], test: true }
|
|
100
|
-
* }
|
|
101
|
-
* })
|
|
102
|
-
*
|
|
103
|
-
* // Update existing pipeline (preserves user jobs)
|
|
104
|
-
* const existing = parseDocument(readFileSync('pipeline.yml', 'utf8'))
|
|
105
|
-
* await generate({
|
|
106
|
-
* cwd: '/path/to/project',
|
|
107
|
-
* existingPipeline: existing,
|
|
108
|
-
* existingPipelineContent: readFileSync('pipeline.yml', 'utf8'),
|
|
109
|
-
* branchFlow: ['develop', 'staging', 'main'],
|
|
110
|
-
* domains: { ... }
|
|
111
|
-
* })
|
|
112
|
-
* ```
|
|
113
|
-
*
|
|
114
|
-
* @note The generator performs these steps:
|
|
115
|
-
* 1. Calls `createPathBasedPipeline()` to build the workflow
|
|
116
|
-
* 2. Logs merge status (new vs. merged)
|
|
117
|
-
* 3. Writes the final YAML to the output path
|
|
118
|
-
*
|
|
119
|
-
* The heavy lifting is done by `createPathBasedPipeline()` which handles:
|
|
120
|
-
* - Job generation based on domains and branch flow
|
|
121
|
-
* - User job preservation and merging
|
|
122
|
-
* - Comment preservation from existing pipeline
|
|
123
|
-
* - Intelligent job ordering
|
|
124
|
-
*/
|
|
125
|
-
export declare const generate: (ctx: PinionContext & {
|
|
126
|
-
existingPipeline?: any;
|
|
127
|
-
outputPipelinePath?: string;
|
|
128
|
-
}) => Promise<any>;
|
|
129
|
-
//# sourceMappingURL=pipeline-path-based.yml.tpl.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline-path-based.yml.tpl.d.ts","sourceRoot":"","sources":["../../../src/templates/workflows/pipeline-path-based.yml.tpl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAEH,OAAO,EAAE,aAAa,EAA0B,MAAM,uBAAuB,CAAA;AAsD7E;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,KAAK,GAAG;;;CAm5B/C,CAAA;AAcD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,eAAO,MAAM,QAAQ,GAAI,KAAK,aAAa,GAAG;IAAE,gBAAgB,CAAC,EAAE,GAAG,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAE,iBAoB/F,CAAA"}
|