diff --git a/.github/scripts/deploy_windows_winrm.py b/.github/scripts/deploy_windows_winrm.py index 81a4a23c..93f79454 100644 --- a/.github/scripts/deploy_windows_winrm.py +++ b/.github/scripts/deploy_windows_winrm.py @@ -29,10 +29,18 @@ def main() -> int: port = optional_env("KK_DEPLOY_PORT", "5985") username = require_env("KK_DEPLOY_USERNAME") password = require_env("KK_DEPLOY_PASSWORD") - deploy_root = optional_env("KK_DEPLOY_ROOT", r"C:\kkFileView-5.0") - health_url = optional_env("KK_DEPLOY_HEALTH_URL", "http://127.0.0.1:8012/") - artifact_url = require_env("KK_DEPLOY_ARTIFACT_URL") - dry_run = optional_env("KK_DEPLOY_DRY_RUN", "false").lower() + env_pairs = { + "KK_DEPLOY_ROOT": optional_env("KK_DEPLOY_ROOT", r"C:\kkFileView-5.0"), + "KK_DEPLOY_HEALTH_URL": optional_env("KK_DEPLOY_HEALTH_URL", "http://127.0.0.1:8012/"), + "KK_DEPLOY_REPO_URL": optional_env("KK_DEPLOY_REPO_URL", "https://github.com/kekingcn/kkFileView.git"), + "KK_DEPLOY_BRANCH": optional_env("KK_DEPLOY_BRANCH", "master"), + "KK_DEPLOY_SOURCE_ROOT": optional_env("KK_DEPLOY_SOURCE_ROOT", r"C:\kkFileView-source"), + "KK_DEPLOY_JAVA_HOME": optional_env("KK_DEPLOY_JAVA_HOME", r"C:\Program Files\jdk-21.0.2"), + "KK_DEPLOY_GIT_EXE": optional_env("KK_DEPLOY_GIT_EXE", r"C:\kkFileView-tools\git\cmd\git.exe"), + "KK_DEPLOY_MVN_CMD": optional_env("KK_DEPLOY_MVN_CMD", r"C:\kkFileView-tools\maven\bin\mvn.cmd"), + "KK_DEPLOY_MAVEN_SETTINGS": optional_env("KK_DEPLOY_MAVEN_SETTINGS", ""), + "KK_DEPLOY_DRY_RUN": optional_env("KK_DEPLOY_DRY_RUN", "false").lower(), + } script_path = pathlib.Path(__file__).with_name("remote_windows_deploy.ps1") script_body = script_path.read_text(encoding="utf-8") @@ -74,17 +82,19 @@ $ErrorActionPreference = 'Stop' $raw = Get-Content -LiteralPath '{ps_quote(remote_b64_path)}' -Raw [System.IO.File]::WriteAllBytes('{ps_quote(remote_ps1_path)}', [Convert]::FromBase64String($raw)) try {{ - $env:KK_DEPLOY_ARTIFACT_URL = '{ps_quote(artifact_url)}' - $env:KK_DEPLOY_ROOT = '{ps_quote(deploy_root)}' - $env:KK_DEPLOY_HEALTH_URL = '{ps_quote(health_url)}' - $env:KK_DEPLOY_DRY_RUN = '{ps_quote(dry_run)}' +""" + + "\n".join( + f" $env:{key} = '{ps_quote(value)}'" for key, value in env_pairs.items() + ) + + f""" powershell -NoProfile -ExecutionPolicy Bypass -File '{ps_quote(remote_ps1_path)}' ` $code = $LASTEXITCODE }} finally {{ - Remove-Item Env:KK_DEPLOY_ARTIFACT_URL -ErrorAction SilentlyContinue - Remove-Item Env:KK_DEPLOY_ROOT -ErrorAction SilentlyContinue - Remove-Item Env:KK_DEPLOY_HEALTH_URL -ErrorAction SilentlyContinue - Remove-Item Env:KK_DEPLOY_DRY_RUN -ErrorAction SilentlyContinue +""" + + "\n".join( + f" Remove-Item Env:{key} -ErrorAction SilentlyContinue" for key in env_pairs + ) + + f""" Remove-Item '{ps_quote(remote_b64_path)}' -Force -ErrorAction SilentlyContinue Remove-Item '{ps_quote(remote_ps1_path)}' -Force -ErrorAction SilentlyContinue }} diff --git a/.github/scripts/remote_windows_deploy.ps1 b/.github/scripts/remote_windows_deploy.ps1 index 4d80a874..bc0901ed 100644 --- a/.github/scripts/remote_windows_deploy.ps1 +++ b/.github/scripts/remote_windows_deploy.ps1 @@ -1,4 +1,5 @@ $ErrorActionPreference = 'Stop' +$ProgressPreference = 'SilentlyContinue' function Write-Step { param([string]$Message) @@ -30,17 +31,22 @@ function Get-OptionalEnv { return $Value } -$ArtifactDownloadUrl = Get-RequiredEnv 'KK_DEPLOY_ARTIFACT_URL' $DeployRoot = Get-OptionalEnv 'KK_DEPLOY_ROOT' 'C:\kkFileView-5.0' $HealthUrl = Get-OptionalEnv 'KK_DEPLOY_HEALTH_URL' 'http://127.0.0.1:8012/' +$RepoUrl = Get-OptionalEnv 'KK_DEPLOY_REPO_URL' 'https://github.com/kekingcn/kkFileView.git' +$Branch = Get-OptionalEnv 'KK_DEPLOY_BRANCH' 'master' +$SourceRoot = Get-OptionalEnv 'KK_DEPLOY_SOURCE_ROOT' 'C:\kkFileView-source' +$JavaHome = Get-OptionalEnv 'KK_DEPLOY_JAVA_HOME' 'C:\Program Files\jdk-21.0.2' +$GitExe = Get-OptionalEnv 'KK_DEPLOY_GIT_EXE' 'C:\kkFileView-tools\git\cmd\git.exe' +$MvnCmd = Get-OptionalEnv 'KK_DEPLOY_MVN_CMD' 'C:\kkFileView-tools\maven\bin\mvn.cmd' +$MavenSettings = Get-OptionalEnv 'KK_DEPLOY_MAVEN_SETTINGS' '' $DryRun = Get-OptionalEnv 'KK_DEPLOY_DRY_RUN' 'false' $BinDir = Join-Path $DeployRoot 'bin' $StartupScript = Join-Path $BinDir 'startup.bat' $ReleaseDir = Join-Path $DeployRoot 'releases' $DeployTmp = Join-Path $DeployRoot 'deploy-tmp' -$ArtifactZip = Join-Path $DeployTmp 'artifact.zip' -$ExtractDir = Join-Path $DeployTmp 'artifact' +$BuildOutputDir = Join-Path (Join-Path $SourceRoot 'server') 'target' if (-not (Test-Path $DeployRoot)) { throw "Deploy root not found: $DeployRoot" @@ -59,6 +65,23 @@ if (-not $CurrentJar) { throw "No kkFileView jar found in $BinDir" } +$JavaExe = Join-Path $JavaHome 'bin\java.exe' +if (-not (Test-Path $JavaExe)) { + throw "JDK 21 java executable not found: $JavaExe" +} + +if (-not (Test-Path $GitExe)) { + throw "Git executable not found: $GitExe" +} + +if (-not (Test-Path $MvnCmd)) { + throw "Maven executable not found: $MvnCmd" +} + +if (-not [string]::IsNullOrWhiteSpace($MavenSettings) -and -not (Test-Path $MavenSettings)) { + throw "Maven settings file not found: $MavenSettings" +} + $JarName = $CurrentJar.Name $JarPath = $CurrentJar.FullName @@ -66,6 +89,74 @@ Write-Step "Deploy root: $DeployRoot" Write-Step "Current jar: $JarPath" Write-Step "Startup script: $StartupScript" Write-Step "Health url: $HealthUrl" +Write-Step "Source root: $SourceRoot" +Write-Step "Branch: $Branch" +Write-Step "Git exe: $GitExe" +Write-Step "Maven cmd: $MvnCmd" +Write-Step "Java home: $JavaHome" +if (-not [string]::IsNullOrWhiteSpace($MavenSettings)) { + Write-Step "Maven settings: $MavenSettings" +} + +function Invoke-External { + param( + [string]$FilePath, + [string[]]$Arguments, + [string]$WorkingDirectory = $null + ) + + $previous = $null + if ($WorkingDirectory) { + $previous = Get-Location + Set-Location $WorkingDirectory + } + + try { + & $FilePath @Arguments + if ($LASTEXITCODE -ne 0) { + throw "Command failed ($LASTEXITCODE): $FilePath $($Arguments -join ' ')" + } + } finally { + if ($previous) { + Set-Location $previous + } + } +} + +function Assert-SafeSourceRoot { + param([string]$PathToCheck) + + $FullPath = [System.IO.Path]::GetFullPath($PathToCheck) + $RootPath = [System.IO.Path]::GetPathRoot($FullPath) + if ($FullPath.TrimEnd('\') -eq $RootPath.TrimEnd('\')) { + throw "Refusing to use drive root as source root: $FullPath" + } + + $DangerousLeafNames = @( + 'Windows', + 'Users', + 'Program Files', + 'Program Files (x86)', + 'ProgramData' + ) + $LeafName = Split-Path -Leaf $FullPath.TrimEnd('\') + if ($DangerousLeafNames -contains $LeafName) { + throw "Refusing to use a high-risk source root path: $FullPath" + } +} + +$env:JAVA_HOME = $JavaHome +$env:Path = (Join-Path $JavaHome 'bin') + ';' + (Split-Path -Parent $GitExe) + ';' + (Split-Path -Parent $MvnCmd) + ';' + $env:Path + +Write-Step 'Validating Git executable' +Invoke-External -FilePath $GitExe -Arguments @('--version') + +Write-Step 'Validating Maven executable' +$MavenVersionArgs = @('-version') +if (-not [string]::IsNullOrWhiteSpace($MavenSettings)) { + $MavenVersionArgs = @('-s', $MavenSettings, '-version') +} +Invoke-External -FilePath $MvnCmd -Arguments $MavenVersionArgs if ($DryRun -eq 'true') { Write-Step "Dry run enabled, remote validation finished" @@ -75,41 +166,51 @@ if ($DryRun -eq 'true') { New-Item -ItemType Directory -Force -Path $ReleaseDir | Out-Null New-Item -ItemType Directory -Force -Path $DeployTmp | Out-Null -if (Test-Path $ArtifactZip) { - Remove-Item $ArtifactZip -Force +function Sync-Repository { + Assert-SafeSourceRoot -PathToCheck $SourceRoot + + if (-not (Test-Path (Join-Path $SourceRoot '.git'))) { + if (Test-Path $SourceRoot) { + Remove-Item $SourceRoot -Recurse -Force + } + + $parent = Split-Path -Parent $SourceRoot + if ($parent) { + New-Item -ItemType Directory -Force -Path $parent | Out-Null + } + + Write-Step "Cloning repository from $RepoUrl" + Invoke-External -FilePath $GitExe -Arguments @('clone', '--depth', '1', '--branch', $Branch, '--single-branch', $RepoUrl, $SourceRoot) + return + } + + Write-Step "Fetching latest branch state from origin/$Branch" + Invoke-External -FilePath $GitExe -Arguments @('remote', 'set-url', 'origin', $RepoUrl) -WorkingDirectory $SourceRoot + Invoke-External -FilePath $GitExe -Arguments @('fetch', '--prune', '--depth', '1', 'origin', $Branch) -WorkingDirectory $SourceRoot + Invoke-External -FilePath $GitExe -Arguments @('checkout', '-B', $Branch, "origin/$Branch") -WorkingDirectory $SourceRoot + Invoke-External -FilePath $GitExe -Arguments @('reset', '--hard', "origin/$Branch") -WorkingDirectory $SourceRoot + Invoke-External -FilePath $GitExe -Arguments @('clean', '-fd') -WorkingDirectory $SourceRoot } -if (Test-Path $ExtractDir) { - Remove-Item $ExtractDir -Recurse -Force +function Build-KkFileView { + Write-Step 'Building kkFileView from source' + $BuildArgs = @('-B', 'clean', 'package', '-Dmaven.test.skip=true', '--file', 'pom.xml') + if (-not [string]::IsNullOrWhiteSpace($MavenSettings)) { + $BuildArgs = @('-s', $MavenSettings) + $BuildArgs + } + Invoke-External -FilePath $MvnCmd -Arguments $BuildArgs -WorkingDirectory $SourceRoot } -Write-Step 'Downloading workflow artifact via signed URL' -$PreviousProgressPreference = $ProgressPreference -$ProgressPreference = 'SilentlyContinue' -try { - Invoke-WebRequest -Uri $ArtifactDownloadUrl -OutFile $ArtifactZip -UseBasicParsing -TimeoutSec 120 -} finally { - $ProgressPreference = $PreviousProgressPreference -} +Sync-Repository +Build-KkFileView -if (-not (Test-Path $ArtifactZip)) { - throw "Artifact zip was not created: $ArtifactZip" -} - -$ArtifactZipInfo = Get-Item $ArtifactZip -if ($ArtifactZipInfo.Length -le 0) { - throw "Downloaded artifact zip is empty: $ArtifactZip" -} - -Expand-Archive -LiteralPath $ArtifactZip -DestinationPath $ExtractDir -Force - -$DownloadedJars = Get-ChildItem $ExtractDir -Filter 'kkFileView-*.jar' -Recurse +$DownloadedJars = Get-ChildItem $BuildOutputDir -Filter 'kkFileView-*.jar' -File if (-not $DownloadedJars) { - throw 'No kkFileView jar found inside downloaded workflow artifact' + throw "No kkFileView jar found in build output: $BuildOutputDir" } if ($DownloadedJars.Count -ne 1) { - throw "Expected exactly one kkFileView jar inside downloaded workflow artifact, found $($DownloadedJars.Count)" + throw "Expected exactly one kkFileView jar in build output, found $($DownloadedJars.Count)" } $DownloadedJar = $DownloadedJars[0] @@ -118,27 +219,33 @@ $Timestamp = Get-Date -Format 'yyyyMMddHHmmss' $BackupJar = Join-Path $ReleaseDir ("{0}.{1}.bak" -f $JarName, $Timestamp) function Stop-KkFileView { + foreach ($Process in @(Get-KkFileViewJavaProcesses) + @(Get-KkFileViewLauncherProcesses)) { + Write-Step "Stopping process $($Process.ProcessId)" + Stop-Process -Id $Process.ProcessId -Force -ErrorAction SilentlyContinue + } +} + +function Get-KkFileViewJavaProcesses { $JarPattern = [regex]::Escape($JarName) - $Processes = Get-CimInstance Win32_Process | Where-Object { + return Get-CimInstance Win32_Process | Where-Object { $_.Name -match '^java(\.exe)?$' -and $_.CommandLine -and $_.CommandLine -match $JarPattern } +} - foreach ($Process in $Processes) { - Write-Step "Stopping java process $($Process.ProcessId)" - Stop-Process -Id $Process.ProcessId -Force -ErrorAction SilentlyContinue +function Get-KkFileViewLauncherProcesses { + $StartupPattern = [regex]::Escape([System.IO.Path]::GetFileName($StartupScript)) + return Get-CimInstance Win32_Process | Where-Object { + $_.Name -ieq 'cmd.exe' -and $_.CommandLine -and $_.CommandLine -match $StartupPattern } } function Wait-KkFileViewStopped { param([int]$TimeoutSeconds = 30) - $JarPattern = [regex]::Escape($JarName) for ($i = 0; $i -lt $TimeoutSeconds; $i++) { - $Processes = Get-CimInstance Win32_Process | Where-Object { - $_.Name -match '^java(\.exe)?$' -and $_.CommandLine -and $_.CommandLine -match $JarPattern - } - - if (-not $Processes) { + $JavaProcesses = @(Get-KkFileViewJavaProcesses) + $CmdProcesses = @(Get-KkFileViewLauncherProcesses) + if ((@($JavaProcesses).Count + @($CmdProcesses).Count) -eq 0) { return $true } @@ -150,20 +257,37 @@ function Wait-KkFileViewStopped { function Start-KkFileView { Write-Step "Starting kkFileView" - Start-Process -FilePath 'cmd.exe' -ArgumentList '/c', "`"$StartupScript`"" -WorkingDirectory $BinDir -WindowStyle Hidden + $CreateResult = Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ + CommandLine = ('cmd.exe /c ""' + $StartupScript + '""') + CurrentDirectory = $BinDir + } + + if ($CreateResult.ReturnValue -ne 0) { + throw "Failed to start kkFileView launcher, Win32_Process.Create returned $($CreateResult.ReturnValue)" + } + + Write-Step "Launcher process created with pid $($CreateResult.ProcessId)" } function Wait-Health { param([string]$Url) + $SuccessfulChecks = 0 for ($i = 0; $i -lt 24; $i++) { Start-Sleep -Seconds 5 try { $Response = Invoke-WebRequest -Uri $Url -UseBasicParsing -TimeoutSec 5 - if ($Response.StatusCode -eq 200) { + if ($Response.StatusCode -eq 200 -and @(Get-KkFileViewJavaProcesses).Count -gt 0) { + $SuccessfulChecks++ + } else { + $SuccessfulChecks = 0 + } + + if ($SuccessfulChecks -ge 3) { return $true } } catch { + $SuccessfulChecks = 0 Start-Sleep -Milliseconds 200 } } diff --git a/.github/workflows/master-auto-deploy.yml b/.github/workflows/master-auto-deploy.yml index 6b0c4516..cfc0ef72 100644 --- a/.github/workflows/master-auto-deploy.yml +++ b/.github/workflows/master-auto-deploy.yml @@ -11,46 +11,24 @@ concurrency: permissions: contents: read - actions: read jobs: - build: - runs-on: ubuntu-22.04 - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: temurin - cache: maven - - - name: Build with Maven - run: mvn -B package -Dmaven.test.skip=true --file pom.xml - - - name: Upload server jar artifact - uses: actions/upload-artifact@v4 - with: - name: kkfileview-server-jar - path: server/target/kkFileView-*.jar - retention-days: 7 - deploy-windows: - needs: build runs-on: ubuntu-22.04 env: - GITHUB_REPOSITORY_NAME: ${{ github.repository }} - GITHUB_RUN_ID_VALUE: ${{ github.run_id }} KK_DEPLOY_HOST: ${{ secrets.KK_DEPLOY_HOST }} KK_DEPLOY_PORT: ${{ secrets.KK_DEPLOY_PORT }} KK_DEPLOY_USERNAME: ${{ secrets.KK_DEPLOY_USERNAME }} KK_DEPLOY_PASSWORD: ${{ secrets.KK_DEPLOY_PASSWORD }} KK_DEPLOY_ROOT: ${{ secrets.KK_DEPLOY_ROOT }} KK_DEPLOY_HEALTH_URL: ${{ secrets.KK_DEPLOY_HEALTH_URL }} - KK_DEPLOY_ARTIFACT_NAME: kkfileview-server-jar + KK_DEPLOY_REPO_URL: ${{ vars.KK_DEPLOY_REPO_URL }} + KK_DEPLOY_BRANCH: ${{ vars.KK_DEPLOY_BRANCH }} + KK_DEPLOY_SOURCE_ROOT: ${{ vars.KK_DEPLOY_SOURCE_ROOT }} + KK_DEPLOY_JAVA_HOME: ${{ vars.KK_DEPLOY_JAVA_HOME }} + KK_DEPLOY_GIT_EXE: ${{ vars.KK_DEPLOY_GIT_EXE }} + KK_DEPLOY_MVN_CMD: ${{ vars.KK_DEPLOY_MVN_CMD }} + KK_DEPLOY_MAVEN_SETTINGS: ${{ vars.KK_DEPLOY_MAVEN_SETTINGS }} steps: - name: Checkout repository @@ -70,26 +48,5 @@ jobs: test -n "$KK_DEPLOY_USERNAME" || (echo "Missing secret: KK_DEPLOY_USERNAME" && exit 1) test -n "$KK_DEPLOY_PASSWORD" || (echo "Missing secret: KK_DEPLOY_PASSWORD" && exit 1) - - name: Resolve artifact download URL - env: - GH_TOKEN: ${{ github.token }} - run: | - artifact_json=$(curl -fsSL \ - -H "Authorization: Bearer $GH_TOKEN" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/$GITHUB_REPOSITORY_NAME/actions/runs/$GITHUB_RUN_ID_VALUE/artifacts") - artifact_id=$(ARTIFACT_JSON="$artifact_json" ARTIFACT_NAME="$KK_DEPLOY_ARTIFACT_NAME" python -c "import json, os; payload=json.loads(os.environ['ARTIFACT_JSON']); name=os.environ['ARTIFACT_NAME']; matches=[artifact for artifact in payload.get('artifacts', []) if artifact.get('name') == name]; matches or (_ for _ in ()).throw(SystemExit(f\"Artifact '{name}' not found for run\")); len(matches) == 1 or (_ for _ in ()).throw(SystemExit(f\"Expected one artifact named '{name}', found {len(matches)}\")); print(matches[0]['id'])") - headers_file=$(mktemp) - curl -fsS -D "$headers_file" -o /dev/null \ - -H "Authorization: Bearer $GH_TOKEN" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/$GITHUB_REPOSITORY_NAME/actions/artifacts/$artifact_id/zip" - artifact_url=$(awk 'BEGIN{IGNORECASE=1} /^location:/ { sub(/\r$/, "", $0); print substr($0, index($0, ":") + 2); exit }' "$headers_file") - test -n "$artifact_url" || (echo "Failed to resolve artifact download redirect URL" && exit 1) - rm -f "$headers_file" - echo "KK_DEPLOY_ARTIFACT_URL=$artifact_url" >> "$GITHUB_ENV" - - name: Deploy to Windows server run: python .github/scripts/deploy_windows_winrm.py diff --git a/doc/ci-auto-deploy.md b/doc/ci-auto-deploy.md index 4c4dfdcf..fc7ccdc5 100644 --- a/doc/ci-auto-deploy.md +++ b/doc/ci-auto-deploy.md @@ -8,17 +8,14 @@ - 运行配置:`C:\kkFileView-5.0\config\test.properties` - 健康检查地址:`http://127.0.0.1:8012/` -服务器当前没有安装 `git` 和 `mvn`,因此自动部署链路采用: +当前自动部署链路采用服务器拉最新源码并本机编译的方式: -1. GitHub Actions 在 `master` 合并后构建 `kkFileView-*.jar` -2. 由 GitHub Actions runner 解析当前 workflow artifact 的临时下载地址 -3. 通过 WinRM 连接 Windows 服务器 -4. 由服务器通过临时下载地址拉取 jar artifact -5. 备份线上 jar,替换为新版本 -6. 使用现有 `startup.bat` 重启,并做健康检查 -7. 如果健康检查失败,则自动回滚旧 jar 并重新拉起 - -这样做的目的是不把 GitHub token 下发到生产服务器,服务器只接触一次性 artifact 下载链接。 +1. 通过 WinRM 连接 Windows 服务器 +2. 在服务器上的源码目录执行 `git fetch/reset/clean`,同步到 `origin/$KK_DEPLOY_BRANCH`(默认 `master`) +3. 使用服务器上的 JDK 21 和 Maven 执行 `mvn clean package -Dmaven.test.skip=true` +4. 备份线上 jar,替换为新构建产物 +5. 使用现有 `startup.bat` 重启,并做健康检查 +6. 如果健康检查失败,则自动回滚旧 jar 并重新拉起 ## 需要配置的 GitHub Secrets @@ -26,16 +23,35 @@ - `KK_DEPLOY_USERNAME` - `KK_DEPLOY_PASSWORD` -下面这些可以不配,未配置时会使用默认值: +以下部署参数当前由 workflow 从 GitHub Secrets 读取;如果未单独配置,则使用脚本默认值: - `KK_DEPLOY_PORT=5985` - `KK_DEPLOY_ROOT=C:\kkFileView-5.0` - `KK_DEPLOY_HEALTH_URL=http://127.0.0.1:8012/` +下面这些非敏感参数可以通过 workflow env 或 GitHub Variables 覆盖;未配置时会使用默认值: +- `KK_DEPLOY_REPO_URL=https://github.com/kekingcn/kkFileView.git` +- `KK_DEPLOY_BRANCH=master` +- `KK_DEPLOY_SOURCE_ROOT=C:\kkFileView-source` +- `KK_DEPLOY_JAVA_HOME=C:\Program Files\jdk-21.0.2` +- `KK_DEPLOY_GIT_EXE=C:\kkFileView-tools\git\cmd\git.exe` +- `KK_DEPLOY_MVN_CMD=C:\kkFileView-tools\maven\bin\mvn.cmd` +- `KK_DEPLOY_MAVEN_SETTINGS=` + +如果服务器到 GitHub 的拉取速度不稳定,也可以把 `KK_DEPLOY_REPO_URL` 改成你自己的 Git 镜像地址。 +如果服务器访问 Maven Central 不稳定,也可以通过 `KK_DEPLOY_MAVEN_SETTINGS` 指向自定义 `settings.xml`,切换到就近镜像仓库。 + +## 服务器前置环境 + +服务器需要具备以下工具: + +- Git for Windows(推荐安装在 `C:\kkFileView-tools\git`) +- Apache Maven 3.9.x(推荐安装在 `C:\kkFileView-tools\maven`) +- JDK 21(当前线上已存在:`C:\Program Files\jdk-21.0.2`) + ## Workflow 新增 workflow:`.github/workflows/master-auto-deploy.yml` - 触发条件:`push` 到 `master`,或手动 `workflow_dispatch` -- 构建产物:`kkfileview-server-jar` -- 部署方式:WinRM + runner 侧解析 artifact 临时下载地址 + Windows 服务器拉取 artifact +- 部署方式:WinRM + 服务器源码同步 + 服务器本机 Maven 编译 + jar 替换/回滚