greenbump 0.2.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 (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -0
  3. package/README.zh-CN.md +213 -0
  4. package/action-dist/index.cjs +19695 -0
  5. package/action.yml +76 -0
  6. package/dist/action/github.js +70 -0
  7. package/dist/action/github.js.map +1 -0
  8. package/dist/action/main.js +99 -0
  9. package/dist/action/main.js.map +1 -0
  10. package/dist/agent/factory.js +72 -0
  11. package/dist/agent/factory.js.map +1 -0
  12. package/dist/agent/fixer.js +307 -0
  13. package/dist/agent/fixer.js.map +1 -0
  14. package/dist/agent/fixer.test.js +224 -0
  15. package/dist/agent/fixer.test.js.map +1 -0
  16. package/dist/agent/provider-anthropic.js +59 -0
  17. package/dist/agent/provider-anthropic.js.map +1 -0
  18. package/dist/agent/provider-openai.js +65 -0
  19. package/dist/agent/provider-openai.js.map +1 -0
  20. package/dist/agent/provider.js +4 -0
  21. package/dist/agent/provider.js.map +1 -0
  22. package/dist/cli.js +138 -0
  23. package/dist/cli.js.map +1 -0
  24. package/dist/engine/batch.js +246 -0
  25. package/dist/engine/batch.js.map +1 -0
  26. package/dist/engine/batch.test.js +59 -0
  27. package/dist/engine/batch.test.js.map +1 -0
  28. package/dist/engine/changelog.js +66 -0
  29. package/dist/engine/changelog.js.map +1 -0
  30. package/dist/engine/checks.js +41 -0
  31. package/dist/engine/checks.js.map +1 -0
  32. package/dist/engine/checks.test.js +92 -0
  33. package/dist/engine/checks.test.js.map +1 -0
  34. package/dist/engine/detect.js +5 -0
  35. package/dist/engine/detect.js.map +1 -0
  36. package/dist/engine/ecosystems/bundler.js +59 -0
  37. package/dist/engine/ecosystems/bundler.js.map +1 -0
  38. package/dist/engine/ecosystems/cargo.js +83 -0
  39. package/dist/engine/ecosystems/cargo.js.map +1 -0
  40. package/dist/engine/ecosystems/cocoapods.js +47 -0
  41. package/dist/engine/ecosystems/cocoapods.js.map +1 -0
  42. package/dist/engine/ecosystems/composer.js +32 -0
  43. package/dist/engine/ecosystems/composer.js.map +1 -0
  44. package/dist/engine/ecosystems/conan.js +106 -0
  45. package/dist/engine/ecosystems/conan.js.map +1 -0
  46. package/dist/engine/ecosystems/elm.js +77 -0
  47. package/dist/engine/ecosystems/elm.js.map +1 -0
  48. package/dist/engine/ecosystems/go.js +72 -0
  49. package/dist/engine/ecosystems/go.js.map +1 -0
  50. package/dist/engine/ecosystems/gradle.js +90 -0
  51. package/dist/engine/ecosystems/gradle.js.map +1 -0
  52. package/dist/engine/ecosystems/index.js +67 -0
  53. package/dist/engine/ecosystems/index.js.map +1 -0
  54. package/dist/engine/ecosystems/maven.js +77 -0
  55. package/dist/engine/ecosystems/maven.js.map +1 -0
  56. package/dist/engine/ecosystems/mix.js +64 -0
  57. package/dist/engine/ecosystems/mix.js.map +1 -0
  58. package/dist/engine/ecosystems/npm.js +47 -0
  59. package/dist/engine/ecosystems/npm.js.map +1 -0
  60. package/dist/engine/ecosystems/nuget.js +50 -0
  61. package/dist/engine/ecosystems/nuget.js.map +1 -0
  62. package/dist/engine/ecosystems/parsers.test.js +255 -0
  63. package/dist/engine/ecosystems/parsers.test.js.map +1 -0
  64. package/dist/engine/ecosystems/pip.js +61 -0
  65. package/dist/engine/ecosystems/pip.js.map +1 -0
  66. package/dist/engine/ecosystems/pipenv.js +37 -0
  67. package/dist/engine/ecosystems/pipenv.js.map +1 -0
  68. package/dist/engine/ecosystems/pnpm.js +48 -0
  69. package/dist/engine/ecosystems/pnpm.js.map +1 -0
  70. package/dist/engine/ecosystems/poetry.js +42 -0
  71. package/dist/engine/ecosystems/poetry.js.map +1 -0
  72. package/dist/engine/ecosystems/pub.js +32 -0
  73. package/dist/engine/ecosystems/pub.js.map +1 -0
  74. package/dist/engine/ecosystems/python-shared.js +29 -0
  75. package/dist/engine/ecosystems/python-shared.js.map +1 -0
  76. package/dist/engine/ecosystems/swiftpm.js +102 -0
  77. package/dist/engine/ecosystems/swiftpm.js.map +1 -0
  78. package/dist/engine/ecosystems/types.js +19 -0
  79. package/dist/engine/ecosystems/types.js.map +1 -0
  80. package/dist/engine/ecosystems/uv.js +36 -0
  81. package/dist/engine/ecosystems/uv.js.map +1 -0
  82. package/dist/engine/ecosystems/yarn.js +62 -0
  83. package/dist/engine/ecosystems/yarn.js.map +1 -0
  84. package/dist/engine/exec.js +47 -0
  85. package/dist/engine/exec.js.map +1 -0
  86. package/dist/engine/git.js +42 -0
  87. package/dist/engine/git.js.map +1 -0
  88. package/dist/engine/git.test.js +111 -0
  89. package/dist/engine/git.test.js.map +1 -0
  90. package/dist/engine/pm.js +14 -0
  91. package/dist/engine/pm.js.map +1 -0
  92. package/dist/engine/run.js +167 -0
  93. package/dist/engine/run.js.map +1 -0
  94. package/dist/engine/run.test.js +47 -0
  95. package/dist/engine/run.test.js.map +1 -0
  96. package/dist/engine/upgrade.js +10 -0
  97. package/dist/engine/upgrade.js.map +1 -0
  98. package/dist/engine/workspace.js +155 -0
  99. package/dist/engine/workspace.js.map +1 -0
  100. package/dist/engine/workspace.test.js +95 -0
  101. package/dist/engine/workspace.test.js.map +1 -0
  102. package/dist/exitcode.js +51 -0
  103. package/dist/exitcode.js.map +1 -0
  104. package/dist/exitcode.test.js +62 -0
  105. package/dist/exitcode.test.js.map +1 -0
  106. package/dist/format.js +101 -0
  107. package/dist/format.js.map +1 -0
  108. package/dist/pr.js +63 -0
  109. package/dist/pr.js.map +1 -0
  110. package/dist/report.js +13 -0
  111. package/dist/report.js.map +1 -0
  112. package/dist/report.test.js +56 -0
  113. package/dist/report.test.js.map +1 -0
  114. package/dist/test-utils.js +36 -0
  115. package/dist/test-utils.js.map +1 -0
  116. package/package.json +56 -0
@@ -0,0 +1,246 @@
1
+ import { run, RunError, computeNeedsReview } from "./run.js";
2
+ import { runChecks } from "./checks.js";
3
+ import { upgradeDependency } from "./upgrade.js";
4
+ import { detectPackageManager } from "./pm.js";
5
+ import { fetchChangelog } from "./changelog.js";
6
+ import { isGitRepo, isTreeClean, currentBranch, createBranch, commitAll, diffStat, fullDiff, checkout } from "./git.js";
7
+ import { runFixLoop } from "../agent/fixer.js";
8
+ import { createProvider } from "../agent/factory.js";
9
+ import { detectOutdatedAll, resolveWorkspaceTarget, WORKSPACE_ROOT, } from "./workspace.js";
10
+ import { join } from "node:path";
11
+ /** `git checkout` back to the base ref, ignoring errors (best-effort cleanup between batch targets). */
12
+ async function checkoutBack(cwd, base) {
13
+ await checkout(cwd, base);
14
+ }
15
+ function resolveCwd(cwd, workspacePath) {
16
+ if (!workspacePath || workspacePath === WORKSPACE_ROOT)
17
+ return cwd;
18
+ return join(cwd, workspacePath);
19
+ }
20
+ export async function runBatch(opts) {
21
+ const { cwd } = opts;
22
+ if (opts.all && opts.deps?.length) {
23
+ throw new RunError("--all and an explicit dependency list are mutually exclusive.");
24
+ }
25
+ const pm = opts.ecosystem ?? (await detectPackageManager(cwd));
26
+ const candidates = await detectOutdatedAll(pm, cwd);
27
+ if (candidates.length === 0) {
28
+ throw new RunError("No outdated dependencies found — nothing to upgrade.");
29
+ }
30
+ const targets = resolveTargets(opts, candidates);
31
+ const baseBranch = (await isGitRepo(cwd)) && !opts.noGit ? await currentBranch(cwd) : undefined;
32
+ const results = [];
33
+ if (opts.group && targets.length > 1) {
34
+ try {
35
+ const summary = await runGrouped(opts, pm, targets, opts.group);
36
+ results.push(summary);
37
+ }
38
+ catch (err) {
39
+ if (opts.failFast)
40
+ throw err;
41
+ results.push({ dep: opts.group, error: err.message, fatal: true });
42
+ }
43
+ if (baseBranch)
44
+ await checkoutBack(cwd, baseBranch);
45
+ return { results };
46
+ }
47
+ for (const target of targets) {
48
+ try {
49
+ const summary = await run({
50
+ ...stripBatchOnlyFields(opts),
51
+ cwd: resolveCwd(cwd, target.workspacePath),
52
+ dep: target.dep,
53
+ to: target.to,
54
+ });
55
+ results.push(summary);
56
+ }
57
+ catch (err) {
58
+ if (opts.failFast)
59
+ throw err;
60
+ results.push({ dep: target.dep, error: err.message, fatal: true });
61
+ }
62
+ if (baseBranch)
63
+ await checkoutBack(cwd, baseBranch);
64
+ }
65
+ return { results };
66
+ }
67
+ /**
68
+ * Grouped run: ONE branch, ONE baseline check, install all N targets
69
+ * back-to-back, ONE post-upgrade check, ONE fix-loop call across all N
70
+ * breakages, ONE commit. Mirrors run()'s body but widened to a target list —
71
+ * see FixOptions.deps in fixer.ts for the multi-dep prompt this feeds.
72
+ */
73
+ async function runGrouped(opts, pm, targets, groupName) {
74
+ const log = opts.onLog ?? (() => { });
75
+ const startedAt = Date.now();
76
+ const cwd = opts.cwd;
77
+ const scopes = new Set(targets.map((t) => t.workspacePath ?? WORKSPACE_ROOT));
78
+ if (scopes.size > 1) {
79
+ throw new RunError(`--group targets must all live in the same workspace package; found: ${[...scopes].join(", ")}. ` +
80
+ `Run each workspace's group separately.`);
81
+ }
82
+ const groupCwd = resolveCwd(cwd, targets[0]?.workspacePath);
83
+ const checkOverrides = { buildCmd: opts.buildCmd, testCmd: opts.testCmd };
84
+ const resolvedTargets = targets.map((t) => {
85
+ if (!t.to)
86
+ throw new RunError(`\`${t.dep}\` has no resolved target version — internal error in resolveTargets().`);
87
+ return { dep: t.dep, from: t.from ?? "", to: t.to };
88
+ });
89
+ let branch;
90
+ const gitRepo = await isGitRepo(cwd);
91
+ if (gitRepo && !opts.noGit) {
92
+ if (!(await isTreeClean(cwd))) {
93
+ throw new RunError("Working tree is dirty. Commit or stash your changes first (or pass --no-git).");
94
+ }
95
+ await currentBranch(cwd);
96
+ branch = `greenbump/group-${groupName.replace(/[^a-zA-Z0-9._-]/g, "-")}`;
97
+ await createBranch(cwd, branch);
98
+ log(`created branch ${branch}`);
99
+ }
100
+ log("running baseline build + tests…");
101
+ const baseline = await runChecks(pm, groupCwd, checkOverrides);
102
+ if (!baseline.ok && !baseline.unverifiable) {
103
+ throw new RunError(`Baseline is already failing (${baseline.failedStep}) before any upgrade. ` +
104
+ `Fix that first — greenbump can't tell your pre-existing failures from upgrade breakage.`);
105
+ }
106
+ const baselineGreen = baseline.ok && !baseline.unverifiable;
107
+ for (const target of resolvedTargets) {
108
+ log(`installing ${target.dep}@${target.to}…`);
109
+ const up = await upgradeDependency(pm, groupCwd, target.dep, target.to);
110
+ if (!up.ok) {
111
+ throw new RunError(`${pm} failed to install ${target.dep}@${target.to}:\n${up.output}`);
112
+ }
113
+ }
114
+ const post = await runChecks(pm, groupCwd, checkOverrides);
115
+ const depsSummary = resolvedTargets.map((t) => `${t.dep}→${t.to}`).join(", ");
116
+ const summary = {
117
+ dep: `group:${groupName}`,
118
+ from: "",
119
+ to: depsSummary,
120
+ packageManager: pm,
121
+ branch,
122
+ baselineGreen,
123
+ neededFix: false,
124
+ fixed: post.ok,
125
+ unverifiable: post.unverifiable,
126
+ needsReview: false,
127
+ committed: false,
128
+ rounds: 0,
129
+ usage: { inputTokens: 0, outputTokens: 0 },
130
+ editedFiles: [],
131
+ testFilesTouched: [],
132
+ durationMs: 0,
133
+ };
134
+ if (post.unverifiable) {
135
+ log("no build/test scripts — group upgrade applied but UNVERIFIED");
136
+ summary.needsReview = true;
137
+ await maybeCommitGroup(cwd, summary, depsSummary, true);
138
+ summary.durationMs = Date.now() - startedAt;
139
+ return summary;
140
+ }
141
+ if (post.ok) {
142
+ log("clean group upgrade — build + tests green with no code changes");
143
+ await maybeCommitGroup(cwd, summary, depsSummary, true);
144
+ summary.durationMs = Date.now() - startedAt;
145
+ return summary;
146
+ }
147
+ summary.neededFix = true;
148
+ const deps = [];
149
+ for (const target of resolvedTargets) {
150
+ const changelog = await fetchChangelog(target.dep, target.from, target.to);
151
+ deps.push({ dep: target.dep, from: target.from, to: target.to, changelog });
152
+ }
153
+ const provider = createProvider({
154
+ provider: opts.provider,
155
+ model: opts.model,
156
+ baseURL: opts.baseURL,
157
+ apiKey: opts.apiKey,
158
+ });
159
+ log(`group upgrade broke ${post.failedStep} — starting fix loop via ${provider.name} (${provider.model})`);
160
+ const fix = await runFixLoop({
161
+ cwd: groupCwd,
162
+ pm,
163
+ checkOverrides,
164
+ provider,
165
+ maxRounds: opts.maxRounds,
166
+ maxTokens: opts.maxTokens,
167
+ dep: deps[0]?.dep ?? groupName,
168
+ from: deps[0]?.from ?? "",
169
+ to: deps[0]?.to ?? "",
170
+ deps,
171
+ failureOutput: post.output,
172
+ onLog: log,
173
+ });
174
+ summary.fixed = fix.fixed;
175
+ summary.rounds = fix.rounds;
176
+ summary.usage = fix.usage;
177
+ summary.editedFiles = fix.editedFiles;
178
+ summary.testFilesTouched = fix.editedFiles.filter((f) => /(^|\/)(test|tests|__tests__|spec)(\/|\.)|\.(test|spec)\./i.test(f));
179
+ summary.needsReview = computeNeedsReview({
180
+ unverifiable: false,
181
+ neededFix: true,
182
+ fixed: fix.fixed,
183
+ testFilesTouched: summary.testFilesTouched,
184
+ budgetExceeded: fix.budgetExceeded,
185
+ });
186
+ await maybeCommitGroup(cwd, summary, depsSummary, fix.fixed);
187
+ summary.durationMs = Date.now() - startedAt;
188
+ return summary;
189
+ }
190
+ async function maybeCommitGroup(cwd, summary, depsSummary, shouldCommit) {
191
+ if (!summary.branch || !shouldCommit)
192
+ return;
193
+ const note = summary.neededFix ? ` and fix ${summary.editedFiles.length} file(s)` : "";
194
+ await commitAll(cwd, `chore(deps): bump ${depsSummary}${note}\n\nAutomated by greenbump.`);
195
+ summary.committed = true;
196
+ summary.diffStat = await diffStat(cwd, "HEAD~1");
197
+ if (summary.neededFix)
198
+ summary.fullDiff = await fullDiff(cwd, "HEAD~1");
199
+ }
200
+ function stripBatchOnlyFields(opts) {
201
+ const { all, deps, workspace, group, failFast, ...rest } = opts;
202
+ return rest;
203
+ }
204
+ /**
205
+ * Resolve the CLI's --all / explicit-deps input into concrete UpgradeTargets.
206
+ * Explicit lists where EVERY name is invalid are a genuine usage error and
207
+ * throw immediately (before any git/branch work); a partially-valid list
208
+ * defers the bad names to per-target RunFailure records instead, since one
209
+ * typo shouldn't sink an otherwise-valid batch.
210
+ */
211
+ export function resolveTargets(opts, candidates) {
212
+ if (opts.all) {
213
+ return candidates.map((c) => ({ dep: c.name, from: c.current, to: c.latest, workspacePath: c.workspacePath }));
214
+ }
215
+ const names = opts.deps ?? [];
216
+ if (names.length === 0) {
217
+ // zero-arg UX: caller should have routed to the single-dep path instead;
218
+ // batch.ts is never invoked with neither --all nor explicit deps.
219
+ throw new RunError("runBatch() requires --all or an explicit dependency list.");
220
+ }
221
+ const resolved = [];
222
+ const invalid = [];
223
+ for (const name of names) {
224
+ const match = resolveWorkspaceTarget(name, candidates, opts.workspace);
225
+ if (!match) {
226
+ invalid.push(name);
227
+ continue;
228
+ }
229
+ resolved.push({
230
+ dep: match.name,
231
+ from: match.current,
232
+ to: match.latest,
233
+ workspacePath: match.workspacePath,
234
+ });
235
+ }
236
+ if (resolved.length === 0) {
237
+ throw new RunError(`None of the requested dependencies are outdated (or direct): ${invalid.join(", ")}. ` +
238
+ `Available: ${candidates.map((c) => c.name).join(", ")}`);
239
+ }
240
+ // Partial invalid names surface as synthetic failures alongside real results.
241
+ for (const name of invalid) {
242
+ resolved.push({ dep: name, workspacePath: undefined });
243
+ }
244
+ return resolved;
245
+ }
246
+ //# sourceMappingURL=batch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/engine/batch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { resolveTargets } from "./batch.js";
4
+ import { WORKSPACE_ROOT, WorkspaceAmbiguityError } from "./workspace.js";
5
+ import { RunError } from "./run.js";
6
+ function outdated(name, current, latest, workspacePath = WORKSPACE_ROOT) {
7
+ return { name, current, wanted: "", latest, workspacePath };
8
+ }
9
+ function baseOpts(overrides = {}) {
10
+ return { cwd: "/tmp/does-not-matter", maxRounds: 5, ...overrides };
11
+ }
12
+ test("resolveTargets: --all resolves every candidate, carrying from/to/workspacePath", () => {
13
+ const candidates = [outdated("lodash", "4.17.20", "4.17.21"), outdated("axios", "1.2.0", "1.3.0")];
14
+ const targets = resolveTargets(baseOpts({ all: true }), candidates);
15
+ assert.deepEqual(targets.map((t) => [t.dep, t.from, t.to, t.workspacePath]), [
16
+ ["lodash", "4.17.20", "4.17.21", WORKSPACE_ROOT],
17
+ ["axios", "1.2.0", "1.3.0", WORKSPACE_ROOT],
18
+ ]);
19
+ });
20
+ test("resolveTargets: explicit deps list resolves each by name", () => {
21
+ const candidates = [outdated("lodash", "4.17.20", "4.17.21"), outdated("axios", "1.2.0", "1.3.0")];
22
+ const targets = resolveTargets(baseOpts({ deps: ["axios"] }), candidates);
23
+ assert.deepEqual(targets, [{ dep: "axios", from: "1.2.0", to: "1.3.0", workspacePath: WORKSPACE_ROOT }]);
24
+ });
25
+ test("resolveTargets: a mix of valid and invalid names keeps the valid ones and defers invalid ones as targets without a resolved version", () => {
26
+ const candidates = [outdated("lodash", "4.17.20", "4.17.21")];
27
+ const targets = resolveTargets(baseOpts({ deps: ["lodash", "not-a-real-package"] }), candidates);
28
+ assert.equal(targets.length, 2);
29
+ assert.equal(targets[0].dep, "lodash");
30
+ assert.ok(targets[0].to);
31
+ assert.equal(targets[1].dep, "not-a-real-package");
32
+ assert.equal(targets[1].to, undefined);
33
+ });
34
+ test("resolveTargets: every requested name invalid throws before any git/branch work", () => {
35
+ const candidates = [outdated("lodash", "4.17.20", "4.17.21")];
36
+ assert.throws(() => resolveTargets(baseOpts({ deps: ["totally-fake-1", "totally-fake-2"] }), candidates), RunError);
37
+ });
38
+ test("resolveTargets: neither --all nor deps given throws (batch.ts is never called this way from the CLI)", () => {
39
+ const candidates = [outdated("lodash", "4.17.20", "4.17.21")];
40
+ assert.throws(() => resolveTargets(baseOpts({}), candidates), RunError);
41
+ });
42
+ test("resolveTargets: ambiguous dep across workspaces without --workspace throws WorkspaceAmbiguityError", () => {
43
+ const candidates = [
44
+ outdated("lodash", "4.17.15", "4.17.21", "packages/api"),
45
+ outdated("lodash", "4.17.20", "4.17.21", "packages/web"),
46
+ ];
47
+ assert.throws(() => resolveTargets(baseOpts({ deps: ["lodash"] }), candidates), WorkspaceAmbiguityError);
48
+ });
49
+ test("resolveTargets: ambiguous dep resolved via --workspace picks the right package", () => {
50
+ const candidates = [
51
+ outdated("lodash", "4.17.15", "4.17.21", "packages/api"),
52
+ outdated("lodash", "4.17.20", "4.17.21", "packages/web"),
53
+ ];
54
+ const targets = resolveTargets(baseOpts({ deps: ["lodash"], workspace: "packages/web" }), candidates);
55
+ assert.equal(targets.length, 1);
56
+ assert.equal(targets[0].from, "4.17.20");
57
+ assert.equal(targets[0].workspacePath, "packages/web");
58
+ });
59
+ //# sourceMappingURL=batch.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.test.js","sourceRoot":"","sources":["../../src/engine/batch.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ const FETCH_TIMEOUT_MS = 8_000;
2
+ const MAX_CHANGELOG_CHARS = 6_000;
3
+ async function timedFetch(url, headers) {
4
+ const ctrl = new AbortController();
5
+ const t = setTimeout(() => ctrl.abort(), FETCH_TIMEOUT_MS);
6
+ try {
7
+ const res = await fetch(url, { signal: ctrl.signal, headers });
8
+ return res.ok ? res : null;
9
+ }
10
+ catch {
11
+ return null;
12
+ }
13
+ finally {
14
+ clearTimeout(t);
15
+ }
16
+ }
17
+ function truncate(s) {
18
+ return s.length > MAX_CHANGELOG_CHARS ? s.slice(0, MAX_CHANGELOG_CHARS) + "\n...(truncated)" : s;
19
+ }
20
+ /** Extract an `owner/repo` slug from npm's registry metadata, if it points at GitHub. */
21
+ async function githubSlug(pkgName) {
22
+ const res = await timedFetch(`https://registry.npmjs.org/${encodeURIComponent(pkgName)}/latest`);
23
+ if (!res)
24
+ return null;
25
+ const data = (await res.json().catch(() => null));
26
+ const url = typeof data?.repository === "string" ? data.repository : data?.repository?.url;
27
+ if (!url)
28
+ return null;
29
+ const m = url.match(/github\.com[/:]([\w.-]+)\/([\w.-]+?)(\.git)?$/);
30
+ return m ? `${m[1]}/${m[2]}` : null;
31
+ }
32
+ /** Try GitHub's release notes for a version tag, trying a couple of common tag formats. */
33
+ async function githubRelease(slug, version) {
34
+ for (const tag of [version, `v${version}`]) {
35
+ const res = await timedFetch(`https://api.github.com/repos/${slug}/releases/tags/${tag}`, {
36
+ Accept: "application/vnd.github+json",
37
+ });
38
+ if (!res)
39
+ continue;
40
+ const data = (await res.json().catch(() => null));
41
+ if (data?.body)
42
+ return `## ${data.name ?? tag}\n\n${data.body}`;
43
+ }
44
+ return null;
45
+ }
46
+ /**
47
+ * Best-effort fetch of release notes / changelog for the version range being
48
+ * upgraded to, to give the fix agent real migration guidance instead of
49
+ * making it guess from the error alone. Never throws — returns null on any
50
+ * failure (offline, rate-limited, no GitHub repo, etc).
51
+ */
52
+ export async function fetchChangelog(pkgName, from, to) {
53
+ try {
54
+ const slug = await githubSlug(pkgName);
55
+ if (!slug)
56
+ return null;
57
+ const notes = await githubRelease(slug, to);
58
+ if (!notes)
59
+ return null;
60
+ return truncate(notes);
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ }
66
+ //# sourceMappingURL=changelog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/engine/changelog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import { exec } from "./exec.js";
2
+ import { getAdapter } from "./pm.js";
3
+ const MAX_OUTPUT = 16_000;
4
+ function tail(s, max = MAX_OUTPUT) {
5
+ if (s.length <= max)
6
+ return s;
7
+ return "...(truncated)...\n" + s.slice(s.length - max);
8
+ }
9
+ function parseOverride(raw) {
10
+ const [cmd, ...args] = raw.split(/\s+/).filter(Boolean);
11
+ return { cmd, args };
12
+ }
13
+ /**
14
+ * Run the project's build then test command, whichever exist. Stops at the
15
+ * first failure and returns its output so the agent has something concrete
16
+ * to fix. Commands come from `--build-cmd`/`--test-cmd` when given,
17
+ * otherwise from the detected ecosystem adapter's best-effort defaults.
18
+ */
19
+ export async function runChecks(pm, cwd, overrides = {}) {
20
+ const adapter = getAdapter(pm);
21
+ const defaults = await adapter.defaultCheckCommands(cwd);
22
+ const build = overrides.buildCmd ? parseOverride(overrides.buildCmd) : defaults.build;
23
+ const test = overrides.testCmd ? parseOverride(overrides.testCmd) : defaults.test;
24
+ if (!build && !test) {
25
+ return { ok: true, output: "", unverifiable: true };
26
+ }
27
+ if (build) {
28
+ const r = await exec(build.cmd, build.args, { cwd, timeout: 300_000 });
29
+ if (r.code !== 0) {
30
+ return { ok: false, output: tail(r.combined), failedStep: "build", unverifiable: false };
31
+ }
32
+ }
33
+ if (test) {
34
+ const r = await exec(test.cmd, test.args, { cwd, timeout: 300_000 });
35
+ if (r.code !== 0) {
36
+ return { ok: false, output: tail(r.combined), failedStep: "test", unverifiable: false };
37
+ }
38
+ }
39
+ return { ok: true, output: "", unverifiable: false };
40
+ }
41
+ //# sourceMappingURL=checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.js","sourceRoot":"","sources":["../../src/engine/checks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAuB,MAAM,SAAS,CAAC;AAmB1D,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,SAAS,IAAI,CAAC,CAAS,EAAE,GAAG,GAAG,UAAU;IACvC,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,EAAkB,EAClB,GAAW,EACX,YAA4B,EAAE;IAE9B,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;IACtF,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;IAElF,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACpB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACtD,CAAC;IAED,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;QAC3F,CAAC;IACH,CAAC;IAED,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;QAC1F,CAAC;IACH,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AACvD,CAAC"}
@@ -0,0 +1,92 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtemp, writeFile, rm } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { runChecks } from "./checks.js";
7
+ async function withTmpDir(fn) {
8
+ const dir = await mkdtemp(join(tmpdir(), "greenbump-checks-"));
9
+ try {
10
+ await fn(dir);
11
+ }
12
+ finally {
13
+ await rm(dir, { recursive: true, force: true });
14
+ }
15
+ }
16
+ async function writePkg(dir, scripts) {
17
+ await writeFile(join(dir, "package.json"), JSON.stringify({ name: "tmp", version: "1.0.0", scripts }), "utf8");
18
+ }
19
+ test("runChecks: unverifiable when the adapter has no build or test script", async () => {
20
+ await withTmpDir(async (dir) => {
21
+ await writePkg(dir, {});
22
+ const r = await runChecks("npm", dir);
23
+ assert.equal(r.unverifiable, true);
24
+ assert.equal(r.ok, true);
25
+ });
26
+ });
27
+ test("runChecks: ok when build and test scripts both succeed", async () => {
28
+ await withTmpDir(async (dir) => {
29
+ await writePkg(dir, { build: "node -e \"process.exit(0)\"", test: "node -e \"process.exit(0)\"" });
30
+ const r = await runChecks("npm", dir);
31
+ assert.equal(r.ok, true);
32
+ assert.equal(r.unverifiable, false);
33
+ assert.equal(r.failedStep, undefined);
34
+ });
35
+ });
36
+ test("runChecks: stops at build failure without running test", async () => {
37
+ await withTmpDir(async (dir) => {
38
+ await writePkg(dir, {
39
+ build: "node -e \"console.error('boom'); process.exit(1)\"",
40
+ test: "node -e \"require('fs').writeFileSync('ran-test','1')\"",
41
+ });
42
+ const r = await runChecks("npm", dir);
43
+ assert.equal(r.ok, false);
44
+ assert.equal(r.failedStep, "build");
45
+ assert.match(r.output, /boom/);
46
+ await assert.rejects(async () => {
47
+ const { stat } = await import("node:fs/promises");
48
+ await stat(join(dir, "ran-test"));
49
+ });
50
+ });
51
+ });
52
+ test("runChecks: build passes, test fails — reports test as the failed step", async () => {
53
+ await withTmpDir(async (dir) => {
54
+ await writePkg(dir, {
55
+ build: "node -e \"process.exit(0)\"",
56
+ test: "node -e \"console.error('test failed'); process.exit(1)\"",
57
+ });
58
+ const r = await runChecks("npm", dir);
59
+ assert.equal(r.ok, false);
60
+ assert.equal(r.failedStep, "test");
61
+ assert.match(r.output, /test failed/);
62
+ });
63
+ });
64
+ test("runChecks: --build-cmd/--test-cmd overrides win over the adapter's own scripts", async () => {
65
+ await withTmpDir(async (dir) => {
66
+ await writePkg(dir, { build: "node -e \"process.exit(1)\"" });
67
+ const r = await runChecks("npm", dir, { buildCmd: "node -e \"process.exit(0)\"" });
68
+ assert.equal(r.ok, true);
69
+ assert.equal(r.unverifiable, false);
70
+ });
71
+ });
72
+ test("runChecks: truncates output that exceeds the max size, keeping the tail", async () => {
73
+ await withTmpDir(async (dir) => {
74
+ // Write >16_000 chars of stdout before failing, then check only the end survives.
75
+ // Use process.exitCode (not process.exit()) so Node drains stdout before exiting —
76
+ // stdout writes to a pipe are asynchronous, and a forced process.exit() right after
77
+ // thousands of console.log calls can truncate the buffer before it's flushed. That
78
+ // race is invisible on a local TTY but reliably bites in CI's piped, headless stdio.
79
+ // MARKER_END also goes through console.log (stdout), not console.error (stderr) —
80
+ // exec.ts appends to `combined` from two independent stream 'data' listeners, so
81
+ // interleaving order across stdout/stderr is not guaranteed; keeping the marker on
82
+ // the same stream as the 2000 lines guarantees it lands after them.
83
+ const script = "for (let i = 0; i < 2000; i++) console.log('line-' + i); console.log('MARKER_END'); process.exitCode = 1;";
84
+ await writePkg(dir, { build: `node -e "${script.replace(/"/g, '\\"')}"` });
85
+ const r = await runChecks("npm", dir);
86
+ assert.equal(r.ok, false);
87
+ assert.match(r.output, /MARKER_END/);
88
+ assert.ok(r.output.length <= 16_000 + 50);
89
+ assert.doesNotMatch(r.output, /line-0\b/);
90
+ });
91
+ });
92
+ //# sourceMappingURL=checks.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.test.js","sourceRoot":"","sources":["../../src/engine/checks.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { outdated } from "./pm.js";
2
+ export async function detectOutdated(pm, cwd) {
3
+ return outdated(pm, cwd);
4
+ }
5
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/engine/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAuB,MAAM,SAAS,CAAC;AAKxD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAkB,EAAE,GAAW;IAClE,OAAO,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { join } from "node:path";
2
+ import { exec } from "../exec.js";
3
+ import { pathExists } from "./types.js";
4
+ // `bundle outdated` prints lines like:
5
+ // * rails (newest 7.1.2, installed 7.0.4, requested ~> 7.0)
6
+ const OUTDATED_LINE = /^\s*\*\s*([A-Za-z0-9_.-]+)\s*\(newest\s+([^\s,]+),\s*installed\s+([^\s,)]+)/;
7
+ export function parseBundlerOutdated(stdout) {
8
+ const out = [];
9
+ for (const line of stdout.split("\n")) {
10
+ const m = OUTDATED_LINE.exec(line);
11
+ if (m && m[2] !== m[3])
12
+ out.push({ name: m[1], current: m[3], wanted: "", latest: m[2] });
13
+ }
14
+ return out;
15
+ }
16
+ export const bundlerAdapter = {
17
+ id: "bundler",
18
+ displayName: "Bundler",
19
+ manifestFiles: ["Gemfile"],
20
+ lockFiles: ["Gemfile.lock"],
21
+ verified: true,
22
+ async detect(cwd) {
23
+ return pathExists(join(cwd, "Gemfile"));
24
+ },
25
+ async outdated(cwd) {
26
+ // `bundle outdated` exits non-zero when it finds outdated gems.
27
+ const r = await exec("bundle", ["outdated"], { cwd, timeout: 120_000 });
28
+ return parseBundlerOutdated(r.stdout);
29
+ },
30
+ async install(cwd, name, version) {
31
+ // Bundler pins via the Gemfile, not a per-install flag — update the
32
+ // version constraint then let `bundle update` resolve it.
33
+ const r = await exec("bundle", ["update", name, "--conservative"], { cwd, timeout: 300_000 });
34
+ if (r.code !== 0)
35
+ return r;
36
+ return pinInGemfile(cwd, name, version, r);
37
+ },
38
+ async defaultCheckCommands(cwd) {
39
+ const hasRakefile = await pathExists(join(cwd, "Rakefile"));
40
+ return { test: { cmd: "bundle", args: hasRakefile ? ["exec", "rake", "test"] : ["exec", "rspec"] } };
41
+ },
42
+ };
43
+ async function pinInGemfile(cwd, name, version, fallback) {
44
+ const { readFile, writeFile } = await import("node:fs/promises");
45
+ try {
46
+ const path = join(cwd, "Gemfile");
47
+ const raw = await readFile(path, "utf8");
48
+ const re = new RegExp(`^(\\s*gem\\s+["']${name}["'])(.*)$`, "m");
49
+ if (re.test(raw)) {
50
+ const next = raw.replace(re, `$1, "= ${version}"`);
51
+ await writeFile(path, next, "utf8");
52
+ }
53
+ }
54
+ catch {
55
+ // best effort; `bundle update` already ran.
56
+ }
57
+ return fallback;
58
+ }
59
+ //# sourceMappingURL=bundler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundler.js","sourceRoot":"","sources":["../../../src/engine/ecosystems/bundler.ts"],"names":[],"mappings":"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"}