diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..3c91e02 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "semi": false, + "quoteProps": "preserve" +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..3ccc89d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["esbenp.prettier-vscode", "github.vscode-github-actions"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..65a1965 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.defaultFormatter": "esbenp.prettier-vscode" +} diff --git a/bun.lock b/bun.lock old mode 100755 new mode 100644 index 98c4b12..677f11c --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "dependencies": { @@ -13,7 +13,7 @@ "devDependencies": { "@types/node": "^20.8.2", "esbuild": "^0.19.2", - "prettier": "^2.8.4", + "prettier": "^3.4.2", "typescript": "^4.9.5", }, }, @@ -139,7 +139,7 @@ "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], - "prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="], + "prettier": ["prettier@3.4.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ=="], "process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="], diff --git a/package-lock.json b/package-lock.json index 2ed5f16..b0cb2db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "devDependencies": { "@types/node": "^20.8.2", "esbuild": "^0.19.2", - "prettier": "^2.8.4", + "prettier": "^3.4.2", "typescript": "^4.9.5" } }, @@ -473,14 +473,16 @@ } }, "node_modules/prettier": { - "version": "2.8.8", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "dev": true, "license": "MIT", "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" diff --git a/package.json b/package.json index fe16227..39d1caa 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,7 @@ "devDependencies": { "@types/node": "^20.8.2", "esbuild": "^0.19.2", - "prettier": "^2.8.4", + "prettier": "^3.4.2", "typescript": "^4.9.5" - }, - "prettier": { - "quoteProps": "preserve" } } diff --git a/src/action.ts b/src/action.ts index 2e4fdae..7a2029f 100644 --- a/src/action.ts +++ b/src/action.ts @@ -1,117 +1,117 @@ -import { createHash } from "node:crypto"; -import { homedir } from "node:os"; -import { join } from "node:path"; +import { createHash } from "node:crypto" +import { homedir } from "node:os" +import { join } from "node:path" import { mkdirSync, readdirSync, symlinkSync, renameSync, copyFileSync, -} from "node:fs"; -import { addPath, info, warning } from "@actions/core"; -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"; +} from "node:fs" +import { addPath, info, warning } from "@actions/core" +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; - version?: string; - os?: string; - arch?: string; - avx2?: boolean; - profile?: boolean; - scope?: string; - registryUrl?: string; - noCache?: boolean; -}; + customUrl?: string + version?: string + os?: string + arch?: string + avx2?: boolean + profile?: boolean + scope?: string + registryUrl?: string + noCache?: boolean +} export type Output = { - version: string; - revision: string; - bunPath: string; - url: string; - cacheHit: boolean; -}; + version: string + revision: string + bunPath: string + url: string + cacheHit: boolean +} export type CacheState = { - cacheEnabled: boolean; - cacheHit: boolean; - bunPath: string; - url: string; -}; + cacheEnabled: boolean + cacheHit: boolean + bunPath: string + url: string +} export default async (options: Input): Promise => { - const bunfigPath = join(process.cwd(), "bunfig.toml"); - writeBunfig(bunfigPath, options); + const bunfigPath = join(process.cwd(), "bunfig.toml") + writeBunfig(bunfigPath, options) - const url = getDownloadUrl(options); - const cacheEnabled = isCacheEnabled(options); + const url = getDownloadUrl(options) + const cacheEnabled = isCacheEnabled(options) - const binPath = join(homedir(), ".bun", "bin"); + const binPath = join(homedir(), ".bun", "bin") try { - mkdirSync(binPath, { recursive: true }); + mkdirSync(binPath, { recursive: true }) } catch (error) { if (error.code !== "EEXIST") { - throw error; + throw error } } - addPath(binPath); + addPath(binPath) const exe = (name: string) => - process.platform === "win32" ? `${name}.exe` : name; - const bunPath = join(binPath, exe("bun")); + process.platform === "win32" ? `${name}.exe` : name + const bunPath = join(binPath, exe("bun")) try { - symlinkSync(bunPath, join(binPath, exe("bunx"))); + symlinkSync(bunPath, join(binPath, exe("bunx"))) } catch (error) { if (error.code !== "EEXIST") { - throw error; + throw error } } - let revision: string | undefined; - let cacheHit = false; + let revision: string | undefined + let cacheHit = false if (cacheEnabled) { - const cacheKey = createHash("sha1").update(url).digest("base64"); + const cacheKey = createHash("sha1").update(url).digest("base64") - const cacheRestored = await restoreCache([bunPath], cacheKey); + const cacheRestored = await restoreCache([bunPath], cacheKey) if (cacheRestored) { - revision = await getRevision(bunPath); + revision = await getRevision(bunPath) if (revision) { - cacheHit = true; - info(`Using a cached version of Bun: ${revision}`); + cacheHit = true + info(`Using a cached version of Bun: ${revision}`) } else { warning( - `Found a cached version of Bun: ${revision} (but it appears to be corrupted?)` - ); + `Found a cached version of Bun: ${revision} (but it appears to be corrupted?)`, + ) } } } 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 retry(async () => await downloadBun(url, bunPath), 3); + revision = await retry(async () => await downloadBun(url, bunPath), 3) } if (!revision) { throw new Error( - "Downloaded a new version of Bun, but failed to check its version? Try again." - ); + "Downloaded a new version of Bun, but failed to check its version? Try again.", + ) } - const [version] = revision.split("+"); + const [version] = revision.split("+") const cacheState: CacheState = { cacheEnabled, cacheHit, bunPath, url, - }; + } - saveState("cache", JSON.stringify(cacheState)); + saveState("cache", JSON.stringify(cacheState)) return { version, @@ -119,92 +119,92 @@ export default async (options: Input): Promise => { bunPath, url, cacheHit, - }; -}; + } +} async function downloadBun( url: string, - bunPath: string + bunPath: string, ): Promise { // 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); + const zipPath = addExtension(await downloadTool(url), ".zip") + const extractedZipPath = await extractZip(zipPath) + const extractedBunPath = await extractBun(extractedZipPath) try { - renameSync(extractedBunPath, bunPath); + 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); + copyFileSync(extractedBunPath, bunPath) } - return await getRevision(bunPath); + return await getRevision(bunPath) } function isCacheEnabled(options: Input): boolean { - const { customUrl, version, noCache } = options; + const { customUrl, version, noCache } = options if (noCache) { - return false; + return false } if (customUrl) { - return false; + return false } if (!version || /latest|canary|action/i.test(version)) { - return false; + return false } - return isFeatureAvailable(); + return isFeatureAvailable() } function getDownloadUrl(options: Input): string { - const { customUrl } = options; + const { customUrl } = options if (customUrl) { - return 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 { 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; + "https://bun.sh/download/", + ) + return href } async function extractBun(path: string): Promise { for (const entry of readdirSync(path, { withFileTypes: true })) { - const { name } = entry; - const entryPath = join(path, name); + const { name } = entry + const entryPath = join(path, name) if (entry.isFile()) { if (name === "bun" || name === "bun.exe") { - return entryPath; + return entryPath } if (/^bun.*\.zip/.test(name)) { - const extractedPath = await extractZip(entryPath); - return extractBun(extractedPath); + const extractedPath = await extractZip(entryPath) + return extractBun(extractedPath) } } if (/^bun/.test(name) && entry.isDirectory()) { - return extractBun(entryPath); + return extractBun(entryPath) } } - throw new Error("Could not find executable: bun"); + throw new Error("Could not find executable: bun") } async function getRevision(exe: string): Promise { const revision = await getExecOutput(exe, ["--revision"], { ignoreReturnCode: true, - }); + }) if (revision.exitCode === 0 && /^\d+\.\d+\.\d+/.test(revision.stdout)) { - return revision.stdout.trim(); + return revision.stdout.trim() } const version = await getExecOutput(exe, ["--version"], { ignoreReturnCode: true, - }); + }) if (version.exitCode === 0 && /^\d+\.\d+\.\d+/.test(version.stdout)) { - return version.stdout.trim(); + return version.stdout.trim() } - return undefined; + return undefined } diff --git a/src/bunfig.ts b/src/bunfig.ts index b408f5f..f80302f 100644 --- a/src/bunfig.ts +++ b/src/bunfig.ts @@ -1,50 +1,50 @@ -import { EOL } from "node:os"; -import { appendFileSync } from "node:fs"; -import { info } from "@actions/core"; +import { EOL } from "node:os" +import { appendFileSync } from "node:fs" +import { info } from "@actions/core" type BunfigOptions = { - registryUrl?: string; - scope?: string; -}; + registryUrl?: string + scope?: string +} export function createBunfig(options: BunfigOptions): string | null { - const { registryUrl, scope } = options; + const { registryUrl, scope } = options - let url: URL | undefined; + let url: URL | undefined if (registryUrl) { try { - url = new URL(registryUrl); + url = new URL(registryUrl) } catch { - throw new Error(`Invalid registry-url: ${registryUrl}`); + throw new Error(`Invalid registry-url: ${registryUrl}`) } } - let owner: string | undefined; + let owner: string | undefined if (scope) { owner = scope.startsWith("@") ? scope.toLocaleLowerCase() - : `@${scope.toLocaleLowerCase()}`; + : `@${scope.toLocaleLowerCase()}` } if (url && owner) { - return `[install.scopes]${EOL}'${owner}' = { token = "$BUN_AUTH_TOKEN", url = "${url}"}${EOL}`; + return `[install.scopes]${EOL}'${owner}' = { token = "$BUN_AUTH_TOKEN", url = "${url}"}${EOL}` } if (url && !owner) { - return `[install]${EOL}registry = "${url}"${EOL}`; + return `[install]${EOL}registry = "${url}"${EOL}` } - return null; + return null } export function writeBunfig(path: string, options: BunfigOptions): void { - const bunfig = createBunfig(options); + const bunfig = createBunfig(options) if (!bunfig) { - return; + return } - info(`Writing bunfig.toml to '${path}'.`); + info(`Writing bunfig.toml to '${path}'.`) appendFileSync(path, bunfig, { encoding: "utf8", - }); + }) } diff --git a/src/cache-save.ts b/src/cache-save.ts index 566e219..988e764 100644 --- a/src/cache-save.ts +++ b/src/cache-save.ts @@ -1,18 +1,17 @@ -import { saveCache } from "@actions/cache"; -import { getState, warning } from "@actions/core"; -import { CacheState } from "./action"; -import { createHash } from "node:crypto"; - -(async () => { - const state: CacheState = JSON.parse(getState("cache")); +import { saveCache } from "@actions/cache" +import { getState, warning } from "@actions/core" +import { CacheState } from "./action" +import { createHash } from "node:crypto" +;(async () => { + const state: CacheState = JSON.parse(getState("cache")) if (state.cacheEnabled && !state.cacheHit) { - const cacheKey = createHash("sha1").update(state.url).digest("base64"); + const cacheKey = createHash("sha1").update(state.url).digest("base64") try { - await saveCache([state.bunPath], cacheKey); - process.exit(0); + await saveCache([state.bunPath], cacheKey) + process.exit(0) } catch (error) { - warning("Failed to save Bun to cache."); + warning("Failed to save Bun to cache.") } } -})(); +})() diff --git a/src/index.ts b/src/index.ts index e7578d8..03a17fb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,10 @@ -import { tmpdir } from "node:os"; -import { getInput, setOutput, setFailed, getBooleanInput } from "@actions/core"; -import runAction from "./action.js"; -import { readVersionFromFile } from "./utils.js"; +import { tmpdir } from "node:os" +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(); + process.env.RUNNER_TEMP = tmpdir() } runAction({ @@ -18,14 +18,14 @@ runAction({ noCache: getBooleanInput("no-cache") || false, }) .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); + 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); - }); + setFailed(error) + process.exit(1) + }) diff --git a/src/utils.ts b/src/utils.ts index 7e0ca63..dce6c59 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,30 +1,30 @@ -import { debug, warning } from "@actions/core"; -import { info } from "node:console"; -import { existsSync, readFileSync, renameSync } from "node:fs"; -import { resolve, basename } from "node:path"; +import { debug, warning } from "@actions/core" +import { info } from "node:console" +import { existsSync, readFileSync, renameSync } from "node:fs" +import { resolve, basename } from "node:path" export function retry( fn: () => Promise, retries: number, - timeout = 10000 + timeout = 10000, ): Promise { return fn().catch((err) => { if (retries <= 0) { - throw err; + throw err } return new Promise((resolve) => setTimeout(resolve, timeout)).then(() => - retry(fn, retries - 1, timeout) - ); - }); + retry(fn, retries - 1, timeout), + ) + }) } export function addExtension(path: string, ext: string): string { if (!path.endsWith(ext)) { - renameSync(path, path + ext); - return path + ext; + renameSync(path, path + ext) + return path + ext } - return path; + return path } const FILE_VERSION_READERS = { @@ -34,45 +34,45 @@ const FILE_VERSION_READERS = { content.match(/^bun\s*(?.*?)$/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; + const cwd = process.env.GITHUB_WORKSPACE if (!cwd) { - return; + return } if (!file) { - return; + return } - debug(`Reading version from ${file}`); + debug(`Reading version from ${file}`) - const path = resolve(cwd, file); - const base = basename(file); + const path = resolve(cwd, file) + const base = basename(file) if (!existsSync(path)) { - warning(`File ${path} not found`); - return; + warning(`File ${path} not found`) + return } - const reader = FILE_VERSION_READERS[base] ?? (() => undefined); + const reader = FILE_VERSION_READERS[base] ?? (() => undefined) - let output: string | undefined; + let output: string | undefined try { - output = reader(readFileSync(path, "utf8"))?.trim(); + output = reader(readFileSync(path, "utf8"))?.trim() if (!output) { - warning(`Failed to read version from ${file}`); - return; + warning(`Failed to read version from ${file}`) + return } } catch (error) { - const { message } = error as Error; - warning(`Failed to read ${file}: ${message}`); + const { message } = error as Error + warning(`Failed to read ${file}: ${message}`) } finally { if (output) { - info(`Obtained version ${output} from ${file}`); - return output; + info(`Obtained version ${output} from ${file}`) + return output } } }