Skip to content

Conversation

@nuomi1
Copy link

@nuomi1 nuomi1 commented Oct 27, 2025

Resolved #37

Should we match the exact version (like 1.3.1) instead of latest?


tests/action.spec.ts:
✓ action > getDownloadUrl > input 0 - output 0.8.1 [1.14ms]
✓ action > getDownloadUrl > input 0.x - output 0.8.1 [0.19ms]
✓ action > getDownloadUrl > input 0.0 - output 0.0.12 [0.16ms]
✓ action > getDownloadUrl > input 0.0.x - output 0.0.12 [0.13ms]
✓ action > getDownloadUrl > input 0.7 - output 0.7.3 [0.10ms]
✓ action > getDownloadUrl > input 0.7.x - output 0.7.3 [0.08ms]
✓ action > getDownloadUrl > input 0.7.4 - failure [0.08ms]
✓ action > getDownloadUrl > input 0.8 - output 0.8.1 [0.12ms]
✓ action > getDownloadUrl > input 0.8.x - output 0.8.1 [0.07ms]
✓ action > getDownloadUrl > input 0.9 - failure [0.06ms]
✓ action > getDownloadUrl > input 1 - output 1.3.1 [0.07ms]
✓ action > getDownloadUrl > input 1.x - output 1.3.1 [0.09ms]
✓ action > getDownloadUrl > input 1.0 - output 1.0.36 [0.09ms]
✓ action > getDownloadUrl > input 1.0.x - output 1.0.36 [0.07ms]
✓ action > getDownloadUrl > input 1.2 - output 1.2.23 [0.05ms]
✓ action > getDownloadUrl > input 1.2.x - output 1.2.23 [0.04ms]
✓ action > getDownloadUrl > input 1.3 - output 1.3.1 [0.04ms]
✓ action > getDownloadUrl > input 1.3.x - output 1.3.1 [0.04ms]
✓ action > getDownloadUrl > input 1.4 - failure [0.03ms]
✓ action > getDownloadUrl > input 2 - failure [0.07ms]
✓ action > getDownloadUrl > input latest - output latest [0.09ms]
✓ action > getDownloadUrl > input canary - output canary [0.04ms]
✓ action > getDownloadUrl > input  - output latest [0.03ms]
✓ action > getDownloadUrl > input null - output latest [0.02ms]
✓ action > getDownloadUrl > input undefined - output latest

@coderabbitai
Copy link

coderabbitai bot commented Oct 27, 2025

Walkthrough

Adds semver as a dependency and refactors version resolution to support semver ranges. getDownloadUrl is now async and resolves ranged selectors by querying and caching available Bun versions. New helpers for fetching/filtering versions added and a comprehensive test suite for selector behavior included.

Changes

Cohort / File(s) Summary
Package dependencies
package.json
Adds runtime dependency semver (v6) and dev dependency @types/semver (v6).
Version resolution implementation
src/action.ts
Imports semver; makes getDownloadUrl(options: Input) async and exported as Promise<string>; adds getAllVersions(): Promise<semver.SemVer[]>, internal fetchAllVersions(): Promise<semver.SemVer[]>, and module-level `let cachedVersions: semver.SemVer[]
Test suite
tests/action.spec.ts
Adds tests that mock getAllVersions and assert success/failure across many semver selectors (wildcards, partials, exact, ranges, latest/canary/empty); verifies generated download URL format including platform/arch/AVX parameters.

Pre-merge checks

✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "feat: support semver" is concise and clearly describes the main change being introduced. It directly relates to the primary objective of the changeset, which is to add semantic versioning support to the action to resolve version ranges like "1.x" and "1.0.x". The title accurately summarizes the feature being added without unnecessary noise or vague terminology.
Linked Issues Check ✅ Passed The changes comprehensively address the objectives from issue #37. The PR implements proper handling of semver selectors by making getDownloadUrl asynchronous, adding version range resolution logic, and caching available versions. The test results demonstrate that problematic selectors like "1.x" and "1.0.x" now correctly resolve to appropriate versions (1.3.1 and 1.0.36 respectively) instead of producing 400/404 errors. Additionally, the PR includes extensive test coverage validating selector-to-release resolution and failure modes for unsupported versions, directly meeting the requirement to provide tests that validate the new functionality [#37].
Out of Scope Changes Check ✅ Passed All changes in the PR are directly related to implementing semver support as described in the linked issue. The modifications to package.json add necessary dependencies (semver and its type definitions), the changes to src/action.ts implement the core version range resolution logic, and the tests/action.spec.ts additions provide the required test coverage. No out-of-scope changes or unrelated modifications are detected in the changeset.
Description Check ✅ Passed The pull request description is clearly related to the changeset. It references the resolved issue (#37) which documents the exact problem being addressed (400/404 errors with semver selectors like 1.x and 1.0.x), and includes concrete test evidence showing successful version resolutions for various inputs. The description provides meaningful context about what the PR accomplishes and validates the implementation with test results.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@xhyrom
Copy link
Collaborator

xhyrom commented Oct 27, 2025

I already implemented something like that but Jarred closed it - #93

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6356405 and fae4c11.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • package.json (1 hunks)
  • src/action.ts (4 hunks)
  • tests/action.spec.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
tests/action.spec.ts (1)
src/action.ts (3)
  • getAllVersions (229-237)
  • Input (21-30)
  • options (49-126)
src/action.ts (1)
src/bunfig.ts (1)
  • writeBunfig (17-81)
🔇 Additional comments (3)
src/action.ts (2)

19-19: Import looks good

ESM-compatible namespace import works with esbuild CJS output and semver v6+.


53-53: Switch to async URL resolution LGTM

Moving to await getDownloadUrl(options) cleanly integrates range resolution without changing downstream flow.

package.json (1)

31-32: Corrected: semver v7 still requires @types/semver

semver v7 does not ship built-in TypeScript types; the @types/semver package is required for both v6 and v7. The suggestion to drop @types/semver when upgrading is incorrect. If you choose to upgrade to semver v7 (currently 7.7.2), keep @types/semver aligned accordingly. If staying on v6, consider pinning with a caret (^6.x.x) or exact patch to reduce version drift.

Likely an incorrect or invalid review comment.

Comment on lines +47 to +48
let cachedVersions: semver.SemVer[] | null = null;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Version list cache: consider optional invalidation/TTL

Static cache is fine per-run. If long-lived processes or tests ever need refresh, expose a lightweight resetVersionsCache() or add a short TTL.

 let cachedVersions: semver.SemVer[] | null = null;
+
+// Optional: testing/ops hook
+export function resetVersionsCache(): void {
+  cachedVersions = null;
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let cachedVersions: semver.SemVer[] | null = null;
let cachedVersions: semver.SemVer[] | null = null;
// Optional: testing/ops hook
export function resetVersionsCache(): void {
cachedVersions = null;
}
🤖 Prompt for AI Agents
In src/action.ts around lines 47-48 the versions cache is a module-level
variable (let cachedVersions: semver.SemVer[] | null = null;) with no way to
invalidate it; add a lightweight exported function resetVersionsCache() that
sets cachedVersions = null so callers/tests can force refresh, and optionally
add an exported configureVersionsCacheTTL(ms: number) or internal timestamp
check so the code invalidates the cache after a short TTL; update any code that
reads cachedVersions to respect TTL or call resetVersionsCache where
appropriate.

Comment on lines +161 to +181
export async function getDownloadUrl(options: Input): Promise<string> {
const { customUrl } = options;
if (customUrl) {
return customUrl;
}
const { version, os, arch, avx2, profile } = options;
const eversion = encodeURIComponent(version ?? "latest");
let resolvedVersion: string | null = null;
const range = semver.validRange(version);
if (version == "") {
resolvedVersion = null;
} else if (range !== null) {
const availableVersions = await getAllVersions();
const satisfiedVersion = semver.maxSatisfying(availableVersions, range);
if (satisfiedVersion === null) {
throw new Error(`Version "${version}" is not available`);
}
resolvedVersion = satisfiedVersion.toString();
} else {
resolvedVersion = version;
}
const eversion = encodeURIComponent(resolvedVersion ?? "latest");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Harden range parsing: trim input and use strict equality

Trim whitespace to avoid surprises and use strict equality for the empty-string case. Optionally pass { loose: true } to validRange to be forgiving with user input.

-export async function getDownloadUrl(options: Input): Promise<string> {
+export async function getDownloadUrl(options: Input): Promise<string> {
   const { customUrl } = options;
   if (customUrl) {
     return customUrl;
   }
   const { version, os, arch, avx2, profile } = options;
-  let resolvedVersion: string | null = null;
-  const range = semver.validRange(version);
-  if (version == "") {
+  let resolvedVersion: string | null = null;
+  const raw = typeof version === "string" ? version.trim() : version;
+  const range = raw ? semver.validRange(raw, { loose: true }) : null;
+  if (raw === "") {
     resolvedVersion = null;
   } else if (range !== null) {
     const availableVersions = await getAllVersions();
     const satisfiedVersion = semver.maxSatisfying(availableVersions, range);
     if (satisfiedVersion === null) {
-      throw new Error(`Version "${version}" is not available`);
+      throw new Error(`Version "${raw}" is not available`);
     }
     resolvedVersion = satisfiedVersion.toString();
   } else {
-    resolvedVersion = version;
+    resolvedVersion = raw ?? undefined;
   }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/action.ts around lines 161 to 181, the version input should be trimmed
and compared with strict equality to harden range parsing: create a
trimmedVersion = version.trim() (or destructure and trim when reading options),
use strict === "" when checking for empty string, and pass the trimmedVersion to
semver.validRange (optionally with { loose: true } if you want forgiving
parsing), then use trimmedVersion for subsequent logic (semver.maxSatisfying and
resolvedVersion assignments) so whitespace does not break range detection.

Comment on lines +229 to +237
export async function getAllVersions(): Promise<semver.SemVer[]> {
if (cachedVersions !== null) {
return cachedVersions;
}

const versions = await fetchAllVersions();
cachedVersions = versions;
return versions;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

getAllVersions cache logic LGTM; consider minor ergonomics

Works as intended. If you add resetVersionsCache() (earlier comment), tests can force refresh without monkeypatching.

🤖 Prompt for AI Agents
In src/action.ts around lines 229 to 237, add and export a small helper to reset
the cached versions so tests can force a refresh: implement and export a
function named resetVersionsCache (or clearVersionsCache) that sets the
module-level cachedVersions back to null; keep it simple (no args, void return)
and use it in tests instead of monkeypatching to ensure fetchAllVersions is
called anew.

Comment on lines 239 to 258
async function fetchAllVersions(): Promise<semver.SemVer[]> {
const versions = await getExecOutput(
"npm",
["view", "bun", "versions", "--json"],
{
silent: true,
ignoreReturnCode: true,
},
);

if (versions.exitCode == 0) {
const jsonList = JSON.parse(versions.stdout.trim()) as string[];
const stableList = jsonList.filter((v) => !v.includes("-"));
const semverList = stableList.flatMap((v) => semver.coerce(v));
const sortedList = semver.rsort(semverList);
return sortedList;
}

return [];
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Null-safe coerce and clearer failure signal from npm view

Guard against coerce returning null and add a warning when npm view fails to aid diagnostics. Returning an empty list conflates “no versions” with “fetch failed”.

   if (versions.exitCode == 0) {
-    const jsonList = JSON.parse(versions.stdout.trim()) as string[];
-    const stableList = jsonList.filter((v) => !v.includes("-"));
-    const semverList = stableList.flatMap((v) => semver.coerce(v));
-    const sortedList = semver.rsort(semverList);
+    const jsonList = JSON.parse(versions.stdout.trim()) as string[];
+    const stableList = jsonList.filter((v) => !v.includes("-"));
+    const semverList = stableList
+      .map((v) => semver.coerce(v))
+      .filter((v): v is semver.SemVer => v !== null);
+    const sortedList = semver.rsort(semverList);
     return sortedList;
   }
 
-  return [];
+  warning?.("Failed to retrieve versions via `npm view bun versions --json`; proceeding with empty list");
+  return [];

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/action.ts around lines 239 to 258, make fetchAllVersions null-safe and
signal failure explicitly: change the return type to Promise<semver.SemVer[] |
null>, and when getExecOutput returns a non-zero exitCode call a logger/warning
(include exitCode and versions.stderr or stdout) and return null instead of an
empty array; when parsing results, guard semver.coerce by mapping and filtering
out nulls (e.g., flatMap/coerce then filter(Boolean)) before sorting so you
never pass nulls into semver.rsort.

Comment on lines +164 to +169
function getOptions(version: string | null): action.Input {
const options: action.Input = {
version: version,
};
return options;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Broaden getOptions type to accept undefined (used by tests)

expectSuccess(undefined, "latest") passes undefined but getOptions only admits string | null. Add undefined to the parameter type.

-function getOptions(version: string | null): action.Input {
+function getOptions(version: string | null | undefined): action.Input {
   const options: action.Input = {
     version: version,
   };
   return options;
}

Also applies to: 228-228

🤖 Prompt for AI Agents
In tests/action.spec.ts around lines 164-169 (and also at line 228), the
getOptions helper currently types its parameter as string | null but tests pass
undefined; update the function signature to accept string | null | undefined for
the version parameter, and adjust any related call sites or type annotations if
needed so undefined values are allowed and compiled cleanly.

Comment on lines +181 to +186
it(`input ${input} - failure`, async () => {
const options = getOptions(input);
expect(action.getDownloadUrl(options)).rejects.toThrow(
`Version "${input}" is not available`,
);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Await the rejection assertion to avoid false positives

Without awaiting .rejects, the test may pass even if the promise resolves. Await the assertion.

-  it(`input ${input} - failure`, async () => {
+  it(`input ${input} - failure`, async () => {
     const options = getOptions(input);
-    expect(action.getDownloadUrl(options)).rejects.toThrow(
+    await expect(action.getDownloadUrl(options)).rejects.toThrow(
       `Version "${input}" is not available`,
     );
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it(`input ${input} - failure`, async () => {
const options = getOptions(input);
expect(action.getDownloadUrl(options)).rejects.toThrow(
`Version "${input}" is not available`,
);
});
it(`input ${input} - failure`, async () => {
const options = getOptions(input);
await expect(action.getDownloadUrl(options)).rejects.toThrow(
`Version "${input}" is not available`,
);
});
🤖 Prompt for AI Agents
In tests/action.spec.ts around lines 181 to 186, the test uses
expect(...).rejects without awaiting it, which can cause false positives; update
the test to await the rejection assertion by adding an await before
expect(action.getDownloadUrl(options)).rejects.toThrow(...), ensuring the async
assertion is actually executed and the test fails when the promise resolves.

Comment on lines +190 to +191
describe("getDownloadUrl", async () => {
spyOn(action, "getAllVersions").mockResolvedValue(getAllVersions());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove unnecessary async on describe

describe body doesn’t await anything; keeping it sync avoids subtle ordering issues.

-  describe("getDownloadUrl", async () => {
+  describe("getDownloadUrl", () => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
describe("getDownloadUrl", async () => {
spyOn(action, "getAllVersions").mockResolvedValue(getAllVersions());
describe("getDownloadUrl", () => {
spyOn(action, "getAllVersions").mockResolvedValue(getAllVersions());
🤖 Prompt for AI Agents
In tests/action.spec.ts around lines 190-191, the describe callback is declared
async despite not awaiting anything; remove the async keyword from the describe
declaration so the suite runs synchronously (if any setup needs async behavior,
move awaits into beforeEach/it blocks or use beforeAll with async as needed).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (7)
tests/action.spec.ts (4)

160-163: Good: null‑safety for semver.coerce is implemented

Mapping then filtering out nulls is correct; this prevents SemVer | null from leaking into later logic.


166-171: Fix types: allow undefined and avoid assigning null to Input.version

Tests pass null/undefined, but Input.version is string | undefined. Don’t assign null; omit the key when nullish, and widen helper types.

Apply this diff:

-function getOptions(version: string | null): action.Input {
-  const options: action.Input = {
-    version: version,
-  };
-  return options;
-}
+function getOptions(version: string | null | undefined): action.Input {
+  const options: action.Input = {};
+  if (version != null) {
+    options.version = version;
+  }
+  return options;
+}
 
-function expectSuccess(input: string | null, output: string) {
+function expectSuccess(input: string | null | undefined, output: string) {

Also applies to: 173-173


182-189: Await the rejection assertion to avoid false positives

Without await, the test may pass even if the promise resolves.

Apply this diff:

   it(`input ${input} - failure`, async () => {
     const options = getOptions(input);
-    expect(action.getDownloadUrl(options)).rejects.toThrow(
+    await expect(action.getDownloadUrl(options)).rejects.toThrow(
       `Version "${input}" is not available`,
     );
   });

191-194: Remove unnecessary async from describe

The describe body doesn’t await anything; keep it sync.

Apply this diff:

-describe("action", () => {
-  describe("getDownloadUrl", async () => {
+describe("action", () => {
+  describe("getDownloadUrl", () => {
src/action.ts (3)

47-48: Add a small cache reset helper for tests and long‑lived processes

Expose an explicit invalidation hook.

Apply this diff:

 let cachedVersions: semver.SemVer[] | null = null;
 
+export function resetVersionsCache(): void {
+  cachedVersions = null;
+}

249-260: Use strict equality for exitCode and warn when npm query fails

Improves correctness and diagnostics when npm view does not succeed.

Apply this diff:

-  if (versions.exitCode == 0) {
+  if (versions.exitCode === 0) {
     const jsonList = JSON.parse(versions.stdout.trim()) as string[];
     const stableList = jsonList.filter((v) => !v.includes("-"));
     const semverList = stableList
       .map((v) => semver.coerce(v))
       .filter((v): v is semver.SemVer => v !== null);
-    const sortedList = semver.rsort(semverList);
-    return sortedList;
+    semverList.sort((a, b) => semver.rcompare(a, b));
+    return semverList;
   }
 
-  return [];
+  warning(
+    `Failed to retrieve versions via "npm view bun versions --json" (exitCode ${versions.exitCode}). stderr: ${versions.stderr?.trim() || "<empty>"}`,
+  );
+  return [];

167-181: Type bug and input hardening in getDownloadUrl

resolvedVersion is string | null but later assigned undefined; also == "" and no trim can mis-handle whitespace. Normalize input, use strict equality, and keep resolvedVersion as string | undefined.

Apply this diff:

-  let resolvedVersion: string | null = null;
-  const range = semver.validRange(version);
-  if (version == "") {
-    resolvedVersion = null;
-  } else if (range !== null) {
+  let resolvedVersion: string | undefined;
+  const raw = typeof version === "string" ? version.trim() : version;
+  const range = raw ? semver.validRange(raw, { loose: true }) : null;
+  if (raw === "") {
+    resolvedVersion = undefined;
+  } else if (range !== null) {
     const availableVersions = await getAllVersions();
     const satisfiedVersion = semver.maxSatisfying(availableVersions, range);
     if (satisfiedVersion === null) {
-      throw new Error(`Version "${version}" is not available`);
+      throw new Error(`Version "${raw}" is not available`);
     }
     resolvedVersion = satisfiedVersion.toString();
   } else {
-    resolvedVersion = version;
+    resolvedVersion = raw ?? undefined;
   }
-  const eversion = encodeURIComponent(resolvedVersion ?? "latest");
+  const eversion = encodeURIComponent(resolvedVersion ?? "latest");
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fae4c11 and f767a53.

📒 Files selected for processing (2)
  • src/action.ts (4 hunks)
  • tests/action.spec.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/action.spec.ts (1)
src/action.ts (2)
  • getAllVersions (229-237)
  • Input (21-30)

Comment on lines +239 to +256
async function fetchAllVersions(): Promise<semver.SemVer[]> {
const versions = await getExecOutput(
"npm",
["view", "bun", "versions", "--json"],
{
silent: true,
ignoreReturnCode: true,
},
);

if (versions.exitCode == 0) {
const jsonList = JSON.parse(versions.stdout.trim()) as string[];
const stableList = jsonList.filter((v) => !v.includes("-"));
const semverList = stableList
.map((v) => semver.coerce(v))
.filter((v): v is semver.SemVer => v !== null);
const sortedList = semver.rsort(semverList);
return sortedList;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Return type mismatch: semver.rsort yields string[], but function promises SemVer[]

Sort the SemVer[] in-place using rcompare to preserve types.

Apply this diff:

-  if (versions.exitCode == 0) {
+  if (versions.exitCode == 0) {
     const jsonList = JSON.parse(versions.stdout.trim()) as string[];
     const stableList = jsonList.filter((v) => !v.includes("-"));
     const semverList = stableList
       .map((v) => semver.coerce(v))
       .filter((v): v is semver.SemVer => v !== null);
-    const sortedList = semver.rsort(semverList);
-    return sortedList;
+    semverList.sort((a, b) => semver.rcompare(a, b));
+    return semverList;
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function fetchAllVersions(): Promise<semver.SemVer[]> {
const versions = await getExecOutput(
"npm",
["view", "bun", "versions", "--json"],
{
silent: true,
ignoreReturnCode: true,
},
);
if (versions.exitCode == 0) {
const jsonList = JSON.parse(versions.stdout.trim()) as string[];
const stableList = jsonList.filter((v) => !v.includes("-"));
const semverList = stableList
.map((v) => semver.coerce(v))
.filter((v): v is semver.SemVer => v !== null);
const sortedList = semver.rsort(semverList);
return sortedList;
async function fetchAllVersions(): Promise<semver.SemVer[]> {
const versions = await getExecOutput(
"npm",
["view", "bun", "versions", "--json"],
{
silent: true,
ignoreReturnCode: true,
},
);
if (versions.exitCode == 0) {
const jsonList = JSON.parse(versions.stdout.trim()) as string[];
const stableList = jsonList.filter((v) => !v.includes("-"));
const semverList = stableList
.map((v) => semver.coerce(v))
.filter((v): v is semver.SemVer => v !== null);
semverList.sort((a, b) => semver.rcompare(a, b));
return semverList;
🤖 Prompt for AI Agents
In src/action.ts around lines 239 to 256, the code uses semver.rsort which
returns string[] causing a mismatch with the function's Promise<semver.SemVer[]>
return type; replace the call with an in-place sort of the semver.SemVer[] using
semver.rcompare (e.g. call semverList.sort(semver.rcompare)) and then return the
mutated semverList so the returned type remains SemVer[].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Version selectors 1.x/1.0.x result in 400/404 response errors on install

2 participants