@fern-api/generator-cli 0.9.13 → 0.9.15
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.js +110 -39
- package/dist/cli.js +110 -39
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -11088,14 +11088,22 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
11088
11088
|
async handleNormalFlow(params) {
|
|
11089
11089
|
const { prepared, service, language, mappedMagicVersion, previousGenerationSha } = params;
|
|
11090
11090
|
const rawDiff = this.gitDiff(previousGenerationSha, prepared.currentGenerationSha);
|
|
11091
|
-
if (rawDiff.trim().length === 0) {
|
|
11092
|
-
this.logger.info("AutoVersionStep: empty diff between generations; skipping autoversion.");
|
|
11093
|
-
return { executed: true, success: true };
|
|
11094
|
-
}
|
|
11095
11091
|
const previousVersion = await this.resolvePreviousVersion({ service, rawDiff, mappedMagicVersion });
|
|
11096
11092
|
if (previousVersion == null) {
|
|
11097
11093
|
return await this.handleFirstGeneration({ service, language, mappedMagicVersion });
|
|
11098
11094
|
}
|
|
11095
|
+
if (rawDiff.trim().length === 0) {
|
|
11096
|
+
this.logger.info(
|
|
11097
|
+
`AutoVersionStep: empty diff between generations; rewriting placeholder to ${previousVersion}.`
|
|
11098
|
+
);
|
|
11099
|
+
return await this.finalizeNoChange({
|
|
11100
|
+
service,
|
|
11101
|
+
language,
|
|
11102
|
+
mappedMagicVersion,
|
|
11103
|
+
previousVersion,
|
|
11104
|
+
reason: "no diff between generations"
|
|
11105
|
+
});
|
|
11106
|
+
}
|
|
11099
11107
|
const cleanedDiff = service.cleanDiffForAI(rawDiff, mappedMagicVersion);
|
|
11100
11108
|
const rawBytes = Buffer.byteLength(rawDiff, "utf-8");
|
|
11101
11109
|
const cleanedBytes = Buffer.byteLength(cleanedDiff, "utf-8");
|
|
@@ -11103,8 +11111,16 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
11103
11111
|
`AutoVersionStep: raw=${formatSizeKB(rawBytes)}KB (${countFilesInDiff(rawDiff)} files), cleaned=${formatSizeKB(cleanedBytes)}KB (${countFilesInDiff(cleanedDiff)} files)`
|
|
11104
11112
|
);
|
|
11105
11113
|
if (cleanedDiff.trim().length === 0) {
|
|
11106
|
-
this.logger.info(
|
|
11107
|
-
|
|
11114
|
+
this.logger.info(
|
|
11115
|
+
`AutoVersionStep: cleaned diff is empty; no semantic changes \u2014 rewriting placeholder to ${previousVersion}.`
|
|
11116
|
+
);
|
|
11117
|
+
return await this.finalizeNoChange({
|
|
11118
|
+
service,
|
|
11119
|
+
language,
|
|
11120
|
+
mappedMagicVersion,
|
|
11121
|
+
previousVersion,
|
|
11122
|
+
reason: "no semantic changes"
|
|
11123
|
+
});
|
|
11108
11124
|
}
|
|
11109
11125
|
if (cleanedBytes > MAX_RAW_DIFF_BYTES) {
|
|
11110
11126
|
this.logger.warn(
|
|
@@ -11134,13 +11150,14 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
11134
11150
|
analysis = { versionBump: "PATCH", message: this.brandMessage("SDK regeneration") };
|
|
11135
11151
|
}
|
|
11136
11152
|
if (analysis == null) {
|
|
11137
|
-
this.logger.info(
|
|
11138
|
-
return {
|
|
11139
|
-
|
|
11140
|
-
|
|
11153
|
+
this.logger.info(`AutoVersionStep: FAI returned NO_CHANGE; rewriting placeholder to ${previousVersion}.`);
|
|
11154
|
+
return await this.finalizeNoChange({
|
|
11155
|
+
service,
|
|
11156
|
+
language,
|
|
11157
|
+
mappedMagicVersion,
|
|
11141
11158
|
previousVersion,
|
|
11142
|
-
|
|
11143
|
-
};
|
|
11159
|
+
reason: "FAI returned NO_CHANGE"
|
|
11160
|
+
});
|
|
11144
11161
|
}
|
|
11145
11162
|
return await this.finalizeWithBump({
|
|
11146
11163
|
service,
|
|
@@ -11150,6 +11167,38 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
11150
11167
|
analysis
|
|
11151
11168
|
});
|
|
11152
11169
|
}
|
|
11170
|
+
/**
|
|
11171
|
+
* Terminal path for runs that determine no semver bump is needed. The
|
|
11172
|
+
* current working tree still contains `0.0.0-fern-placeholder` from this
|
|
11173
|
+
* run's generator output, so we must rewrite it to `previousVersion`
|
|
11174
|
+
* before exiting — otherwise the SDK ships with the placeholder embedded
|
|
11175
|
+
* in manifests (package.json, pyproject.toml, .fern/metadata.json) and
|
|
11176
|
+
* user-agent strings (e.g. `X-Fern-SDK-Version`). Commits the rewrite as
|
|
11177
|
+
* `[fern-autoversion]` so the replay + github steps see a stable base.
|
|
11178
|
+
*/
|
|
11179
|
+
async finalizeNoChange(params) {
|
|
11180
|
+
const { service, language, mappedMagicVersion, previousVersion, reason } = params;
|
|
11181
|
+
if (!isValidSemver(previousVersion)) {
|
|
11182
|
+
const errorMessage = `AutoVersionStep: resolved previousVersion ${JSON.stringify(previousVersion)} is not a valid semver string. Refusing to rewrite placeholder to avoid shell injection.`;
|
|
11183
|
+
this.logger.error(errorMessage);
|
|
11184
|
+
return { executed: true, success: false, errorMessage };
|
|
11185
|
+
}
|
|
11186
|
+
await service.replaceMagicVersion(this.outputDir, mappedMagicVersion, previousVersion);
|
|
11187
|
+
if (language === "go") {
|
|
11188
|
+
await service.addGoMajorVersionSuffix(this.outputDir, previousVersion);
|
|
11189
|
+
}
|
|
11190
|
+
const commitMessage = this.brandMessage(`SDK regeneration (no semver change: ${reason})`);
|
|
11191
|
+
const commitSha = this.commitAutoversion(commitMessage);
|
|
11192
|
+
return {
|
|
11193
|
+
executed: true,
|
|
11194
|
+
success: true,
|
|
11195
|
+
version: previousVersion,
|
|
11196
|
+
previousVersion,
|
|
11197
|
+
versionBump: "NO_CHANGE",
|
|
11198
|
+
commitMessage,
|
|
11199
|
+
commitSha
|
|
11200
|
+
};
|
|
11201
|
+
}
|
|
11153
11202
|
async finalizeWithBump(params) {
|
|
11154
11203
|
const { service, language, mappedMagicVersion, previousVersion, analysis } = params;
|
|
11155
11204
|
const newVersion = incrementVersion(previousVersion, analysis.versionBump);
|
|
@@ -12108,8 +12157,10 @@ var GithubStep = class extends BaseStep {
|
|
|
12108
12157
|
name = "github";
|
|
12109
12158
|
async execute(context) {
|
|
12110
12159
|
const replayResult = context.previousStepResults.replay;
|
|
12160
|
+
const autoVersionResult = context.previousStepResults.autoVersion;
|
|
12111
12161
|
const skipCommit = this.config.skipCommit ?? this.deriveSkipCommit(replayResult);
|
|
12112
12162
|
const replayConflictInfo = this.config.replayConflictInfo ?? this.deriveReplayConflictInfo(replayResult);
|
|
12163
|
+
const resolvedPrFields = this.resolvePrFields(autoVersionResult);
|
|
12113
12164
|
try {
|
|
12114
12165
|
this.logger.debug("Starting GitHub self-hosted flow in directory: " + this.outputDir);
|
|
12115
12166
|
const repository = ClonedRepository.createAtPath(this.outputDir);
|
|
@@ -12128,10 +12179,11 @@ var GithubStep = class extends BaseStep {
|
|
|
12128
12179
|
newPrBranch,
|
|
12129
12180
|
skipCommit,
|
|
12130
12181
|
replayConflictInfo,
|
|
12131
|
-
replayResult
|
|
12182
|
+
replayResult,
|
|
12183
|
+
resolvedPrFields
|
|
12132
12184
|
);
|
|
12133
12185
|
case "push":
|
|
12134
|
-
return await this.executePushMode(repository);
|
|
12186
|
+
return await this.executePushMode(repository, resolvedPrFields);
|
|
12135
12187
|
default: {
|
|
12136
12188
|
const exhaustive = mode;
|
|
12137
12189
|
throw new Error(`Unexpected GitHub mode: ${String(exhaustive)}`);
|
|
@@ -12147,7 +12199,7 @@ var GithubStep = class extends BaseStep {
|
|
|
12147
12199
|
};
|
|
12148
12200
|
}
|
|
12149
12201
|
}
|
|
12150
|
-
async executePullRequestMode(repository, newPrBranch, skipCommit, replayConflictInfo, replayResult) {
|
|
12202
|
+
async executePullRequestMode(repository, newPrBranch, skipCommit, replayConflictInfo, replayResult, resolved) {
|
|
12151
12203
|
const baseBranch = this.config.branch ?? await repository.getDefaultBranch();
|
|
12152
12204
|
const octokit = new import_rest2.Octokit({ auth: this.config.token });
|
|
12153
12205
|
const { owner, repo } = parseRepository(this.config.uri);
|
|
@@ -12181,7 +12233,7 @@ var GithubStep = class extends BaseStep {
|
|
|
12181
12233
|
generationBaseSha = await createReplayBranch(
|
|
12182
12234
|
repository,
|
|
12183
12235
|
prBranch,
|
|
12184
|
-
|
|
12236
|
+
resolved.commitMessage,
|
|
12185
12237
|
replayConflictInfo,
|
|
12186
12238
|
this.logger
|
|
12187
12239
|
);
|
|
@@ -12203,8 +12255,7 @@ var GithubStep = class extends BaseStep {
|
|
|
12203
12255
|
if (!skipCommit) {
|
|
12204
12256
|
await this.ensureFernignore();
|
|
12205
12257
|
this.logger.debug("Committing changes...");
|
|
12206
|
-
|
|
12207
|
-
await repository.commitAllChanges(finalCommitMessage2);
|
|
12258
|
+
await repository.commitAllChanges(resolved.commitMessage);
|
|
12208
12259
|
this.logger.debug(`Committed changes to local copy of GitHub repository at ${this.outputDir}`);
|
|
12209
12260
|
}
|
|
12210
12261
|
if (shouldCheckNoDiff(this.config)) {
|
|
@@ -12244,22 +12295,21 @@ var GithubStep = class extends BaseStep {
|
|
|
12244
12295
|
}
|
|
12245
12296
|
}
|
|
12246
12297
|
}
|
|
12247
|
-
const finalCommitMessage = this.config.commitMessage ?? "SDK Generation";
|
|
12248
12298
|
const headSha = await repository.getHeadSha();
|
|
12249
|
-
const changelogUrl =
|
|
12299
|
+
const changelogUrl = resolved.changelogEntry ? `https://github.com/${this.config.uri}/blob/${headSha}/changelog.md` : void 0;
|
|
12250
12300
|
const { prTitle, prBody } = parseCommitMessageForPR(
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
|
|
12255
|
-
|
|
12256
|
-
|
|
12257
|
-
|
|
12301
|
+
resolved.commitMessage,
|
|
12302
|
+
resolved.changelogEntry,
|
|
12303
|
+
resolved.prDescription,
|
|
12304
|
+
resolved.versionBumpReason,
|
|
12305
|
+
resolved.previousVersion,
|
|
12306
|
+
resolved.newVersion,
|
|
12307
|
+
resolved.versionBump,
|
|
12258
12308
|
changelogUrl
|
|
12259
12309
|
);
|
|
12260
12310
|
const replaySection = formatReplayPrBody(replayResult, { branchName: prBranch, repoUri: this.config.uri });
|
|
12261
12311
|
let enrichedBody = replaySection != null ? prBody + "\n\n---\n\n" + replaySection : prBody;
|
|
12262
|
-
enrichedBody = enrichPrBodyForAutomation(enrichedBody, this.config);
|
|
12312
|
+
enrichedBody = enrichPrBodyForAutomation(enrichedBody, this.config, resolved);
|
|
12263
12313
|
if (isUpdatingExistingPR && existingPR != null) {
|
|
12264
12314
|
this.logger.info(`Updated existing pull request: ${existingPR.htmlUrl}`);
|
|
12265
12315
|
result.prUrl = existingPR.htmlUrl;
|
|
@@ -12290,7 +12340,7 @@ var GithubStep = class extends BaseStep {
|
|
|
12290
12340
|
this.logger.info(`Created pull request: ${pullRequest.html_url}`);
|
|
12291
12341
|
result.prUrl = pullRequest.html_url;
|
|
12292
12342
|
result.prNumber = pullRequest.number;
|
|
12293
|
-
if (shouldEnableAutomerge(this.config) && pullRequest.node_id) {
|
|
12343
|
+
if (shouldEnableAutomerge(this.config, resolved) && pullRequest.node_id) {
|
|
12294
12344
|
try {
|
|
12295
12345
|
await octokit.graphql(
|
|
12296
12346
|
`mutation($pullRequestId: ID!) {
|
|
@@ -12318,7 +12368,7 @@ var GithubStep = class extends BaseStep {
|
|
|
12318
12368
|
}
|
|
12319
12369
|
return result;
|
|
12320
12370
|
}
|
|
12321
|
-
async executePushMode(repository) {
|
|
12371
|
+
async executePushMode(repository, resolved) {
|
|
12322
12372
|
const baseBranch = this.config.branch ?? await repository.getDefaultBranch();
|
|
12323
12373
|
if (this.config.branch != null) {
|
|
12324
12374
|
this.logger.debug(`Checking out branch ${this.config.branch}`);
|
|
@@ -12326,8 +12376,7 @@ var GithubStep = class extends BaseStep {
|
|
|
12326
12376
|
}
|
|
12327
12377
|
await this.ensureFernignore();
|
|
12328
12378
|
this.logger.debug("Committing changes...");
|
|
12329
|
-
|
|
12330
|
-
await repository.commitAllChanges(finalCommitMessage);
|
|
12379
|
+
await repository.commitAllChanges(resolved.commitMessage);
|
|
12331
12380
|
this.logger.debug(`Committed changes to local copy of GitHub repository at ${this.outputDir}`);
|
|
12332
12381
|
if (shouldCheckNoDiff(this.config)) {
|
|
12333
12382
|
const noDiff = await repository.treeHashEquals(`origin/${baseBranch}`);
|
|
@@ -12390,14 +12439,33 @@ var GithubStep = class extends BaseStep {
|
|
|
12390
12439
|
}
|
|
12391
12440
|
return void 0;
|
|
12392
12441
|
}
|
|
12442
|
+
resolvePrFields(autoVersion) {
|
|
12443
|
+
return resolvePrFields(this.config, autoVersion);
|
|
12444
|
+
}
|
|
12393
12445
|
};
|
|
12394
|
-
function
|
|
12446
|
+
function resolvePrFields(config, autoVersion) {
|
|
12447
|
+
const autoVersionBreaking = autoVersion?.versionBump === "MAJOR";
|
|
12448
|
+
return {
|
|
12449
|
+
commitMessage: config.commitMessage ?? autoVersion?.commitMessage ?? "SDK Generation",
|
|
12450
|
+
changelogEntry: config.changelogEntry ?? autoVersion?.changelogEntry,
|
|
12451
|
+
prDescription: config.prDescription ?? autoVersion?.prDescription,
|
|
12452
|
+
versionBumpReason: config.versionBumpReason ?? autoVersion?.versionBumpReason,
|
|
12453
|
+
previousVersion: config.previousVersion ?? autoVersion?.previousVersion,
|
|
12454
|
+
newVersion: config.newVersion ?? autoVersion?.version,
|
|
12455
|
+
versionBump: config.versionBump ?? autoVersion?.versionBump,
|
|
12456
|
+
hasBreakingChanges: config.hasBreakingChanges ?? autoVersionBreaking,
|
|
12457
|
+
breakingChangesSummary: config.breakingChangesSummary ?? autoVersion?.prDescription
|
|
12458
|
+
};
|
|
12459
|
+
}
|
|
12460
|
+
function enrichPrBodyForAutomation(body, config, breaking = {}) {
|
|
12395
12461
|
if (!config.automationMode) {
|
|
12396
12462
|
return body;
|
|
12397
12463
|
}
|
|
12464
|
+
const hasBreakingChanges = breaking.hasBreakingChanges ?? config.hasBreakingChanges;
|
|
12465
|
+
const breakingChangesSummary = breaking.breakingChangesSummary ?? config.breakingChangesSummary;
|
|
12398
12466
|
let result = body;
|
|
12399
|
-
if (
|
|
12400
|
-
result += "\n\n---\n\n## \u26A0\uFE0F Breaking Changes\n\nThis release contains breaking changes that require manual review:\n\n" +
|
|
12467
|
+
if (hasBreakingChanges && breakingChangesSummary) {
|
|
12468
|
+
result += "\n\n---\n\n## \u26A0\uFE0F Breaking Changes\n\nThis release contains breaking changes that require manual review:\n\n" + breakingChangesSummary;
|
|
12401
12469
|
}
|
|
12402
12470
|
if (config.runId) {
|
|
12403
12471
|
result += `
|
|
@@ -12408,8 +12476,9 @@ _Fern Run ID: \`${config.runId}\`_`;
|
|
|
12408
12476
|
}
|
|
12409
12477
|
return result;
|
|
12410
12478
|
}
|
|
12411
|
-
function shouldEnableAutomerge(config) {
|
|
12412
|
-
|
|
12479
|
+
function shouldEnableAutomerge(config, breaking = {}) {
|
|
12480
|
+
const hasBreakingChanges = breaking.hasBreakingChanges ?? config.hasBreakingChanges;
|
|
12481
|
+
return config.automationMode === true && config.autoMerge === true && hasBreakingChanges !== true;
|
|
12413
12482
|
}
|
|
12414
12483
|
function shouldCheckNoDiff(config) {
|
|
12415
12484
|
return config.skipIfNoDiff === true;
|
|
@@ -12585,8 +12654,10 @@ var PostGenerationPipeline = class {
|
|
|
12585
12654
|
try {
|
|
12586
12655
|
const stepResult = await step.execute(pipelineContext);
|
|
12587
12656
|
if (step.name === "generationCommit") {
|
|
12588
|
-
|
|
12589
|
-
|
|
12657
|
+
const gcResult = stepResult;
|
|
12658
|
+
const { preparedReplay: _preparedReplay, ...serializable } = gcResult;
|
|
12659
|
+
result.steps.generationCommit = serializable;
|
|
12660
|
+
pipelineContext.previousStepResults.generationCommit = gcResult;
|
|
12590
12661
|
} else if (step.name === "replay") {
|
|
12591
12662
|
result.steps.replay = stepResult;
|
|
12592
12663
|
pipelineContext.previousStepResults.replay = stepResult;
|
package/dist/cli.js
CHANGED
|
@@ -39176,14 +39176,22 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
39176
39176
|
async handleNormalFlow(params) {
|
|
39177
39177
|
const { prepared, service, language, mappedMagicVersion, previousGenerationSha } = params;
|
|
39178
39178
|
const rawDiff = this.gitDiff(previousGenerationSha, prepared.currentGenerationSha);
|
|
39179
|
-
if (rawDiff.trim().length === 0) {
|
|
39180
|
-
this.logger.info("AutoVersionStep: empty diff between generations; skipping autoversion.");
|
|
39181
|
-
return { executed: true, success: true };
|
|
39182
|
-
}
|
|
39183
39179
|
const previousVersion = await this.resolvePreviousVersion({ service, rawDiff, mappedMagicVersion });
|
|
39184
39180
|
if (previousVersion == null) {
|
|
39185
39181
|
return await this.handleFirstGeneration({ service, language, mappedMagicVersion });
|
|
39186
39182
|
}
|
|
39183
|
+
if (rawDiff.trim().length === 0) {
|
|
39184
|
+
this.logger.info(
|
|
39185
|
+
`AutoVersionStep: empty diff between generations; rewriting placeholder to ${previousVersion}.`
|
|
39186
|
+
);
|
|
39187
|
+
return await this.finalizeNoChange({
|
|
39188
|
+
service,
|
|
39189
|
+
language,
|
|
39190
|
+
mappedMagicVersion,
|
|
39191
|
+
previousVersion,
|
|
39192
|
+
reason: "no diff between generations"
|
|
39193
|
+
});
|
|
39194
|
+
}
|
|
39187
39195
|
const cleanedDiff = service.cleanDiffForAI(rawDiff, mappedMagicVersion);
|
|
39188
39196
|
const rawBytes = Buffer.byteLength(rawDiff, "utf-8");
|
|
39189
39197
|
const cleanedBytes = Buffer.byteLength(cleanedDiff, "utf-8");
|
|
@@ -39191,8 +39199,16 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
39191
39199
|
`AutoVersionStep: raw=${formatSizeKB(rawBytes)}KB (${countFilesInDiff(rawDiff)} files), cleaned=${formatSizeKB(cleanedBytes)}KB (${countFilesInDiff(cleanedDiff)} files)`
|
|
39192
39200
|
);
|
|
39193
39201
|
if (cleanedDiff.trim().length === 0) {
|
|
39194
|
-
this.logger.info(
|
|
39195
|
-
|
|
39202
|
+
this.logger.info(
|
|
39203
|
+
`AutoVersionStep: cleaned diff is empty; no semantic changes \u2014 rewriting placeholder to ${previousVersion}.`
|
|
39204
|
+
);
|
|
39205
|
+
return await this.finalizeNoChange({
|
|
39206
|
+
service,
|
|
39207
|
+
language,
|
|
39208
|
+
mappedMagicVersion,
|
|
39209
|
+
previousVersion,
|
|
39210
|
+
reason: "no semantic changes"
|
|
39211
|
+
});
|
|
39196
39212
|
}
|
|
39197
39213
|
if (cleanedBytes > MAX_RAW_DIFF_BYTES) {
|
|
39198
39214
|
this.logger.warn(
|
|
@@ -39222,13 +39238,14 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
39222
39238
|
analysis = { versionBump: "PATCH", message: this.brandMessage("SDK regeneration") };
|
|
39223
39239
|
}
|
|
39224
39240
|
if (analysis == null) {
|
|
39225
|
-
this.logger.info(
|
|
39226
|
-
return {
|
|
39227
|
-
|
|
39228
|
-
|
|
39241
|
+
this.logger.info(`AutoVersionStep: FAI returned NO_CHANGE; rewriting placeholder to ${previousVersion}.`);
|
|
39242
|
+
return await this.finalizeNoChange({
|
|
39243
|
+
service,
|
|
39244
|
+
language,
|
|
39245
|
+
mappedMagicVersion,
|
|
39229
39246
|
previousVersion,
|
|
39230
|
-
|
|
39231
|
-
};
|
|
39247
|
+
reason: "FAI returned NO_CHANGE"
|
|
39248
|
+
});
|
|
39232
39249
|
}
|
|
39233
39250
|
return await this.finalizeWithBump({
|
|
39234
39251
|
service,
|
|
@@ -39238,6 +39255,38 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
39238
39255
|
analysis
|
|
39239
39256
|
});
|
|
39240
39257
|
}
|
|
39258
|
+
/**
|
|
39259
|
+
* Terminal path for runs that determine no semver bump is needed. The
|
|
39260
|
+
* current working tree still contains `0.0.0-fern-placeholder` from this
|
|
39261
|
+
* run's generator output, so we must rewrite it to `previousVersion`
|
|
39262
|
+
* before exiting — otherwise the SDK ships with the placeholder embedded
|
|
39263
|
+
* in manifests (package.json, pyproject.toml, .fern/metadata.json) and
|
|
39264
|
+
* user-agent strings (e.g. `X-Fern-SDK-Version`). Commits the rewrite as
|
|
39265
|
+
* `[fern-autoversion]` so the replay + github steps see a stable base.
|
|
39266
|
+
*/
|
|
39267
|
+
async finalizeNoChange(params) {
|
|
39268
|
+
const { service, language, mappedMagicVersion, previousVersion, reason } = params;
|
|
39269
|
+
if (!isValidSemver(previousVersion)) {
|
|
39270
|
+
const errorMessage = `AutoVersionStep: resolved previousVersion ${JSON.stringify(previousVersion)} is not a valid semver string. Refusing to rewrite placeholder to avoid shell injection.`;
|
|
39271
|
+
this.logger.error(errorMessage);
|
|
39272
|
+
return { executed: true, success: false, errorMessage };
|
|
39273
|
+
}
|
|
39274
|
+
await service.replaceMagicVersion(this.outputDir, mappedMagicVersion, previousVersion);
|
|
39275
|
+
if (language === "go") {
|
|
39276
|
+
await service.addGoMajorVersionSuffix(this.outputDir, previousVersion);
|
|
39277
|
+
}
|
|
39278
|
+
const commitMessage = this.brandMessage(`SDK regeneration (no semver change: ${reason})`);
|
|
39279
|
+
const commitSha = this.commitAutoversion(commitMessage);
|
|
39280
|
+
return {
|
|
39281
|
+
executed: true,
|
|
39282
|
+
success: true,
|
|
39283
|
+
version: previousVersion,
|
|
39284
|
+
previousVersion,
|
|
39285
|
+
versionBump: "NO_CHANGE",
|
|
39286
|
+
commitMessage,
|
|
39287
|
+
commitSha
|
|
39288
|
+
};
|
|
39289
|
+
}
|
|
39241
39290
|
async finalizeWithBump(params) {
|
|
39242
39291
|
const { service, language, mappedMagicVersion, previousVersion, analysis } = params;
|
|
39243
39292
|
const newVersion = incrementVersion(previousVersion, analysis.versionBump);
|
|
@@ -40159,8 +40208,10 @@ var GithubStep = class extends BaseStep {
|
|
|
40159
40208
|
name = "github";
|
|
40160
40209
|
async execute(context) {
|
|
40161
40210
|
const replayResult = context.previousStepResults.replay;
|
|
40211
|
+
const autoVersionResult = context.previousStepResults.autoVersion;
|
|
40162
40212
|
const skipCommit = this.config.skipCommit ?? this.deriveSkipCommit(replayResult);
|
|
40163
40213
|
const replayConflictInfo = this.config.replayConflictInfo ?? this.deriveReplayConflictInfo(replayResult);
|
|
40214
|
+
const resolvedPrFields = this.resolvePrFields(autoVersionResult);
|
|
40164
40215
|
try {
|
|
40165
40216
|
this.logger.debug("Starting GitHub self-hosted flow in directory: " + this.outputDir);
|
|
40166
40217
|
const repository = ClonedRepository.createAtPath(this.outputDir);
|
|
@@ -40179,10 +40230,11 @@ var GithubStep = class extends BaseStep {
|
|
|
40179
40230
|
newPrBranch,
|
|
40180
40231
|
skipCommit,
|
|
40181
40232
|
replayConflictInfo,
|
|
40182
|
-
replayResult
|
|
40233
|
+
replayResult,
|
|
40234
|
+
resolvedPrFields
|
|
40183
40235
|
);
|
|
40184
40236
|
case "push":
|
|
40185
|
-
return await this.executePushMode(repository);
|
|
40237
|
+
return await this.executePushMode(repository, resolvedPrFields);
|
|
40186
40238
|
default: {
|
|
40187
40239
|
const exhaustive = mode;
|
|
40188
40240
|
throw new Error(`Unexpected GitHub mode: ${String(exhaustive)}`);
|
|
@@ -40198,7 +40250,7 @@ var GithubStep = class extends BaseStep {
|
|
|
40198
40250
|
};
|
|
40199
40251
|
}
|
|
40200
40252
|
}
|
|
40201
|
-
async executePullRequestMode(repository, newPrBranch, skipCommit, replayConflictInfo, replayResult) {
|
|
40253
|
+
async executePullRequestMode(repository, newPrBranch, skipCommit, replayConflictInfo, replayResult, resolved) {
|
|
40202
40254
|
const baseBranch = this.config.branch ?? await repository.getDefaultBranch();
|
|
40203
40255
|
const octokit = new Octokit2({ auth: this.config.token });
|
|
40204
40256
|
const { owner, repo } = parseRepository(this.config.uri);
|
|
@@ -40232,7 +40284,7 @@ var GithubStep = class extends BaseStep {
|
|
|
40232
40284
|
generationBaseSha = await createReplayBranch(
|
|
40233
40285
|
repository,
|
|
40234
40286
|
prBranch,
|
|
40235
|
-
|
|
40287
|
+
resolved.commitMessage,
|
|
40236
40288
|
replayConflictInfo,
|
|
40237
40289
|
this.logger
|
|
40238
40290
|
);
|
|
@@ -40254,8 +40306,7 @@ var GithubStep = class extends BaseStep {
|
|
|
40254
40306
|
if (!skipCommit) {
|
|
40255
40307
|
await this.ensureFernignore();
|
|
40256
40308
|
this.logger.debug("Committing changes...");
|
|
40257
|
-
|
|
40258
|
-
await repository.commitAllChanges(finalCommitMessage2);
|
|
40309
|
+
await repository.commitAllChanges(resolved.commitMessage);
|
|
40259
40310
|
this.logger.debug(`Committed changes to local copy of GitHub repository at ${this.outputDir}`);
|
|
40260
40311
|
}
|
|
40261
40312
|
if (shouldCheckNoDiff(this.config)) {
|
|
@@ -40295,22 +40346,21 @@ var GithubStep = class extends BaseStep {
|
|
|
40295
40346
|
}
|
|
40296
40347
|
}
|
|
40297
40348
|
}
|
|
40298
|
-
const finalCommitMessage = this.config.commitMessage ?? "SDK Generation";
|
|
40299
40349
|
const headSha = await repository.getHeadSha();
|
|
40300
|
-
const changelogUrl =
|
|
40350
|
+
const changelogUrl = resolved.changelogEntry ? `https://github.com/${this.config.uri}/blob/${headSha}/changelog.md` : void 0;
|
|
40301
40351
|
const { prTitle, prBody } = parseCommitMessageForPR(
|
|
40302
|
-
|
|
40303
|
-
|
|
40304
|
-
|
|
40305
|
-
|
|
40306
|
-
|
|
40307
|
-
|
|
40308
|
-
|
|
40352
|
+
resolved.commitMessage,
|
|
40353
|
+
resolved.changelogEntry,
|
|
40354
|
+
resolved.prDescription,
|
|
40355
|
+
resolved.versionBumpReason,
|
|
40356
|
+
resolved.previousVersion,
|
|
40357
|
+
resolved.newVersion,
|
|
40358
|
+
resolved.versionBump,
|
|
40309
40359
|
changelogUrl
|
|
40310
40360
|
);
|
|
40311
40361
|
const replaySection = formatReplayPrBody(replayResult, { branchName: prBranch, repoUri: this.config.uri });
|
|
40312
40362
|
let enrichedBody = replaySection != null ? prBody + "\n\n---\n\n" + replaySection : prBody;
|
|
40313
|
-
enrichedBody = enrichPrBodyForAutomation(enrichedBody, this.config);
|
|
40363
|
+
enrichedBody = enrichPrBodyForAutomation(enrichedBody, this.config, resolved);
|
|
40314
40364
|
if (isUpdatingExistingPR && existingPR != null) {
|
|
40315
40365
|
this.logger.info(`Updated existing pull request: ${existingPR.htmlUrl}`);
|
|
40316
40366
|
result.prUrl = existingPR.htmlUrl;
|
|
@@ -40341,7 +40391,7 @@ var GithubStep = class extends BaseStep {
|
|
|
40341
40391
|
this.logger.info(`Created pull request: ${pullRequest.html_url}`);
|
|
40342
40392
|
result.prUrl = pullRequest.html_url;
|
|
40343
40393
|
result.prNumber = pullRequest.number;
|
|
40344
|
-
if (shouldEnableAutomerge(this.config) && pullRequest.node_id) {
|
|
40394
|
+
if (shouldEnableAutomerge(this.config, resolved) && pullRequest.node_id) {
|
|
40345
40395
|
try {
|
|
40346
40396
|
await octokit.graphql(
|
|
40347
40397
|
`mutation($pullRequestId: ID!) {
|
|
@@ -40369,7 +40419,7 @@ var GithubStep = class extends BaseStep {
|
|
|
40369
40419
|
}
|
|
40370
40420
|
return result;
|
|
40371
40421
|
}
|
|
40372
|
-
async executePushMode(repository) {
|
|
40422
|
+
async executePushMode(repository, resolved) {
|
|
40373
40423
|
const baseBranch = this.config.branch ?? await repository.getDefaultBranch();
|
|
40374
40424
|
if (this.config.branch != null) {
|
|
40375
40425
|
this.logger.debug(`Checking out branch ${this.config.branch}`);
|
|
@@ -40377,8 +40427,7 @@ var GithubStep = class extends BaseStep {
|
|
|
40377
40427
|
}
|
|
40378
40428
|
await this.ensureFernignore();
|
|
40379
40429
|
this.logger.debug("Committing changes...");
|
|
40380
|
-
|
|
40381
|
-
await repository.commitAllChanges(finalCommitMessage);
|
|
40430
|
+
await repository.commitAllChanges(resolved.commitMessage);
|
|
40382
40431
|
this.logger.debug(`Committed changes to local copy of GitHub repository at ${this.outputDir}`);
|
|
40383
40432
|
if (shouldCheckNoDiff(this.config)) {
|
|
40384
40433
|
const noDiff = await repository.treeHashEquals(`origin/${baseBranch}`);
|
|
@@ -40441,14 +40490,33 @@ var GithubStep = class extends BaseStep {
|
|
|
40441
40490
|
}
|
|
40442
40491
|
return void 0;
|
|
40443
40492
|
}
|
|
40493
|
+
resolvePrFields(autoVersion) {
|
|
40494
|
+
return resolvePrFields(this.config, autoVersion);
|
|
40495
|
+
}
|
|
40444
40496
|
};
|
|
40445
|
-
function
|
|
40497
|
+
function resolvePrFields(config, autoVersion) {
|
|
40498
|
+
const autoVersionBreaking = autoVersion?.versionBump === "MAJOR";
|
|
40499
|
+
return {
|
|
40500
|
+
commitMessage: config.commitMessage ?? autoVersion?.commitMessage ?? "SDK Generation",
|
|
40501
|
+
changelogEntry: config.changelogEntry ?? autoVersion?.changelogEntry,
|
|
40502
|
+
prDescription: config.prDescription ?? autoVersion?.prDescription,
|
|
40503
|
+
versionBumpReason: config.versionBumpReason ?? autoVersion?.versionBumpReason,
|
|
40504
|
+
previousVersion: config.previousVersion ?? autoVersion?.previousVersion,
|
|
40505
|
+
newVersion: config.newVersion ?? autoVersion?.version,
|
|
40506
|
+
versionBump: config.versionBump ?? autoVersion?.versionBump,
|
|
40507
|
+
hasBreakingChanges: config.hasBreakingChanges ?? autoVersionBreaking,
|
|
40508
|
+
breakingChangesSummary: config.breakingChangesSummary ?? autoVersion?.prDescription
|
|
40509
|
+
};
|
|
40510
|
+
}
|
|
40511
|
+
function enrichPrBodyForAutomation(body, config, breaking = {}) {
|
|
40446
40512
|
if (!config.automationMode) {
|
|
40447
40513
|
return body;
|
|
40448
40514
|
}
|
|
40515
|
+
const hasBreakingChanges = breaking.hasBreakingChanges ?? config.hasBreakingChanges;
|
|
40516
|
+
const breakingChangesSummary = breaking.breakingChangesSummary ?? config.breakingChangesSummary;
|
|
40449
40517
|
let result = body;
|
|
40450
|
-
if (
|
|
40451
|
-
result += "\n\n---\n\n## \u26A0\uFE0F Breaking Changes\n\nThis release contains breaking changes that require manual review:\n\n" +
|
|
40518
|
+
if (hasBreakingChanges && breakingChangesSummary) {
|
|
40519
|
+
result += "\n\n---\n\n## \u26A0\uFE0F Breaking Changes\n\nThis release contains breaking changes that require manual review:\n\n" + breakingChangesSummary;
|
|
40452
40520
|
}
|
|
40453
40521
|
if (config.runId) {
|
|
40454
40522
|
result += `
|
|
@@ -40459,8 +40527,9 @@ _Fern Run ID: \`${config.runId}\`_`;
|
|
|
40459
40527
|
}
|
|
40460
40528
|
return result;
|
|
40461
40529
|
}
|
|
40462
|
-
function shouldEnableAutomerge(config) {
|
|
40463
|
-
|
|
40530
|
+
function shouldEnableAutomerge(config, breaking = {}) {
|
|
40531
|
+
const hasBreakingChanges = breaking.hasBreakingChanges ?? config.hasBreakingChanges;
|
|
40532
|
+
return config.automationMode === true && config.autoMerge === true && hasBreakingChanges !== true;
|
|
40464
40533
|
}
|
|
40465
40534
|
function shouldCheckNoDiff(config) {
|
|
40466
40535
|
return config.skipIfNoDiff === true;
|
|
@@ -40636,8 +40705,10 @@ var PostGenerationPipeline = class {
|
|
|
40636
40705
|
try {
|
|
40637
40706
|
const stepResult = await step.execute(pipelineContext);
|
|
40638
40707
|
if (step.name === "generationCommit") {
|
|
40639
|
-
|
|
40640
|
-
|
|
40708
|
+
const gcResult = stepResult;
|
|
40709
|
+
const { preparedReplay: _preparedReplay, ...serializable } = gcResult;
|
|
40710
|
+
result.steps.generationCommit = serializable;
|
|
40711
|
+
pipelineContext.previousStepResults.generationCommit = gcResult;
|
|
40641
40712
|
} else if (step.name === "replay") {
|
|
40642
40713
|
result.steps.replay = stepResult;
|
|
40643
40714
|
pipelineContext.previousStepResults.replay = stepResult;
|