24 Commits

Author SHA1 Message Date
Jozef Steinhübl
4bc047ad25 release: v2.0.1 (#91)
* build: bump version

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2024-07-15 21:09:36 +02:00
Araxeus
f43b443c1c fix: bun-version-file default value (#90)
fix #89
2024-07-15 14:17:41 +02:00
autofix-ci[bot]
339e277e69 [autofix.ci] apply automated fixes 2024-06-24 13:19:56 +00:00
Jozef Steinhübl
e20a54d1da docs: add bun-path & bun-download-url to outputs table 2024-06-24 15:19:27 +02:00
Jozef Steinhübl
3fcae870de docs: show correct bun-version-file examples (#86)
* docs: .bun-version

* docs: correct bun-version-file examples
2024-06-24 15:15:35 +02:00
Jozef Steinhübl
123c6c4e2f docs: use v2 version 2024-06-23 21:56:22 +02:00
Jozef Steinhübl
ef00e4ac8e release: v2.0 🎉 (#80)
* feat: add input bun-version-file (#76)

* feat: add input for bun-version-file

* docs: update example bun version file

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* refactor: reduce read from file code

* [autofix.ci] apply automated fixes

* feat: read from all known files if not specified

* [autofix.ci] apply automated fixes

* fix: just continue if file doesnt exist

* [autofix.ci] apply automated fixes

* fix: return output if found version

* [autofix.ci] apply automated fixes

* fix: make whitespace in .tool-versions optional

* [autofix.ci] apply automated fixes

* log loglog

* [autofix.ci] apply automated fixes

* log log log

* [autofix.ci] apply automated fixes

* better warnings, fix ci failing

* [autofix.ci] apply automated fixes

* feat: log obtained version

* [autofix.ci] apply automated fixes

* build: bump version

* [autofix.ci] apply automated fixes

* fix: add .zip extension if it's not present

Workaround for https://github.com/actions/toolkit/issues/1179

Fixes https://github.com/oven-sh/setup-bun/issues/79

* [autofix.ci] apply automated fixes

* docs: add comment for easier understanding

* ci: more readable version

* ci: match name

* docs: add package.json and .tool-versions to bun-version-file examples

* ci: add cache test

* ci: install another pkg for cache test

* ci: install more pkgs for cache test

* ci: block all trusted deps in cache test

* ci: more deps for cache test

* ci: cache test should cache

* refactor: dont try all files if not defined

* [autofix.ci] apply automated fixes

* ci: remove cache test

* feat: support .bunrc

* [autofix.ci] apply automated fixes

* refactor: .bun-version instead .bunrc

* [autofix.ci] apply automated fixes

* feat: add bun paths and url to output

Fixes https://github.com/oven-sh/setup-bun/issues/81

* [autofix.ci] apply automated fixes

* ci: test for .bun-version

* feat: make .bun-version as default in bun-version-file

* ci: remove cache before test

* ci: remove cache before test

* ci: remove cache before test

* ci: remove cache before test

---------

Co-authored-by: Ade Hery Shopyan <51158020+adeherysh@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2024-06-21 21:11:16 +02:00
Jarred Sumner
43b2dc9ae8 Update README.md 2024-06-02 04:02:05 -07:00
Jarred Sumner
45d2c09359 Update README.md 2024-06-02 04:01:49 -07:00
Jarred Sumner
6ef34ab578 Update README.md 2024-06-02 04:00:50 -07:00
Jarred Sumner
f4d14e03ff Add bun-download-url to actions.yml and rebuild (#83)
* Add download URL

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2024-06-02 03:52:40 -07:00
Jozef Steinhübl
8f24390df0 fix: close immediately (#75)
* fix

* add test for outputs

* ci: use correct outputs from setup bun

* dist update

* feat: add timeout

* c

* increase

* [autofix.ci] apply automated fixes

* refactor: remove unnecesary loging, decrease retries

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2024-04-03 14:01:25 +02:00
Jozef Steinhübl
932c3b236c fix: retry installing three times, add windows for testing (#72)
* ci: test windows

* ci: specify shell

* ci: we don't have >1.1.0

* fix: retry installing version three times

* [autofix.ci] apply automated fixes

* build: bump version to 1.2.1

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2024-04-02 11:24:51 +02:00
Jozef Steinhübl
9e6479509b feat: support .tool-versions (#68)
* feat: support .tool-versions

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2024-04-02 10:26:15 +02:00
Jozef Steinhübl
194c60efc3 build: bump ci actions (#66)
* ci: update checkout

* ci: update checkout
2024-03-07 11:39:32 +01:00
Max Schwenk
d3603274ac Add no-cache option (#58) 2024-02-23 11:09:38 -08:00
Andy Palmer
0f37bd8169 Move cache save to runs.post and exit early (#60) 2024-02-16 14:14:07 -08:00
Filip Czaplicki
12944059f7 Fix typo in README.md (#57) 2024-02-09 18:03:04 +01:00
Ben Limmer
8642d99a51 docs: add --frozen-lockfile to README (#52)
Many folks will copy/paste the sample code from the README directly. In CI, most people will want to enforce a frozen lockfile.
2024-02-01 17:30:42 -08:00
Jacob Hummer
40646b1808 Add GitHub action to auto-update the v1 tag (#53)
Create release.yml
2024-02-01 17:29:22 -08:00
Paul Razvan Berg
94177e527c docs: add explanatory note about setup-node (#47) 2024-01-03 11:33:26 +01:00
autofix-ci[bot]
9b21598af8 [autofix.ci] apply automated fixes 2023-12-03 12:43:51 +00:00
Jozef Steinhübl (xHyroM)
c7420ae597 release: 1.1.1 2023-12-03 13:43:25 +01:00
Jozef Steinhübl
c0059f0222 fix: package manager (#42)
* fix: read version from package json

* [autofix.ci] apply automated fixes

* Update index.ts

* Update action.yml

* [autofix.ci] apply automated fixes

* yarn does random things

* [autofix.ci] apply automated fixes

* ci: check if version from packageManager is actually 1.0.0

* ci: bash is not javascript

* ci: use  instead ::set-output

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2023-12-03 13:42:54 +01:00
14 changed files with 446 additions and 116 deletions

View File

@@ -0,0 +1,28 @@
name: Compare Bun Version
description: Compare the version of Bun to a specified version
inputs:
bun-version:
description: "The version of Bun to compare against"
required: true
default: "1.1.0"
runs:
using: "composite"
steps:
- name: Get installed Bun version
id: bun
shell: bash
run: |
bun --version
echo "version=$(bun --version)" >> $GITHUB_OUTPUT
- name: Compare versions
shell: bash
run: |
if [[ "${{ steps.bun.outputs.version }}" == "${{ inputs.bun-version }}" ]]; then
echo "Version is ${{ inputs.bun-version }}"
else
echo "Expected version to be ${{ inputs.bun-version }}, got ${{ steps.bun.outputs.version }}"
exit 1
fi

25
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: Release new action version
on:
release:
types: [released]
workflow_dispatch:
inputs:
TAG_NAME:
description: 'Tag name that the major tag will point to'
required: true
env:
TAG_NAME: ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }}
jobs:
update_tag:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/publish-action@v0.3.0
with:
source-tag: ${{ env.TAG_NAME }}

View File

@@ -8,26 +8,45 @@ on:
- main
permissions:
contents: read
contents: write
jobs:
remove-cache:
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install github cli
run: |
(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
&& sudo mkdir -p -m 755 /etc/apt/keyrings \
&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& sudo apt update \
&& sudo apt install gh -y
- run: |
gh cache delete --all || true
env:
GH_TOKEN: ${{ github.token }}
setup-bun:
runs-on: ${{ matrix.os }}
continue-on-error: true
needs: [remove-cache]
strategy:
matrix:
include:
- os: windows-latest
bun-version: canary
os:
- ubuntu-latest
- macos-latest
- windows-latest
bun-version:
- latest
- canary
- "0.8.1" # last version before 1.0
- "0.x"
- "1.0.0"
- "1.1.0"
- "1.x"
- "1"
- "> 1.0.0"
@@ -38,28 +57,67 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Bun
uses: ./
id: setup_bun
with:
bun-version: ${{ matrix.bun-version }}
- name: Run Bun
id: run_bun
run: |
bun --version
setup-bun-from-package-json-version:
setup-bun-from-file:
name: setup-bun from (${{ matrix.os }}, ${{ matrix.file.name }})
runs-on: ${{ matrix.os }}
continue-on-error: true
needs: [remove-cache]
strategy:
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
file:
- name: package.json (bun@1.1.0)
file: package.json
run: |
echo "$(jq '. += {"packageManager": "bun@1.1.0"}' package.json)" > package.json
- name: package.json (yarn@bun@1.1.0)
file: package.json
run: |
echo "$(jq '. += {"packageManager": "yarn@bun@1.1.0"}' package.json)" > package.json
- name: .tool-versions (bun 1.1.0)
file: .tool-versions
run: |
echo "bun 1.1.0" > .tool-versions
- name: .tool-versions (bun1.1.0)
file: .tool-versions
run: |
echo "bun1.1.0" > .tool-versions
- name: .bumrc (1.1.0)
file: .bumrc
run: |
echo "1.1.0" > .bumrc
- name: .bun-version (1.1.0)
file: .bun-version
run: |
echo "1.1.0" > .bun-version
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup package.json
run: |
echo "$(jq '. += {"packageManager": "bun@1.0.0"}' package.json)" > package.json
uses: actions/checkout@v4
- name: Setup file
run: ${{ matrix.file.run }}
- name: Setup Bun
uses: ./
- name: Run Bun
run: |
bun --version
with:
bun-version-file: ${{ matrix.file.file }}
- name: Compare versions
uses: ./.github/actions/compare-bun-version
with:
bun-version: "1.1.0"

View File

@@ -5,15 +5,23 @@ Download, install, and setup [Bun](https://bun.sh) in GitHub Actions.
## Usage
```yaml
- uses: oven-sh/setup-bun@v1
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
```
## Using version file
```yaml
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: ".bun-version"
```
### Using a custom NPM registry
```yaml
- uses: oven-sh/setup-bun@v1
- uses: oven-sh/setup-bun@v2
with:
registry-url: "https://npm.pkg.github.com/"
scope: "@foo"
@@ -25,21 +33,39 @@ If you need to authenticate with a private registry, you can set the `BUN_AUTH_T
- name: Install Dependencies
env:
BUN_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: bun install
run: bun install --frozen-lockfile
```
### Override download url
If you need to override the download URL, you can use the `bun-download-url` input.
```yaml
- uses: oven-sh/setup-bun
with:
bun-download-url: "https://github.com/oven-sh/bun/releases/latest/download/bun-linux-x64.zip"
```
### Node.js not needed
In most cases, you shouldn't need to use the [setup-node](https://github.com/actions/setup-node) GitHub Action.
## Inputs
| Name | Description | Default | Examples |
| -------------- | -------------------------------------------------- | ----------- | ------------------------------- |
| `bun-version` | The version of Bun to download and install. | `latest` | `canary`, `1.0.0`, `1.0.x` |
| `registry-url` | Registry URL where some private package is stored. | `undefined` | `"https://npm.pkg.github.com/"` |
| `scope` | Scope for private pacakages. | `undefined` | `"@foo"`, `"@orgname"` |
| Name | Description | Default | Examples |
| ------------------ | ----------------------------------------------------- | ----------- | ------------------------------------------------ |
| `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-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/"` |
| `scope` | Scope for private packages. | `undefined` | `"@foo"`, `"@orgname"` |
## Outputs
| Name | Description | Example |
| -------------- | ------------------------------------------ | ---------------- |
| `cache-hit` | If the Bun executable was read from cache. | `true` |
| `bun-version` | The output from `bun --version`. | `1.0.0` |
| `bun-revision` | The output from `bun --revision`. | `1.0.0+822a00c4` |
| Name | Description | Example |
| ------------------ | ------------------------------------------ | ------------------------------------------------------------------ |
| `bun-version` | The output from `bun --version`. | `1.0.0` |
| `bun-revision` | The output from `bun --revision`. | `1.0.0+822a00c4` |
| `bun-path` | The path to the Bun executable. | `/path/to/bun` |
| `bun-download-url` | The URL from which Bun was downloaded. | `https://bun.sh/download/latest/linux/x64?avx2=true&profile=false` |
| `cache-hit` | If the Bun executable was read from cache. | `true` |

View File

@@ -7,7 +7,13 @@ branding:
inputs:
bun-version:
description: 'The version of Bun to install. (e.g. "latest", "canary", "1.0.0", "1.0.x", <sha>)'
default: latest
required: false
bun-version-file:
description: 'The version of Bun to install from file. (e.g. "package.json", ".bun-version", ".tool-versions")'
default: null
required: false
bun-download-url:
description: "Override the URL to download Bun from. This skips version resolution and verifying AVX2 support."
required: false
registry-url:
required: false
@@ -15,13 +21,25 @@ inputs:
scope:
required: false
description: "The scope for authenticating with the package registry."
no-cache:
required: false
type: boolean
default: false
description: "Disable caching of bun executable."
outputs:
bun-version:
description: The version of Bun that was installed.
bun-revision:
description: The revision of Bun that was installed.
bun-path:
description: The path to the Bun executable.
bun-download-url:
description: The URL from which Bun was downloaded.
cache-hit:
description: If the version of Bun was cached.
runs:
using: node20
main: dist/index.js
using: "node20"
main: "dist/setup/index.js"
post: "dist/cache-save/index.js"
post-if: success()

BIN
bun.lockb

Binary file not shown.

68
dist/cache-save/index.js generated vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "setup-bun",
"version": "1.1.0",
"version": "2.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "setup-bun",
"version": "1.1.0",
"version": "2.0.1",
"license": "MIT",
"dependencies": {
"@actions/cache": "^3.1.4",

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "setup-bun",
"version": "1.1.0",
"version": "2.0.1",
"description": "Setup Bun on GitHub Actions.",
"keywords": [
"bun",
@@ -18,8 +18,8 @@
"author": "xHyroM",
"scripts": {
"format": "prettier --write src *.yml *.json *.md",
"build": "esbuild --target=node20 --outdir=dist --bundle --minify --platform=node --format=cjs src/index.ts",
"start": "npm run build && node dist/index.js"
"build": "esbuild --target=node20 --outfile=dist/setup/index.js --bundle --minify --platform=node --format=cjs src/index.ts && esbuild --target=node20 --outfile=dist/cache-save/index.js --bundle --minify --platform=node --format=cjs src/cache-save.ts",
"start": "npm run build && node dist/setup/index.js"
},
"dependencies": {
"@actions/cache": "^3.1.4",

View File

@@ -8,10 +8,12 @@ import {
copyFileSync,
} from "node:fs";
import { addPath, info, warning } from "@actions/core";
import { isFeatureAvailable, restoreCache, saveCache } from "@actions/cache";
import { isFeatureAvailable, restoreCache } from "@actions/cache";
import { downloadTool, extractZip } from "@actions/tool-cache";
import { getExecOutput } from "@actions/exec";
import { writeBunfig } from "./bunfig";
import { saveState } from "@actions/core";
import { addExtension, retry } from "./utils";
export type Input = {
customUrl?: string;
@@ -22,14 +24,24 @@ export type Input = {
profile?: boolean;
scope?: string;
registryUrl?: string;
noCache?: boolean;
};
export type Output = {
version: string;
revision: string;
bunPath: string;
url: string;
cacheHit: boolean;
};
export type CacheState = {
cacheEnabled: boolean;
cacheHit: boolean;
bunPath: string;
url: string;
};
export default async (options: Input): Promise<Output> => {
const bunfigPath = join(process.cwd(), "bunfig.toml");
writeBunfig(bunfigPath, options);
@@ -77,17 +89,8 @@ export default async (options: Input): Promise<Output> => {
if (!cacheHit) {
info(`Downloading a new version of Bun: ${url}`);
const zipPath = await downloadTool(url);
const extractedZipPath = await extractZip(zipPath);
const extractedBunPath = await extractBun(extractedZipPath);
try {
renameSync(extractedBunPath, bunPath);
} catch {
// If mv does not work, try to copy the file instead.
// For example: EXDEV: cross-device link not permitted
copyFileSync(extractedBunPath, bunPath);
}
revision = await getRevision(bunPath);
// TODO: remove this, temporary fix for https://github.com/oven-sh/setup-bun/issues/73
revision = await retry(async () => await downloadBun(url, bunPath), 3);
}
if (!revision) {
@@ -96,24 +99,50 @@ export default async (options: Input): Promise<Output> => {
);
}
if (cacheEnabled && !cacheHit) {
try {
await saveCache([bunPath], url);
} catch (error) {
warning("Failed to save Bun to cache.");
}
}
const [version] = revision.split("+");
const cacheState: CacheState = {
cacheEnabled,
cacheHit,
bunPath,
url,
};
saveState("cache", JSON.stringify(cacheState));
return {
version,
revision,
bunPath,
url,
cacheHit,
};
};
async function downloadBun(
url: string,
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(url), ".zip");
const extractedZipPath = await extractZip(zipPath);
const extractedBunPath = await extractBun(extractedZipPath);
try {
renameSync(extractedBunPath, bunPath);
} catch {
// If mv does not work, try to copy the file instead.
// For example: EXDEV: cross-device link not permitted
copyFileSync(extractedBunPath, bunPath);
}
return await getRevision(bunPath);
}
function isCacheEnabled(options: Input): boolean {
const { customUrl, version } = options;
const { customUrl, version, noCache } = options;
if (noCache) {
return false;
}
if (customUrl) {
return false;
}

15
src/cache-save.ts Normal file
View File

@@ -0,0 +1,15 @@
import { saveCache } from "@actions/cache";
import { getState, warning } from "@actions/core";
import { CacheState } from "./action";
(async () => {
const state: CacheState = JSON.parse(getState("cache"));
if (state.cacheEnabled && !state.cacheHit) {
try {
await saveCache([state.bunPath], state.url);
process.exit(0);
} catch (error) {
warning("Failed to save Bun to cache.");
}
}
})();

View File

@@ -1,46 +1,31 @@
import { tmpdir } from "node:os";
import { join } from "node:path";
import { existsSync, readFileSync } from "node:fs";
import { getInput, setOutput, setFailed, warning } from "@actions/core";
import { getInput, setOutput, setFailed, getBooleanInput } from "@actions/core";
import runAction from "./action.js";
import { readVersionFromFile } from "./utils.js";
if (!process.env.RUNNER_TEMP) {
process.env.RUNNER_TEMP = tmpdir();
}
function readVersionFromPackageJson(): string | undefined {
const cwd = process.env.GITHUB_WORKSPACE;
if (!cwd) {
return;
}
const path = join(cwd, "package.json");
try {
if (!existsSync(path)) {
return;
}
const { packageManager } = JSON.parse(readFileSync(path, "utf8"));
if (!packageManager?.startsWith("bun@")) {
return;
}
const [_, version] = packageManager.split("bun@");
return version;
} catch (error) {
const { message } = error as Error;
warning(`Failed to read package.json: ${message}`);
}
}
runAction({
version: getInput("bun-version") || readVersionFromPackageJson() || undefined,
version:
getInput("bun-version") ||
readVersionFromFile(getInput("bun-version-file")) ||
undefined,
customUrl: getInput("bun-download-url") || undefined,
registryUrl: getInput("registry-url") || undefined,
scope: getInput("scope") || undefined,
noCache: getBooleanInput("no-cache") || false,
})
.then(({ version, revision, cacheHit }) => {
.then(({ version, revision, bunPath, url, cacheHit }) => {
setOutput("bun-version", version);
setOutput("bun-revision", revision);
setOutput("bun-path", bunPath);
setOutput("bun-download-url", url);
setOutput("cache-hit", cacheHit);
process.exit(0);
})
.catch((error) => {
setFailed(error);
process.exit(1);
});

78
src/utils.ts Normal file
View File

@@ -0,0 +1,78 @@
import { debug, warning } from "@actions/core";
import { info } from "node:console";
import { existsSync, readFileSync, renameSync } from "node:fs";
import { join, basename } from "node:path";
export function retry<T>(
fn: () => Promise<T>,
retries: number,
timeout = 10000
): Promise<T> {
return fn().catch((err) => {
if (retries <= 0) {
throw err;
}
return new Promise((resolve) => setTimeout(resolve, timeout)).then(() =>
retry(fn, retries - 1, timeout)
);
});
}
export function addExtension(path: string, ext: string): string {
if (!path.endsWith(ext)) {
renameSync(path, path + ext);
return path + ext;
}
return path;
}
const FILE_VERSION_READERS = {
"package.json": (content: string) =>
JSON.parse(content).packageManager?.split("bun@")?.[1],
".tool-versions": (content: string) =>
content.match(/^bun\s?(?<version>.*?)$/m)?.groups?.version,
".bumrc": (content: string) => content, // https://github.com/owenizedd/bum
".bun-version": (content: string) => content,
};
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 = join(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();
if (!output) {
warning(`Failed to read version from ${file}`);
return;
}
} catch (error) {
const { message } = error as Error;
warning(`Failed to read ${file}: ${message}`);
} finally {
if (output) {
info(`Obtained version ${output} from ${file}`);
return output;
}
}
}