no message
This commit is contained in:
+212
-52
@@ -1,8 +1,9 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$SourceDir = "server",
|
||||
[string]$SourceDir = ".",
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$RemoteDir,
|
||||
[string]$UniappReleasePath = "",
|
||||
[string]$HostName = "sbnews",
|
||||
[string]$SshBin = "ssh.exe",
|
||||
[switch]$AutoIncremental,
|
||||
@@ -181,7 +182,9 @@ function Start-ProcessWithInputText {
|
||||
|
||||
$inputFile = [System.IO.Path]::GetTempFileName()
|
||||
try {
|
||||
[System.IO.File]::WriteAllText($inputFile, $InputText, $Utf8NoBom)
|
||||
# Remote shells like `bash -s` choke on Windows CRLF in stdin scripts.
|
||||
$normalizedInputText = $InputText.Replace("`r`n", "`n").Replace("`r", "`n")
|
||||
[System.IO.File]::WriteAllText($inputFile, $normalizedInputText, $Utf8NoBom)
|
||||
Start-ProcessWithInputFile -FilePath $FilePath -Arguments $Arguments -InputFile $inputFile
|
||||
} finally {
|
||||
Remove-Item -LiteralPath $inputFile -Force -ErrorAction SilentlyContinue
|
||||
@@ -195,13 +198,123 @@ function Remove-IfExists {
|
||||
}
|
||||
}
|
||||
|
||||
function Test-IsRepoRootDeploy {
|
||||
return ($SourceDir -eq "." -or [string]::IsNullOrWhiteSpace($SourceDir))
|
||||
}
|
||||
|
||||
function Get-SourceLabel {
|
||||
if (Test-IsRepoRootDeploy) {
|
||||
return "repo-root"
|
||||
}
|
||||
return $SourceDir
|
||||
}
|
||||
|
||||
function Get-DeployPathspec {
|
||||
if (Test-IsRepoRootDeploy) {
|
||||
return @($FullIncludePaths)
|
||||
}
|
||||
if ([string]::IsNullOrEmpty($GitPathPrefix)) {
|
||||
return @(".")
|
||||
}
|
||||
return @($GitPathPrefix)
|
||||
}
|
||||
|
||||
function Get-FullIncludePaths {
|
||||
switch ($SourceDir.ToLowerInvariant()) {
|
||||
"." {
|
||||
return @("server", "uniapp", "admin", "docker")
|
||||
}
|
||||
"server" {
|
||||
return @("app", "config", "extend", "public", "route")
|
||||
}
|
||||
"uniapp" {
|
||||
return @(".")
|
||||
}
|
||||
default {
|
||||
return @(".")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ArchiveExcludePatterns {
|
||||
$patterns = @(
|
||||
".git",
|
||||
".idea",
|
||||
".vscode",
|
||||
".tmp",
|
||||
".hbuilderx",
|
||||
".gitignore",
|
||||
"*.log",
|
||||
"release-*.zip",
|
||||
"*.zip",
|
||||
"__pycache__",
|
||||
"*.pyc",
|
||||
"node_modules",
|
||||
"dist"
|
||||
)
|
||||
|
||||
switch ($SourceDir.ToLowerInvariant()) {
|
||||
"." {
|
||||
$patterns += @("uniapp/node_modules", "uniapp/dist", "admin/node_modules", "admin/dist")
|
||||
if (-not $IncludeEnv) {
|
||||
$patterns += "server/.env"
|
||||
}
|
||||
if (-not $IncludeVendor) {
|
||||
$patterns += "server/vendor"
|
||||
}
|
||||
if (-not $IncludeRuntime) {
|
||||
$patterns += "server/runtime"
|
||||
}
|
||||
if (-not $IncludeUploads) {
|
||||
$patterns += "server/public/uploads"
|
||||
}
|
||||
if (-not $IncludePublicBuilds) {
|
||||
$patterns += @("server/public/admin", "server/public/mobile")
|
||||
}
|
||||
if (-not $IncludeCrawlerData) {
|
||||
$patterns += @(
|
||||
"server/public/dongqiudi-crawler/data",
|
||||
"server/public/dongqiudi-crawler/logs",
|
||||
"server/public/dongqiudi-crawler/venv",
|
||||
"server/public/dongqiudi-crawler/__pycache__"
|
||||
)
|
||||
}
|
||||
}
|
||||
"server" {
|
||||
if (-not $IncludeEnv) {
|
||||
$patterns += ".env"
|
||||
}
|
||||
if (-not $IncludeVendor) {
|
||||
$patterns += "vendor"
|
||||
}
|
||||
if (-not $IncludeRuntime) {
|
||||
$patterns += "runtime"
|
||||
}
|
||||
if (-not $IncludeUploads) {
|
||||
$patterns += "public/uploads"
|
||||
}
|
||||
if (-not $IncludePublicBuilds) {
|
||||
$patterns += @("public/admin", "public/mobile")
|
||||
}
|
||||
if (-not $IncludeCrawlerData) {
|
||||
$patterns += @(
|
||||
"public/dongqiudi-crawler/data",
|
||||
"public/dongqiudi-crawler/logs",
|
||||
"public/dongqiudi-crawler/venv",
|
||||
"public/dongqiudi-crawler/__pycache__"
|
||||
)
|
||||
}
|
||||
}
|
||||
"uniapp" {
|
||||
if (-not $IncludeEnv) {
|
||||
$patterns += ".env"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return @($patterns)
|
||||
}
|
||||
|
||||
function Commit-SourceChangesIfNeeded {
|
||||
param(
|
||||
[string]$Repository,
|
||||
@@ -220,12 +333,12 @@ function Commit-SourceChangesIfNeeded {
|
||||
|
||||
$unmerged = @($statusLines | Where-Object { $_ -match "^(DD|AU|UD|UA|DU|AA|UU)" })
|
||||
if ($unmerged.Count -gt 0) {
|
||||
Write-DeployLog "unmerged changes detected under ${SourceDir}:"
|
||||
Write-DeployLog "unmerged changes detected under $(Get-SourceLabel):"
|
||||
$unmerged | Select-Object -First 20 | ForEach-Object { Write-Host " $_" }
|
||||
Fail "resolve merge conflicts under $SourceDir before deploy"
|
||||
Fail "resolve merge conflicts under $(Get-SourceLabel) before deploy"
|
||||
}
|
||||
|
||||
Write-DeployLog "uncommitted changes detected under $SourceDir; auto committing before deploy:"
|
||||
Write-DeployLog "uncommitted changes detected under $(Get-SourceLabel); auto committing before deploy:"
|
||||
$maxDisplay = 80
|
||||
$statusLines | Select-Object -First $maxDisplay | ForEach-Object { Write-Host " $_" }
|
||||
if ($statusLines.Count -gt $maxDisplay) {
|
||||
@@ -234,9 +347,18 @@ function Commit-SourceChangesIfNeeded {
|
||||
|
||||
Invoke-Native "git" (@("-C", $Repository, "add", "-A", "--") + $Pathspec)
|
||||
|
||||
& git -C $Repository diff --cached --quiet -- $Pathspec
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-DeployLog "no committable root changes detected after git add; continue with current working tree payload"
|
||||
return
|
||||
}
|
||||
if ($LASTEXITCODE -ne 1) {
|
||||
Fail "git diff --cached failed"
|
||||
}
|
||||
|
||||
$commitMessage = $AutoCommitMessage
|
||||
if ([string]::IsNullOrWhiteSpace($commitMessage)) {
|
||||
$commitMessage = "deploy: auto commit $SourceDir changes $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
||||
$commitMessage = "deploy: auto commit $(Get-SourceLabel) changes $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
||||
}
|
||||
|
||||
Invoke-Native "git" (@("-C", $Repository, "commit", "-m", $commitMessage, "--") + $Pathspec)
|
||||
@@ -244,55 +366,42 @@ function Commit-SourceChangesIfNeeded {
|
||||
Write-DeployLog "auto commit created: $newCommit"
|
||||
}
|
||||
|
||||
function Copy-FullPayload {
|
||||
Write-DeployLog "building full payload from current working tree: $SourceDir"
|
||||
Write-DeployLog "full include paths: $($FullIncludePaths -join ' ')"
|
||||
function Copy-WorkingTreePayloadPaths {
|
||||
param(
|
||||
[string[]]$IncludePaths,
|
||||
[string]$Reason
|
||||
)
|
||||
|
||||
if ($IncludePaths.Count -eq 0) {
|
||||
return
|
||||
}
|
||||
|
||||
Write-DeployLog $Reason
|
||||
Write-DeployLog "working tree include paths: $($IncludePaths -join ' ')"
|
||||
|
||||
$payloadTar = Join-Path $WorkDir "payload-copy.tar"
|
||||
$tarArgs = @(
|
||||
"-cf", $payloadTar,
|
||||
"-C", $SourceAbs,
|
||||
"--exclude=.git",
|
||||
"--exclude=.idea",
|
||||
"--exclude=.vscode",
|
||||
"--exclude=.tmp",
|
||||
"--exclude=.gitignore",
|
||||
"--exclude=*.log",
|
||||
"--exclude=release-*.zip",
|
||||
"--exclude=*.zip",
|
||||
"--exclude=__pycache__",
|
||||
"--exclude=*.pyc"
|
||||
"-C", $SourceAbs
|
||||
)
|
||||
|
||||
if (-not $IncludeEnv) {
|
||||
$tarArgs += "--exclude=.env"
|
||||
}
|
||||
if (-not $IncludeVendor) {
|
||||
$tarArgs += "--exclude=vendor"
|
||||
}
|
||||
if (-not $IncludeRuntime) {
|
||||
$tarArgs += "--exclude=runtime"
|
||||
}
|
||||
if (-not $IncludeUploads) {
|
||||
$tarArgs += "--exclude=public/uploads"
|
||||
}
|
||||
if (-not $IncludePublicBuilds) {
|
||||
$tarArgs += @("--exclude=public/admin", "--exclude=public/mobile")
|
||||
}
|
||||
if (-not $IncludeCrawlerData) {
|
||||
$tarArgs += @(
|
||||
"--exclude=public/dongqiudi-crawler/data",
|
||||
"--exclude=public/dongqiudi-crawler/logs",
|
||||
"--exclude=public/dongqiudi-crawler/venv",
|
||||
"--exclude=public/dongqiudi-crawler/__pycache__"
|
||||
)
|
||||
foreach ($pattern in (Get-ArchiveExcludePatterns)) {
|
||||
if (-not [string]::IsNullOrWhiteSpace($pattern)) {
|
||||
$tarArgs += "--exclude=$pattern"
|
||||
}
|
||||
}
|
||||
|
||||
$tarArgs += $FullIncludePaths
|
||||
$tarArgs += $IncludePaths
|
||||
Invoke-Native "tar" $tarArgs
|
||||
Invoke-Native "tar" @("-xf", $payloadTar, "-C", $PayloadDir)
|
||||
}
|
||||
|
||||
function Copy-FullPayload {
|
||||
Copy-WorkingTreePayloadPaths `
|
||||
-IncludePaths $FullIncludePaths `
|
||||
-Reason "building full payload from current working tree: $(Get-SourceLabel)"
|
||||
}
|
||||
|
||||
function Strip-SourcePrefix {
|
||||
param([string]$Path)
|
||||
if ([string]::IsNullOrEmpty($GitPathPrefix)) {
|
||||
@@ -308,6 +417,9 @@ function Strip-SourcePrefix {
|
||||
function Test-DeployIncludedPath {
|
||||
param([string]$RelativePath)
|
||||
foreach ($include in $FullIncludePaths) {
|
||||
if ($include -eq ".") {
|
||||
return $true
|
||||
}
|
||||
if ($RelativePath -eq $include -or $RelativePath.StartsWith("$include/")) {
|
||||
return $true
|
||||
}
|
||||
@@ -315,6 +427,25 @@ function Test-DeployIncludedPath {
|
||||
return $false
|
||||
}
|
||||
|
||||
function Get-RootGitLinkIncludePaths {
|
||||
if (-not (Test-IsRepoRootDeploy)) {
|
||||
return @()
|
||||
}
|
||||
|
||||
$lsFiles = @(& git -C $RepoRoot ls-files -s -- $FullIncludePaths)
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Fail "git ls-files failed"
|
||||
}
|
||||
|
||||
return @(
|
||||
$lsFiles |
|
||||
Where-Object { $_ -match "^160000\s+\S+\s+\d+\t(.+)$" } |
|
||||
ForEach-Object { $Matches[1] } |
|
||||
Where-Object { Test-DeployIncludedPath $_ } |
|
||||
Sort-Object -Unique
|
||||
)
|
||||
}
|
||||
|
||||
function Test-UnderSourceDir {
|
||||
param([string]$GitPath)
|
||||
if ([string]::IsNullOrEmpty($GitPathPrefix)) {
|
||||
@@ -401,6 +532,11 @@ function Build-IncrementalPayload {
|
||||
return
|
||||
}
|
||||
|
||||
$rootGitLinkPayloadPaths = @()
|
||||
if (Test-IsRepoRootDeploy) {
|
||||
$rootGitLinkPayloadPaths = @($RootGitLinkIncludePaths)
|
||||
}
|
||||
|
||||
$diffArgs = @("-C", $GitCwd, "diff", "--name-status", "--find-renames", $FromCommit, $ToCommit)
|
||||
if (-not [string]::IsNullOrEmpty($GitPathPrefix)) {
|
||||
$diffArgs += @("--", $GitPathPrefix)
|
||||
@@ -448,11 +584,15 @@ function Build-IncrementalPayload {
|
||||
}
|
||||
}
|
||||
|
||||
$script:ChangedDisplayPaths = @($script:ChangedDisplayPaths | Sort-Object -Unique)
|
||||
$script:DeletedDisplayPaths = @($script:DeletedDisplayPaths | Sort-Object -Unique)
|
||||
$changedGitPaths = @($changedGitPaths | Sort-Object -Unique)
|
||||
|
||||
if ($changedGitPaths.Count -eq 0 -and $script:DeletedDisplayPaths.Count -eq 0) {
|
||||
if ($rootGitLinkPayloadPaths.Count -gt 0) {
|
||||
$script:ChangedDisplayPaths += @($rootGitLinkPayloadPaths | ForEach-Object { "$_/" })
|
||||
}
|
||||
$script:ChangedDisplayPaths = @($script:ChangedDisplayPaths | Sort-Object -Unique)
|
||||
|
||||
if ($changedGitPaths.Count -eq 0 -and $script:DeletedDisplayPaths.Count -eq 0 -and $rootGitLinkPayloadPaths.Count -eq 0) {
|
||||
Write-DeployLog "no changed files detected between $FromCommit and $ToCommit under $SourceDir"
|
||||
$script:NoChanges = $true
|
||||
return
|
||||
@@ -477,11 +617,18 @@ function Build-IncrementalPayload {
|
||||
Get-ChildItem -LiteralPath $extractSource -Force | Copy-Item -Destination $PayloadDir -Recurse -Force
|
||||
}
|
||||
}
|
||||
|
||||
if ($rootGitLinkPayloadPaths.Count -gt 0) {
|
||||
Copy-WorkingTreePayloadPaths `
|
||||
-IncludePaths $rootGitLinkPayloadPaths `
|
||||
-Reason "building working tree payload for root gitlink include paths"
|
||||
}
|
||||
}
|
||||
|
||||
$SourceDir = Normalize-DeployDir $SourceDir
|
||||
$RemoteDir = Normalize-DeployDir $RemoteDir
|
||||
$RemoteTmp = Normalize-DeployDir $RemoteTmp
|
||||
$SourceLabel = Get-SourceLabel
|
||||
|
||||
if ($AutoIncremental -and ($From -or $To)) {
|
||||
Fail "-AutoIncremental cannot be used with -From/-To"
|
||||
@@ -519,7 +666,7 @@ if (-not (Test-Path -LiteralPath $SourceAbs -PathType Container)) {
|
||||
Fail "source directory not found: $SourceDir"
|
||||
}
|
||||
|
||||
$FullIncludePaths = @("app", "config", "extend", "public", "route")
|
||||
$FullIncludePaths = @(Get-FullIncludePaths)
|
||||
$GitCwd = $RepoRoot
|
||||
$GitPathPrefix = $SourceDir
|
||||
$SourceIsGitRepo = $false
|
||||
@@ -543,6 +690,10 @@ if (-not $SourceIsGitRepo -and ($lsFiles | Where-Object { $_ -match "^160000\s"
|
||||
}
|
||||
|
||||
$DeployPathspec = @(Get-DeployPathspec)
|
||||
$RootGitLinkIncludePaths = @(Get-RootGitLinkIncludePaths)
|
||||
if ($RootGitLinkIncludePaths.Count -gt 0) {
|
||||
Write-DeployLog "root gitlink include paths will be copied from working tree: $($RootGitLinkIncludePaths -join ' ')"
|
||||
}
|
||||
Commit-SourceChangesIfNeeded -Repository $GitCwd -Pathspec $DeployPathspec
|
||||
|
||||
if ($Mode -eq "incremental") {
|
||||
@@ -564,7 +715,7 @@ $WorkDir = Join-Path $TempRoot ("deploy-server-" + [System.Guid]::NewGuid().ToSt
|
||||
$PackageRoot = Join-Path $WorkDir "package"
|
||||
$PayloadDir = Join-Path $PackageRoot "payload"
|
||||
$ExtractDir = Join-Path $WorkDir "extract"
|
||||
$ArchivePath = Join-Path $WorkDir ("{0}-{1}.tar.gz" -f ($SourceDir -replace "[\\/]", "-"), $Mode)
|
||||
$ArchivePath = Join-Path $WorkDir ("{0}-{1}.tar.gz" -f $SourceLabel, $Mode)
|
||||
$DeletedPathsFile = Join-Path $PackageRoot ".deleted-paths.txt"
|
||||
$DeployInfoFile = Join-Path $PackageRoot ".deploy-info.txt"
|
||||
$script:ChangedDisplayPaths = @()
|
||||
@@ -588,9 +739,10 @@ try {
|
||||
|
||||
$deployInfo = @(
|
||||
"mode=$Mode",
|
||||
"source_dir=$SourceDir",
|
||||
"source_dir=$SourceLabel",
|
||||
"host=$HostName",
|
||||
"remote_dir=$RemoteDir",
|
||||
"uniapp_release_path=$UniappReleasePath",
|
||||
"built_at=$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
||||
)
|
||||
if ($Mode -eq "incremental") {
|
||||
@@ -619,8 +771,8 @@ try {
|
||||
|
||||
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
$pidValue = $PID
|
||||
$remoteWorkDir = "$RemoteTmp/$($SourceDir -replace '[\\/]', '-')-deploy-$timestamp-$pidValue"
|
||||
$remoteArchive = "$RemoteTmp/$($SourceDir -replace '[\\/]', '-')-$Mode-$timestamp.tar.gz"
|
||||
$remoteWorkDir = "$RemoteTmp/$SourceLabel-deploy-$timestamp-$pidValue"
|
||||
$remoteArchive = "$RemoteTmp/$SourceLabel-$Mode-$timestamp.tar.gz"
|
||||
|
||||
$remoteTmpQ = ConvertTo-RemoteSingleQuoted $RemoteTmp
|
||||
$remoteArchiveQ = ConvertTo-RemoteSingleQuoted $remoteArchive
|
||||
@@ -640,6 +792,7 @@ try {
|
||||
"REMOTE_DIR=$(ConvertTo-RemoteSingleQuoted $RemoteDir)",
|
||||
"REMOTE_ARCHIVE=$(ConvertTo-RemoteSingleQuoted $remoteArchive)",
|
||||
"REMOTE_WORK_DIR=$(ConvertTo-RemoteSingleQuoted $remoteWorkDir)",
|
||||
"UNIAPP_RELEASE_PATH=$(ConvertTo-RemoteSingleQuoted $UniappReleasePath)",
|
||||
"KEEP_REMOTE_TEMP='$keepRemoteTempValue'",
|
||||
"POST_INSTALL_B64='$postInstallB64'",
|
||||
"USE_SUDO='$useSudoValue'",
|
||||
@@ -762,8 +915,15 @@ if [[ -n "${POST_INSTALL_B64:-}" ]]; then
|
||||
remote_log "run post-install command"
|
||||
POST_INSTALL_CMD="$(printf '%s' "$POST_INSTALL_B64" | base64 -d)"
|
||||
cd "$REMOTE_DIR"
|
||||
if [[ -n "${UNIAPP_RELEASE_PATH:-}" ]]; then
|
||||
export UNIAPP_RELEASE_PATH
|
||||
fi
|
||||
if [[ "${USE_SUDO:-0}" == "1" ]]; then
|
||||
sudo bash -lc "$POST_INSTALL_CMD"
|
||||
if [[ -n "${UNIAPP_RELEASE_PATH:-}" ]]; then
|
||||
sudo env UNIAPP_RELEASE_PATH="$UNIAPP_RELEASE_PATH" bash -lc "$POST_INSTALL_CMD"
|
||||
else
|
||||
sudo bash -lc "$POST_INSTALL_CMD"
|
||||
fi
|
||||
else
|
||||
bash -lc "$POST_INSTALL_CMD"
|
||||
fi
|
||||
@@ -782,7 +942,7 @@ remote_log "remote install finished"
|
||||
|
||||
Write-DeployLog "deploy finished"
|
||||
Write-DeployLog "mode: $Mode"
|
||||
Write-DeployLog "source: $SourceDir"
|
||||
Write-DeployLog "source: $SourceLabel"
|
||||
Write-DeployLog "remote: ${HostName}:$RemoteDir"
|
||||
} finally {
|
||||
if ($WorkDir -and (Test-Path -LiteralPath $WorkDir)) {
|
||||
|
||||
Reference in New Issue
Block a user