@fern-api/generator-cli 0.9.6 → 0.9.8
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/dist/api.d.ts +7 -1
- package/dist/api.js +32 -4
- package/dist/cli.js +87 -9
- package/package.json +2 -2
package/dist/api.d.ts
CHANGED
|
@@ -536,8 +536,14 @@ interface GithubStepConfig {
|
|
|
536
536
|
changelogEntry?: string;
|
|
537
537
|
/** Structured PR description with Before/After code fences for breaking changes. Takes priority over changelogEntry for PR body. */
|
|
538
538
|
prDescription?: string;
|
|
539
|
-
/** One-sentence justification for WHY the version bump was chosen.
|
|
539
|
+
/** One-sentence justification for WHY the version bump was chosen. Shown only for breaking changes. */
|
|
540
540
|
versionBumpReason?: string;
|
|
541
|
+
/** The previous SDK version before this change (e.g. "1.2.3"). Used for version header in PR body. */
|
|
542
|
+
previousVersion?: string;
|
|
543
|
+
/** The new SDK version after this change (e.g. "1.3.0"). Used for version header in PR body. */
|
|
544
|
+
newVersion?: string;
|
|
545
|
+
/** The version bump level: MAJOR, MINOR, or PATCH. Used for version header formatting. */
|
|
546
|
+
versionBump?: string;
|
|
541
547
|
/** Skip push/PR creation, just prepare branches locally */
|
|
542
548
|
previewMode?: boolean;
|
|
543
549
|
/** Generator name for namespaced fern-generation-base tag */
|
package/dist/api.js
CHANGED
|
@@ -10122,15 +10122,37 @@ async function checkPRHasOnlyGenerationCommits(octokit, owner, repo, pullNumber,
|
|
|
10122
10122
|
}
|
|
10123
10123
|
|
|
10124
10124
|
// src/pipeline/github/parseCommitMessage.ts
|
|
10125
|
-
function parseCommitMessageForPR(commitMessage, changelogEntry, prDescription, versionBumpReason) {
|
|
10125
|
+
function parseCommitMessageForPR(commitMessage, changelogEntry, prDescription, versionBumpReason, previousVersion, newVersion, versionBump, changelogUrl) {
|
|
10126
10126
|
const lines = commitMessage.split("\n");
|
|
10127
10127
|
const prTitle = lines[0]?.trim() || "SDK Generation";
|
|
10128
10128
|
const bodyFromCommit = lines.slice(1).join("\n").trim() || "Automated SDK generation by Fern";
|
|
10129
10129
|
let prBody = prDescription?.trim() || changelogEntry?.trim() || bodyFromCommit;
|
|
10130
|
-
|
|
10131
|
-
|
|
10130
|
+
const isBreaking = versionBump === "MAJOR";
|
|
10131
|
+
if (previousVersion?.trim() && newVersion?.trim()) {
|
|
10132
|
+
const emoji = isBreaking ? "\u26A0\uFE0F " : "";
|
|
10133
|
+
const header = `## ${emoji}${previousVersion.trim()} \u2192 ${newVersion.trim()}`;
|
|
10134
|
+
if (isBreaking && versionBumpReason?.trim()) {
|
|
10135
|
+
prBody = `${header}
|
|
10136
|
+
|
|
10137
|
+
**Breaking:** ${versionBumpReason.trim()}
|
|
10138
|
+
|
|
10139
|
+
${prBody}`;
|
|
10140
|
+
} else {
|
|
10141
|
+
prBody = `${header}
|
|
10132
10142
|
|
|
10133
10143
|
${prBody}`;
|
|
10144
|
+
}
|
|
10145
|
+
} else if (isBreaking && versionBumpReason?.trim()) {
|
|
10146
|
+
prBody = `\u26A0\uFE0F **Breaking:** ${versionBumpReason.trim()}
|
|
10147
|
+
|
|
10148
|
+
${prBody}`;
|
|
10149
|
+
}
|
|
10150
|
+
if (changelogUrl?.trim()) {
|
|
10151
|
+
prBody += `
|
|
10152
|
+
|
|
10153
|
+
---
|
|
10154
|
+
|
|
10155
|
+
[See full changelog](${changelogUrl.trim()})`;
|
|
10134
10156
|
}
|
|
10135
10157
|
return { prTitle, prBody };
|
|
10136
10158
|
}
|
|
@@ -10415,11 +10437,17 @@ var GithubStep = class extends BaseStep {
|
|
|
10415
10437
|
}
|
|
10416
10438
|
}
|
|
10417
10439
|
const finalCommitMessage = this.config.commitMessage ?? "SDK Generation";
|
|
10440
|
+
const headSha = await repository.getHeadSha();
|
|
10441
|
+
const changelogUrl = this.config.changelogEntry ? `https://github.com/${this.config.uri}/blob/${headSha}/changelog.md` : void 0;
|
|
10418
10442
|
const { prTitle, prBody } = parseCommitMessageForPR(
|
|
10419
10443
|
finalCommitMessage,
|
|
10420
10444
|
this.config.changelogEntry,
|
|
10421
10445
|
this.config.prDescription,
|
|
10422
|
-
this.config.versionBumpReason
|
|
10446
|
+
this.config.versionBumpReason,
|
|
10447
|
+
this.config.previousVersion,
|
|
10448
|
+
this.config.newVersion,
|
|
10449
|
+
this.config.versionBump,
|
|
10450
|
+
changelogUrl
|
|
10423
10451
|
);
|
|
10424
10452
|
const replaySection = formatReplayPrBody(replayResult, { branchName: prBranch, repoUri: this.config.uri });
|
|
10425
10453
|
let enrichedBody = replaySection != null ? prBody + "\n\n---\n\n" + replaySection : prBody;
|
package/dist/cli.js
CHANGED
|
@@ -20098,7 +20098,7 @@ var init_diff3 = __esm({
|
|
|
20098
20098
|
}
|
|
20099
20099
|
});
|
|
20100
20100
|
|
|
20101
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.10.
|
|
20101
|
+
// ../../node_modules/.pnpm/@fern-api+replay@0.10.4/node_modules/@fern-api/replay/dist/index.js
|
|
20102
20102
|
var dist_exports = {};
|
|
20103
20103
|
__export(dist_exports, {
|
|
20104
20104
|
FERN_BOT_EMAIL: () => FERN_BOT_EMAIL2,
|
|
@@ -21063,7 +21063,7 @@ function status(outputDir) {
|
|
|
21063
21063
|
}
|
|
21064
21064
|
var import_fs6, import_path8, import_yaml, import_crypto, import_promises4, import_os, import_path9, import_fs7, import_path10, import_crypto2, import_fs8, import_path11, import_yaml2, import_crypto3, import_fs9, import_path12, import_fs10, __defProp3, __getOwnPropNames3, __esm3, __export3, GitClient_exports, GitClient, init_GitClient, HybridReconstruction_exports, init_HybridReconstruction, FERN_BOT_NAME2, FERN_BOT_EMAIL2, FERN_BOT_LOGIN2, FERN_SUPPORT_NAMES, LOCKFILE_HEADER, LockfileNotFoundError, LockfileManager, INFRASTRUCTURE_FILES, ReplayDetector, CONFLICT_OPENER, CONFLICT_SEPARATOR, CONFLICT_CLOSER, BINARY_EXTENSIONS, ReplayApplicator, ReplayCommitter, ReplayService, FernignoreMigrator, REPLAY_FERNIGNORE_ENTRIES, GITATTRIBUTES_ENTRIES, EMPTY_RESULT;
|
|
21065
21065
|
var init_dist3 = __esm({
|
|
21066
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.10.
|
|
21066
|
+
"../../node_modules/.pnpm/@fern-api+replay@0.10.4/node_modules/@fern-api/replay/dist/index.js"() {
|
|
21067
21067
|
"use strict";
|
|
21068
21068
|
init_esm4();
|
|
21069
21069
|
import_fs6 = require("fs");
|
|
@@ -21427,6 +21427,7 @@ var init_dist3 = __esm({
|
|
|
21427
21427
|
}
|
|
21428
21428
|
const log = await this.git.exec([
|
|
21429
21429
|
"log",
|
|
21430
|
+
"--first-parent",
|
|
21430
21431
|
"--format=%H%x00%an%x00%ae%x00%s",
|
|
21431
21432
|
`${lastGen.commit_sha}..HEAD`,
|
|
21432
21433
|
"--",
|
|
@@ -21442,11 +21443,20 @@ var init_dist3 = __esm({
|
|
|
21442
21443
|
if (isGenerationCommit(commit)) {
|
|
21443
21444
|
continue;
|
|
21444
21445
|
}
|
|
21445
|
-
|
|
21446
|
-
if (parents.length > 1) {
|
|
21446
|
+
if (lock.patches.find((p) => p.original_commit === commit.sha)) {
|
|
21447
21447
|
continue;
|
|
21448
21448
|
}
|
|
21449
|
-
|
|
21449
|
+
const parents = await this.git.getCommitParents(commit.sha);
|
|
21450
|
+
if (parents.length > 1) {
|
|
21451
|
+
const compositePatch = await this.createMergeCompositePatch({
|
|
21452
|
+
mergeCommit: commit,
|
|
21453
|
+
firstParent: parents[0],
|
|
21454
|
+
lastGen,
|
|
21455
|
+
lock
|
|
21456
|
+
});
|
|
21457
|
+
if (compositePatch) {
|
|
21458
|
+
newPatches.push(compositePatch);
|
|
21459
|
+
}
|
|
21450
21460
|
continue;
|
|
21451
21461
|
}
|
|
21452
21462
|
let patchContent;
|
|
@@ -21545,6 +21555,46 @@ var init_dist3 = __esm({
|
|
|
21545
21555
|
const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
|
|
21546
21556
|
return `sha256:${(0, import_crypto.createHash)("sha256").update(normalized).digest("hex")}`;
|
|
21547
21557
|
}
|
|
21558
|
+
/**
|
|
21559
|
+
* Create a single composite patch for a merge commit by diffing the merge
|
|
21560
|
+
* commit against its first parent. This captures the net change of the
|
|
21561
|
+
* entire merged branch as one patch, eliminating accumulator chaining and
|
|
21562
|
+
* zero-net-change ghost conflicts.
|
|
21563
|
+
*/
|
|
21564
|
+
async createMergeCompositePatch(input) {
|
|
21565
|
+
const { mergeCommit, firstParent, lastGen, lock } = input;
|
|
21566
|
+
const forgottenHashes = new Set(lock.forgotten_hashes ?? []);
|
|
21567
|
+
const filesOutput = await this.git.exec([
|
|
21568
|
+
"diff",
|
|
21569
|
+
"--name-only",
|
|
21570
|
+
firstParent,
|
|
21571
|
+
mergeCommit.sha
|
|
21572
|
+
]);
|
|
21573
|
+
const files = filesOutput.trim().split("\n").filter(Boolean).filter((f2) => !INFRASTRUCTURE_FILES.has(f2)).filter((f2) => !f2.startsWith(".fern/"));
|
|
21574
|
+
if (files.length === 0) return null;
|
|
21575
|
+
const diff = await this.git.exec([
|
|
21576
|
+
"diff",
|
|
21577
|
+
firstParent,
|
|
21578
|
+
mergeCommit.sha,
|
|
21579
|
+
"--",
|
|
21580
|
+
...files
|
|
21581
|
+
]);
|
|
21582
|
+
if (!diff.trim()) return null;
|
|
21583
|
+
const contentHash = this.computeContentHash(diff);
|
|
21584
|
+
if (lock.patches.some((p) => p.content_hash === contentHash) || forgottenHashes.has(contentHash)) {
|
|
21585
|
+
return null;
|
|
21586
|
+
}
|
|
21587
|
+
return {
|
|
21588
|
+
id: `patch-merge-${mergeCommit.sha.slice(0, 8)}`,
|
|
21589
|
+
content_hash: contentHash,
|
|
21590
|
+
original_commit: mergeCommit.sha,
|
|
21591
|
+
original_message: mergeCommit.message,
|
|
21592
|
+
original_author: `${mergeCommit.authorName} <${mergeCommit.authorEmail}>`,
|
|
21593
|
+
base_generation: lastGen.commit_sha,
|
|
21594
|
+
files,
|
|
21595
|
+
patch_content: diff
|
|
21596
|
+
};
|
|
21597
|
+
}
|
|
21548
21598
|
/**
|
|
21549
21599
|
* Detect patches via tree diff for non-linear history. Returns a composite patch.
|
|
21550
21600
|
* Revert reconciliation is skipped here because tree-diff produces a single composite
|
|
@@ -32982,15 +33032,37 @@ async function checkPRHasOnlyGenerationCommits(octokit, owner, repo, pullNumber,
|
|
|
32982
33032
|
}
|
|
32983
33033
|
|
|
32984
33034
|
// src/pipeline/github/parseCommitMessage.ts
|
|
32985
|
-
function parseCommitMessageForPR(commitMessage, changelogEntry, prDescription, versionBumpReason) {
|
|
33035
|
+
function parseCommitMessageForPR(commitMessage, changelogEntry, prDescription, versionBumpReason, previousVersion, newVersion, versionBump, changelogUrl) {
|
|
32986
33036
|
const lines = commitMessage.split("\n");
|
|
32987
33037
|
const prTitle = lines[0]?.trim() || "SDK Generation";
|
|
32988
33038
|
const bodyFromCommit = lines.slice(1).join("\n").trim() || "Automated SDK generation by Fern";
|
|
32989
33039
|
let prBody = prDescription?.trim() || changelogEntry?.trim() || bodyFromCommit;
|
|
32990
|
-
|
|
32991
|
-
|
|
33040
|
+
const isBreaking = versionBump === "MAJOR";
|
|
33041
|
+
if (previousVersion?.trim() && newVersion?.trim()) {
|
|
33042
|
+
const emoji = isBreaking ? "\u26A0\uFE0F " : "";
|
|
33043
|
+
const header = `## ${emoji}${previousVersion.trim()} \u2192 ${newVersion.trim()}`;
|
|
33044
|
+
if (isBreaking && versionBumpReason?.trim()) {
|
|
33045
|
+
prBody = `${header}
|
|
33046
|
+
|
|
33047
|
+
**Breaking:** ${versionBumpReason.trim()}
|
|
32992
33048
|
|
|
32993
33049
|
${prBody}`;
|
|
33050
|
+
} else {
|
|
33051
|
+
prBody = `${header}
|
|
33052
|
+
|
|
33053
|
+
${prBody}`;
|
|
33054
|
+
}
|
|
33055
|
+
} else if (isBreaking && versionBumpReason?.trim()) {
|
|
33056
|
+
prBody = `\u26A0\uFE0F **Breaking:** ${versionBumpReason.trim()}
|
|
33057
|
+
|
|
33058
|
+
${prBody}`;
|
|
33059
|
+
}
|
|
33060
|
+
if (changelogUrl?.trim()) {
|
|
33061
|
+
prBody += `
|
|
33062
|
+
|
|
33063
|
+
---
|
|
33064
|
+
|
|
33065
|
+
[See full changelog](${changelogUrl.trim()})`;
|
|
32994
33066
|
}
|
|
32995
33067
|
return { prTitle, prBody };
|
|
32996
33068
|
}
|
|
@@ -33239,11 +33311,17 @@ var GithubStep = class extends BaseStep {
|
|
|
33239
33311
|
}
|
|
33240
33312
|
}
|
|
33241
33313
|
const finalCommitMessage = this.config.commitMessage ?? "SDK Generation";
|
|
33314
|
+
const headSha = await repository.getHeadSha();
|
|
33315
|
+
const changelogUrl = this.config.changelogEntry ? `https://github.com/${this.config.uri}/blob/${headSha}/changelog.md` : void 0;
|
|
33242
33316
|
const { prTitle, prBody } = parseCommitMessageForPR(
|
|
33243
33317
|
finalCommitMessage,
|
|
33244
33318
|
this.config.changelogEntry,
|
|
33245
33319
|
this.config.prDescription,
|
|
33246
|
-
this.config.versionBumpReason
|
|
33320
|
+
this.config.versionBumpReason,
|
|
33321
|
+
this.config.previousVersion,
|
|
33322
|
+
this.config.newVersion,
|
|
33323
|
+
this.config.versionBump,
|
|
33324
|
+
changelogUrl
|
|
33247
33325
|
);
|
|
33248
33326
|
const replaySection = formatReplayPrBody(replayResult, { branchName: prBranch, repoUri: this.config.uri });
|
|
33249
33327
|
let enrichedBody = replaySection != null ? prBody + "\n\n---\n\n" + replaySection : prBody;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fern-api/generator-cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.8",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/fern-api/fern.git",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"**"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@fern-api/replay": "0.10.
|
|
25
|
+
"@fern-api/replay": "0.10.4",
|
|
26
26
|
"@octokit/rest": "^22.0.1",
|
|
27
27
|
"es-toolkit": "^1.45.1",
|
|
28
28
|
"tmp-promise": "^3.0.3"
|