From 4aa9ea2174079df9ac0ab542cb5ebb32dfbf86ef Mon Sep 17 00:00:00 2001 From: bea-claude Date: Tue, 6 Oct 2026 11:26:06 +0200 Subject: [PATCH 1/2] Make `be auto` install the beplus CLI version beplus.estate.json pins (BE-213) Every deploy path floats on `be latest` today, so a CLI release changes what an estate deploys without a commit in that estate. `be auto` was meant to read a committed pin, but it still ran the logic inherited from `n`: it read `.n-node-version`, `.node-version`, `.nvmrc` or `engines.node` in `package.json` (Node.js versions, not beplus CLI ones), while the help text promised `.bepluscloud`, `.beplus-version` and `package.json`, none of which was ever read. `auto` now walks up from the working directory to the nearest `beplus.estate.json` and reads `"cli": { "version": "x.y.z" }`. The pin must be one exact version (a leading v and a pre-release are accepted, as everywhere in be), and `be auto` installs exactly it without reading the release index. No manifest, a manifest without a pin, a floating pin (`2`, `2.11`, `latest`, `^2.11.0`), a pin that is not a string or a file that is not valid JSON exits non-zero with a message naming the file, and installs nothing. The nearest manifest decides even when it pins nothing; one further up never stands in for it. The manifest is read with node, which every deploy path has, or with jq where there is no node, and be says so when it has neither. `.beplus-version` is not kept as a second source: one pin per repository, in the manifest, is the point. `ls-remote`, `which`, `run`, `exec` and `rm` resolve `auto` the same way. The help text and CHANGELOG (under Unreleased) describe it; the version is not bumped. test/tests/auto.bats installs from the local mirror, which `setup_tmp_mirror` now builds for several versions, against an index whose newest release is 2.12.0 while the pin is 2.11.0. All 11 tests fail against main's be. Co-Authored-By: Igor Lamos --- CHANGELOG.md | 16 +++ bin/be | 209 ++++++++++++++----------------- test/tests/auto.bats | 190 ++++++++++++++++++++++++++++ test/tests/shared-functions.bash | 33 ++--- 4 files changed, 318 insertions(+), 130 deletions(-) create mode 100644 test/tests/auto.bats diff --git a/CHANGELOG.md b/CHANGELOG.md index f124707..779c503 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 https://github.com/beplus/be/compare/v0.9.0...main +Make `be auto` install exactly the beplus CLI version the repository pins, so that a CLI release +cannot change what a deploy runs without a commit in that repository. `auto` reads +`"cli": { "version": "x.y.z" }` from the nearest `beplus.estate.json`, in the current directory or +the closest one above it, and installs that version without consulting the release index. No +manifest, a manifest without a pin, a pin that is not one exact version (`2`, `2.11`, `latest`, +`^2.11.0`) or a file that is not valid JSON fails with a message naming the file; nothing falls +back to the newest release, and a manifest further up never stands in for the nearest one. A +leading `v` and pre-releases are accepted, as everywhere in `be`. The manifest is read with `node`, +or with `jq` where there is no `node`. `be ls-remote auto`, `be which auto`, `be run auto` and +`be exec auto` resolve the same pin. + +`auto` no longer reads `.n-node-version`, `.node-version`, `.nvmrc` or `engines.node` in +`package.json`, which it inherited from `n` and which name Node.js versions, not beplus CLI ones. +The help text promised `.bepluscloud`, `.beplus-version` and `package.json`; none of them was ever +read, and `beplus.estate.json` is now the only place a repository pins its CLI. + ## [v0.9.0] (10/02/2026) Verify every download against the `SHA256SUMS` the beplus CLI release publishes beside its diff --git a/bin/be b/bin/be index ed296ad..25b8bb8 100755 --- a/bin/be +++ b/bin/be @@ -278,6 +278,7 @@ Commands: be Display downloaded beplus CLI versions and install selection be latest Install the latest beplus CLI release (downloading if necessary) + be auto Install the beplus CLI version the nearest beplus.estate.json pins be Install beplus CLI (downloading if necessary) be install Install beplus CLI (downloading if necessary) be run [args ...] Execute downloaded beplus CLI with [args ...] @@ -316,7 +317,8 @@ Versions: 0.17.0, 1, v1.2 Numeric versions latest, current Newest official release - auto Read version from file: .bepluscloud, .beplus-version, or package.json + auto The exact version pinned as "cli": { "version": "x.y.z" } in the nearest + beplus.estate.json (in the current directory or above it); fails without one EOF } @@ -897,138 +899,109 @@ function tarball_url() { } # -# Synopsis: get_file_node_version filename -# Sets g_target_beplus +# Synopsis: display_estate_manifest_path +# Output the path of the nearest beplus.estate.json: in PWD, or else in the closest directory above +# it. Fails when there is none. # -function get_file_node_version() { - g_target_beplus= - local filepath="$1" - verbose_log "found" "${filepath}" - # read returns a non-zero status but does still work if there is no line ending - local version - <"${filepath}" read -r version - # trim possible trailing \d from a Windows created file - version="${version%%[[:space:]]}" - verbose_log "read" "${version}" - g_target_beplus="${version}" +function display_estate_manifest_path() { + local dir="${PWD}" + while true; do + if [[ -f "${dir%/}/beplus.estate.json" ]]; then + echo "${dir%/}/beplus.estate.json" + return 0 + fi + [[ -z "${dir}" || "${dir}" == "/" ]] && return 1 + dir="${dir%/*}" + done } # -# Synopsis: get_package_engine_version\ -# Sets g_target_beplus -# - -function get_package_engine_version() { - g_target_beplus= - local filepath="$1" - verbose_log "found" "${filepath}" - command -v node &> /dev/null || abort "an active version of node is required to read 'engines' from package.json" - local range - range="$(node -e "package = require('${filepath}'); if (package && package.engines && package.engines.node) console.log(package.engines.node)")" - verbose_log "read" "${range}" - [[ -n "${range}" ]] || return 2 - if [[ "*" == "${range}" ]]; then - verbose_log "target" "current" - g_target_beplus="current" - return - fi - - local version - if [[ "${range}" =~ ^([>~^=]|\>\=)?v?([0-9]+(\.[0-9]+){0,2})(.[xX*])?$ ]]; then - local operator="${BASH_REMATCH[1]}" - version="${BASH_REMATCH[2]}" - case "${operator}" in - '' | =) ;; - \> | \>=) version="current" ;; - \~) [[ "${version}" =~ ^([0-9]+\.[0-9]+)\.[0-9]+$ ]] && version="${BASH_REMATCH[1]}" ;; - ^) [[ "${version}" =~ ^([0-9]+) ]] && version="${BASH_REMATCH[1]}" ;; - esac - verbose_log "target" "${version}" +# Synopsis: display_estate_cli_version node|jq manifest +# Output the manifest's "cli": { "version" } as JSON, on one line: a string when the pin is one, +# null when the manifest has none. Fails, with the reason on stderr, when the file is not exactly +# one JSON value. +# + +function display_estate_cli_version() { + if [[ "$1" == "node" ]]; then + node -e ' + const has = (value, key) => + value !== null && typeof value === "object" && !Array.isArray(value) + && Object.prototype.hasOwnProperty.call(value, key); + let manifest; + try { + manifest = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); + } catch (error) { + console.error(error.message); + process.exit(1); + } + const version = has(manifest, "cli") && has(manifest.cli, "version") ? manifest.cli.version : null; + console.log(JSON.stringify(version)); + ' "$2" else - command -v npx &> /dev/null || abort "an active version of npx is required to use complex 'engine' ranges from package.json" - verbose_log "resolving" "${range}" - local version_per_line="$(be lsr --all)" - local versions_one_line=$(echo "${version_per_line}" | tr '\n' ' ') - # Using semver@7 so works with older versions of node. - # shellcheck disable=SC2086 - version=$(npm_config_yes=true npx --quiet semver@7 -r "${range}" ${versions_one_line} | tail -n 1) + # --slurp so that an empty file, or one holding several values, fails as JSON.parse does. + jq -r --slurp ' + if length != 1 then error("expected one JSON value, found \(length)") + else .[0] + | if type == "object" and (.cli | type) == "object" and (.cli | has("version")) + then .cli.version + else null + end + | tojson + end + ' "$2" fi - g_target_beplus="${version}" } # -# Synopsis: get_nvmrc_version +# Synopsis: get_auto_version +# Resolve auto to the beplus CLI version the nearest beplus.estate.json pins as +# "cli": { "version": "x.y.z" }. The pin must be one exact version (a leading v and a pre-release +# are allowed, as everywhere in be); a missing, floating or unreadable pin aborts, naming the file, +# rather than falling back to another version. The nearest manifest decides, even when it pins +# nothing: one further up is never consulted. # Sets g_target_beplus # -function get_nvmrc_version() { +function get_auto_version() { g_target_beplus= - local filepath="$1" - verbose_log "found" "${filepath}" - local version - <"${filepath}" read -r version - verbose_log "read" "${version}" - # Translate from nvm aliases - case "${version}" in - lts/\*) version="lts" ;; - lts/*) version="${version:4}" ;; - node) version="current" ;; - *) ;; - esac - g_target_beplus="${version}" -} + local manifest + manifest="$(display_estate_manifest_path)" \ + || abort "auto found no beplus.estate.json in ${PWD} or above it, so no beplus CLI version is pinned" + verbose_log "found" "${manifest}" -# -# Synopsis: get_engine_version [error-message] -# Sets g_target_beplus -# + # node is on every deploy path; jq is what be's remote lookups use. + local reader + if command -v node &> /dev/null; then + reader="node" + elif command -v jq &> /dev/null; then + reader="jq" + else + abort "reading the beplus CLI pin from ${manifest} needs node or jq, and neither is on PATH" + fi -function get_engine_version() { - g_target_beplus= - local error_message="${1-package.json not found}" - local parent - parent="${PWD}" - while [[ -n "${parent}" ]]; do - if [[ -e "${parent}/package.json" ]]; then - get_package_engine_version "${parent}/package.json" - else - parent=${parent%/*} - continue - fi - break - done - [[ -n "${parent}" ]] || abort "${error_message}" - [[ -n "${g_target_beplus}" ]] || abort "did not find supported version of node in 'engines' field of package.json" -} + local value + if ! value="$(display_estate_cli_version "${reader}" "${manifest}" 2> /dev/null)"; then + abort "${manifest} could not be read as JSON by ${reader}: $(display_estate_cli_version "${reader}" "${manifest}" 2>&1 > /dev/null)" + fi -# -# Synopsis: get_auto_version -# Sets g_target_beplus -# + local version + case "${value}" in + null) + abort "${manifest} pins no beplus CLI version; add \"cli\": { \"version\": \"x.y.z\" }" ;; + \"*\") + version="${value#\"}" + version="${version%\"}" + ;; + *) + abort "\"cli\": { \"version\" } in ${manifest} is ${value}, not a version string like \"2.11.0\"" ;; + esac + verbose_log "read" "${version}" -# @todo -function get_auto_version() { - g_target_beplus= - # Search for a version control file first - local parent - parent="${PWD}" - while [[ -n "${parent}" ]]; do - if [[ -e "${parent}/.n-node-version" ]]; then - get_file_node_version "${parent}/.n-node-version" - elif [[ -e "${parent}/.node-version" ]]; then - get_file_node_version "${parent}/.node-version" - elif [[ -e "${parent}/.nvmrc" ]]; then - get_nvmrc_version "${parent}/.nvmrc" - else - parent=${parent%/*} - continue - fi - break - done - # Fallback to package.json - [[ -n "${parent}" ]] || get_engine_version "no file found for auto version (.n-node-version, .node-version, .nvmrc, or package.json)" - [[ -n "${g_target_beplus}" ]] || abort "file found for auto did not contain target version of node" + is_exact_numeric_version "${version}" \ + || abort "\"cli\": { \"version\" } in ${manifest} is \"${version}\", not one exact version like \"2.11.0\"" + g_target_beplus="${version#v}" } # @@ -1039,6 +1012,12 @@ function get_auto_version() { function get_latest_resolved_version() { g_target_beplus= local version=${1} + if [[ "${version}" == "auto" ]]; then + # The pin is one exact version, so there is nothing to look up: auto installs exactly that + # version or fails, and never reads the release index (where "newest" lives). + get_auto_version + return + fi simple_version=${version} if is_exact_numeric_version "${simple_version}"; then # Just numbers, already resolved, no need to lookup first. diff --git a/test/tests/auto.bats b/test/tests/auto.bats new file mode 100644 index 0000000..0db3fcd --- /dev/null +++ b/test/tests/auto.bats @@ -0,0 +1,190 @@ +#!/usr/bin/env bats +# +# `be auto` installs exactly the beplus CLI version a repository pins in its beplus.estate.json, +# as "cli": { "version": "x.y.z" }, so that a CLI release cannot change what a deploy runs without +# a commit in that repository. Without a pin it fails, naming the file, rather than falling back to +# the newest release. These run against a local mirror and release index where 2.12.0 is newer +# than the pinned 2.11.0. + +load shared-functions +load '../../node_modules/bats-support/load' +load '../../node_modules/bats-assert/load' + + +function setup() { + unset_n_env + setup_tmp_prefix + setup_tmp_mirror 2.11.0 2.12.0 + cat > "${TMP_MIRROR_DIR}/releases.json" <<'JSON' +[ + {"name": "v2.12.0", "tag_name": "v2.12.0", "prerelease": false, "draft": false}, + {"name": "v2.11.0", "tag_name": "v2.11.0", "prerelease": false, "draft": false} +] +JSON + export BE_RELEASE_INDEX_URL="file://${TMP_MIRROR_DIR}/releases.json" + + PROJECT="${TMP_PREFIX_DIR}/estate" + mkdir -p "${PROJECT}/packages/app/src" + cd "${PROJECT}" || exit 2 +} + + +function teardown() { + rm -rf "${TMP_PREFIX_DIR}" "${TMP_MIRROR_DIR}" "${TMP_SHIM_DIR}" +} + + +# Synopsis: write_manifest [dir] +function write_manifest() { + printf '{\n "name": "estate",\n "cli": { "version": %s }\n}\n' "$1" > "${2:-${PROJECT}}/beplus.estate.json" +} + + +# Synopsis: setup_shim command... +# A directory holding be, bash and the given commands, and nothing else, to run be with as its PATH. +function setup_shim() { + TMP_SHIM_DIR="$(mktemp -d)" + ln -s "$(command -v be)" "${TMP_SHIM_DIR}/be" + ln -s "$(command -v bash)" "${TMP_SHIM_DIR}/bash" + local command + for command in "$@"; do + ln -s "$(command -v "${command}")" "${TMP_SHIM_DIR}/${command}" + done +} + + +@test "be auto installs exactly the version beplus.estate.json pins, not the newest" { + write_manifest '"2.11.0"' + cd "${PROJECT}/packages/app/src" + # The index this runs against offers a newer release. + assert_equal "$(be --latest)" "2.12.0" + + run be auto + assert_success + assert_output --partial "found : ${PROJECT}/beplus.estate.json" + assert_equal "$(beplus --version | cli_version)" "2.11.0" + assert_equal "$(be ls)" "beplus/2.11.0" + assert_equal "$(be which auto 2> /dev/null)" "${BE_PREFIX}/be/versions/beplus/2.11.0/beplus" + assert_equal "$(be ls-remote auto 2> /dev/null)" "2.11.0" +} + + +@test "the nearest beplus.estate.json decides" { + write_manifest '"2.12.0"' + write_manifest '"2.11.0"' "${PROJECT}/packages/app" + cd "${PROJECT}/packages/app/src" + + assert_equal "$(be N_TEST_DISPLAY_LATEST_RESOLVED_VERSION auto 2> /dev/null)" "2.11.0" +} + + +@test "a pin with a leading v, or a pre-release, is still one exact version" { + write_manifest '"v2.11.0"' + assert_equal "$(be N_TEST_DISPLAY_LATEST_RESOLVED_VERSION auto 2> /dev/null)" "2.11.0" + + write_manifest '"2.12.0-beta.1"' + assert_equal "$(be N_TEST_DISPLAY_LATEST_RESOLVED_VERSION auto 2> /dev/null)" "2.12.0-beta.1" +} + + +@test "be auto without a beplus.estate.json fails and installs nothing" { + run be auto + assert_failure + assert_output --partial "auto found no beplus.estate.json in ${PROJECT} or above it" + [ ! -e "${BE_PREFIX}/bin/beplus" ] + [ ! -e "${BE_PREFIX}/be/versions" ] +} + + +@test "be auto fails, naming the file, when beplus.estate.json pins no version" { + local manifest + for manifest in '{ "name": "estate" }' '{ "cli": {} }' '{ "cli": { "version": null } }'; do + echo "${manifest}" > "${PROJECT}/beplus.estate.json" + run be auto + assert_failure + assert_output --partial "${PROJECT}/beplus.estate.json pins no beplus CLI version" + done + [ ! -e "${BE_PREFIX}/bin/beplus" ] +} + + +@test "a nearer beplus.estate.json without a pin does not fall back to one further up" { + write_manifest '"2.11.0"' + echo '{ "name": "app" }' > "${PROJECT}/packages/app/beplus.estate.json" + cd "${PROJECT}/packages/app" + + run be auto + assert_failure + assert_output --partial "${PROJECT}/packages/app/beplus.estate.json pins no beplus CLI version" + [ ! -e "${BE_PREFIX}/bin/beplus" ] +} + + +@test "be auto refuses a pin that is not one exact version" { + local version + for version in '"2"' '"2.11"' '"latest"' '"^2.11.0"' '"~2.11.0"' '">=2.11.0"' '"2.11.x"' '""'; do + write_manifest "${version}" + run be auto + assert_failure + assert_output --partial "in ${PROJECT}/beplus.estate.json is ${version}, not one exact version" + done + [ ! -e "${BE_PREFIX}/bin/beplus" ] +} + + +@test "be auto refuses a pin that is not a string" { + local version + for version in '2.11' 'true' '{"major":2}'; do + write_manifest "${version}" + run be auto + assert_failure + assert_output --partial "in ${PROJECT}/beplus.estate.json is ${version}, not a version string" + done + [ ! -e "${BE_PREFIX}/bin/beplus" ] +} + + +@test "be auto fails, naming the file, when beplus.estate.json is not valid JSON" { + local manifest + for manifest in '{ "cli": { "version": "2.11.0" }' '' '{} {}'; do + printf '%s' "${manifest}" > "${PROJECT}/beplus.estate.json" + run be auto + assert_failure + assert_output --partial "${PROJECT}/beplus.estate.json could not be read as JSON by " + done + [ ! -e "${BE_PREFIX}/bin/beplus" ] +} + + +@test "jq reads the pin where there is no node" { + command -v jq > /dev/null || skip "jq is not installed" + setup_shim jq + + write_manifest '"2.11.0"' + run env PATH="${TMP_SHIM_DIR}" "${TMP_SHIM_DIR}/be" N_TEST_DISPLAY_LATEST_RESOLVED_VERSION auto + assert_success + assert_line "2.11.0" + + echo '{ "name": "estate" }' > "${PROJECT}/beplus.estate.json" + run env PATH="${TMP_SHIM_DIR}" "${TMP_SHIM_DIR}/be" auto + assert_failure + assert_output --partial "${PROJECT}/beplus.estate.json pins no beplus CLI version" + + local manifest + for manifest in '{ "cli": { "version": "2.11.0" }' '' '{} {}'; do + printf '%s' "${manifest}" > "${PROJECT}/beplus.estate.json" + run env PATH="${TMP_SHIM_DIR}" "${TMP_SHIM_DIR}/be" auto + assert_failure + assert_output --partial "${PROJECT}/beplus.estate.json could not be read as JSON by jq: " + done +} + + +@test "be auto without node or jq says it needs one of them" { + setup_shim + + write_manifest '"2.11.0"' + run env PATH="${TMP_SHIM_DIR}" "${TMP_SHIM_DIR}/be" auto + assert_failure + assert_output --partial "reading the beplus CLI pin from ${PROJECT}/beplus.estate.json needs node or jq" +} diff --git a/test/tests/shared-functions.bash b/test/tests/shared-functions.bash index 2a18844..067301e 100644 --- a/test/tests/shared-functions.bash +++ b/test/tests/shared-functions.bash @@ -36,31 +36,34 @@ function setup_tmp_prefix() { # Create a local mirror laid out as the beplus CLI release publishes one, and point be at it: -# v/ holds this machine's tarball, with a stub beplus that prints the version banner, -# and SHA256SUMS beside it. The mirror is a file:// URL, which be reads with curl only (wget -# fetches http, https and ftp), so without curl the test is skipped. +# for each given, v/ holds this machine's tarball, with a stub beplus that +# prints the version banner, and SHA256SUMS beside it. The mirror is a file:// URL, which be reads +# with curl only (wget fetches http, https and ftp), so without curl the test is skipped. +# Usage: setup_tmp_mirror version... # Globals: # TMP_MIRROR_DIR # BE_MIRROR function setup_tmp_mirror() { command -v curl > /dev/null || skip "the local mirror is a file:// URL, which needs curl" - local version="$1" TMP_MIRROR_DIR="$(mktemp -d)" [ -d "${TMP_MIRROR_DIR}" ] || exit 2 export TMP_MIRROR_DIR - local release="${TMP_MIRROR_DIR}/v${version}" - local tarball="beplus-cli-v${version}-$(tarball_platform).tar.gz" - mkdir -p "${release}" "${TMP_MIRROR_DIR}/stub" - printf '#!/bin/sh\necho "beplus CLI v%s"\n' "${version}" > "${TMP_MIRROR_DIR}/stub/beplus" - chmod +x "${TMP_MIRROR_DIR}/stub/beplus" - tar -czf "${release}/${tarball}" -C "${TMP_MIRROR_DIR}/stub" beplus - if command -v sha256sum &> /dev/null; then - (cd "${release}" && sha256sum "${tarball}" > SHA256SUMS) - else - (cd "${release}" && shasum -a 256 "${tarball}" > SHA256SUMS) - fi + local version + for version in "$@"; do + local release="${TMP_MIRROR_DIR}/v${version}" + local tarball="beplus-cli-v${version}-$(tarball_platform).tar.gz" + mkdir -p "${release}" "${TMP_MIRROR_DIR}/stub" + printf '#!/bin/sh\necho "beplus CLI v%s"\n' "${version}" > "${TMP_MIRROR_DIR}/stub/beplus" + chmod +x "${TMP_MIRROR_DIR}/stub/beplus" + tar -czf "${release}/${tarball}" -C "${TMP_MIRROR_DIR}/stub" beplus + if command -v sha256sum &> /dev/null; then + (cd "${release}" && sha256sum "${tarball}" > SHA256SUMS) + else + (cd "${release}" && shasum -a 256 "${tarball}" > SHA256SUMS) + fi + done export BE_MIRROR="file://${TMP_MIRROR_DIR}" } From 6c4311eecb9dce699ac5df1513fbffb97e130b66 Mon Sep 17 00:00:00 2001 From: bea-claude Date: Wed, 7 Oct 2026 23:43:53 +0200 Subject: [PATCH 2/2] Bump the version to v0.10.0 + update CHANGELOG Co-Authored-By: Igor Lamos --- CHANGELOG.md | 4 +++- bin/be | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 779c503..036a009 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -https://github.com/beplus/be/compare/v0.9.0...main +https://github.com/beplus/be/compare/v0.10.0...main + +## [v0.10.0] (10/07/2026) Make `be auto` install exactly the beplus CLI version the repository pins, so that a CLI release cannot change what a deploy runs without a commit in that repository. `auto` reads diff --git a/bin/be b/bin/be index 25b8bb8..14e284a 100755 --- a/bin/be +++ b/bin/be @@ -64,7 +64,7 @@ function n_grep() { # Setup and state # -VERSION="v0.9.0" +VERSION="v0.10.0" BE_PREFIX="${BE_PREFIX-/usr/local}" BE_PREFIX=${BE_PREFIX%/} diff --git a/package-lock.json b/package-lock.json index c2194d9..8bd2ab7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@beplus/be", - "version": "0.9.0", + "version": "0.10.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@beplus/be", - "version": "0.9.0", + "version": "0.10.0", "license": "MIT", "os": [ "!win32" diff --git a/package.json b/package.json index 691b8b0..e5c1354 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@beplus/be", "description": "Interactively Manage beplus CLI Versions", - "version": "0.9.0", + "version": "0.10.0", "author": "Igor Lamos ", "homepage": "https://github.com/beplus/be", "bugs": "https://github.com/beplus/be",