Skip to content

feat: v9.0.0 重大更新 — 镜像源重构、CoolerControl集成、垃圾清理系统、磁盘直通增强、Web文档站移除#86

Merged
Mapleawaa merged 2 commits into
PVE-Tools:mainfrom
Mapleawaa:main
Jun 20, 2026
Merged

feat: v9.0.0 重大更新 — 镜像源重构、CoolerControl集成、垃圾清理系统、磁盘直通增强、Web文档站移除#86
Mapleawaa merged 2 commits into
PVE-Tools:mainfrom
Mapleawaa:main

Conversation

@Mapleawaa

@Mapleawaa Mapleawaa commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator
  • 镜像源系统重构为并行数组架构,新增智能镜像选择与通用下载函数
  • 新增 CoolerControl 风扇控制工具一键管理(安装/更新/卸载)
  • 新增完整垃圾清理系统(基础清理、备份修剪、快照修剪、孤立磁盘扫描)
  • 磁盘直通能力大幅增强(整盘发现、存储控制器直通、NVMe直通、系统盘保护)
  • 新增存储挂载向导,支持 ext4/xfs 分区一键挂载
  • 新增安全中心菜单,整合安全相关功能
  • 主菜单重组:新增「安全中心」「第三方工具」入口,移除已修复CVE模块
  • 虚拟机高级操作拆分为聚焦型子菜单
  • 移除内嵌 Web 文档站点,仓库更精简
  • VERSION 升级至 9.0.0

Summary by Sourcery

Release PVE-Tools 9.0.0 with a reworked mirror registry, new third-party cooler and security tooling, expanded disk passthrough utilities, a comprehensive garbage cleanup system, and removal of the embedded web documentation site.

Enhancements:

  • Refactor mirror configuration into a structured parallel-array registry with per-source selection and smarter update URL handling.
  • Add CoolerControl integration for managing third-party fan control tooling from within the script.
  • Significantly expand disk and controller passthrough capabilities, including safer RDM, controller/NVMe passthrough with system disk protection, and boot-assist helpers.
  • Introduce a centralized garbage cleanup system covering temp files, outdated tool backups/exports, vzdump backups, and VM/CT snapshots with interactive deletion.
  • Restructure VM advanced operations into focused submenus and improve storage location discovery and mount wizarding for ext4/xfs partitions.
  • Add a new security center with SSH hardening, fail2ban integration, and read-only risk reporting.
  • Streamline third-party tooling access into a unified menu, including Modules, CoolerControl, and Community Scripts.
  • Remove legacy Copy Fail CVE handling logic, associated menu items, and related kernel inspection helpers.
  • Refine host networking and firewall tooling with IPv6 helper flows and an expanded diagnostics toolbox.

Build:

  • Add a Node-based mirror testing utility script to validate external mirror availability and structure.

Documentation:

  • Remove the bundled VitePress-based web documentation site and related assets from the repository.

Summary by CodeRabbit

  • New Features

    • Added mirror availability testing utility for batch-validating PVE mirror server accessibility.
  • Chores

    • Version bumped to 9.0.0.
    • Removed web documentation site.
    • Updated line ending configuration for shell scripts.

- 镜像源系统重构为并行数组架构,新增智能镜像选择与通用下载函数
- 新增 CoolerControl 风扇控制工具一键管理(安装/更新/卸载)
- 新增完整垃圾清理系统(基础清理、备份修剪、快照修剪、孤立磁盘扫描)
- 磁盘直通能力大幅增强(整盘发现、存储控制器直通、NVMe直通、系统盘保护)
- 新增存储挂载向导,支持 ext4/xfs 分区一键挂载
- 新增安全中心菜单,整合安全相关功能
- 主菜单重组:新增「安全中心」「第三方工具」入口,移除已修复CVE模块
- 虚拟机高级操作拆分为聚焦型子菜单
- 移除内嵌 Web 文档站点,仓库更精简
- VERSION 升级至 9.0.0
@sourcery-ai

sourcery-ai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors mirror source handling into a parallel-array registry with smart selection, introduces shared download utilities and smarter update URL selection, significantly extends disk/NVMe/PCI passthrough tooling and adds a CoolerControl manager, garbage-cleanup system, storage mount wizard, security center menu, reorganized menus, and removes the embedded Web docs while bumping VERSION to 9.0.0.

File-Level Changes

Change Details Files
Refactor mirror source configuration into a parallel-array registry with per-source selection and smarter update URL handling.
  • Replace hardcoded MIRROR_* variables with MIRROR_NAMES/IDs and per-content URI arrays for Debian, security, PVE, Ceph, and CT templates.
  • Track selected mirror indices per content type and add selection helpers plus a summary printer to support unified or per-source mirror selection.
  • Introduce pve_tools_download_url/pve_tools_download_file and pve_tools_choose_update_urls to centralize HTTP downloads and choose between GitHub and mirror prefixes for VERSION/UPDATE/script URLs based on network region.
PVE-Tools.sh
Rework change_sources to consume the new mirror registry and generate DEB822 sources plus CT template acceleration with safer replacements.
  • Change change_sources to derive all URIs from MIRROR_* parallel arrays, with fallbacks to official upstreams when specific URIs are missing.
  • Generate Debian DEB822 sources for trixie + security, including commented deb-src stanzas and consistent Signed-By usage.
  • Rewrite Ceph and pve-no-subscription sources using mirror URIs, and update CT template URLs by normalizing known URIs before replacing only the base host, avoiding residual mirror paths.
PVE-Tools.sh
Remove the Copy Fail (CVE-2026-31431) module and simplify the kernel management menu.
  • Delete all Copy Fail–related constants, helpers, state, menus, and integration from the kernel management flow.
  • Shrink kernel_management_menu options, removing the Copy Fail submenu entry and reindexing menu items so option 6 is now reboot.
  • Ensure no dangling references to COPY_FAIL_* symbols remain in the file.
PVE-Tools.sh
Enhance disk and PCI/NVMe passthrough capabilities with safer discovery, system-disk protection, and NVMe MSI-X relocation support.
  • Introduce RDM (裸磁盘映射) single-disk attach/detach helpers that enumerate /dev/disk/by-id, filter partitions/LVM/DM devices, and allocate free scsi/sata/ide slots, with config backups and confirmations.
  • Add storage_controller_passthrough and nvme_passthrough flows that list PCI controllers (SATA/SCSI/RAID/NVMe), derive which IOMMU groups host system disks, block passthrough of controllers owning the system disk, and attach hostpci entries only to free slots with q35 pcie flags when needed.
  • Add helpers to parse PCI BDFs from udev, map block devices back to PCI controllers, identify system disks via findmnt/pvs, manage hostpci index allocation, and append QEMU args for NVMe MSI-X relocation via NVMe-specific heuristics.
  • Introduce a top-level disk/controller passthrough menu that wires together RDM, controller passthrough, NVMe passthrough, and boot helper actions under a focused submenu.
PVE-Tools.sh
Add a full garbage cleanup system for temp files, PVE-Tools backups, vzdump backups, snapshots, and orphaned disks, with interactive previews and risk gating.
  • Introduce helpers to discover PVE-Tools-generated temp and backup/export files, aggregate sizes, and interactively delete them with per-item or batch modes.
  • Add vzdump backup discovery across common roots, classify backups as old and/or orphaned (no matching VM/CT), present candidates with sizes and VMID types, and support controlled deletion behind high-risk confirmations.
  • Add snapshot scanning for VM/CT snaptime entries older than a configurable threshold, with per-snapshot deletion and separate handling for VMs and CTs.
  • Add orphan disk reconnaissance that cross-references pvesm list volumes with VM/LXC config references, reporting unmanaged volumes without providing automatic deletion, explicitly requiring manual pvesm free for safety.
  • Wrap these capabilities in a garbage_cleanup_menu under a new storage/cleanup submenu entry.
PVE-Tools.sh
Extend storage management with a storage location panel and a guided dir storage mount wizard that reuses existing ext4/xfs partitions.
  • Add pve_storage_status_records/pve_storage_config_value/pve_storage_content_path helpers to resolve file-backed storages' root paths and per-content subdirectories (iso, backup, vztmpl, snippets, etc.), including support for content-dirs overrides.
  • Implement a storage location panel that lists storages, types, states, paths, disk usage via df, and provides SCP command hints for uploading ISO and backup files.
  • Add a mount wizard that enumerates ext4/xfs partitions, prompts for a new storage ID, mountpoint, and content types, writes a UUID-based /etc/fstab entry, mounts the filesystem, and adds a dir storage via pvesm add dir, with rollback if mount or pvesm fails.
  • Guard mountpoints against dangerous paths (/, /etc, /var/lib/vz, etc.) and check for existing mount usage or conflicting storage IDs before writing fstab.
PVE-Tools.sh
Integrate a CoolerControl manager as a third-party fan control tool under the new "第三方工具" menu.
  • Add CoolerControl project/doc/setup URLs and a new third_party_tools_menu with a CoolerControl 管理器 submenu alongside the module market and Community Scripts informational entry.
  • Implement CoolerControl install/update/uninstall flows that download and run Cloudsmith's Debian repo setup script, install coolercontrold (+optional GUI and hw-support packages), enable and restart the service, and manage the APT mirror for updates with high-risk gating.
  • Expose a "手动安装" view that prints official wget/bash commands and a local CoolerControl Web UI URL based on hostname -I.
  • Provide status/version detection for coolercontrold/coolercontrol using dpkg-query and systemctl, surfacing them in the CoolerControl manager header.
PVE-Tools.sh
Add a new security center with SSH hardening, fail2ban integration, and a read-only risk report.
  • Introduce security_center_menu that aggregates a risk report (security_risk_check) and an SSH hardening workflow (security_ssh_hardening) under "安全中心" in the main menu.
  • Implement SSH hardening that generates a systemd sshd_config.d drop-in to set a high, non-conflicting port, enable PubkeyAuthentication, and disable password-based methods, while commenting out conflicting global sshd_config directives.
  • Add fail2ban integration that auto-installs fail2ban (if missing), writes a dedicated jail.d entry for sshd with customizable maxretry/bantime/findtime, and safely restarts sshd and fail2ban, with full rollback if syntax checks or restarts fail.
  • Enhance the risk report to analyze SSH port and password policy, fail2ban status, PVE firewall enablement, public listeners on common high-risk ports, pending upgrades, empty-password/extra UID0 accounts, and permissive permissions on key config files, categorizing issues by severity.
  • Wire the old Copy Fail entry (menu 9) to launch the new security center instead.
PVE-Tools.sh
Reorganize top-level menus, add a "第三方工具" entry, and wire new submenus while removing the embedded Web docs directory.
  • Adjust the main menu labels to highlight new "安全中心" and "第三方工具" entries, compress wording, and align indices with the new feature layout.
  • Split the old VM/Container menu into a cleaner set of focused submenus: fast download, scheduled power, image import, and advanced VM operations, now decoupling Community Scripts into the third-party tools menu.
  • Remove all Web/.vitepress and static site files from the repository, simplifying the codebase and reducing script footprint for shell-only usage.
  • Add .gitattributes and a Tools/mirror-test.mjs helper script as a separate Node-based utility for mirror availability testing, independent from the main shell script.
PVE-Tools.sh
.gitattributes
Tools/mirror-test.mjs
Web/.vitepress/config.mts
Web/.vitepress/theme/components/Announcement.vue
Web/.vitepress/theme/components/CookieConsent.vue
Web/.vitepress/theme/components/CopyCodeBox.vue
Web/.vitepress/theme/components/Giscus.vue
Web/.vitepress/theme/components/HomeFeaturesWithTimeline.vue
Web/.vitepress/theme/components/SponsorWall.vue
Web/.vitepress/theme/components/TodoList.vue
Web/.vitepress/theme/custom.css
Web/.vitepress/theme/index.ts
Web/CLAUDE.md
Web/advanced/*
Web/assets/*
Web/index.md
Web/package.json
Web/*
Bump script VERSION to 9.0.0 and wire the new version URL into the update mechanism.
  • Update CURRENT_VERSION from 8.8.8 to 9.0.0 to reflect the major feature release.
  • Ensure VERSION_FILE_URL/UPDATE_FILE_URL/PVE_TOOLS_SCRIPT_URL all point to the PVE-Tools-9 GitHub repo and are consumed by pve_tools_choose_update_urls and the local updater.
  • Allow the new local script updater to fetch, validate, backup, and replace PVE-Tools.sh from the configured URL, with syntax checks and rollbacks.
PVE-Tools.sh
VERSION

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds Tools/mirror-test.mjs, a 435-line Node.js CLI that batch-tests PVE mirror availability using HEAD/GET probes with concurrency control, rating computation, and optional JSON output. Enforces LF line endings for shell scripts via .gitattributes, bumps VERSION from 8.8.8 to 9.0.0, and removes the entire Web/ VitePress documentation site (all Vue components, Markdown pages, configuration, and build artifacts).

Changes

Mirror Test CLI Tool, Shell LF Enforcement, and Version Bump

Layer / File(s) Summary
Mirror data, probe definitions, and CLI args
.gitattributes, VERSION, Tools/mirror-test.mjs
.gitattributes enforces LF for *.sh/Tools/*.sh/Modules/*.sh. VERSION bumped to 9.0.0. mirror-test.mjs defines the MIRRORS array (names, ids, base URLs), SOURCE_PROBES (candidate paths, required flags, fallbackGet per probe type), and parseArgs() for --timeout, --concurrency, --output, --verbose, and --help.
Network probing primitives and concurrency
Tools/mirror-test.mjs
probeUrl() issues HEAD/GET via AbortController timeout and treats 301/302/403 as "path exists." probeWithRetry() retries failed HEAD attempts and optionally falls back to GET. mapWithConcurrency() + sleep() drive bounded async worker loops for parallel mirror testing.
Mirror testing, rating, and report output
Tools/mirror-test.mjs
testMirror() iterates probes and candidates, records first matching path/status, and computes a rating string from required Debian/Debian-Security probe availability and optional probe count. printReport() sorts by rating, renders a tabular console report with per-tier summary counts and matched-path details. pad() aligns CJK-aware columns. main() orchestrates concurrent tests, calls printReport, and writes an optional JSON report with timestamp, elapsed time, probe metadata, and per-mirror results.

Web Directory Removal

Layer / File(s) Summary
Entire VitePress documentation site removed
Web/...
All VitePress config, Vue theme components (Announcement, CookieConsent, CopyCodeBox, Giscus, HomeFeaturesWithTimeline, SponsorWall, TodoList), custom CSS, theme entry, all Markdown documentation pages, package.json, wrangler.jsonc, index.js, public/_headers, public/robots.txt, sponsor-data.json, todo-data.json, and CLAUDE.md were deleted with no replacement.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit hops through mirrors galore,
HEAD and GET knock on each server's door.
LF endings tamed, version nine is here,
The old Web swept away, crystal clear.
Now probes race in parallel, ratings alight —
🐇✨ Every mirror ranked just right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title comprehensively describes the major changes in the v9.0.0 release including mirror source refactoring, CoolerControl integration, garbage cleanup system, disk passthrough enhancements, and removal of the web documentation site.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The PVE-Tools.sh script is getting very large and now mixes concerns like mirror management, SSH hardening, garbage cleanup, VM tooling, etc.; consider extracting major subsystems (e.g. mirrors, garbage cleanup, security, networking) into separate sourced files or shell modules to keep each file smaller and easier to reason about.
  • Several helper functions are duplicated or redefined in slightly different forms (e.g. storage path calculation, archive discovery, and some network helpers are reintroduced later in the file); it would be safer to centralize these utilities in a single section and reuse them to avoid diverging behavior over time.
  • The SSH hardening logic directly edits /etc/ssh/sshd_config and writes drop-in configs while also manipulating fail2ban; to reduce the risk of locking users out, consider adding a dry‑run mode and an explicit check that key-based root login works (or that a non-root admin user exists) before applying changes, and ensure rollback paths are clearly logged for operators.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `PVE-Tools.sh` script is getting very large and now mixes concerns like mirror management, SSH hardening, garbage cleanup, VM tooling, etc.; consider extracting major subsystems (e.g. mirrors, garbage cleanup, security, networking) into separate sourced files or shell modules to keep each file smaller and easier to reason about.
- Several helper functions are duplicated or redefined in slightly different forms (e.g. storage path calculation, archive discovery, and some network helpers are reintroduced later in the file); it would be safer to centralize these utilities in a single section and reuse them to avoid diverging behavior over time.
- The SSH hardening logic directly edits `/etc/ssh/sshd_config` and writes drop-in configs while also manipulating fail2ban; to reduce the risk of locking users out, consider adding a dry‑run mode and an explicit check that key-based root login works (or that a non-root admin user exists) before applying changes, and ensure rollback paths are clearly logged for operators.

## Individual Comments

### Comment 1
<location path="PVE-Tools.sh" line_range="505-511" />
<code_context>
+        return 1
+    fi
+
+    if command -v curl >/dev/null 2>&1; then
+        curl -fsSL --connect-timeout "$timeout" --max-time "$timeout" "$url" 2>/dev/null
+    elif command -v wget >/dev/null 2>&1; then
+        wget -q -T "$timeout" -O - "$url" 2>/dev/null
+    else
+        return 1
+    fi
+}
+
+pve_tools_download_file() {
+    local url="$1"
+    local output_file="$2"
+    local timeout="${3:-60}"
+
+    if [[ -z "$url" || -z "$output_file" ]]; then
+        return 1
+    fi
+
+    if command -v curl >/dev/null 2>&1; then
+        curl -fsSL --connect-timeout 15 --max-time "$timeout" -o "$output_file" "$url" 2>/dev/null
+    elif command -v wget >/dev/null 2>&1; then
+        wget -q -T "$timeout" -O "$output_file" "$url" 2>/dev/null
</code_context>
<issue_to_address>
**suggestion (bug_risk):** The download timeout parameter is partially ignored for curl, which could cause unexpected behavior.

In `pve_tools_download_file`, `wget` honors `timeout` via `-T "$timeout"`, but the `curl` path hardcodes `--connect-timeout 15` while only `--max-time` uses the caller value, so callers cannot control connect timeout and behavior differs between the two tools.

To make the API consistent and predictable, consider either using `--connect-timeout "$timeout"` as well, or adding a separate connect-timeout parameter (defaulting to 15s). Aligning this with `pve_tools_download_url` (which uses `--connect-timeout "$timeout" --max-time "$timeout"`) would avoid subtle differences in timeout behavior.

```suggestion
    if command -v curl >/dev/null 2>&1; then
        curl -fsSL --connect-timeout "$timeout" --max-time "$timeout" -o "$output_file" "$url" 2>/dev/null
    elif command -v wget >/dev/null 2>&1; then
        wget -q -T "$timeout" -O "$output_file" "$url" 2>/dev/null
    else
        return 1
    fi
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread PVE-Tools.sh
Comment on lines +505 to +511
if command -v curl >/dev/null 2>&1; then
curl -fsSL --connect-timeout 15 --max-time "$timeout" -o "$output_file" "$url" 2>/dev/null
elif command -v wget >/dev/null 2>&1; then
wget -q -T "$timeout" -O "$output_file" "$url" 2>/dev/null
else
return 1
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): The download timeout parameter is partially ignored for curl, which could cause unexpected behavior.

In pve_tools_download_file, wget honors timeout via -T "$timeout", but the curl path hardcodes --connect-timeout 15 while only --max-time uses the caller value, so callers cannot control connect timeout and behavior differs between the two tools.

To make the API consistent and predictable, consider either using --connect-timeout "$timeout" as well, or adding a separate connect-timeout parameter (defaulting to 15s). Aligning this with pve_tools_download_url (which uses --connect-timeout "$timeout" --max-time "$timeout") would avoid subtle differences in timeout behavior.

Suggested change
if command -v curl >/dev/null 2>&1; then
curl -fsSL --connect-timeout 15 --max-time "$timeout" -o "$output_file" "$url" 2>/dev/null
elif command -v wget >/dev/null 2>&1; then
wget -q -T "$timeout" -O "$output_file" "$url" 2>/dev/null
else
return 1
fi
if command -v curl >/dev/null 2>&1; then
curl -fsSL --connect-timeout "$timeout" --max-time "$timeout" -o "$output_file" "$url" 2>/dev/null
elif command -v wget >/dev/null 2>&1; then
wget -q -T "$timeout" -O "$output_file" "$url" 2>/dev/null
else
return 1
fi

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Tools/mirror-test.mjs`:
- Around line 113-124: The CLI argument parsing in the switch statement lacks
validation for option values, allowing invalid inputs to be silently accepted or
the next token to be incorrectly consumed. For each case (--timeout,
--concurrency, and --output/-o), add validation to check that the next argument
exists (to prevent out-of-bounds access), validate that the parsed value is
appropriate for that option (for example, ensure timeout and concurrency are
positive numbers), and throw or exit with a clear error message if validation
fails. This prevents negative concurrency values, missing output filenames, and
other malformed inputs from being silently accepted.
- Around line 169-181: The probeWithRetry function discards the actual HTTP
status code from the final probe attempt by always returning a hardcoded {
status: 0, ok: false } object when all retries are exhausted. Instead of
returning the hardcoded error object at the end of the function, preserve and
return the last result object obtained from the final probeUrl call (whether it
was from the HEAD request or the GET fallback), so that the actual HTTP status
codes like 404 or 500 are preserved in the final report for better debugging.

In `@VERSION`:
- Line 1: The VERSION file has been updated to 9.0.0 but the CURRENT_VERSION
variable in PVE-Tools.sh is still set to 8.8.8, causing a version mismatch that
will fail CI checks. Locate the CURRENT_VERSION variable in PVE-Tools.sh and
update its value from 8.8.8 to 9.0.0 to match the VERSION file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 24b59f09-c48e-4692-8646-54893f6e78ab

📥 Commits

Reviewing files that changed from the base of the PR and between dec829c and d946818.

⛔ Files ignored due to path filters (24)
  • Web/assets/WeChat.jpg is excluded by !**/*.jpg
  • Web/assets/images/Proxmox-Corporate-Brandguideline.pdf is excluded by !**/*.pdf
  • Web/assets/images/Proxmox_logos_full_lockup_SVG/proxmox-full-lockup-color.svg is excluded by !**/*.svg
  • Web/assets/images/Proxmox_logos_full_lockup_SVG/proxmox-full-lockup-inverted-color.svg is excluded by !**/*.svg
  • Web/assets/images/Proxmox_logos_full_lockup_SVG/proxmox-logo-stacked-color.svg is excluded by !**/*.svg
  • Web/assets/images/Proxmox_logos_full_lockup_SVG/proxmox-logo-stacked-inverted-color.svg is excluded by !**/*.svg
  • Web/bun.lock is excluded by !**/*.lock
  • Web/home-full.png is excluded by !**/*.png
  • Web/public/icons/clock-outline.svg is excluded by !**/*.svg
  • Web/public/icons/dots-horizontal.svg is excluded by !**/*.svg
  • Web/public/icons/harddisk.svg is excluded by !**/*.svg
  • Web/public/icons/rocket-launch-outline.svg is excluded by !**/*.svg
  • Web/public/icons/server-network.svg is excluded by !**/*.svg
  • Web/public/icons/shield-check-outline.svg is excluded by !**/*.svg
  • Web/public/icons/sparkles.svg is excluded by !**/*.svg
  • Web/public/icons/video-card.svg is excluded by !**/*.svg
  • Web/public/images/PixPin_2026-05-15_19-56-27.png is excluded by !**/*.png
  • Web/public/images/PixPin_2026-05-15_19-58-55.png is excluded by !**/*.png
  • Web/public/images/PixPin_2026-05-15_20-05-01.png is excluded by !**/*.png
  • Web/public/logo-dark.svg is excluded by !**/*.svg
  • Web/public/logo-horizontal-dark.svg is excluded by !**/*.svg
  • Web/public/logo-horizontal.svg is excluded by !**/*.svg
  • Web/public/logo.svg is excluded by !**/*.svg
  • Web/public/og-image.png is excluded by !**/*.png
📒 Files selected for processing (45)
  • .gitattributes
  • PVE-Tools.sh
  • Tools/mirror-test.mjs
  • VERSION
  • Web/.vitepress/config.mts
  • Web/.vitepress/theme/components/Announcement.vue
  • Web/.vitepress/theme/components/CookieConsent.vue
  • Web/.vitepress/theme/components/CopyCodeBox.vue
  • Web/.vitepress/theme/components/Giscus.vue
  • Web/.vitepress/theme/components/HomeFeaturesWithTimeline.vue
  • Web/.vitepress/theme/components/SponsorWall.vue
  • Web/.vitepress/theme/components/TodoList.vue
  • Web/.vitepress/theme/custom.css
  • Web/.vitepress/theme/index.ts
  • Web/CLAUDE.md
  • Web/advanced/cpu-optimization.md
  • Web/advanced/data-recovery-after-mistake.md
  • Web/advanced/gpu-passthrough.md
  • Web/advanced/gpu-virtualization.md
  • Web/advanced/host-network-firewall-ipv6.md
  • Web/advanced/how-to-connect-ssh.md
  • Web/advanced/index.md
  • Web/advanced/nvidia-vgpu-driver-notes.md
  • Web/advanced/pve-upgrade.md
  • Web/advanced/storage-management.md
  • Web/advanced/vm-backup-migration-cloudinit.md
  • Web/eol.md
  • Web/faq.md
  • Web/features.md
  • Web/guide.md
  • Web/index.js
  • Web/index.md
  • Web/package.json
  • Web/pay.md
  • Web/public/_headers
  • Web/public/robots.txt
  • Web/sponsor-data.json
  • Web/sponsor.md
  • Web/submit-plugin.md
  • Web/todo-data.json
  • Web/todo.md
  • Web/tos.md
  • Web/ula.md
  • Web/update.md
  • Web/wrangler.jsonc
💤 Files with no reviewable changes (41)
  • Web/ula.md
  • Web/eol.md
  • Web/advanced/data-recovery-after-mistake.md
  • Web/advanced/host-network-firewall-ipv6.md
  • Web/advanced/index.md
  • Web/wrangler.jsonc
  • Web/advanced/storage-management.md
  • Web/guide.md
  • Web/.vitepress/theme/components/Announcement.vue
  • Web/todo.md
  • Web/faq.md
  • Web/submit-plugin.md
  • Web/.vitepress/theme/components/Giscus.vue
  • Web/sponsor-data.json
  • Web/.vitepress/theme/components/TodoList.vue
  • Web/features.md
  • Web/pay.md
  • Web/advanced/nvidia-vgpu-driver-notes.md
  • Web/advanced/pve-upgrade.md
  • Web/.vitepress/theme/components/CookieConsent.vue
  • Web/tos.md
  • Web/package.json
  • Web/advanced/how-to-connect-ssh.md
  • Web/advanced/gpu-virtualization.md
  • Web/public/_headers
  • Web/advanced/cpu-optimization.md
  • Web/.vitepress/config.mts
  • Web/.vitepress/theme/custom.css
  • Web/advanced/vm-backup-migration-cloudinit.md
  • Web/.vitepress/theme/components/CopyCodeBox.vue
  • Web/public/robots.txt
  • Web/sponsor.md
  • Web/advanced/gpu-passthrough.md
  • Web/index.js
  • Web/todo-data.json
  • Web/index.md
  • Web/.vitepress/theme/components/HomeFeaturesWithTimeline.vue
  • Web/update.md
  • Web/.vitepress/theme/index.ts
  • Web/.vitepress/theme/components/SponsorWall.vue
  • Web/CLAUDE.md

Comment thread Tools/mirror-test.mjs
Comment on lines +113 to +124
for (let i = 0; i < args.length; i++) {
switch (args[i]) {
case "--timeout":
opts.timeout = Number(args[++i]) || 8000;
break;
case "--concurrency":
opts.concurrency = Number(args[++i]) || 6;
break;
case "--output":
case "-o":
opts.output = args[++i];
break;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast on invalid CLI option values instead of silently coercing.

Line 116/119/123 currently consume the next token without validation. This can silently break execution (e.g., --concurrency -1 yields zero workers and an empty report; missing --output value can consume the next flag as a filename).

Suggested fix
 function parseArgs() {
     const args = process.argv.slice(2);
@@
     for (let i = 0; i < args.length; i++) {
         switch (args[i]) {
             case "--timeout":
-                opts.timeout = Number(args[++i]) || 8000;
+                if (i + 1 >= args.length || args[i + 1].startsWith("-")) {
+                    throw new Error("--timeout requires a numeric value");
+                }
+                opts.timeout = Number(args[++i]);
+                if (!Number.isFinite(opts.timeout) || opts.timeout <= 0) {
+                    throw new Error("--timeout must be > 0");
+                }
                 break;
             case "--concurrency":
-                opts.concurrency = Number(args[++i]) || 6;
+                if (i + 1 >= args.length || args[i + 1].startsWith("-")) {
+                    throw new Error("--concurrency requires an integer value");
+                }
+                opts.concurrency = Number(args[++i]);
+                if (!Number.isInteger(opts.concurrency) || opts.concurrency <= 0) {
+                    throw new Error("--concurrency must be a positive integer");
+                }
                 break;
             case "--output":
             case "-o":
-                opts.output = args[++i];
+                if (i + 1 >= args.length || args[i + 1].startsWith("-")) {
+                    throw new Error("--output requires a file path");
+                }
+                opts.output = args[++i];
                 break;

Also applies to: 189-199, 396-401

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Tools/mirror-test.mjs` around lines 113 - 124, The CLI argument parsing in
the switch statement lacks validation for option values, allowing invalid inputs
to be silently accepted or the next token to be incorrectly consumed. For each
case (--timeout, --concurrency, and --output/-o), add validation to check that
the next argument exists (to prevent out-of-bounds access), validate that the
parsed value is appropriate for that option (for example, ensure timeout and
concurrency are positive numbers), and throw or exit with a clear error message
if validation fails. This prevents negative concurrency values, missing output
filenames, and other malformed inputs from being silently accepted.

Comment thread Tools/mirror-test.mjs
Comment on lines +169 to +181
async function probeWithRetry(url, timeoutMs, { retries = 1, fallbackGet = false } = {}) {
for (let attempt = 0; attempt <= retries; attempt++) {
let result = await probeUrl(url, timeoutMs, "HEAD");
if (result.ok) return result;
// HEAD 失败且启用 GET 回退时,用 GET 再试一次
if (fallbackGet && attempt === retries) {
result = await probeUrl(url, timeoutMs, "GET");
if (result.ok) return result;
}
if (attempt < retries) await sleep(300);
}
return { status: 0, ok: false };
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Preserve final HTTP status from retries for accurate reporting.

Line 180 always returns { status: 0 } after retries, which drops real failure status (e.g., 404/500) and makes the report less actionable.

Suggested fix
 async function probeWithRetry(url, timeoutMs, { retries = 1, fallbackGet = false } = {}) {
+    let last = { status: 0, ok: false };
     for (let attempt = 0; attempt <= retries; attempt++) {
-        let result = await probeUrl(url, timeoutMs, "HEAD");
+        let result = await probeUrl(url, timeoutMs, "HEAD");
+        last = result;
         if (result.ok) return result;
@@
         if (fallbackGet && attempt === retries) {
             result = await probeUrl(url, timeoutMs, "GET");
+            last = result;
             if (result.ok) return result;
         }
         if (attempt < retries) await sleep(300);
     }
-    return { status: 0, ok: false };
+    return last;
 }

Also applies to: 217-236

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Tools/mirror-test.mjs` around lines 169 - 181, The probeWithRetry function
discards the actual HTTP status code from the final probe attempt by always
returning a hardcoded { status: 0, ok: false } object when all retries are
exhausted. Instead of returning the hardcoded error object at the end of the
function, preserve and return the last result object obtained from the final
probeUrl call (whether it was from the HEAD request or the GET fallback), so
that the actual HTTP status codes like 404 or 500 are preserved in the final
report for better debugging.

Comment thread VERSION
@@ -1 +1 @@
8.8.8
9.0.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

SCRIPT_VERSION=$(rg -n 'CURRENT_VERSION=' PVE-Tools.sh | sed -E 's/.*"([^"]+)".*/\1/' | head -n1)
FILE_VERSION=$(tr -d '\r\n' < VERSION)

echo "PVE-Tools.sh CURRENT_VERSION: ${SCRIPT_VERSION}"
echo "VERSION file: ${FILE_VERSION}"

if [[ "${SCRIPT_VERSION}" != "${FILE_VERSION}" ]]; then
  echo "Mismatch detected"
  exit 1
fi

echo "Versions are consistent"

Repository: PVE-Tools/PVE-Tools-9

Length of output: 139


Update CURRENT_VERSION in PVE-Tools.sh to match the VERSION file.

VERSION is set to 9.0.0, but PVE-Tools.sh still has CURRENT_VERSION=8.8.8. This mismatch will cause CI to fail. Update CURRENT_VERSION to 9.0.0 in PVE-Tools.sh before merging.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@VERSION` at line 1, The VERSION file has been updated to 9.0.0 but the
CURRENT_VERSION variable in PVE-Tools.sh is still set to 8.8.8, causing a
version mismatch that will fail CI checks. Locate the CURRENT_VERSION variable
in PVE-Tools.sh and update its value from 8.8.8 to 9.0.0 to match the VERSION
file.

@Mapleawaa Mapleawaa merged commit d9cd6ee into PVE-Tools:main Jun 20, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant