Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Can edit this file if more servers are required.
- $ServerConfigFile = "./servers.json"
- Function Test-Checkout {
- param(
- [parameter(Mandatory=$true)]
- [string]$Branch
- )
- begin {
- }
- process {
- git checkout $Branch | Out-Null
- if ($LASTEXITCODE -eq 1) {
- throw (Write-Warning "Unable to checkout $Branch. Review the output, resolve any issues and try again.")
- }
- }
- }
- Function New-GitBranch {
- <#
- .SYNOPSIS
- Creates a new branch from a source branch, switches to it and pushes it to the remote.
- .DESCRIPTION
- Checks out the source branch and runs a 'git pull' to get the latest commits.
- Creates and switches to a branch named with the given parameters and/or their default values.
- .NOTES
- Assumes that there is a remote set-up on the git repository.
- The working directory should be clean before running this command. Commit, statsh or discard
- and changes that are outstanding before running this command.
- .PARAMETER Path
- The path to the local working directory where the sql-code repo resides. If not supplied
- assumed to be the current working directory.
- .PARAMETER SourceBranch
- The branch from which to create the new branch. Defaults to the 'develop' branch.
- .PARAMETER Prefix
- The prefix to use for the branch. If used, has to be one of: Release, Bugfix, Hotfix, Feature.
- .PARAMETER Name
- The name of the branch to create. Recommended format is <JIRA_CODE>-<some-descriptive-text-for-branch>.
- .EXAMPLE
- PS> New-GitBranch -SourceBranch develop -Prefix Bugfix -Name fix-divide-by-zero
- Creates a new branch named Bugfix/fix-divide-by-zero, sourcing from an updated develop branch,
- pushing to the remote, automatically setting up tracking.
- #>
- [CmdletBinding()]
- Param(
- [ValidateScript( {Test-Path $_ -PathType "Container"})]
- [string]
- $Path = "$pwd",
- [Parameter(mandatory = $true)]
- [ValidateSet("develop", "preprod", "master")]
- [string]$SourceBranch,
- [Parameter(mandatory = $false)]
- [ValidateSet("release", "feature", "bugfix", "hotfix")]
- [string]$Prefix,
- [Parameter(mandatory = $false)]
- [string]$Name = $(Get-Date -Format yyyyMMddHHmmss)
- )
- begin {
- $newBranchName = "$Prefix$(if ($Prefix) {"/"})$Name"
- if ($Path -ne $pwd) {
- Set-Location $Path
- }
- }
- process {
- try {
- #Get latest state of the source branch.
- Test-Checkout -Branch $SourceBranch
- git pull
- #Create the new branch, switch to it and push to the remote.
- git checkout -b "$newBranchName"
- git push -u origin "$newBranchName"
- $newBranchName
- }
- catch {
- Write-Error "$($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)"
- }
- }
- }
- Function Compare-GitBranch {
- <#
- .SYNOPSIS
- Compares any two branches on the current git repository. Returns the files that are different
- between the Source and Target.
- .DESCRIPTION
- .NOTES
- Assumes that the branches exist on the remote and thus can be pulled.
- .PARAMETER SourceBranch
- The comparison branch from which the files will be returned. If not supplied, the current branch
- will be used.
- .PARAMETER TargetBranch
- The branch to compare the SourceBranch against. If not supplied, the 'master' branch will be used.
- .EXAMPLE
- #>
- [CmdletBinding()]
- Param(
- [Parameter(mandatory = $false)]
- [string]$SourceBranch = $(git rev-parse --abbrev-ref HEAD),
- [Parameter(mandatory = $false)]
- [string]$TargetBranch = "master"
- )
- process {
- try {
- $startingBranch = $(git rev-parse --abbrev-ref HEAD) | Out-Null
- #Get latest state of the target branch to compare against
- Test-Checkout -Branch $TargetBranch
- git pull
- if ($startingBranch -ne $sourceBranch) {
- Test-Checkout -Branch $SourceBranch
- }
- #Now we can compare the list of files that are different between this release and the remote/origin
- $filesChanged = git diff --name-status "$TargetBranch..."
- #To trap the SQL objects we might want to deploy code for later
- $objectTypes = "StoredProcedure", "Table", "Trigger", "Function", "View"
- #Build the diff files
- $filesChanged | ForEach-Object {
- #Files that were renamed have 3 parts in the string so need to parse a different way. Will sort later
- $schemaName = $null
- $objectName = $null
- if ($_ -notlike "R*") {
- $data = $_ -split "\s", 2
- $file = $data[1]
- $name = Split-Path -Path "$file" -leaf
- $objType = $name.split(".")[-2]
- #Some extra info for SQL objects
- if ($objectTypes.Contains($objType)) {
- $objectName = ($name.split(".")[-3])
- $schemaName = ($name.split(".")[-4])
- }
- else {
- $objType = $null
- }
- New-Object psobject -Property @{
- Action = $data[0]
- FullName = $file
- Name = $name
- SchemaName = $schemaName
- ObjectName = $objectName
- ObjectType = $objType
- }
- }
- }
- write-host "done"
- }
- catch {
- Write-Error "$($_.Exception.Message) - LineNumber: $($_.InvocationInfo.ScriptLineNumber)"
- }
- finally {
- git checkout $startingBranch | Out-Null
- }
- }
- }
- Function Publish-Code {
- <#
- .SYNOPSIS
- Will figure out the changes of a release, collect the sql files and then run the code against the chosen server.
- .DESCRIPTION
- .NOTES
- .PARAMETER TargetServer
- The server[s] you want to deploy the code to.
- .PARAMETER ReleaseBranch
- The branch to compare against master. If no branch supplied, the current branch will be used.
- .EXAMPLE
- #>
- [CmdletBinding()]
- Param(
- [Parameter(mandatory = $true)]
- [ValidateScript({
- # build the servers list from config file and check the values supplied by the user exist.
- $global:servers = Get-Content -Raw -Path "$serverConfigFile" | ConvertFrom-Json
- $_ -in ($servers | Get-Member -MemberType NoteProperty).Name})
- ]
- [string[]]$TargetServer,
- [Parameter(mandatory = $false)]
- [string]$ReleaseBranch = $(git rev-parse --abbrev-ref HEAD)
- )
- begin {
- $ErrorActionPreference = "stop"
- $currentBranch = git rev-parse --abbrev-ref HEAD
- if ($ReleaseBranch -ne $currentBranch) {
- Test-Checkout -Branch $ReleaseBranch
- }
- }
- process {
- try {
- $sortOrder = "Pre Release Scripts", "Schemas", "Tables", "Triggers", "Views", "Synonyms", "StoredProcedures", "Post Release Scripts"
- $files = Compare-GitBranch |
- Select-Object Action, FullName, SchemaName, ObjectName, ObjectType |
- Where-Object { $_.Action -eq "A" -or $_.Action -eq "M" } |
- Sort-Object { $sortOrder.IndexOf($_.FullName.split("/")[-2])}
- Write-Host "$($files.length) selected for deployment across $($TargetServer.Length) servers."
- $TargetServer.foreach({
- $serverInstanceKey = $_
- $serverInstance = $servers.$serverInstanceKey.server
- Write-Host "Deploying code to $serverInstanceKey" -ForegroundColor Cyan
- $contextQuery = @"
- DECLARE @BinVar varbinary(128);
- SET @BinVar = CAST('$currentBranch' AS varbinary(128));
- SET CONTEXT_INFO @BinVar;
- "@
- $files | ForEach-Object {
- $qualifedObjName = "$($_.Schema).$($_.ObjectName)"
- Write-Host "Attempting to deploy $($_.FullName)" -ForegroundColor Cyan
- $query = (Get-Content -path ($_.FullName)) | Out-String
- Write-Debug $query
- Invoke-Sqlcmd -query "$contextQuery$query" -ServerInstance $serverInstance `
- -QueryTimeout 600 -OutputSqlErrors $true -ErrorAction Continue
- if ($?) {
- Write-host " DEPLOYED: $qualifedObjName" -ForeGroundColor green
- $deployStatus = "DEPLOYED"
- }
- else {
- $deployStatus = "FAILED"
- }
- New-Object psobject -Property @{
- FullName = ($_.FullName)
- ServerInstance = $serverInstanceKey
- DeploymentStatus = $deployStatus
- }
- }
- })
- }
- catch {
- Write-Error "$($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)"
- }
- }
- end {
- }
- }
- Export-ModuleMember -Function New-GitBranch
- Export-ModuleMember -Function Compare-GitBranch
- Export-ModuleMember -Function Publish-Code
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement