Skip to content

feat: implement wildcard resolution into the action - #93

Merged
xhyrom merged 54 commits into
mainfrom
feat/implement-wildcard-resolution-into-the-action
Jan 4, 2026
Merged

xhyrom merged 54 commits into
mainfrom
feat/implement-wildcard-resolution-into-the-action

Conversation

@xhyrom

@xhyrom xhyrom commented Jul 28, 2024 •

Copy link
Copy Markdown
Contributor

resolves #37, #126
brings back #124

https://bun.sh/download is not used anymore

@xhyrom
xhyrom marked this pull request as ready for review July 29, 2024 19:21
Comment thread action.yml Outdated
Comment thread src/download-url.ts Outdated
@Jarred-Sumner

Copy link
Copy Markdown
Contributor

Thank you for this, but I think we should fix the endpoint instead of changing the code in the setup action. It’s best to keep the action as small as possible.

@xhyrom

xhyrom commented Jul 30, 2024 •

Copy link
Copy Markdown
Contributor Author

Thank you for this, but I think we should fix the endpoint instead of changing the code in the setup action. It’s best to keep the action as small as possible.

I don't want to be rude but I've been requesting a fix in our private staff Discord channel for a while with no response. People are asking for it in the issue #37 without any response from the core team. Since this issue is affecting people, I decided to finally resolve this issue even though I'm on vacation. You just closed this pull request and only said that it's better to fix the API, but when can we expect this issue to be resolved? I transferred this action to the oven-sh organisation because you asked for it. I'm happy to have been able to do so, but the API problems are making it harder for me to maintain setup-bun action.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (2)
src/action.ts (2)

175-175: Critical: Missing authentication parameter in downloadTool call.

The downloadTool call does not pass downloadMeta.auth, even though the DownloadMeta type includes an optional auth field. This means authenticated downloads (e.g., for GitHub API with rate limits or private artifacts) will fail or be subject to stricter rate limits.

🔎 Proposed fix
-  const zipPath = addExtension(await downloadTool(downloadMeta.url), ".zip");
+  const zipPath = addExtension(
+    await downloadTool(downloadMeta.url, undefined, downloadMeta.auth),
+    ".zip"
+  );

32-32: Make token optional.

The token field is defined as required, but the code already handles missing tokens gracefully using conditional checks (see lines 43-45, 68-70, 95-97 in src/download-url.ts). Since public downloads don't require authentication and the auth field in DownloadMeta is already optional, the type should reflect this. GitHub Actions inputs are typically optional unless explicitly required.

🔎 Suggested fix
-  token: string;
+  token?: string;
📜 Review details

Configuration used: Organization 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 399635b and 6109b6c.

⛔ Files ignored due to path filters (1)
  • dist/setup/index.js is excluded by !**/dist/**
📒 Files selected for processing (1)
  • src/action.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/action.ts (2)
src/download-url.ts (2)
  • getDownloadMeta (10-23)
  • DownloadMeta (5-8)
src/utils.ts (2)
  • retry (6-19)
  • addExtension (36-43)
🔇 Additional comments (3)
src/action.ts (3)

54-55: LGTM!

The download metadata retrieval and URL extraction are correctly implemented.


170-173: LGTM!

The updated signature correctly accepts DownloadMeta instead of a raw URL, allowing both URL and authentication to be passed together.


147-168: LGTM!

The version matching logic correctly handles:

  • Rejecting matches for non-pinned versions (latest/canary/action) to ensure fresh downloads
  • Normalizing version strings to handle 'v' prefixes
  • Extracting version from revision strings

Comment thread src/action.ts Outdated
Comment on lines +114 to +117
revision = await retry(
async () => await downloadBun(downloadMeta, bunPath),
3,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Retry logic correctly integrated with new signature.

The downloadBun call properly passes downloadMeta and the retry wrapper with 3 attempts is appropriate for network operations.

🔎 Optional: simplify redundant await

The await inside the arrow function is redundant since the arrow function is already async and the result is awaited by retry. You can simplify to:

-      revision = await retry(
-        async () => await downloadBun(downloadMeta, bunPath),
-        3,
-      );
+      revision = await retry(
+        () => downloadBun(downloadMeta, bunPath),
+        3,
+      );
📝 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
revision = await retry(
async () => await downloadBun(downloadMeta, bunPath),
3,
);
revision = await retry(
() => downloadBun(downloadMeta, bunPath),
3,
);
🤖 Prompt for AI Agents
In src/action.ts around lines 114 to 117, the arrow function passed to retry
uses a redundant inner await (async () => await downloadBun(...)); remove the
unnecessary await by returning the promise directly — e.g. use async () =>
downloadBun(downloadMeta, bunPath) or simply () => downloadBun(downloadMeta,
bunPath) so retry receives the promise-returning function without the extra
await.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/test.yml (1)

61-65: Remove stale commented-out code.

These commented lines are now redundant since the same version specs have been re-enabled at lines 57-60. The reference to issue #37 is useful context but could be preserved as a simpler comment if desired.

🔎 Proposed cleanup
           - "1.x"
           - "1"
           - "> 1.0.0"
           - "< 2"
-          # https://github.com/oven-sh/setup-bun/issues/37
-          # - "1.x"
-          # - "1"
-          # - "> 1.0.0"
-          # - "< 2"
           # Disable <sha> support for now. This is because Github Artifacts
♻️ Duplicate comments (1)
src/download-url.ts (1)

77-79: Consider strict equality for boolean checks.

Using avx2 == false (loose equality) works correctly here because undefined == false evaluates to false. However, strict equality (===) is more idiomatic in TypeScript and makes the intent clearer.

🔎 Proposed change
   const name = `bun-${os ?? getPlatform()}-${arch ?? getArchitecture()}${
-    avx2 == false ? "-baseline" : ""
+    avx2 === false ? "-baseline" : ""
   }${profile ? "-profile" : ""}`;
📜 Review details

Configuration used: Organization 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 6109b6c and 73ab092.

⛔ Files ignored due to path filters (1)
  • dist/setup/index.js is excluded by !**/dist/**
📒 Files selected for processing (3)
  • .github/actions/compare-bun-version/action.yml
  • .github/workflows/test.yml
  • src/download-url.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/download-url.ts (2)
src/action.ts (1)
  • Input (23-33)
src/utils.ts (3)
  • request (21-34)
  • getPlatform (45-50)
  • getArchitecture (52-57)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: setup-bun (windows-latest, canary)
🔇 Additional comments (5)
.github/actions/compare-bun-version/action.yml (1)

28-34: LGTM on version comparison function.

Using sort -V for semantic version comparison is a solid approach that handles most version formats correctly.

.github/workflows/test.yml (1)

85-88: Good addition for version verification.

This step ensures the installed Bun version actually satisfies the requested spec, providing valuable regression coverage for the wildcard resolution feature.

src/download-url.ts (3)

1-8: LGTM on module structure.

The imports align with the exported utilities from ./utils and the Input type from ./action. The DownloadMeta interface provides a clean abstraction for the download URL and optional authentication.


10-23: Clean dispatcher logic.

The function correctly prioritizes custom URL, then detects SHA-based versions via the 40-character hex pattern, and falls back to semver resolution. The flow is clear and efficient.


110-126: Tag resolution logic handles edge cases well.

The logic correctly handles:

  • Exact tag matches (including "canary")
  • "latest" or undefined version → latest valid tag
  • Semver constraints via satisfies()
  • Appropriate error when no match is found

The validate() check at line 124 ensures non-semver tags like "canary" aren't incorrectly prefixed with bun-v.

Comment thread .github/actions/compare-bun-version/action.yml
Comment thread src/download-url.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/utils.ts (1)

77-93: Unreachable return statement in finally block.

The return output in the finally block (line 91) is unreachable when output is truthy because the if (!output) block at lines 81-84 already returns undefined via an implicit return when warning is called. The finally block always executes, but the return at line 91 only triggers if output is truthy—which means the function would have already completed the try block successfully. This logic is confusing and the finally return may cause unexpected behavior.

🔎 Proposed fix for clearer control flow
 export function readVersionFromFile(file: string): string | undefined {
   const cwd = process.env.GITHUB_WORKSPACE;
   if (!cwd) {
     return;
   }

   if (!file) {
     return;
   }

   debug(`Reading version from ${file}`);

   const path = resolve(cwd, file);
   const base = basename(file);

   if (!existsSync(path)) {
     warning(`File ${path} not found`);
     return;
   }

   const reader = FILE_VERSION_READERS[base] ?? (() => undefined);

-  let output: string | undefined;
   try {
-    output = reader(readFileSync(path, "utf8"))?.trim();
+    const output = reader(readFileSync(path, "utf8"))?.trim();

     if (!output) {
       warning(`Failed to read version from ${file}`);
-      return;
+      return undefined;
     }
+
+    info(`Obtained version ${output} from ${file}`);
+    return output;
   } catch (error) {
     const { message } = error as Error;
     warning(`Failed to read ${file}: ${message}`);
-  } finally {
-    if (output) {
-      info(`Obtained version ${output} from ${file}`);
-      return output;
-    }
+    return undefined;
   }
 }
src/action.ts (1)

166-183: Auth token not passed to downloadTool for SHA-based downloads.

downloadBun receives downloadMeta which includes an optional auth field (set for SHA-based artifact downloads), but line 171 only passes downloadMeta.url to downloadTool. The @actions/tool-cache downloadTool function accepts an optional auth parameter as the third argument, which is needed for authenticated GitHub artifact downloads.

🔎 Proposed fix
 async function downloadBun(
   downloadMeta: DownloadMeta,
   bunPath: string,
 ): Promise<string | undefined> {
   // Workaround for https://github.com/oven-sh/setup-bun/issues/79 and https://github.com/actions/toolkit/issues/1179
-  const zipPath = addExtension(await downloadTool(downloadMeta.url), ".zip");
+  const zipPath = addExtension(
+    await downloadTool(downloadMeta.url, undefined, downloadMeta.auth),
+    ".zip",
+  );
   const extractedZipPath = await extractZip(zipPath);
♻️ Duplicate comments (1)
src/action.ts (1)

32-32: Consider making token optional.

The token field is marked as required, but the download flow in src/download-url.ts already handles missing tokens gracefully by conditionally omitting the Authorization header. Making this optional would align the type with the actual runtime behavior where unauthenticated requests are valid (though rate-limited).

🔎 Proposed fix
 export type Input = {
   customUrl?: string;
   version?: string;
   os?: string;
   arch?: string;
   avx2?: boolean;
   profile?: boolean;
   registries?: Registry[];
   noCache?: boolean;
-  token: string;
+  token?: string;
 };
📜 Review details

Configuration used: Organization 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 73ab092 and 6c20dbe.

⛔ Files ignored due to path filters (1)
  • dist/setup/index.js is excluded by !**/dist/**
📒 Files selected for processing (4)
  • .github/actions/compare-bun-version/action.yml
  • src/action.ts
  • src/download-url.ts
  • src/utils.ts
🧰 Additional context used
🧬 Code graph analysis (2)
src/action.ts (2)
src/download-url.ts (2)
  • getDownloadMeta (10-23)
  • DownloadMeta (5-8)
src/utils.ts (1)
  • addExtension (21-28)
src/download-url.ts (2)
src/action.ts (2)
  • options (50-141)
  • Input (23-33)
src/utils.ts (3)
  • request (6-19)
  • getPlatform (30-35)
  • getArchitecture (37-42)
🔇 Additional comments (11)
src/utils.ts (2)

6-18: LGTM!

The request helper properly handles non-OK responses by reading the body text and including it in the error message, providing actionable debugging information.


30-42: Architecture mapping is correct.

Bun's release artifacts confirm the naming convention: aarch64 for ARM64 and x64 for x64 (e.g., bun-linux-x64.zip, bun-darwin-aarch64.zip). The getArchitecture() function correctly maps arm64 → aarch64 and returns x64 unchanged, matching Bun's actual release naming.

src/action.ts (1)

54-55: LGTM!

The refactored flow correctly obtains download metadata via getDownloadMeta and extracts the URL for cache key generation and logging purposes.

src/download-url.ts (3)

10-23: LGTM!

The routing logic correctly handles the three cases: custom URL passthrough, SHA-based artifact lookup, and semver resolution.


34-90: SHA-based download flow is well-structured.

The paginated search with proper termination conditions (empty results, found run), error handling for missing runs/artifacts, and conditional auth headers are all correctly implemented per previous review feedback.


101-127: Canary version handling is correct and working as intended.

The code properly handles the "canary" version: when a user requests version: "canary", the tag is found at line 110 before the semver validation filter is applied. Since validate("canary") returns false, the tag remains unprefixed, resulting in the correct URL format (canary/bun-linux-x64.zip). Verification confirms GitHub recognizes and serves this URL format correctly.

.github/actions/compare-bun-version/action.yml (5)

12-17: LGTM!

Good use of tr -d '\r\n' to handle cross-platform line endings, and graceful fallback for --revision on older Bun versions that may not support it.


30-34: sort -V may not be available on all runners.

The sort -V (version sort) flag is a GNU coreutils extension. While it's available on Ubuntu runners, macOS runners use BSD sort which also supports -V, but some minimal environments may not. This is likely fine for GitHub-hosted runners but worth noting.


64-72: Single-segment version without operator defaults to prefix match.

When op is == (default) and version_part has no dots (e.g., 1), the condition at line 64 treats it as a wildcard. This means bun-version: "1" will match any 1.x.y version, which aligns with semver wildcard semantics but differs from exact match behavior. This is likely intentional but worth documenting in the action's description.


26-86: Well-structured version comparison logic.

The script handles multiple version specification formats (latest, canary, exact versions, ranges, wildcards) with clear error messages. The use of set -euo pipefail ensures failures are properly propagated.


61-61: Wildcard replacement only removes first .x occurrence.

The pattern ${version_part//.x/} uses single / which only replaces the first occurrence. A spec like 1.x.x would become 1.x instead of 1. Use ${version_part//.x/} with double slash for global replacement: ${version_part//.x} (remove all .x).

🔎 Proposed fix
-        version_base="${version_part//.x/}"
+        version_base="${version_part//.x}"

Note: The syntax ${var//pattern} removes all occurrences of pattern from var.

Likely an incorrect or invalid review comment.

Comment thread src/download-url.ts Outdated
Comment thread src/download-url.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 13 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

.github/workflows/test.yml:65

  • These commented-out test cases are now duplicates of the active test cases on lines 57-60. The comments indicating they were disabled due to issue #37 are now obsolete since this PR implements the wildcard resolution feature. These duplicate commented lines should be removed.
          # https://github.com/oven-sh/setup-bun/issues/37
          # - "1.x"
          # - "1"
          # - "> 1.0.0"
          # - "< 2"

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/download-url.ts
Comment thread src/download-url.ts
Comment thread src/download-url.ts Outdated
Comment thread src/action.ts Outdated
Comment thread src/download-url.ts Outdated
@xhyrom
xhyrom merged commit 8c296f9 into main Jan 4, 2026
55 checks passed
@xhyrom
xhyrom deleted the feat/implement-wildcard-resolution-into-the-action branch January 4, 2026 23:03
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.

Support fetching Bun from GitHub Version selectors 1.x/1.0.x result in 400/404 response errors on install

4 participants