@expressots/cli 3.0.0-beta.4 → 4.0.0-preview.2
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 +41 -95
- package/bin/cicd/cli.d.ts +6 -0
- package/bin/cicd/cli.js +126 -0
- package/bin/cicd/form.d.ts +29 -0
- package/bin/cicd/form.js +345 -0
- package/bin/cicd/generators/azure-devops.d.ts +2 -0
- package/bin/cicd/generators/azure-devops.js +370 -0
- package/bin/cicd/generators/bitbucket.d.ts +2 -0
- package/bin/cicd/generators/bitbucket.js +217 -0
- package/bin/cicd/generators/circleci.d.ts +2 -0
- package/bin/cicd/generators/circleci.js +274 -0
- package/bin/cicd/generators/github-actions.d.ts +14 -0
- package/bin/cicd/generators/github-actions.js +426 -0
- package/bin/cicd/generators/gitlab-ci.d.ts +2 -0
- package/bin/cicd/generators/gitlab-ci.js +237 -0
- package/bin/cicd/generators/index.d.ts +6 -0
- package/bin/cicd/generators/index.js +15 -0
- package/bin/cicd/generators/jenkins.d.ts +2 -0
- package/bin/cicd/generators/jenkins.js +248 -0
- package/bin/cicd/generators/template-loader.d.ts +17 -0
- package/bin/cicd/generators/template-loader.js +128 -0
- package/bin/cicd/index.d.ts +1 -0
- package/bin/cicd/index.js +5 -0
- package/bin/cli.d.ts +1 -1
- package/bin/cli.js +18 -3
- package/bin/commands/project.commands.d.ts +19 -6
- package/bin/commands/project.commands.js +390 -61
- package/bin/config/index.d.ts +5 -0
- package/bin/config/index.js +10 -0
- package/bin/config/manager.d.ts +98 -0
- package/bin/config/manager.js +222 -0
- package/bin/containerize/analyzers/bootstrap-analyzer.d.ts +46 -0
- package/bin/containerize/analyzers/bootstrap-analyzer.js +187 -0
- package/bin/containerize/analyzers/project-analyzer.d.ts +20 -0
- package/bin/containerize/analyzers/project-analyzer.js +150 -0
- package/bin/containerize/cli.d.ts +4 -0
- package/bin/containerize/cli.js +113 -0
- package/bin/containerize/form.d.ts +15 -0
- package/bin/containerize/form.js +154 -0
- package/bin/containerize/generators/ci-generator.d.ts +31 -0
- package/bin/containerize/generators/ci-generator.js +936 -0
- package/bin/containerize/generators/docker-compose-generator.d.ts +8 -0
- package/bin/containerize/generators/docker-compose-generator.js +186 -0
- package/bin/containerize/generators/dockerfile-generator.d.ts +8 -0
- package/bin/containerize/generators/dockerfile-generator.js +635 -0
- package/bin/containerize/generators/kubernetes-generator.d.ts +8 -0
- package/bin/containerize/generators/kubernetes-generator.js +133 -0
- package/bin/containerize/generators/template-loader.d.ts +36 -0
- package/bin/containerize/generators/template-loader.js +129 -0
- package/bin/containerize/index.d.ts +4 -0
- package/bin/containerize/index.js +13 -0
- package/bin/containerize/presets/preset-registry.d.ts +20 -0
- package/bin/containerize/presets/preset-registry.js +102 -0
- package/bin/costs/cli.d.ts +5 -0
- package/bin/costs/cli.js +183 -0
- package/bin/costs/form.d.ts +44 -0
- package/bin/costs/form.js +412 -0
- package/bin/costs/index.d.ts +4 -0
- package/bin/costs/index.js +25 -0
- package/bin/costs/pricing-manager.d.ts +84 -0
- package/bin/costs/pricing-manager.js +342 -0
- package/bin/costs/providers/index.d.ts +32 -0
- package/bin/costs/providers/index.js +153 -0
- package/bin/costs/sources/api-source.d.ts +10 -0
- package/bin/costs/sources/api-source.js +32 -0
- package/bin/costs/sources/index.d.ts +6 -0
- package/bin/costs/sources/index.js +15 -0
- package/bin/costs/sources/local-json-source.d.ts +23 -0
- package/bin/costs/sources/local-json-source.js +59 -0
- package/bin/costs/sources/remote-json-source.d.ts +11 -0
- package/bin/costs/sources/remote-json-source.js +53 -0
- package/bin/costs/types.d.ts +53 -0
- package/bin/costs/types.js +5 -0
- package/bin/dev/cli.d.ts +4 -0
- package/bin/dev/cli.js +134 -0
- package/bin/dev/form.d.ts +36 -0
- package/bin/dev/form.js +254 -0
- package/bin/dev/index.d.ts +1 -0
- package/bin/dev/index.js +5 -0
- package/bin/generate/cli.js +29 -2
- package/bin/generate/form.d.ts +5 -1
- package/bin/generate/form.js +3 -3
- package/bin/generate/templates/nonopinionated/config.tpl +12 -0
- package/bin/generate/templates/nonopinionated/event.tpl +10 -0
- package/bin/generate/templates/nonopinionated/guard.tpl +18 -0
- package/bin/generate/templates/nonopinionated/handler.tpl +12 -0
- package/bin/generate/templates/nonopinionated/interceptor.tpl +27 -0
- package/bin/generate/templates/opinionated/config.tpl +47 -0
- package/bin/generate/templates/opinionated/entity.tpl +1 -8
- package/bin/generate/templates/opinionated/event.tpl +15 -0
- package/bin/generate/templates/opinionated/guard.tpl +41 -0
- package/bin/generate/templates/opinionated/handler.tpl +23 -0
- package/bin/generate/templates/opinionated/interceptor.tpl +50 -0
- package/bin/generate/utils/command-utils.d.ts +7 -3
- package/bin/generate/utils/command-utils.js +95 -31
- package/bin/generate/utils/nonopininated-cmd.d.ts +10 -1
- package/bin/generate/utils/nonopininated-cmd.js +100 -1
- package/bin/generate/utils/opinionated-cmd.d.ts +10 -1
- package/bin/generate/utils/opinionated-cmd.js +112 -7
- package/bin/generate/utils/string-utils.d.ts +6 -0
- package/bin/generate/utils/string-utils.js +13 -1
- package/bin/help/form.js +11 -3
- package/bin/migrate/analyzers/platform-detector.d.ts +14 -0
- package/bin/migrate/analyzers/platform-detector.js +116 -0
- package/bin/migrate/cli.d.ts +6 -0
- package/bin/migrate/cli.js +96 -0
- package/bin/migrate/form.d.ts +25 -0
- package/bin/migrate/form.js +347 -0
- package/bin/migrate/generators/compose-to-k8s.d.ts +2 -0
- package/bin/migrate/generators/compose-to-k8s.js +324 -0
- package/bin/migrate/generators/compose-to-railway.d.ts +2 -0
- package/bin/migrate/generators/compose-to-railway.js +138 -0
- package/bin/migrate/generators/compose-to-render.d.ts +2 -0
- package/bin/migrate/generators/compose-to-render.js +148 -0
- package/bin/migrate/generators/generic-migration.d.ts +9 -0
- package/bin/migrate/generators/generic-migration.js +221 -0
- package/bin/migrate/generators/heroku-to-fly.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-fly.js +291 -0
- package/bin/migrate/generators/heroku-to-railway.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-railway.js +283 -0
- package/bin/migrate/generators/heroku-to-render.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-render.js +148 -0
- package/bin/migrate/generators/index.d.ts +7 -0
- package/bin/migrate/generators/index.js +17 -0
- package/bin/migrate/generators/template-loader.d.ts +21 -0
- package/bin/migrate/generators/template-loader.js +59 -0
- package/bin/migrate/index.d.ts +1 -0
- package/bin/migrate/index.js +5 -0
- package/bin/new/cli.js +21 -6
- package/bin/new/form.d.ts +25 -4
- package/bin/new/form.js +285 -70
- package/bin/profile/analyzers/dockerfile-analyzer.d.ts +27 -0
- package/bin/profile/analyzers/dockerfile-analyzer.js +122 -0
- package/bin/profile/analyzers/image-analyzer.d.ts +19 -0
- package/bin/profile/analyzers/image-analyzer.js +85 -0
- package/bin/profile/cli.d.ts +4 -0
- package/bin/profile/cli.js +92 -0
- package/bin/profile/form.d.ts +56 -0
- package/bin/profile/form.js +400 -0
- package/bin/profile/index.d.ts +1 -0
- package/bin/profile/index.js +5 -0
- package/bin/profile/optimizers/index.d.ts +19 -0
- package/bin/profile/optimizers/index.js +137 -0
- package/bin/providers/add/form.d.ts +1 -1
- package/bin/providers/add/form.js +27 -6
- package/bin/providers/create/form.js +2 -1
- package/bin/scripts/form.js +27 -5
- package/bin/studio/cli.d.ts +15 -0
- package/bin/studio/cli.js +166 -0
- package/bin/studio/index.d.ts +5 -0
- package/bin/studio/index.js +9 -0
- package/bin/templates/cache.d.ts +54 -0
- package/bin/templates/cache.js +180 -0
- package/bin/templates/cli.d.ts +8 -0
- package/bin/templates/cli.js +292 -0
- package/bin/templates/fetcher.d.ts +49 -0
- package/bin/templates/fetcher.js +208 -0
- package/bin/templates/index.d.ts +11 -0
- package/bin/templates/index.js +37 -0
- package/bin/templates/manager.d.ts +116 -0
- package/bin/templates/manager.js +323 -0
- package/bin/templates/renderer.d.ts +49 -0
- package/bin/templates/renderer.js +204 -0
- package/bin/templates/types.d.ts +51 -0
- package/bin/templates/types.js +5 -0
- package/bin/utils/add-module-to-container.d.ts +2 -2
- package/bin/utils/add-module-to-container.js +15 -5
- package/bin/utils/cli-ui.d.ts +30 -3
- package/bin/utils/cli-ui.js +95 -13
- package/bin/utils/index.d.ts +4 -0
- package/bin/utils/index.js +4 -0
- package/bin/utils/input-validation.d.ts +50 -0
- package/bin/utils/input-validation.js +143 -0
- package/bin/utils/package-manager-commands.d.ts +24 -0
- package/bin/utils/package-manager-commands.js +50 -0
- package/bin/utils/safe-spawn.d.ts +35 -0
- package/bin/utils/safe-spawn.js +51 -0
- package/bin/utils/update-tsconfig-paths.d.ts +35 -0
- package/bin/utils/update-tsconfig-paths.js +286 -0
- package/package.json +154 -154
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateGitLabCI = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const template_loader_1 = require("./template-loader");
|
|
11
|
+
async function generateGitLabCI(outputDir, options) {
|
|
12
|
+
// Try remote template, fall back to embedded
|
|
13
|
+
const result = await (0, template_loader_1.loadCICDTemplate)("gitlab", options.strategy, options, generateGitLabContentEmbedded);
|
|
14
|
+
(0, template_loader_1.logTemplateSource)("GitLab CI", result.source);
|
|
15
|
+
const filePath = path_1.default.join(outputDir, ".gitlab-ci.yml");
|
|
16
|
+
fs_1.default.writeFileSync(filePath, result.content, "utf-8");
|
|
17
|
+
console.log(chalk_1.default.green(` ✓ Created .gitlab-ci.yml`));
|
|
18
|
+
}
|
|
19
|
+
exports.generateGitLabCI = generateGitLabCI;
|
|
20
|
+
/**
|
|
21
|
+
* Embedded template generator (fallback when remote templates unavailable)
|
|
22
|
+
*/
|
|
23
|
+
function generateGitLabContentEmbedded(options) {
|
|
24
|
+
const { nodeVersion, packageManager, strategy, includeSecurity, includeE2E, includeCoverage, deployTarget, branch, } = options;
|
|
25
|
+
const installCmd = packageManager === "pnpm"
|
|
26
|
+
? "pnpm install"
|
|
27
|
+
: packageManager === "yarn"
|
|
28
|
+
? "yarn install"
|
|
29
|
+
: "npm ci";
|
|
30
|
+
const testCmd = packageManager === "pnpm"
|
|
31
|
+
? "pnpm test"
|
|
32
|
+
: packageManager === "yarn"
|
|
33
|
+
? "yarn test"
|
|
34
|
+
: "npm test";
|
|
35
|
+
const buildCmd = packageManager === "pnpm"
|
|
36
|
+
? "pnpm build"
|
|
37
|
+
: packageManager === "yarn"
|
|
38
|
+
? "yarn build"
|
|
39
|
+
: "npm run build";
|
|
40
|
+
const lintCmd = packageManager === "pnpm"
|
|
41
|
+
? "pnpm lint"
|
|
42
|
+
: packageManager === "yarn"
|
|
43
|
+
? "yarn lint"
|
|
44
|
+
: "npm run lint";
|
|
45
|
+
let content = `# GitLab CI/CD Pipeline
|
|
46
|
+
# Generated by ExpressoTS CLI
|
|
47
|
+
# Strategy: ${strategy}
|
|
48
|
+
|
|
49
|
+
image: node:${nodeVersion}-alpine
|
|
50
|
+
|
|
51
|
+
stages:
|
|
52
|
+
- lint
|
|
53
|
+
- test${includeSecurity && (strategy === "comprehensive" || strategy === "security-focused") ? "\n - security" : ""}${includeE2E ? "\n - e2e" : ""}
|
|
54
|
+
- build
|
|
55
|
+
- docker${deployTarget !== "none" ? "\n - deploy" : ""}
|
|
56
|
+
|
|
57
|
+
variables:
|
|
58
|
+
npm_config_cache: "$CI_PROJECT_DIR/.npm"
|
|
59
|
+
DOCKER_IMAGE: $CI_REGISTRY_IMAGE
|
|
60
|
+
|
|
61
|
+
cache:
|
|
62
|
+
key: \${CI_COMMIT_REF_SLUG}
|
|
63
|
+
paths:
|
|
64
|
+
- .npm/
|
|
65
|
+
- node_modules/
|
|
66
|
+
|
|
67
|
+
# Lint Stage
|
|
68
|
+
lint:
|
|
69
|
+
stage: lint
|
|
70
|
+
script:
|
|
71
|
+
- ${installCmd}
|
|
72
|
+
- ${lintCmd}
|
|
73
|
+
only:
|
|
74
|
+
- ${branch}
|
|
75
|
+
- merge_requests
|
|
76
|
+
|
|
77
|
+
# Test Stage
|
|
78
|
+
test:
|
|
79
|
+
stage: test
|
|
80
|
+
script:
|
|
81
|
+
- ${installCmd}
|
|
82
|
+
- ${testCmd}${includeCoverage ? ` --coverage` : ""}
|
|
83
|
+
${includeCoverage
|
|
84
|
+
? `coverage: '/All files[^|]*\\|[^|]*\\s+([\\d\\.]+)/'
|
|
85
|
+
artifacts:
|
|
86
|
+
reports:
|
|
87
|
+
coverage_report:
|
|
88
|
+
coverage_format: cobertura
|
|
89
|
+
path: coverage/cobertura-coverage.xml`
|
|
90
|
+
: ""}
|
|
91
|
+
only:
|
|
92
|
+
- ${branch}
|
|
93
|
+
- merge_requests
|
|
94
|
+
|
|
95
|
+
`;
|
|
96
|
+
// Security scanning
|
|
97
|
+
if (includeSecurity &&
|
|
98
|
+
(strategy === "comprehensive" || strategy === "security-focused")) {
|
|
99
|
+
content += `# Security Stage
|
|
100
|
+
security:
|
|
101
|
+
stage: security
|
|
102
|
+
image:
|
|
103
|
+
name: aquasec/trivy:latest
|
|
104
|
+
entrypoint: [""]
|
|
105
|
+
script:
|
|
106
|
+
- trivy fs --exit-code 0 --severity HIGH,CRITICAL --format json -o trivy-report.json .
|
|
107
|
+
artifacts:
|
|
108
|
+
reports:
|
|
109
|
+
container_scanning: trivy-report.json
|
|
110
|
+
expire_in: 1 week
|
|
111
|
+
only:
|
|
112
|
+
- ${branch}
|
|
113
|
+
|
|
114
|
+
`;
|
|
115
|
+
if (strategy === "security-focused") {
|
|
116
|
+
content += `dependency_scanning:
|
|
117
|
+
stage: security
|
|
118
|
+
image: node:${nodeVersion}
|
|
119
|
+
script:
|
|
120
|
+
- npm audit --audit-level=high
|
|
121
|
+
allow_failure: true
|
|
122
|
+
only:
|
|
123
|
+
- ${branch}
|
|
124
|
+
|
|
125
|
+
`;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// E2E tests
|
|
129
|
+
if (includeE2E) {
|
|
130
|
+
content += `# E2E Tests
|
|
131
|
+
e2e:
|
|
132
|
+
stage: e2e
|
|
133
|
+
services:
|
|
134
|
+
- postgres:15-alpine
|
|
135
|
+
variables:
|
|
136
|
+
DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/test"
|
|
137
|
+
script:
|
|
138
|
+
- ${installCmd}
|
|
139
|
+
- ${buildCmd}
|
|
140
|
+
- npm start &
|
|
141
|
+
- sleep 10
|
|
142
|
+
- npm run test:e2e
|
|
143
|
+
only:
|
|
144
|
+
- ${branch}
|
|
145
|
+
|
|
146
|
+
`;
|
|
147
|
+
}
|
|
148
|
+
// Build stage
|
|
149
|
+
content += `# Build Stage
|
|
150
|
+
build:
|
|
151
|
+
stage: build
|
|
152
|
+
script:
|
|
153
|
+
- ${installCmd}
|
|
154
|
+
- ${buildCmd}
|
|
155
|
+
artifacts:
|
|
156
|
+
paths:
|
|
157
|
+
- dist/
|
|
158
|
+
expire_in: 1 week
|
|
159
|
+
only:
|
|
160
|
+
- ${branch}
|
|
161
|
+
|
|
162
|
+
# Docker Build Stage
|
|
163
|
+
docker:
|
|
164
|
+
stage: docker
|
|
165
|
+
image: docker:24
|
|
166
|
+
services:
|
|
167
|
+
- docker:24-dind
|
|
168
|
+
variables:
|
|
169
|
+
DOCKER_TLS_CERTDIR: "/certs"
|
|
170
|
+
before_script:
|
|
171
|
+
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
|
172
|
+
script:
|
|
173
|
+
- docker build -t $DOCKER_IMAGE:$CI_COMMIT_SHA -t $DOCKER_IMAGE:latest .
|
|
174
|
+
- docker push $DOCKER_IMAGE:$CI_COMMIT_SHA
|
|
175
|
+
- docker push $DOCKER_IMAGE:latest
|
|
176
|
+
only:
|
|
177
|
+
- ${branch}
|
|
178
|
+
|
|
179
|
+
`;
|
|
180
|
+
// Deploy stage
|
|
181
|
+
if (deployTarget !== "none") {
|
|
182
|
+
content += generateGitLabDeployJob(deployTarget, branch);
|
|
183
|
+
}
|
|
184
|
+
return content;
|
|
185
|
+
}
|
|
186
|
+
function generateGitLabDeployJob(target, branch) {
|
|
187
|
+
switch (target) {
|
|
188
|
+
case "kubernetes":
|
|
189
|
+
return `# Deploy to Kubernetes
|
|
190
|
+
deploy:
|
|
191
|
+
stage: deploy
|
|
192
|
+
image: bitnami/kubectl:latest
|
|
193
|
+
script:
|
|
194
|
+
- kubectl config set-cluster k8s --server="$KUBE_URL"
|
|
195
|
+
- kubectl config set-credentials gitlab --token="$KUBE_TOKEN"
|
|
196
|
+
- kubectl config set-context default --cluster=k8s --user=gitlab
|
|
197
|
+
- kubectl config use-context default
|
|
198
|
+
- kubectl set image deployment/expressots-app app=$DOCKER_IMAGE:$CI_COMMIT_SHA
|
|
199
|
+
- kubectl rollout status deployment/expressots-app
|
|
200
|
+
environment:
|
|
201
|
+
name: production
|
|
202
|
+
url: https://your-app.com
|
|
203
|
+
only:
|
|
204
|
+
- ${branch}
|
|
205
|
+
when: manual
|
|
206
|
+
|
|
207
|
+
`;
|
|
208
|
+
case "railway":
|
|
209
|
+
return `# Deploy to Railway
|
|
210
|
+
deploy:
|
|
211
|
+
stage: deploy
|
|
212
|
+
image: node:20-alpine
|
|
213
|
+
script:
|
|
214
|
+
- npm install -g @railway/cli
|
|
215
|
+
- railway up
|
|
216
|
+
environment:
|
|
217
|
+
name: production
|
|
218
|
+
only:
|
|
219
|
+
- ${branch}
|
|
220
|
+
when: manual
|
|
221
|
+
|
|
222
|
+
`;
|
|
223
|
+
default:
|
|
224
|
+
return `# Deploy Stage
|
|
225
|
+
deploy:
|
|
226
|
+
stage: deploy
|
|
227
|
+
script:
|
|
228
|
+
- echo "Deploy to ${target}"
|
|
229
|
+
environment:
|
|
230
|
+
name: production
|
|
231
|
+
only:
|
|
232
|
+
- ${branch}
|
|
233
|
+
when: manual
|
|
234
|
+
|
|
235
|
+
`;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { generateGitHubActions } from "./github-actions";
|
|
2
|
+
export { generateGitLabCI } from "./gitlab-ci";
|
|
3
|
+
export { generateCircleCI } from "./circleci";
|
|
4
|
+
export { generateJenkinsfile } from "./jenkins";
|
|
5
|
+
export { generateBitbucketPipelines } from "./bitbucket";
|
|
6
|
+
export { generateAzureDevOps } from "./azure-devops";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateAzureDevOps = exports.generateBitbucketPipelines = exports.generateJenkinsfile = exports.generateCircleCI = exports.generateGitLabCI = exports.generateGitHubActions = void 0;
|
|
4
|
+
var github_actions_1 = require("./github-actions");
|
|
5
|
+
Object.defineProperty(exports, "generateGitHubActions", { enumerable: true, get: function () { return github_actions_1.generateGitHubActions; } });
|
|
6
|
+
var gitlab_ci_1 = require("./gitlab-ci");
|
|
7
|
+
Object.defineProperty(exports, "generateGitLabCI", { enumerable: true, get: function () { return gitlab_ci_1.generateGitLabCI; } });
|
|
8
|
+
var circleci_1 = require("./circleci");
|
|
9
|
+
Object.defineProperty(exports, "generateCircleCI", { enumerable: true, get: function () { return circleci_1.generateCircleCI; } });
|
|
10
|
+
var jenkins_1 = require("./jenkins");
|
|
11
|
+
Object.defineProperty(exports, "generateJenkinsfile", { enumerable: true, get: function () { return jenkins_1.generateJenkinsfile; } });
|
|
12
|
+
var bitbucket_1 = require("./bitbucket");
|
|
13
|
+
Object.defineProperty(exports, "generateBitbucketPipelines", { enumerable: true, get: function () { return bitbucket_1.generateBitbucketPipelines; } });
|
|
14
|
+
var azure_devops_1 = require("./azure-devops");
|
|
15
|
+
Object.defineProperty(exports, "generateAzureDevOps", { enumerable: true, get: function () { return azure_devops_1.generateAzureDevOps; } });
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateJenkinsfile = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const template_loader_1 = require("./template-loader");
|
|
11
|
+
async function generateJenkinsfile(outputDir, options) {
|
|
12
|
+
// Try remote template, fall back to embedded
|
|
13
|
+
const result = await (0, template_loader_1.loadCICDTemplate)("jenkins", options.strategy, options, generateJenkinsContentEmbedded);
|
|
14
|
+
(0, template_loader_1.logTemplateSource)("Jenkins", result.source);
|
|
15
|
+
const filePath = path_1.default.join(outputDir, "Jenkinsfile");
|
|
16
|
+
fs_1.default.writeFileSync(filePath, result.content, "utf-8");
|
|
17
|
+
console.log(chalk_1.default.green(` ✓ Created Jenkinsfile`));
|
|
18
|
+
}
|
|
19
|
+
exports.generateJenkinsfile = generateJenkinsfile;
|
|
20
|
+
/**
|
|
21
|
+
* Embedded template generator (fallback when remote templates unavailable)
|
|
22
|
+
*/
|
|
23
|
+
function generateJenkinsContentEmbedded(options) {
|
|
24
|
+
const { projectName, nodeVersion, packageManager, strategy, includeSecurity, includeE2E, includeCoverage, deployTarget, branch, } = options;
|
|
25
|
+
const installCmd = packageManager === "pnpm"
|
|
26
|
+
? "pnpm install"
|
|
27
|
+
: packageManager === "yarn"
|
|
28
|
+
? "yarn install"
|
|
29
|
+
: "npm ci";
|
|
30
|
+
const testCmd = packageManager === "pnpm"
|
|
31
|
+
? "pnpm test"
|
|
32
|
+
: packageManager === "yarn"
|
|
33
|
+
? "yarn test"
|
|
34
|
+
: "npm test";
|
|
35
|
+
const buildCmd = packageManager === "pnpm"
|
|
36
|
+
? "pnpm build"
|
|
37
|
+
: packageManager === "yarn"
|
|
38
|
+
? "yarn build"
|
|
39
|
+
: "npm run build";
|
|
40
|
+
const lintCmd = packageManager === "pnpm"
|
|
41
|
+
? "pnpm lint"
|
|
42
|
+
: packageManager === "yarn"
|
|
43
|
+
? "yarn lint"
|
|
44
|
+
: "npm run lint";
|
|
45
|
+
let content = `// Jenkinsfile
|
|
46
|
+
// Generated by ExpressoTS CLI
|
|
47
|
+
// Strategy: ${strategy}
|
|
48
|
+
|
|
49
|
+
pipeline {
|
|
50
|
+
agent any
|
|
51
|
+
|
|
52
|
+
environment {
|
|
53
|
+
NODE_VERSION = '${nodeVersion}'
|
|
54
|
+
DOCKER_IMAGE = '${projectName}'
|
|
55
|
+
DOCKER_TAG = "\${BUILD_NUMBER}"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
tools {
|
|
59
|
+
nodejs "node-\${NODE_VERSION}"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
options {
|
|
63
|
+
buildDiscarder(logRotator(numToKeepStr: '10'))
|
|
64
|
+
timeout(time: 30, unit: 'MINUTES')
|
|
65
|
+
disableConcurrentBuilds()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
stages {
|
|
69
|
+
stage('Checkout') {
|
|
70
|
+
steps {
|
|
71
|
+
checkout scm
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
stage('Install Dependencies') {
|
|
76
|
+
steps {
|
|
77
|
+
sh '${installCmd}'
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
stage('Lint') {
|
|
82
|
+
steps {
|
|
83
|
+
sh '${lintCmd}'
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
stage('Test') {
|
|
88
|
+
steps {
|
|
89
|
+
sh '${testCmd}${includeCoverage ? " --coverage" : ""}'
|
|
90
|
+
}
|
|
91
|
+
`;
|
|
92
|
+
if (includeCoverage) {
|
|
93
|
+
content += ` post {
|
|
94
|
+
always {
|
|
95
|
+
publishHTML(target: [
|
|
96
|
+
allowMissing: false,
|
|
97
|
+
alwaysLinkToLastBuild: true,
|
|
98
|
+
keepAll: true,
|
|
99
|
+
reportDir: 'coverage/lcov-report',
|
|
100
|
+
reportFiles: 'index.html',
|
|
101
|
+
reportName: 'Coverage Report'
|
|
102
|
+
])
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
`;
|
|
106
|
+
}
|
|
107
|
+
content += ` }
|
|
108
|
+
`;
|
|
109
|
+
// Security stage
|
|
110
|
+
if (includeSecurity &&
|
|
111
|
+
(strategy === "comprehensive" || strategy === "security-focused")) {
|
|
112
|
+
content += `
|
|
113
|
+
stage('Security Scan') {
|
|
114
|
+
steps {
|
|
115
|
+
script {
|
|
116
|
+
// Run npm audit
|
|
117
|
+
sh 'npm audit --audit-level=high || true'
|
|
118
|
+
|
|
119
|
+
// Run Trivy if available
|
|
120
|
+
sh '''
|
|
121
|
+
if command -v trivy &> /dev/null; then
|
|
122
|
+
trivy fs --exit-code 0 --severity HIGH,CRITICAL .
|
|
123
|
+
else
|
|
124
|
+
echo "Trivy not installed, skipping filesystem scan"
|
|
125
|
+
fi
|
|
126
|
+
'''
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
`;
|
|
131
|
+
}
|
|
132
|
+
// E2E tests
|
|
133
|
+
if (includeE2E) {
|
|
134
|
+
content += `
|
|
135
|
+
stage('E2E Tests') {
|
|
136
|
+
steps {
|
|
137
|
+
script {
|
|
138
|
+
sh '${buildCmd}'
|
|
139
|
+
sh '''
|
|
140
|
+
npm start &
|
|
141
|
+
sleep 10
|
|
142
|
+
npm run test:e2e
|
|
143
|
+
'''
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
148
|
+
}
|
|
149
|
+
// Build stage
|
|
150
|
+
content += `
|
|
151
|
+
stage('Build') {
|
|
152
|
+
steps {
|
|
153
|
+
sh '${buildCmd}'
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
stage('Docker Build') {
|
|
158
|
+
when {
|
|
159
|
+
branch '${branch}'
|
|
160
|
+
}
|
|
161
|
+
steps {
|
|
162
|
+
script {
|
|
163
|
+
docker.build("\${DOCKER_IMAGE}:\${DOCKER_TAG}")
|
|
164
|
+
docker.build("\${DOCKER_IMAGE}:latest")
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
stage('Docker Push') {
|
|
170
|
+
when {
|
|
171
|
+
branch '${branch}'
|
|
172
|
+
}
|
|
173
|
+
steps {
|
|
174
|
+
script {
|
|
175
|
+
docker.withRegistry('https://registry.hub.docker.com', 'docker-hub-credentials') {
|
|
176
|
+
docker.image("\${DOCKER_IMAGE}:\${DOCKER_TAG}").push()
|
|
177
|
+
docker.image("\${DOCKER_IMAGE}:latest").push()
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
`;
|
|
183
|
+
// Deploy stage
|
|
184
|
+
if (deployTarget !== "none") {
|
|
185
|
+
content += generateJenkinsDeployStage(deployTarget, branch);
|
|
186
|
+
}
|
|
187
|
+
content += ` }
|
|
188
|
+
|
|
189
|
+
post {
|
|
190
|
+
always {
|
|
191
|
+
cleanWs()
|
|
192
|
+
}
|
|
193
|
+
success {
|
|
194
|
+
echo 'Pipeline completed successfully!'
|
|
195
|
+
}
|
|
196
|
+
failure {
|
|
197
|
+
echo 'Pipeline failed!'
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
`;
|
|
202
|
+
return content;
|
|
203
|
+
}
|
|
204
|
+
function generateJenkinsDeployStage(target, branch) {
|
|
205
|
+
switch (target) {
|
|
206
|
+
case "kubernetes":
|
|
207
|
+
return `
|
|
208
|
+
stage('Deploy to Kubernetes') {
|
|
209
|
+
when {
|
|
210
|
+
branch '${branch}'
|
|
211
|
+
}
|
|
212
|
+
steps {
|
|
213
|
+
withKubeConfig([credentialsId: 'kubeconfig']) {
|
|
214
|
+
sh '''
|
|
215
|
+
kubectl set image deployment/expressots-app \\
|
|
216
|
+
app=\${DOCKER_IMAGE}:\${DOCKER_TAG}
|
|
217
|
+
kubectl rollout status deployment/expressots-app
|
|
218
|
+
'''
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
`;
|
|
223
|
+
case "railway":
|
|
224
|
+
return `
|
|
225
|
+
stage('Deploy to Railway') {
|
|
226
|
+
when {
|
|
227
|
+
branch '${branch}'
|
|
228
|
+
}
|
|
229
|
+
steps {
|
|
230
|
+
withCredentials([string(credentialsId: 'railway-token', variable: 'RAILWAY_TOKEN')]) {
|
|
231
|
+
sh 'npx @railway/cli up'
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
`;
|
|
236
|
+
default:
|
|
237
|
+
return `
|
|
238
|
+
stage('Deploy') {
|
|
239
|
+
when {
|
|
240
|
+
branch '${branch}'
|
|
241
|
+
}
|
|
242
|
+
steps {
|
|
243
|
+
echo 'Deploying to ${target}...'
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
`;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template loader for CI/CD generators
|
|
3
|
+
* Handles remote template fetching with fallback to embedded templates
|
|
4
|
+
*/
|
|
5
|
+
import type { GeneratorOptions } from "./github-actions";
|
|
6
|
+
export interface TemplateResult {
|
|
7
|
+
content: string;
|
|
8
|
+
source: "remote" | "embedded";
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Load CI/CD template with fallback
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadCICDTemplate(platform: string, strategy: string, options: GeneratorOptions, embeddedGenerator: (options: GeneratorOptions) => string): Promise<TemplateResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Log template source for debugging
|
|
16
|
+
*/
|
|
17
|
+
export declare function logTemplateSource(platform: string, source: "remote" | "embedded"): void;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Template loader for CI/CD generators
|
|
4
|
+
* Handles remote template fetching with fallback to embedded templates
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.logTemplateSource = exports.loadCICDTemplate = void 0;
|
|
8
|
+
const templates_1 = require("../../templates");
|
|
9
|
+
/**
|
|
10
|
+
* Load CI/CD template with fallback
|
|
11
|
+
*/
|
|
12
|
+
async function loadCICDTemplate(platform, strategy, options, embeddedGenerator) {
|
|
13
|
+
const manager = (0, templates_1.getTemplateManager)();
|
|
14
|
+
try {
|
|
15
|
+
// Try to fetch from remote template repository
|
|
16
|
+
const result = await manager.fetchCICDTemplate(platform, strategy);
|
|
17
|
+
if (result.data) {
|
|
18
|
+
// Template found, render with variables
|
|
19
|
+
const renderOptions = {
|
|
20
|
+
variables: {
|
|
21
|
+
projectName: options.projectName,
|
|
22
|
+
nodeVersion: options.nodeVersion,
|
|
23
|
+
packageManager: options.packageManager,
|
|
24
|
+
strategy: options.strategy,
|
|
25
|
+
includeSecurity: options.includeSecurity,
|
|
26
|
+
includeE2E: options.includeE2E,
|
|
27
|
+
includeCoverage: options.includeCoverage,
|
|
28
|
+
dockerRegistry: options.dockerRegistry || "ghcr.io",
|
|
29
|
+
deployTarget: options.deployTarget,
|
|
30
|
+
branch: options.branch,
|
|
31
|
+
port: options.port,
|
|
32
|
+
// Computed variables
|
|
33
|
+
installCmd: getInstallCommand(options.packageManager),
|
|
34
|
+
testCmd: getTestCommand(options.packageManager),
|
|
35
|
+
buildCmd: getBuildCommand(options.packageManager),
|
|
36
|
+
lintCmd: getLintCommand(options.packageManager),
|
|
37
|
+
},
|
|
38
|
+
conditionals: {
|
|
39
|
+
includeSecurity: options.includeSecurity,
|
|
40
|
+
includeE2E: options.includeE2E,
|
|
41
|
+
includeCoverage: options.includeCoverage,
|
|
42
|
+
isComprehensive: options.strategy === "comprehensive",
|
|
43
|
+
isSecurityFocused: options.strategy === "security-focused",
|
|
44
|
+
hasDeployTarget: options.deployTarget !== "none",
|
|
45
|
+
deployKubernetes: options.deployTarget === "kubernetes",
|
|
46
|
+
deployRailway: options.deployTarget === "railway",
|
|
47
|
+
deployRender: options.deployTarget === "render",
|
|
48
|
+
deployFly: options.deployTarget === "fly",
|
|
49
|
+
deployECS: options.deployTarget === "ecs",
|
|
50
|
+
deployCloudRun: options.deployTarget === "cloudrun",
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
const rendered = manager.render(result.data, renderOptions);
|
|
54
|
+
return { content: rendered, source: "remote" };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Remote fetch failed, fall back to embedded
|
|
59
|
+
}
|
|
60
|
+
// Fall back to embedded template generator
|
|
61
|
+
return {
|
|
62
|
+
content: embeddedGenerator(options),
|
|
63
|
+
source: "embedded",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
exports.loadCICDTemplate = loadCICDTemplate;
|
|
67
|
+
/**
|
|
68
|
+
* Get install command for package manager
|
|
69
|
+
*/
|
|
70
|
+
function getInstallCommand(packageManager) {
|
|
71
|
+
switch (packageManager) {
|
|
72
|
+
case "pnpm":
|
|
73
|
+
return "pnpm install";
|
|
74
|
+
case "yarn":
|
|
75
|
+
return "yarn install";
|
|
76
|
+
default:
|
|
77
|
+
return "npm ci";
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get test command for package manager
|
|
82
|
+
*/
|
|
83
|
+
function getTestCommand(packageManager) {
|
|
84
|
+
switch (packageManager) {
|
|
85
|
+
case "pnpm":
|
|
86
|
+
return "pnpm test";
|
|
87
|
+
case "yarn":
|
|
88
|
+
return "yarn test";
|
|
89
|
+
default:
|
|
90
|
+
return "npm test";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get build command for package manager
|
|
95
|
+
*/
|
|
96
|
+
function getBuildCommand(packageManager) {
|
|
97
|
+
switch (packageManager) {
|
|
98
|
+
case "pnpm":
|
|
99
|
+
return "pnpm build";
|
|
100
|
+
case "yarn":
|
|
101
|
+
return "yarn build";
|
|
102
|
+
default:
|
|
103
|
+
return "npm run build";
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get lint command for package manager
|
|
108
|
+
*/
|
|
109
|
+
function getLintCommand(packageManager) {
|
|
110
|
+
switch (packageManager) {
|
|
111
|
+
case "pnpm":
|
|
112
|
+
return "pnpm lint";
|
|
113
|
+
case "yarn":
|
|
114
|
+
return "yarn lint";
|
|
115
|
+
default:
|
|
116
|
+
return "npm run lint";
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Log template source for debugging
|
|
121
|
+
*/
|
|
122
|
+
function logTemplateSource(platform, source) {
|
|
123
|
+
if (process.env.EXPRESSOTS_DEBUG) {
|
|
124
|
+
const sourceLabel = source === "remote" ? "remote template" : "embedded template";
|
|
125
|
+
console.log(` [DEBUG] ${platform}: Using ${sourceLabel}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
exports.logTemplateSource = logTemplateSource;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { cicdCommand } from "./cli";
|
package/bin/cli.d.ts
CHANGED