mirror of
https://github.com/Skyvern-AI/skyvern.git
synced 2026-07-09 16:09:13 +00:00
feat: add curl-based Skyvern server installer (#5804)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3212ca8d7f
commit
0842a82a38
2 changed files with 231 additions and 0 deletions
168
install.sh
Executable file
168
install.sh
Executable file
|
|
@ -0,0 +1,168 @@
|
|||
#!/bin/sh
|
||||
# Skyvern installer. Run `install.sh --help` for usage.
|
||||
|
||||
set -eu
|
||||
|
||||
SKYVERN_RUN_INIT="${SKYVERN_RUN_INIT:-}"
|
||||
SKYVERN_VERSION="${SKYVERN_VERSION:-}"
|
||||
SKYVERN_VARIANT="${SKYVERN_VARIANT:-server}"
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--no-init) SKYVERN_RUN_INIT=0; shift ;;
|
||||
--run-init|--run-setup) SKYVERN_RUN_INIT=1; shift ;;
|
||||
--version) SKYVERN_VERSION="${2:?--version requires a value}"; shift 2 ;;
|
||||
--version=*) SKYVERN_VERSION="${1#--version=}"; shift ;;
|
||||
--variant) SKYVERN_VARIANT="${2:?--variant requires a value}"; shift 2 ;;
|
||||
--variant=*) SKYVERN_VARIANT="${1#--variant=}"; shift ;;
|
||||
--help|-h)
|
||||
# Heredoc rather than self-parsing $0: when piped, $0 is the
|
||||
# shell name, not a real file path.
|
||||
cat <<'EOF'
|
||||
Skyvern installer.
|
||||
|
||||
Usage:
|
||||
curl -LsSf https://install.skyvern.com | sh
|
||||
curl -LsSf https://install.skyvern.com | sh -s -- --no-init
|
||||
curl -LsSf https://install.skyvern.com | sh -s -- --run-setup
|
||||
curl -LsSf https://install.skyvern.com | sh -s -- --version 1.0.35
|
||||
curl -LsSf https://install.skyvern.com | sh -s -- --variant server
|
||||
|
||||
Flags:
|
||||
--variant V install variant (default: server). This curl installer is
|
||||
intentionally for the self-hosted CLI/server path. For SDKs,
|
||||
use pip inside your project: 'skyvern' or 'skyvern[local]'.
|
||||
--run-setup run the setup wizard after install (requires a terminal).
|
||||
--run-init alias for --run-setup.
|
||||
--no-init skip the post-install setup wizard.
|
||||
--version X pin a specific PyPI version (e.g., 1.0.35).
|
||||
|
||||
Environment overrides:
|
||||
SKYVERN_VARIANT=V same as --variant
|
||||
SKYVERN_RUN_INIT=0 same as --no-init
|
||||
SKYVERN_RUN_INIT=1 same as --run-setup
|
||||
SKYVERN_VERSION=X same as --version
|
||||
|
||||
What this does:
|
||||
1. Bootstraps 'uv' if missing — uv manages Python so the host
|
||||
doesn't need one preinstalled.
|
||||
2. Installs the self-hosted PyPI package as an isolated tool
|
||||
('skyvern' on PATH).
|
||||
3. Prints the next setup command. Use --run-setup to run it immediately.
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
printf 'unknown option: %s (try --help)\n' "$1" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$(uname -s)" in
|
||||
Darwin|Linux) ;;
|
||||
*)
|
||||
printf 'unsupported OS: %s\n' "$(uname -s)" >&2
|
||||
printf "For Windows, use WSL or 'pip install skyvern' from a Python environment.\n" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
uv_was_freshly_installed=0
|
||||
if ! command -v uv >/dev/null 2>&1; then
|
||||
uv_was_freshly_installed=1
|
||||
printf 'installing uv (one-time, into ~/.local/bin)...\n'
|
||||
# Download then execute (not `curl ... | sh`): POSIX /bin/sh has no
|
||||
# pipefail, so curl failures would otherwise be swallowed silently.
|
||||
UV_INSTALLER="$(mktemp -t skyvern-uv-installer.XXXXXX)"
|
||||
trap 'rm -f "$UV_INSTALLER"' EXIT
|
||||
if ! curl -LsSf https://astral.sh/uv/install.sh -o "$UV_INSTALLER"; then
|
||||
printf 'ERROR: failed to download uv installer from astral.sh.\n' >&2
|
||||
printf ' Check your network/proxy. See https://docs.astral.sh/uv/getting-started/installation/\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
sh "$UV_INSTALLER"
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
if ! command -v uv >/dev/null 2>&1; then
|
||||
printf 'ERROR: uv installer ran but uv is not on PATH.\n' >&2
|
||||
printf ' See https://docs.astral.sh/uv/getting-started/installation/\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Variant policy: the curl installer is for isolated CLI/server installs.
|
||||
# SDK installs belong in the user's project environment, not a uv tool venv.
|
||||
case "$SKYVERN_VARIANT" in
|
||||
server)
|
||||
PKG_SPEC="skyvern[server]"
|
||||
PYTHON_SPEC=">=3.11,<3.14"
|
||||
DEFAULT_RUN_INIT=0
|
||||
SUCCESS_HINT="Next: skyvern quickstart"
|
||||
;;
|
||||
sdk|cloud|base)
|
||||
printf "ERROR: --variant '%s' is not installed by this curl installer.\n" "$SKYVERN_VARIANT" >&2
|
||||
printf " Use 'pip install skyvern' inside your Python project instead.\n" >&2
|
||||
exit 2
|
||||
;;
|
||||
local|embedded)
|
||||
printf "ERROR: --variant '%s' is not installed by this curl installer.\n" "$SKYVERN_VARIANT" >&2
|
||||
printf " Use 'pip install \"skyvern[local]\"' inside your Python project instead.\n" >&2
|
||||
exit 2
|
||||
;;
|
||||
mcp|all)
|
||||
printf "ERROR: --variant '%s' is not available from this installer.\n" "$SKYVERN_VARIANT" >&2
|
||||
printf " Use --variant server for the self-hosted CLI/server tool.\n" >&2
|
||||
exit 2
|
||||
;;
|
||||
*)
|
||||
printf "ERROR: unknown variant '%s'. Valid: server (default).\n" "$SKYVERN_VARIANT" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -n "$SKYVERN_RUN_INIT" ] || SKYVERN_RUN_INIT="$DEFAULT_RUN_INIT"
|
||||
case "$SKYVERN_RUN_INIT" in
|
||||
0|1) ;;
|
||||
*)
|
||||
printf "ERROR: SKYVERN_RUN_INIT must be 0 or 1.\n" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
PKG_SPEC_INSTALL="$PKG_SPEC"
|
||||
if [ -n "$SKYVERN_VERSION" ]; then
|
||||
PKG_SPEC_INSTALL="${PKG_SPEC}==${SKYVERN_VERSION}"
|
||||
fi
|
||||
|
||||
printf 'installing %s via uv tool install...\n' "$PKG_SPEC_INSTALL"
|
||||
# Pin Python to the variant's supported range. Without this, uv may pick a
|
||||
# host Python outside the range and env-marker deps (e.g., playwright with
|
||||
# `<'3.14'`) silently drop from the resolution. Bump intentionally when
|
||||
# upstream `requires-python` shifts — does NOT auto-track.
|
||||
uv tool install --python "$PYTHON_SPEC" --force "$PKG_SPEC_INSTALL"
|
||||
|
||||
SETUP_COMMAND="skyvern quickstart"
|
||||
if skyvern quickstart --help 2>/dev/null | grep -q -- "--install-type"; then
|
||||
SETUP_COMMAND="skyvern quickstart --install-type server"
|
||||
fi
|
||||
SUCCESS_HINT="Next: $SETUP_COMMAND"
|
||||
|
||||
if [ "$SKYVERN_RUN_INIT" = "1" ]; then
|
||||
if [ ! -t 0 ]; then
|
||||
printf "\nWARN: not running setup because stdin is not an interactive terminal.\n" >&2
|
||||
printf " Run '%s' from your shell when ready.\n" "$SETUP_COMMAND" >&2
|
||||
else
|
||||
printf "\nrunning '%s'...\n" "$SETUP_COMMAND"
|
||||
if ! sh -c "$SETUP_COMMAND"; then
|
||||
printf "\nWARN: '%s' did not complete. The CLI is installed;\n" "$SETUP_COMMAND" >&2
|
||||
printf " re-run '%s' once the issue is sorted.\n" "$SETUP_COMMAND" >&2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
printf '\nSkyvern installed. %s\n' "$SUCCESS_HINT"
|
||||
|
||||
if [ "$uv_was_freshly_installed" = "1" ]; then
|
||||
printf "\nNote: uv was just installed in ~/.local/bin. Run 'source ~/.local/bin/env'\n"
|
||||
printf " or open a new terminal to use 'skyvern' in this shell.\n"
|
||||
fi
|
||||
63
scripts/test-install.sh
Executable file
63
scripts/test-install.sh
Executable file
|
|
@ -0,0 +1,63 @@
|
|||
#!/bin/sh
|
||||
# Smoke-test install.sh against fresh Docker base images.
|
||||
#
|
||||
# Usage:
|
||||
# scripts/test-install.sh # default matrix, --no-init
|
||||
# scripts/test-install.sh --with-init # run post-install setup when possible
|
||||
# IMAGES="ubuntu:22.04" scripts/test-install.sh # subset
|
||||
#
|
||||
# Requires Docker on the host.
|
||||
|
||||
set -eu
|
||||
|
||||
WITH_INIT=0
|
||||
[ "${1:-}" = "--with-init" ] && WITH_INIT=1
|
||||
|
||||
DEFAULT_IMAGES="ubuntu:22.04 ubuntu:24.04 debian:12-slim python:3.11-slim python:3.13-slim"
|
||||
IMAGES="${IMAGES:-$DEFAULT_IMAGES}"
|
||||
|
||||
# This installer is intentionally server-only; SDK/local installs belong in a
|
||||
# project environment via pip, not a uv tool venv.
|
||||
DEFAULT_VARIANTS="server"
|
||||
VARIANTS="${VARIANTS:-$DEFAULT_VARIANTS}"
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
INSTALL_SH="$REPO_ROOT/install.sh"
|
||||
[ -f "$INSTALL_SH" ] || { printf 'install.sh not found at %s\n' "$INSTALL_SH" >&2; exit 1; }
|
||||
|
||||
init_flag="--no-init"
|
||||
[ "$WITH_INIT" = "1" ] && init_flag=""
|
||||
|
||||
failed=""
|
||||
for variant in $VARIANTS; do
|
||||
for img in $IMAGES; do
|
||||
printf '\n=== %s / variant=%s ===\n' "$img" "$variant"
|
||||
if docker run --rm \
|
||||
-v "$INSTALL_SH:/tmp/install.sh:ro" \
|
||||
-e "VARIANT=$variant" \
|
||||
-e "INIT_FLAG=$init_flag" \
|
||||
"$img" sh -c '
|
||||
set -e
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq >/dev/null
|
||||
apt-get install -qq -y curl ca-certificates >/dev/null
|
||||
sh /tmp/install.sh --variant "$VARIANT" $INIT_FLAG
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
# --help exit 0 proves the package imports cleanly (the CLI
|
||||
# has no --version flag).
|
||||
skyvern --help >/dev/null
|
||||
'; then
|
||||
printf 'PASS: %s / variant=%s\n' "$img" "$variant"
|
||||
else
|
||||
printf 'FAIL: %s / variant=%s\n' "$img" "$variant"
|
||||
failed="$failed $img(variant=$variant)"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [ -n "$failed" ]; then
|
||||
printf '\nFAILED:%s\n' "$failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '\nAll images passed.\n'
|
||||
Loading…
Add table
Add a link
Reference in a new issue