Skip to content
Merged
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
86 changes: 32 additions & 54 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,10 @@ permissions:
env:
WALLY_VERSION: ${{ github.event.inputs.version || github.ref_name }}

# Every platform builds two bottles from one kit: `prod` (empty bake -> the
# production console defaults in credentials.cpp) and `dev` (dev console
# endpoints baked from the WALLY_DEV_* repo variables, so a dev build targets
# the dev backend with no env vars). The bake reaches the configure step as
# environment only — never on the command line, never in committed source. The
# configure→build→package sequence lives in .github/actions/build-wally; e2e
# runs on the binary it produced, so the bottle is built exactly once.
# Every platform builds one bottle from one kit: `prod` (empty bake -> the
# production console defaults in credentials.cpp). The configure→build→package
# sequence lives in .github/actions/build-wally; e2e runs on the binary it
# produced, so the bottle is built exactly once.
jobs:
macos:
# SDK Package.swift is swift-tools-version 6.2 (Xcode 26).
Expand All @@ -32,11 +29,9 @@ jobs:
strategy:
fail-fast: false
matrix:
variant: [prod, dev]
variant: [prod]
env:
WALLY_SDK_SWIFT_PATH: ${{ github.workspace }}/.deps/runanywhere-sdks
WALLY_BAKED_CONSOLE_API_URL: ${{ matrix.variant == 'dev' && vars.WALLY_DEV_CONSOLE_API_URL || '' }}
WALLY_BAKED_CONSOLE_WEB_ORIGIN: ${{ matrix.variant == 'dev' && vars.WALLY_DEV_CONSOLE_WEB_ORIGIN || '' }}
steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -79,10 +74,9 @@ jobs:
- name: Verify archive
run: |
VERSION="${WALLY_VERSION#v}"
suffix=""; [ "${{ matrix.variant }}" = dev ] && suffix="-dev"
python3 scripts/release/verify-release-assets.py \
"dist/wally-${VERSION}-macos-arm64${suffix}.tar.gz" \
"dist/wally-${VERSION}-macos-arm64${suffix}.tar.gz.sha256"
"dist/wally-${VERSION}-macos-arm64.tar.gz" \
"dist/wally-${VERSION}-macos-arm64.tar.gz.sha256"
- uses: actions/upload-artifact@v4
with:
name: wally-macos-arm64-${{ matrix.variant }}
Expand All @@ -94,10 +88,7 @@ jobs:
strategy:
fail-fast: false
matrix:
variant: [prod, dev]
env:
WALLY_BAKED_CONSOLE_API_URL: ${{ matrix.variant == 'dev' && vars.WALLY_DEV_CONSOLE_API_URL || '' }}
WALLY_BAKED_CONSOLE_WEB_ORIGIN: ${{ matrix.variant == 'dev' && vars.WALLY_DEV_CONSOLE_WEB_ORIGIN || '' }}
variant: [prod]
steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -139,16 +130,14 @@ jobs:
shell: pwsh
run: |
$ver = "${env:WALLY_VERSION}".TrimStart("v")
$suffix = if ("${{ matrix.variant }}" -eq "dev") { "-dev" } else { "" }
scripts/test/smoke-zip-windows.ps1 -Zip "dist/wally-$ver-windows-arm64$suffix.zip"
scripts/test/smoke-zip-windows.ps1 -Zip "dist/wally-$ver-windows-arm64.zip"
- name: Verify archive
shell: bash
run: |
ver="${WALLY_VERSION#v}"
suffix=""; [ "${{ matrix.variant }}" = dev ] && suffix="-dev"
python scripts/release/verify-release-assets.py \
"dist/wally-$ver-windows-arm64$suffix.zip" \
"dist/wally-$ver-windows-arm64$suffix.zip.sha256"
"dist/wally-$ver-windows-arm64.zip" \
"dist/wally-$ver-windows-arm64.zip.sha256"
- uses: actions/upload-artifact@v4
with:
name: wally-windows-arm64-${{ matrix.variant }}
Expand All @@ -163,10 +152,7 @@ jobs:
strategy:
fail-fast: false
matrix:
variant: [prod, dev]
env:
WALLY_BAKED_CONSOLE_API_URL: ${{ matrix.variant == 'dev' && vars.WALLY_DEV_CONSOLE_API_URL || '' }}
WALLY_BAKED_CONSOLE_WEB_ORIGIN: ${{ matrix.variant == 'dev' && vars.WALLY_DEV_CONSOLE_WEB_ORIGIN || '' }}
variant: [prod]
steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -206,16 +192,14 @@ jobs:
shell: pwsh
run: |
$ver = "${env:WALLY_VERSION}".TrimStart("v")
$suffix = if ("${{ matrix.variant }}" -eq "dev") { "-dev" } else { "" }
scripts/test/smoke-zip-windows.ps1 -Zip "dist/wally-$ver-windows-x86_64$suffix.zip"
scripts/test/smoke-zip-windows.ps1 -Zip "dist/wally-$ver-windows-x86_64.zip"
- name: Verify archive
shell: bash
run: |
ver="${WALLY_VERSION#v}"
suffix=""; [ "${{ matrix.variant }}" = dev ] && suffix="-dev"
python scripts/release/verify-release-assets.py \
"dist/wally-$ver-windows-x86_64$suffix.zip" \
"dist/wally-$ver-windows-x86_64$suffix.zip.sha256"
"dist/wally-$ver-windows-x86_64.zip" \
"dist/wally-$ver-windows-x86_64.zip.sha256"
- uses: actions/upload-artifact@v4
with:
name: wally-windows-x64-${{ matrix.variant }}
Expand All @@ -230,10 +214,7 @@ jobs:
strategy:
fail-fast: false
matrix:
variant: [prod, dev]
env:
WALLY_BAKED_CONSOLE_API_URL: ${{ matrix.variant == 'dev' && vars.WALLY_DEV_CONSOLE_API_URL || '' }}
WALLY_BAKED_CONSOLE_WEB_ORIGIN: ${{ matrix.variant == 'dev' && vars.WALLY_DEV_CONSOLE_WEB_ORIGIN || '' }}
variant: [prod]
steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -271,10 +252,9 @@ jobs:
- name: Verify archive
run: |
VERSION="${WALLY_VERSION#v}"
suffix=""; [ "${{ matrix.variant }}" = dev ] && suffix="-dev"
python3 scripts/release/verify-release-assets.py \
"dist/wally-${VERSION}-linux-x86_64${suffix}.tar.gz" \
"dist/wally-${VERSION}-linux-x86_64${suffix}.tar.gz.sha256"
"dist/wally-${VERSION}-linux-x86_64.tar.gz" \
"dist/wally-${VERSION}-linux-x86_64.tar.gz.sha256"
- uses: actions/upload-artifact@v4
with:
name: wally-linux-x86_64-${{ matrix.variant }}
Expand All @@ -295,26 +275,24 @@ jobs:
run: |
set -euo pipefail
VERSION="${WALLY_VERSION#v}"
# Both bottles of every platform: prod (no suffix) and dev (-dev).
for suffix in "" "-dev"; do
python3 scripts/release/verify-release-assets.py \
"artifacts/wally-${VERSION}-macos-arm64${suffix}.tar.gz" \
"artifacts/wally-${VERSION}-macos-arm64${suffix}.tar.gz.sha256"
python3 scripts/release/verify-release-assets.py \
"artifacts/wally-${VERSION}-windows-x86_64${suffix}.zip" \
"artifacts/wally-${VERSION}-windows-x86_64${suffix}.zip.sha256"
python3 scripts/release/verify-release-assets.py \
"artifacts/wally-${VERSION}-windows-arm64${suffix}.zip" \
"artifacts/wally-${VERSION}-windows-arm64${suffix}.zip.sha256"
python3 scripts/release/verify-release-assets.py \
"artifacts/wally-${VERSION}-linux-x86_64${suffix}.tar.gz" \
"artifacts/wally-${VERSION}-linux-x86_64${suffix}.tar.gz.sha256"
done
# One bottle per platform.
python3 scripts/release/verify-release-assets.py \
"artifacts/wally-${VERSION}-macos-arm64.tar.gz" \
"artifacts/wally-${VERSION}-macos-arm64.tar.gz.sha256"
python3 scripts/release/verify-release-assets.py \
"artifacts/wally-${VERSION}-windows-x86_64.zip" \
"artifacts/wally-${VERSION}-windows-x86_64.zip.sha256"
python3 scripts/release/verify-release-assets.py \
"artifacts/wally-${VERSION}-windows-arm64.zip" \
"artifacts/wally-${VERSION}-windows-arm64.zip.sha256"
python3 scripts/release/verify-release-assets.py \
"artifacts/wally-${VERSION}-linux-x86_64.tar.gz" \
"artifacts/wally-${VERSION}-linux-x86_64.tar.gz.sha256"
- name: Generate Homebrew formula update
run: |
set -euo pipefail
VERSION="${WALLY_VERSION#v}"
# Homebrew ships the production bottle; the dev bottle is not tapped.
# Homebrew ships the production bottle.
sidecar="artifacts/wally-${VERSION}-macos-arm64.tar.gz.sha256"
digest=$(awk 'NF == 2 { print $1 }' "$sidecar")
[[ "$digest" =~ ^[0-9a-f]{64}$ ]]
Expand Down
18 changes: 4 additions & 14 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@ set -eu
# that finds them, so a plain extract-and-symlink keeps every engine working.
#
# Usage:
# curl -fsSL <install.sh> | sh # production build
# curl -fsSL <install.sh> | sh -s -- nightly # nightly (dev-endpoint) build
#
# `nightly` (or --nightly) installs the -dev bottle, which is baked to talk to
# the development console and APIs. Same binary otherwise; it only changes which
# backend it points at, so it does not disturb the production install path.
# curl -fsSL <install.sh> | sh
REPO="RunanywhereAI/wally"
LIB_DIR="${HOME}/.local/lib/wally"
BIN_DIR="${HOME}/.local/bin"
Expand Down Expand Up @@ -58,25 +53,20 @@ skill_target_dirs() {
}

# --- arguments --------------------------------------------------------------
NIGHTLY=0
# The version the caller already has, passed by `wally update` so the script can
# tell it apart from a fresh install and skip the download when nothing is newer.
CURRENT_VERSION=""
for arg in "$@"; do
case "$arg" in
nightly|--nightly) NIGHTLY=1 ;;
nightly|--nightly) fail "nightly/dev installs are no longer published; this installer only supports production releases" ;;
--version=*) CURRENT_VERSION="${arg#--version=}" ;;
# Debug-only: print the resolved skill targets and exit before any
# network work. Exercised by scripts/test/test-install-skill-dirs.sh.
--print-skill-dirs) skill_target_dirs; exit 0 ;;
esac
done

if [ "$NIGHTLY" = 1 ]; then
SUFFIX="-dev"; CHANNEL="nightly (development endpoints)"
else
SUFFIX=""; CHANNEL="production"
fi
CHANNEL="production"

banner
printf ' %sInstalling the %s%s%s build%s\n\n' "$DIM" "$R$B" "$CHANNEL" "$R$DIM" "$R"
Expand Down Expand Up @@ -116,7 +106,7 @@ case "${os}/${arch}" in
esac
ok "${PLATFORM}"

ASSET="wally-${VERSION}-${PLATFORM}${SUFFIX}.tar.gz"
ASSET="wally-${VERSION}-${PLATFORM}.tar.gz"
URL="https://github.com/${REPO}/releases/download/v${VERSION}/${ASSET}"

tmp=$(mktemp -d)
Expand Down
5 changes: 1 addition & 4 deletions scripts/release/verify-release-assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,10 @@
import zipfile


# The dev bottle differs only in an added `-dev` before the extension; its
# staged root is still wally-<platform> (package scripts keep them identical so
# install extracts both the same), so `platform` must exclude the channel.
ASSET = re.compile(
r"^wally-(?P<version>[0-9]+\.[0-9]+\.[0-9]+)-"
r"(?P<platform>macos-arm64|linux-x86_64|windows-x86_64|windows-arm64)"
r"(?P<channel>-dev)?\.(?P<suffix>tar\.gz|zip)$"
r"\.(?P<suffix>tar\.gz|zip)$"
)
MAX_MEMBERS = 100_000
MAX_UNCOMPRESSED_BYTES = 4 * 1024 * 1024 * 1024
Expand Down
21 changes: 20 additions & 1 deletion scripts/test/test-install-cross-shell.sh
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ run_case() {
}

for case_name in happy-path unsupported-platform bad-checksum failed-release-lookup \
update-already-latest update-available; do
update-already-latest update-available nightly-rejected; do
extra=""
case "$case_name" in
happy-path) stub="$GOOD"; os="Darwin"; arch="arm64" ;;
Expand All @@ -138,6 +138,8 @@ for case_name in happy-path unsupported-platform bad-checksum failed-release-loo
update-already-latest) stub="$GOOD"; os="Darwin"; arch="arm64"; extra="--version=1.2.3" ;;
# `wally update` from an older build: proceeds to the full install.
update-available) stub="$GOOD"; os="Darwin"; arch="arm64"; extra="--version=1.0.0" ;;
# nightly/--nightly must fail clearly, not silently fall back to prod.
nightly-rejected) stub="$GOOD"; os="Darwin"; arch="arm64"; extra="nightly" ;;
esac
bash_out="$(run_case bash "$stub" "$os" "$arch" "$extra")"
dash_out="$(run_case dash "$stub" "$os" "$arch" "$extra")"
Expand All @@ -147,4 +149,21 @@ for case_name in happy-path unsupported-platform bad-checksum failed-release-loo
done

[ "$fails" -eq 0 ] || { printf '%d comparison(s) failed\n' "$fails" >&2; exit 1; }

# Extra structural check: nightly-rejected must exit non-zero and mention "error"
nightly_out="$(run_case bash "$GOOD" Darwin arm64 nightly)"
nightly_exit="$(printf '%s\n' "$nightly_out" | head -1)"
nightly_body="$(printf '%s\n' "$nightly_out" | tail -n +2)"
if [ "$nightly_exit" = "1" ]; then
printf 'ok nightly-rejected: exits 1\n'
else
printf 'FAIL nightly-rejected: expected exit 1, got %s\n' "$nightly_exit"
fails=$((fails + 1))
fi
case "$nightly_body" in
*error:*) printf 'ok nightly-rejected: error message printed\n' ;;
*) printf 'FAIL nightly-rejected: no "error:" in output: %s\n' "$nightly_body"; fails=$((fails + 1)) ;;
esac

[ "$fails" -eq 0 ] || { printf '%d check(s) failed\n' "$fails" >&2; exit 1; }
printf 'all cross-shell cases byte-identical\n'
10 changes: 5 additions & 5 deletions tests/test_release_assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,16 @@ def test_valid_windows_arm64_archive(self) -> None:
bundle.writestr("wally-windows-arm64/bin/wally.exe", b"binary")
VERIFY.verify(archive, self.sidecar(archive))

def test_valid_dev_bottle_shares_the_platform_root(self) -> None:
# The -dev bottle only adds -dev to the filename; its staged root stays
# wally-<platform>. This is the exact asset name the release verify
# rejected before the channel group was added.
def test_rejects_dev_bottle_name(self) -> None:
# The -dev suffix is no longer published; the verifier must reject it
# so a stale dev artifact cannot accidentally land in a production release.
with tempfile.TemporaryDirectory() as temporary:
archive = pathlib.Path(temporary) / "wally-0.5.3-macos-arm64-dev.tar.gz"
with tarfile.open(archive, "w:gz") as bundle:
self.add_tar_file(bundle, "wally-macos-arm64/README.md", b"readme", 0o644)
self.add_tar_file(bundle, "wally-macos-arm64/bin/wally", b"binary", 0o755)
VERIFY.verify(archive, self.sidecar(archive))
with self.assertRaisesRegex(VERIFY.VerificationError, "unsupported release asset name"):
VERIFY.verify(archive, self.sidecar(archive))

def test_valid_windows_archive_with_backslash_members(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
Expand Down
Loading