Public/utils.ps1
function Get-RKRandomCharacters($length, $characters) { [CmdletBinding()] $random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length } $private:ofs = "" return [String]$characters[$random] } function Confirm-RKCurrentDirectoryInGitRepository { <# .SYNOPSIS Git Directory Checker .DESCRIPTION Validates whether or not the current directory exists within a git repo. .OUTPUTS .NOTES Version: 1.0 Author: Liam Dunphy Creation Date: 05/05/2021 Purpose/Change: Initial function development .EXAMPLE Confirm-RKCurrentDirectoryInGitRepository #> $res = git rev-parse --is-inside-work-tree if ($null -eq $res) { return $false } else { return $true } } Function Get-RKGitDeltaFiles { <# .SYNOPSIS Gets the name and status of files which have changed in the given commit. .DESCRIPTION Generates an object documenting files that have been added, modified, or deleted in a given commit. .PARAMETER CommitId The git commit id we are looking at to identify changes. This can either be a literal id, or use the relative HEAD value. In DevOps we can leverage the system variable $(Build.SourceVersion) within our YAML pipelines. .PARAMETER LongKeyNames Indicates whether the default git status code should be converted into its more descriptive version e.g. "A" becomes "Added". .PARAMETER Filter Simple wildcard filtering to limit the scope of considered files. E.g. if you only want to see files in FolderA, you could write "*FolderA/*". .PARAMETER Pattern Advanced regex pattern filtering to limit the scope of considered files. .PARAMETER SimpleMatch Switch condition to indicate that simple filtering should be used. .PARAMETER RegexMatch Switch cndition to indicate that regex pattern matching should be used. .OUTPUTS .NOTES Version: 1.0 Author: Liam Dunphy Creation Date: 05/05/2021 Purpose/Change: Initial function development .EXAMPLE Get-RKGitDeltaFiles -CommitId "HEAD" -SimpleMatch -Filter "*FolderA*" .EXAMPLE Get-RKGitDeltaFiles -CommitId "1e49aef" -LongKeyNames $true -RegexMatch -Pattern '.*[0-9]{2}.*(.sql){1}' #> [CmdletBinding(DefaultParameterSetName = 'Simple')] param ( [OutputType([Object[]])] [string] $CommitId = "HEAD", [bool] $LongKeyNames = $true, [Parameter(ParameterSetName = 'Simple')] [string] $Filter = "*", [Parameter(ParameterSetName = 'Regex', Mandatory = $true)] [string] $Pattern, [Parameter(ParameterSetName = 'Simple', Mandatory = $true)] [switch] $SimpleMatch, [Parameter(ParameterSetName = 'Regex', Mandatory = $true)] [switch] $RegexMatch ) [Object[]] $diffFiles = @() if ($RegexMatch) { $diffFiles = (git diff-tree --no-commit-id --name-status -r $CommitId) | Where-Object { $_ -match $Pattern } | ConvertFrom-String -Delimiter '\t' -PropertyNames Status, Name } else { $diffFiles = (git diff-tree --no-commit-id --name-status -r $CommitId) | Where-Object { $_ -like $Filter } | ConvertFrom-String -Delimiter '\t' -PropertyNames Status, Name } if ($LongKeyNames -and ($diffFiles.Count -ne 0)) { $diffFiles | ForEach-Object { $_.Status = switch ($_.Status) { "A" { "Added"; Continue } "D" { "Deleted"; Continue } "M" { "Modified"; Continue } } } } Write-Output $diffFiles -NoEnumerate } Function Get-RKPublicIp { return Invoke-RestMethod http://ipinfo.io/json | Select-Object -exp ip } Function New-RKGitManifestFile { <# .SYNOPSIS Manifest File Generator. .DESCRIPTION This script generates a manifest file documenting files that have been added, modified, or deleted based on properties retrieved using git diff-tree. We can optionally specify to copy added or modified files over to a bin folder, and have this incorporated in the manifest file. .PARAMETER DiffFiles Object with Status and Name columns. You can generate this object using Get-RKGitDeltaFiles and pass it down the pipeline. .PARAMETER OutputFolder The output folder for the manifest and copied files relative to the script root. It is recommended that this should follow the form of bin/... so that if the file is run locally it is ignored by .gitignore settings. .PARAMETER CleanOutputFolder Switch command indicating if the output folder should be cleaned before writing files to it. .PARAMETER ManifestOnly Switch command indicating if only the manifest file itself should be generated (i.e. source files are not copied to the output folder) .PARAMETER OrderByFile Switch command indicating that the manifest file should be ordered by file name. .PARAMETER OrderByStatus Switch command indicating that the manifest file should be ordered by status. .OUTPUTS A JSON manifest file is generated and placed in the outputFolder path, along with copied files if specified. .NOTES Version: 1.0 Author: Liam Dunphy Creation Date: 30/04/2021 Purpose/Change: Initial script development .EXAMPLE New-RKGitManifestFile -DiffFiles $files -OutputFolder "bin" -ManifestOnly .EXAMPLE New-RKGitManifestFile -DiffFiles $files -OutputFolder "bin" -ManifestOnly -CleanOutputFolder #> [CmdletBinding(DefaultParameterSetName = "File")] param( [Parameter(Mandatory = $true)] [object[]]$DiffFiles, [string]$OutputFolder = "bin", [switch]$CleanOutputFolder, [switch]$ManifestOnly, [Parameter(ParameterSetName = "File", Mandatory = $true)] [switch]$OrderByFile, [Parameter(ParameterSetName = "Status", Mandatory = $true)] [switch]$OrderByStatus ) $rootFolder = Get-RKGitRepositoryRoot Write-Verbose "Git Repo Root: $rootFolder" $outputFolderAbsoluteFilePath = Join-Path $rootFolder -ChildPath $OutputFolder Write-Verbose "Absolute Output Path: $outputFolderAbsoluteFilePath" if ($DiffFiles.Count -ne 0) { if ($CleanOutputFolder.IsPresent) { Write-Verbose "Cleaning Output Directory (If Exists)..." Remove-Item -Recurse -Force $outputFolderAbsoluteFilePath -ErrorAction SilentlyContinue | Out-Null Write-Verbose "Cleaned Output Directory." } Write-Verbose "Force Creating Output Directory..." mkdir -Path $outputFolderAbsoluteFilePath -Force | Out-Null Write-Verbose "Created Output Directory." $manifestDictionary = @() $metadataDictionary = @{} $counter = 1 Write-Verbose "Looping Through ($($DiffFiles.Count)) Delta Files" $DiffFiles | ForEach-Object { Write-Verbose "Loop $counter/$($DiffFiles.Count)" $targetFile = @() $fileProperties = @{} Write-Verbose "Attempting To Resolve Source File Name..." $sourceAbsoluteFilePath = (Resolve-RKTheoreticalPath -FileName (Join-Path $rootFolder -ChildPath $_.Name)) $sourceRelativeFilePath = [System.IO.Path]::GetRelativePath($rootFolder, $sourceAbsoluteFilePath) Write-Verbose "Source File Name: $sourceAbsoluteFilePath" Write-Verbose "Source File Name: $sourceRelativeFilePath" if (!($ManifestOnly) -and (Test-Path $sourceAbsoluteFilePath)) { Write-Verbose "Generating Output Directory" $targetAbsoluteFolderPath = (Join-Path $outputFolderAbsoluteFilePath -ChildPath (Split-Path $_.Name -Parent)) New-Item -Type dir $targetAbsoluteFolderPath -Force Write-Verbose "Generating Output File..." $targetFile = Copy-Item $sourceAbsoluteFilePath -Destination $targetAbsoluteFolderPath -Force -PassThru -ErrorAction SilentlyContinue if ($targetFile -ne "") { Write-Verbose "Output File Name: $($targetFile.Name)" Write-Verbose "Generating File Property..." $targetAbsoluteFilePath = (Resolve-RKTheoreticalPath -FileName $targetFile.FullName) $targetRelativeFilePath = [System.IO.Path]::GetRelativePath($rootFolder, $targetAbsoluteFilePath) $fileProperties += @{ Status = $_.Status; SourceAbsoluteFilePath = $sourceAbsoluteFilePath; SourceRelativeFilePath = $sourceRelativeFilePath; TargetAbsoluteFilePath = $targetAbsoluteFilePath; TargetRelativeFilePath = $targetRelativeFilePath } Write-Verbose "Generated File Property:`n$($fileProperties | ConvertTo-Json)" } else { Write-Error "Failed To Generate Output File." } } else { Write-Verbose "Generating File Property..." $fileProperties += @{ Status = $_.Status; SourceAbsoluteFilePath = $sourceAbsoluteFilePath; SourceRelativeFilePath = $sourceRelativeFilePath } Write-Verbose "Generated File Property:`n$($fileProperties | ConvertTo-Json)" } Write-Verbose "Updating Manifest HashTable..." $manifestDictionary += $fileProperties Write-Verbose "Manifest Updated." $counter++ } $metadataDictionary = Add-ValueToHashTable -HashTable $metadataDictionary -Key "created_timestamp" -Value (Get-Date -Format o -AsUTC) -AsJsonObject $jsonDoc = [pscustomobject]@{ Files = $manifestDictionary Metadata = $metadataDictionary } $manifestFileName = "_manifest$(New-RKTimestampGuid).json" $manifestAbsoluteFilePath = (Resolve-RKTheoreticalPath -FileName $outputFolderAbsoluteFilePath/$manifestFileName) $jsonDoc | ConvertTo-Json -Depth 10 | Out-File $manifestAbsoluteFilePath -Force Write-Verbose "Manifest written to $manifestAbsoluteFilePath." return $manifestAbsoluteFilePath } } |