cistack 1.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -34
- package/bin/ciflow.js +91 -7
- package/package.json +10 -3
- package/src/analyzers/monorepo.js +124 -0
- package/src/analyzers/workflow.js +195 -0
- package/src/config/loader.js +163 -0
- package/src/detectors/env.js +69 -0
- package/src/detectors/framework.js +37 -12
- package/src/detectors/hosting.js +54 -46
- package/src/detectors/release.js +124 -0
- package/src/generators/dependabot.js +155 -0
- package/src/generators/release.js +195 -0
- package/src/generators/workflow.js +402 -125
- package/src/index.js +247 -54
- package/src/utils/helpers.js +146 -9
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Detects the release tooling used in a project.
|
|
8
|
+
*
|
|
9
|
+
* Checks (in order of priority):
|
|
10
|
+
* 1. semantic-release
|
|
11
|
+
* 2. @changesets/cli
|
|
12
|
+
* 3. release-it
|
|
13
|
+
* 4. standard-version
|
|
14
|
+
*
|
|
15
|
+
* Returns: { tool: string, config: object, publishToNpm: bool } or null
|
|
16
|
+
*/
|
|
17
|
+
class ReleaseDetector {
|
|
18
|
+
constructor(projectPath, codebaseInfo) {
|
|
19
|
+
this.root = projectPath;
|
|
20
|
+
this.info = codebaseInfo;
|
|
21
|
+
this.pkg = codebaseInfo.packageJson || {};
|
|
22
|
+
this.deps = {
|
|
23
|
+
...(this.pkg.dependencies || {}),
|
|
24
|
+
...(this.pkg.devDependencies || {}),
|
|
25
|
+
};
|
|
26
|
+
this.scripts = this.pkg.scripts || {};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async detect() {
|
|
30
|
+
// --- semantic-release ---
|
|
31
|
+
if (this.deps['semantic-release']) {
|
|
32
|
+
const config = this._loadSemanticReleaseConfig();
|
|
33
|
+
const plugins = config.plugins || ['@semantic-release/commit-analyzer', '@semantic-release/release-notes-generator', '@semantic-release/github'];
|
|
34
|
+
return {
|
|
35
|
+
tool: 'semantic-release',
|
|
36
|
+
command: 'npx semantic-release',
|
|
37
|
+
config,
|
|
38
|
+
plugins,
|
|
39
|
+
publishToNpm: plugins.some((p) => (typeof p === 'string' ? p : p[0]) === '@semantic-release/npm'),
|
|
40
|
+
requiresNpmToken: plugins.some((p) => (typeof p === 'string' ? p : p[0]) === '@semantic-release/npm'),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// --- changesets ---
|
|
45
|
+
if (this.deps['@changesets/cli']) {
|
|
46
|
+
const publishScript = this.scripts['release'] || this.scripts['publish'];
|
|
47
|
+
return {
|
|
48
|
+
tool: 'changesets',
|
|
49
|
+
command: 'npx changeset publish',
|
|
50
|
+
publishToNpm: !!(publishScript && publishScript.includes('publish')),
|
|
51
|
+
requiresNpmToken: true,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// --- release-it ---
|
|
56
|
+
if (this.deps['release-it']) {
|
|
57
|
+
const config = this._loadReleaseItConfig();
|
|
58
|
+
return {
|
|
59
|
+
tool: 'release-it',
|
|
60
|
+
command: 'npx release-it --ci',
|
|
61
|
+
config,
|
|
62
|
+
publishToNpm: !!(config && config.npm && config.npm.publish !== false),
|
|
63
|
+
requiresNpmToken: true,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// --- standard-version ---
|
|
68
|
+
if (this.deps['standard-version']) {
|
|
69
|
+
return {
|
|
70
|
+
tool: 'standard-version',
|
|
71
|
+
command: 'npx standard-version',
|
|
72
|
+
publishToNpm: false,
|
|
73
|
+
requiresNpmToken: false,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// --- fallback: check scripts ---
|
|
78
|
+
const releaseScript = this.scripts['release'] || this.scripts['version'];
|
|
79
|
+
if (releaseScript) {
|
|
80
|
+
return {
|
|
81
|
+
tool: 'custom',
|
|
82
|
+
command: 'npm run release',
|
|
83
|
+
publishToNpm: releaseScript.includes('publish'),
|
|
84
|
+
requiresNpmToken: releaseScript.includes('publish'),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
_loadSemanticReleaseConfig() {
|
|
92
|
+
// Try .releaserc, .releaserc.json, .releaserc.js, package.json#release
|
|
93
|
+
const candidates = ['.releaserc', '.releaserc.json', '.releaserc.js', '.releaserc.yaml'];
|
|
94
|
+
for (const c of candidates) {
|
|
95
|
+
const p = path.join(this.root, c);
|
|
96
|
+
if (fs.existsSync(p)) {
|
|
97
|
+
try {
|
|
98
|
+
const raw = fs.readFileSync(p, 'utf8');
|
|
99
|
+
if (c.endsWith('.js')) return require(p);
|
|
100
|
+
return JSON.parse(raw);
|
|
101
|
+
} catch (_) {}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (this.pkg.release) return this.pkg.release;
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
_loadReleaseItConfig() {
|
|
109
|
+
const candidates = ['.release-it.json', '.release-it.js', '.release-it.yaml'];
|
|
110
|
+
for (const c of candidates) {
|
|
111
|
+
const p = path.join(this.root, c);
|
|
112
|
+
if (fs.existsSync(p)) {
|
|
113
|
+
try {
|
|
114
|
+
const raw = fs.readFileSync(p, 'utf8');
|
|
115
|
+
return JSON.parse(raw);
|
|
116
|
+
} catch (_) {}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (this.pkg['release-it']) return this.pkg['release-it'];
|
|
120
|
+
return {};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
module.exports = ReleaseDetector;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const yaml = require('js-yaml');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generates a .github/dependabot.yml based on detected ecosystems.
|
|
7
|
+
*
|
|
8
|
+
* Supported ecosystems:
|
|
9
|
+
* npm, pip, cargo, bundler, go, maven, gradle, github-actions, composer, docker
|
|
10
|
+
*/
|
|
11
|
+
class DependabotGenerator {
|
|
12
|
+
constructor(codebaseInfo) {
|
|
13
|
+
this.info = codebaseInfo;
|
|
14
|
+
this.pkg = codebaseInfo.packageJson || {};
|
|
15
|
+
this.lockFiles = new Set(codebaseInfo.lockFiles || []);
|
|
16
|
+
this.configFiles = new Set(codebaseInfo.configFiles || []);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
generate() {
|
|
20
|
+
const updates = [];
|
|
21
|
+
|
|
22
|
+
// ── npm ────────────────────────────────────────────────────────────────
|
|
23
|
+
if (this.pkg.dependencies || this.pkg.devDependencies ||
|
|
24
|
+
this.lockFiles.has('package-lock.json') ||
|
|
25
|
+
this.lockFiles.has('yarn.lock') ||
|
|
26
|
+
this.lockFiles.has('pnpm-lock.yaml')) {
|
|
27
|
+
updates.push({
|
|
28
|
+
'package-ecosystem': 'npm',
|
|
29
|
+
directory: '/',
|
|
30
|
+
schedule: { interval: 'weekly', day: 'monday' },
|
|
31
|
+
'open-pull-requests-limit': 10,
|
|
32
|
+
groups: {
|
|
33
|
+
'dev-dependencies': {
|
|
34
|
+
'dependency-type': 'development',
|
|
35
|
+
'update-types': ['minor', 'patch'],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ── pip ────────────────────────────────────────────────────────────────
|
|
42
|
+
if (this.lockFiles.has('Pipfile.lock') ||
|
|
43
|
+
this.configFiles.has('requirements.txt') ||
|
|
44
|
+
this.configFiles.has('pyproject.toml')) {
|
|
45
|
+
updates.push({
|
|
46
|
+
'package-ecosystem': 'pip',
|
|
47
|
+
directory: '/',
|
|
48
|
+
schedule: { interval: 'weekly', day: 'monday' },
|
|
49
|
+
'open-pull-requests-limit': 10,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ── cargo ──────────────────────────────────────────────────────────────
|
|
54
|
+
if (this.lockFiles.has('Cargo.lock') || this.configFiles.has('Cargo.toml')) {
|
|
55
|
+
updates.push({
|
|
56
|
+
'package-ecosystem': 'cargo',
|
|
57
|
+
directory: '/',
|
|
58
|
+
schedule: { interval: 'weekly', day: 'monday' },
|
|
59
|
+
'open-pull-requests-limit': 10,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ── bundler (Ruby) ─────────────────────────────────────────────────────
|
|
64
|
+
if (this.lockFiles.has('Gemfile.lock') || this.configFiles.has('Gemfile')) {
|
|
65
|
+
updates.push({
|
|
66
|
+
'package-ecosystem': 'bundler',
|
|
67
|
+
directory: '/',
|
|
68
|
+
schedule: { interval: 'weekly', day: 'monday' },
|
|
69
|
+
'open-pull-requests-limit': 10,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ── Go modules ─────────────────────────────────────────────────────────
|
|
74
|
+
if (this.lockFiles.has('go.sum') || this.configFiles.has('go.mod')) {
|
|
75
|
+
updates.push({
|
|
76
|
+
'package-ecosystem': 'gomod',
|
|
77
|
+
directory: '/',
|
|
78
|
+
schedule: { interval: 'weekly', day: 'monday' },
|
|
79
|
+
'open-pull-requests-limit': 10,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ── Maven ──────────────────────────────────────────────────────────────
|
|
84
|
+
if (this.configFiles.has('pom.xml')) {
|
|
85
|
+
updates.push({
|
|
86
|
+
'package-ecosystem': 'maven',
|
|
87
|
+
directory: '/',
|
|
88
|
+
schedule: { interval: 'weekly', day: 'monday' },
|
|
89
|
+
'open-pull-requests-limit': 10,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ── Gradle ─────────────────────────────────────────────────────────────
|
|
94
|
+
if (this.configFiles.has('build.gradle') || this.configFiles.has('build.gradle.kts')) {
|
|
95
|
+
updates.push({
|
|
96
|
+
'package-ecosystem': 'gradle',
|
|
97
|
+
directory: '/',
|
|
98
|
+
schedule: { interval: 'weekly', day: 'monday' },
|
|
99
|
+
'open-pull-requests-limit': 10,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ── Composer (PHP) ─────────────────────────────────────────────────────
|
|
104
|
+
if (this.lockFiles.has('composer.lock') || this.configFiles.has('composer.json')) {
|
|
105
|
+
updates.push({
|
|
106
|
+
'package-ecosystem': 'composer',
|
|
107
|
+
directory: '/',
|
|
108
|
+
schedule: { interval: 'weekly', day: 'monday' },
|
|
109
|
+
'open-pull-requests-limit': 10,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ── Docker ─────────────────────────────────────────────────────────────
|
|
114
|
+
if (this.configFiles.has('Dockerfile') ||
|
|
115
|
+
this.configFiles.has('docker-compose.yml') ||
|
|
116
|
+
this.configFiles.has('docker-compose.yaml')) {
|
|
117
|
+
updates.push({
|
|
118
|
+
'package-ecosystem': 'docker',
|
|
119
|
+
directory: '/',
|
|
120
|
+
schedule: { interval: 'weekly', day: 'monday' },
|
|
121
|
+
'open-pull-requests-limit': 5,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ── GitHub Actions ─────────────────────────────────────────────────────
|
|
126
|
+
// Always include — keeps action versions up to date
|
|
127
|
+
updates.push({
|
|
128
|
+
'package-ecosystem': 'github-actions',
|
|
129
|
+
directory: '/',
|
|
130
|
+
schedule: { interval: 'weekly', day: 'monday' },
|
|
131
|
+
'open-pull-requests-limit': 10,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const doc = { version: 2, updates };
|
|
135
|
+
|
|
136
|
+
const raw = yaml.dump(doc, {
|
|
137
|
+
indent: 2,
|
|
138
|
+
lineWidth: 120,
|
|
139
|
+
quotingType: "'",
|
|
140
|
+
forceQuotes: false,
|
|
141
|
+
noRefs: true,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
filename: 'dependabot.yml',
|
|
146
|
+
outputPath: '.github', // written to .github/, not .github/workflows/
|
|
147
|
+
content:
|
|
148
|
+
'# Generated by cistack — https://github.com/cistack\n' +
|
|
149
|
+
'# Dependabot configuration — auto-update dependencies weekly\n\n' +
|
|
150
|
+
raw,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
module.exports = DependabotGenerator;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const yaml = require('js-yaml');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generates a .github/workflows/release.yml tailored to the detected release tool.
|
|
7
|
+
*
|
|
8
|
+
* Supported tools: semantic-release, changesets, release-it, standard-version, custom
|
|
9
|
+
*/
|
|
10
|
+
class ReleaseGenerator {
|
|
11
|
+
constructor(releaseInfo, config, projectPath) {
|
|
12
|
+
this.release = releaseInfo; // output from ReleaseDetector
|
|
13
|
+
this.config = config; // full detected + merged stack config
|
|
14
|
+
this.projectPath = projectPath;
|
|
15
|
+
this.primaryLang = (config.languages && config.languages[0]) || { name: 'JavaScript', packageManager: 'npm', nodeVersion: '20' };
|
|
16
|
+
this.extraConfig = config._config || {}; // raw cistack.config.js
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
generate() {
|
|
20
|
+
if (!this.release) return null;
|
|
21
|
+
|
|
22
|
+
const tool = this.release.tool;
|
|
23
|
+
const lang = this.primaryLang;
|
|
24
|
+
const pm = lang.packageManager || 'npm';
|
|
25
|
+
const nodeVersion = lang.nodeVersion || '20';
|
|
26
|
+
|
|
27
|
+
const runCmd = (script) =>
|
|
28
|
+
pm === 'yarn' ? `yarn ${script}` : pm === 'pnpm' ? `pnpm ${script}` : `npm run ${script}`;
|
|
29
|
+
|
|
30
|
+
const installCmd =
|
|
31
|
+
pm === 'npm' ? 'npm ci' :
|
|
32
|
+
pm === 'yarn' ? 'yarn install --frozen-lockfile' :
|
|
33
|
+
pm === 'pnpm' ? 'pnpm install --frozen-lockfile' :
|
|
34
|
+
'bun install';
|
|
35
|
+
|
|
36
|
+
// ── common setup steps ────────────────────────────────────────────────
|
|
37
|
+
const setupSteps = [
|
|
38
|
+
{ name: 'Checkout', uses: 'actions/checkout@v4', with: { 'fetch-depth': 0 } },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
if (pm === 'pnpm') {
|
|
42
|
+
setupSteps.push({ name: 'Install pnpm', uses: 'pnpm/action-setup@v3', with: { version: 'latest' } });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setupSteps.push({
|
|
46
|
+
name: 'Set up Node.js',
|
|
47
|
+
uses: 'actions/setup-node@v4',
|
|
48
|
+
with: {
|
|
49
|
+
'node-version': nodeVersion,
|
|
50
|
+
cache: pm === 'yarn' ? 'yarn' : pm === 'pnpm' ? 'pnpm' : 'npm',
|
|
51
|
+
...(this.release.publishToNpm ? { 'registry-url': 'https://registry.npmjs.org' } : {}),
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
setupSteps.push({ name: 'Install dependencies', run: installCmd });
|
|
56
|
+
|
|
57
|
+
// ── tool-specific steps ────────────────────────────────────────────────
|
|
58
|
+
let releaseSteps = [];
|
|
59
|
+
let envVars = {
|
|
60
|
+
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}',
|
|
61
|
+
};
|
|
62
|
+
let requiredSecrets = ['GITHUB_TOKEN'];
|
|
63
|
+
|
|
64
|
+
switch (tool) {
|
|
65
|
+
case 'semantic-release': {
|
|
66
|
+
if (this.release.requiresNpmToken) {
|
|
67
|
+
envVars['NPM_TOKEN'] = '${{ secrets.NPM_TOKEN }}';
|
|
68
|
+
requiredSecrets.push('NPM_TOKEN');
|
|
69
|
+
}
|
|
70
|
+
releaseSteps.push({
|
|
71
|
+
name: '🚀 Semantic Release',
|
|
72
|
+
run: 'npx semantic-release',
|
|
73
|
+
env: envVars,
|
|
74
|
+
});
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
case 'changesets': {
|
|
79
|
+
envVars['NPM_TOKEN'] = '${{ secrets.NPM_TOKEN }}';
|
|
80
|
+
requiredSecrets.push('NPM_TOKEN');
|
|
81
|
+
releaseSteps.push(
|
|
82
|
+
{
|
|
83
|
+
name: 'Create Release PR or Publish',
|
|
84
|
+
uses: 'changesets/action@v1',
|
|
85
|
+
with: {
|
|
86
|
+
publish: runCmd('release'),
|
|
87
|
+
title: 'chore: version packages',
|
|
88
|
+
commit: 'chore: version packages',
|
|
89
|
+
},
|
|
90
|
+
env: envVars,
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
case 'release-it': {
|
|
97
|
+
if (this.release.publishToNpm) {
|
|
98
|
+
envVars['NPM_TOKEN'] = '${{ secrets.NPM_TOKEN }}';
|
|
99
|
+
requiredSecrets.push('NPM_TOKEN');
|
|
100
|
+
}
|
|
101
|
+
releaseSteps.push({
|
|
102
|
+
name: '🚀 Release It',
|
|
103
|
+
run: 'npx release-it --ci',
|
|
104
|
+
env: envVars,
|
|
105
|
+
});
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
case 'standard-version': {
|
|
110
|
+
releaseSteps.push(
|
|
111
|
+
{
|
|
112
|
+
name: 'Configure Git',
|
|
113
|
+
run: [
|
|
114
|
+
'git config user.email "github-actions[bot]@users.noreply.github.com"',
|
|
115
|
+
'git config user.name "github-actions[bot]"',
|
|
116
|
+
].join('\n'),
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'Bump version & changelog',
|
|
120
|
+
run: 'npx standard-version',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'Push release commit & tag',
|
|
124
|
+
run: 'git push --follow-tags origin ${{ github.ref_name }}',
|
|
125
|
+
env: { GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' },
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: 'Create GitHub Release',
|
|
129
|
+
uses: 'softprops/action-gh-release@v2',
|
|
130
|
+
with: {
|
|
131
|
+
generate_release_notes: true,
|
|
132
|
+
},
|
|
133
|
+
env: { GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' },
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
default: {
|
|
140
|
+
releaseSteps.push({
|
|
141
|
+
name: '🚀 Release',
|
|
142
|
+
run: this.release.command || 'npm run release',
|
|
143
|
+
env: envVars,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const secretsDoc = requiredSecrets.filter((s) => s !== 'GITHUB_TOKEN').length > 0
|
|
149
|
+
? `# Required secrets: ${requiredSecrets.filter((s) => s !== 'GITHUB_TOKEN').join(', ')}\n# Add these at: Settings → Secrets and Variables → Actions\n\n`
|
|
150
|
+
: '';
|
|
151
|
+
|
|
152
|
+
const branches = (this.extraConfig.branches) || ['main', 'master'];
|
|
153
|
+
|
|
154
|
+
const workflow = {
|
|
155
|
+
name: 'Release',
|
|
156
|
+
on: {
|
|
157
|
+
push: { branches },
|
|
158
|
+
workflow_dispatch: {},
|
|
159
|
+
},
|
|
160
|
+
permissions: {
|
|
161
|
+
contents: 'write',
|
|
162
|
+
'pull-requests': 'write',
|
|
163
|
+
...(this.release.publishToNpm ? { packages: 'write' } : {}),
|
|
164
|
+
},
|
|
165
|
+
jobs: {
|
|
166
|
+
release: {
|
|
167
|
+
name: `🏷️ Release (${tool})`,
|
|
168
|
+
'runs-on': 'ubuntu-latest',
|
|
169
|
+
// Only run on the default branch, not every push in a monorepo etc.
|
|
170
|
+
if: "github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'",
|
|
171
|
+
steps: [...setupSteps, ...releaseSteps],
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const raw = yaml.dump(workflow, {
|
|
177
|
+
indent: 2,
|
|
178
|
+
lineWidth: 120,
|
|
179
|
+
quotingType: "'",
|
|
180
|
+
forceQuotes: false,
|
|
181
|
+
noRefs: true,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
filename: 'release.yml',
|
|
186
|
+
content:
|
|
187
|
+
`# Generated by cistack — https://github.com/cistack\n` +
|
|
188
|
+
`# Release Pipeline → ${tool}\n` +
|
|
189
|
+
secretsDoc +
|
|
190
|
+
raw,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
module.exports = ReleaseGenerator;
|