mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-04 15:57:33 +01:00
fix(capy-install): follow a project's exact Bun pin above the minimum when gstack has its verified archive (adds Bun 1.4.3)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
5baa4a7c3f
commit
f492a5a9d0
3 files changed
+65
-19
No files matched your search
+22
-10
@@ -16,17 +16,29 @@
|
||||
GSTACK_BUN_FLOOR="1.3.3"
|
||||
GSTACK_BUN_TESTED="1.4.2"
|
||||
|
||||
# gstack_bun_archive_sha256 TARGET — the SHA-256 of
|
||||
# https://github.com/oven-sh/bun/releases/download/bun-v$GSTACK_BUN_TESTED/bun-TARGET.zip
|
||||
# from that release's SHASUMS256.txt, for the targets bin/gstack-capy-install
|
||||
# installs on Capy cloud machines (the same exact-archive recipe as
|
||||
# .github/docker/Dockerfile.ci; test/bun-version-drift.test.ts keeps them
|
||||
# equal). Prints nothing and returns 1 for a target without a verified archive.
|
||||
# gstack_bun_archive_sha256 TARGET [VERSION] — the SHA-256 of
|
||||
# https://github.com/oven-sh/bun/releases/download/bun-v$VERSION/bun-TARGET.zip
|
||||
# (VERSION defaults to $GSTACK_BUN_TESTED) from that release's SHASUMS256.txt,
|
||||
# for the targets bin/gstack-capy-install installs on Capy cloud machines (the
|
||||
# same exact-archive recipe as .github/docker/Dockerfile.ci;
|
||||
# test/bun-version-drift.test.ts keeps the $GSTACK_BUN_TESTED rows equal). A
|
||||
# newer version is listed so the installer can follow a project's exact pin
|
||||
# above the minimum. Prints nothing and returns 1 without a verified archive.
|
||||
GSTACK_BUN_VERIFIED="1.4.2 1.4.3"
|
||||
gstack_bun_archive_sha256() {
|
||||
case "$1" in
|
||||
linux-x64) echo 36368faef7527875d5ffa52e53cd48021741f2a83eb6208a8dd64068d422a913 ;;
|
||||
linux-x64-baseline) echo c678040f14fe0440eb839d37cbd0ce4c051a32da72806ac97de6a6aab6bf728f ;;
|
||||
linux-aarch64) echo 54328bbc2d9c8e0c9f892c544d66c57a83b84139e34909e5ee81758f1ac8fda7 ;;
|
||||
case "${2:-$GSTACK_BUN_TESTED}" in
|
||||
1.4.2) case "$1" in
|
||||
linux-x64) echo 36368faef7527875d5ffa52e53cd48021741f2a83eb6208a8dd64068d422a913 ;;
|
||||
linux-x64-baseline) echo c678040f14fe0440eb839d37cbd0ce4c051a32da72806ac97de6a6aab6bf728f ;;
|
||||
linux-aarch64) echo 54328bbc2d9c8e0c9f892c544d66c57a83b84139e34909e5ee81758f1ac8fda7 ;;
|
||||
*) return 1 ;;
|
||||
esac ;;
|
||||
1.4.3) case "$1" in
|
||||
linux-x64) echo 3e730528d89775f03f87f05c06787c4df4099d0a37f3f252e7b829cb23816e18 ;;
|
||||
linux-x64-baseline) echo 1fc2edac843102909e3a1be1d8d9802cc6071cf074e67e88231f4ffe0f8b397b ;;
|
||||
linux-aarch64) echo efa9813da5ed72423bf847f916e8d2c47c0d776add972354026a75e10da9aa21 ;;
|
||||
*) return 1 ;;
|
||||
esac ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
+19
-9
@@ -103,7 +103,7 @@ install_bun() { # REASON — download, verify and install Bun $WANT into $BUN_DI
|
||||
'Linux aarch64'|'Linux arm64') TARGET=linux-aarch64 ;;
|
||||
*) stop INSTALL_PREFLIGHT_FAILED "no verified Bun $WANT archive for $(uname -ms) (this installer is for Capy cloud Ubuntu)" "install Bun $WANT by hand (https://bun.sh), then re-run" ;;
|
||||
esac
|
||||
SHA=$(gstack_bun_archive_sha256 "$TARGET") || stop INSTALL_PREFLIGHT_FAILED "no verified Bun $WANT archive for $TARGET" "install Bun $WANT by hand, then re-run"
|
||||
SHA=$(gstack_bun_archive_sha256 "$TARGET" "$WANT") || stop INSTALL_PREFLIGHT_FAILED "no verified Bun $WANT archive for $TARGET" "install Bun $WANT by hand, then re-run"
|
||||
TMP=$(mktemp -d "${TMPDIR:-/tmp}/gstack-bun.XXXXXX") || stop INSTALL_PREFLIGHT_FAILED "cannot create a temp dir" "point TMPDIR at a writable directory"
|
||||
curl --retry 3 -fsSL "https://github.com/oven-sh/bun/releases/download/bun-v$WANT/bun-$TARGET.zip" -o "$TMP/bun.zip" || stop INSTALL_PREFLIGHT_FAILED "could not download bun-v$WANT/bun-$TARGET.zip" "check network access to github.com, then re-run"
|
||||
echo "$SHA $TMP/bun.zip" | sha256sum -c - >/dev/null 2>&1 || { rm -rf "$TMP"; stop INSTALL_PREFLIGHT_FAILED "bun-$TARGET.zip SHA-256 mismatch (expected $SHA); nothing installed" "update gstack_bun_archive_sha256 in bin/gstack-bun-version.sh only after checking the release's SHASUMS256.txt"; }
|
||||
@@ -130,6 +130,14 @@ for _d in "$BUN_DIR" "$HOME/.bun/bin"; do
|
||||
_v=$("$_d/bun" --version 2>/dev/null | head -1)
|
||||
[ "$(gstack_bun_status "${_v:-0.0.0}")" = ok ] && { LD_BIN="$_d/bun" LD_VER="$_v"; break; }
|
||||
done
|
||||
# follow_pin VERSION SOURCE — an exact project pin becomes the Bun to install
|
||||
# when it is at or above gstack's minimum and has a verified archive; anything
|
||||
# else is a conflict naming both constraints and the verified versions.
|
||||
follow_pin() {
|
||||
[ "$1" = "$WANT" ] && return 0
|
||||
if [ "$WANT" = "$GSTACK_BUN_TESTED" ] && [ "$(gstack_bun_status "$1")" = ok ] && gstack_bun_archive_sha256 linux-x64 "$1" >/dev/null; then WANT="$1"; return 0; fi
|
||||
stop RUNTIME_PIN_CONFLICT "Bun conflict: gstack needs >=$GSTACK_BUN_TESTED (verified archives: $GSTACK_BUN_VERIFIED), $2 pins exactly $1" "raise the project's pin to a verified version, or install gstack on a machine the project already provisions"
|
||||
}
|
||||
reuse_ld() { launch_with "$(dirname "$LD_BIN")"; say "reusing bun $LD_VER at $LD_BIN (not first on PATH; the GSTACK_LAUNCH line puts it first)"; }
|
||||
# No Bun at or above the security floor anywhere: install the verified one
|
||||
# first, so the project's pins can be read with it.
|
||||
@@ -144,16 +152,18 @@ if printf '%s\n' "$PINS_OUT" | grep -q '^PINS_VERDICT: '; then
|
||||
if [ "$HAVE_OK" -eq 1 ] && pins_ok "$HAVE"; then say "bun $HAVE satisfies gstack's supported minimum $WANT and the project pins"
|
||||
elif [ -n "$LD_BIN" ] && pins_ok "$LD_VER"; then reuse_ld
|
||||
else
|
||||
printf '%s\n' "$PINS_OUT" | sed -n 's/^PIN: bun \([^ ]*\) exact \([^ ]*\) lane=[a-z]*$/\1 \2/p' | while read -r _c _src; do
|
||||
[ "$_c" = "$WANT" ] || stop RUNTIME_PIN_CONFLICT "Bun conflict: gstack needs >=$WANT (its verified archive is $WANT), $PROJECT/${_src%%:*} pins exactly $_c (${_src})" "raise the project's pin to $WANT, or install gstack on a machine the project accepts"
|
||||
done || exit 3
|
||||
while read -r _c _src; do
|
||||
[ -z "$_c" ] || follow_pin "$_c" "$PROJECT/${_src%%:*}"
|
||||
done <<EOF_PINS
|
||||
$(printf '%s\n' "$PINS_OUT" | sed -n 's/^PIN: bun \([^ ]*\) exact \([^ ]*\) lane=[a-z]*$/\1 \2/p')
|
||||
EOF_PINS
|
||||
pins_ok "$WANT" || stop RUNTIME_PIN_CONFLICT "Bun conflict: gstack needs >=$WANT, $PROJECT pins $(printf '%s\n' "$PINS_OUT" | sed -n 's/^PIN_SUMMARY: //p' | grep '^bun' | tr '\n' ';' | sed 's/;$//')" "raise the project's pin to $WANT or newer, or install gstack on a machine the project accepts"
|
||||
if [ "$LD_VER" = "$WANT" ]; then reuse_ld; else install_bun "bun ${HAVE:-absent} does not satisfy the project pins (or gstack's minimum $WANT)"; fi
|
||||
fi
|
||||
else
|
||||
# No pin report (no project, or a Bun that cannot run the parser): the
|
||||
# package.json / .bun-version subset, read with jq.
|
||||
PIN="" PIN_SRC=""
|
||||
PIN="" PIN_SRC="" EXACT=0
|
||||
if [ -n "$PROJECT" ] && [ -f "$PROJECT/package.json" ]; then
|
||||
PIN=$(jq -r '.engines.bun // (.packageManager // "" | select(startswith("bun@")) | ltrimstr("bun@")) // empty' "$PROJECT/package.json" 2>/dev/null | head -1)
|
||||
[ -n "$PIN" ] && PIN_SRC="$PROJECT/package.json"
|
||||
@@ -162,12 +172,12 @@ else
|
||||
case "$PIN" in
|
||||
'') ;;
|
||||
'>='*) _gstack_bun_below "$WANT" "${PIN#>=}" && stop RUNTIME_PIN_CONFLICT "Bun conflict: gstack needs >=$WANT, $PIN_SRC pins $PIN" "raise the project's pin to $WANT or newer, or install gstack on a machine the project accepts" ;;
|
||||
[0-9]*.[0-9]*.[0-9]*) [ "$PIN" = "$WANT" ] || stop RUNTIME_PIN_CONFLICT "Bun conflict: gstack needs >=$WANT, $PIN_SRC pins exactly $PIN" "raise the project's pin to $WANT, or install gstack on a machine the project accepts" ;;
|
||||
[0-9]*.[0-9]*.[0-9]*) follow_pin "$PIN" "$PIN_SRC"; EXACT=1 ;;
|
||||
*) say "note: project pin '$PIN' ($PIN_SRC) is not evaluated here; gstack-doctor's pins row checks it after install" ;;
|
||||
esac
|
||||
if [ "$HAVE_OK" -eq 1 ]; then say "bun $HAVE satisfies gstack's supported minimum $WANT${PIN:+ and the project pin $PIN}"
|
||||
elif [ -n "$LD_BIN" ]; then reuse_ld
|
||||
elif [ -z "$LAUNCH_DIR" ]; then install_bun "bun ${HAVE:-absent} is below gstack's supported minimum $WANT${PIN:+ (project pin $PIN agrees)}"
|
||||
if [ "$HAVE_OK" -eq 1 ] && { [ "$EXACT" -eq 0 ] || [ "$HAVE" = "$WANT" ]; }; then say "bun $HAVE satisfies gstack's supported minimum $GSTACK_BUN_TESTED${PIN:+ and the project pin $PIN}"
|
||||
elif [ -n "$LD_BIN" ] && { [ "$EXACT" -eq 0 ] || [ "$LD_VER" = "$WANT" ]; }; then reuse_ld
|
||||
elif [ -z "$LAUNCH_DIR" ] || [ "$LD_VER" != "$WANT" ]; then install_bun "bun ${HAVE:-absent} does not satisfy gstack's supported minimum $GSTACK_BUN_TESTED${PIN:+ and the project pin $PIN}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -160,6 +160,30 @@ describe('gstack-capy-install', () => {
|
||||
expect(conflictRange.stderr).toContain('pins >=2.0.0');
|
||||
});
|
||||
|
||||
test('an exact project pin above the minimum with a verified archive is the Bun installed; an unverified one stops naming the verified versions', () => {
|
||||
const f = fixture({ bun: '1.3.14' });
|
||||
const project = path.join(f.base, 'project');
|
||||
write(path.join(project, '.bun-version'), '1.4.3\n');
|
||||
sh('git init -q', project);
|
||||
const zip = path.join(f.base, 'bad.zip');
|
||||
fs.mkdirSync(path.join(f.base, 'z/bun-linux-x64'), { recursive: true });
|
||||
script(path.join(f.base, 'z/bun-linux-x64/bun'), ['echo 1.4.3']);
|
||||
expect(sh(`cd "${f.base}/z" && zip -qr "${zip}" bun-linux-x64`).status).toBe(0);
|
||||
const adopted = run(f, ['--project', project], { STUB_CURL_ZIP: zip });
|
||||
expect(adopted.stdout).toContain('installing bun 1.4.3 from its release archive');
|
||||
expect(f.calls().filter(l => l.startsWith('curl '))).toEqual([expect.stringContaining('https://github.com/oven-sh/bun/releases/download/bun-v1.4.3/bun-linux')]);
|
||||
expect(adopted.status).toBe(3);
|
||||
expect(adopted.stderr).toContain('SHA-256 mismatch');
|
||||
const g = fixture({ bun: '1.3.14' });
|
||||
write(path.join(project, '.bun-version'), '1.4.9\n');
|
||||
const unverified = run(g, ['--project', project]);
|
||||
expect(unverified.status).toBe(3);
|
||||
expect(unverified.stderr).toContain(`${project}/.bun-version pins exactly 1.4.9`);
|
||||
expect(unverified.stderr).toContain('verified archives: 1.4.2 1.4.3');
|
||||
expect(unverified.stderr).toContain('(RUNTIME_PIN_CONFLICT; ');
|
||||
expect(g.calls().some(l => l.startsWith('curl ') || l.startsWith('setup '))).toBe(false);
|
||||
});
|
||||
|
||||
test('Bun below the minimum: the exact release archive is downloaded and SHA-256 verified; a mismatch installs nothing', () => {
|
||||
const f = fixture({ bun: '1.3.14' });
|
||||
const zip = path.join(f.base, 'bad.zip');
|
||||
|
||||
Reference in new issue
Block a user