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
2 changes: 2 additions & 0 deletions install_zh.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Flocks 中国用户一键安装脚本。
然后转交 scripts/install_zh.sh 继续安装。默认会在当前工作目录下创建 "flocks" 子目录。

默认会为 install_zh 注入国内软件源与 uv 安装镜像。
uv 备用源: https://uv.agentsmirror.com/install-cn.sh

远程使用:
curl -fsSL $RAW_INSTALL_ZH_SH_URL | bash
Expand Down Expand Up @@ -130,6 +131,7 @@ resolve_project_dir() {
configure_cn_environment() {
export FLOCKS_INSTALL_LANGUAGE="${FLOCKS_INSTALL_LANGUAGE:-zh-CN}"
export FLOCKS_UV_INSTALL_SH_URL="${FLOCKS_UV_INSTALL_SH_URL:-https://astral.org.cn/uv/install.sh}"
export FLOCKS_UV_INSTALL_SH_FALLBACK_URL="${FLOCKS_UV_INSTALL_SH_FALLBACK_URL:-https://uv.agentsmirror.com/install-cn.sh}"
export FLOCKS_UV_INSTALL_PS1_URL="${FLOCKS_UV_INSTALL_PS1_URL:-https://astral.org.cn/uv/install.ps1}"
export PUPPETEER_CHROME_DOWNLOAD_BASE_URL="${PUPPETEER_CHROME_DOWNLOAD_BASE_URL:-https://cdn.npmmirror.com/binaries/chrome-for-testing}"
}
Expand Down
28 changes: 27 additions & 1 deletion scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ PATH_REFRESH_HINT_REQUIRED=0
INSTALL_LANGUAGE="${FLOCKS_INSTALL_LANGUAGE:-en}"
UV_DEFAULT_INDEX="${FLOCKS_UV_DEFAULT_INDEX:-https://pypi.org/simple}"
UV_INSTALL_SH_URL="${FLOCKS_UV_INSTALL_SH_URL:-https://astral.sh/uv/install.sh}"
UV_INSTALL_SH_FALLBACK_URL="${FLOCKS_UV_INSTALL_SH_FALLBACK_URL:-}"
NPM_REGISTRY="${FLOCKS_NPM_REGISTRY:-https://registry.npmjs.org/}"
NODEJS_MANUAL_DOWNLOAD_URL="${FLOCKS_NODEJS_MANUAL_DOWNLOAD_URL:-https://nodejs.org/en/download}"
NVM_INSTALL_SCRIPT_URL="${FLOCKS_NVM_INSTALL_SCRIPT_URL:-https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh}"
Expand Down Expand Up @@ -59,6 +60,9 @@ select_install_sources() {
info "使用 PyPI 源: $UV_DEFAULT_INDEX"
info "使用 npm 源: $NPM_REGISTRY"
info "使用 uv 安装脚本: $UV_INSTALL_SH_URL"
if [[ -n "$UV_INSTALL_SH_FALLBACK_URL" ]]; then
info "使用 uv 备用安装脚本: $UV_INSTALL_SH_FALLBACK_URL"
fi
else
info "Using PyPI index: $UV_DEFAULT_INDEX"
info "Using npm registry: $NPM_REGISTRY"
Expand Down Expand Up @@ -517,6 +521,7 @@ ensure_npm_global_prefix_writable() {
}

install_uv() {
local primary_install_failed=0
if has_cmd uv; then
return
fi
Expand All @@ -528,9 +533,30 @@ install_uv() {
has_cmd curl || fail "curl is required to install uv automatically."
info "uv was not found. Installing it automatically..."
fi
curl -LsSf "$UV_INSTALL_SH_URL" | sh
if ! curl -LsSf "$UV_INSTALL_SH_URL" | sh; then
primary_install_failed=1
fi
refresh_path
ensure_path_persisted "$HOME/.local/bin"

if has_cmd uv; then
return
fi

if is_zh_install && [[ -n "$UV_INSTALL_SH_FALLBACK_URL" ]]; then
if [[ "$primary_install_failed" -eq 1 ]]; then
info "默认 uv 安装脚本失败,正在尝试中国大陆备用源..."
else
info "默认 uv 安装脚本执行后仍未检测到 uv,正在尝试中国大陆备用源..."
fi

if ! curl -LsSf "$UV_INSTALL_SH_FALLBACK_URL" | sh; then
fail "默认 uv 安装脚本和中国大陆备用源都执行失败。请检查网络连通性或 PATH 后重试。"
fi
refresh_path
ensure_path_persisted "$HOME/.local/bin"
fi

if is_zh_install; then
has_cmd uv || fail "uv 安装已完成,但当前仍无法找到 uv。请检查 PATH 后重试。"
else
Expand Down
2 changes: 2 additions & 0 deletions scripts/install_zh.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Flocks 中国用户源码安装脚本。
PyPI: https://mirrors.aliyun.com/pypi/simple
npm : https://registry.npmmirror.com/
uv : https://astral.org.cn/uv/install.sh
uv 备用源: https://uv.agentsmirror.com/install-cn.sh

一键安装入口:
curl -fsSL $RAW_INSTALL_ZH_SH_URL | bash
Expand All @@ -38,6 +39,7 @@ configure_cn_environment() {
export FLOCKS_RAW_INSTALL_PS1_URL="${FLOCKS_RAW_INSTALL_PS1_URL:-$RAW_INSTALL_ZH_PS1_URL}"
export FLOCKS_UV_DEFAULT_INDEX="${FLOCKS_UV_DEFAULT_INDEX:-https://mirrors.aliyun.com/pypi/simple}"
export FLOCKS_UV_INSTALL_SH_URL="${FLOCKS_UV_INSTALL_SH_URL:-https://astral.org.cn/uv/install.sh}"
export FLOCKS_UV_INSTALL_SH_FALLBACK_URL="${FLOCKS_UV_INSTALL_SH_FALLBACK_URL:-https://uv.agentsmirror.com/install-cn.sh}"
export FLOCKS_UV_INSTALL_PS1_URL="${FLOCKS_UV_INSTALL_PS1_URL:-https://astral.org.cn/uv/install.ps1}"
export FLOCKS_NPM_REGISTRY="${FLOCKS_NPM_REGISTRY:-https://registry.npmmirror.com/}"
export PUPPETEER_CHROME_DOWNLOAD_BASE_URL="${PUPPETEER_CHROME_DOWNLOAD_BASE_URL:-https://cdn.npmmirror.com/binaries/chrome-for-testing}"
Expand Down
99 changes: 99 additions & 0 deletions tests/scripts/test_install_script_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ def test_install_zh_bash_bootstrap_uses_gitee_archive_and_delegates_to_zh_worksp
assert 'zh-CN' in script
assert 'FLOCKS_UV_INSTALL_SH_URL' in script
assert 'https://astral.org.cn/uv/install.sh' in script
assert 'FLOCKS_UV_INSTALL_SH_FALLBACK_URL' in script
assert 'https://uv.agentsmirror.com/install-cn.sh' in script
assert 'FLOCKS_UV_INSTALL_PS1_URL' in script
assert 'https://astral.org.cn/uv/install.ps1' in script
assert 'PUPPETEER_CHROME_DOWNLOAD_BASE_URL' in script
Expand Down Expand Up @@ -110,10 +112,13 @@ def test_main_bash_installer_uses_configured_default_sources_without_probing() -
assert 'FLOCKS_UV_DEFAULT_INDEX' in script
assert 'FLOCKS_UV_INSTALL_SH_URL' in script
assert 'https://astral.sh/uv/install.sh' in script
assert 'FLOCKS_UV_INSTALL_SH_FALLBACK_URL' in script
assert 'FLOCKS_NPM_REGISTRY' in script
assert 'Using PyPI index: $UV_DEFAULT_INDEX' in script
assert 'Using npm registry: $NPM_REGISTRY' in script
assert 'Using uv install script: $UV_INSTALL_SH_URL' in script
assert 'Using uv fallback script' not in script
assert '使用 uv 备用安装脚本: $UV_INSTALL_SH_FALLBACK_URL' in script
assert 'pick_fastest_url' not in script
assert 'Probing PyPI and npm registries to choose the faster source' not in script
assert 'npm_config_registry="$NPM_REGISTRY" npm install' in script
Expand All @@ -126,6 +131,7 @@ def test_main_bash_installer_uses_configured_default_sources_without_probing() -
assert "load_nvm()" in script
assert 'curl -o- "$NVM_INSTALL_SCRIPT_URL" | bash' in script
assert 'curl -LsSf "$UV_INSTALL_SH_URL" | sh' in script
assert 'curl -LsSf "$UV_INSTALL_SH_FALLBACK_URL" | sh' in script
assert 'nvm install "$MIN_NODE_MAJOR"' in script
assert 'nvm use "$MIN_NODE_MAJOR" >/dev/null' in script
assert "Homebrew was not found. Trying to install nvm..." in script
Expand Down Expand Up @@ -354,6 +360,99 @@ def test_main_bash_installer_checks_node_modules_dir_before_accepting_global_pre
assert result.returncode == 0, output


def test_main_bash_installer_uses_cn_uv_fallback_when_primary_script_fails() -> None:
script = (SCRIPT_DIR / "install.sh").read_text(encoding="utf-8")
script_without_main = re.sub(r'\nmain "\$@"\s*$', "\n", script)
test_script = script_without_main + textwrap.dedent(
r"""

export HOME="$(mktemp -d)"
export FLOCKS_INSTALL_LANGUAGE="zh-CN"
export FLOCKS_UV_INSTALL_SH_URL="https://primary.example/install.sh"
export FLOCKS_UV_INSTALL_SH_FALLBACK_URL="https://uv.agentsmirror.com/install-cn.sh"
export TEST_LOG="$HOME/install-uv.log"
INSTALL_LANGUAGE="$FLOCKS_INSTALL_LANGUAGE"
UV_INSTALL_SH_URL="$FLOCKS_UV_INSTALL_SH_URL"
UV_INSTALL_SH_FALLBACK_URL="$FLOCKS_UV_INSTALL_SH_FALLBACK_URL"

has_cmd() {
case "$1" in
curl)
return 0
;;
uv)
[[ -f "$HOME/uv-installed" ]]
return $?
;;
*)
command -v "$1" >/dev/null 2>&1
;;
esac
}

info() {
printf '%s\n' "$1" >> "$TEST_LOG"
}

fail() {
printf 'FAIL:%s\n' "$1" >&2
exit 1
}

refresh_path() {
:
}

ensure_path_persisted() {
:
}

curl() {
printf '%s\n' "$*" >> "$HOME/curl-commands.log"
if [[ "$*" == *"primary.example"* ]]; then
return 22
fi

cat <<'EOF'
touch "$HOME/uv-installed"
EOF
}

install_uv

curl_commands="$(<"$HOME/curl-commands.log")"
install_log="$(<"$TEST_LOG")"

[[ -f "$HOME/uv-installed" ]] || {
printf 'uv was not installed by fallback script\n' >&2
exit 1
}
[[ "$curl_commands" == *"https://primary.example/install.sh"* ]] || {
printf 'primary uv script was not attempted: %s\n' "$curl_commands" >&2
exit 1
}
[[ "$curl_commands" == *"https://uv.agentsmirror.com/install-cn.sh"* ]] || {
printf 'fallback uv script was not attempted: %s\n' "$curl_commands" >&2
exit 1
}
[[ "$install_log" == *"默认 uv 安装脚本失败,正在尝试中国大陆备用源"* ]] || {
printf 'fallback log missing: %s\n' "$install_log" >&2
exit 1
}
"""
)

result = subprocess.run(
["bash", "-c", test_script],
check=False,
capture_output=True,
text=True,
)

output = f"{result.stdout}\n{result.stderr}"
assert result.returncode == 0, output


def test_main_powershell_installer_uses_configured_default_sources_without_probing() -> None:
script = (SCRIPT_DIR / "install.ps1").read_text(encoding="utf-8-sig")

Expand Down
Loading