ReCrutch.GitLab.psm1
[System.Reflection.Assembly]::LoadWithPartialName("System.Web") function Set-ReCrGitLabSettings($apiUrl, $prj, $privTokenEnvVarName, $privTokenScripts, $privTokenValue) { $ReCr.GitLab = @{ ApiUrl = $apiUrl Prj = $prj PrivateToken = @{ EnvVarName = $privTokenEnvVarName Scripts = $privTokenScripts PrivateToken = $privTokenValue } } } function Get-ReCrGitLabPrivateToken() { try { $settings = $ReCr.GitLab.PrivateToken if($settings.PrivateToken -ne $null) { return $settings.PrivateToken } if($settings.EnvVarName -ne $null) { $pt = [System.Environment]::GetEnvironmentVariable($settings.EnvVarName) if($pt -ne $null) { return $pt } } if($settings.Scripts -ne $null) { foreach($script in $settings.Scripts) { if((Test-Path $script) -eq $true) { . $script if($settings.PrivateToken -ne $null) { return $settings.PrivateToken } } } } if($settings.PrivateToken -eq $null) { $settings.PrivateToken = Read-Host -Prompt 'Input private token for accsess GitLab' } return $settings.PrivateToken } catch { Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception) } } function Invoke-ReCrGitLabRestApi($method, [string]$url, $urlParameters, $if404ToNull, $prj = $null) { $oldSecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol; try { $settings = $ReCr.GitLab $pt = Get-ReCrGitLabPrivateToken [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; $urlParametersStr = "" if($urlParameters -ne $null) { $urlParametersStr = ($urlParameters.Keys | ForEach-Object { "{0}={1}" -f [System.Uri]::EscapeDataString($_), [System.Uri]::EscapeDataString($urlParameters[$_]) }) -join "&" } $con = "" if([string]::IsNullOrEmpty($urlParametersStr) -ne $true -and $url.Contains("?") -ne $true -and $url.Contains("&") -ne $true) { $con = "?" } elseif([string]::IsNullOrEmpty($urlParametersStr) -ne $true -and $url.EndsWith("?") -eq $true) { $con = "" } elseif([string]::IsNullOrEmpty($urlParametersStr) -ne $true -and $url.EndsWith("&") -eq $true) { $con = "" } elseif([string]::IsNullOrEmpty($urlParametersStr) -ne $true -and $url.Contains("?") -eq $true) { $con = "&" } if($prj -eq $null) { $prj = $settings.Prj } $fullUrl = "$($settings.ApiUrl)/projects/$([System.Web.HttpUtility]::UrlEncode($prj))$($url)$con$($urlParametersStr)" $uri = New-Object System.Uri -ArgumentList ($fullUrl) Repair-ReCrUri $uri $resp = Invoke-WebRequest -Uri $uri -Method $method -Headers @{ "PRIVATE-TOKEN" = $pt "Content-Type" = "application/json;charset=utf-8" } $str=[system.Text.Encoding]::UTF8.GetString($resp.RawContentStream.ToArray()); return ConvertFrom-Json $str } catch { if($if404ToNull -eq $true -and $_.Exception.GetType() -eq [System.Net.WebException]) { if($_.Exception.Response.StatusCode -eq 404) { return $null } } throw new-object System.Exception ("$fullUrl", $_.Exception) } finally { [System.Net.ServicePointManager]::SecurityProtocol = $oldSecurityProtocol } } function Invoke-ReCrGitLabRestApiGet([string]$url, $urlParameters, $if404ToNull, $prj = $null) { return Invoke-ReCrGitLabRestApi Get $url $urlParameters $if404ToNull $prj } function Invoke-ReCrGitLabRestApiPost([string]$url, $urlParameters, $if404ToNull, $prj = $null) { return Invoke-ReCrGitLabRestApi Post $url $urlParameters $if404ToNull $prj } function Invoke-ReCrGitLabRestApiPut([string]$url, $urlParameters, $if404ToNull, $prj = $null) { return Invoke-ReCrGitLabRestApi Put $url $urlParameters $if404ToNull $prj } # tags b function Get-ReCrGitLabTag($tagName, $if404ToNull) { try { $tag = Invoke-ReCrGitLabRestApiGet "/repository/tags/$tagName" -if404ToNull:$if404ToNull $tag } catch { Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception) } } function New-ReCrGitLabTag($branch, $tagName, $buildPath) { <#if([string]::IsNullOrEmpty($tagName) -eq $true) { throw [System.Exception] "`$tagName requery" }#> #$tagName = "1" #$r = BuildGLRestGet "/repository/tags/" @{ per_page = 1000 } #?per_page=3&page=2&sort=commit.committed_date <# $r = $r | Sort-Object { $_.commit.committed_date } -Descending $r | Select-Object { $_.name; $_.commit.committed_date } | Format-Table $lastTag = $r[0] [Regex]::Matches($lastTag.name, "(?<stend>/)") $g = [Regex]::Matches($lastTag.name, "(?<stend>^\S[^/]+)/v(?<v1>\d+).(?<v2>\d+).(?<v3>\d+)") $g[0].Groups $nextVer = [int]::Parse($g[0].Groups["v2"].Value) + 1 $newTagName = "$($g[0].Groups["stend"].Value)/v$($g[0].Groups["v1"].Value).$nextVer.$($g[0].Groups["v3"].Value)" #> <#$tag = BuildGLRestGet "/repository/tags/$tagName" -if404ToNull:true if($tag -ne $null) { throw [System.Exception] "Tag $tagName уже существует" } $issues = BuildGLRestGet "/issues" @{ labels = "$tagName"; state = "opened" } $issues = $issues | sort iid $issues.Count $issues | Format-Table iid, title $release_description = "" foreach ($issue in $issues) { $release_description += "* #$($issue.iid) " } $newtag = BuildGLRestPost "/repository/tags/" @{ tag_name = $tagName ref = $branch message = "$buildPath" release_description = $release_description } #> } function New-ReCrGitLabTagRelease($tagName, $description) { try { if([string]::IsNullOrEmpty($tagName) -eq $true) { throw new-object System.Exception ("tagName require") } if([string]::IsNullOrEmpty($description) -eq $true) { throw new-object System.Exception ("description require") } $r = Invoke-ReCrGitLabRestApiPost "/repository/tags/$tagName/release/" @{ description = $description } } catch { Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception) } } function Update-ReCrGitLabTagRelease($tagName, $description) { try { if([string]::IsNullOrEmpty($tagName) -eq $true) { throw new-object System.Exception ("tagName require") } if([string]::IsNullOrEmpty($description) -eq $true) { throw new-object System.Exception ("description require") } $r = Invoke-ReCrGitLabRestApiPut "/repository/tags/$tagName/release/" @{ description = $description } } catch { Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception) } } function Update-ReCrGitLabTagReleaseBuildPathAndIssues($tagName, $buildPath, $issueIds) { # $tagName = "mrgrp-suip.v0.0-build.1-revision.1" #$buildPath = $buildDevServerPath try { if([string]::IsNullOrEmpty($tagName) -eq $true) { throw new-object System.Exception ("tagName require") } $tag = Get-ReCrGitLabTag -tagName:$tagName -if404ToNull:$true $release_description = "" if($tag.release -ne $null -and $tag.release.description -ne $null) { $release_description = $tag.release.description } $releaseDescription = "`r`n>>>`r`n" $releaseDescription += "Билд тут: " # \\aakozlov-vm4.test.local\C$\_MRGRP-SUIP\Builds\mrgrp-suip.v0.0-build.1-revision.1 #Билд тут: \\aakozlov-vm4.test.local\C$_MRGRP-SUIP\Builds\mrgrp-suip.v0.0-build.1-revision.1 #$releaseDescription += $buildPath.Replace("\\", "\\\\").Replace("$\", "$\\") $releaseDescription += "file://" + $buildPath.Replace("\\", "").Replace("\", "/") $releaseDescription += "`r`n ``(если не открывается, то нужно ссылку скопировать и вставить в Explorer, IE или файловый менеджер или новую вкладку браузера)``" $groups = $issueIds | Group-Object -Property prj foreach ($group in $groups) { $releaseDescription += "`r`n`r`n" $labelName = [System.Uri]::EscapeDataString("$($ReCr.GitLab.Prj)/$tagName") $releaseDescription += "[**issues $($group.Name)**](https://git.i-sys.ru/$($group.Name)/issues?label_name%5B%5D=$labelName)" $releaseDescription += "`r`n" foreach ($issueId in $group.Group) { $releaseDescription += "* $($issueId.prj)#$($issueId.id) `r`n" } } $releaseDescription += ">>>" if($release_description -match "Билд тут:") { $pat = "[\r\n]+>>>[\r\n]+Билд тут: (.*[\r\n])+>>>" [System.Text.RegularExpressions.Regex]::Match($release_description, $pat, [System.Text.RegularExpressions.RegexOptions]::Multiline) $release_description = [System.Text.RegularExpressions.Regex]::Replace($release_description, $pat, "", [System.Text.RegularExpressions.RegexOptions]::Multiline) } $release_description += $releaseDescription + "`r`n`r`n" if($tag.release -eq $null) { New-ReCrGitLabTagRelease -tagName:$tagName -description:$release_description } else { Update-ReCrGitLabTagRelease -tagName:$tagName -description:$release_description } } catch { Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception) } } function Get-ReCrGitLabTagCommits($tagName, $regExpMaskTagName) { #$tagName = $buildOptions.tagName #$regExpMaskTagName = $buildOptions.regExpMaskTagName try { $tag = Get-ReCrGitLabTag -tagName:$tagName -if404ToNull:$false $tags = Invoke-ReCrGitLabRestApiGet "/repository/tags/" @{ order_by = "updated" sort = "desc" } $tags = $tags | Where-Object { [System.Text.RegularExpressions.Regex]::IsMatch($_.name, $regExpMaskTagName) -eq $true ` -and $_.commit.committed_date -lt $tag.commit.committed_date } ` | Sort-Object -Property @{ Expression = "commit.committed_date" } -Descending ` | select -First 1 #$tags | Format-List $tagCommitsCurrent = @() $tagCommits = @() while($true) { $p = @{ ref_name = "$tagName" } $l = $tagCommits | select -Last 1 if($l -ne $null) { $d = [System.DateTime]::Parse($l.committed_date) #$l.committed_date $until = $d.AddMilliseconds(-1).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ") $p.until = $until } $tagCommits = Invoke-ReCrGitLabRestApiGet "/repository/commits/" $p #$tagCommits | select message if($tagCommits.Count -eq 0) { break } $flag = $false foreach($commit in $tagCommits) { #$commit = $tagCommits[0] #$commitRefs = Invoke-ReCrGitLabRestApiGet "/repository/commits/$($commit.short_id)/refs/" if($tags -ne $null -and $tags.commit.id -eq $commit.id) { $flag = $true break } $tagCommitsCurrent += $commit } if($flag -eq $true) { break } } #$tagCommitsCurrent | select -Property short_id,message | Format-Table $tagCommitsCurrent } catch { Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception) } } function Get-ReCrGitLabTagCommitsIssueIds($tagName, $regExpMaskTagName) { #$tagName = $buildOptions.tagName #$regExpMaskTagName = $buildOptions.regExpMaskTagName try { $commits = Get-ReCrGitLabTagCommits -tagName:$tagName -regExpMaskTagName:$regExpMaskTagName #$commits = $tagCommitsCurrent #$commits | select message if($commits.Count -gt 1) { [array]::Reverse($commits) } $groups = @("id", "idWitProj", "url") $issueIds = @() foreach($commit in $commits) { $msg = $commit.message <# $msg = "[*] #1177 Структура решения [*] #2 Структура решения #3" $msg = "Merge branch 'task/1-structure-solution' into 'master' #1 Структура решения 2 See merge request MRGRP/SUIP!2" #> #$msg = "[*] systemz/ISYS-DXFM#132 Test #478 #479 https://git.i-sys.ru/systemz/ISYS-DXFM/issues/132" #$msg = "[*]#192 Запретил редактирование DelegateFrom и DelegateTo...." #$msg = "Revert `"#342 Обязательность поля Commentaries approval-таски не соответствует тз`"... " #$msg = "[+] #1 Добавлена базовая инфраструктура создания сайтов...." #cls #$msg $mathes = [System.Text.RegularExpressions.Regex]::Matches($msg, "(^|\s|\]|`"|')(?<f>(?<id>#[0-9]+)|(?<idWitProj>[^\s\]`"']+#[0-9]+)|(?<url>https://git.i-sys.ru/[^\s]+/issues/[0-9]+))") <# foreach($math in $mathes) { $math.Groups | Where-Object { $_.Success -eq $true -and $groups -contains $_.Name } } #> if($mathes.Count -eq 0) { $branchMathes = [System.Text.RegularExpressions.Regex]::Matches($msg, "^Merge branch '(?<branch>[^\s'`"]+)' into 'master'") if($branchMathes.Count -eq 1) { <# Merge branch 'task/108-table-requirement' into 'master' Task/108 table requirement See merge request 4FIN/APRS!412 #> # todo Write-Host ">>>$msg" } elseif([System.Text.RegularExpressions.Regex]::IsMatch($msg, "^Merge branch 'master' ") -eq $true) { continue } elseif([System.Text.RegularExpressions.Regex]::IsMatch($msg, "^\[~\] Merge master into ") -eq $true) { continue } elseif([System.Text.RegularExpressions.Regex]::IsMatch($msg, "^\[~\] Merge from master to ") -eq $true) { continue } elseif([System.Text.RegularExpressions.Regex]::IsMatch($msg, "^\[~\] Merge from origin/master to") -eq $true) { continue } elseif([System.Text.RegularExpressions.Regex]::IsMatch($msg, "^\[~\] Merge origin/master to ") -eq $true) { continue } elseif([System.Text.RegularExpressions.Regex]::IsMatch($msg, "^Merge remote-tracking branch 'origin/master' into ") -eq $true) { continue } elseif([System.Text.RegularExpressions.Regex]::IsMatch($msg, "^Merge remote-tracking branch 'origin' into ") -eq $true) { continue } else { #Write-Host ">>>$msg" } } foreach($math in $mathes) { $gs = $math.Groups | Where-Object { $_.Success -eq $true -and $groups -contains $_.Name } foreach($g in $gs) { #Write-Host "$($g.Value) $($g.Name)" $id = $g.Value if($g.Name -eq "id") { $id = $id.Replace("#", "") } if($issueIds.Contains($id) -eq $false) { $issueIds += $id } } } } $issueIdsCmplx = $issueIds | ForEach-Object { Get-ReCrPrjFromIssueId $_ } | Select-Object -Property @{Name="prj"; Expression = {$_.prj}},@{Name="id"; Expression = {$_.id}} -Unique $issueIdsCmplx } catch { Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception) } } # tags e # label b function New-ReCrGitLabLabel($labelName, $color, $prj = $null) { try { if([string]::IsNullOrEmpty($labelName) -eq $true) { throw [System.Exception] "`$labelName requery" } $labels = Invoke-ReCrGitLabRestApiGet "/labels" @{ per_page = 1000 } -prj:$prj $label = $labels | where name -eq $labelName if($label -ne $null) { return $label } $label = Invoke-ReCrGitLabRestApiPost "/labels/" @{ name = $labelName color = $color } -prj:$prj return $label } catch { Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception) } } # label e # Issue b function Get-ReCrPrjFromIssueId($id) { $idInt = 0 if([int]::TryParse($id, [ref] $idInt)) { $settings = $ReCr.GitLab return @{ prj = $settings.Prj; id = $id; } } #$id = "https://git.i-sys.ru/systemz/ISYS-DXFM/issues/132" #$id = "systemz/ISYS-DXFM#132" $mathes = [System.Text.RegularExpressions.Regex]::Matches($id, "^(?<prj>[^\s]+)#(?<id>[0-9]+)$") if($mathes.Success) { return @{ prj = $mathes[0].Groups["prj"].Value; id = $mathes[0].Groups["id"].Value; } } $mathes = [System.Text.RegularExpressions.Regex]::Matches($id, "^https://git.i-sys.ru/(?<prj>[^\s]+)/issues/(?<id>[0-9]+)$") if($mathes.Success) { return @{ prj = $mathes[0].Groups["prj"].Value; id = $mathes[0].Groups["id"].Value; } } throw [System.Exception] "не удалось распарсить issue id: $id" } function Get-ReCrGitLabIssue($id, $if404ToNull, $prj = $null) { try { if($id.GetType() -eq [string]) { $idInt = 0 if([int]::TryParse($id, [ref] $idInt)) { $issue = Invoke-ReCrGitLabRestApiGet "/issues/$id/" -if404ToNull:$if404ToNull -prj:$prj return $issue } else { $idComplex = Get-ReCrPrjFromIssueId $id $issue = Invoke-ReCrGitLabRestApiGet "/issues/$($idComplex.id)/" -if404ToNull:$if404ToNull -prj:$idComplex.prj return $issue } } else { $issue = Invoke-ReCrGitLabRestApiGet "/issues/$($id.id)/" -if404ToNull:$if404ToNull -prj:$id.prj return $issue } } catch { Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception) } } function Add-ReCrGitLabCommentToIssue($id, $body, $prj = $null) { try { $newNote = Invoke-ReCrGitLabRestApiPost "/issues/$id/notes" @{ body = $body } -prj:$prj $newNote } catch { Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception) } } function Set-ReCrGitLabLabelToIssue($labelName, $labelBuildColor, $issueIds, $needToDeployLabel, $msg) { try { $needToDeployLabelCmd = "" if($needToDeployLabel -ne $null) { $needToDeployLabelCmd = " ~`"$needToDeployLabel`"" } $groups = $issueIds | Group-Object -Property prj foreach ($group in $groups) { $labelFullName = "$($ReCr.GitLab.Prj)/$labelName" $labelBuild = New-ReCrGitLabLabel -labelName:$labelFullName -color:$labelBuildColor -prj:$group.Name foreach ($issueId in $group.Group) { $issue = Get-ReCrGitLabIssue -id:$issueId.id -if404ToNull:true -prj:$issueId.prj if($issue -eq $null) { Write-Host-Indent 1 "issue not found by id '$id'" -ForegroundColor:$ReCr.ConsoleColors.errorMessage continue } $body = "$msg`r`n`r`n/label ~`"$labelFullName`"$needToDeployLabelCmd`r`n" $newNote = Add-ReCrGitLabCommentToIssue -id:$issueId.id -body:$body -prj:$issueId.prj } } } catch { Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception) } } # Issue e |