ps/Modules/Alkami.DevOps.Operations/Retired/Copy-AlkamiReleaseManifest.ps1
2023-05-30 22:51:22 -07:00

215 lines
5.9 KiB
PowerShell

function Copy-AlkamiReleaseManifest {
<#
.SYNOPSIS
Copies Orb with a file manifest to track files between releases.
Files that are not tracked by the manifest are left alone.
DiffMove flag makes it so that unchanged files are not copied.
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$false)]
[Alias("TempOrbPath")]
[string]$srcPath = "C:\temp\deploy\orb",
[Parameter(Mandatory=$false)]
[Alias("OrbPath")]
[string]$dstPath,
[Parameter(Mandatory=$false)]
[switch] $diffMove
)
$logLead = (Get-LogLeadName);
if([string]::IsNullOrEmpty($dstPath)) {
$dstPath = (Get-OrbPath)
}
if($dstPath -eq $srcPath)
{
Write-Warning "$logLead Cannot copy Alkami release from/to the same folder. $srcPath"
return
}
$timer = [System.Diagnostics.Stopwatch]::StartNew()
$manifestPath = Join-Path $dstPath "manifest.txt"
$manifestLeftoverPath = Join-Path $dstPath "manifestLeftovers.txt"
$exclude = "*log4net.config"
Write-Host "$logLead Discovering files to copy:"
Write-Host "$logLead Note: log4net.config files are ignored!"
Write-Host "$loglead Discovering files in $srcPath"
$srcFiles = (Get-RelativeFileList $srcPath -exclude $exclude)
$dstFiles = @();
if(Test-Path $manifestPath)
{
Write-Host "$loglead Loading file paths from manifest file: $manifestPath"
$dstFiles = (Get-Content $manifestPath)
}
else
{
Write-Host "$logLead Release manifest not detected at $manifestPath"
Write-Host "$logLead Discovering files in $dstPath"
$dstFiles = (Get-RelativeFileList $dstPath -exclude $exclude)
}
Write-Host "`n$logLead Copying Alkami release from $srcPath to $dstPath"
Write-Host "$logLead Determining files to add."
$filesToAdd = (Get-SetDifference $srcFiles $dstFiles)
Write-Host "$logLead Determining files to delete."
$filesToDelete = (Get-SetDifference $dstFiles $srcFiles)
Write-Host "$logLead Determining files to move."
$filesToMove = @();
$filesToMove = (Get-SetDifference $srcFiles $filesToAdd);
$filesToMove = (Get-SetDifference $filesToMove $filesToDelete)
if($diffMove.isPresent)
{
Write-Host "$logLead DiffMove flag is present. Finding files that have not changed to avoid copies."
# Only move the files that have changed by hash comparison.
$newFilesToMove = @();
foreach($file in $filesToMove)
{
$srcFile = Join-Path $srcPath $file
$dstFile = Join-Path $dstPath $file
if((Get-FileHash -path $srcFile).hash -ne (Get-FileHash -path $dstFile).hash)
{
Write-Verbose "$logLead $srcFile hash is different than $dstFile hash."
$newFilesToMove += $file
}
}
# Reassign $filesToMove to a list of fewer files to copy.
$count = $filesToMove.Count
$filesToMove = $newFilesToMove
$count = $count - $filesToMove.Count
Write-Host "$logLead $count files don't need to be updated!"
}
$addCount = $filesToAdd.count;
$delCount = $filesToDelete.count;
$movCount = $filesToMove.count;
Write-Host "`n$logLead Peforming the following actions:"
Write-Host "$logLead Adding $addCount new files."
Write-Host "$logLead Copying $movCount files."
Write-Host "$logLead Deleting $delCount existing files.`n"
$filesToCopy = $filesToAdd + $filesToMove
if($filesToCopy.Count)
{
Write-Host "$logLead Starting file copies."
$filesPerJob = 3000;
$maxJobs = 8;
$numFiles = $filesToCopy.Count
$numJobs = [Math]::Ceiling($numFiles / $filesPerJob);
Write-Host "NumJobs $numJobs"
$scriptBlock = {
param ($srcPath, $dstPath, $copyFiles)
$VerbosePreference = 'Continue'
foreach($file in $copyFiles)
{
$srcFile = Join-Path $srcPath $file
$dstFile = Join-Path $dstPath $file
if(!(Test-Path $dstFile))
{
Write-Verbose "$logLead File $dstFile doesn't exist. Creating."
New-Item -ItemType File -Path $dstFile -Force | Out-Null
}
Write-Verbose "$logLead Copying $file"
Copy-Item $srcFile $dstFile -Force
}
}
$jobs = @()
for($i = 0; $i -lt $numJobs; $i++)
{
$start = $i * $filesPerJob
$end = ($i + 1) * $filesPerJob
if($start -ge $numFiles)
{
break;
}
elseif($end -gt ($numFiles - 1))
{
$end = ($numFiles - 1)
}
$copyFiles = $filesToCopy[$start..$end]
$jobs += Start-Job -ScriptBlock $scriptBlock -ArgumentList $srcPath, $dstPath, $copyFiles
$running = @($jobs | Where-Object {$_.State -in ('Running','NotStarted')})
while ($running.Count -ge $maxJobs -and $running.Count -ne 0)
{
$finished = Wait-Job -Job $jobs -Any
$running = @($jobs | Where-Object {$_.State -in ('Running','NotStarted')})
}
}
# Wait for all jobs in this session to complete.
Get-Job | Wait-Job > $null
# Receive-Job to output the logs.
$jobs | ForEach-Object { $_ | Receive-Job }
}
else
{
Write-Host "$logLead No files to copy."
}
if($delCount)
{
Write-Host "$logLead Starting file deletes."
foreach($file in $filesToDelete)
{
$dstFile = Join-Path $dstPath $file
if(test-path $dstFile)
{
Write-Verbose "$logLead Deleting $dstFile"
Remove-Item -Path $dstFile -Force
}
}
}
else
{
Write-Host "$logLead No files to delete."
}
Write-Host "`n$logLead Writing file manifest to $manifestPath"
Set-Content -Force -Path $manifestPath -Value $srcFiles
# Write out leftover files that survived the release.
Write-Host "`n$logLead Now determining leftover files that were untouched by the release copy in $dstPath"
$dstFiles = (Get-RelativeFileList $dstPath)
$leftoverFiles = Get-SetDifference $dstFiles $srcFiles
Write-Host "$logLead Writing leftover files to $manifestLeftoverPath"
Set-Content -Force -Path $manifestLeftoverPath -Value $leftoverFiles
$symlinkPath = (Join-Path $dstPath "createSymlinks.ps1")
if (Test-Path $symlinkPath)
{
Write-Output "$logLead Running Symlink script."
& $symlinkPath
}
else
{
Write-Warning ("$logLead Symlink script not found at `"$symlinkPath`"")
}
$timer.Stop();
Write-Host ("`n$logLead Alkami Manifest Release Copy finished in [{0}]" -f $timer.Elapsed.ToString())
}