Repository navigation
Estate Consolidation P0 — be auto installs the beplus CLI version beplus.estate.json pins - #6
Merged
Conversation
… (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 <igor@be.plus>
Co-Authored-By: Igor Lamos <igor@be.plus>
igorlamos
approved these changes
Oct 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
be autonow installs exactly the beplus CLI version that a repository pins in itsbeplus.estate.json. When there is no pin, it fails with a clear message. Today every deploy path runsbe latestor a floating major, so a CLI release can change what an estate deploys without any commit in that estate. This PR is the part of that fix that lives inbe.This PR is part of Linear initiative I-34, Estate Consolidation: One Copy of Every Helper, project P0, Foundations & Guardrails. The initiative uses one branch per project and one commit per issue, so please review commit by commit, then squash-merge.
4aa9ea2be autoreads the pin frombeplus.estate.jsonBE-213: Pin the beplus CLI per repository
Linear: https://linear.app/bepluscloud/issue/BE-213
Problem
be latest.deploy-buildspec.ymlrunsbe ${BE_CLI_VERSION:-2}, and the workflows default to'2'.setup-beplus/clidefaults tolatest. This is EXTRACTION-PLAN Risk 1, which is still open.be autocould not read a pin. It was a@todoinherited fromn. It read.n-node-version,.node-version,.nvmrcandengines.nodefrompackage.json, which hold Node.js versions, not beplus CLI ones. The help text promised.bepluscloud,.beplus-versionandpackage.json, butbenever read any of them.What changes
be autonow works like this:beplus.estate.json, and reads"cli": { "version" }from it.x.y.z, with an optional leadingvand an optional pre-release or build suffix. This uses be's existingis_exact_numeric_version, so the rules match the rest ofbe.be autofails, even when a manifest further up has one.node, orjqwhennodeis missing. If neither is installed, it fails and says so. This adds no new hard dependency.be ls-remote auto,be which auto,be run auto,be exec autoandbe rm autoall resolve the same pin.get_latest_resolved_versionhandlesautobefore any index lookup.In the tests below, the release index offers 2.12.0 as the newest release:
beplus.estate.jsonbe auto"cli": { "version": "2.11.0" }"v2.11.0"/"2.12.0-beta.1"2.11.0/2.12.0-beta.1$PWDor above itauto found no beplus.estate.json in <PWD> or above it, so no beplus CLI version is pinnedcli,cli: {},version: null<file> pins no beplus CLI version; add "cli": { "version": "x.y.z" }"2","2.11","latest","^2.11.0","~2.11.0",">=2.11.0","2.11.x",""… in <file> is "2.11", not one exact version like "2.11.0"2.11,true,{"major":2}… in <file> is 2.11, not a version string like "2.11.0"{} {}<file> could not be read as JSON by node|jq: …nodenorjqonPATHreading the beplus CLI pin from <file> needs node or jq, and neither is on PATHIn every failure case, nothing is installed.
Removed:
autoinherited fromn:.n-node-version,.node-version,.nvmrcandengines.node.get_file_node_version,get_package_engine_version,get_nvmrc_versionandget_engine_version..bepluscloud,.beplus-versionandpackage.json.Files:
bin/be(+94 −115).test/tests/auto.bats: new, 11 tests.test/tests/shared-functions.bash(+18 −15):setup_tmp_mirrornow accepts several versions and still works with one.CHANGELOG.md: an entry under[Unreleased]. The version is not bumped (see Release below).Gates
npm run lint(shellcheck -S warning bin/be bin/bump scripts/install.sh scripts/release/*.sh)shellcheck bin/becount is the same before and after (1 = 1).npm run test:host(PATH="$PWD/bin:$PATH" bats test/tests) on macOS with Homebrew bash 5.3origin/main546c2e6 was 43/43; the 11 new tests are inauto.bats. The network suites (lookup, install, lsr, run/which, uninstall) still pass.bats test/tests/auto.bats test/tests/checksums.bats test/tests/ordering.batswith macOS/bin/bash3.2.57 (the macOS CI leg's bash) and jq 1.7.1-applebats test/tests/auto.bats, re-run before opening this PRauto.batsagainstorigin/main'sbin/bebe.scripts/release/verify-version.sh pr origin/main feature/estate-consolidation-p0-foundations(the CI Version job)bin/be changed but the version is still 0.9.0. Run bin/bump …. The release bump is a human step; see Waiting on Igor.On this PR, expect CI to show Test (ubuntu-latest), Test (macos-latest) and Lint green. Version stays red until the bump lands.
Deviations from the issue
belives. The issue placesbeinbeplus/cli_v2as@beplus/be. In factbeis the bash scriptbin/bein its own repo,beplus/be, with bats tests, a shellcheck lint, andmainas its base and PR target.be autois implemented here..beplus-version(promised in the old help text but never read) and the sources inherited fromn, instead of keeping any of them as a fallback.beplus.estate.jsoncli.versionis now the only pin. One pin per repository is the point of the issue.is_exact_numeric_version:x.y.z, an optional leadingv, and an optional pre-release or build suffix. Every floating form is rejected. The rest ofbealready accepts a leadingv.bin/bechanges, so the Version job stays red until Igor bumps.setup_tmp_mirrornow accepts several versions, so one mirror can hold both 2.11.0 and 2.12.0. It still works with one version.Not in this PR
BE-213 scope items 2 to 4 live in other repos:
cli: { version }schema inbeplus.estate.json(inbeplus/cli_v2, after BE-214)setup-beplus/cliandsetup-beplus/cdk-packagedefaulting tobe auto(inbeplus/setup-beplus)The estates adopt the pin in each estate's first adoption issue in P3. That means adding
cli.versionand switching their Dockerfiles, base images and buildspecs tobe auto. None of that can run until this change is released, so @beplus/be 0.10.0 must be published first.Release
bin/bump minorand described it in CHANGELOG.md. Not yet done; this is Igor's step, below.bin/beis unchanged. Does not apply:bin/bechanged.Waiting on Igor
bin/bump minor && git commit -am "Bump the version to v0.10.0 + update CHANGELOG".package.json,package-lock.jsonandbin/be, and moves the[Unreleased]notes under## [v0.10.0].scripts/release/verify-version.sh pr origin/main feature/estate-consolidation-p0-foundations. Expected output:Merging this PR releases @beplus/be@0.10.0 (0.9.0 → 0.10.0).main.v0.10.0and its GitHub Release, and mirrors the version to GitHub Packages.curl -s https://registry.npmjs.org/@beplus%2fbe | jq -r '."dist-tags".latest'should print0.10.0.be auto.Part of initiative I-34 (Estate Consolidation: One Copy of Every Helper), project P0. One branch per project, one commit per issue: review commit by commit, then squash-merge.