This is an automated email from the ASF dual-hosted git repository. sciabarracom pushed a commit to branch 0.9.1 in repository https://gitbox.apache.org/repos/asf/openserverless-task.git
commit be83eae2d19a4adebc6cb0b59e096d7a69939f36 Author: Trustable User <[email protected]> AuthorDate: Sun Jul 12 12:01:36 2026 +0200 Update Bun to 1.3.14 --- ide/install-dependencies.test.ts | 70 +++++++++++++++++++++ ide/install-dependencies.ts | 133 +++++++++++++++++++++++++++++++++++++++ ide/opsfile.yml | 26 +------- prereq.yml | 6 +- tests/opsfile.yml | 2 +- 5 files changed, 210 insertions(+), 27 deletions(-) diff --git a/ide/install-dependencies.test.ts b/ide/install-dependencies.test.ts new file mode 100644 index 0000000..0e0aa40 --- /dev/null +++ b/ide/install-dependencies.test.ts @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { expect, test } from "bun:test"; +import { + access, + mkdtemp, + mkdir, + readFile, + rm, + writeFile, +} from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; + +import { installDependencies } from "./install-dependencies"; + +async function exists(path: string): Promise<boolean> { + try { + await access(path); + return true; + } catch { + return false; + } +} + +test("replaces a partial install and skips a verified install", async () => { + const projectDir = await mkdtemp(join(tmpdir(), "ops-bun-install-test-")); + const nodeModules = join(projectDir, "node_modules"); + + try { + await writeFile( + join(projectDir, "package.json"), + JSON.stringify({ name: "dependency-test", private: true }), + ); + await mkdir(nodeModules); + await writeFile(join(nodeModules, "partial-download"), "incomplete"); + + expect(await installDependencies(projectDir)).toBe(true); + expect(await exists(join(nodeModules, "partial-download"))).toBe(false); + + const state = await readFile( + join(nodeModules, ".ops-bun-install-state"), + "utf8", + ); + expect(state.trim()).toHaveLength(64); + + await writeFile(join(nodeModules, "verified-install"), "keep"); + expect(await installDependencies(projectDir)).toBe(false); + expect(await exists(join(nodeModules, "verified-install"))).toBe(true); + } finally { + await rm(projectDir, { recursive: true, force: true }); + } +}); diff --git a/ide/install-dependencies.ts b/ide/install-dependencies.ts new file mode 100644 index 0000000..7afd147 --- /dev/null +++ b/ide/install-dependencies.ts @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createHash } from "node:crypto"; +import { + access, + mkdir, + mkdtemp, + readFile, + rm, + writeFile, +} from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { basename, join, resolve } from "node:path"; + +const stateFileName = ".ops-bun-install-state"; +const dependencyInputs = [ + "package.json", + "bun.lock", + "bun.lockb", + "package-lock.json", + "pnpm-lock.yaml", + "yarn.lock", +]; + +async function exists(path: string): Promise<boolean> { + try { + await access(path); + return true; + } catch { + return false; + } +} + +async function dependencyState(projectDir: string): Promise<string> { + const hash = createHash("sha256"); + hash.update(`bun:${Bun.version}\n`); + + for (const name of dependencyInputs) { + const path = join(projectDir, name); + if (await exists(path)) { + hash.update(`${name}\0`); + hash.update(await readFile(path)); + } + } + + return hash.digest("hex"); +} + +export async function installDependencies(projectPath: string): Promise<boolean> { + const projectDir = resolve(projectPath); + const packageJson = join(projectDir, "package.json"); + if (!(await exists(packageJson))) { + throw new Error(`package.json not found in ${projectDir}`); + } + + const nodeModules = join(projectDir, "node_modules"); + const stateFile = join(nodeModules, stateFileName); + const expectedState = await dependencyState(projectDir); + + if (await exists(stateFile)) { + const installedState = (await readFile(stateFile, "utf8")).trim(); + if (installedState === expectedState) { + return false; + } + } + + await rm(nodeModules, { recursive: true, force: true }); + const cacheDir = await mkdtemp(join(tmpdir(), "openserverless-bun-cache-")); + + try { + const install = Bun.spawn( + [ + process.execPath, + "install", + "--no-save", + "--no-cache", + "--cache-dir", + cacheDir, + "--network-concurrency=1", + ], + { + cwd: projectDir, + env: process.env, + stdout: "inherit", + stderr: "inherit", + }, + ); + const exitCode = await install.exited; + if (exitCode !== 0) { + throw new Error( + `bun install failed with exit code ${exitCode} in ${projectDir}`, + ); + } + + await mkdir(nodeModules, { recursive: true }); + await writeFile(stateFile, `${expectedState}\n`); + return true; + } finally { + await rm(cacheDir, { recursive: true, force: true }); + } +} + +if (import.meta.main) { + const projectDir = Bun.argv[2]; + if (!projectDir) { + console.error(`Usage: bun ${basename(Bun.argv[1])} <project-directory>`); + process.exit(2); + } + + try { + await installDependencies(projectDir); + } catch (error) { + console.error(error instanceof Error ? error.message : String(error)); + process.exit(1); + } +} diff --git a/ide/opsfile.yml b/ide/opsfile.yml index 89f83dd..4ca3369 100644 --- a/ide/opsfile.yml +++ b/ide/opsfile.yml @@ -23,20 +23,6 @@ vars: sh: | echo "http://localhost:80" - DEPLOY_CURRENT_HASH: - sh: | - if test -e "$OPS_ROOT/ide/deploy/bun.lockb" - then cd "$OPS_ROOT/ide/deploy" && bun "$OPS_ROOT/ide/deploy/bun.lockb" --hash - else echo "0" - fi - - DEPLOY_PREVIOUS_HASH: - sh: | - if test -e "$OPS_ROOT/ide/deploy/hash.lock" - then cat "$OPS_ROOT/ide/deploy/hash.lock" - else echo "0" - fi - tasks: prereq: @@ -49,21 +35,15 @@ tasks: You can also reopen the project with VSCode and use the command 'Reopen in Container'. cmds: - test {{OS}} != "windows" || die '{{.MSG}}' - - test "$(printf '%s\n' "$(bun -v)" "1.1.18" | sort -V | head -n 1)" = "1.1.18" || die "bun 1.1.18 or greater not available" + - test "$(printf '%s\n' "$(bun -v)" "1.3.14" | sort -V | head -n 1)" = "1.3.14" || die "bun 1.3.14 or greater not available" - test -d "$OPS_PWD/packages" || die "no packages in current directory" - test -e ~/.wskprops || die "please run 'ops ide login' first" - test -n "$OPSDEV_HOST" || die "please run 'ops ide login' first" - test "$(ops -wsk property get --namespace | awk '{ print $3 }')" = "$OPSDEV_USERNAME" || die "Repeat the login" - - | - if ! test -d "$OPS_ROOT/ide/deploy/node_modules" || [ "{{.DEPLOY_CURRENT_HASH}}" != "{{.DEPLOY_PREVIOUS_HASH}}" ] - then - cd $OPS_ROOT/ide/deploy && bun install && rm -f $OPS_ROOT/ide/deploy/hash.lock && bun $OPS_ROOT/ide/deploy/bun.lockb --hash > $OPS_ROOT/ide/deploy/hash.lock - fi + - bun "$OPS_ROOT/ide/install-dependencies.ts" "$OPS_ROOT/ide/deploy" - | if test -e "$OPS_PWD/package.json" - then if ! test -d "$OPS_PWD/node_modules" - then cd $OPS_PWD ; bun install - fi + then bun "$OPS_ROOT/ide/install-dependencies.ts" "$OPS_PWD" fi - task: kill diff --git a/prereq.yml b/prereq.yml index bd866ca..ce70e3c 100644 --- a/prereq.yml +++ b/prereq.yml @@ -102,14 +102,15 @@ tasks: bun: desc: download bun vars: - VERSION: "1.2.5" + VERSION: "1.3.14" ARCH2: '{{if eq .ARCH "amd64"}}x64{{else}}aarch64{{end}}' URL: 'https://github.com/oven-sh/bun/releases/download/bun-v{{.VERSION}}/bun-{{.OS}}-{{.ARCH2}}.zip' FILE: '{{base .URL}}' cmds: - echo "{{.URL}}" - - curl -sL "{{.URL}}" -o "{{.FILE}}" + - curl -fsSL "{{.URL}}" -o "{{.FILE}}" - extract "{{.FILE}}" bun{{.EXE}} + - executable bun{{.EXE}} - remove "{{.FILE}}" kubectl: @@ -385,4 +386,3 @@ tasks: - __OS=darwin __ARCH=amd64 ops -task -t prereq.yml test - __OS=darwin __ARCH=arm64 ops -task -t prereq.yml test - __OS=windows __ARCH=amd64 ops -task -t prereq.yml test - diff --git a/tests/opsfile.yml b/tests/opsfile.yml index 8549147..2a8e234 100644 --- a/tests/opsfile.yml +++ b/tests/opsfile.yml @@ -46,7 +46,7 @@ tasks: silent: true desc: Bun test cmds: - - bun | rg '1.1.27' + - bun --version | rg '^1.3.14$' kubectl: silent: true
