@fern-api/generator-cli 0.9.32 → 0.9.33
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/cli.js +128 -16
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -22126,7 +22126,7 @@ var init_diff3 = __esm({
|
|
|
22126
22126
|
}
|
|
22127
22127
|
});
|
|
22128
22128
|
|
|
22129
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.16.
|
|
22129
|
+
// ../../node_modules/.pnpm/@fern-api+replay@0.16.1/node_modules/@fern-api/replay/dist/index.js
|
|
22130
22130
|
var dist_exports = {};
|
|
22131
22131
|
__export(dist_exports, {
|
|
22132
22132
|
CREDENTIAL_PATTERNS: () => CREDENTIAL_PATTERNS,
|
|
@@ -23123,12 +23123,23 @@ async function computePerPatchDiff(patch, getCurrentGenContent, getWorkingTreeCo
|
|
|
23123
23123
|
unlocatableFiles.push(file);
|
|
23124
23124
|
continue;
|
|
23125
23125
|
}
|
|
23126
|
-
const locInCurrentGen =
|
|
23127
|
-
|
|
23128
|
-
|
|
23129
|
-
|
|
23130
|
-
|
|
23131
|
-
|
|
23126
|
+
const locInCurrentGen = [];
|
|
23127
|
+
const locInWorkingTree = [];
|
|
23128
|
+
let spanResolutionFailed = false;
|
|
23129
|
+
for (let i2 = 0; i2 < locInCurrentGenRaw.length; i2++) {
|
|
23130
|
+
const cg = resolveSpan(locInCurrentGenRaw[i2], currentGenLines, "old");
|
|
23131
|
+
const wt = resolveSpan(locInWorkingTreeRaw[i2], workingTreeLines, "new");
|
|
23132
|
+
if (cg === null || wt === null) {
|
|
23133
|
+
spanResolutionFailed = true;
|
|
23134
|
+
break;
|
|
23135
|
+
}
|
|
23136
|
+
locInCurrentGen.push(cg);
|
|
23137
|
+
locInWorkingTree.push(wt);
|
|
23138
|
+
}
|
|
23139
|
+
if (spanResolutionFailed) {
|
|
23140
|
+
unlocatableFiles.push(file);
|
|
23141
|
+
continue;
|
|
23142
|
+
}
|
|
23132
23143
|
const overlay = overlayRegions(
|
|
23133
23144
|
currentGenLines,
|
|
23134
23145
|
locInCurrentGen,
|
|
@@ -23190,11 +23201,11 @@ function resolveSpan(loc, oursLines, prefer) {
|
|
|
23190
23201
|
if (prefer === "old") {
|
|
23191
23202
|
if (oldFits) return { ...loc, oursSpan: hunk.oldCount };
|
|
23192
23203
|
if (newFits) return { ...loc, oursSpan: hunk.newCount };
|
|
23193
|
-
|
|
23194
|
-
if (newFits) return { ...loc, oursSpan: hunk.newCount };
|
|
23195
|
-
if (oldFits) return { ...loc, oursSpan: hunk.oldCount };
|
|
23204
|
+
return loc;
|
|
23196
23205
|
}
|
|
23197
|
-
return loc;
|
|
23206
|
+
if (newFits) return { ...loc, oursSpan: hunk.newCount };
|
|
23207
|
+
if (oldFits) return { ...loc, oursSpan: hunk.oldCount };
|
|
23208
|
+
return null;
|
|
23198
23209
|
}
|
|
23199
23210
|
function sequenceMatches(needle, haystack, offset) {
|
|
23200
23211
|
if (offset + needle.length > haystack.length) return false;
|
|
@@ -23947,7 +23958,7 @@ function status(outputDir) {
|
|
|
23947
23958
|
}
|
|
23948
23959
|
var import_promises3, import_os, import_path7, import_fs6, import_path8, import_yaml, import_crypto, import_path9, import_promises4, import_os2, import_path10, import_promises5, import_path11, import_promises6, import_path12, import_fs7, import_promises7, import_path13, import_promises8, import_os3, import_path14, import_child_process3, import_crypto2, import_fs8, import_path15, import_yaml2, import_crypto3, import_fs9, import_path16, import_fs10, import_promises9, import_path17, __defProp3, __getOwnPropNames3, __esm3, __export3, GitClient_exports, GitClient, init_GitClient, HybridReconstruction_exports, init_HybridReconstruction, PatchApplyTheirs_exports, init_PatchApplyTheirs, CREDENTIAL_PATTERNS, SENSITIVE_FILE_PATTERNS, FERN_BOT_NAME, FERN_BOT_EMAIL, FERN_BOT_LOGIN, FERN_SUPPORT_NAMES, LOCKFILE_HEADER, LockfileNotFoundError, LockfileManager, BINARY_EXTENSIONS, INFRASTRUCTURE_FILES, ReplayDetector, MergeAccumulator, CONFLICT_OPENER, CONFLICT_SEPARATOR, CONFLICT_CLOSER, ReplayApplicator, ReplayCommitter, FileOwnership, FirstGenerationFlow, SkipApplicationFlow, NoPatchesFlow, NormalRegenerationFlow, ReplayService, FernignoreMigrator, REPLAY_FERNIGNORE_ENTRIES, GITATTRIBUTES_ENTRIES, EMPTY_RESULT;
|
|
23949
23960
|
var init_dist3 = __esm({
|
|
23950
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.16.
|
|
23961
|
+
"../../node_modules/.pnpm/@fern-api+replay@0.16.1/node_modules/@fern-api/replay/dist/index.js"() {
|
|
23951
23962
|
"use strict";
|
|
23952
23963
|
init_esm4();
|
|
23953
23964
|
import_promises3 = require("fs/promises");
|
|
@@ -23955,6 +23966,7 @@ var init_dist3 = __esm({
|
|
|
23955
23966
|
import_path7 = require("path");
|
|
23956
23967
|
import_fs6 = require("fs");
|
|
23957
23968
|
import_path8 = require("path");
|
|
23969
|
+
init_esm3();
|
|
23958
23970
|
import_yaml = __toESM(require_dist3(), 1);
|
|
23959
23971
|
import_crypto = require("crypto");
|
|
23960
23972
|
import_path9 = require("path");
|
|
@@ -24187,10 +24199,23 @@ var init_dist3 = __esm({
|
|
|
24187
24199
|
LockfileManager = class {
|
|
24188
24200
|
outputDir;
|
|
24189
24201
|
lock = null;
|
|
24202
|
+
fernignorePatterns = [];
|
|
24190
24203
|
warnings = [];
|
|
24191
24204
|
constructor(outputDir) {
|
|
24192
24205
|
this.outputDir = outputDir;
|
|
24193
24206
|
}
|
|
24207
|
+
/**
|
|
24208
|
+
* Inform the lockfile of the customer's `.fernignore` patterns so that
|
|
24209
|
+
* `save()` can suppress its "Patch X removed from lockfile" warning when
|
|
24210
|
+
* every file in the stripped patch is already `.fernignore`-protected.
|
|
24211
|
+
* The strip itself still happens (credentials never persist); only the
|
|
24212
|
+
* customer-visible warning is suppressed in that case, because the
|
|
24213
|
+
* protected files survive the generator wipe regardless of whether the
|
|
24214
|
+
* lockfile tracks them, so there's nothing for the customer to action.
|
|
24215
|
+
*/
|
|
24216
|
+
setFernignorePatterns(patterns) {
|
|
24217
|
+
this.fernignorePatterns = patterns;
|
|
24218
|
+
}
|
|
24194
24219
|
get lockfilePath() {
|
|
24195
24220
|
return (0, import_path8.join)(this.outputDir, ".fern", "replay.lock");
|
|
24196
24221
|
}
|
|
@@ -24259,9 +24284,14 @@ var init_dist3 = __esm({
|
|
|
24259
24284
|
if (sensitiveFiles.length > 0) {
|
|
24260
24285
|
reasons.push(`sensitive files: ${sensitiveFiles.join(", ")}`);
|
|
24261
24286
|
}
|
|
24262
|
-
|
|
24263
|
-
|
|
24287
|
+
const allProtected = patch.files.length > 0 && patch.files.every(
|
|
24288
|
+
(f) => this.fernignorePatterns.some((p2) => f === p2 || minimatch(f, p2))
|
|
24264
24289
|
);
|
|
24290
|
+
if (!allProtected) {
|
|
24291
|
+
this.warnings.push(
|
|
24292
|
+
`Patch ${patch.id} removed from lockfile: ${reasons.join("; ")}. This prevents credential exposure in committed lockfiles.`
|
|
24293
|
+
);
|
|
24294
|
+
}
|
|
24265
24295
|
} else {
|
|
24266
24296
|
cleanPatches.push(patch);
|
|
24267
24297
|
}
|
|
@@ -25665,6 +25695,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
|
|
|
25665
25695
|
};
|
|
25666
25696
|
}
|
|
25667
25697
|
async apply(_prep) {
|
|
25698
|
+
this.service.lockManager.setFernignorePatterns(this.service.readFernignorePatterns());
|
|
25668
25699
|
this.service.lockManager.save();
|
|
25669
25700
|
return firstGenerationReport();
|
|
25670
25701
|
}
|
|
@@ -25711,6 +25742,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
|
|
|
25711
25742
|
};
|
|
25712
25743
|
}
|
|
25713
25744
|
async apply(_prep, options) {
|
|
25745
|
+
this.service.lockManager.setFernignorePatterns(this.service.readFernignorePatterns());
|
|
25714
25746
|
this.service.lockManager.save();
|
|
25715
25747
|
const credentialWarnings = [...this.service.lockManager.warnings];
|
|
25716
25748
|
if (!options?.stageOnly) {
|
|
@@ -25832,6 +25864,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
|
|
|
25832
25864
|
this.service.lockManager.addPatch(patch);
|
|
25833
25865
|
}
|
|
25834
25866
|
}
|
|
25867
|
+
this.service.lockManager.setFernignorePatterns(this.service.readFernignorePatterns());
|
|
25835
25868
|
this.service.lockManager.save();
|
|
25836
25869
|
this.service.warnings.push(...this.service.lockManager.warnings);
|
|
25837
25870
|
if (newPatches.length > 0) {
|
|
@@ -25992,6 +26025,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
|
|
|
25992
26025
|
}
|
|
25993
26026
|
}
|
|
25994
26027
|
}
|
|
26028
|
+
this.service.lockManager.setFernignorePatterns(this.service.readFernignorePatterns());
|
|
25995
26029
|
this.service.lockManager.save();
|
|
25996
26030
|
this.service.warnings.push(...this.service.lockManager.warnings);
|
|
25997
26031
|
if (options?.stageOnly) {
|
|
@@ -26676,6 +26710,11 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
|
|
|
26676
26710
|
(files) => this.git.exec(["diff", currentGen, "HEAD", "--", ...files]).catch(() => null)
|
|
26677
26711
|
);
|
|
26678
26712
|
if (ppResult === null) continue;
|
|
26713
|
+
if (ppResult.hadFallback) {
|
|
26714
|
+
this.warnings.push(
|
|
26715
|
+
`Patch ${patch.id}: couldn't fully isolate ${ppResult.fallbackFiles.join(", ")} \u2014 customization preserved, attribution may have merged with another patch.`
|
|
26716
|
+
);
|
|
26717
|
+
}
|
|
26679
26718
|
const diff = ppResult.diff;
|
|
26680
26719
|
if (!diff.trim()) {
|
|
26681
26720
|
if (await allPatchFilesUserOwned(patch)) continue;
|
|
@@ -26763,6 +26802,11 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
|
|
|
26763
26802
|
(files) => this.git.exec(["diff", currentGen, "HEAD", "--", ...files]).catch(() => null)
|
|
26764
26803
|
);
|
|
26765
26804
|
if (ppResult === null) continue;
|
|
26805
|
+
if (ppResult.hadFallback) {
|
|
26806
|
+
this.warnings.push(
|
|
26807
|
+
`Patch ${patch.id}: couldn't fully isolate ${ppResult.fallbackFiles.join(", ")} \u2014 customization preserved, attribution may have merged with another patch.`
|
|
26808
|
+
);
|
|
26809
|
+
}
|
|
26766
26810
|
const diff = ppResult.diff;
|
|
26767
26811
|
if (!diff.trim()) {
|
|
26768
26812
|
if (await allPatchFilesUserOwned(patch)) {
|
|
@@ -26857,6 +26901,7 @@ If you want to keep these lines, restore them in a follow-up commit and re-run r
|
|
|
26857
26901
|
}
|
|
26858
26902
|
}
|
|
26859
26903
|
}
|
|
26904
|
+
/** @internal Used by Flow implementations in `src/flows/`. */
|
|
26860
26905
|
readFernignorePatterns() {
|
|
26861
26906
|
const fernignorePath = (0, import_path13.join)(this.outputDir, ".fernignore");
|
|
26862
26907
|
if (!(0, import_fs7.existsSync)(fernignorePath)) return [];
|
|
@@ -41858,6 +41903,8 @@ var GithubStep = class extends BaseStep {
|
|
|
41858
41903
|
);
|
|
41859
41904
|
case "push":
|
|
41860
41905
|
return await this.executePushMode(repository, resolvedPrFields);
|
|
41906
|
+
case "commit-and-release":
|
|
41907
|
+
return await this.executeCommitAndReleaseMode(repository, resolvedPrFields);
|
|
41861
41908
|
default: {
|
|
41862
41909
|
const exhaustive = mode;
|
|
41863
41910
|
throw new Error(`Unexpected GitHub mode: ${String(exhaustive)}`);
|
|
@@ -42084,6 +42131,71 @@ var GithubStep = class extends BaseStep {
|
|
|
42084
42131
|
}
|
|
42085
42132
|
return result;
|
|
42086
42133
|
}
|
|
42134
|
+
async executeCommitAndReleaseMode(repository, resolved) {
|
|
42135
|
+
const baseBranch = this.config.branch ?? await repository.getDefaultBranch();
|
|
42136
|
+
if (this.config.branch != null) {
|
|
42137
|
+
this.logger.debug(`Checking out branch ${this.config.branch}`);
|
|
42138
|
+
await repository.checkout(this.config.branch);
|
|
42139
|
+
}
|
|
42140
|
+
await this.ensureFernignore();
|
|
42141
|
+
this.logger.debug("Committing changes...");
|
|
42142
|
+
await repository.commitAllChanges(resolved.commitMessage);
|
|
42143
|
+
this.logger.debug(`Committed changes to local copy of GitHub repository at ${this.outputDir}`);
|
|
42144
|
+
if (shouldCheckNoDiff(this.config)) {
|
|
42145
|
+
const noDiff = await repository.treeHashEquals(`origin/${baseBranch}`);
|
|
42146
|
+
if (noDiff) {
|
|
42147
|
+
this.logger.info("No changes detected after generation \u2014 skipping commit-and-release");
|
|
42148
|
+
return { executed: true, success: true, skippedNoDiff: true };
|
|
42149
|
+
}
|
|
42150
|
+
}
|
|
42151
|
+
const result = {
|
|
42152
|
+
executed: true,
|
|
42153
|
+
success: true
|
|
42154
|
+
};
|
|
42155
|
+
if (!this.config.previewMode) {
|
|
42156
|
+
const octokit = this.createOctokit();
|
|
42157
|
+
const { owner, repo, remote } = parseRepository(this.config.uri);
|
|
42158
|
+
await pushSignedCommit({
|
|
42159
|
+
repository,
|
|
42160
|
+
octokit,
|
|
42161
|
+
owner,
|
|
42162
|
+
repo,
|
|
42163
|
+
branch: baseBranch,
|
|
42164
|
+
force: false,
|
|
42165
|
+
rebaseOnConflict: true,
|
|
42166
|
+
author: this.config.author,
|
|
42167
|
+
logger: this.logger
|
|
42168
|
+
});
|
|
42169
|
+
const pushedBranch = await repository.getCurrentBranch();
|
|
42170
|
+
result.branchUrl = `https://${remote}/${owner}/${repo}/tree/${pushedBranch}`;
|
|
42171
|
+
this.logger.info(`Pushed branch: ${result.branchUrl}`);
|
|
42172
|
+
if (resolved.newVersion == null) {
|
|
42173
|
+
this.logger.warn(
|
|
42174
|
+
"No new version available \u2014 skipping release tag creation. Pass --version <semver> or --version AUTO to fern generate to enable release tagging."
|
|
42175
|
+
);
|
|
42176
|
+
} else {
|
|
42177
|
+
try {
|
|
42178
|
+
const tagName = resolved.newVersion;
|
|
42179
|
+
const headSha = await repository.getHeadSha();
|
|
42180
|
+
await octokit.repos.createRelease({
|
|
42181
|
+
owner,
|
|
42182
|
+
repo,
|
|
42183
|
+
tag_name: tagName,
|
|
42184
|
+
target_commitish: headSha,
|
|
42185
|
+
name: tagName,
|
|
42186
|
+
body: resolved.changelogEntry ?? resolved.commitMessage,
|
|
42187
|
+
draft: false,
|
|
42188
|
+
prerelease: false
|
|
42189
|
+
});
|
|
42190
|
+
this.logger.info(`Created GitHub release ${tagName}`);
|
|
42191
|
+
result.releaseUrl = `https://${remote}/${owner}/${repo}/releases/tag/${tagName}`;
|
|
42192
|
+
} catch (error) {
|
|
42193
|
+
this.logger.warn(`Could not create GitHub release: ${extractErrorMessage(error)}`);
|
|
42194
|
+
}
|
|
42195
|
+
}
|
|
42196
|
+
}
|
|
42197
|
+
return result;
|
|
42198
|
+
}
|
|
42087
42199
|
createOctokit() {
|
|
42088
42200
|
const opts = { auth: this.config.token };
|
|
42089
42201
|
if (this.config.apiBaseUrl != null) {
|
|
@@ -42528,9 +42640,9 @@ var PostGenerationPipeline = class {
|
|
|
42528
42640
|
this.logger = logger;
|
|
42529
42641
|
let replayEnabled = config.replay?.enabled ?? false;
|
|
42530
42642
|
let autoVersionEnabled = config.autoVersion?.enabled ?? false;
|
|
42531
|
-
if (replayEnabled && config.github?.mode === "push") {
|
|
42643
|
+
if (replayEnabled && (config.github?.mode === "push" || config.github?.mode === "commit-and-release")) {
|
|
42532
42644
|
this.logger.warn(
|
|
42533
|
-
|
|
42645
|
+
`Replay is not supported with GitHub ${config.github.mode} mode. Disabling replay to prevent push to base branch.`
|
|
42534
42646
|
);
|
|
42535
42647
|
replayEnabled = false;
|
|
42536
42648
|
}
|
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.33",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/fern-api/fern.git",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@boundaryml/baml": "^0.219.0",
|
|
26
|
-
"@fern-api/replay": "0.16.
|
|
26
|
+
"@fern-api/replay": "0.16.1",
|
|
27
27
|
"@octokit/rest": "^22.0.1",
|
|
28
28
|
"es-toolkit": "^1.45.1",
|
|
29
29
|
"semver": "^7.6.3",
|