Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions scripts/run
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,30 @@ set -euo pipefail
# OpenCode, and direct local invocation.
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}}"

# Platform detection
# Platform detection. Normalise MinGW/MSYS/Cygwin (Git Bash on Windows) to
# `windows` so the launcher resolves the same binary as scripts/run.cmd and
# the goreleaser asset names on GitHub releases.
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
case "$OS" in
mingw*|msys*|cygwin*) OS="windows" ;;
esac
ARCH="$(uname -m)"
case "$ARCH" in
x86_64) ARCH="amd64" ;;
aarch64) ARCH="arm64" ;;
esac
EXT=""
[ "$OS" = "windows" ] && EXT=".exe"

# Find binary: check bin/ first, then goreleaser dist/ output, then download
# Find binary: check bin/ first, then goreleaser dist/ output, then download.
# `make build-local` runs `go build -o bin/lumen .` which, even on Windows,
# does NOT append .exe when -o is explicit — so we must keep the
# extensionless dev-build candidate alongside the .exe one.
BINARY=""
for candidate in \
"${PLUGIN_ROOT}/bin/lumen${EXT}" \
"${PLUGIN_ROOT}/bin/lumen" \
"${PLUGIN_ROOT}/bin/lumen-${OS}-${ARCH}"; do
"${PLUGIN_ROOT}/bin/lumen-${OS}-${ARCH}${EXT}"; do
if [ -x "$candidate" ]; then
BINARY="$candidate"
break
Expand All @@ -27,7 +38,7 @@ done

# Download on first run if no binary found
if [ -z "$BINARY" ]; then
BINARY="${PLUGIN_ROOT}/bin/lumen-${OS}-${ARCH}"
BINARY="${PLUGIN_ROOT}/bin/lumen-${OS}-${ARCH}${EXT}"

REPO="ory/lumen"

Expand All @@ -43,7 +54,7 @@ if [ -z "$BINARY" ]; then
exit 1
fi

ASSET="lumen-${VERSION#v}-${OS}-${ARCH}"
ASSET="lumen-${VERSION#v}-${OS}-${ARCH}${EXT}"
URL="https://github.com/${REPO}/releases/download/${VERSION}/${ASSET}"

echo "Downloading lumen ${VERSION} for ${OS}/${ARCH}..." >&2
Expand All @@ -70,7 +81,7 @@ if [ -z "$BINARY" ]; then

echo "Falling back to ${LATEST_TAG}..." >&2
VERSION="$LATEST_TAG"
ASSET="lumen-${VERSION#v}-${OS}-${ARCH}"
ASSET="lumen-${VERSION#v}-${OS}-${ARCH}${EXT}"
URL="https://github.com/${REPO}/releases/download/${VERSION}/${ASSET}"

curl -fL --progress-bar --max-time 300 --retry 3 --retry-delay 2 "$URL" -o "$BINARY"
Expand Down
72 changes: 70 additions & 2 deletions scripts/test_run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ normalise_arch() {
esac
}

# ---------------------------------------------------------------------------
# OS normalisation (mirrors run case statement). Maps Git Bash / MSYS2 /
# Cygwin uname strings to `windows` so the launcher resolves the same
# binary asset as run.cmd. Emits "<os>:<ext>" so callers can also verify
# the executable suffix that windows builds require.
# ---------------------------------------------------------------------------
normalise_os() {
local os="$1"
case "$os" in
mingw*|msys*|cygwin*) os="windows" ;;
esac
local ext=""
[ "$os" = "windows" ] && ext=".exe"
echo "${os}:${ext}"
}

echo "=== asset name tests ==="
assert_eq "macOS arm64 asset" \
"lumen-0.0.1-alpha.4-darwin-arm64" \
Expand Down Expand Up @@ -104,8 +120,54 @@ assert_eq "aarch64 → arm64" "arm64" "$(normalise_arch "aarch64")"
assert_eq "arm64 passthrough" "arm64" "$(normalise_arch "arm64")"
assert_eq "amd64 passthrough" "amd64" "$(normalise_arch "amd64")"

echo ""
echo "=== OS normalisation tests ==="
# Git Bash / MSYS2 / Cygwin emit uname -s strings that begin with MINGW64_NT,
# MINGW32_NT, MSYS_NT, or CYGWIN_NT. Before this normalisation the launcher
# took those strings verbatim and constructed asset URLs like
# `lumen-X.Y.Z-mingw64_nt-10.0-26200-amd64`, which 404 on GitHub releases
# and skip the already-installed `bin/lumen-windows-amd64.exe`.
assert_eq "MinGW64 Git Bash → windows + .exe" \
"windows:.exe" "$(normalise_os "mingw64_nt-10.0-26200")"
assert_eq "MinGW32 Git Bash → windows + .exe" \
"windows:.exe" "$(normalise_os "mingw32_nt-10.0")"
assert_eq "MSYS2 → windows + .exe" \
"windows:.exe" "$(normalise_os "msys_nt-10.0-26200")"
assert_eq "Cygwin → windows + .exe" \
"windows:.exe" "$(normalise_os "cygwin_nt-10.0")"
assert_eq "windows passthrough → windows + .exe" \
"windows:.exe" "$(normalise_os "windows")"
assert_eq "linux passthrough → linux, no ext" \
"linux:" "$(normalise_os "linux")"
assert_eq "darwin passthrough → darwin, no ext" \
"darwin:" "$(normalise_os "darwin")"

echo ""
echo "=== binary candidate priority tests ==="
# Windows dev-build case: `make build-local` runs `go build -o bin/lumen .`
# which produces an extensionless `bin/lumen` even on Windows. The launcher
# must still discover it ahead of falling back to the downloaded artefact.
# We test the candidate ordering directly (no [ -x ] dependency, since Git
# Bash refuses to mark extensionless touch-created files as executable —
# the pre-existing two `[ -x ]`-based tests below fail on Git Bash for that
# reason, unrelated to this fix).
expected_candidates() {
local os="$1" arch="$2"
local ext=""
case "$os" in mingw*|msys*|cygwin*) os="windows" ;; esac
[ "$os" = "windows" ] && ext=".exe"
printf 'bin/lumen%s\nbin/lumen\nbin/lumen-%s-%s%s\n' "$ext" "$os" "$arch" "$ext"
}
assert_eq "windows candidates: .exe, extensionless dev, downloaded" \
"$(printf 'bin/lumen.exe\nbin/lumen\nbin/lumen-windows-amd64.exe\n')" \
"$(expected_candidates windows amd64)"
assert_eq "mingw normalises, keeps extensionless dev build candidate" \
"$(printf 'bin/lumen.exe\nbin/lumen\nbin/lumen-windows-amd64.exe\n')" \
"$(expected_candidates mingw64_nt-10.0-26200 amd64)"
assert_eq "linux candidates: extensionless dev, downloaded" \
"$(printf 'bin/lumen\nbin/lumen\nbin/lumen-linux-amd64\n')" \
"$(expected_candidates linux amd64)"

TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT

Expand Down Expand Up @@ -168,9 +230,12 @@ echo "=== stdio download-on-first-run integration test ==="
trap 'rm -rf "$_TMPROOT" "$_FAKE_CURL_DIR"' EXIT

OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
case "$OS" in mingw*|msys*|cygwin*) OS="windows" ;; esac
EXT=""
[ "$OS" = "windows" ] && EXT=".exe"
ARCH_RAW="$(uname -m)"
case "$ARCH_RAW" in x86_64) ARCH="amd64" ;; aarch64) ARCH="arm64" ;; *) ARCH="$ARCH_RAW" ;; esac
_EXPECTED_BINARY="${_TMPROOT}/bin/lumen-${OS}-${ARCH}"
_EXPECTED_BINARY="${_TMPROOT}/bin/lumen-${OS}-${ARCH}${EXT}"

printf '{\n ".": "0.0.1"\n}\n' > "${_TMPROOT}/.release-please-manifest.json"
mkdir -p "${_TMPROOT}/bin"
Expand Down Expand Up @@ -304,13 +369,16 @@ echo "=== stdio first-install MCP handshake test ==="
trap 'rm -rf "$_TMPROOT" "$_FAKE_CURL_DIR" "$_MOCK_BIN_DIR"' EXIT

_OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
case "$_OS" in mingw*|msys*|cygwin*) _OS="windows" ;; esac
_EXT=""
[ "$_OS" = "windows" ] && _EXT=".exe"
_ARCH_RAW="$(uname -m)"
case "$_ARCH_RAW" in
x86_64) _ARCH="amd64" ;;
aarch64) _ARCH="arm64" ;;
*) _ARCH="$_ARCH_RAW" ;;
esac
_EXPECTED_BINARY="${_TMPROOT}/bin/lumen-${_OS}-${_ARCH}"
_EXPECTED_BINARY="${_TMPROOT}/bin/lumen-${_OS}-${_ARCH}${_EXT}"

_MOCK_BIN="${_MOCK_BIN_DIR}/mock_lumen"
if ! (cd "${_REPO_ROOT}" && CGO_ENABLED=0 go build -o "${_MOCK_BIN}" ./scripts/testdata/mock_mcp_server) >"${_TMPROOT}/mock_build.log" 2>&1; then
Expand Down
Loading