Skip to content

Commit 223880c

Browse files
chore: add biomejs, replace eslint with biome for linting and formatting
Co-Authored-By: Niels Swimberghe <3382717+Swimburger@users.noreply.github.com>
1 parent 8a31f0c commit 223880c

8 files changed

Lines changed: 373 additions & 158 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ jobs:
2020
- name: Install dependencies
2121
run: npm ci
2222

23+
- name: Lint
24+
run: npm run lint
25+
2326
- name: Run tests
2427
run: npx vitest run
2528

biome.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/2.4.5/schema.json",
3+
"vcs": {
4+
"enabled": true,
5+
"clientKind": "git",
6+
"useIgnoreFile": true
7+
},
8+
"files": {
9+
"includes": ["**", "!!**/dist"]
10+
},
11+
"formatter": {
12+
"enabled": true,
13+
"indentStyle": "space",
14+
"indentWidth": 4
15+
},
16+
"linter": {
17+
"enabled": true,
18+
"rules": {
19+
"recommended": true,
20+
"suspicious": {
21+
"noExplicitAny": "off"
22+
}
23+
}
24+
},
25+
"javascript": {
26+
"formatter": {
27+
"quoteStyle": "double"
28+
}
29+
},
30+
"assist": {
31+
"enabled": true,
32+
"actions": {
33+
"source": {
34+
"organizeImports": "on"
35+
}
36+
}
37+
}
38+
}

dist/index.js

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -39311,14 +39311,14 @@ var __importStar = (this && this.__importStar) || (function () {
3931139311
})();
3931239312
Object.defineProperty(exports, "__esModule", ({ value: true }));
3931339313
exports.run = run;
39314+
const fs = __importStar(__nccwpck_require__(7561));
39315+
const path = __importStar(__nccwpck_require__(9411));
3931439316
const core = __importStar(__nccwpck_require__(2186));
39315-
const github = __importStar(__nccwpck_require__(5438));
3931639317
const exec = __importStar(__nccwpck_require__(1514));
39318+
const github = __importStar(__nccwpck_require__(5438));
3931739319
const io = __importStar(__nccwpck_require__(7436));
39318-
const fs = __importStar(__nccwpck_require__(7147));
39319-
const path = __importStar(__nccwpck_require__(1017));
39320-
const yaml = __importStar(__nccwpck_require__(1917));
3932139320
const glob = __importStar(__nccwpck_require__(8211));
39321+
const yaml = __importStar(__nccwpck_require__(1917));
3932239322
const minimatch_1 = __nccwpck_require__(4501);
3932339323
async function run() {
3932439324
try {
@@ -39400,7 +39400,7 @@ async function updateTargetSpec(token, branch, autoMerge) {
3940039400
try {
3940139401
fileMapping = JSON.parse(fileMappingInput);
3940239402
}
39403-
catch (jsonError) {
39403+
catch (_jsonError) {
3940439404
throw new Error(`Failed to parse 'sources' input as either YAML or JSON. Please check the format. Error: ${yamlError.message}`);
3940539405
}
3940639406
}
@@ -39429,7 +39429,7 @@ async function runFernApiUpdate() {
3942939429
await exec.exec("fern", ["--version"], { silent: true });
3943039430
core.info("Fern CLI is already installed");
3943139431
}
39432-
catch (error) {
39432+
catch (_error) {
3943339433
core.info("Fern CLI not found. Installing Fern CLI...");
3943439434
await exec.exec("npm", ["install", "-g", "fern-api"]);
3943539435
}
@@ -39468,7 +39468,7 @@ async function cloneRepository(options) {
3946839468
try {
3946939469
await exec.exec("git", ["clone", repoUrl, repoDir]);
3947039470
}
39471-
catch (error) {
39471+
catch (_error) {
3947239472
throw new Error(`Failed to clone repository. Please ensure your token has 'repo' scope and you have write access to ${options.repository}.`);
3947339473
}
3947439474
process.chdir(repoDir);
@@ -39528,7 +39528,7 @@ async function branchExists(owner, repo, branchName, octokit) {
3952839528
});
3952939529
return true;
3953039530
}
39531-
catch (error) {
39531+
catch (_error) {
3953239532
return false;
3953339533
}
3953439534
}
@@ -39610,7 +39610,7 @@ async function hasDifferenceWithRemote(branchName) {
3961039610
const diff = await exec.getExecOutput("git", ["diff", `HEAD`, `origin/${branchName}`], { silent: true });
3961139611
return !!diff.stdout.trim();
3961239612
}
39613-
catch (error) {
39613+
catch (_error) {
3961439614
core.info(`Could not fetch remote branch, assuming this is the first push to new branch.`);
3961539615
return true;
3961639616
}
@@ -39640,7 +39640,9 @@ async function pushChanges(branchName, options) {
3964039640
async function pushWithFallback(branchName, owner, repo, octokit) {
3964139641
// Try regular push first
3964239642
try {
39643-
await exec.exec("git", ["push", "--verbose", "origin", branchName], { silent: false });
39643+
await exec.exec("git", ["push", "--verbose", "origin", branchName], {
39644+
silent: false,
39645+
});
3964439646
return true;
3964539647
}
3964639648
catch {
@@ -39660,34 +39662,31 @@ async function pushWithFallback(branchName, owner, repo, octokit) {
3966039662
}
3966139663
// Push after rebase failed — no rebase in progress, don't abort
3966239664
errorLabel = "Push error";
39663-
errorMsg = [
39664-
pushResult.stderr.trim(),
39665-
pushResult.stdout.trim(),
39666-
]
39667-
.filter(Boolean)
39668-
.join("\n") || `git push failed with exit code ${pushResult.exitCode}`;
39665+
errorMsg =
39666+
[pushResult.stderr.trim(), pushResult.stdout.trim()]
39667+
.filter(Boolean)
39668+
.join("\n") ||
39669+
`git push failed with exit code ${pushResult.exitCode}`;
3966939670
core.info(`Push after rebase failed: ${errorMsg}`);
3967039671
}
3967139672
else {
3967239673
// Rebase itself failed (merge conflicts)
3967339674
rebaseFailed = true;
3967439675
errorLabel = "Rebase error";
39675-
errorMsg = [
39676-
rebaseResult.stderr.trim(),
39677-
rebaseResult.stdout.trim(),
39678-
]
39679-
.filter(Boolean)
39680-
.join("\n") || `git pull --rebase failed with exit code ${rebaseResult.exitCode}`;
39676+
errorMsg =
39677+
[rebaseResult.stderr.trim(), rebaseResult.stdout.trim()]
39678+
.filter(Boolean)
39679+
.join("\n") ||
39680+
`git pull --rebase failed with exit code ${rebaseResult.exitCode}`;
3968139681
core.info(`Rebase failed (likely due to merge conflicts). Aborting rebase.`);
3968239682
// Abort the rebase so the working tree is clean
3968339683
const abortResult = await exec.getExecOutput("git", ["rebase", "--abort"], { ignoreReturnCode: true });
3968439684
if (abortResult.exitCode !== 0) {
39685-
abortErrorMsg = [
39686-
abortResult.stderr.trim(),
39687-
abortResult.stdout.trim(),
39688-
]
39689-
.filter(Boolean)
39690-
.join("\n") || `rebase --abort failed with exit code ${abortResult.exitCode}`;
39685+
abortErrorMsg =
39686+
[abortResult.stderr.trim(), abortResult.stdout.trim()]
39687+
.filter(Boolean)
39688+
.join("\n") ||
39689+
`rebase --abort failed with exit code ${abortResult.exitCode}`;
3969139690
core.info(`rebase --abort failed: ${abortErrorMsg}. The working tree may be in an unexpected state.`);
3969239691
}
3969339692
}
@@ -39745,10 +39744,10 @@ async function updatePR(octokit, owner, repo, prNumber) {
3974539744
async function createPR(octokit, owner, repo, branchName, targetBranch, isFromFern) {
3974639745
core.info(`Creating new PR from ${branchName} to ${targetBranch}`);
3974739746
const date = new Date().toISOString().replace(/[:.]/g, "-");
39748-
let prTitle = isFromFern
39747+
const prTitle = isFromFern
3974939748
? `chore: Update API specifications with fern api update (${date})`
3975039749
: `chore: Update OpenAPI specifications (${date})`;
39751-
let prBody = isFromFern
39750+
const prBody = isFromFern
3975239751
? "Update API specifications by running fern api update."
3975339752
: "Update OpenAPI specifications based on changes in the source repository.";
3975439753
const prResponse = await octokit.rest.pulls.create({

e2e/run-e2e.ts

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ async function githubApi(
7474

7575
if (!resp.ok) {
7676
const text = await resp.text();
77-
throw new Error(`GitHub API ${resp.status} ${resp.statusText}: ${text}`);
77+
throw new Error(
78+
`GitHub API ${resp.status} ${resp.statusText}: ${text}`,
79+
);
7880
}
7981

8082
// 204 No Content
@@ -128,16 +130,18 @@ async function updateSourceSpec(): Promise<void> {
128130
operationId: "getStatus",
129131
summary: `Status v${specVersion}`,
130132
responses: {
131-
"200": { description: `Returns status v${specVersion}` },
133+
"200": {
134+
description: `Returns status v${specVersion}`,
135+
},
132136
},
133137
},
134138
},
135139
},
136140
};
137141

138-
const content = Buffer.from(
139-
JSON.stringify(spec, null, 2) + "\n",
140-
).toString("base64");
142+
const content = Buffer.from(`${JSON.stringify(spec, null, 2)}\n`).toString(
143+
"base64",
144+
);
141145
const sha = await getFileSha(SOURCE_SPEC_PATH);
142146

143147
await githubApi(`/repos/${OWNER}/${REPO}/contents/${SOURCE_SPEC_PATH}`, {
@@ -241,9 +245,7 @@ async function waitForWorkflowRun(
241245
const runs: WorkflowRun[] = data.workflow_runs;
242246

243247
// Find a run that started after our trigger
244-
const run = runs.find(
245-
(r: any) => new Date(r.created_at) > afterDate,
246-
);
248+
const run = runs.find((r: any) => new Date(r.created_at) > afterDate);
247249

248250
if (run) {
249251
if (run.status === "completed") {
@@ -279,9 +281,7 @@ async function getPRCommitCount(prNumber: number): Promise<number> {
279281
}
280282

281283
async function getPRComments(prNumber: number): Promise<GitHubComment[]> {
282-
return githubApi(
283-
`/repos/${OWNER}/${REPO}/issues/${prNumber}/comments`,
284-
);
284+
return githubApi(`/repos/${OWNER}/${REPO}/issues/${prNumber}/comments`);
285285
}
286286

287287
async function pushConflictingCommit(branchSha: string): Promise<void> {
@@ -327,26 +327,20 @@ async function pushConflictingCommit(branchSha: string): Promise<void> {
327327
});
328328

329329
// Create a commit
330-
const newCommit = await githubApi(
331-
`/repos/${OWNER}/${REPO}/git/commits`,
332-
{
333-
method: "POST",
334-
body: {
335-
message: "Conflicting change to force merge conflict",
336-
tree: tree.sha,
337-
parents: [branchSha],
338-
},
330+
const newCommit = await githubApi(`/repos/${OWNER}/${REPO}/git/commits`, {
331+
method: "POST",
332+
body: {
333+
message: "Conflicting change to force merge conflict",
334+
tree: tree.sha,
335+
parents: [branchSha],
339336
},
340-
);
337+
});
341338

342339
// Update the branch ref
343-
await githubApi(
344-
`/repos/${OWNER}/${REPO}/git/refs/heads/${BRANCH}`,
345-
{
346-
method: "PATCH",
347-
body: { sha: newCommit.sha, force: true },
348-
},
349-
);
340+
await githubApi(`/repos/${OWNER}/${REPO}/git/refs/heads/${BRANCH}`, {
341+
method: "PATCH",
342+
body: { sha: newCommit.sha, force: true },
343+
});
350344

351345
console.log(` Pushed conflicting commit ${newCommit.sha} to ${BRANCH}`);
352346
}
@@ -356,7 +350,9 @@ async function pushConflictingCommit(branchSha: string): Promise<void> {
356350
async function testHappyPath(): Promise<void> {
357351
console.log("\n=== TEST: Happy Path ===");
358352

359-
console.log("Step 1: Update source spec and trigger workflow (first run - should create PR)");
353+
console.log(
354+
"Step 1: Update source spec and trigger workflow (first run - should create PR)",
355+
);
360356
await updateSourceSpec();
361357

362358
const before1 = new Date();
@@ -379,7 +375,9 @@ async function testHappyPath(): Promise<void> {
379375
const commits1 = await getPRCommitCount(prNumber);
380376
console.log(` PR #${prNumber} created with ${commits1} commit(s)`);
381377

382-
console.log("\nStep 2: Reset fern spec on PR branch and trigger workflow (should reuse existing PR)");
378+
console.log(
379+
"\nStep 2: Reset fern spec on PR branch and trigger workflow (should reuse existing PR)",
380+
);
383381
// Instead of changing the source spec (which is subject to raw.githubusercontent.com CDN cache),
384382
// we reset fern/openapi/openapi.json on the update-api branch to {} so that fern api update
385383
// will write the (cached) origin content and produce a git diff.
@@ -415,7 +413,9 @@ async function testHappyPath(): Promise<void> {
415413
);
416414
}
417415

418-
console.log(` Still 1 PR (#${prNumber}), commits: ${commits1}${commits2}`);
416+
console.log(
417+
` Still 1 PR (#${prNumber}), commits: ${commits1}${commits2}`,
418+
);
419419
console.log(" PASS: Happy path\n");
420420
}
421421

@@ -434,12 +434,16 @@ async function testConflictPath(): Promise<void> {
434434
const branchData = await githubApi(
435435
`/repos/${OWNER}/${REPO}/git/refs/heads/${BRANCH}`,
436436
);
437-
const currentSha = branchData.object.sha;
437+
const _currentSha = branchData.object.sha;
438438

439-
console.log("Step 1: Reset fern spec on PR branch so fern api update will produce a diff");
439+
console.log(
440+
"Step 1: Reset fern spec on PR branch so fern api update will produce a diff",
441+
);
440442
await resetFernSpec(BRANCH);
441443

442-
console.log("Step 2: Trigger workflow and push conflicting commit during fern install window");
444+
console.log(
445+
"Step 2: Trigger workflow and push conflicting commit during fern install window",
446+
);
443447
// The workflow takes ~5-10s to install fern-api. During this window,
444448
// we push a commit to origin/update-api that the action won't have locally,
445449
// causing its subsequent push to fail (remote has commits the local doesn't).
@@ -448,7 +452,9 @@ async function testConflictPath(): Promise<void> {
448452

449453
// Wait for the workflow to start and pull the branch, then push a conflicting commit.
450454
// The fern-api install takes ~5-10s, so we have a window.
451-
console.log(" Waiting 12s for workflow to pull branch before pushing conflict...");
455+
console.log(
456+
" Waiting 12s for workflow to pull branch before pushing conflict...",
457+
);
452458
await sleep(12000);
453459

454460
// Get the updated SHA (after resetFernSpec added a commit)
@@ -473,14 +479,13 @@ async function testConflictPath(): Promise<void> {
473479
console.log("Step 3: Check for conflict comment on PR");
474480
const comments = await getPRComments(pr.number);
475481
const conflictComment = comments.find(
476-
(c) => c.body.includes("Sync failed") || c.body.includes("Rebase error"),
482+
(c) =>
483+
c.body.includes("Sync failed") || c.body.includes("Rebase error"),
477484
);
478485

479486
if (conflictComment) {
480487
console.log(` Found conflict comment on PR #${pr.number}:`);
481-
console.log(
482-
` ${conflictComment.body.substring(0, 200)}...`,
483-
);
488+
console.log(` ${conflictComment.body.substring(0, 200)}...`);
484489
console.log(" PASS: Conflict path - error comment posted\n");
485490
} else if (run.conclusion === "failure") {
486491
console.log(

0 commit comments

Comments
 (0)