From 7b32bfada8cb191e37cbaa9c966c54b02a73c56a Mon Sep 17 00:00:00 2001 From: Kelly Michels Date: Fri, 21 Aug 2026 21:29:53 -0500 Subject: [PATCH] fix(zdeploy): docker kind now ships config subdirectories (#54) Invoke-DockerDeploy uploaded top-level files ONLY. For any stack that keeps configuration in a directory, that is silently wrong in the worst way: the compose file arrives, the containers restart, and the config they read is whatever was already on the box. The deploy reports success while shipping nothing that matters. The sharp case is a provisioning directory read at container start - alert rules, datasources, mounted config - where the restart makes it look like the change was applied. Same fix the edge kind already got: subdirectories ship recursively. Skipped are $JunkDirNames, plus .github (CI config belongs in the repo, never on a deploy target - it is not in $JunkDirNames because backups DO want it), plus anything the project lists in the new deploy.skipDirs. deploy.skipDirs exists for SERVER-SIDE STATE that shares the tree: a data/ holding mailboxes or a time-series database must never be overwritten by whatever the local checkout has - usually nothing, which is the dangerous case, since scp -r of an absent directory is not the no-op you want to rely on. CHECKSUMS.txt refreshed alongside. Tests: 222/222. --- CHECKSUMS.txt | 2 +- zdeploy.ps1 | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHECKSUMS.txt b/CHECKSUMS.txt index 45a73a0..4d6483f 100644 --- a/CHECKSUMS.txt +++ b/CHECKSUMS.txt @@ -8,7 +8,7 @@ dbd1b9c64fba16a308ffa8fa936f1bfda556b049aaa30ebe5400ca74b7e6aa5d zbackup_ec2.ps e03075f367a9ecee0f97438bc381044c74b7bd4e8cb4ff66b40048bba7ffd25a zchecksums.cmd 8382ad5f972405678b73616f608a80e3eb1814c927ba104e446d36c4f9f5c66d zchecksums.ps1 3d1064817ace57fe61c54104900775a0208fdf7e782043cced84b002347acb11 zdeploy.cmd -c7c7ee1019808356bc4bad738edcd4e851ea797e28fe367a88fcd96bc5570770 zdeploy.ps1 +c3b5eeac28cb4c17a8b74638466a7e8529af64dba79b11ad46b3d78c36b6b81f zdeploy.ps1 6fa05d7c47992801d0ad65095146764cc207b566dca85956b3152221ef9af368 zec2.cmd 72217c04e8975f46b489bd7e223f9fda926d982a8e418fc2825c6aa4657f73b7 zec2.ps1 d0702f372ec5e47e2632229c61b71a9184edf0775d6e23af74e3f919d13eadb9 zec2_rotatekeys.cmd diff --git a/zdeploy.ps1 b/zdeploy.ps1 index bfd1362..27c2fd3 100644 --- a/zdeploy.ps1 +++ b/zdeploy.ps1 @@ -776,6 +776,30 @@ function Invoke-DockerDeploy { if ($LASTEXITCODE -ne 0) { throw "SCP failed for $($f.Name) (exit $LASTEXITCODE)" } } + # Config subdirectories ship too, exactly as the edge kind does. Uploading + # top-level files ONLY was silently wrong for any stack that keeps config in + # a directory: the compose file arrives, the containers restart, and the + # config they read is whatever was already on the box. That is worse than a + # failed deploy, because it reports success - a provisioning directory read + # at container start (alert rules, datasources, mounted *.php) would never + # reflect the change you just deployed. + # + # Skipped: $JunkDirNames (.git, __pycache__, .pytest_cache, ...) plus + # anything the project lists in deploy.skipDirs. That list is how a stack + # protects SERVER-SIDE STATE that happens to share the tree - a data/ holding + # mailboxes or a time-series database must never be overwritten by whatever + # the local checkout has (usually nothing, which is the dangerous case). + # .github is CI config - it belongs in the repo and never on a deploy + # target. It is not in $JunkDirNames because backups DO want it. + $skipDirs = @($script:JunkDirNames) + @('.github') + if ($Proj.deploy -and $Proj.deploy.skipDirs) { $skipDirs += @($Proj.deploy.skipDirs) } + $dirs = @(Get-ChildItem -LiteralPath $root -Directory | Where-Object { $skipDirs -notcontains $_.Name }) + foreach ($d in $dirs) { + Write-Host " >> uploading $($d.Name)/ (recursive)" -ForegroundColor DarkCyan + scp -r @SCP_OPTS -i $PEM_KEY $d.FullName "${SSH_TARGET}:$remotePath/" + if ($LASTEXITCODE -ne 0) { throw "SCP failed for $($d.Name) (exit $LASTEXITCODE)" } + } + Invoke-Ec2Step "docker compose pull" "cd $remotePath && sudo docker compose pull" Invoke-Ec2Step "docker compose up -d" "cd $remotePath && sudo docker compose up -d"