From 8c0b79709723837c73777558aaa0565abb026928 Mon Sep 17 00:00:00 2001 From: Vitor Gomes Date: Thu, 16 Nov 2023 16:07:00 -0300 Subject: [PATCH] feat: merge local bunfig with action scope/registry config --- .github/workflows/action.yml | 20 +++++ README.md | 8 +- bun.lockb | Bin 30915 -> 31279 bytes dist/action.js | 17 ++++- package.json | 3 +- src/auth.spec.ts | 139 +++++++++++++++++++++++++++++++++++ src/auth.ts | 25 +++++-- tsconfig.json | 3 +- 8 files changed, 201 insertions(+), 14 deletions(-) create mode 100644 src/auth.spec.ts diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index fc78a6a4..5b3873c8 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -7,6 +7,7 @@ on: branches: - main workflow_dispatch: + jobs: setup-bun: runs-on: ${{ matrix.os }} @@ -25,17 +26,21 @@ jobs: - id: checkout name: Checkout uses: actions/checkout@v3 + - id: setup-bun name: Setup Bun uses: ./ with: bun-version: ${{ matrix.bun-version }} + - id: verify-bun name: Verify Bun run: | bun --version + setup-bun-from-package-json-version: runs-on: ${{ matrix.os }} + needs: setup-bun strategy: matrix: os: @@ -44,11 +49,26 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 + - name: Setup package.json run: | echo "$(jq '. += {"packageManager": "bun@1.0.0"}' package.json)" > package.json + - name: Setup Bun uses: ./ + - name: Verify Bun run: | bun --version + + tests: + name: Run tests + needs: setup-bun + runs-on: 'ubuntu-latest' + + steps: + - name: Setup Bun + uses: ./ + + - name: Run tests + run: bun test --coverage diff --git a/README.md b/README.md index f224effd..1f5f2eca 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,19 @@ Download, install, and setup [Bun](https://bun.sh) in GitHub Actions. ## Usage ```yaml -- uses: oven-sh/setup-bun@v1 +- uses: oven-sh/setup-bun@v1.1.1 with: bun-version: latest ``` ### Setup custom registry-url and scope (for private packages) +For better DX and not having to expose the Github Token locally and inside repo commits, it would be wise to remove any `[install.scopes]` from a local `bunfig.toml` and move it to a global config file, that way each developer will have it's own file, it's not exposed to the repo and it also makes sure that each developer can manage the expiration date. + +[About global config](https://bun.sh/docs/runtime/bunfig#global-vs-local) + ```yaml -- uses: oven-sh/setup-bun@v1 +- uses: oven-sh/setup-bun@main # Or release version greater than v1 with: registry-url: "https://npm.pkg.github.com/" scope: "@foo-bar" diff --git a/bun.lockb b/bun.lockb index 34e7699193feac472440aa1f84e40c0ca1c6f72f..28875514a372a38ac401d5940983eee8f2024b11 100755 GIT binary patch delta 4489 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 delta 4317 zcmeHKeN2_t89(RB1zr#VLGNB}5&S5#idPU2g_c)ZNtshHkHtQ^ttZiIdZ8GoFbfit!O_N!d*4iv%w2d`smHnRczHcv0Y_}!b z{@TfX&U2pc=bZbz=i~UN^31p#@Z9A}5LZ_uOq@-lzv)c5@xRn;jhOq0l259t%bSWtsUE29~NRA#?j!904K7%v!$)M zO^EAKh*;3udOAB>+l5#Tc?{@u3)_B*E!sCl2##|IIQ9+BLtWC?Mp0vwnfjjF9Hi-&rENDCjig+oXjXGM-A&-%kPbJ1L0%b7-Kh_fi1;b_$|DPFkcPuTyEHp{1c1P)UA4@!`303k4xLL7HZ0aahW`m1NYJE6XUL z8FGMv=)*~iGUP9*6#W$npr1*>C_}G9$*hG13iT_kf@Vj5TfR!A(T3xTaQb0%fh?q8 zG`rKL8gi6M(Wg>is-Ydi|Cp_U4o2r{mqFbFDw>djmW)5&!|rJ?Dp#(eK#UaGZK zsXToQYMHXd;%Ey{aQU_;*-C*p!+8|ELW+sVmmiT9Z#WmB%nE65biT6_qxP)?QUC@Ax<7>&%ul4=QtY@|~3M<|eBI0;2pM0*qR zoqxcnSdEfVMI~y~ijgTj`Xz51BU3LIMP*9+FfuL9U{t1TV^PBF>;!yl51tX;F=lX)%P+O6Bh=MyBmzd>N)*A4bf}q5)@EKmHot3k0f& zKULLkhaHe$VuH&IQ&4R(W9MQN=r4y%+Cbi!x1?E4wwsIKFWwUG{O50^HBtmQg z*l{^a=~$9W=Y=e_}YiW7c9f?RL(m*PLN=IWJQG9W3x)`?)UcdtMm6vl!|s*k@}wuR$C$+*L3k zU(7F)w5%X?##)^B_$kBI?xvo$_7?Hfa7V$I9DZoU*tDp3*Oa@hd=$#R2C(|6XJCs-EeOLvx8IgEiC1sM2$8>nX#NA;btQk)i*6*D1$y zdw$dwvNXLPtm?o$Fm}BeO_w8d-})?fx|P|q@u%u&oQ zQC;!&>P;U9-&0yDYB>EFTHi2Bl{?QeF*WmR(^N~rY3lME^;PR`>u&Eqe0t%Og5XEX z)MS>j{U>z1dNs6eLd$-ST=~uEQ@eLoq(LhSiv=woW!C7jlUCK}Zu^yUGH*uL-q-Fw z>X3fx9dnraYrZ3o(bXEuqx6$^gD#n`)5wM-#2MOP$-MTvV`9#phn`yd*I%neKs+J7 zK7##%>bvO892uKdqHNS`RSaC}J8E_JE*#IeLi*2pCZ4O>GS&qx%)*m}w-X(#)#ZMA zrS_!6YpYJj)p}3eYFzaHSeGR)P|QYMUZTbII<454B%h_ajahPt_MtZ|)jDBTpMldz z3peR*`*AeKF(+@}#jsaGYqpPko6J}`J-KO@+kT&UzqjB(&gk)5D)$V}QXy1CxBa|| zdux75$Gqz4kms1IuS!*_0&=TY4CZz=qWmYtA9kD$lc)&w(TvfFdL1)4SFgM6H_$Wg zjF;cK)?6FX^3X)Ro@2k6Vq8Vno_S&WZ$onHS>-=1{`NrHHOGpOWGk)q>2CWOcJZ;z z#hE|;)9WGmAU*2Sao>I#TJ|Gu^k7`_8}qMuLt3NsrcckYAARi&hbG<`e5o)bx1WVg zGr!PcQxdO-B(ap-pu6p7&Q$>R=OK2;!>__O?>;9BSj#N=dtCJ2i z==1DH>(a9GBL|=S)y|Oo2JfI~%NpoXLlMntT#^)pQ)DWZ{PATu=VkA-TU#2GhFI83 R4>slvA8S1BqVc@_{{V2c?(P5p diff --git a/dist/action.js b/dist/action.js index f52f149d..fb07aa71 100644 --- a/dist/action.js +++ b/dist/action.js @@ -78395,18 +78395,27 @@ function writeRegistryToConfigFile({ scope = scope.toLocaleLowerCase(); } core.info(`Setting auth in ${fileLocation}`); + const bunRegistryString = `'${scope}' = { token = "$BUN_AUTH_TOKEN", url = "${registryUrl}" }`; let newContents = ""; if ((0, import_node_fs.existsSync)(fileLocation)) { const curContents = (0, import_node_fs.readFileSync)(fileLocation, "utf8"); - curContents.split(import_node_os.EOL).forEach((line) => { - if (!line.toLowerCase().startsWith(scope)) { + const contents = curContents.split(import_node_os.EOL); + contents.forEach((line, index, array) => { + if (index > 0 && array[index - 1].includes("[install.scopes]")) { + newContents += bunRegistryString + import_node_os.EOL; + } + if (!line.toLowerCase().includes(scope)) { newContents += line + import_node_os.EOL; } }); + if (!contents.includes("[install.scopes]")) { + newContents += `[install.scopes]${import_node_os.EOL}${import_node_os.EOL}${bunRegistryString}${import_node_os.EOL}`; + } newContents += import_node_os.EOL; } - const bunRegistryString = `'${scope}' = { token = "$BUN_AUTH_TOKEN", url = "${registryUrl}"}`; - newContents += `[install.scopes]${import_node_os.EOL}${import_node_os.EOL}${bunRegistryString}${import_node_os.EOL}`; + if (!(0, import_node_fs.existsSync)(fileLocation)) { + newContents += `[install.scopes]${import_node_os.EOL}${import_node_os.EOL}${bunRegistryString}${import_node_os.EOL}`; + } (0, import_node_fs.writeFileSync)("./bunfig.toml", newContents); } diff --git a/package.json b/package.json index c052e2d1..2321792a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "setup-bun", - "version": "1.0.0", + "version": "1.1.1", "description": "Setup Bun on GitHub Actions.", "keywords": [ "bun", @@ -31,6 +31,7 @@ }, "devDependencies": { "@types/node": "^20.8.2", + "bun-types": "latest", "esbuild": "^0.19.2", "prettier": "^2.8.4", "typescript": "^4.9.5" diff --git a/src/auth.spec.ts b/src/auth.spec.ts new file mode 100644 index 00000000..bb2b694d --- /dev/null +++ b/src/auth.spec.ts @@ -0,0 +1,139 @@ +import { afterEach, describe, expect, it } from "bun:test"; +import { unlink } from "fs"; +import { configureAuthentication } from "./auth"; +import { EOL } from "os"; + +describe("#configureAuthentication", () => { + const filePath = "bunfig.toml"; + + async function getFileAndContents() { + const file = Bun.file(filePath); + const contents = (await file.text()).split(EOL); + + return { file, contents }; + } + + afterEach(() => { + unlink(filePath, () => console.log(`${filePath} was deleted`)); + }); + + describe("when no bunfig.toml file exists", () => { + it("should create a new file with scopes content", async () => { + configureAuthentication("https://npm.pkg.github.com", "foo-bar"); + + const { file, contents } = await getFileAndContents(); + + expect(file.exists()).resolves.toBeTrue(); + + const expectedContents = [ + "[install.scopes]", + "", + '\'@foo-bar\' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }', + "", + ]; + + contents.forEach((content, index) => + expect(content).toBe(expectedContents[index]) + ); + + expect(contents.length).toBe(expectedContents.length); + }); + }); + + describe("when local bunfig.toml file exists", () => { + it("and no [install.scopes] exists, should concatenate file correctly", async () => { + const bunfig = `[install]${EOL}optional = true${EOL}${EOL}[install.cache]${EOL}disable = true`; + + await Bun.write(filePath, bunfig); + + configureAuthentication("https://npm.pkg.github.com/", "foo-bar"); + + const { file, contents } = await getFileAndContents(); + + expect(file.exists()).resolves.toBeTrue(); + + const expectedContents = [ + "[install]", + "optional = true", + "", + "[install.cache]", + "disable = true", + "[install.scopes]", + "", + '\'@foo-bar\' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }', + "", + "", + ]; + + contents.forEach((content, index) => + expect(content).toBe(expectedContents[index]) + ); + + expect(contents.length).toBe(expectedContents.length); + }); + + it("and [install.scopes] exists and it's not the same registry, should concatenate file correctly", async () => { + const bunfig = `[install]${EOL}optional = true${EOL}${EOL}[install.scopes]${EOL}'@bla-ble' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }${EOL}${EOL}[install.cache]${EOL}disable = true`; + + await Bun.write(filePath, bunfig); + + configureAuthentication("https://npm.pkg.github.com/", "foo-bar"); + + const { file, contents } = await getFileAndContents(); + + expect(file.exists()).resolves.toBeTrue(); + + const expectedContents = [ + "[install]", + "optional = true", + "", + "[install.scopes]", + '\'@foo-bar\' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }', + '\'@bla-ble\' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }', + "", + "[install.cache]", + "disable = true", + "", + "", + ]; + + contents.forEach((content, index) => + expect(content).toBe(expectedContents[index]) + ); + + expect(contents.length).toBe(expectedContents.length); + }); + + it("and [install.scopes] exists and it's the same registry, should concatenate file correctly", async () => { + const bunfig = `[install]${EOL}optional = true${EOL}${EOL}[install.scopes]${EOL}'@foo-bar' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }${EOL}'@bla-ble' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }${EOL}${EOL}[install.cache]${EOL}disable = true`; + + await Bun.write(filePath, bunfig); + + configureAuthentication("https://npm.pkg.github.com/", "foo-bar"); + + const { file, contents } = await getFileAndContents(); + + expect(file.exists()).resolves.toBeTrue(); + + const expectedContents = [ + "[install]", + "optional = true", + "", + "[install.scopes]", + '\'@foo-bar\' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }', + '\'@bla-ble\' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }', + "", + "[install.cache]", + "disable = true", + "", + "", + ]; + + contents.forEach((content, index) => + expect(content).toBe(expectedContents[index]) + ); + + expect(contents.length).toBe(expectedContents.length); + }); + }); +}); diff --git a/src/auth.ts b/src/auth.ts index e635bfe9..54ca0638 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -34,24 +34,37 @@ function writeRegistryToConfigFile({ core.info(`Setting auth in ${fileLocation}`); + const bunRegistryString = `'${scope}' = { token = "$BUN_AUTH_TOKEN", url = "${registryUrl}" }`; let newContents = ""; if (existsSync(fileLocation)) { const curContents = readFileSync(fileLocation, "utf8"); - curContents.split(EOL).forEach((line: string) => { - // Add current contents unless they are setting the registry - if (!line.toLowerCase().startsWith(scope)) { + const contents = curContents.split(EOL); + + contents.forEach((line, index, array) => { + // If last item is [install.scopes], than it should add the action scope + registry + if (index > 0 && array[index - 1].includes('[install.scopes]')) { + newContents += bunRegistryString + EOL; + } + + // Only add the line if scope does not exists + if (!line.toLowerCase().includes(scope)) { newContents += line + EOL; } }); + // In case bunfig.toml has other properties and does not have [install.scopes] + if (!contents.includes('[install.scopes]')) { + newContents += `[install.scopes]${EOL}${EOL}${bunRegistryString}${EOL}` + } + newContents += EOL; } - const bunRegistryString = `'${scope}' = { token = "$BUN_AUTH_TOKEN", url = "${registryUrl}"}`; - - newContents += `[install.scopes]${EOL}${EOL}${bunRegistryString}${EOL}`; + if (!existsSync(fileLocation)) { + newContents += `[install.scopes]${EOL}${EOL}${bunRegistryString}${EOL}` + } writeFileSync("./bunfig.toml", newContents); } diff --git a/tsconfig.json b/tsconfig.json index 2dfdb6e7..5493748f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "module": "ES2020", "target": "ES2020", "moduleResolution": "node", - "skipLibCheck": true + "skipLibCheck": true, + "types": ["bun-types"] } }