Private/Migration/Invoke-CgrRepositorySnapshotVerification.ps1
|
function Invoke-CgrRepositorySnapshotVerification { [CmdletBinding()] param( [Parameter(Mandatory)] [psobject] $SourceRepository, [Parameter(Mandatory)] [psobject] $DestinationRepository, [psobject] $ApprovedSourceState ) $branchName = if ($ApprovedSourceState) { [string] (Get-CgrObjectProperty -InputObject $ApprovedSourceState -Name 'DefaultBranch') } else { $SourceRepository.DefaultBranch } $sourceHostName = ([uri] $SourceRepository.CloneUrl).Host $destinationHostName = ([uri] $DestinationRepository.CloneUrl).Host if ($SourceRepository.PSObject.Properties.Name -contains 'HostName') { $sourceHostName = $SourceRepository.HostName } if ($DestinationRepository.PSObject.Properties.Name -contains 'HostName') { $destinationHostName = $DestinationRepository.HostName } $workspacePath = Join-Path ([System.IO.Path]::GetTempPath()) "copy-github-repo-verify-$([guid]::NewGuid().ToString('N'))" $sourcePath = Join-Path $workspacePath 'source' $destinationPath = Join-Path $workspacePath 'destination' try { New-Item -Path $workspacePath -ItemType Directory -Force | Out-Null $sourceTree = if ($ApprovedSourceState) { [string] (Get-CgrObjectProperty -InputObject $ApprovedSourceState -Name 'TreeSha') } else { $cloneSourceResult = Invoke-CgrGitCommand ` -HostName $sourceHostName ` -ArgumentList @('clone', '--depth', '1', '--branch', $branchName, $SourceRepository.CloneUrl, $sourcePath) if ($cloneSourceResult.ExitCode -ne 0) { $message = "Git failed to clone source repository '$($SourceRepository.FullName)' for verification. $($cloneSourceResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, 'VerificationSourceRepositoryCloneFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $SourceRepository.FullName) $PSCmdlet.ThrowTerminatingError($errorRecord) } $sourceTreeResult = Invoke-CgrNativeCommand -FilePath 'git' -ArgumentList @('-C', $sourcePath, 'rev-parse', 'HEAD^{tree}') if ($sourceTreeResult.ExitCode -ne 0) { $message = "Git verification command failed for '$($SourceRepository.FullName)'. $($sourceTreeResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, 'VerificationSourceTreeReadFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $SourceRepository.FullName) $PSCmdlet.ThrowTerminatingError($errorRecord) } [string] @($sourceTreeResult.Output)[0] } $cloneDestinationResult = Invoke-CgrGitCommand ` -HostName $destinationHostName ` -ArgumentList @('clone', '--depth', '2', '--branch', $branchName, $DestinationRepository.CloneUrl, $destinationPath) if ($cloneDestinationResult.ExitCode -ne 0) { $message = "Git failed to clone destination repository '$($DestinationRepository.FullName)' for verification. $($cloneDestinationResult.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, 'VerificationDestinationRepositoryCloneFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $DestinationRepository.FullName) $PSCmdlet.ThrowTerminatingError($errorRecord) } $destinationTreeResult = Invoke-CgrNativeCommand -FilePath 'git' -ArgumentList @('-C', $destinationPath, 'rev-parse', 'HEAD^{tree}') $destinationCommitResult = Invoke-CgrNativeCommand -FilePath 'git' -ArgumentList @('-C', $destinationPath, 'rev-parse', 'HEAD') $destinationCommitCountResult = Invoke-CgrNativeCommand -FilePath 'git' -ArgumentList @('-C', $destinationPath, 'rev-list', '--count', 'HEAD') $destinationParentResult = Invoke-CgrNativeCommand -FilePath 'git' -ArgumentList @('-C', $destinationPath, 'rev-list', '--parents', '-n', '1', 'HEAD') $verificationCommands = @( [pscustomobject] @{ Result = $destinationTreeResult; ErrorId = 'VerificationDestinationTreeReadFailed'; Target = $DestinationRepository.FullName } [pscustomobject] @{ Result = $destinationCommitResult; ErrorId = 'VerificationDestinationCommitReadFailed'; Target = $DestinationRepository.FullName } [pscustomobject] @{ Result = $destinationCommitCountResult; ErrorId = 'VerificationDestinationCommitCountReadFailed'; Target = $DestinationRepository.FullName } [pscustomobject] @{ Result = $destinationParentResult; ErrorId = 'VerificationDestinationParentReadFailed'; Target = $DestinationRepository.FullName } ) foreach ($command in $verificationCommands) { if ($command.Result.ExitCode -ne 0) { $message = "Git verification command failed for '$($command.Target)'. $($command.Result.ErrorText)" $exception = [System.InvalidOperationException]::new($message.Trim()) $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, $command.ErrorId, [System.Management.Automation.ErrorCategory]::InvalidOperation, $command.Target) $PSCmdlet.ThrowTerminatingError($errorRecord) } } $destinationTree = [string] @($destinationTreeResult.Output)[0] $destinationCommit = [string] @($destinationCommitResult.Output)[0] $destinationCommitCount = [int] ([string] @($destinationCommitCountResult.Output)[0]) $parentLine = [string] @($destinationParentResult.Output)[0] $parentCount = @($parentLine.Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)).Count - 1 $checks = @( [pscustomobject] @{ Name = 'DestinationExists'; Passed = $true; Expected = $DestinationRepository.FullName; Actual = $DestinationRepository.FullName } [pscustomobject] @{ Name = 'DefaultBranchMatches'; Passed = $DestinationRepository.DefaultBranch -eq $branchName; Expected = $branchName; Actual = $DestinationRepository.DefaultBranch } [pscustomobject] @{ Name = 'GitTreeMatches'; Passed = $destinationTree -eq $sourceTree; Expected = $sourceTree; Actual = $destinationTree } [pscustomobject] @{ Name = 'DestinationHasOneCommit'; Passed = $destinationCommitCount -eq 1; Expected = 1; Actual = $destinationCommitCount } [pscustomobject] @{ Name = 'DestinationCommitHasNoParents'; Passed = $parentCount -eq 0; Expected = 0; Actual = $parentCount } ) return [pscustomobject] @{ PSTypeName = 'CopyGitHubRepo.MigrationVerificationResult' SchemaVersion = 1 ContentMode = 'Snapshot' SourceRepository = $SourceRepository.FullName ApprovedSourceState = $ApprovedSourceState DestinationRepository = $DestinationRepository.FullName BranchName = $branchName SourceTree = $sourceTree DestinationTree = $destinationTree DestinationCommit = $destinationCommit IsSuccessful = -not ($checks | Where-Object { -not $_.Passed }) Checks = $checks } } finally { if (Test-Path -LiteralPath $workspacePath) { Remove-Item -LiteralPath $workspacePath -Recurse -Force -ErrorAction SilentlyContinue } } } |