greenbump 0.4.0 → 0.6.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 (78) hide show
  1. package/README.md +673 -66
  2. package/README.zh-CN.md +525 -100
  3. package/dist/agent/fixer.js +161 -12
  4. package/dist/agent/fixer.js.map +1 -1
  5. package/dist/agent/fixer.test.js +410 -0
  6. package/dist/agent/fixer.test.js.map +1 -0
  7. package/dist/cli/interactive.js +81 -0
  8. package/dist/cli/interactive.js.map +1 -0
  9. package/dist/cli.js +53 -0
  10. package/dist/cli.js.map +1 -1
  11. package/dist/engine/analyzers/changelog-parser.js +121 -0
  12. package/dist/engine/analyzers/changelog-parser.js.map +1 -0
  13. package/dist/engine/batch.test.js +59 -0
  14. package/dist/engine/batch.test.js.map +1 -0
  15. package/dist/engine/cache/manager.js +165 -0
  16. package/dist/engine/cache/manager.js.map +1 -0
  17. package/dist/engine/cache/manager.test.js +75 -0
  18. package/dist/engine/cache/manager.test.js.map +1 -0
  19. package/dist/engine/checks.test.js +92 -0
  20. package/dist/engine/checks.test.js.map +1 -0
  21. package/dist/engine/context/optimizer.js +189 -0
  22. package/dist/engine/context/optimizer.js.map +1 -0
  23. package/dist/engine/context/optimizer.test.js +81 -0
  24. package/dist/engine/context/optimizer.test.js.map +1 -0
  25. package/dist/engine/ecosystems/parsers.test.js +255 -0
  26. package/dist/engine/ecosystems/parsers.test.js.map +1 -0
  27. package/dist/engine/fixer/patterns.js +356 -0
  28. package/dist/engine/fixer/patterns.js.map +1 -0
  29. package/dist/engine/fixer/patterns.test.js +124 -0
  30. package/dist/engine/fixer/patterns.test.js.map +1 -0
  31. package/dist/engine/git.js +1 -0
  32. package/dist/engine/git.js.map +1 -1
  33. package/dist/engine/git.test.js +111 -0
  34. package/dist/engine/git.test.js.map +1 -0
  35. package/dist/engine/perf/metrics.js +171 -0
  36. package/dist/engine/perf/metrics.js.map +1 -0
  37. package/dist/engine/perf/regression.js +115 -0
  38. package/dist/engine/perf/regression.js.map +1 -0
  39. package/dist/engine/run.js +93 -2
  40. package/dist/engine/run.js.map +1 -1
  41. package/dist/engine/run.test.js +47 -0
  42. package/dist/engine/run.test.js.map +1 -0
  43. package/dist/engine/sandbox/docker-manager.js +215 -0
  44. package/dist/engine/sandbox/docker-manager.js.map +1 -0
  45. package/dist/engine/sandbox/orchestrator.js +107 -0
  46. package/dist/engine/sandbox/orchestrator.js.map +1 -0
  47. package/dist/engine/sandbox/service-detector.js +147 -0
  48. package/dist/engine/sandbox/service-detector.js.map +1 -0
  49. package/dist/engine/sandbox/template-generator.js +241 -0
  50. package/dist/engine/sandbox/template-generator.js.map +1 -0
  51. package/dist/engine/verifiers/ast-analyzer.js +212 -0
  52. package/dist/engine/verifiers/ast-analyzer.js.map +1 -0
  53. package/dist/engine/verifiers/ast-analyzer.test.js +96 -0
  54. package/dist/engine/verifiers/ast-analyzer.test.js.map +1 -0
  55. package/dist/engine/workspace.test.js +95 -0
  56. package/dist/engine/workspace.test.js.map +1 -0
  57. package/dist/exitcode.test.js +62 -0
  58. package/dist/exitcode.test.js.map +1 -0
  59. package/dist/format.js +15 -0
  60. package/dist/format.js.map +1 -1
  61. package/dist/report.test.js +56 -0
  62. package/dist/report.test.js.map +1 -0
  63. package/package.json +7 -4
  64. package/CHANGELOG.md +0 -93
  65. package/CONTRIBUTING.md +0 -52
  66. package/SECURITY.md +0 -38
  67. package/action-dist/index.cjs +0 -19935
  68. package/action.yml +0 -76
  69. package/competitive-analysis.md +0 -304
  70. package/examples/greenbump.yml +0 -37
  71. package/examples/legacy-repo/package.json +0 -12
  72. package/examples/legacy-repo/test.js +0 -17
  73. package/examples/multi-file-repo/models/todo.js +0 -8
  74. package/examples/multi-file-repo/models/user.js +0 -11
  75. package/examples/multi-file-repo/package.json +0 -12
  76. package/examples/multi-file-repo/services/session.js +0 -9
  77. package/examples/multi-file-repo/test.js +0 -19
  78. package/optimization-roadmap.md +0 -772
@@ -0,0 +1,215 @@
1
+ import { exec } from "../git.js";
2
+ import { existsSync } from "fs";
3
+ import { join } from "path";
4
+ import { rm } from "fs/promises";
5
+ /**
6
+ * Check if Docker is available and running
7
+ */
8
+ export async function checkDockerAvailable() {
9
+ const info = {
10
+ available: false,
11
+ composeAvailable: false,
12
+ };
13
+ try {
14
+ const versionResult = await exec("docker", ["--version"], { cwd: process.cwd() });
15
+ info.version = versionResult.stdout.trim();
16
+ // Check if Docker daemon is running
17
+ await exec("docker", ["ps"], { cwd: process.cwd() });
18
+ info.available = true;
19
+ // Check docker-compose availability
20
+ try {
21
+ await exec("docker-compose", ["--version"], { cwd: process.cwd() });
22
+ info.composeAvailable = true;
23
+ }
24
+ catch {
25
+ // docker-compose not available, but that's okay
26
+ }
27
+ }
28
+ catch {
29
+ // Docker not available
30
+ }
31
+ return info;
32
+ }
33
+ /**
34
+ * Build Docker image from Dockerfile
35
+ */
36
+ export async function buildDockerImage(cwd, imageName, dockerfilePath) {
37
+ console.log(`🐳 Building Docker image: ${imageName}...`);
38
+ await exec("docker", [
39
+ "build",
40
+ "-t", imageName,
41
+ "-f", dockerfilePath,
42
+ ".",
43
+ ], { cwd });
44
+ }
45
+ /**
46
+ * Run verification in Docker container
47
+ */
48
+ export async function runVerificationInContainer(cwd, options) {
49
+ const args = [
50
+ "run",
51
+ "--rm",
52
+ "-v", `${cwd}:/workspace`,
53
+ "-w", "/workspace",
54
+ ];
55
+ // Add network mode
56
+ if (options.networkMode) {
57
+ args.push("--network", options.networkMode);
58
+ }
59
+ // Add environment variables
60
+ if (options.env) {
61
+ for (const [key, value] of Object.entries(options.env)) {
62
+ args.push("-e", `${key}=${value}`);
63
+ }
64
+ }
65
+ args.push(options.image);
66
+ // Run the container with test command
67
+ args.push("sh", "-c", "npm install && npm run build 2>&1 && npm test 2>&1");
68
+ let exitCode = 0;
69
+ let stdout = "";
70
+ let stderr = "";
71
+ let buildSuccess = false;
72
+ let testsPassed = false;
73
+ try {
74
+ const result = await exec("docker", args, {
75
+ cwd,
76
+ timeout: options.timeout || 600000, // 10 minutes default
77
+ });
78
+ stdout = result.stdout;
79
+ stderr = result.stderr;
80
+ exitCode = 0;
81
+ buildSuccess = true;
82
+ testsPassed = true;
83
+ }
84
+ catch (error) {
85
+ exitCode = error.exitCode || 1;
86
+ stdout = error.stdout || "";
87
+ stderr = error.stderr || "";
88
+ // Determine what failed
89
+ buildSuccess = !stderr.includes("npm run build") && !stdout.includes("build failed");
90
+ testsPassed = false;
91
+ }
92
+ return {
93
+ exitCode,
94
+ stdout,
95
+ stderr,
96
+ buildSuccess,
97
+ testsPassed,
98
+ };
99
+ }
100
+ /**
101
+ * Start docker-compose services
102
+ */
103
+ export async function startComposeServices(cwd, composeFile) {
104
+ console.log("🚀 Starting docker-compose services...");
105
+ const projectName = `greenbump-${Date.now()}`;
106
+ await exec("docker-compose", [
107
+ "-f", composeFile,
108
+ "-p", projectName,
109
+ "up", "-d",
110
+ ], { cwd });
111
+ return projectName;
112
+ }
113
+ /**
114
+ * Check if a service is healthy
115
+ */
116
+ export async function checkServiceHealth(projectName, serviceName) {
117
+ try {
118
+ const result = await exec("docker-compose", ["-p", projectName, "ps", "--filter", `name=${serviceName}`, "--format", "json"], { cwd: process.cwd() });
119
+ const output = result.stdout.trim();
120
+ if (!output)
121
+ return false;
122
+ // Check if service is running
123
+ return output.includes('"State":"running"') || output.includes('healthy');
124
+ }
125
+ catch {
126
+ return false;
127
+ }
128
+ }
129
+ /**
130
+ * Wait for services to become healthy
131
+ */
132
+ export async function waitForServices(projectName, services, timeout = 60) {
133
+ console.log("⏳ Waiting for services to become healthy...");
134
+ const deadline = Date.now() + timeout * 1000;
135
+ const healthyServices = new Set();
136
+ while (Date.now() < deadline && healthyServices.size < services.length) {
137
+ for (const service of services) {
138
+ if (healthyServices.has(service))
139
+ continue;
140
+ const healthy = await checkServiceHealth(projectName, service);
141
+ if (healthy) {
142
+ console.log(`✓ ${service} is healthy`);
143
+ healthyServices.add(service);
144
+ }
145
+ }
146
+ if (healthyServices.size < services.length) {
147
+ await sleep(2000); // Wait 2 seconds before checking again
148
+ }
149
+ }
150
+ if (healthyServices.size < services.length) {
151
+ const unhealthy = services.filter(s => !healthyServices.has(s));
152
+ throw new Error(`Timeout waiting for services to become healthy: ${unhealthy.join(", ")}`);
153
+ }
154
+ }
155
+ /**
156
+ * Stop and remove docker-compose services
157
+ */
158
+ export async function stopComposeServices(cwd, composeFile, projectName) {
159
+ console.log("🛑 Stopping docker-compose services...");
160
+ try {
161
+ await exec("docker-compose", [
162
+ "-f", composeFile,
163
+ "-p", projectName,
164
+ "down", "-v",
165
+ ], { cwd });
166
+ }
167
+ catch (error) {
168
+ console.warn("Warning: Failed to stop compose services:", error);
169
+ }
170
+ }
171
+ /**
172
+ * Remove Docker image
173
+ */
174
+ export async function removeDockerImage(imageName) {
175
+ try {
176
+ await exec("docker", ["rmi", imageName], { cwd: process.cwd() });
177
+ }
178
+ catch {
179
+ // Ignore errors when removing image
180
+ }
181
+ }
182
+ /**
183
+ * Cleanup Docker resources
184
+ */
185
+ export async function cleanupDocker(cwd, imageName, composeFile, projectName) {
186
+ console.log("🧹 Cleaning up Docker resources...");
187
+ // Stop compose services
188
+ if (composeFile && projectName) {
189
+ await stopComposeServices(cwd, composeFile, projectName);
190
+ }
191
+ // Remove image
192
+ await removeDockerImage(imageName);
193
+ // Remove temporary files
194
+ const tempFiles = [
195
+ join(cwd, ".greenbump-Dockerfile"),
196
+ join(cwd, ".greenbump-compose.yml"),
197
+ ];
198
+ for (const file of tempFiles) {
199
+ try {
200
+ if (existsSync(file)) {
201
+ await rm(file);
202
+ }
203
+ }
204
+ catch {
205
+ // Ignore cleanup errors
206
+ }
207
+ }
208
+ }
209
+ /**
210
+ * Utility: sleep
211
+ */
212
+ function sleep(ms) {
213
+ return new Promise(resolve => setTimeout(resolve, ms));
214
+ }
215
+ //# sourceMappingURL=docker-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-manager.js","sourceRoot":"","sources":["../../../src/engine/sandbox/docker-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ import { join } from "path";
2
+ import { writeFile } from "fs/promises";
3
+ import { checkDockerAvailable, buildDockerImage, runVerificationInContainer, startComposeServices, waitForServices, cleanupDocker, } from "./docker-manager.js";
4
+ import { detectProjectType, generateDockerfile, generateComposeFile, } from "./template-generator.js";
5
+ import { detectRequiredServices, getServiceDisplayName, } from "./service-detector.js";
6
+ /**
7
+ * Run verification in isolated Docker sandbox
8
+ */
9
+ export async function runInSandbox(cwd, options) {
10
+ // Check if Docker is available
11
+ const dockerInfo = await checkDockerAvailable();
12
+ if (!dockerInfo.available) {
13
+ console.warn("⚠️ Docker not available, skipping sandbox verification");
14
+ console.warn(" Install Docker for isolated testing: https://docs.docker.com/get-docker/");
15
+ return {
16
+ passed: false,
17
+ buildSuccess: false,
18
+ testsPassed: false,
19
+ services: [],
20
+ logs: "",
21
+ exitCode: -1,
22
+ skipped: true,
23
+ skipReason: "docker_unavailable",
24
+ };
25
+ }
26
+ console.log("🐳 Starting sandbox environment...");
27
+ console.log(` Docker version: ${dockerInfo.version}`);
28
+ // Detect project type
29
+ const projectType = await detectProjectType(cwd);
30
+ console.log(` Project type: ${projectType}`);
31
+ // Detect or use specified services
32
+ const services = options.services || await detectRequiredServices(cwd);
33
+ if (services.length > 0) {
34
+ console.log(` Required services: ${services.map(getServiceDisplayName).join(", ")}`);
35
+ }
36
+ const imageName = options.dockerImage || "greenbump-verify";
37
+ const dockerfilePath = join(cwd, ".greenbump-Dockerfile");
38
+ const composeFilePath = join(cwd, ".greenbump-compose.yml");
39
+ let projectName;
40
+ const serviceHealths = [];
41
+ try {
42
+ // Generate Dockerfile
43
+ const dockerfile = await generateDockerfile(projectType, cwd);
44
+ await writeFile(dockerfilePath, dockerfile);
45
+ // Generate docker-compose.yml if services needed
46
+ let composeFile = "";
47
+ if (services.length > 0) {
48
+ composeFile = await generateComposeFile(services);
49
+ if (composeFile) {
50
+ await writeFile(composeFilePath, composeFile);
51
+ }
52
+ }
53
+ // Build Docker image
54
+ await buildDockerImage(cwd, imageName, dockerfilePath);
55
+ // Start services if needed
56
+ if (services.length > 0 && composeFile && dockerInfo.composeAvailable) {
57
+ projectName = await startComposeServices(cwd, composeFilePath);
58
+ // Wait for services to be healthy
59
+ await waitForServices(projectName, services, options.timeout ? options.timeout / 1000 : 60);
60
+ // Record service health
61
+ for (const service of services) {
62
+ serviceHealths.push({
63
+ name: service,
64
+ healthy: true,
65
+ displayName: getServiceDisplayName(service),
66
+ });
67
+ }
68
+ }
69
+ else if (services.length > 0 && !dockerInfo.composeAvailable) {
70
+ console.warn("⚠️ docker-compose not available, skipping service startup");
71
+ }
72
+ // Run verification in container
73
+ console.log("🔍 Running verification in container...");
74
+ const networkMode = projectName ? `${projectName}_default` : "bridge";
75
+ const result = await runVerificationInContainer(cwd, {
76
+ image: imageName,
77
+ networkMode,
78
+ timeout: options.timeout,
79
+ });
80
+ // Display results
81
+ if (result.exitCode === 0) {
82
+ console.log("✅ Verification passed in sandbox");
83
+ }
84
+ else {
85
+ console.error("❌ Verification failed in sandbox");
86
+ console.error(result.stderr);
87
+ }
88
+ return {
89
+ passed: result.exitCode === 0,
90
+ buildSuccess: result.buildSuccess,
91
+ testsPassed: result.testsPassed,
92
+ services: serviceHealths,
93
+ logs: result.stdout + "\n" + result.stderr,
94
+ exitCode: result.exitCode,
95
+ };
96
+ }
97
+ finally {
98
+ // Cleanup unless keepContainer is true
99
+ if (!options.keepContainer) {
100
+ await cleanupDocker(cwd, imageName, composeFilePath, projectName);
101
+ }
102
+ else {
103
+ console.log("🔧 Container kept for debugging (use --keep-container=false to cleanup)");
104
+ }
105
+ }
106
+ }
107
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../../src/engine/sandbox/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ import { existsSync } from "fs";
2
+ import { join } from "path";
3
+ import { readFile } from "fs/promises";
4
+ /**
5
+ * Detect required database/cache services for the project
6
+ */
7
+ export async function detectRequiredServices(cwd) {
8
+ const services = new Set();
9
+ // Check package.json dependencies
10
+ await detectFromPackageJson(cwd, services);
11
+ // Check docker-compose files
12
+ await detectFromDockerCompose(cwd, services);
13
+ // Check environment files
14
+ await detectFromEnvFiles(cwd, services);
15
+ return Array.from(services);
16
+ }
17
+ /**
18
+ * Detect services from package.json dependencies
19
+ */
20
+ async function detectFromPackageJson(cwd, services) {
21
+ const pkgPath = join(cwd, "package.json");
22
+ if (!existsSync(pkgPath))
23
+ return;
24
+ try {
25
+ const content = await readFile(pkgPath, "utf-8");
26
+ const pkg = JSON.parse(content);
27
+ const allDeps = {
28
+ ...pkg.dependencies,
29
+ ...pkg.devDependencies,
30
+ };
31
+ // PostgreSQL
32
+ if (allDeps.pg || allDeps["pg-promise"] || allDeps.postgres || allDeps.sequelize) {
33
+ services.add("postgres");
34
+ }
35
+ // MySQL
36
+ if (allDeps.mysql || allDeps.mysql2) {
37
+ services.add("mysql");
38
+ }
39
+ // Redis
40
+ if (allDeps.redis || allDeps.ioredis) {
41
+ services.add("redis");
42
+ }
43
+ // MongoDB
44
+ if (allDeps.mongodb || allDeps.mongoose) {
45
+ services.add("mongodb");
46
+ }
47
+ }
48
+ catch {
49
+ // Ignore errors reading package.json
50
+ }
51
+ }
52
+ /**
53
+ * Detect services from docker-compose files
54
+ */
55
+ async function detectFromDockerCompose(cwd, services) {
56
+ const composeFiles = [
57
+ "docker-compose.yml",
58
+ "docker-compose.yaml",
59
+ "docker-compose.test.yml",
60
+ "docker-compose.test.yaml",
61
+ ];
62
+ for (const file of composeFiles) {
63
+ const composePath = join(cwd, file);
64
+ if (!existsSync(composePath))
65
+ continue;
66
+ try {
67
+ const content = await readFile(composePath, "utf-8");
68
+ // Simple text search for service images
69
+ if (/image:\s*postgres/i.test(content)) {
70
+ services.add("postgres");
71
+ }
72
+ if (/image:\s*mysql/i.test(content)) {
73
+ services.add("mysql");
74
+ }
75
+ if (/image:\s*redis/i.test(content)) {
76
+ services.add("redis");
77
+ }
78
+ if (/image:\s*mongo/i.test(content)) {
79
+ services.add("mongodb");
80
+ }
81
+ }
82
+ catch {
83
+ // Ignore errors reading compose files
84
+ }
85
+ }
86
+ }
87
+ /**
88
+ * Detect services from .env files
89
+ */
90
+ async function detectFromEnvFiles(cwd, services) {
91
+ const envFiles = [
92
+ ".env",
93
+ ".env.test",
94
+ ".env.local",
95
+ ".env.development",
96
+ ];
97
+ for (const file of envFiles) {
98
+ const envPath = join(cwd, file);
99
+ if (!existsSync(envPath))
100
+ continue;
101
+ try {
102
+ const content = await readFile(envPath, "utf-8");
103
+ // Check for database connection strings
104
+ if (/postgres:\/\//i.test(content) || /postgresql:\/\//i.test(content)) {
105
+ services.add("postgres");
106
+ }
107
+ if (/mysql:\/\//i.test(content)) {
108
+ services.add("mysql");
109
+ }
110
+ if (/redis:\/\//i.test(content)) {
111
+ services.add("redis");
112
+ }
113
+ if (/mongodb:\/\//i.test(content)) {
114
+ services.add("mongodb");
115
+ }
116
+ // Check for database host environment variables
117
+ if (/POSTGRES_HOST|PGHOST|DATABASE_URL.*postgres/i.test(content)) {
118
+ services.add("postgres");
119
+ }
120
+ if (/MYSQL_HOST|DATABASE_URL.*mysql/i.test(content)) {
121
+ services.add("mysql");
122
+ }
123
+ if (/REDIS_HOST|REDIS_URL/i.test(content)) {
124
+ services.add("redis");
125
+ }
126
+ if (/MONGO_HOST|MONGODB_URL|MONGO_URL/i.test(content)) {
127
+ services.add("mongodb");
128
+ }
129
+ }
130
+ catch {
131
+ // Ignore errors reading env files
132
+ }
133
+ }
134
+ }
135
+ /**
136
+ * Get display name for service
137
+ */
138
+ export function getServiceDisplayName(service) {
139
+ const names = {
140
+ postgres: "PostgreSQL",
141
+ mysql: "MySQL",
142
+ redis: "Redis",
143
+ mongodb: "MongoDB",
144
+ };
145
+ return names[service] || service;
146
+ }
147
+ //# sourceMappingURL=service-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-detector.js","sourceRoot":"","sources":["../../../src/engine/sandbox/service-detector.ts"],"names":[],"mappings":"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"}