@fern-api/generator-cli 0.9.43 → 0.9.45
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 +222 -32
- 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
|
*/
|
|
@@ -40998,7 +41018,8 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
40998
41018
|
contentLines.push(line);
|
|
40999
41019
|
}
|
|
41000
41020
|
}
|
|
41001
|
-
let processedContent = this.
|
|
41021
|
+
let processedContent = this.removeGoModulePathSuffixPairs(contentLines);
|
|
41022
|
+
processedContent = this.removeVersionChangePairs(processedContent, mappedMagicVersion);
|
|
41002
41023
|
processedContent = this.removeRemainingMagicVersionLines(processedContent, mappedMagicVersion);
|
|
41003
41024
|
let hasChanges = false;
|
|
41004
41025
|
for (const line of processedContent) {
|
|
@@ -41134,21 +41155,85 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
41134
41155
|
* so non-Go diffs like API URL version changes are not affected.
|
|
41135
41156
|
*/
|
|
41136
41157
|
isGoModulePathSuffixChange(minusLine, plusLine) {
|
|
41137
|
-
const
|
|
41138
|
-
const
|
|
41139
|
-
|
|
41140
|
-
const goModuleDirectivePattern = /^\s*module\s+(?:github\.com|golang\.org|google\.golang\.org|gopkg\.in)\/\S+/;
|
|
41141
|
-
const hasGoModulePath = goModulePathPattern.test(minusContent) || goModulePathPattern.test(plusContent) || goModuleDirectivePattern.test(minusContent.trim()) || goModuleDirectivePattern.test(plusContent.trim());
|
|
41142
|
-
if (!hasGoModulePath) {
|
|
41158
|
+
const minus = this.analyzeGoModulePathLine(minusLine);
|
|
41159
|
+
const plus = this.analyzeGoModulePathLine(plusLine);
|
|
41160
|
+
if (minus == null || plus == null) {
|
|
41143
41161
|
return false;
|
|
41144
41162
|
}
|
|
41145
|
-
|
|
41146
|
-
const minusWithoutSuffix = minusContent.replace(suffixPattern, "");
|
|
41147
|
-
const plusWithoutSuffix = plusContent.replace(suffixPattern, "");
|
|
41148
|
-
if (minusWithoutSuffix !== plusWithoutSuffix) {
|
|
41163
|
+
if (minus.strippedContent !== plus.strippedContent) {
|
|
41149
41164
|
return false;
|
|
41150
41165
|
}
|
|
41151
|
-
return
|
|
41166
|
+
return minus.hasSuffix || plus.hasSuffix;
|
|
41167
|
+
}
|
|
41168
|
+
/**
|
|
41169
|
+
* Removes Go module path `/vN` suffix-only churn from a diff section, regardless of how the
|
|
41170
|
+
* deletion and addition lines are laid out. `removeVersionChangePairs` only removes a deletion
|
|
41171
|
+
* when it can pair it with a *nearby* addition and keeps every line in between — so a diff that
|
|
41172
|
+
* groups all deletions before all additions (as Go import blocks do) leaks the suffix churn for
|
|
41173
|
+
* every line except the first. That churn then reaches the AI diff analyzer, which sees the
|
|
41174
|
+
* previously published `/vN` module path changing on every import and misclassifies a
|
|
41175
|
+
* no-op regeneration as a breaking change (spurious major bump).
|
|
41176
|
+
*
|
|
41177
|
+
* This pass matches each suffix-bearing deletion with any suffix-only-equivalent addition in
|
|
41178
|
+
* the section (by suffix-stripped content) and drops both, so only genuine content changes to
|
|
41179
|
+
* Go module path lines survive.
|
|
41180
|
+
*/
|
|
41181
|
+
removeGoModulePathSuffixPairs(lines) {
|
|
41182
|
+
const additions = [];
|
|
41183
|
+
for (let index = 0; index < lines.length; index++) {
|
|
41184
|
+
const line = lines[index];
|
|
41185
|
+
if (line == null || !this.isAdditionLine(line)) {
|
|
41186
|
+
continue;
|
|
41187
|
+
}
|
|
41188
|
+
const info = this.analyzeGoModulePathLine(line);
|
|
41189
|
+
if (info != null) {
|
|
41190
|
+
additions.push({ index, strippedContent: info.strippedContent });
|
|
41191
|
+
}
|
|
41192
|
+
}
|
|
41193
|
+
const removed = /* @__PURE__ */ new Set();
|
|
41194
|
+
const usedAdditions = /* @__PURE__ */ new Set();
|
|
41195
|
+
for (let index = 0; index < lines.length; index++) {
|
|
41196
|
+
const line = lines[index];
|
|
41197
|
+
if (line == null || !this.isDeletionLine(line)) {
|
|
41198
|
+
continue;
|
|
41199
|
+
}
|
|
41200
|
+
const info = this.analyzeGoModulePathLine(line);
|
|
41201
|
+
if (info == null || !info.hasSuffix) {
|
|
41202
|
+
continue;
|
|
41203
|
+
}
|
|
41204
|
+
const match2 = additions.find(
|
|
41205
|
+
(addition) => !usedAdditions.has(addition.index) && addition.strippedContent === info.strippedContent
|
|
41206
|
+
);
|
|
41207
|
+
if (match2 != null) {
|
|
41208
|
+
usedAdditions.add(match2.index);
|
|
41209
|
+
removed.add(index);
|
|
41210
|
+
removed.add(match2.index);
|
|
41211
|
+
}
|
|
41212
|
+
}
|
|
41213
|
+
if (removed.size === 0) {
|
|
41214
|
+
return lines;
|
|
41215
|
+
}
|
|
41216
|
+
return lines.filter((_2, index) => !removed.has(index));
|
|
41217
|
+
}
|
|
41218
|
+
/**
|
|
41219
|
+
* If a diff line (with its leading +/- stripped) references a Go module path — either a quoted
|
|
41220
|
+
* import path or a `module` directive — returns its content with any `/vN` module-version
|
|
41221
|
+
* suffixes removed, plus whether a suffix was present. Returns undefined for non-Go lines so
|
|
41222
|
+
* unrelated diffs (e.g. API URL version segments) are never touched.
|
|
41223
|
+
*/
|
|
41224
|
+
analyzeGoModulePathLine(line) {
|
|
41225
|
+
const content = line.substring(1);
|
|
41226
|
+
const goModulePathPattern = /"[^"]*(?:github\.com|golang\.org|google\.golang\.org|gopkg\.in)\/[^"]*"/;
|
|
41227
|
+
const goModuleDirectivePattern = /^\s*module\s+(?:github\.com|golang\.org|google\.golang\.org|gopkg\.in)\/\S+/;
|
|
41228
|
+
const isGoModulePathLine = goModulePathPattern.test(content) || goModuleDirectivePattern.test(content.trim());
|
|
41229
|
+
if (!isGoModulePathLine) {
|
|
41230
|
+
return void 0;
|
|
41231
|
+
}
|
|
41232
|
+
const suffixPattern = /\/v\d+(?=\/|"|$)/g;
|
|
41233
|
+
return {
|
|
41234
|
+
strippedContent: content.replace(suffixPattern, ""),
|
|
41235
|
+
hasSuffix: suffixPattern.test(content)
|
|
41236
|
+
};
|
|
41152
41237
|
}
|
|
41153
41238
|
/**
|
|
41154
41239
|
* Gets the latest semantic version from git tags in the given repository.
|
|
@@ -42461,6 +42546,7 @@ ${prBody}`;
|
|
|
42461
42546
|
|
|
42462
42547
|
// src/pipeline/github/pushSignedCommit.ts
|
|
42463
42548
|
var MAX_CONCURRENT_PUSH_RETRIES = 3;
|
|
42549
|
+
var MAX_SIGNED_CHAIN_LENGTH = 20;
|
|
42464
42550
|
async function pushSignedCommit({
|
|
42465
42551
|
repository,
|
|
42466
42552
|
octokit,
|
|
@@ -42475,25 +42561,19 @@ async function pushSignedCommit({
|
|
|
42475
42561
|
const tempRef = `refs/temp/fern-${Date.now()}`;
|
|
42476
42562
|
let tempRefPushed = false;
|
|
42477
42563
|
try {
|
|
42478
|
-
let
|
|
42479
|
-
repository.getHeadSha(),
|
|
42480
|
-
repository.getHeadTreeHash(),
|
|
42481
|
-
repository.getHeadCommitMessage(),
|
|
42482
|
-
repository.getHeadParents()
|
|
42483
|
-
]);
|
|
42564
|
+
let localHeadSha = await repository.getHeadSha();
|
|
42484
42565
|
await repository.pushObjectToRef(localHeadSha, tempRef);
|
|
42485
42566
|
tempRefPushed = true;
|
|
42486
42567
|
for (let attempt2 = 0; attempt2 < MAX_CONCURRENT_PUSH_RETRIES; attempt2++) {
|
|
42487
|
-
const
|
|
42488
|
-
|
|
42568
|
+
const signedSha = await signLocalCommitChain({
|
|
42569
|
+
repository,
|
|
42570
|
+
octokit,
|
|
42489
42571
|
owner,
|
|
42490
42572
|
repo,
|
|
42491
|
-
|
|
42492
|
-
|
|
42493
|
-
|
|
42494
|
-
...identityFields
|
|
42573
|
+
localHeadSha,
|
|
42574
|
+
author,
|
|
42575
|
+
logger
|
|
42495
42576
|
});
|
|
42496
|
-
const signedSha = signedCommit.sha;
|
|
42497
42577
|
try {
|
|
42498
42578
|
await upsertBranchRef({ octokit, owner, repo, branch, sha: signedSha, force });
|
|
42499
42579
|
logger.debug(`Updated refs/heads/${branch} to signed commit ${signedSha}`);
|
|
@@ -42508,12 +42588,7 @@ async function pushSignedCommit({
|
|
|
42508
42588
|
`Non-fast-forward on refs/heads/${branch} (attempt ${attempt2 + 1}/${MAX_CONCURRENT_PUSH_RETRIES}); rebasing locally and retrying.`
|
|
42509
42589
|
);
|
|
42510
42590
|
await repository.pullWithRebase(branch);
|
|
42511
|
-
|
|
42512
|
-
repository.getHeadSha(),
|
|
42513
|
-
repository.getHeadTreeHash(),
|
|
42514
|
-
repository.getHeadCommitMessage(),
|
|
42515
|
-
repository.getHeadParents()
|
|
42516
|
-
]);
|
|
42591
|
+
localHeadSha = await repository.getHeadSha();
|
|
42517
42592
|
await repository.pushObjectToRef(localHeadSha, tempRef, { force: true });
|
|
42518
42593
|
} else {
|
|
42519
42594
|
throw err;
|
|
@@ -42533,6 +42608,49 @@ async function pushSignedCommit({
|
|
|
42533
42608
|
}
|
|
42534
42609
|
}
|
|
42535
42610
|
}
|
|
42611
|
+
async function signLocalCommitChain({
|
|
42612
|
+
repository,
|
|
42613
|
+
octokit,
|
|
42614
|
+
owner,
|
|
42615
|
+
repo,
|
|
42616
|
+
localHeadSha,
|
|
42617
|
+
author,
|
|
42618
|
+
logger
|
|
42619
|
+
}) {
|
|
42620
|
+
let chain = await repository.getLocalOnlyCommits();
|
|
42621
|
+
if (chain.length === 0 || chain[chain.length - 1] !== localHeadSha) {
|
|
42622
|
+
chain = [localHeadSha];
|
|
42623
|
+
} else if (chain.length > MAX_SIGNED_CHAIN_LENGTH) {
|
|
42624
|
+
logger.warn(
|
|
42625
|
+
`Local commit chain has ${chain.length} commits (limit ${MAX_SIGNED_CHAIN_LENGTH}); signing HEAD only.`
|
|
42626
|
+
);
|
|
42627
|
+
chain = [localHeadSha];
|
|
42628
|
+
}
|
|
42629
|
+
const identityFields = author != null ? { author, committer: author } : {};
|
|
42630
|
+
const signedShaByLocalSha = /* @__PURE__ */ new Map();
|
|
42631
|
+
let signedSha = localHeadSha;
|
|
42632
|
+
for (const sha of chain) {
|
|
42633
|
+
const [treeSha, message, parents] = await Promise.all([
|
|
42634
|
+
repository.getCommitTreeHash(sha),
|
|
42635
|
+
repository.getCommitMessage(sha),
|
|
42636
|
+
repository.getCommitParents(sha)
|
|
42637
|
+
]);
|
|
42638
|
+
const { data: signedCommit } = await octokit.git.createCommit({
|
|
42639
|
+
owner,
|
|
42640
|
+
repo,
|
|
42641
|
+
message,
|
|
42642
|
+
tree: treeSha,
|
|
42643
|
+
parents: parents.map((parent) => signedShaByLocalSha.get(parent) ?? parent),
|
|
42644
|
+
...identityFields
|
|
42645
|
+
});
|
|
42646
|
+
signedShaByLocalSha.set(sha, signedCommit.sha);
|
|
42647
|
+
signedSha = signedCommit.sha;
|
|
42648
|
+
}
|
|
42649
|
+
if (chain.length > 1) {
|
|
42650
|
+
logger.debug(`Signed ${chain.length} local commits via the GitHub API`);
|
|
42651
|
+
}
|
|
42652
|
+
return signedSha;
|
|
42653
|
+
}
|
|
42536
42654
|
async function upsertBranchRef({
|
|
42537
42655
|
octokit,
|
|
42538
42656
|
owner,
|
|
@@ -42793,11 +42911,16 @@ var GithubStep = class extends BaseStep {
|
|
|
42793
42911
|
throw new Error(`Unexpected branch action: ${String(_exhaustive)}`);
|
|
42794
42912
|
}
|
|
42795
42913
|
}
|
|
42914
|
+
const createdChangelog = await this.ensureChangelogFile(resolved);
|
|
42796
42915
|
if (!skipCommit) {
|
|
42797
42916
|
await this.ensureFernignore();
|
|
42798
42917
|
this.logger.debug("Committing changes...");
|
|
42799
42918
|
await repository.commitAllChanges(resolved.commitMessage);
|
|
42800
42919
|
this.logger.debug(`Committed changes to local copy of GitHub repository at ${this.outputDir}`);
|
|
42920
|
+
} else if (createdChangelog) {
|
|
42921
|
+
this.logger.debug("Committing reconstructed changelog.md on top of the replay commit...");
|
|
42922
|
+
await repository.add("changelog.md");
|
|
42923
|
+
await repository.commit(resolved.commitMessage);
|
|
42801
42924
|
}
|
|
42802
42925
|
if (shouldCheckNoDiff(this.config)) {
|
|
42803
42926
|
const noDiff = await repository.treeHashEquals(`origin/${baseBranch}`);
|
|
@@ -42838,7 +42961,20 @@ var GithubStep = class extends BaseStep {
|
|
|
42838
42961
|
}
|
|
42839
42962
|
}
|
|
42840
42963
|
const headSha = await repository.getHeadSha();
|
|
42841
|
-
const
|
|
42964
|
+
const changelogCommitted = (await repository.listTrackedFiles()).includes("changelog.md");
|
|
42965
|
+
const changelogUrl = resolveChangelogUrl({
|
|
42966
|
+
changelogEntry: resolved.changelogEntry,
|
|
42967
|
+
changelogCommitted,
|
|
42968
|
+
remote,
|
|
42969
|
+
owner,
|
|
42970
|
+
repo,
|
|
42971
|
+
headSha
|
|
42972
|
+
});
|
|
42973
|
+
if (resolved.changelogEntry && !changelogCommitted) {
|
|
42974
|
+
this.logger.warn(
|
|
42975
|
+
'changelog.md is not present in the committed tree; omitting the "See full changelog" link.'
|
|
42976
|
+
);
|
|
42977
|
+
}
|
|
42842
42978
|
const { prTitle, prBody } = parseCommitMessageForPR(
|
|
42843
42979
|
resolved.commitMessage,
|
|
42844
42980
|
resolved.changelogEntry,
|
|
@@ -42916,6 +43052,7 @@ var GithubStep = class extends BaseStep {
|
|
|
42916
43052
|
this.logger.debug(`Checking out branch ${this.config.branch}`);
|
|
42917
43053
|
await repository.checkout(this.config.branch);
|
|
42918
43054
|
}
|
|
43055
|
+
await this.ensureChangelogFile(resolved);
|
|
42919
43056
|
await this.ensureFernignore();
|
|
42920
43057
|
this.logger.debug("Committing changes...");
|
|
42921
43058
|
await repository.commitAllChanges(resolved.commitMessage);
|
|
@@ -42957,6 +43094,7 @@ var GithubStep = class extends BaseStep {
|
|
|
42957
43094
|
this.logger.debug(`Checking out branch ${this.config.branch}`);
|
|
42958
43095
|
await repository.checkout(this.config.branch);
|
|
42959
43096
|
}
|
|
43097
|
+
await this.ensureChangelogFile(resolved);
|
|
42960
43098
|
await this.ensureFernignore();
|
|
42961
43099
|
this.logger.debug("Committing changes...");
|
|
42962
43100
|
await repository.commitAllChanges(resolved.commitMessage);
|
|
@@ -43034,6 +43172,33 @@ var GithubStep = class extends BaseStep {
|
|
|
43034
43172
|
await (0, import_promises16.writeFile)(fernignorePath, "# Specify files that shouldn't be modified by Fern\n", "utf-8");
|
|
43035
43173
|
}
|
|
43036
43174
|
}
|
|
43175
|
+
/**
|
|
43176
|
+
* Guarantees `changelog.md` is present in the output directory whenever a changelog entry
|
|
43177
|
+
* exists for this run, so the file lands in the committed tree that GithubStep pushes and the
|
|
43178
|
+
* "See full changelog" link resolves. AutoVersionStep normally writes this file via
|
|
43179
|
+
* `prependChangelogEntry`; this is a safety net for paths where that write never reached the
|
|
43180
|
+
* directory GithubStep commits (e.g. non-replay self-hosted generation), which previously left
|
|
43181
|
+
* the link pointing at a non-existent blob (404).
|
|
43182
|
+
*
|
|
43183
|
+
* Returns `true` when it created the file, `false` when the file already existed (or there is
|
|
43184
|
+
* no changelog entry to write).
|
|
43185
|
+
*/
|
|
43186
|
+
async ensureChangelogFile(resolved) {
|
|
43187
|
+
const entry = resolved.changelogEntry?.trim();
|
|
43188
|
+
if (entry == null || entry.length === 0) {
|
|
43189
|
+
return false;
|
|
43190
|
+
}
|
|
43191
|
+
const changelogPath = (0, import_path24.join)(this.outputDir, "changelog.md");
|
|
43192
|
+
try {
|
|
43193
|
+
await (0, import_promises16.access)(changelogPath);
|
|
43194
|
+
return false;
|
|
43195
|
+
} catch {
|
|
43196
|
+
const version2 = resolved.newVersion ?? resolved.previousVersion;
|
|
43197
|
+
await (0, import_promises16.writeFile)(changelogPath, buildChangelogFileContents(entry, version2), "utf-8");
|
|
43198
|
+
this.logger.debug(`Wrote changelog.md${version2 != null ? ` for ${version2}` : ""}.`);
|
|
43199
|
+
return true;
|
|
43200
|
+
}
|
|
43201
|
+
}
|
|
43037
43202
|
deriveSkipCommit(replayResult) {
|
|
43038
43203
|
if (replayResult == null) {
|
|
43039
43204
|
return false;
|
|
@@ -43117,6 +43282,31 @@ function resolveBranchAction({
|
|
|
43117
43282
|
}
|
|
43118
43283
|
return "create-from-head";
|
|
43119
43284
|
}
|
|
43285
|
+
function buildChangelogFileContents(entry, version2) {
|
|
43286
|
+
const trimmed2 = entry.trim();
|
|
43287
|
+
const now = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
43288
|
+
const header = version2 != null ? `## [${version2}] - ${now}
|
|
43289
|
+
` : `## ${now}
|
|
43290
|
+
`;
|
|
43291
|
+
return `# Changelog
|
|
43292
|
+
|
|
43293
|
+
${header}${trimmed2}
|
|
43294
|
+
|
|
43295
|
+
`;
|
|
43296
|
+
}
|
|
43297
|
+
function resolveChangelogUrl({
|
|
43298
|
+
changelogEntry,
|
|
43299
|
+
changelogCommitted,
|
|
43300
|
+
remote,
|
|
43301
|
+
owner,
|
|
43302
|
+
repo,
|
|
43303
|
+
headSha
|
|
43304
|
+
}) {
|
|
43305
|
+
if (changelogEntry == null || changelogEntry.trim().length === 0 || !changelogCommitted) {
|
|
43306
|
+
return void 0;
|
|
43307
|
+
}
|
|
43308
|
+
return `https://${remote}/${owner}/${repo}/blob/${headSha}/changelog.md`;
|
|
43309
|
+
}
|
|
43120
43310
|
|
|
43121
43311
|
// src/pipeline/steps/ReplayStep.ts
|
|
43122
43312
|
var import_child_process6 = require("child_process");
|