From c39f311a20e58fa0af454abf6ef6a0c60a0247b0 Mon Sep 17 00:00:00 2001 From: catlog22 Date: Thu, 2 Oct 2025 12:37:29 +0800 Subject: [PATCH] feat: Add version selection support to installation scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhanced both Windows and Linux/macOS installation scripts with flexible version selection: New Features: - Version selection: stable (default), latest, or branch - Specific release tag installation (e.g., v3.2.0) - Auto-detection of latest stable release via GitHub API - Clear version information displayed during installation Installation Script Updates: - install-remote.ps1: Added -Version, -Tag parameters - install-remote.sh: Added --version, --tag flags - Updated help documentation with examples - Improved user prompts with version information Documentation Updates: - README.md: Added installation examples for all version types - README_CN.md: Added Chinese installation examples - Clear distinction between stable, latest, and specific versions Examples: - Stable (recommended): Default one-liner installation - Latest: --version latest flag - Specific: --version stable --tag v3.2.0 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- README.md | 28 ++++++++ README_CN.md | 28 ++++++++ image.png | Bin 0 -> 44010 bytes install-remote.ps1 | 167 +++++++++++++++++++++++++++++++++++++++------ install-remote.sh | 151 +++++++++++++++++++++++++++++++++++----- 5 files changed, 335 insertions(+), 39 deletions(-) create mode 100644 image.png diff --git a/README.md b/README.md index bbffef25..4f934167 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,8 @@ ### **🚀 Quick One-Line Installation** +#### **Install Latest Stable Release (Recommended)** + **Windows (PowerShell):** ```powershell Invoke-Expression (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.ps1" -UseBasicParsing).Content @@ -49,6 +51,32 @@ Invoke-Expression (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/cat bash <(curl -fsSL https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.sh) ``` +#### **Install Latest Development Version** + +**Windows (PowerShell):** +```powershell +$script = (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.ps1" -UseBasicParsing).Content +[ScriptBlock]::Create($script).Invoke('-Version', 'latest') +``` + +**Linux/macOS (Bash/Zsh):** +```bash +bash <(curl -fsSL https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.sh) --version latest +``` + +#### **Install Specific Version** + +**Windows (PowerShell):** +```powershell +$script = (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.ps1" -UseBasicParsing).Content +[ScriptBlock]::Create($script).Invoke('-Version', 'stable', '-Tag', 'v3.2.0') +``` + +**Linux/macOS (Bash/Zsh):** +```bash +bash <(curl -fsSL https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.sh) --version stable --tag v3.2.0 +``` + ### **✅ Verify Installation** After installation, run the following command to ensure CCW is working: ```bash diff --git a/README_CN.md b/README_CN.md index b18be338..837d31e9 100644 --- a/README_CN.md +++ b/README_CN.md @@ -39,6 +39,8 @@ ### **🚀 一键快速安装** +#### **安装最新稳定版(推荐)** + **Windows (PowerShell):** ```powershell Invoke-Expression (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.ps1" -UseBasicParsing).Content @@ -49,6 +51,32 @@ Invoke-Expression (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/cat bash <(curl -fsSL https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.sh) ``` +#### **安装最新开发版** + +**Windows (PowerShell):** +```powershell +$script = (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.ps1" -UseBasicParsing).Content +[ScriptBlock]::Create($script).Invoke('-Version', 'latest') +``` + +**Linux/macOS (Bash/Zsh):** +```bash +bash <(curl -fsSL https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.sh) --version latest +``` + +#### **安装指定版本** + +**Windows (PowerShell):** +```powershell +$script = (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.ps1" -UseBasicParsing).Content +[ScriptBlock]::Create($script).Invoke('-Version', 'stable', '-Tag', 'v3.2.0') +``` + +**Linux/macOS (Bash/Zsh):** +```bash +bash <(curl -fsSL https://raw.githubusercontent.com/catlog22/Claude-Code-Workflow/main/install-remote.sh) --version stable --tag v3.2.0 +``` + ### **✅ 验证安装** 安装后,运行以下命令以确保 CCW 正常工作: ```bash diff --git a/image.png b/image.png new file mode 100644 index 0000000000000000000000000000000000000000..2e1bde6c471720a4c1e2f379323cbb7b89d4073c GIT binary patch literal 44010 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 R68H>s-o(PV^o+-yzW{q9Dr5iv literal 0 HcmV?d00001 diff --git a/install-remote.ps1 b/install-remote.ps1 index 1adc260e..41eb35de 100644 --- a/install-remote.ps1 +++ b/install-remote.ps1 @@ -1,16 +1,88 @@ #!/usr/bin/env pwsh -# Claude Code Workflow (CCW) - Remote Installation Script -# One-liner remote installation for Claude Code Workflow system +<# +.SYNOPSIS + Claude Code Workflow (CCW) - Remote Installation Script + +.DESCRIPTION + One-liner remote installation for Claude Code Workflow system. + Downloads and installs CCW from GitHub with flexible version selection. + +.PARAMETER Version + Installation version type: + - "stable" (default): Latest stable release tag + - "latest": Latest main branch (development version) + - "branch": Install from specific branch + +.PARAMETER Tag + Specific release tag to install (e.g., "v3.2.0") + Only used when Version is "stable" + +.PARAMETER Branch + Branch name to install from (default: "main") + Only used when Version is "branch" + +.PARAMETER Global + Install to global user directory (~/.claude) + +.PARAMETER Directory + Install to custom directory + +.PARAMETER Force + Skip confirmation prompts + +.PARAMETER NoBackup + Skip backup of existing installation + +.PARAMETER NonInteractive + Run in non-interactive mode + +.PARAMETER BackupAll + Backup all files including git-ignored files + +.EXAMPLE + # Install latest stable release (recommended) + .\install-remote.ps1 + +.EXAMPLE + # Install specific stable version + .\install-remote.ps1 -Version stable -Tag "v3.2.0" + +.EXAMPLE + # Install latest development version + .\install-remote.ps1 -Version latest + +.EXAMPLE + # Install from specific branch + .\install-remote.ps1 -Version branch -Branch "feature/new-feature" + +.EXAMPLE + # Install to global directory without prompts + .\install-remote.ps1 -Global -Force + +.LINK + https://github.com/catlog22/Claude-Code-Workflow +#> [CmdletBinding()] param( + [ValidateSet("stable", "latest", "branch")] + [string]$Version = "stable", + + [string]$Tag = "", + + [string]$Branch = "main", + [switch]$Global, + [string]$Directory = "", + [switch]$Force, + [switch]$NoBackup, + [switch]$NonInteractive, - [switch]$BackupAll, - [string]$Branch = "main" + + [switch]$BackupAll ) # Set encoding for proper Unicode support @@ -26,7 +98,7 @@ if ($PSVersionTable.PSVersion.Major -ge 6) { # Script metadata $ScriptName = "Claude Code Workflow (CCW) Remote Installer" -$Version = "2.1.1" +$InstallerVersion = "2.2.0" # Colors for output $ColorSuccess = "Green" @@ -43,7 +115,7 @@ function Write-ColorOutput { } function Show-Header { - Write-ColorOutput "==== $ScriptName v$Version ====" $ColorInfo + Write-ColorOutput "==== $ScriptName v$InstallerVersion ====" $ColorInfo Write-ColorOutput "========================================================" $ColorInfo Write-Host "" } @@ -78,29 +150,70 @@ function Get-TempDirectory { return $tempDir } +function Get-LatestRelease { + try { + $apiUrl = "https://api.github.com/repos/catlog22/Claude-Code-Workflow/releases/latest" + $response = Invoke-RestMethod -Uri $apiUrl -UseBasicParsing + return $response.tag_name + } catch { + Write-ColorOutput "WARNING: Failed to fetch latest release, using 'main' branch" $ColorWarning + return $null + } +} + function Download-Repository { param( [string]$TempDir, - [string]$Branch = "main" + [string]$Version = "stable", + [string]$Branch = "main", + [string]$Tag = "" ) - + $repoUrl = "https://github.com/catlog22/Claude-Code-Workflow" - $zipUrl = "$repoUrl/archive/refs/heads/$Branch.zip" + + # Determine download URL based on version type + if ($Version -eq "stable") { + # Download latest stable release + if ([string]::IsNullOrEmpty($Tag)) { + $latestTag = Get-LatestRelease + if ($latestTag) { + $Tag = $latestTag + } else { + # Fallback to main branch if API fails + $zipUrl = "$repoUrl/archive/refs/heads/main.zip" + $downloadType = "main branch (fallback)" + } + } + + if (-not [string]::IsNullOrEmpty($Tag)) { + $zipUrl = "$repoUrl/archive/refs/tags/$Tag.zip" + $downloadType = "stable release $Tag" + } + } elseif ($Version -eq "latest") { + # Download latest main branch + $zipUrl = "$repoUrl/archive/refs/heads/main.zip" + $downloadType = "latest main branch" + } else { + # Download specific branch + $zipUrl = "$repoUrl/archive/refs/heads/$Branch.zip" + $downloadType = "branch $Branch" + } + $zipPath = Join-Path $TempDir "repo.zip" - + Write-ColorOutput "Downloading from GitHub..." $ColorInfo Write-ColorOutput "Source: $repoUrl" $ColorInfo - Write-ColorOutput "Branch: $Branch" $ColorInfo - + Write-ColorOutput "Type: $downloadType" $ColorInfo + try { # Download with progress $progressPreference = $ProgressPreference $ProgressPreference = 'SilentlyContinue' - + Invoke-WebRequest -Uri $zipUrl -OutFile $zipPath -UseBasicParsing - + $ProgressPreference = $progressPreference - + if (Test-Path $zipPath) { $fileSize = (Get-Item $zipPath).Length Write-ColorOutput "Download complete ($([math]::Round($fileSize/1024/1024, 2)) MB)" $ColorSuccess @@ -237,17 +350,29 @@ function Main { Wait-ForUserConfirmation "System check failed! Press any key to exit..." -ExitAfter } + # Determine version information for display + $versionInfo = switch ($Version) { + "stable" { + if ($Tag) { "Stable release: $Tag" } + else { "Latest stable release (auto-detected)" } + } + "latest" { "Latest main branch (development)" } + "branch" { "Custom branch: $Branch" } + } + # Confirm installation if (-not $NonInteractive -and -not $Force) { Write-Host "" - Write-ColorOutput "SECURITY NOTE:" $ColorWarning - Write-Host "- This script will download and execute Claude Code Workflow from GitHub" - Write-Host "- Repository: https://github.com/catlog22/Claude-Code-Workflow" - Write-Host "- Branch: $Branch (latest stable version)" + Write-ColorOutput "INSTALLATION DETAILS:" $ColorInfo + Write-Host "- Repository: https://github.com/catlog22/Claude-Code-Workflow" + Write-Host "- Version: $versionInfo" Write-Host "- Features: Intelligent workflow orchestration with multi-agent coordination" + Write-Host "" + Write-ColorOutput "SECURITY NOTE:" $ColorWarning + Write-Host "- This script will download and execute code from GitHub" Write-Host "- Please ensure you trust this source" Write-Host "" - + $choice = Read-Host "Continue with installation? (y/N)" if ($choice -notmatch '^[Yy]') { Write-ColorOutput "Installation cancelled" $ColorWarning @@ -261,7 +386,7 @@ function Main { try { # Download repository - $zipPath = Download-Repository $tempDir $Branch + $zipPath = Download-Repository -TempDir $tempDir -Version $Version -Branch $Branch -Tag $Tag if (-not $zipPath) { throw "Download failed" } diff --git a/install-remote.sh b/install-remote.sh index 1ada09fc..e9ae64ac 100644 --- a/install-remote.sh +++ b/install-remote.sh @@ -6,9 +6,13 @@ set -e # Exit on error # Script metadata SCRIPT_NAME="Claude Code Workflow (CCW) Remote Installer" -VERSION="2.1.1" +INSTALLER_VERSION="2.2.0" BRANCH="${BRANCH:-main}" +# Version control +VERSION_TYPE="${VERSION_TYPE:-stable}" # stable, latest, branch +TAG_VERSION="" + # Colors for output COLOR_RESET='\033[0m' COLOR_SUCCESS='\033[0;32m' @@ -32,7 +36,7 @@ function write_color() { } function show_header() { - write_color "==== $SCRIPT_NAME v$VERSION ====" "$COLOR_INFO" + write_color "==== $SCRIPT_NAME v$INSTALLER_VERSION ====" "$COLOR_INFO" write_color "========================================================" "$COLOR_INFO" echo "" } @@ -72,17 +76,80 @@ function get_temp_directory() { echo "$temp_dir" } +function get_latest_release() { + local api_url="https://api.github.com/repos/catlog22/Claude-Code-Workflow/releases/latest" + + if command -v jq &> /dev/null; then + # Use jq if available + local tag + tag=$(curl -fsSL "$api_url" 2>/dev/null | jq -r '.tag_name' 2>/dev/null) + if [ -n "$tag" ] && [ "$tag" != "null" ]; then + echo "$tag" + return 0 + fi + else + # Fallback: parse JSON with grep/sed + local tag + tag=$(curl -fsSL "$api_url" 2>/dev/null | grep -o '"tag_name":\s*"[^"]*"' | sed 's/"tag_name":\s*"\([^"]*\)"/\1/') + if [ -n "$tag" ]; then + echo "$tag" + return 0 + fi + fi + + write_color "WARNING: Failed to fetch latest release, using 'main' branch" "$COLOR_WARNING" >&2 + return 1 +} + function download_repository() { local temp_dir="$1" - local branch="${2:-main}" + local version_type="${2:-stable}" + local branch="${3:-main}" + local tag="${4:-}" local repo_url="https://github.com/catlog22/Claude-Code-Workflow" - local zip_url="${repo_url}/archive/refs/heads/${branch}.zip" + local zip_url="" + local download_type="" + + # Determine download URL based on version type + case "$version_type" in + stable) + # Download latest stable release + if [ -z "$tag" ]; then + tag=$(get_latest_release) + if [ -z "$tag" ]; then + # Fallback to main branch if API fails + zip_url="${repo_url}/archive/refs/heads/main.zip" + download_type="main branch (fallback)" + else + zip_url="${repo_url}/archive/refs/tags/${tag}.zip" + download_type="stable release $tag" + fi + else + zip_url="${repo_url}/archive/refs/tags/${tag}.zip" + download_type="stable release $tag" + fi + ;; + latest) + # Download latest main branch + zip_url="${repo_url}/archive/refs/heads/main.zip" + download_type="latest main branch" + ;; + branch) + # Download specific branch + zip_url="${repo_url}/archive/refs/heads/${branch}.zip" + download_type="branch $branch" + ;; + *) + write_color "ERROR: Invalid version type: $version_type" "$COLOR_ERROR" >&2 + return 1 + ;; + esac + local zip_path="${temp_dir}/repo.zip" write_color "Downloading from GitHub..." "$COLOR_INFO" >&2 write_color "Source: $repo_url" "$COLOR_INFO" >&2 - write_color "Branch: $branch" "$COLOR_INFO" >&2 - write_color "URL: $zip_url" "$COLOR_INFO" >&2 + write_color "Type: $download_type" "$COLOR_INFO" >&2 # Download with curl if curl -fsSL -o "$zip_path" "$zip_url" 2>&1 >&2; then @@ -217,6 +284,23 @@ function wait_for_user() { function parse_arguments() { while [[ $# -gt 0 ]]; do case "$1" in + --version) + VERSION_TYPE="$2" + if [[ ! "$VERSION_TYPE" =~ ^(stable|latest|branch)$ ]]; then + write_color "ERROR: Invalid version type: $VERSION_TYPE" "$COLOR_ERROR" + write_color "Valid options: stable, latest, branch" "$COLOR_ERROR" + exit 1 + fi + shift 2 + ;; + --tag) + TAG_VERSION="$2" + shift 2 + ;; + --branch) + BRANCH="$2" + shift 2 + ;; --global) INSTALL_GLOBAL=true shift @@ -241,10 +325,6 @@ function parse_arguments() { BACKUP_ALL=true shift ;; - --branch) - BRANCH="$2" - shift 2 - ;; --help) show_help exit 0 @@ -260,30 +340,45 @@ function parse_arguments() { function show_help() { cat << EOF -$SCRIPT_NAME v$VERSION +$SCRIPT_NAME v$INSTALLER_VERSION Usage: $0 [OPTIONS] -Options: +Version Options: + --version TYPE Version type: stable (default), latest, or branch + --tag TAG Specific release tag (e.g., v3.2.0) - for stable version + --branch BRANCH Branch name (default: main) - for branch version + +Installation Options: --global Install to global user directory (~/.claude) --directory DIR Install to custom directory --force Force installation without prompts --no-backup Skip backup creation --non-interactive Non-interactive mode (no prompts) --backup-all Backup all files before installation - --branch BRANCH Specify GitHub branch (default: main) --help Show this help message Examples: - # Interactive installation + # Install latest stable release (recommended) $0 + # Install specific stable version + $0 --version stable --tag v3.2.0 + + # Install latest development version + $0 --version latest + + # Install from specific branch + $0 --version branch --branch feature/new-feature + # Global installation without prompts $0 --global --non-interactive # Custom directory installation $0 --directory /opt/claude-code-workflow +Repository: https://github.com/catlog22/Claude-Code-Workflow + EOF } @@ -300,14 +395,34 @@ function main() { exit 1 fi + # Determine version information for display + local version_info="" + case "$VERSION_TYPE" in + stable) + if [ -n "$TAG_VERSION" ]; then + version_info="Stable release: $TAG_VERSION" + else + version_info="Latest stable release (auto-detected)" + fi + ;; + latest) + version_info="Latest main branch (development)" + ;; + branch) + version_info="Custom branch: $BRANCH" + ;; + esac + # Confirm installation if [ "$NON_INTERACTIVE" != true ] && [ "$FORCE" != true ]; then echo "" - write_color "SECURITY NOTE:" "$COLOR_WARNING" - echo "- This script will download and execute Claude Code Workflow from GitHub" + write_color "INSTALLATION DETAILS:" "$COLOR_INFO" echo "- Repository: https://github.com/catlog22/Claude-Code-Workflow" - echo "- Branch: $BRANCH (latest stable version)" + echo "- Version: $version_info" echo "- Features: Intelligent workflow orchestration with multi-agent coordination" + echo "" + write_color "SECURITY NOTE:" "$COLOR_WARNING" + echo "- This script will download and execute code from GitHub" echo "- Please ensure you trust this source" echo "" @@ -328,7 +443,7 @@ function main() { # Download repository local zip_path write_color "Starting download process..." "$COLOR_INFO" - zip_path=$(download_repository "$temp_dir" "$BRANCH") + zip_path=$(download_repository "$temp_dir" "$VERSION_TYPE" "$BRANCH" "$TAG_VERSION") local download_status=$? if [ $download_status -eq 0 ] && [ -n "$zip_path" ] && [ -f "$zip_path" ]; then