mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
fix: deliver the static -portable linux binary on all install/update paths
The standard linux release binary dynamically links glibc 2.38+ and GLIBCXX_3.4.32, so it fails to start on Debian 11, Ubuntu 20.04/22.04, RHEL/Rocky 8/9, Amazon Linux 2, etc. — yet install.sh, the npm and PyPI wrappers, and the binary's own self-update all fetched it by default, contradicting the "single static binary" promise. Point every linux install + self-update path at the fully-static "-portable" asset (gcc -static), which has no glibc floor. macOS/Windows are unaffected and unchanged. - install.sh, pkg/npm/install.js, pkg/pypi _cli.py: select -portable on linux - src/cli/cli.c: self-update download URL AND checksum archive name both use -portable on linux (they must match or the update fails checksum verify) - scripts/smoke-test.sh: assert linux self-update targets the -portable asset - scripts/ci/check-glibc-compat.sh: new guard — runs the binary inside debian:bullseye (glibc 2.31) and asserts it starts - _smoke.yml: run the guard on the portable binary in smoke-linux-portable Reproduced: standard binary -> "GLIBC_2.38 not found" on glibc 2.31; portable binary runs cleanly.
This commit is contained in:
1 parent
16103d9e39
commit
69c16cada4
7 files changed
+69
-8
No files matched your search
@@ -189,6 +189,13 @@ jobs:
|
||||
chmod +x codebase-memory-mcp
|
||||
scripts/smoke-test.sh ./codebase-memory-mcp
|
||||
|
||||
# The -portable binary is what all linux install/update paths now deliver;
|
||||
# it MUST start on old glibc (Debian 11 / RHEL 8 / Ubuntu 20.04). Runs it
|
||||
# in debian:bullseye (glibc 2.31) — the standard dynamic binary would fail
|
||||
# here with `GLIBC_2.38 not found`.
|
||||
- name: Old-glibc compatibility
|
||||
run: scripts/ci/check-glibc-compat.sh ./codebase-memory-mcp
|
||||
|
||||
- name: Security audits
|
||||
run: |
|
||||
scripts/security-strings.sh ./codebase-memory-mcp
|
||||
|
||||
+8
-2
@@ -97,10 +97,16 @@ else
|
||||
EXT="tar.gz"
|
||||
fi
|
||||
|
||||
# Linux ships a fully-static "-portable" build; the standard linux binary
|
||||
# dynamically links glibc 2.38+ and fails on older distros (Debian 11, RHEL 8,
|
||||
# Ubuntu 20.04). macOS/Windows have no such variant.
|
||||
PORTABLE=""
|
||||
[ "$OS" = "linux" ] && PORTABLE="-portable"
|
||||
|
||||
if [ "$VARIANT" = "ui" ]; then
|
||||
ARCHIVE="codebase-memory-mcp-ui-${OS}-${ARCH}.${EXT}"
|
||||
ARCHIVE="codebase-memory-mcp-ui-${OS}-${ARCH}${PORTABLE}.${EXT}"
|
||||
else
|
||||
ARCHIVE="codebase-memory-mcp-${OS}-${ARCH}.${EXT}"
|
||||
ARCHIVE="codebase-memory-mcp-${OS}-${ARCH}${PORTABLE}.${EXT}"
|
||||
fi
|
||||
|
||||
URL="${CBM_DOWNLOAD_URL}/${ARCHIVE}"
|
||||
|
||||
+5
-1
@@ -105,7 +105,11 @@ async function main() {
|
||||
|
||||
fs.mkdirSync(BIN_DIR, { recursive: true });
|
||||
|
||||
const archive = `codebase-memory-mcp-${platform}-${arch}.${ext}`;
|
||||
// Linux ships a fully-static "-portable" build; the standard linux binary
|
||||
// dynamically links glibc 2.38+ and fails on older distros. macOS/Windows
|
||||
// have no such variant. Keep in sync with install.sh / pypi _cli.py / cli.c.
|
||||
const variant = platform === 'linux' ? '-portable' : '';
|
||||
const archive = `codebase-memory-mcp-${platform}-${arch}${variant}.${ext}`;
|
||||
const url = `https://github.com/${REPO}/releases/download/v${VERSION}/${archive}`;
|
||||
|
||||
process.stdout.write(`codebase-memory-mcp: downloading v${VERSION} for ${platform}/${arch}...\n`);
|
||||
|
||||
@@ -153,7 +153,11 @@ def _download(version: str) -> Path:
|
||||
os_name = _os_name()
|
||||
arch = _arch()
|
||||
ext = "zip" if os_name == "windows" else "tar.gz"
|
||||
archive = f"codebase-memory-mcp-{os_name}-{arch}.{ext}"
|
||||
# Linux ships a fully-static "-portable" build; the standard linux binary
|
||||
# dynamically links glibc 2.38+ and fails on older distros. macOS/Windows
|
||||
# have no such variant. Keep in sync with install.sh / install.js / cli.c.
|
||||
variant = "-portable" if os_name == "linux" else ""
|
||||
archive = f"codebase-memory-mcp-{os_name}-{arch}{variant}.{ext}"
|
||||
url = f"https://github.com/{REPO}/releases/download/v{version}/{archive}"
|
||||
_validate_url_scheme(url)
|
||||
|
||||
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
# Regression guard: the linux binary we ship must START on OLD glibc.
|
||||
#
|
||||
# The standard linux release binary dynamically links glibc 2.38+ / GLIBCXX
|
||||
# 3.4.32 and fails to start on Debian 11, RHEL/Rocky 8, Ubuntu 20.04, Amazon
|
||||
# Linux 2, etc. The fix points all linux install + self-update paths at the
|
||||
# fully-static "-portable" asset. This runs a given linux binary inside an
|
||||
# old-glibc container (debian:bullseye, glibc 2.31) and asserts it starts:
|
||||
# - RED for the dynamic standard binary (GLIBC_2.38 not found)
|
||||
# - GREEN for the static -portable binary (runs anywhere)
|
||||
#
|
||||
# Usage: check-glibc-compat.sh <path-to-linux-binary>
|
||||
# Env: GLIBC_TEST_IMAGE (default: debian:bullseye-slim, glibc 2.31)
|
||||
set -euo pipefail
|
||||
|
||||
BIN="${1:?usage: check-glibc-compat.sh <path-to-linux-binary>}"
|
||||
IMAGE="${GLIBC_TEST_IMAGE:-debian:bullseye-slim}"
|
||||
BIN_ABS="$(cd "$(dirname "$BIN")" && pwd)/$(basename "$BIN")"
|
||||
|
||||
echo "==> running $(basename "$BIN") --version inside ${IMAGE} (glibc 2.31)"
|
||||
docker run --rm -v "${BIN_ABS}:/cbm:ro" "${IMAGE}" /cbm --version
|
||||
echo "PASS: binary starts on old glibc (${IMAGE})"
|
||||
@@ -584,6 +584,17 @@ if ! echo "$UPDATE_OUT" | grep -qi 'standard'; then
|
||||
echo "FAIL: update --dry-run did not respect --standard flag"
|
||||
exit 1
|
||||
fi
|
||||
# On Linux the binary must self-update from the static "-portable" asset: the
|
||||
# standard linux asset dynamically links glibc 2.38+ and breaks on older distros
|
||||
# (Debian 11, RHEL 8, Ubuntu 20.04). Guards build_update_url in src/cli/cli.c.
|
||||
if [ "$(uname -s)" = "Linux" ]; then
|
||||
if ! echo "$UPDATE_OUT" | grep -q -- '-portable'; then
|
||||
echo "FAIL: linux update --dry-run does not target the -portable asset"
|
||||
echo "$UPDATE_OUT"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: linux update targets the -portable (static) asset"
|
||||
fi
|
||||
echo "OK: update --dry-run --standard completed"
|
||||
|
||||
# 6d: config set/get/reset round-trip
|
||||
|
||||
+11
-4
@@ -3761,8 +3761,13 @@ static void build_update_url(char *url, int url_sz, const char *os, const char *
|
||||
if (!base_url || !base_url[0]) {
|
||||
base_url = "https://github.com/DeusData/codebase-memory-mcp/releases/latest/download";
|
||||
}
|
||||
snprintf(url, url_sz, "%s/codebase-memory-mcp-%s%s-%s.%s", base_url, want_ui ? "ui-" : "", os,
|
||||
arch, ext);
|
||||
/* Linux ships a fully-static "-portable" build; the standard linux binary
|
||||
* dynamically links glibc 2.38+ and fails on older distros. macOS/Windows
|
||||
* have no such variant. Keep in sync with install.sh / install.js / pypi
|
||||
* _cli.py. */
|
||||
const char *portable = (strcmp(os, "linux") == 0) ? "-portable" : "";
|
||||
snprintf(url, url_sz, "%s/codebase-memory-mcp-%s%s-%s%s.%s", base_url, want_ui ? "ui-" : "", os,
|
||||
arch, portable, ext);
|
||||
}
|
||||
|
||||
/* Prompt to delete existing indexes. Returns 0 to continue, 1 to abort. */
|
||||
@@ -3801,8 +3806,10 @@ static int download_verify_install(const char *url, const char *ext, const char
|
||||
}
|
||||
|
||||
char archive_name[CLI_BUF_256];
|
||||
snprintf(archive_name, sizeof(archive_name), "codebase-memory-mcp-%s%s-%s.%s",
|
||||
want_ui ? "ui-" : "", os, arch, ext);
|
||||
/* Must match build_update_url: linux uses the static "-portable" asset. */
|
||||
const char *portable = (strcmp(os, "linux") == 0) ? "-portable" : "";
|
||||
snprintf(archive_name, sizeof(archive_name), "codebase-memory-mcp-%s%s-%s%s.%s",
|
||||
want_ui ? "ui-" : "", os, arch, portable, ext);
|
||||
int crc = verify_download_checksum(tmp_archive, archive_name);
|
||||
if (crc == CLI_TRUE) {
|
||||
cbm_unlink(tmp_archive);
|
||||
|
||||
Reference in new issue
Block a user