Initial commit
This commit is contained in:
+346
@@ -0,0 +1,346 @@
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Version,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ZipPath,
|
||||
|
||||
[string]$ReportsZipPath = "",
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$TargetId,
|
||||
|
||||
[string]$TargetsPath = ""
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Write-Step {
|
||||
param([string]$Message)
|
||||
Write-Host "[INFO] $Message"
|
||||
}
|
||||
|
||||
function Write-Success {
|
||||
param([string]$Message)
|
||||
Write-Host "[SUCCESS] $Message"
|
||||
}
|
||||
|
||||
function Get-ToolPath {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$FileName,
|
||||
|
||||
[string[]]$FallbackPaths = @()
|
||||
)
|
||||
|
||||
$localPath = Join-Path $PSScriptRoot $FileName
|
||||
if (Test-Path $localPath) { return $localPath }
|
||||
|
||||
foreach ($path in $FallbackPaths) {
|
||||
if (Test-Path $path) { return $path }
|
||||
}
|
||||
|
||||
$command = Get-Command $FileName -ErrorAction SilentlyContinue
|
||||
if ($command) { return $command.Source }
|
||||
|
||||
throw "No se encontro $FileName. Copialo junto a la app o instalalo con PuTTY."
|
||||
}
|
||||
|
||||
function Get-ZipEntryNames {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
$zip = [System.IO.Compression.ZipFile]::OpenRead($Path)
|
||||
try {
|
||||
return @(
|
||||
$zip.Entries |
|
||||
Where-Object { -not [string]::IsNullOrWhiteSpace($_.FullName) } |
|
||||
ForEach-Object { $_.FullName.Replace("\", "/") } |
|
||||
Where-Object {
|
||||
$_ -and
|
||||
$_ -notmatch "^__MACOSX/" -and
|
||||
$_ -notmatch "(^|/)\.DS_Store$"
|
||||
}
|
||||
)
|
||||
}
|
||||
finally {
|
||||
$zip.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
function ConvertTo-ShellArg {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Value
|
||||
)
|
||||
|
||||
$singleQuote = [string][char]39
|
||||
return $singleQuote + $Value.Replace($singleQuote, "$singleQuote\$singleQuote$singleQuote") + $singleQuote
|
||||
}
|
||||
|
||||
function Invoke-Plink {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Command
|
||||
)
|
||||
|
||||
& $script:Plink -ssh "$($script:Target.user)@$($script:Target.host)" -P $script:Target.port -pw $script:Target.password -batch $Command 2>&1
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($TargetsPath)) {
|
||||
$TargetsPath = Join-Path $PSScriptRoot "targets.json"
|
||||
}
|
||||
|
||||
if (-not (Test-Path $TargetsPath)) {
|
||||
throw "No se encontro el archivo de destinos: $TargetsPath"
|
||||
}
|
||||
|
||||
if (-not (Test-Path $ZipPath)) {
|
||||
throw "No se encontro el ZIP principal: $ZipPath"
|
||||
}
|
||||
|
||||
$targetsConfig = Get-Content -Raw -Path $TargetsPath | ConvertFrom-Json
|
||||
$targetMatches = @($targetsConfig.targets | Where-Object { $_.id -eq $TargetId })
|
||||
if ($targetMatches.Count -eq 0) {
|
||||
throw "No existe el destino seleccionado: $TargetId"
|
||||
}
|
||||
|
||||
$script:Target = $targetMatches[0]
|
||||
$script:Plink = Get-ToolPath -FileName "plink.exe" -FallbackPaths @(
|
||||
"C:\Program Files\PuTTY\plink.exe",
|
||||
"C:\Program Files (x86)\PuTTY\plink.exe"
|
||||
)
|
||||
$pscp = Get-ToolPath -FileName "pscp.exe" -FallbackPaths @(
|
||||
"C:\Program Files\PuTTY\pscp.exe",
|
||||
"C:\Program Files (x86)\PuTTY\pscp.exe"
|
||||
)
|
||||
|
||||
$zipFileName = Split-Path -Leaf $ZipPath
|
||||
$reportesFolderName = "reportes_subidos_jasper"
|
||||
$hasReportsZipPath = -not [string]::IsNullOrWhiteSpace($ReportsZipPath)
|
||||
|
||||
if ($hasReportsZipPath -and -not (Test-Path $ReportsZipPath)) {
|
||||
throw "No se encontro el ZIP de reportes: $ReportsZipPath"
|
||||
}
|
||||
|
||||
Write-Step "Version indicada: $Version"
|
||||
Write-Step "Destino: $($Target.name) ($($Target.host):$($Target.port))"
|
||||
Write-Step "Validando estructura del ZIP principal..."
|
||||
|
||||
$zipEntryNames = Get-ZipEntryNames -Path $ZipPath
|
||||
if ($zipEntryNames.Count -eq 0) {
|
||||
throw "El ZIP principal esta vacio: $ZipPath"
|
||||
}
|
||||
|
||||
$topLevelNames = @(
|
||||
$zipEntryNames |
|
||||
ForEach-Object { ($_ -split "/", 2)[0] } |
|
||||
Where-Object { $_ } |
|
||||
Sort-Object -Unique
|
||||
)
|
||||
|
||||
$topLevelFiles = @(
|
||||
$zipEntryNames |
|
||||
Where-Object { ($_ -notmatch "/") -and (-not $_.EndsWith("/")) }
|
||||
)
|
||||
|
||||
$zipRootPrefix = $null
|
||||
if (($topLevelNames.Count -eq 1) -and ($topLevelFiles.Count -eq 0)) {
|
||||
$zipRootPrefix = $topLevelNames[0]
|
||||
Write-Step "El ZIP contiene una carpeta raiz ($zipRootPrefix). Se desplegara su contenido."
|
||||
}
|
||||
|
||||
$deployEntryNames = $zipEntryNames
|
||||
if ($zipRootPrefix) {
|
||||
$rootPrefixPattern = "^" + [regex]::Escape($zipRootPrefix.TrimEnd("/")) + "/"
|
||||
$deployEntryNames = @(
|
||||
$zipEntryNames |
|
||||
Where-Object { $_ -match $rootPrefixPattern } |
|
||||
ForEach-Object { $_ -replace $rootPrefixPattern, "" } |
|
||||
Where-Object { $_ }
|
||||
)
|
||||
}
|
||||
|
||||
$deployTopLevelFolders = @(
|
||||
$deployEntryNames |
|
||||
Where-Object { $_ -match "/" } |
|
||||
ForEach-Object { ($_ -split "/", 2)[0] } |
|
||||
Where-Object { $_ } |
|
||||
Sort-Object -Unique
|
||||
)
|
||||
|
||||
if ($deployTopLevelFolders.Count -le 1) {
|
||||
throw "El contenido a desplegar debe tener mas de una carpeta en el nivel padre."
|
||||
}
|
||||
|
||||
$hasReportesFolder = @(
|
||||
$deployEntryNames |
|
||||
Where-Object {
|
||||
$_ -eq "$reportesFolderName/" -or
|
||||
$_ -like "$reportesFolderName/*"
|
||||
}
|
||||
).Count -gt 0
|
||||
|
||||
$needsReportesZip = -not $hasReportesFolder
|
||||
$reportesZipExtractMode = "direct"
|
||||
$reportesZipName = ""
|
||||
|
||||
if ($needsReportesZip) {
|
||||
if (-not $hasReportsZipPath) {
|
||||
Write-Step "El ZIP no incluye $reportesFolderName y no se selecciono ZIP auxiliar. Se continua sin reportes."
|
||||
}
|
||||
else {
|
||||
$reportesZipName = Split-Path -Leaf $ReportsZipPath
|
||||
$reportesEntryNames = Get-ZipEntryNames -Path $ReportsZipPath
|
||||
if ($reportesEntryNames.Count -eq 0) {
|
||||
throw "El ZIP de reportes esta vacio: $ReportsZipPath"
|
||||
}
|
||||
|
||||
$reportesZipHasFolder = @(
|
||||
$reportesEntryNames |
|
||||
Where-Object {
|
||||
$_ -eq "$reportesFolderName/" -or
|
||||
$_ -like "$reportesFolderName/*"
|
||||
}
|
||||
).Count -gt 0
|
||||
|
||||
if (-not $reportesZipHasFolder) {
|
||||
$reportesZipExtractMode = "into-folder"
|
||||
Write-Step "El ZIP de reportes no contiene carpeta raiz. Se extraera dentro de $reportesFolderName."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$remoteUploadPath = $Target.remoteUploadPath
|
||||
$remoteAppPath = $Target.remoteAppPath
|
||||
$backupDir = $Target.backupDir
|
||||
$jasperstarterPath = "$remoteAppPath/_lib/libraries/grp/composer/vendor/geekcom/phpjasper/bin/jasperstarter/bin/jasperstarter"
|
||||
$remoteTempPath = "$remoteUploadPath/gt_nova_deploy_tmp_$Version"
|
||||
$remoteZipPath = "$remoteUploadPath/$zipFileName"
|
||||
$remoteReportesZipPath = if ($reportesZipName) { "$remoteUploadPath/$reportesZipName" } else { "" }
|
||||
$remoteExtractSource = if ($zipRootPrefix) { "$remoteTempPath/$zipRootPrefix" } else { $remoteTempPath }
|
||||
|
||||
$remoteAppArg = ConvertTo-ShellArg $remoteAppPath
|
||||
$remoteTempArg = ConvertTo-ShellArg $remoteTempPath
|
||||
$remoteZipArg = ConvertTo-ShellArg $remoteZipPath
|
||||
$remoteExtractSourceArg = ConvertTo-ShellArg $remoteExtractSource
|
||||
$remoteReportesFolderArg = ConvertTo-ShellArg "$remoteAppPath/$reportesFolderName"
|
||||
$remoteReportesZipArg = if ($remoteReportesZipPath) { ConvertTo-ShellArg $remoteReportesZipPath } else { "" }
|
||||
$jasperstarterArg = ConvertTo-ShellArg $jasperstarterPath
|
||||
|
||||
Write-Step "Probando conexion SSH..."
|
||||
$connectionCheck = Invoke-Plink -Command "echo SSH_OK"
|
||||
if ($connectionCheck -notmatch "SSH_OK") {
|
||||
throw "No se pudo conectar por SSH. Salida: $connectionCheck"
|
||||
}
|
||||
Write-Success "Conexion SSH OK."
|
||||
|
||||
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||
$backupFileName = "backup_gt_nova_${Version}_$timestamp.tar.gz"
|
||||
$backupCommand = "mkdir -p $(ConvertTo-ShellArg $backupDir) && tar -czf $(ConvertTo-ShellArg "$backupDir/$backupFileName") -C /var/www/html $(Split-Path -Leaf $remoteAppPath) && echo BACKUP_OK"
|
||||
|
||||
Write-Step "Creando backup remoto..."
|
||||
$backupOutput = Invoke-Plink -Command $backupCommand
|
||||
if ($backupOutput -notmatch "BACKUP_OK") {
|
||||
throw "Error al crear backup remoto. Salida: $backupOutput"
|
||||
}
|
||||
Write-Success "Backup creado: $backupDir/$backupFileName"
|
||||
|
||||
Write-Step "Subiendo ZIP principal..."
|
||||
& $pscp -P $Target.port -pw $Target.password $ZipPath "$($Target.user)@$($Target.host):$remoteUploadPath/" 2>&1 | ForEach-Object { Write-Host $_ }
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Error al subir el ZIP principal."
|
||||
}
|
||||
Write-Success "ZIP principal subido."
|
||||
|
||||
$shouldUploadReportsZip = $needsReportesZip -and $hasReportsZipPath
|
||||
if ($shouldUploadReportsZip) {
|
||||
Write-Step "Subiendo ZIP auxiliar de reportes..."
|
||||
& $pscp -P $Target.port -pw $Target.password $ReportsZipPath "$($Target.user)@$($Target.host):$remoteUploadPath/" 2>&1 | ForEach-Object { Write-Host $_ }
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Error al subir el ZIP de reportes."
|
||||
}
|
||||
Write-Success "ZIP de reportes subido."
|
||||
}
|
||||
|
||||
$cmdReportes = ":"
|
||||
if ($shouldUploadReportsZip -and $reportesZipExtractMode -eq "direct") {
|
||||
$cmdReportes = "sudo unzip -oq $remoteReportesZipArg -d $remoteAppArg"
|
||||
}
|
||||
elseif ($shouldUploadReportsZip -and $reportesZipExtractMode -eq "into-folder") {
|
||||
$cmdReportes = @"
|
||||
sudo mkdir -p $remoteReportesFolderArg
|
||||
sudo unzip -oq $remoteReportesZipArg -d $remoteReportesFolderArg
|
||||
"@
|
||||
}
|
||||
|
||||
Write-Step "Descomprimiendo y reemplazando aplicacion..."
|
||||
$deployCommand = @"
|
||||
set -e
|
||||
sudo rm -rf $remoteTempArg
|
||||
sudo mkdir -p $remoteTempArg $remoteAppArg
|
||||
sudo unzip -q $remoteZipArg -d $remoteTempArg
|
||||
sudo find $remoteAppArg -mindepth 1 -maxdepth 1 -exec rm -rf {} +
|
||||
sudo cp -a $remoteExtractSourceArg/. $remoteAppArg/
|
||||
$cmdReportes
|
||||
sudo rm -rf $remoteTempArg
|
||||
echo UNZIP_OK
|
||||
"@
|
||||
|
||||
$deployOutput = Invoke-Plink -Command $deployCommand
|
||||
if ($deployOutput -notmatch "UNZIP_OK") {
|
||||
throw "Error al descomprimir o reemplazar aplicacion. Salida: $deployOutput"
|
||||
}
|
||||
Write-Success "Aplicacion reemplazada."
|
||||
|
||||
$serviceRestartLines = @()
|
||||
foreach ($service in @($Target.services)) {
|
||||
if (-not [string]::IsNullOrWhiteSpace($service)) {
|
||||
$serviceRestartLines += "sudo systemctl restart $(ConvertTo-ShellArg $service)"
|
||||
}
|
||||
}
|
||||
|
||||
$cleanupReportes = if ($shouldUploadReportsZip) { "sudo rm -f $remoteReportesZipArg" } else { ":" }
|
||||
$fixJasperstarterPermissions = ":"
|
||||
if ($Target.host -eq "4.246.183.98") {
|
||||
$fixJasperstarterPermissions = @"
|
||||
if [ -f $jasperstarterArg ]; then
|
||||
sudo chmod 755 $jasperstarterArg
|
||||
ls -l $jasperstarterArg
|
||||
else
|
||||
echo JASPERSTARTER_NOT_FOUND
|
||||
exit 1
|
||||
fi
|
||||
"@
|
||||
}
|
||||
|
||||
$postDeployCommand = @"
|
||||
set -e
|
||||
sudo chown -R www-data:www-data $remoteAppArg
|
||||
sudo find $remoteAppArg -type d -exec chmod 755 {} \;
|
||||
sudo find $remoteAppArg -type f -exec chmod 644 {} \;
|
||||
$fixJasperstarterPermissions
|
||||
$($serviceRestartLines -join "`n")
|
||||
sudo rm -f $remoteZipArg
|
||||
$cleanupReportes
|
||||
echo DEPLOY_OK
|
||||
"@
|
||||
|
||||
Write-Step "Aplicando permisos, reiniciando servicios y limpiando temporales..."
|
||||
$postDeployOutput = Invoke-Plink -Command $postDeployCommand
|
||||
if ($postDeployOutput -notmatch "DEPLOY_OK") {
|
||||
throw "El deploy reemplazo archivos, pero fallo el post-deploy. Salida: $postDeployOutput"
|
||||
}
|
||||
|
||||
if ($Target.host -eq "4.246.183.98") {
|
||||
if ($postDeployOutput -notmatch "jasperstarter") {
|
||||
throw "El deploy finalizo, pero no se pudo verificar el permiso de jasperstarter. Salida: $postDeployOutput"
|
||||
}
|
||||
|
||||
Write-Success "Permiso 755 aplicado a jasperstarter."
|
||||
}
|
||||
|
||||
Write-Success "Deploy finalizado correctamente para version $Version en $($Target.name)."
|
||||
Reference in New Issue
Block a user