@fern-api/generator-cli 0.9.42 → 0.9.44
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 +20 -0
- package/dist/cli.js +120 -24
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -6168,6 +6168,26 @@ var ClonedRepository = class _ClonedRepository {
|
|
|
6168
6168
|
const result = await this.git.raw(["rev-parse", `${commitSha}^{tree}`]);
|
|
6169
6169
|
return result.trim();
|
|
6170
6170
|
}
|
|
6171
|
+
async getCommitMessage(commitSha) {
|
|
6172
|
+
await this.git.cwd(this.clonePath);
|
|
6173
|
+
const result = await this.git.raw(["log", "-1", "--format=%B", commitSha]);
|
|
6174
|
+
return result.replace(/\n$/, "");
|
|
6175
|
+
}
|
|
6176
|
+
async getCommitParents(commitSha) {
|
|
6177
|
+
await this.git.cwd(this.clonePath);
|
|
6178
|
+
const result = await this.git.raw(["rev-list", "--parents", "-n", "1", commitSha]);
|
|
6179
|
+
const parts = result.trim().split(/\s+/);
|
|
6180
|
+
return parts.slice(1);
|
|
6181
|
+
}
|
|
6182
|
+
/**
|
|
6183
|
+
* Returns the SHAs of commits reachable from HEAD but not from any remote-tracking ref,
|
|
6184
|
+
* ordered oldest-first. These are the commits created locally that have not been pushed.
|
|
6185
|
+
*/
|
|
6186
|
+
async getLocalOnlyCommits() {
|
|
6187
|
+
await this.git.cwd(this.clonePath);
|
|
6188
|
+
const result = await this.git.raw(["rev-list", "--reverse", "HEAD", "--not", "--remotes=origin"]);
|
|
6189
|
+
return result.trim().split("\n").filter((line) => line.length > 0);
|
|
6190
|
+
}
|
|
6171
6191
|
/**
|
|
6172
6192
|
* Returns true if the working tree has uncommitted changes (staged or unstaged).
|
|
6173
6193
|
*/
|
package/dist/cli.js
CHANGED
|
@@ -32254,6 +32254,26 @@ var ClonedRepository = class _ClonedRepository {
|
|
|
32254
32254
|
const result = await this.git.raw(["rev-parse", `${commitSha}^{tree}`]);
|
|
32255
32255
|
return result.trim();
|
|
32256
32256
|
}
|
|
32257
|
+
async getCommitMessage(commitSha) {
|
|
32258
|
+
await this.git.cwd(this.clonePath);
|
|
32259
|
+
const result = await this.git.raw(["log", "-1", "--format=%B", commitSha]);
|
|
32260
|
+
return result.replace(/\n$/, "");
|
|
32261
|
+
}
|
|
32262
|
+
async getCommitParents(commitSha) {
|
|
32263
|
+
await this.git.cwd(this.clonePath);
|
|
32264
|
+
const result = await this.git.raw(["rev-list", "--parents", "-n", "1", commitSha]);
|
|
32265
|
+
const parts = result.trim().split(/\s+/);
|
|
32266
|
+
return parts.slice(1);
|
|
32267
|
+
}
|
|
32268
|
+
/**
|
|
32269
|
+
* Returns the SHAs of commits reachable from HEAD but not from any remote-tracking ref,
|
|
32270
|
+
* ordered oldest-first. These are the commits created locally that have not been pushed.
|
|
32271
|
+
*/
|
|
32272
|
+
async getLocalOnlyCommits() {
|
|
32273
|
+
await this.git.cwd(this.clonePath);
|
|
32274
|
+
const result = await this.git.raw(["rev-list", "--reverse", "HEAD", "--not", "--remotes=origin"]);
|
|
32275
|
+
return result.trim().split("\n").filter((line) => line.length > 0);
|
|
32276
|
+
}
|
|
32257
32277
|
/**
|
|
32258
32278
|
* Returns true if the working tree has uncommitted changes (staged or unstaged).
|
|
32259
32279
|
*/
|
|
@@ -40448,7 +40468,7 @@ var consolePipelineLogger = {
|
|
|
40448
40468
|
};
|
|
40449
40469
|
|
|
40450
40470
|
// src/pipeline/PostGenerationPipeline.ts
|
|
40451
|
-
var
|
|
40471
|
+
var import_child_process7 = require("child_process");
|
|
40452
40472
|
|
|
40453
40473
|
// src/pipeline/github/constants.ts
|
|
40454
40474
|
var FERN_BOT_NAME2 = "fern-api";
|
|
@@ -42461,6 +42481,7 @@ ${prBody}`;
|
|
|
42461
42481
|
|
|
42462
42482
|
// src/pipeline/github/pushSignedCommit.ts
|
|
42463
42483
|
var MAX_CONCURRENT_PUSH_RETRIES = 3;
|
|
42484
|
+
var MAX_SIGNED_CHAIN_LENGTH = 20;
|
|
42464
42485
|
async function pushSignedCommit({
|
|
42465
42486
|
repository,
|
|
42466
42487
|
octokit,
|
|
@@ -42475,25 +42496,19 @@ async function pushSignedCommit({
|
|
|
42475
42496
|
const tempRef = `refs/temp/fern-${Date.now()}`;
|
|
42476
42497
|
let tempRefPushed = false;
|
|
42477
42498
|
try {
|
|
42478
|
-
let
|
|
42479
|
-
repository.getHeadSha(),
|
|
42480
|
-
repository.getHeadTreeHash(),
|
|
42481
|
-
repository.getHeadCommitMessage(),
|
|
42482
|
-
repository.getHeadParents()
|
|
42483
|
-
]);
|
|
42499
|
+
let localHeadSha = await repository.getHeadSha();
|
|
42484
42500
|
await repository.pushObjectToRef(localHeadSha, tempRef);
|
|
42485
42501
|
tempRefPushed = true;
|
|
42486
42502
|
for (let attempt2 = 0; attempt2 < MAX_CONCURRENT_PUSH_RETRIES; attempt2++) {
|
|
42487
|
-
const
|
|
42488
|
-
|
|
42503
|
+
const signedSha = await signLocalCommitChain({
|
|
42504
|
+
repository,
|
|
42505
|
+
octokit,
|
|
42489
42506
|
owner,
|
|
42490
42507
|
repo,
|
|
42491
|
-
|
|
42492
|
-
|
|
42493
|
-
|
|
42494
|
-
...identityFields
|
|
42508
|
+
localHeadSha,
|
|
42509
|
+
author,
|
|
42510
|
+
logger
|
|
42495
42511
|
});
|
|
42496
|
-
const signedSha = signedCommit.sha;
|
|
42497
42512
|
try {
|
|
42498
42513
|
await upsertBranchRef({ octokit, owner, repo, branch, sha: signedSha, force });
|
|
42499
42514
|
logger.debug(`Updated refs/heads/${branch} to signed commit ${signedSha}`);
|
|
@@ -42508,12 +42523,7 @@ async function pushSignedCommit({
|
|
|
42508
42523
|
`Non-fast-forward on refs/heads/${branch} (attempt ${attempt2 + 1}/${MAX_CONCURRENT_PUSH_RETRIES}); rebasing locally and retrying.`
|
|
42509
42524
|
);
|
|
42510
42525
|
await repository.pullWithRebase(branch);
|
|
42511
|
-
|
|
42512
|
-
repository.getHeadSha(),
|
|
42513
|
-
repository.getHeadTreeHash(),
|
|
42514
|
-
repository.getHeadCommitMessage(),
|
|
42515
|
-
repository.getHeadParents()
|
|
42516
|
-
]);
|
|
42526
|
+
localHeadSha = await repository.getHeadSha();
|
|
42517
42527
|
await repository.pushObjectToRef(localHeadSha, tempRef, { force: true });
|
|
42518
42528
|
} else {
|
|
42519
42529
|
throw err;
|
|
@@ -42533,6 +42543,49 @@ async function pushSignedCommit({
|
|
|
42533
42543
|
}
|
|
42534
42544
|
}
|
|
42535
42545
|
}
|
|
42546
|
+
async function signLocalCommitChain({
|
|
42547
|
+
repository,
|
|
42548
|
+
octokit,
|
|
42549
|
+
owner,
|
|
42550
|
+
repo,
|
|
42551
|
+
localHeadSha,
|
|
42552
|
+
author,
|
|
42553
|
+
logger
|
|
42554
|
+
}) {
|
|
42555
|
+
let chain = await repository.getLocalOnlyCommits();
|
|
42556
|
+
if (chain.length === 0 || chain[chain.length - 1] !== localHeadSha) {
|
|
42557
|
+
chain = [localHeadSha];
|
|
42558
|
+
} else if (chain.length > MAX_SIGNED_CHAIN_LENGTH) {
|
|
42559
|
+
logger.warn(
|
|
42560
|
+
`Local commit chain has ${chain.length} commits (limit ${MAX_SIGNED_CHAIN_LENGTH}); signing HEAD only.`
|
|
42561
|
+
);
|
|
42562
|
+
chain = [localHeadSha];
|
|
42563
|
+
}
|
|
42564
|
+
const identityFields = author != null ? { author, committer: author } : {};
|
|
42565
|
+
const signedShaByLocalSha = /* @__PURE__ */ new Map();
|
|
42566
|
+
let signedSha = localHeadSha;
|
|
42567
|
+
for (const sha of chain) {
|
|
42568
|
+
const [treeSha, message, parents] = await Promise.all([
|
|
42569
|
+
repository.getCommitTreeHash(sha),
|
|
42570
|
+
repository.getCommitMessage(sha),
|
|
42571
|
+
repository.getCommitParents(sha)
|
|
42572
|
+
]);
|
|
42573
|
+
const { data: signedCommit } = await octokit.git.createCommit({
|
|
42574
|
+
owner,
|
|
42575
|
+
repo,
|
|
42576
|
+
message,
|
|
42577
|
+
tree: treeSha,
|
|
42578
|
+
parents: parents.map((parent) => signedShaByLocalSha.get(parent) ?? parent),
|
|
42579
|
+
...identityFields
|
|
42580
|
+
});
|
|
42581
|
+
signedShaByLocalSha.set(sha, signedCommit.sha);
|
|
42582
|
+
signedSha = signedCommit.sha;
|
|
42583
|
+
}
|
|
42584
|
+
if (chain.length > 1) {
|
|
42585
|
+
logger.debug(`Signed ${chain.length} local commits via the GitHub API`);
|
|
42586
|
+
}
|
|
42587
|
+
return signedSha;
|
|
42588
|
+
}
|
|
42536
42589
|
async function upsertBranchRef({
|
|
42537
42590
|
octokit,
|
|
42538
42591
|
owner,
|
|
@@ -43119,6 +43172,7 @@ function resolveBranchAction({
|
|
|
43119
43172
|
}
|
|
43120
43173
|
|
|
43121
43174
|
// src/pipeline/steps/ReplayStep.ts
|
|
43175
|
+
var import_child_process6 = require("child_process");
|
|
43122
43176
|
var ReplayStep = class extends BaseStep {
|
|
43123
43177
|
constructor(outputDir, logger, config, cliVersion, generatorVersions) {
|
|
43124
43178
|
super(outputDir, logger);
|
|
@@ -43159,17 +43213,21 @@ var ReplayStep = class extends BaseStep {
|
|
|
43159
43213
|
patchesWithConflicts: 0
|
|
43160
43214
|
};
|
|
43161
43215
|
}
|
|
43216
|
+
const stageOnly = this.config.stageOnly ?? false;
|
|
43162
43217
|
const result = prepared != null ? await replayApply(prepared, {
|
|
43163
|
-
stageOnly
|
|
43218
|
+
stageOnly,
|
|
43164
43219
|
logger: this.logger
|
|
43165
43220
|
}) : await replayRun({
|
|
43166
43221
|
outputDir: this.outputDir,
|
|
43167
43222
|
cliVersion: this.cliVersion,
|
|
43168
43223
|
generatorVersions: this.generatorVersions,
|
|
43169
|
-
stageOnly
|
|
43224
|
+
stageOnly,
|
|
43170
43225
|
skipApplication: this.config.skipApplication,
|
|
43171
43226
|
logger: this.logger
|
|
43172
43227
|
});
|
|
43228
|
+
if (!stageOnly) {
|
|
43229
|
+
this.commitLockfileIfUncommitted();
|
|
43230
|
+
}
|
|
43173
43231
|
if (result.failureReason != null) {
|
|
43174
43232
|
return {
|
|
43175
43233
|
executed: true,
|
|
@@ -43233,6 +43291,44 @@ var ReplayStep = class extends BaseStep {
|
|
|
43233
43291
|
warnings: report.warnings
|
|
43234
43292
|
};
|
|
43235
43293
|
}
|
|
43294
|
+
/**
|
|
43295
|
+
* Commits `.fern/replay.lock` when replay saved the lockfile to disk but
|
|
43296
|
+
* didn't create a `[fern-replay]` commit (e.g. no-patches flow with zero
|
|
43297
|
+
* new patches). Without this, `skipCommit = true` in GithubStep drops the
|
|
43298
|
+
* lockfile advance, freezing `previousGenerationSha` across runs.
|
|
43299
|
+
*/
|
|
43300
|
+
commitLockfileIfUncommitted() {
|
|
43301
|
+
try {
|
|
43302
|
+
const status2 = (0, import_child_process6.execFileSync)("git", ["status", "--porcelain", "--", ".fern/replay.lock"], {
|
|
43303
|
+
cwd: this.outputDir,
|
|
43304
|
+
encoding: "utf-8",
|
|
43305
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
43306
|
+
}).trim();
|
|
43307
|
+
if (status2.length === 0) {
|
|
43308
|
+
return;
|
|
43309
|
+
}
|
|
43310
|
+
(0, import_child_process6.execFileSync)("git", ["add", "--", ".fern/replay.lock"], {
|
|
43311
|
+
cwd: this.outputDir,
|
|
43312
|
+
stdio: "pipe"
|
|
43313
|
+
});
|
|
43314
|
+
(0, import_child_process6.execFileSync)(
|
|
43315
|
+
"git",
|
|
43316
|
+
[
|
|
43317
|
+
"-c",
|
|
43318
|
+
`user.name=${FERN_BOT_NAME2}`,
|
|
43319
|
+
"-c",
|
|
43320
|
+
`user.email=${FERN_BOT_EMAIL2}`,
|
|
43321
|
+
"commit",
|
|
43322
|
+
"-m",
|
|
43323
|
+
"[fern-replay] advance lockfile"
|
|
43324
|
+
],
|
|
43325
|
+
{ cwd: this.outputDir, stdio: "pipe" }
|
|
43326
|
+
);
|
|
43327
|
+
this.logger.debug("ReplayStep: committed uncommitted lockfile advance.");
|
|
43328
|
+
} catch (error) {
|
|
43329
|
+
this.logger.debug("ReplayStep: failed to commit lockfile advance: " + String(error));
|
|
43330
|
+
}
|
|
43331
|
+
}
|
|
43236
43332
|
};
|
|
43237
43333
|
|
|
43238
43334
|
// ../cli/generation/local-generation/docker-utils/lib/runDocker.js
|
|
@@ -43567,8 +43663,8 @@ var PostGenerationPipeline = class {
|
|
|
43567
43663
|
async run() {
|
|
43568
43664
|
if (this.config.github?.enabled) {
|
|
43569
43665
|
try {
|
|
43570
|
-
(0,
|
|
43571
|
-
(0,
|
|
43666
|
+
(0, import_child_process7.execFileSync)("git", ["config", "user.name", FERN_BOT_NAME2], { cwd: this.config.outputDir });
|
|
43667
|
+
(0, import_child_process7.execFileSync)("git", ["config", "user.email", FERN_BOT_EMAIL2], { cwd: this.config.outputDir });
|
|
43572
43668
|
} catch {
|
|
43573
43669
|
}
|
|
43574
43670
|
}
|