From e65267fe219d649eb0235eee619690c422757dc8 Mon Sep 17 00:00:00 2001 From: linkong Date: Fri, 22 May 2026 21:37:38 +0800 Subject: [PATCH] release: bump version to 0.65.2 --- VERSION | 2 +- aiprovider/Dockerfile | 4 ++++ docker-compose.local-model.yml | 1 + docker-compose.simple.yml | 1 + docker-compose.yml | 1 + docs/CHANGELOG.md | 16 +++++++++++++ docs/version-history.md | 3 ++- frontend/package.json | 2 +- planet.cmd | 18 ++++++++++++++ planet.sh | 43 +++++++++++++++++++++++----------- pyproject.toml | 2 +- scripts/bootstrap-dev.sh | 2 +- uv.lock | 2 +- 13 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 planet.cmd diff --git a/VERSION b/VERSION index 522ab7d4..8fbb20c5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.65.1 +0.65.2 diff --git a/aiprovider/Dockerfile b/aiprovider/Dockerfile index 32c1e95a..91ea40df 100644 --- a/aiprovider/Dockerfile +++ b/aiprovider/Dockerfile @@ -2,10 +2,14 @@ ARG PYTHON_IMAGE=python:3.14-slim ARG UV_IMAGE=ghcr.io/astral-sh/uv:latest +ARG AI_PROVIDER_BUILD_FINGERPRINT=unknown FROM ${UV_IMAGE} AS uv FROM ${PYTHON_IMAGE} +ARG AI_PROVIDER_BUILD_FINGERPRINT +LABEL planet.aiprovider.build-fingerprint="${AI_PROVIDER_BUILD_FINGERPRINT}" + COPY --from=uv /uv /uvx /bin/ WORKDIR /app diff --git a/docker-compose.local-model.yml b/docker-compose.local-model.yml index 2e71368a..50f2c14b 100644 --- a/docker-compose.local-model.yml +++ b/docker-compose.local-model.yml @@ -22,6 +22,7 @@ services: args: PYTHON_IMAGE: ${PYTHON_IMAGE:-python:3.14-slim} UV_IMAGE: ${UV_IMAGE:-ghcr.io/astral-sh/uv:latest} + AI_PROVIDER_BUILD_FINGERPRINT: ${AI_PROVIDER_BUILD_FINGERPRINT:-unknown} secrets: - planet_uv_config container_name: planet_aiprovider diff --git a/docker-compose.simple.yml b/docker-compose.simple.yml index 262c3a94..cd2e1a97 100644 --- a/docker-compose.simple.yml +++ b/docker-compose.simple.yml @@ -9,6 +9,7 @@ services: args: PYTHON_IMAGE: ${PYTHON_IMAGE:-python:3.14-slim} UV_IMAGE: ${UV_IMAGE:-ghcr.io/astral-sh/uv:latest} + AI_PROVIDER_BUILD_FINGERPRINT: ${AI_PROVIDER_BUILD_FINGERPRINT:-unknown} secrets: - planet_uv_config env_file: diff --git a/docker-compose.yml b/docker-compose.yml index 2bd8ebb8..f05a6415 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,6 +9,7 @@ services: args: PYTHON_IMAGE: ${PYTHON_IMAGE:-python:3.14-slim} UV_IMAGE: ${UV_IMAGE:-ghcr.io/astral-sh/uv:latest} + AI_PROVIDER_BUILD_FINGERPRINT: ${AI_PROVIDER_BUILD_FINGERPRINT:-unknown} secrets: - planet_uv_config env_file: diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index c1a9d290..a4f4ee5c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -8,6 +8,22 @@ This project follows the repository versioning rule: - `improvement` -> `+0.0.1`(bugfix + 小功能混合) - `bugfix` -> `+0.0.1` +## [0.65.2] — 2026-05-22 + +Released: 2026-05-22 + +### Highlights +- Stabilize AI Provider rebuild detection so unchanged source no longer rebuilds just because file timestamps or local cache state changed. +- Keep `uv.lock` on the official registry while still allowing local and Docker builds to use the user's `uv.toml`. +- Prevent local startup and bootstrap commands from rewriting `uv.lock` when a user-level mirror is configured. + +### Added / Fixed / Improved +- AI Provider fingerprints now use content hashes, base image inputs, dependency metadata, and an image label instead of file mtimes. +- `planet.sh` and `scripts/bootstrap-dev.sh` now use `uv sync --frozen`, and backend startup uses `uv run --frozen`. +- Docker Compose passes the AI Provider fingerprint into the image build so future starts can inspect the image label directly. + +--- + ## [0.65.1] — 2026-05-22 Released: 2026-05-22 diff --git a/docs/version-history.md b/docs/version-history.md index befecd27..02b06e5d 100644 --- a/docs/version-history.md +++ b/docs/version-history.md @@ -16,12 +16,13 @@ ## Current Version - `main` 当前主线历史推导到:`0.16.5` -- `dev` 当前开发分支历史推导到:`0.65.1` +- `dev` 当前开发分支历史推导到:`0.65.2` ## Timeline | Version | Type | Branch | Commit | Summary | | --- | --- | --- | --- | --- | +| `0.65.2` | bugfix | `dev` | `pending` | AI Provider 镜像重建判定改为内容 fingerprint 与镜像 label,启动链路改用 frozen uv,避免用户级镜像源污染 `uv.lock`,并加入 Windows 一键启动脚本 | | `0.65.1` | bugfix | `dev` | `pending` | 统一 `planet.sh` 与 Compose 的 AI Provider 镜像名,并让本地和 Docker build 通过用户级 `uv.toml` 共享 uv 源配置,避免镜像源污染 `uv.lock` | | `0.65.0` | feature | `dev` | `pending` | Admin Next 数据源触发入口收敛为“触发全部/触发已选 N”,队列改为右上角浮层按钮,并强化 `planet.sh destroy` 的 OOBE 数据清理 | | `0.64.0` | feature | `dev` | `pending` | Earth 新增后端状态驱动 OOBE 与 About 配置,Admin Next 数据源页新增采集队列,补齐深色主题滑块和用户/技术文档 | diff --git a/frontend/package.json b/frontend/package.json index d1327f7f..0202b245 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "planet-frontend", - "version": "0.65.1", + "version": "0.65.2", "private": true, "packageManager": "bun@1", "dependencies": { diff --git a/planet.cmd b/planet.cmd new file mode 100644 index 00000000..8e666c42 --- /dev/null +++ b/planet.cmd @@ -0,0 +1,18 @@ +@echo off +setlocal EnableExtensions + +net session >nul 2>&1 +if not "%errorlevel%"=="0" ( + powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "$script = '%~f0'; $arg = '-NoExit -NoProfile -ExecutionPolicy Bypass -Command ""& { & ''' + $script + ''' --elevated }""'; if (Get-Command wt.exe -ErrorAction SilentlyContinue) { Start-Process wt.exe -Verb RunAs -ArgumentList @('powershell.exe', $arg) } else { Start-Process powershell.exe -Verb RunAs -ArgumentList $arg }" + exit /b +) + +if /i "%~1"=="--elevated" shift + +echo Starting Planet in WSL as Administrator... +echo This window will stay inside WSL after startup. Close it manually when you are done. +echo. + +wsl.exe -d Ubuntu --cd /home/linkong/planet -- zsh -lic "./planet.sh restart --allow-lan; planet_exit=\$?; echo; if [ \$planet_exit -eq 0 ]; then echo 'Planet restart finished successfully.'; powershell.exe -NoProfile -Command 'Start-Process "http://localhost:3000/earth"'; else echo \"Planet restart failed with exit code \$planet_exit.\"; fi; echo; echo 'Staying in WSL. Close this terminal manually when you are done.'; exec zsh -l" + +exit /b %errorlevel% diff --git a/planet.sh b/planet.sh index 6f7ead51..c06a48be 100755 --- a/planet.sh +++ b/planet.sh @@ -1117,6 +1117,9 @@ compute_ai_provider_build_fingerprint() { ( cd "$SCRIPT_DIR" || exit 1 { + printf "PYTHON_IMAGE=%s\n" "${PYTHON_IMAGE:-python:3.14-slim}" + printf "UV_IMAGE=%s\n" "${UV_IMAGE:-ghcr.io/astral-sh/uv:latest}" + sha256sum aiprovider/Dockerfile pyproject.toml uv.lock 2>/dev/null find aiprovider \ -type f \ ! -path '*/__pycache__/*' \ @@ -1125,13 +1128,8 @@ compute_ai_provider_build_fingerprint() { ! -name '*.pyc' \ ! -name '*.pyo' \ | LC_ALL=C sort \ - | xargs -r stat --format="%Y %s %n" 2>/dev/null - sha256sum docker-compose.yml docker-compose.simple.yml 2>/dev/null + | xargs -r sha256sum 2>/dev/null python3 "$SCRIPT_DIR/scripts/compute_aiprovider_dependency_fingerprint.py" 2>/dev/null - if [ -n "${PLANET_UV_CONFIG_FILE:-}" ] && [ -f "$PLANET_UV_CONFIG_FILE" ]; then - printf "uv-config " - sha256sum "$PLANET_UV_CONFIG_FILE" | awk '{print $1}' - fi } ) | sha256sum | awk '{print $1}' } @@ -1151,6 +1149,12 @@ ai_provider_image_exists() { docker image inspect "$AI_PROVIDER_IMAGE_NAME" >/dev/null 2>&1 } +read_ai_provider_image_fingerprint() { + docker image inspect \ + --format '{{ index .Config.Labels "planet.aiprovider.build-fingerprint" }}' \ + "$AI_PROVIDER_IMAGE_NAME" 2>/dev/null || true +} + list_ai_provider_containers() { docker ps -aq --filter "name=planet_aiprovider" 2>/dev/null || true } @@ -1217,12 +1221,23 @@ ensure_ai_provider_image_current() { current_fingerprint="$(compute_ai_provider_build_fingerprint)" previous_fingerprint="$(read_ai_provider_build_stamp || true)" - if ai_provider_image_exists && [ -n "$previous_fingerprint" ] && [ "$current_fingerprint" = "$previous_fingerprint" ]; then - AI_PROVIDER_RECREATE_REQUIRED=0 - return 0 + if ai_provider_image_exists; then + local image_fingerprint + image_fingerprint="$(read_ai_provider_image_fingerprint)" + if [ -n "$image_fingerprint" ] && [ "$current_fingerprint" = "$image_fingerprint" ]; then + write_ai_provider_build_stamp "$current_fingerprint" + AI_PROVIDER_RECREATE_REQUIRED=0 + return 0 + fi + if [ -z "$image_fingerprint" ] && [ -n "$previous_fingerprint" ] && [ "$current_fingerprint" = "$previous_fingerprint" ]; then + AI_PROVIDER_RECREATE_REQUIRED=0 + return 0 + fi fi set_wait_detail "检测到 AI Provider 代码或配置变化,重建镜像" + AI_PROVIDER_BUILD_FINGERPRINT="$current_fingerprint" + export AI_PROVIDER_BUILD_FINGERPRINT if ! compose_supports_build; then log_error "当前 docker compose 不支持 build,请检查 Docker / Compose 环境" @@ -1349,8 +1364,8 @@ ensure_uv_backend_deps() { "$DEPENDENCY_INSTALL_MAX_RETRIES" \ "$DEPENDENCY_INSTALL_RETRY_INTERVAL" \ "uv 环境初始化失败,已重试 ${DEPENDENCY_INSTALL_MAX_RETRIES} 次" \ - "uv sync" \ - run_command_quiet_unless_verbose "$log_file" uv sync --group dev; then + "uv sync --frozen" \ + run_command_quiet_unless_verbose "$log_file" uv sync --frozen --group dev; then tail -20 "$log_file" 2>/dev/null || true exit 1 fi @@ -1403,8 +1418,8 @@ sync_python_deps() { "$DEPENDENCY_INSTALL_MAX_RETRIES" \ "$DEPENDENCY_INSTALL_RETRY_INTERVAL" \ "uv 环境初始化失败,已重试 ${DEPENDENCY_INSTALL_MAX_RETRIES} 次" \ - "uv sync" \ - run_command_quiet_unless_verbose "$log_file" uv sync --group dev; then + "uv sync --frozen" \ + run_command_quiet_unless_verbose "$log_file" uv sync --frozen --group dev; then tail -20 "$log_file" 2>/dev/null || true exit 1 fi @@ -1959,7 +1974,7 @@ start_backend_with_retry() { fi cd "$SCRIPT_DIR/backend" : > "$BACKEND_LOG_FILE" - PYTHONPATH="$SCRIPT_DIR/backend" nohup uv run --project "$SCRIPT_DIR" python -m uvicorn app.main:app --host "$backend_bind_host" --port "$backend_port" --reload > "$BACKEND_LOG_FILE" 2>&1 & + PYTHONPATH="$SCRIPT_DIR/backend" nohup uv run --frozen --project "$SCRIPT_DIR" python -m uvicorn app.main:app --host "$backend_bind_host" --port "$backend_port" --reload > "$BACKEND_LOG_FILE" 2>&1 & BACKEND_PID=$! write_pid_file "$BACKEND_PID_FILE" "$BACKEND_PID" if [ "$VERBOSE" -eq 1 ]; then diff --git a/pyproject.toml b/pyproject.toml index aa4fd5e0..7178d66b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "planet" -version = "0.65.1" +version = "0.65.2" description = "智能星球计划 - 态势感知系统" requires-python = ">=3.14" dependencies = [ diff --git a/scripts/bootstrap-dev.sh b/scripts/bootstrap-dev.sh index d0fabe68..42577154 100755 --- a/scripts/bootstrap-dev.sh +++ b/scripts/bootstrap-dev.sh @@ -64,7 +64,7 @@ sync_python_env() { echo -e "${BLUE}同步 Python 依赖...${NC}" cd "$ROOT_DIR" uv python install 3.14 - uv sync --group dev + uv sync --frozen --group dev } sync_frontend_env() { diff --git a/uv.lock b/uv.lock index f9273057..15538298 100644 --- a/uv.lock +++ b/uv.lock @@ -757,7 +757,7 @@ wheels = [ [[package]] name = "planet" -version = "0.65.1" +version = "0.65.2" source = { virtual = "." } dependencies = [ { name = "aiofiles" },