feat: implement wildcard resolution into the action (#93)
* feat: remove retry attempts * [autofix.ci] apply automated fixes * feat: get download url from github's api * [autofix.ci] apply automated fixes * fix: add token property to action definition & fix satisfies params * [autofix.ci] apply automated fixes * fix: getPlatform, getArchitecture + eversion * [autofix.ci] apply automated fixes * fix: duplicate v * [autofix.ci] apply automated fixes * fix: check if valid semver and add bun-v * [autofix.ci] apply automated fixes * refactor: wrap validation * [autofix.ci] apply automated fixes * ci(format): use bun bun install is rqeuired for patches * ci(format): use bun bun install is rqeuired for patches * [autofix.ci] apply automated fixes * feat: bring back support for sha downloads * [autofix.ci] apply automated fixes * fix: add bearer prefix for token * [autofix.ci] apply automated fixes * fix: proper error when artifact is not found * [autofix.ci] apply automated fixes * conflicts * autofix build * fix * fix * fix * fix * fix * autofix build * fix * [autofix.ci] apply automated fixes * fix * [autofix.ci] apply automated fixes * fix * [autofix.ci] apply automated fixes * fix * fix * [autofix.ci] apply automated fixes * fix * fix * [autofix.ci] apply automated fixes * fix: drop sha support for now * [autofix.ci] apply automated fixes * fix: filter tags * [autofix.ci] apply automated fixes * docs: token * docs: token * docs: token * refactor: cleanup * [autofix.ci] apply automated fixes * refactor: cleanup --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
76
.github/actions/compare-bun-version/action.yml
vendored
76
.github/actions/compare-bun-version/action.yml
vendored
@@ -1,28 +1,86 @@
|
|||||||
name: ⚖️ Compare Bun Version
|
name: ⚖️ Compare Bun Version
|
||||||
description: Compare the version of Bun to a specified version
|
description: Compare the installed Bun version against a version specification.
|
||||||
|
|
||||||
inputs:
|
inputs:
|
||||||
bun-version:
|
bun-version:
|
||||||
description: The version of Bun to compare against
|
description: The version spec to compare against (e.g., '1.1.0', 'canary', '>1.2.0', '1.x').
|
||||||
required: true
|
required: true
|
||||||
default: "1.1.0"
|
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- name: 🛠️ Get installed Bun version
|
- name: 🛠️ Get installed Bun version and revision
|
||||||
id: bun
|
id: bun
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
bun --version
|
echo "version=$(bun --version | tr -d '\r\n')" >> $GITHUB_OUTPUT
|
||||||
echo "version=$(bun --version)" >> $GITHUB_OUTPUT
|
echo "revision=$(bun --revision 2>/dev/null || true)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: ⚖️ Compare versions
|
- name: ⚖️ Compare versions
|
||||||
shell: bash
|
shell: bash
|
||||||
|
env:
|
||||||
|
REQUESTED_SPEC: ${{ inputs.bun-version }}
|
||||||
|
ACTUAL_VERSION: ${{ steps.bun.outputs.version }}
|
||||||
|
ACTUAL_REVISION: ${{ steps.bun.outputs.revision }}
|
||||||
run: |
|
run: |
|
||||||
if [[ "${{ steps.bun.outputs.version }}" == "${{ inputs.bun-version }}" ]]; then
|
set -euo pipefail
|
||||||
echo "Version is ${{ inputs.bun-version }}"
|
|
||||||
|
# Function to compare two semantic versions (e.g., version_compare 1.2.3 1.10.0)
|
||||||
|
# Returns: 0 if v1 == v2, 1 if v1 > v2, 2 if v1 < v2
|
||||||
|
version_compare() {
|
||||||
|
if [[ "$1" == "$2" ]]; then return 0; fi
|
||||||
|
local lowest=$(printf '%s\n' "$1" "$2" | sort -V | head -n1)
|
||||||
|
if [[ "$1" == "$lowest" ]]; then return 2; else return 1; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Requested spec: ${REQUESTED_SPEC}"
|
||||||
|
echo "Actual version: ${ACTUAL_VERSION}"
|
||||||
|
|
||||||
|
# Case 1: 'latest' - always passes
|
||||||
|
if [[ "${REQUESTED_SPEC}" == "latest" ]]; then
|
||||||
|
echo "OK: Skipping explicit version check for 'latest'."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 2: 'canary' - check for 'canary' in revision or version string
|
||||||
|
if [[ "${REQUESTED_SPEC}" == "canary" ]]; then
|
||||||
|
if [[ "${ACTUAL_REVISION}" == *canary* ]] || [[ "${ACTUAL_VERSION}" == *canary* ]]; then
|
||||||
|
echo "OK: Detected canary build (version: ${ACTUAL_VERSION}, revision: ${ACTUAL_REVISION:-n/a})."
|
||||||
|
exit 0
|
||||||
else
|
else
|
||||||
echo "Expected version to be ${{ inputs.bun-version }}, got ${{ steps.bun.outputs.version }}"
|
echo "Error: Expected a canary build, but got ${ACTUAL_VERSION} (revision: ${ACTUAL_REVISION:-n/a})."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 3: Semver ranges (e.g., >1.0.0, <2, 1.x, 1.1.0)
|
||||||
|
op_part=$(echo "${REQUESTED_SPEC}" | sed -E 's/^([><=]*).*/\1/')
|
||||||
|
version_part=$(echo "${REQUESTED_SPEC}" | sed -E 's/^[><= ]*//')
|
||||||
|
|
||||||
|
op="${op_part:-==}"
|
||||||
|
version_base="${version_part//.x/}"
|
||||||
|
|
||||||
|
# Handle wildcards like '1.x' or '1'
|
||||||
|
if [[ "${version_part}" == *.x* ]] || { [[ ! "${version_part}" == *.* ]] && [[ "${op}" == "==" ]]; }; then
|
||||||
|
if [[ "${ACTUAL_VERSION}" == "${version_base}" || "${ACTUAL_VERSION}" == "${version_base}".* ]]; then
|
||||||
|
echo "OK: Version ${ACTUAL_VERSION} matches wildcard spec '${REQUESTED_SPEC}'."
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "Error: Version ${ACTUAL_VERSION} does not match wildcard spec '${REQUESTED_SPEC}'."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform comparison for >, <, >=, <=, ==
|
||||||
|
version_compare "${ACTUAL_VERSION}" "${version_part}" && result=0 || result=$?
|
||||||
|
|
||||||
|
case "${op}" in
|
||||||
|
'==') if [[ ${result} -ne 0 ]]; then echo "Error: Expected version ${version_part}, but got ${ACTUAL_VERSION}." && exit 1; fi ;;
|
||||||
|
'>') if [[ ${result} -ne 1 ]]; then echo "Error: Expected version > ${version_part}, but got ${ACTUAL_VERSION}." && exit 1; fi ;;
|
||||||
|
'<') if [[ ${result} -ne 2 ]]; then echo "Error: Expected version < ${version_part}, but got ${ACTUAL_VERSION}." && exit 1; fi ;;
|
||||||
|
'>=') if [[ ${result} -eq 2 ]]; then echo "Error: Expected version >= ${version_part}, but got ${ACTUAL_VERSION}." && exit 1; fi ;;
|
||||||
|
'<=') if [[ ${result} -eq 1 ]]; then echo "Error: Expected version <= ${version_part}, but got ${ACTUAL_VERSION}." && exit 1; fi ;;
|
||||||
|
*) echo "Error: Unsupported operator '${op}' in spec '${REQUESTED_SPEC}'." && exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "OK: Version ${ACTUAL_VERSION} satisfies spec '${REQUESTED_SPEC}'."
|
||||||
|
|||||||
9
.github/workflows/test.yml
vendored
9
.github/workflows/test.yml
vendored
@@ -54,6 +54,10 @@ jobs:
|
|||||||
- latest
|
- latest
|
||||||
- canary
|
- canary
|
||||||
- "1.1.0"
|
- "1.1.0"
|
||||||
|
- "1.x"
|
||||||
|
- "1"
|
||||||
|
- "> 1.0.0"
|
||||||
|
- "< 2"
|
||||||
# https://github.com/oven-sh/setup-bun/issues/37
|
# https://github.com/oven-sh/setup-bun/issues/37
|
||||||
# - "1.x"
|
# - "1.x"
|
||||||
# - "1"
|
# - "1"
|
||||||
@@ -78,6 +82,11 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
bun --version
|
bun --version
|
||||||
|
|
||||||
|
- name: ⚖️ Verify Bun version
|
||||||
|
uses: ./.github/actions/compare-bun-version
|
||||||
|
with:
|
||||||
|
bun-version: ${{ matrix.bun-version }}
|
||||||
|
|
||||||
setup-bun-from-file:
|
setup-bun-from-file:
|
||||||
name: setup-bun from (${{ matrix.os }}, ${{ matrix.file.name }})
|
name: setup-bun from (${{ matrix.os }}, ${{ matrix.file.name }})
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|||||||
@@ -67,13 +67,14 @@ If you need to override the download URL, you can use the `bun-download-url` inp
|
|||||||
## Inputs
|
## Inputs
|
||||||
|
|
||||||
| Name | Description | Default | Examples |
|
| Name | Description | Default | Examples |
|
||||||
| ------------------ | ----------------------------------------------------- | ----------- | ------------------------------------------------ |
|
| ------------------ | --------------------------------------------------------------------------------- | --------------------- | ------------------------------------------------ |
|
||||||
| `bun-version` | The version of Bun to download and install. | `latest` | `canary`, `1.0.0` |
|
| `bun-version` | The version of Bun to download and install. | `latest` | `canary`, `1.0.0`, `1.0.x` |
|
||||||
| `bun-version-file` | The version of Bun to download and install from file. | `undefined` | `package.json`, `.bun-version`, `.tool-versions` |
|
| `bun-version-file` | The version of Bun to download and install from file. | `undefined` | `package.json`, `.bun-version`, `.tool-versions` |
|
||||||
| `bun-download-url` | URL to download .zip file for Bun release | | |
|
| `bun-download-url` | URL to download .zip file for Bun release | | |
|
||||||
| `registry-url` | Registry URL where some private package is stored. | `undefined` | `"https://npm.pkg.github.com/"` |
|
| `registry-url` | Registry URL where some private package is stored. | `undefined` | `"https://npm.pkg.github.com/"` |
|
||||||
| `scope` | Scope for private packages. | `undefined` | `"@foo"`, `"@orgname"` |
|
| `scope` | Scope for private packages. | `undefined` | `"@foo"`, `"@orgname"` |
|
||||||
| `no-cache` | Disable caching of the downloaded executable. | `false` | `true`, `false` |
|
| `no-cache` | Disable caching of the downloaded executable. | `false` | `true`, `false` |
|
||||||
|
| `token` | Personal access token (PAT) used to fetch tags from the `oven-sh/bun` repository. | `${{ github.token }}` | `${{ secrets.GITHUB_TOKEN }}` |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ inputs:
|
|||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
description: Disable caching of bun executable.
|
description: Disable caching of bun executable.
|
||||||
|
token:
|
||||||
|
required: false
|
||||||
|
default: ${{ github.token }}
|
||||||
|
description: Personal access token (PAT) used to fetch tags from oven-sh/bun repository. Recommended for resolving wildcard/range versions to avoid GitHub API rate limiting.
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
bun-version:
|
bun-version:
|
||||||
|
|||||||
6
bun.lock
6
bun.lock
@@ -11,6 +11,7 @@
|
|||||||
"@actions/io": "^1.1.2",
|
"@actions/io": "^1.1.2",
|
||||||
"@actions/tool-cache": "^2.0.1",
|
"@actions/tool-cache": "^2.0.1",
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
|
"compare-versions": "^6.1.1",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.1.13",
|
"@types/bun": "^1.1.13",
|
||||||
@@ -21,6 +22,9 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"patchedDependencies": {
|
||||||
|
"compare-versions@6.1.1": "patches/compare-versions@6.1.1.patch",
|
||||||
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@actions/cache": ["@actions/cache@4.0.3", "", { "dependencies": { "@actions/core": "^1.11.1", "@actions/exec": "^1.0.1", "@actions/glob": "^0.1.0", "@actions/http-client": "^2.1.1", "@actions/io": "^1.0.1", "@azure/abort-controller": "^1.1.0", "@azure/ms-rest-js": "^2.6.0", "@azure/storage-blob": "^12.13.0", "@protobuf-ts/plugin": "^2.9.4", "semver": "^6.3.1" } }, "sha512-SvrqFtYJ7I48A/uXNkoJrnukx5weQv1fGquhs3+4nkByZThBH109KTIqj5x/cGV7JGNvb8dLPVywUOqX1fjiXg=="],
|
"@actions/cache": ["@actions/cache@4.0.3", "", { "dependencies": { "@actions/core": "^1.11.1", "@actions/exec": "^1.0.1", "@actions/glob": "^0.1.0", "@actions/http-client": "^2.1.1", "@actions/io": "^1.0.1", "@azure/abort-controller": "^1.1.0", "@azure/ms-rest-js": "^2.6.0", "@azure/storage-blob": "^12.13.0", "@protobuf-ts/plugin": "^2.9.4", "semver": "^6.3.1" } }, "sha512-SvrqFtYJ7I48A/uXNkoJrnukx5weQv1fGquhs3+4nkByZThBH109KTIqj5x/cGV7JGNvb8dLPVywUOqX1fjiXg=="],
|
||||||
|
|
||||||
@@ -144,6 +148,8 @@
|
|||||||
|
|
||||||
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||||
|
|
||||||
|
"compare-versions": ["compare-versions@6.1.1", "", {}, "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg=="],
|
||||||
|
|
||||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||||
|
|
||||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||||
|
|||||||
219
dist/setup/index.js
generated
vendored
219
dist/setup/index.js
generated
vendored
File diff suppressed because one or more lines are too long
5
package-lock.json
generated
5
package-lock.json
generated
@@ -461,6 +461,11 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/compare-versions": {
|
||||||
|
"version": "6.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz",
|
||||||
|
"integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg=="
|
||||||
|
},
|
||||||
"node_modules/concat-map": {
|
"node_modules/concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
|
|||||||
@@ -28,7 +28,8 @@
|
|||||||
"@actions/glob": "^0.4.0",
|
"@actions/glob": "^0.4.0",
|
||||||
"@actions/io": "^1.1.2",
|
"@actions/io": "^1.1.2",
|
||||||
"@actions/tool-cache": "^2.0.1",
|
"@actions/tool-cache": "^2.0.1",
|
||||||
"@iarna/toml": "^2.2.5"
|
"@iarna/toml": "^2.2.5",
|
||||||
|
"compare-versions": "^6.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.1.13",
|
"@types/bun": "^1.1.13",
|
||||||
@@ -36,5 +37,8 @@
|
|||||||
"esbuild": "^0.19.2",
|
"esbuild": "^0.19.2",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
|
},
|
||||||
|
"patchedDependencies": {
|
||||||
|
"compare-versions@6.1.1": "patches/compare-versions@6.1.1.patch"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
67
patches/compare-versions@6.1.1.patch
Normal file
67
patches/compare-versions@6.1.1.patch
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
diff --git a/lib/esm/satisfies.js b/lib/esm/satisfies.js
|
||||||
|
index 7586b71657332f855431c4dd4f05e9394fd9aac3..a6ec29bfc98907c67ed4af71fca73bd8bff88798 100644
|
||||||
|
--- a/lib/esm/satisfies.js
|
||||||
|
+++ b/lib/esm/satisfies.js
|
||||||
|
@@ -40,8 +40,9 @@ export const satisfies = (version, range) => {
|
||||||
|
// else range of either "~" or "^" is assumed
|
||||||
|
const [v1, v2, v3, , vp] = validateAndParse(version);
|
||||||
|
const [r1, r2, r3, , rp] = validateAndParse(range);
|
||||||
|
- const v = [v1, v2, v3];
|
||||||
|
+ const v = [v1, v2 !== null && v2 !== void 0 ? v2 : 'x', v3 !== null && v3 !== void 0 ? v3 : 'x'];
|
||||||
|
const r = [r1, r2 !== null && r2 !== void 0 ? r2 : 'x', r3 !== null && r3 !== void 0 ? r3 : 'x'];
|
||||||
|
+
|
||||||
|
// validate pre-release
|
||||||
|
if (rp) {
|
||||||
|
if (!vp)
|
||||||
|
diff --git a/lib/esm/utils.js b/lib/esm/utils.js
|
||||||
|
index b5cc8b9927ab38fc67032c133b531e95ec4cec15..ec56105fd2d806aa922f1488a27b02c56aff1865 100644
|
||||||
|
--- a/lib/esm/utils.js
|
||||||
|
+++ b/lib/esm/utils.js
|
||||||
|
@@ -28,7 +28,7 @@ const compareStrings = (a, b) => {
|
||||||
|
};
|
||||||
|
export const compareSegments = (a, b) => {
|
||||||
|
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
||||||
|
- const r = compareStrings(a[i] || '0', b[i] || '0');
|
||||||
|
+ const r = compareStrings(a[i] || 'x', b[i] || 'x');
|
||||||
|
if (r !== 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
diff --git a/lib/umd/index.js b/lib/umd/index.js
|
||||||
|
index 2cfef261bca520e21ed41fc14950732b8aa6339b..1059784db86635f3aaaba83b5a72c5015e1d8490 100644
|
||||||
|
--- a/lib/umd/index.js
|
||||||
|
+++ b/lib/umd/index.js
|
||||||
|
@@ -152,7 +152,7 @@
|
||||||
|
// else range of either "~" or "^" is assumed
|
||||||
|
const [v1, v2, v3, , vp] = validateAndParse(version);
|
||||||
|
const [r1, r2, r3, , rp] = validateAndParse(range);
|
||||||
|
- const v = [v1, v2, v3];
|
||||||
|
+ const v = [v1, v2 !== null && v2 !== void 0 ? v2 : 'x', v3 !== null && v3 !== void 0 ? v3 : 'x'];
|
||||||
|
const r = [r1, r2 !== null && r2 !== void 0 ? r2 : 'x', r3 !== null && r3 !== void 0 ? r3 : 'x'];
|
||||||
|
// validate pre-release
|
||||||
|
if (rp) {
|
||||||
|
diff --git a/package.json b/package.json
|
||||||
|
index b05b3daf706d7ba4e594233f8791fc3007a8e2cd..e51e76b86f95e9ebf0b5dba3b82aeb119628528d 100644
|
||||||
|
--- a/package.json
|
||||||
|
+++ b/package.json
|
||||||
|
@@ -26,7 +26,7 @@
|
||||||
|
"prepublishOnly": "npm run build",
|
||||||
|
"test": "c8 --reporter=lcov mocha"
|
||||||
|
},
|
||||||
|
- "main": "./lib/umd/index.js",
|
||||||
|
+ "main": "./lib/src/index.ts",
|
||||||
|
"module": "./lib/esm/index.js",
|
||||||
|
"types": "./lib/esm/index.d.ts",
|
||||||
|
"sideEffects": false,
|
||||||
|
diff --git a/src/satisfies.ts b/src/satisfies.ts
|
||||||
|
index 66cb171d7f32e68fdda6929d2da223b97a053737..6b4973f037843f264338a01efdc4ace5dcf042cd 100644
|
||||||
|
--- a/src/satisfies.ts
|
||||||
|
+++ b/src/satisfies.ts
|
||||||
|
@@ -43,7 +43,7 @@ export const satisfies = (version: string, range: string): boolean => {
|
||||||
|
// else range of either "~" or "^" is assumed
|
||||||
|
const [v1, v2, v3, , vp] = validateAndParse(version);
|
||||||
|
const [r1, r2, r3, , rp] = validateAndParse(range);
|
||||||
|
- const v = [v1, v2, v3];
|
||||||
|
+ const v = [v1, v2 ?? 'x', v3 ?? 'x'];
|
||||||
|
const r = [r1, r2 ?? 'x', r3 ?? 'x'];
|
||||||
|
|
||||||
|
// validate pre-release
|
||||||
@@ -13,9 +13,11 @@ import { addPath, info, warning } from "@actions/core";
|
|||||||
import { isFeatureAvailable, restoreCache } from "@actions/cache";
|
import { isFeatureAvailable, restoreCache } from "@actions/cache";
|
||||||
import { downloadTool, extractZip } from "@actions/tool-cache";
|
import { downloadTool, extractZip } from "@actions/tool-cache";
|
||||||
import { getExecOutput } from "@actions/exec";
|
import { getExecOutput } from "@actions/exec";
|
||||||
import { writeBunfig, Registry } from "./bunfig";
|
import { Registry } from "./registry";
|
||||||
|
import { writeBunfig } from "./bunfig";
|
||||||
import { saveState } from "@actions/core";
|
import { saveState } from "@actions/core";
|
||||||
import { addExtension, retry } from "./utils";
|
import { addExtension } from "./utils";
|
||||||
|
import { getDownloadUrl } from "./download-url";
|
||||||
import { cwd } from "node:process";
|
import { cwd } from "node:process";
|
||||||
|
|
||||||
export type Input = {
|
export type Input = {
|
||||||
@@ -27,6 +29,7 @@ export type Input = {
|
|||||||
profile?: boolean;
|
profile?: boolean;
|
||||||
registries?: Registry[];
|
registries?: Registry[];
|
||||||
noCache?: boolean;
|
noCache?: boolean;
|
||||||
|
token?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Output = {
|
export type Output = {
|
||||||
@@ -48,7 +51,7 @@ export default async (options: Input): Promise<Output> => {
|
|||||||
const bunfigPath = join(cwd(), "bunfig.toml");
|
const bunfigPath = join(cwd(), "bunfig.toml");
|
||||||
writeBunfig(bunfigPath, options.registries);
|
writeBunfig(bunfigPath, options.registries);
|
||||||
|
|
||||||
const url = getDownloadUrl(options);
|
const url = await getDownloadUrl(options);
|
||||||
const cacheEnabled = isCacheEnabled(options);
|
const cacheEnabled = isCacheEnabled(options);
|
||||||
|
|
||||||
const binPath = join(homedir(), ".bun", "bin");
|
const binPath = join(homedir(), ".bun", "bin");
|
||||||
@@ -105,8 +108,7 @@ export default async (options: Input): Promise<Output> => {
|
|||||||
|
|
||||||
if (!cacheHit) {
|
if (!cacheHit) {
|
||||||
info(`Downloading a new version of Bun: ${url}`);
|
info(`Downloading a new version of Bun: ${url}`);
|
||||||
// TODO: remove this, temporary fix for https://github.com/oven-sh/setup-bun/issues/73
|
revision = await downloadBun(url, bunPath);
|
||||||
revision = await retry(async () => await downloadBun(url, bunPath), 3);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,24 +194,6 @@ function isCacheEnabled(options: Input): boolean {
|
|||||||
return isFeatureAvailable();
|
return isFeatureAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDownloadUrl(options: Input): string {
|
|
||||||
const { customUrl } = options;
|
|
||||||
if (customUrl) {
|
|
||||||
return customUrl;
|
|
||||||
}
|
|
||||||
const { version, os, arch, avx2, profile } = options;
|
|
||||||
const eversion = encodeURIComponent(version ?? "latest");
|
|
||||||
const eos = encodeURIComponent(os ?? process.platform);
|
|
||||||
const earch = encodeURIComponent(arch ?? process.arch);
|
|
||||||
const eavx2 = encodeURIComponent(avx2 ?? true);
|
|
||||||
const eprofile = encodeURIComponent(profile ?? false);
|
|
||||||
const { href } = new URL(
|
|
||||||
`${eversion}/${eos}/${earch}?avx2=${eavx2}&profile=${eprofile}`,
|
|
||||||
"https://bun.sh/download/",
|
|
||||||
);
|
|
||||||
return href;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function extractBun(path: string): Promise<string> {
|
async function extractBun(path: string): Promise<string> {
|
||||||
for (const entry of readdirSync(path, { withFileTypes: true })) {
|
for (const entry of readdirSync(path, { withFileTypes: true })) {
|
||||||
const { name } = entry;
|
const { name } = entry;
|
||||||
|
|||||||
63
src/download-url.ts
Normal file
63
src/download-url.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { compareVersions, satisfies, validate } from "compare-versions";
|
||||||
|
import { Input } from "./action";
|
||||||
|
import { getArchitecture, getPlatform, request } from "./utils";
|
||||||
|
|
||||||
|
export async function getDownloadUrl(options: Input): Promise<string> {
|
||||||
|
const { customUrl } = options;
|
||||||
|
if (customUrl) {
|
||||||
|
return customUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await getSemverDownloadUrl(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getSemverDownloadUrl(options: Input): Promise<string> {
|
||||||
|
const res = (await (
|
||||||
|
await request("https://api.github.com/repos/oven-sh/bun/git/refs/tags", {
|
||||||
|
headers: options.token
|
||||||
|
? { "Authorization": `Bearer ${options.token}` }
|
||||||
|
: {},
|
||||||
|
})
|
||||||
|
).json()) as { ref: string }[];
|
||||||
|
|
||||||
|
let tags = res
|
||||||
|
.filter(
|
||||||
|
(tag) =>
|
||||||
|
tag.ref.startsWith("refs/tags/bun-v") || tag.ref === "refs/tags/canary",
|
||||||
|
)
|
||||||
|
.map((item) => item.ref.replace(/refs\/tags\/(bun-v)?/g, ""))
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
const { version, os, arch, avx2, profile } = options;
|
||||||
|
|
||||||
|
let tag = tags.find((t) => t === version);
|
||||||
|
if (!tag) {
|
||||||
|
tags = tags.filter((t) => validate(t)).sort(compareVersions);
|
||||||
|
|
||||||
|
const matchedTag =
|
||||||
|
version === "latest" || !version
|
||||||
|
? tags.at(-1)
|
||||||
|
: tags.filter((t) => satisfies(t, version)).at(-1);
|
||||||
|
|
||||||
|
if (!matchedTag) {
|
||||||
|
throw new Error(`No Bun release found matching version '${version}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = `bun-v${matchedTag}`;
|
||||||
|
} else if (validate(tag)) {
|
||||||
|
tag = `bun-v${tag}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const eversion = encodeURIComponent(tag ?? version);
|
||||||
|
const eos = encodeURIComponent(os ?? getPlatform());
|
||||||
|
const earch = encodeURIComponent(arch ?? getArchitecture());
|
||||||
|
const eavx2 = encodeURIComponent(avx2 === false ? "-baseline" : "");
|
||||||
|
const eprofile = encodeURIComponent(profile === true ? "-profile" : "");
|
||||||
|
|
||||||
|
const { href } = new URL(
|
||||||
|
`${eversion}/bun-${eos}-${earch}${eavx2}${eprofile}.zip`,
|
||||||
|
"https://github.com/oven-sh/bun/releases/download/",
|
||||||
|
);
|
||||||
|
|
||||||
|
return href;
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ runAction({
|
|||||||
customUrl: getInput("bun-download-url") || undefined,
|
customUrl: getInput("bun-download-url") || undefined,
|
||||||
registries: registries,
|
registries: registries,
|
||||||
noCache: getBooleanInput("no-cache") || false,
|
noCache: getBooleanInput("no-cache") || false,
|
||||||
|
token: getInput("token"),
|
||||||
})
|
})
|
||||||
.then(({ version, revision, bunPath, url, cacheHit }) => {
|
.then(({ version, revision, bunPath, url, cacheHit }) => {
|
||||||
setOutput("bun-version", version);
|
setOutput("bun-version", version);
|
||||||
|
|||||||
44
src/utils.ts
44
src/utils.ts
@@ -3,19 +3,27 @@ import { info } from "node:console";
|
|||||||
import { existsSync, readFileSync, renameSync } from "node:fs";
|
import { existsSync, readFileSync, renameSync } from "node:fs";
|
||||||
import { resolve, basename } from "node:path";
|
import { resolve, basename } from "node:path";
|
||||||
|
|
||||||
export function retry<T>(
|
export async function request(
|
||||||
fn: () => Promise<T>,
|
url: string,
|
||||||
retries: number,
|
init?: RequestInit,
|
||||||
timeout = 10000,
|
): Promise<Response> {
|
||||||
): Promise<T> {
|
const headers = new Headers(init?.headers);
|
||||||
return fn().catch((err) => {
|
if (!headers.has("User-Agent")) {
|
||||||
if (retries <= 0) {
|
headers.set("User-Agent", "@oven-sh/setup-bun");
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
return new Promise((resolve) => setTimeout(resolve, timeout)).then(() =>
|
|
||||||
retry(fn, retries - 1, timeout),
|
const res = await fetch(url, {
|
||||||
);
|
...init,
|
||||||
|
headers,
|
||||||
});
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const body = await res.text().catch(() => "");
|
||||||
|
throw new Error(
|
||||||
|
`Failed to fetch url ${url}. (status code: ${res.status}, status text: ${res.statusText})${body ? `\n${body}` : ""}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addExtension(path: string, ext: string): string {
|
export function addExtension(path: string, ext: string): string {
|
||||||
@@ -27,6 +35,20 @@ export function addExtension(path: string, ext: string): string {
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPlatform(): string {
|
||||||
|
const platform = process.platform;
|
||||||
|
if (platform === "win32") return "windows";
|
||||||
|
|
||||||
|
return platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getArchitecture(): string {
|
||||||
|
const arch = process.arch;
|
||||||
|
if (arch === "arm64") return "aarch64";
|
||||||
|
|
||||||
|
return arch;
|
||||||
|
}
|
||||||
|
|
||||||
const FILE_VERSION_READERS = {
|
const FILE_VERSION_READERS = {
|
||||||
"package.json": (content: string) => {
|
"package.json": (content: string) => {
|
||||||
const pkg = JSON.parse(content);
|
const pkg = JSON.parse(content);
|
||||||
|
|||||||
Reference in New Issue
Block a user