PSGitLab.psm1
########################## # Public Functions ########################## Function New-GitLabBuild { [cmdletbinding()] param( [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName="Default",Mandatory=$true)] [Parameter(ParameterSetName="Variable",Mandatory=$true)] [int]$ProjectId, [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName="Default",Mandatory=$true)] [Parameter(ParameterSetName="Variable",Mandatory=$true)] [string]$Reference, [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName="Default",Mandatory=$true)] [Parameter(ParameterSetName="Variable",Mandatory=$true)] [string]$token, [Parameter(ParameterSetName="Variable",Mandatory=$true)] [string]$Variable, [Parameter(ParameterSetName="Variable",Mandatory=$true)] [string]$Value ) $LF = "`r`n" $uri = "http://gitlab.columbia.csc/api/v3/projects/$ProjectId/trigger/builds" $boundary = [System.Guid]::NewGuid().ToString() $bodyLines = "--$boundary$LF" + "Content-Disposition: form-data; name=`"token`"$LF" + "Content-Type: 'multipart/form-data'$LF$LF" + "$token$LF" + "--$boundary$LF" + "Content-Disposition: form-data; name=`"ref`"$LF" + "Content-Type: 'multipart/form-data'$LF$LF" + "$Reference$LF" if ($Variable) { $Variable = "variables[$Variable]" $bodyLines += ("--$boundary$LF" + "Content-Disposition: form-data; name=`"$Variable`"$LF" + "Content-Type: multipart/form-data$LF$LF" + "$Value$LF") } $bodyLines += "--$boundary--$LF" try { $result = Invoke-RestMethod -Uri $uri -Method Post -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines Write-Debug $result Write-Output "Build trigger sent successfully" } catch { Write-Output ($x.ErrorDetails.Message | convertfrom-json).message } } Function Save-GitLabAPIConfiguration { [cmdletbinding()] param( [Parameter(Mandatory=$true, HelpMessage='You can find the token in your profile.', Position=0)] [ValidateNotNullOrEmpty()] $Token, [Parameter(Mandatory=$true, HelpMessage='Please provide a URI to the GitLab installation', Position=1)] [ValidateNotNullOrEmpty()] [ValidatePattern("^(?:http|https):\/\/(?:[\w\.\-\+]+:{0,1}[\w\.\-\+]*@)?(?:[a-z0-9\-\.]+)(?::[0-9]+)?(?:\/|\/(?:[\w#!:\.\?\+=&%@!\-\/\(\)]+)|\?(?:[\w#!:\.\?\+=&%@!\-\/\(\)]+))?$")] $Domain ) if ( $Domain -match '^http:\/\/' ) { Write-Warning "All tokens will be sent over HTTP. Recommendation: Use HTTPS." } if ( $IsWindows -or ( [version]$PSVersionTable.PSVersion -lt [version]"5.99.0" ) ) { $Parameters = @{ Token=(ConvertTo-SecureString -string $Token -AsPlainText -Force) Domain=$Domain; } $ConfigFile = "$env:appdata\PSGitLab\PSGitLabConfiguration.xml" } elseif ( $IsLinux ) { Write-Warning "Warning: Your GitLab token will be stored in plain-text on non-Windows platforms." $Parameters = @{ Token=$Token Domain=$Domain; } $ConfigFile = "{0}/.psgitlab/PSGitLabConfiguration.xml" -f $HOME } else { Write-Error "Unknown Platform" } if (-not (Test-Path (Split-Path $ConfigFile))) { New-Item -ItemType Directory -Path (Split-Path $ConfigFile) | Out-Null } $Parameters | Export-Clixml -Path $ConfigFile Remove-Variable Parameters } Function Test-GitLabAPI { param( [Parameter(Mandatory=$false)] [string]$Version = 'v3' ) $GitLabConfig = ImportConfig $Domain = $GitLabConfig.Domain $Token = DecryptString -Token $GitLabConfig.Token $Result = Invoke-WebRequest -UseBasicParsing -Uri "$Domain/api/$Version/projects?private_token=$Token" Remove-Variable Token GetGitLabStatusCode $Result.StatusCode } Function Get-GitLabUserKey { [cmdletbinding(DefaultParameterSetName='All')] [OutputType('GitLab.User.Key')] param( [Parameter(ParameterSetName='All')] [switch]$All, [Parameter(ParameterSetName='Key')] [int]$Key, [Parameter(ParameterSetName='Username')] [string]$Username, [Parameter(ParameterSetName='UserID')] [int]$UserId ) $Request = @{ URI=""; Method='Get'; } if ( $PSCmdlet.ParameterSetName -eq 'Username' ) { $UserID = Get-GitLabUser -Username $Username | Select-Object -ExpandProperty Id -First 1 } switch ( $PSCmdlet.ParameterSetName) { 'Key' { $Request.URI = "/user/keys/$Key" } 'All' { $Request.URI = "/user/keys/" } 'Username' { $Request.URI = "/users/$UserID/keys" } 'UserID' { $Request.URI = "/users/$UserID/keys" } } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User.Key' } Function New-GitLabUserKey { [cmdletbinding(DefaultParameterSetName='Explicit')] [OutputType('GitLab.User.Key')] param( [Parameter(ParameterSetName='Explicit')] [string]$Title, [Parameter(ParameterSetName='Explicit',Mandatory=$true)] [string]$Key, [Parameter(ParameterSetName='File',Mandatory=$true)] [string]$KeyFile = $null, [Parameter(Mandatory=$false)] $Username = $null ) if ( $PSBoundParameters.ContainsKey('Username') ) { try { $User = Get-GitLabUser -Username $Username } catch { Write-Error "Unable to find user" } $URI = '/users/{0}/keys' -f $User.ID } else { $URI = "/user/keys" } if ( $PSCmdlet.ParameterSetName -eq 'File' ) { $Contents = Get-Content -Path $KeyFile $Title = ($Contents -split " ")[2] $Key = "{0} {1}" -f ($Contents -split " ")[0],($Contents -split " ")[1] Write-Verbose "Title: $Title Key: $Key" } if ($Title -eq $null) { Write-Error "Title could not be determined." } $Body = @{ title= $Title key = $Key } $Request = @{ URI=$URI; Method='POST' Body = $Body } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User.Key' } Function Push-SSHKeysToGitLab { [cmdletbinding(SupportsShouldProcess=$true,ConfirmImpact='High')] param( [ValidateScript({ Test-Path $_ })] $SSHDirectory = "~/.ssh/" ) $PublicKeyFiles = Get-Childitem -Recurse -Path $SSHDirectory -Include "*.pub" if ($PublicKeyFiles.count -gt 0 ) { $PublicKeyFiles | ForEach-Object { if ( $PSCmdlet.ShouldProcess("Push SSH Key $_ to GitLab Instance") ) { Write-Verbose "Uploading $($_.Fullname)" New-GitLabUserKey -KeyFile $_.FullName } } } else { Write-Warning "No Public Keys Found" } } Function Remove-GitLabUserKey { [cmdletbinding(SupportsShouldProcess=$true)] [OutputType('GitLab.User.Key')] param( [Parameter(ParameterSetName='Id',Mandatory=$true)] [Parameter(ParameterSetName='User',Mandatory=$true)] [string]$Id, [Parameter(ParameterSetName='User',Mandatory=$true)] [string]$Username, [switch]$Passthru ) $Request = @{ URI=''; Method='DELETE'; } switch ( $PSCmdlet.ParameterSetName ) { 'User' { $UserId = (Get-GitLabUser -Username $Username).Id $Request.URI = "/users/$UserId/keys/$Id" } 'Id' { $Request.URI = "/user/keys/$Id" } } if ( $PSCmdlet.ShouldProcess("Delete SSH Key $Id") ) { $Results = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User.Key' if ( $Passthru ) { $Results } } } Function Close-GitLabMergeRequest { [cmdletbinding()] param( [Alias('project_id')] [ValidateNotNullOrEmpty()] [Parameter(ValueFromPipelineByPropertyName,Mandatory)] [string]$ProjectId, [ValidateNotNullOrEmpty()] [Parameter(ValueFromPipelineByPropertyName,Mandatory)] [string[]]$ID, [switch]$Passthru ) BEGIN {} PROCESS { foreach ( $MergeRequestID in $ID ) { $Results = Set-GitLabMergeRequest -Project $ProjectId -Id $ID -StateEvent close if ( $Passthru.isPresent ) { $Results } } } END {} } Function Get-GitLabMergeRequest { [cmdletbinding(DefaultParameterSetName='MergeRequests')] [OutputType('GitLab.MergeRequest')] param ( [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName='Single',Mandatory)] [Parameter(ParameterSetName='MergeRequests',Mandatory)] [string]$ProjectId, [Parameter(ParameterSetName='Single',Mandatory)] [string]$Id, [Parameter(ParameterSetName='MergeRequests')] # merge request iid [string]$Iid, [Parameter(ParameterSetName='MergeRequests')] # possible values: all, merged, opened, closed [string]$State, [Parameter(ParameterSetName='MergeRequests')] # possible values: created_at (default) and updated_at [string]$OrderBy, [Parameter(ParameterSetName='MergeRequests')] # possible values: asc and desc (default) [string]$Sort ) $Project = Get-GitlabProject -Id $ProjectId; if($PSCmdlet.ParameterSetName -ne 'Single') { $GetUrlParameters = @() if ($Iid) { $GetUrlParameters += @{iid=$Id} } if ($State) { $GetUrlParameters += @{state=$State} } if ($OrderBy) { $GetUrlParameters += @{order_by=$OrderBy} } if ($Sort) { $GetUrlParameters += @{sort=$Sort} } $URLParameters = GetMethodParameters -GetURLParameters $GetUrlParameters } $Request = @{ URI = '' Method = 'GET' } Write-Verbose "Parameter Set Name: $($PSCmdlet.ParameterSetName)" switch ($PSCmdlet.ParameterSetName) { MergeRequests { $Request.URI="/projects/$($Project.id)/merge_requests$URLParameters"; break; } Single { $Request.URI="/projects/$($Project.id)/merge_requests/$Id"; break; } default { Write-Error "Incorrect parameter set."; break; } } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.MergeRequest' } Function New-GitLabMergeRequest { [cmdletbinding()] param( [ValidateNotNullOrEmpty()] [Parameter(Mandatory)] [string]$ProjectId, [ValidateNotNullOrEmpty()] [Parameter(Mandatory)] [string]$SourceBranch, [ValidateNotNullOrEmpty()] [Parameter(Mandatory)] [string]$TargetBranch, [int]$AssigneeId, [ValidateNotNullOrEmpty()] [Parameter(Mandatory)] [string]$Title, [string]$Description, [string]$TargetProjectId, [string]$Labels, [string]$MilestoneId ) $Project = $Project = Get-GitlabProject -Id $ProjectId; $GetUrlParameters = @() $GetUrlParameters += @{source_branch=$SourceBranch} $GetUrlParameters += @{target_branch=$TargetBranch} $GetUrlParameters += @{title=$Title} if ($AssigneeId) { $GetUrlParameters += @{assignee_id=$AssigneeId} } if ($Description) { $GetUrlParameters += @{description=$Description} } if ($TargetProjectId) { $GetUrlParameters += @{target_project_id=$TargetProjectId} } if ($Labels) { $GetUrlParameters += @{labels=$Labels} } if ($MilestoneId) { $GetUrlParameters += @{milestone_id=$MilestoneId} } $URLParameters = GetMethodParameters -GetURLParameters $GetUrlParameters $Request = @{ URI="/projects/$($Project.id)/merge_requests$URLParameters"; Method='POST'; } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.MergeRequest' } Function Remove-GitLabMergeRequest { [cmdletbinding(SupportsShouldProcess,ConfirmImpact='High')] param( [Alias('project_id')] [ValidateNotNullOrEmpty()] [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string]$ProjectId, [ValidateNotNullOrEmpty()] [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string]$Id ) BEGIN {} PROCESS { $Project = $Project = Get-GitlabProject -Id $ProjectId; $Request = @{ URI="/projects/$($Project.id)/merge_requests/$Id"; Method='Delete'; } $MergeRequest = Get-GitLabMergeRequest -Project $ProjectId -Id $Id if ($PSCmdlet.ShouldProcess($MergeRequest.Title, 'Delete Merge Request')) { $Worked = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.MergeRequest' } } END {} } Function Set-GitLabMergeRequest { [cmdletbinding()] param( [Alias('project_id')] [ValidateNotNullOrEmpty()] [Parameter(ValueFromPipelineByPropertyName,Mandatory)] [string]$ProjectId, [ValidateNotNullOrEmpty()] [Parameter(ValueFromPipelineByPropertyName,Mandatory)] [string[]]$ID, [string]$TargetBranch, [string]$AssigneeId, [string]$Title, [string]$Description, [ValidateSet("close", "reopen", "merge")] [string]$StateEvent, [string]$Labels, [string]$MilestoneId, [switch]$Passthru ) BEGIN {} PROCESS { foreach ( $MergeRequestID in $ID ) { $Project = $Project = Get-GitlabProject -Id $ProjectId; $MergeRequest = Get-GitLabMergeRequest -ProjectId $ProjectId -Id $MergeRequestID Write-Verbose "Project Name: $($Project.Name), Merge Request Name: $($MergeRequest.Name)" $GetUrlParameters = @() if ($TargetBranch) { $GetUrlParameters += @{target_branch=$TargetBranch} } if ($AssigneeId) { $GetUrlParameters += @{assignee_id=$AssigneeId} } if ($Title) { $GetUrlParameters += @{title=$Title} } if ($Description) { $GetUrlParameters += @{description=$Description} } if ($StateEvent) { $GetUrlParameters += @{state_event=$StateEvent} } if ($Labels) { $GetUrlParameters += @{labels=$Labels} } if ($MilestoneId) { $GetUrlParameters += @{milestone_id=$MilestoneId} } $URLParameters = GetMethodParameters -GetURLParameters $GetUrlParameters $Request = @{ URI = "/projects/$($Project.ID)/merge_requests/$($MergeRequest.ID)$URLParameters" Method = 'PUT' } $Results = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.MergeRequest' if ( $Passthru.isPresent ) { $Results } } } END {} } Function Close-GitLabMilestone { [cmdletbinding()] param( [Alias('project_id')] [ValidateNotNullOrEmpty()] [Parameter(ValueFromPipelineByPropertyName,Mandatory)] [string]$ProjectId, [ValidateNotNullOrEmpty()] [Parameter(ValueFromPipelineByPropertyName,Mandatory)] [string[]]$ID, [switch]$Passthru ) BEGIN {} PROCESS { foreach ( $MergeRequestID in $ID ) { $Results = Set-GitLabMilestone -Project $ProjectId -Id $ID -StateEvent close if ( $Passthru.isPresent ) { $Results } } } END {} } Function Get-GitLabMilestone { [cmdletbinding(DefaultParameterSetName='MergeRequests')] [OutputType('GitLab.Milestone')] param ( [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName='Single',Mandatory)] [Parameter(ParameterSetName='MergeRequests',Mandatory)] [string]$ProjectId, [Parameter(ParameterSetName='Single',Mandatory)] [string]$Id, [Parameter(ParameterSetName='MergeRequests')] # milestone iid [string]$Iid, [Parameter(ParameterSetName='MergeRequests')] # possible values: active, closed [string]$State ) $Project = Get-GitlabProject -Id $ProjectId; if($PSCmdlet.ParameterSetName -ne 'Single') { $GetUrlParameters = @() if ($Iid) { $GetUrlParameters += @{iid=$Id} } if ($State) { $GetUrlParameters += @{state=$State} } $URLParameters = GetMethodParameters -GetURLParameters $GetUrlParameters } $Request = @{ URI = '' Method = 'GET' } switch ($PSCmdlet.ParameterSetName) { MergeRequests { $Request.URI="/projects/$($Project.id)/milestones$URLParameters"; break; } Single { $Request.URI="/projects/$($Project.id)/milestones/$Id"; break; } default { Write-Error "Incorrect parameter set."; break; } } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Milestone' } Function New-GitLabMilestone { [cmdletbinding()] param( [ValidateNotNullOrEmpty()] [Parameter(Mandatory)] [string]$ProjectId, [ValidateNotNullOrEmpty()] [Parameter(Mandatory)] [string]$Title, [string]$Description, [datetime]$DueDate ) $Project = $Project = Get-GitlabProject -Id $ProjectId; $GetUrlParameters = @() $GetUrlParameters += @{title=$Title} if ($Description) { $GetUrlParameters += @{description=$Description} } if ($DueDate) { $GetUrlParameters += @{due_date=($DueDate).ToString("yyyy-MM-dd")} } $URLParameters = GetMethodParameters -GetURLParameters $GetUrlParameters $Request = @{ URI="/projects/$($Project.id)/milestones$URLParameters"; Method='POST'; } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Milestone' } Function Set-GitLabMilestone { [cmdletbinding()] param( [Alias('project_id')] [ValidateNotNullOrEmpty()] [Parameter(ValueFromPipelineByPropertyName,Mandatory)] [string]$ProjectId, [ValidateNotNullOrEmpty()] [Parameter(ValueFromPipelineByPropertyName,Mandatory)] [string[]]$ID, [string]$Title, [string]$Description, [Nullable[datetime]]$DueDate, [Alias('state_event')] [ValidateSet("close", "activate")] [string]$StateEvent ) BEGIN {} PROCESS { foreach ( $MilestoneID in $ID ) { $Project = $Project = Get-GitlabProject -Id $ProjectId; $Milestone = Get-GitLabMilestone -ProjectId $ProjectId -Id $MilestoneID Write-Verbose "Project Name: $($Project.Name), Milestone Name: $($Milestone.Name)" $GetUrlParameters = @() if ($Title) { $GetUrlParameters += @{title=$Title} } if ($Description) { $GetUrlParameters += @{description=$Description} } if ($DueDate) { $GetUrlParameters += @{due_date=$DueDate.ToString("yyyy-MM-dd")} } if ($StateEvent) { $GetUrlParameters += @{state_event=$StateEvent} } $URLParameters = GetMethodParameters -GetURLParameters $GetUrlParameters $Request = @{ URI = "/projects/$($Project.ID)/milestones/$($Milestone.ID)$URLParameters" Method = 'PUT' } $Results = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Milestone' if ( $Passthru.isPresent ) { $Results } } } END {} } Function Get-GitLabNamespace { [cmdletbinding()] [OutputType('GitLab.Namespace')] param ( [string]$search ) $GetUrlParameters = @() if ($search -ne $null) { $GetUrlParameters += @{search=$search} } $GetUrlParameters += @{per_page=100} $URLParameters = GetMethodParameters -GetURLParameters $GetUrlParameters #$Request.URI = "$($Request.URI)" + "$URLParameters" $Request = @{ URI="/namespaces$URLParameters"; Method='Get'; } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Namespace' } Function Get-GitLabProject { [cmdletbinding(DefaultParameterSetName='Projects')] [OutputType("GitLab.Project")] param( [Parameter(ParameterSetName='Single', Mandatory=$true)] [int]$Id, [Parameter(Mandatory=$false, ParameterSetName='Projects', HelpMessage='Return only archived projects')] [Parameter(Mandatory=$false, ParameterSetName='Owned', HelpMessage='Return only archived projects')] [Parameter(Mandatory=$false, ParameterSetName='All', HelpMessage='Return only archived projects')] [Parameter(Mandatory=$false, ParameterSetName='Starred', HelpMessage='Return only archived projects')] [switch]$Archived = $false, [Parameter(Mandatory=$false, HelpMessage='Limit by visibility', ParameterSetName='Projects')] [Parameter(Mandatory=$false, HelpMessage='Limit by visibility', ParameterSetName='Owned')] [Parameter(Mandatory=$false, HelpMessage='Limit by visibility', ParameterSetName='All')] [Parameter(Mandatory=$false, HelpMessage='Limit by visibility', ParameterSetName='Starred')] [ValidateSet("public", "internal", "private","none")] $Visibility = 'none', [Parameter(Mandatory=$false, HelpMessage='Choose the order in which projects are returned.', ParameterSetName='Projects')] [Parameter(Mandatory=$false, HelpMessage='Choose the order in which projects are returned.', ParameterSetName='Owned')] [Parameter(Mandatory=$false, HelpMessage='Choose the order in which projects are returned.', ParameterSetName='All')] [Parameter(Mandatory=$false, HelpMessage='Choose the order in which projects are returned.', ParameterSetName='Starred')] [ValidateSet('id','name','path','created_at','updated_at','last_activity_at')] $Order_by = 'created_at', [Parameter(Mandatory=$false, HelpMessage='Ascending or Descending', ParameterSetName='Projects')] [Parameter(Mandatory=$false, HelpMessage='Ascending or Descending', ParameterSetName='Owned')] [Parameter(Mandatory=$false, HelpMessage='Ascending or Descending', ParameterSetName='All')] [Parameter(Mandatory=$false, HelpMessage='Ascending or Descending', ParameterSetName='Starred')] [ValidateSet('asc','desc')] $Sort = 'desc', [Parameter(Mandatory=$false, HelpMessage='Search for a project.', ParameterSetName='Projects')] [Parameter(Mandatory=$false, HelpMessage='Search for a project.', ParameterSetName='Owned')] [Parameter(Mandatory=$false, HelpMessage='Search for a project.', ParameterSetName='All')] [Parameter(Mandatory=$false, HelpMessage='Search for a project.', ParameterSetName='Starred')] $Search, [Parameter(ParameterSetName='Owned', Mandatory=$true)] [switch]$Owned, [Parameter(ParameterSetName='All', Mandatory=$true)] [switch]$All, [Parameter(ParameterSetName='Starred', Mandatory=$true)] [switch]$Starred ) if ($PSCmdlet.ParameterSetName -ne 'Single') { Write-Verbose "Create GET Request" $GetUrlParameters = @() if ($archived) { $GetUrlParameters += @{archived='true'} } if ($search -ne $null) { $GetUrlParameters += @{search=$search} } $GetUrlParameters += @{order_by=$order_by} $GetUrlParameters += @{sort=$sort} $GetUrlParameters += @{per_page=100} $URLParameters = GetMethodParameters -GetURLParameters $GetUrlParameters #$Request.URI = "$($Request.URI)" + "$URLParameters" } $Request = @{ URI = '' Method = 'GET' } Write-Verbose "Parameter Set Name: $($PSCmdlet.ParameterSetName)" switch ($PSCmdlet.ParameterSetName) { Projects { $Request.URI = "/projects$URLParameters"; break; } Owned { $Request.URI = "/projects/owned$URLParameters"; break; } All { $Request.URI="/projects/all$URLParameters"; break; } Starred { $Request.URI="/projects/starred$URLParameters"; break; } Single { $Request.URI="/projects/$Id"; break; } default { Write-Error "Incorrect parameter set."; break; } } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project' } Function Get-GitLabProjectArchive { [OutputType('String')] param( [parameter(mandatory,HelpMessage = 'Project ID')][int]$ProjectID, [string]$CommitID = $null, [string]$OutFile = "$PWD\test.zip" ) $Commits = Get-GitLabProjectCommit -id $ProjectID IF (-not($CommitID)) { $CommitID = $Commits[0].id #most recent commit id } ElseIF ($Commits | Where-Object -FilterScript { $_.id -eq $CommitID }) { Write-Verbose -Message ('Commit id OK') } Else { Throw 'Commit ID bad' } $ProjectName = (Get-GitLabProject | Where-Object -FilterScript { ($_.id -eq $ProjectID) }).Name $RequestURI = ('/projects/{0}/repository/archive.zip?sha={1}' -f $ProjectID, $CommitID) DownloadFromGitLabAPI -RequestURI $RequestURI -OutFile $OutFile return ('Project ID:{0} Archive saved to {1}' -f $ProjectID, $OutFile) } Function Get-GitLabProjectCommit { [OutputType('GitLab.Project.Commit')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace } } $Request = @{ URI = "/projects/$($Project.id)/repository/commits" Method = 'GET' } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Commit' } Function Get-GitLabProjectEvent { [cmdletbinding()] [OutputType('GitLab.Project.Event')] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName='Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName='Namespace')] [string]$Namespace ) $queryID = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $queryID = $id } 'Namespace' { $queryID = $Namespace -replace '/','%2F' -replace ' ','' } } $Request = @{ URI="/projects/$queryID/events"; Method='Get'; } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Event' } function Get-GitlabProjectRepositoryTree { [OutputType('GitLab.Repository.Tree')] [cmdletbinding()] param( [parameter(mandatory,HelpMessage='Project ID')][int]$ProjectID, [string]$CommitID ) $Commits = Get-GitLabProjectCommit -Id $ProjectID IF (-not($CommitID)) { $CommitID = $Commits[0].id #most recent commit id } ElseIF ($Commits | Where-Object -FilterScript { $_.id -eq $CommitID }) { Write-Verbose -Message ('Commit id OK') } Else { Throw 'Commit ID bad' } $repoTree = (QueryGitLabAPI -Request @{ URI = ('/projects/{0}/repository/tree?ref_name={1}&recursive=true' -f $ProjectID, $CommitID) Method = 'GET' } -ObjectType 'GitLab.Repository.Tree') $repoTree | Add-Member -MemberType NoteProperty -Name 'ProjectID' -Value $ProjectID $repoTree | Add-Member -MemberType NoteProperty -Name 'CommitID' -Value $CommitID return $repoTree } Function Get-GitLabProjectServiceMSTeams { [OutputType('GitLab.Project.Service.MSTeams')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace } } $Request = @{ URI = "/projects/$($Project.id)/services/microsoft-teams" Method = 'GET' } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Service.MSTeams' } Function Get-GitLabProjectServiceSlack { [OutputType('GitLab.Project.Service.Slack')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace } } $Request = @{ URI = "/projects/$($Project.id)/services/slack" Method = 'GET' } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Service.Slack' } function Get-GitlabProjectSubmodule { [OutputType('GitLab.Project.Submodule.Information')] [cmdletbinding()] param( [parameter(mandatory,HelpMessage='Project ID')][int]$ProjectID, [string]$CommitID ) $repoTree = Get-GitlabProjectRepositoryTree -ProjectID $ProjectID If (-not($repotree | Where-Object -FilterScript { ($_.Type -eq 'blob') -and ($_.name -eq '.gitmodules') })) { Throw ('.gitmodules file missing from Project {0}' -f $ProjectID) } $Projects = Get-GitLabProject $repoTree = $repoTree | Where-Object -FilterScript { $_.Type -eq 'commit' } $Request = @{ URI = ('/projects/{0}/repository/files/.gitmodules?ref={1}' -f $repoTree[0].ProjectID, $repoTree[0].CommitID) Method = 'GET' } $GitsubmoduleFile = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String((QueryGitLabAPI -Request $Request -ObjectType 'File').content)) $Gitsubmodules = $GitsubmoduleFile.Split('[]') -ne '' | ForEach-Object -Begin { $i = 0 } -Process { if ($i++ % 2) { [PSCustomObject](ConvertFrom-StringData -StringData $_) } } $Object = @() Foreach ($commit in $repoTree) { $SubmoduleURL = ($Gitsubmodules | Where-Object -FilterScript { $_.path -eq $commit.Path }).url $SubmoduleProjectName = $SubmoduleURL.Split('/')[-1].Replace('.git','') $SubModuleNamespace = $SubmoduleURL.Split('/')[-2] $SubmoduleProjectID = ($Projects | Where-Object -FilterScript { $_.name -eq $SubmoduleProjectName }).Id $hash = [pscustomobject]@{ ParentProjectID = $commit.ProjectID ParentProjectCommitID = $commit.CommitID SubModuleNamespace = $SubModuleNamespace SubmoduleProjectID = $SubmoduleProjectID SubmoduleProjectName = $SubmoduleProjectName SubmodulePath = $commit.Path SubmoduleFoldername = $commit.Name SubmoduleURL = $SubmoduleURL SubmoduleProjectCommitID = $commit.ID } $Object += $hash } $Object } Function Get-GitLabProjectTag { [OutputType('GitLab.Project.Tag')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace } } $Request = @{ URI = "/projects/$($Project.id)/repository/tags" Method = 'GET' } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Tag' } Function Get-GitLabProjectWebhook { [OutputType('GitLab.Project.Webhook')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace } } $Request = @{ URI = "/projects/$($Project.id)/hooks" Method = 'GET' } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Webhook' } Function New-GitLabFork { [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName='Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace } } $Request = @{ URI="/projects/fork/$($Project.id)"; Method='POST'; } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project' } Function New-GitLabProject { [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(Mandatory=$true)] [string]$name, [string]$path, [string]$namespace, [string]$description, [switch]$issues_enabled, [switch]$merge_requests_enabled, [switch]$builds_enabled, [switch]$wiki_enabled, [Switch]$snippets_enabled, [Switch]$container_registry_enabled, [Switch]$public, [ValidateSet("Private", "Internal", "Public")] [String]$visibility_level ) $Body = @{ name = $Name } $PSBoundParameters.Remove('Name') | Out-Null try { if ($PSBoundParameters.ContainsKey('Namespace')) { $nSpace = Get-GitLabNamespace | Where-Object {$_.path -eq "$Namespace"} if ($nSpace.id.Count -eq 1) { $Body.Add('namespace_id', $nSpace.id) $PSBoundParameters.Remove('Namespace') | Out-Null } else { throw "Error: No Namespace found" } foreach($p in $PSBoundParameters.GetEnumerator()) { if ($p.Key -eq 'visibility_level') { $vLevel = switch ($p.Value) { 'Private' {0} 'Internal' {10} 'Public' {20} } $Body.Add($p.Key, $vLevel) } else { $Body.Add($p.Key, $p.Value) } } $Request = @{ URI='/projects'; Method='POST'; Body=$Body; } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project' } } catch { Write-Error $_ } } Function New-GitLabProjectWebhook { [OutputType('GitLab.Project.Webhook')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace, [parameter(mandatory,HelpMessage = 'WebHook URL')][string]$URL, [switch]$push_events, [switch]$issues_events, [switch]$merge_requests_events, [switch]$tag_push_events, [switch]$note_events, [switch]$pipeline_events, [switch]$wiki_events, [switch]$enable_ssl_verification, [string]$Token ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id $null = $PSBoundParameters.Remove('Id') } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace $null = $PSBoundParameters.Remove('Namespace') } } $Body = @{ id = $Project.id url = $URL } If ($PSBoundParameters.ContainsKey('verbose')) { $null = $PSBoundParameters.Remove('verbose') } $PSBoundParameters.Remove('URL') If (-not($PSBoundParameters.ContainsKey('enable_ssl_verification'))) { $PSBoundParameters.Add('enable_ssl_verification',$False) } try { foreach($p in $PSBoundParameters.GetEnumerator()) { $Body.Add($p.Key, $($p.Value)) } $Request = @{ URI = "/projects/$($Project.id)/hooks" Method = 'POST' Body = $Body } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Webhook' } catch { Write-Error -Message $_ } } Function Remove-GitLabProject { [cmdletbinding(SupportsShouldProcess=$True,ConfirmImpact='High')] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [string]$Id ) BEGIN {} PROCESS { $Request = @{ URI="/projects/$ID"; Method='Delete'; } $Project = Get-GitLabProject -Id $Id if ($PSCmdlet.ShouldProcess($Project.Name, 'Delete Project')) { $Worked = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project' } } END {} } Function Remove-GitLabProjectServiceMSTeams { [OutputType('GitLab.Project.Service.MSTeams')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id $null = $PSBoundParameters.Remove('Id') } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace $null = $PSBoundParameters.Remove('Namespace') } } If ($PSBoundParameters.ContainsKey('verbose')) { $null = $PSBoundParameters.Remove('verbose') } try { $Request = @{ URI = "/projects/$($Project.id)/services/microsoft-teams" Method = 'DELETE' } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Services.MSTeams' } catch { Write-Error -Message $_ } } Function Remove-GitLabProjectServiceSlack { [OutputType('GitLab.Project.Service.Slack')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id $null = $PSBoundParameters.Remove('Id') } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace $null = $PSBoundParameters.Remove('Namespace') } } If ($PSBoundParameters.ContainsKey('verbose')) { $null = $PSBoundParameters.Remove('verbose') } try { $Request = @{ URI = "/projects/$($Project.id)/services/slack" Method = 'DELETE' } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Services.Slack' } catch { Write-Error -Message $_ } } Function Remove-GitLabProjectWebhook { [OutputType('GitLab.Project.Webhook')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace, [parameter(mandatory,HelpMessage = 'Webhook id')][string]$hook_id ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id $null = $PSBoundParameters.Remove('Id') } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace $null = $PSBoundParameters.Remove('Namespace') } } If ($PSBoundParameters.ContainsKey('verbose')) { $null = $PSBoundParameters.Remove('verbose') } $Body = @{ id = $Project.id url = $URL hook_id = $hook_id } try { $Request = @{ URI = "/projects/$($Project.id)/hooks/$hook_id" Method = 'DELETE' Body = $Body } $Body QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Webhook' } catch { Write-Error -Message $_ } } Function Set-GitLabProject { [cmdletbinding()] param( [ValidateNotNullOrEmpty()] [Parameter( Mandatory=$true, ParameterSetName='ID', ValueFromPipelineByPropertyName=$true )] [string[]]$ID, [string]$Name = $null, [string]$Path = $null, [string]$Description = $null, #$default_branch, #[Alias('issues_enabled')] #[switch]$IssuesEnabled = $false, #$merge_requests_enabled, #$wiki_enabled, #$snippets_enabled, #$public, [Alias('visibility_level')] [ValidateSet("Public", "Internal", "Private")] $VisabilityLevel = $null, [switch]$Passthru ) BEGIN {} PROCESS { foreach ( $ProjID in $ID ) { $Project = Get-GitLabProject -Id $ProjID Write-Verbose "Project Name: $($Project.Name)" $Body = @{} if ($Name -ne $null) { $Body.Add('name',$Name) } if ($Path -ne $null) { $Body.Add('path',$Path) } if ($Description -ne $null) { $Body.Add('description',$Description) } if ($VisabilityLevel -ne $null ) { $Body.Add('visibility_level', (GetVisibilityLevel $VisabilityLevel) )} Write-Verbose ( $PSBoundParameters | ConvertTo-Json ) Write-Verbose "Body: $($Body | ConvertTo-Json )" $Request = @{ URI = "/projects/$($Project.ID)" Method = 'PUT' Body = $Body ContentType = 'application/x-www-form-urlencoded' } $Results = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User' if ( $Passthru.isPresent ) { $Results } } } END {} } Function Set-GitLabProjectServiceMSTeams { [OutputType('GitLab.Project.Service.MSTeams')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace, [parameter(mandatory,HelpMessage='MSTeams Webhook')][string]$webhook ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id $null = $PSBoundParameters.Remove('Id') } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace $null = $PSBoundParameters.Remove('Namespace') } } If ($PSBoundParameters.ContainsKey('verbose')) { $null = $PSBoundParameters.Remove('verbose') } $Body = @{ webhook = $webhook } $null = $PSBoundParameters.Remove('webhook') try { $Request = @{ URI = "/projects/$($Project.id)/services/microsoft-teams" Method = 'PUT' Body = $Body ContentType = 'application/x-www-form-urlencoded' } $Body QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Service.MSTeams' } catch { Write-Error -Message $_ } } Function Set-GitLabProjectServiceSlack { [OutputType('GitLab.Project.Service.Slack')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace, [parameter(mandatory,HelpMessage='Slack Webhook')][string]$webhook ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id $null = $PSBoundParameters.Remove('Id') } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace $null = $PSBoundParameters.Remove('Namespace') } } If ($PSBoundParameters.ContainsKey('verbose')) { $null = $PSBoundParameters.Remove('verbose') } $Body = @{ webhook = $webhook } $null = $PSBoundParameters.Remove('webhook') try { $Request = @{ URI = "/projects/$($Project.id)/services/slack" Method = 'PUT' Body = $Body ContentType = 'application/x-www-form-urlencoded' } $Body QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Service.Slack' } catch { Write-Error -Message $_ } } Function Set-GitLabProjectWebhook { [OutputType('GitLab.Project.Webhook')] [cmdletbinding()] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(ParameterSetName = 'Id')] [string]$Id, [ValidateNotNull()] [ValidateNotNullOrEmpty()] #[Parameter(ParameterSetName='Namespace')] [string]$Namespace, [parameter(mandatory,HelpMessage='Webhook URL')][string]$URL, [parameter(mandatory,HelpMessage='Hook ID')][string]$hook_id, [switch]$push_events, [switch]$issues_events, [switch]$merge_requests_events, [switch]$tag_push_events, [switch]$note_events, [switch]$pipeline_events, [switch]$wiki_events, [switch]$enable_ssl_verification, [string]$Token ) $Project = $null switch ($PSCmdlet.ParameterSetName) { 'Id' { $Project = Get-GitLabProject -Id $Id $null = $PSBoundParameters.Remove('Id') } 'Namespace' { $Project = Get-GitLabProject -Namespace $Namespace $null = $PSBoundParameters.Remove('Namespace') } } If ($PSBoundParameters.ContainsKey('verbose')) { $null = $PSBoundParameters.Remove('verbose') } $Body = @{ id = $Project.id url = $URL } $null = $PSBoundParameters.Remove('URL') try { foreach($p in $PSBoundParameters.GetEnumerator()) { $Body.Add($p.Key, $($p.Value)) } $Request = @{ URI = "/projects/$($Project.id)/hooks/$hook_id" Method = 'PUT' Body = $Body ContentType = 'application/x-www-form-urlencoded' } $Body QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Project.Webhook' } catch { Write-Error -Message $_ } } Function Get-GitLabCommitStats { [cmdletbinding()] [OutputType('GitLab.Commit')] param( [Parameter(ParameterSetName="Id",Mandatory=$true)] [Parameter(ParameterSetName="IdAuth",Mandatory=$true)] [Parameter(ParameterSetName="IdLastYear",Mandatory=$true)] [Parameter(ParameterSetName="IdByAuthor",Mandatory=$false)] [Parameter(ParameterSetName="IdBDate",Mandatory=$true)] [Parameter(ParameterSetName="IdADate",Mandatory=$true)] [Parameter(ParameterSetName="IdBothDate",Mandatory=$true)] [int]$Id, [Parameter(ParameterSetName="All",Mandatory=$true)] [Parameter(ParameterSetName="AllAuth",Mandatory=$true)] [Parameter(ParameterSetName="AllLastYear",Mandatory=$true)] [Parameter(ParameterSetName="AllByAuthor",Mandatory=$false)] [Parameter(ParameterSetName="AllBDate",Mandatory=$true)] [Parameter(ParameterSetName="AllADate",Mandatory=$true)] [Parameter(ParameterSetName="AllBothDate",Mandatory=$true)] [switch]$All, [Parameter(ParameterSetName="IdAuth",Mandatory=$true)] [Parameter(ParameterSetName="IdLastYear",Mandatory=$false)] [Parameter(ParameterSetName="IdByAuthor",Mandatory=$false)] [Parameter(ParameterSetName="IdBDate",Mandatory=$false)] [Parameter(ParameterSetName="IdADate",Mandatory=$false)] [Parameter(ParameterSetName="AllAuth",Mandatory=$true)] [Parameter(ParameterSetName="AllLastYear",Mandatory=$false)] [Parameter(ParameterSetName="AllByAuthor",Mandatory=$false)] [Parameter(ParameterSetName="AllBDate",Mandatory=$false)] [Parameter(ParameterSetName="AllADate",Mandatory=$false)] [Parameter(ParameterSetName="IdBothDate",Mandatory=$false)] [Parameter(ParameterSetName="AllBothDate",Mandatory=$false)] [string[]]$author = "*", [Parameter(ParameterSetName="IdBDate",Mandatory=$true)] [Parameter(ParameterSetName="AllBDate",Mandatory=$true)] [Parameter(ParameterSetName="IdBothDate",Mandatory=$true)] [Parameter(ParameterSetName="AllBothDate",Mandatory=$true)] [datetime]$beforeDate, [Parameter(ParameterSetName="IdADate",Mandatory=$true)] [Parameter(ParameterSetName="AllADate",Mandatory=$true)] [Parameter(ParameterSetName="IdBothDate",Mandatory=$true)] [Parameter(ParameterSetName="AllBothDate",Mandatory=$true)] [datetime]$afterDate, [Parameter(ParameterSetName="IdLastYear",Mandatory=$true)] [Parameter(ParameterSetName="AllLastYear",Mandatory=$true)] [switch]$lastYear, [Parameter(ParameterSetName="IdByAuthor",Mandatory=$true)] [Parameter(ParameterSetName="AllByAuthor",Mandatory=$true)] [switch]$byAuthor ) try { $commits = @() $dtcommits = @() if (!($Id)) { $allProjectsId = (Get-GitLabProject -All).Id foreach ($project in $allProjectsId) { $Request = @{ URI="/projects/$project/repository/commits?per_page=100"; Method='Get'; } $commits += QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Commit' -Version "v4" } } else { $Request = @{ URI="/projects/$Id/repository/commits?per_page=100"; Method='Get'; } $commits = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.Commit' -Version "v4" } foreach ($name in $author) { if ($lastYear) { $dtCommits += $commits | Where-Object {[datetime]$_.created_at -ge ((Get-Date).AddDays(-365))} | Where-Object {$_.author_name -like $name} } elseif ($beforeDate) { if ($afterDate) { if ($beforeDate -le $afterDate) { throw "beforeDate cannot be less than afterDate" } else { $dtCommits += $commits | Where-Object {([datetime]$_.created_at -le (Get-Date $beforeDate)) -and ([datetime]$_.created_at -ge (Get-Date $afterDate))} | Where-Object {$_.author_name -like $name} } } else { $dtCommits += $commits | Where-Object {[datetime]$_.created_at -le (Get-Date $beforeDate)} | Where-Object {$_.author_name -like $name} } } elseif ($afterDate) { $dtCommits += $commits | Where-Object {[datetime]$_.created_at -ge (Get-Date $afterDate)} | Where-Object {$_.author_name -like $name} } else { $dtCommits += $commits | Where-Object {$_.author_name -like $name} } } if ($dtCommits) { if ($byAuthor) { FormatCommits -dtCommits $dtCommits -ByAuthor } else { FormatCommits -dtCommits $dtCommits -ByWeek } } else { Write-Output "No commits found" } } catch { Write-Error $_.Exception.Message } } Function Block-GitLabUser { [cmdletbinding(DefaultParameterSetName='ID')] param( [Parameter(Mandatory=$True, ParameterSetName='ID', ValueFromPipelineByPropertyName=$true)] [string]$ID, [Parameter(Mandatory=$True, ParameterSetName='Username')] [string]$Username, [Parameter(Mandatory=$True, ParameterSetName='Email')] [string]$Email, [switch] $Passthru = $false ) BEGIN {} PROCESS { Write-Verbose "$ID" switch ($PSCmdlet.ParameterSetName) { 'ID' { $User = Get-GitLabUser -ID $ID } 'Email' { $User = Get-GitLabUser -ID $Email } 'Username' { $User = Get-GitLabUser -ID $Username } } $request = @{ URI = "/users/$($User.ID)/block" Method = 'PUT' } $null = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User' if ($Passthru.IsPresent) { Get-GitLabuser -id $User.ID } } END {} } Function Get-GitLabUser { [cmdletbinding(DefaultParameterSetName='All')] [OutputType('GitLab.User')] param( [Parameter(ParameterSetName='ID')] [string]$ID, [Parameter(ParameterSetName='All')] [switch]$All, [Parameter(ParameterSetName='Username')] [string]$Username, [Parameter(ParameterSetName='Email')] [string]$Email, [Parameter(ParameterSetName='CurrentUser')] [switch]$CurrentUser ) $Request = @{ URI = '/users' Method = 'GET' } switch ( $PSCmdlet.ParameterSetName) { 'ID' { $Request.URI = "/users/$ID" } 'All' { $Request.URI = '/users' } 'CurrentUser' { $Request.URI = '/user' } } if ( $PSCmdlet.ParameterSetName -eq 'Username') { QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User' | where-object { $_.username -eq $Username } } elseif ( $PSCmdlet.ParameterSetName -eq 'Email') { QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User' | where-object { $_.email -eq $email } } else { QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User' } } Function New-GitLabUser { [CmdletBinding()] param ( [ValidateNotNullOrEmpty()] [Parameter(Mandatory=$true)] [string]$Email, [ValidateNotNullOrEmpty()] [ValidatePattern("(?# Error: Password Must Contain at least 8 characters).{8,}")] [Parameter(Mandatory=$true)] [string]$Password, [ValidateNotNullOrEmpty()] [Parameter(Mandatory=$true)] [string]$Username, [ValidateNotNullOrEmpty()] [Parameter(Mandatory=$true)] [string]$Name, [string]$SkypeID = $null, [string]$LinkedIn = $null, [string]$Twitter = $null, [string]$WebsiteURL = $null, [int]$ProjectsLimit = 0, [switch]$Admin = $false, [switch]$CanCreateGroup = $false, [switch]$External = $false, [switch]$Passthru = $false ) $Body = @{ email = $Email password = $Password username = $Username name = $Name } if ($SkypeID -ne $null ) { $Body.Add('skype',$SkypeID) } if ($LinkedIn -ne $null ) { $Body.Add('linkedin',$LinkedIn) } if ($Twitter -ne $null ) { $Body.Add('twitter',$Twitter) } if ($WebsiteURL -ne $null ) { $Body.Add('website_url',$WebsiteURL) } if ($ProjectsLimit -ne $null ) { $Body.Add('projects_limit',$ProjectsLimit) } if ($Admin.IsPresent ) { $Body.Add('admin','true') } if ($CanCreateGroup.IsPresent ) { $Body.Add('can_create_group','true') } if ($External.IsPresent ) { $Body.Add('external','true') } $Request = @{ URI = '/users' Method = 'POST' Body = $Body } $Results = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User' if ($Passthru.IsPresent) { $Results } } Function Remove-GitLabUser { [cmdletbinding(SupportsShouldProcess=$True,ConfirmImpact='High')] param( [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [string[]]$Username ) BEGIN {} PROCESS { foreach ( $user in $Username ) { $UserInfo = (Get-GitLabUser -Username $User)[0] Write-Verbose "$($UserInfo.Username)" $Request = @{ URI="/users/$($UserInfo.ID)" Method = 'DELETE' } if ( $PSCmdlet.ShouldProcess("Delete User $Username") ) { $Results = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User' } } } END {} } Function Search-GitLabUser { [cmdletbinding()] param( [Parameter(Mandatory=$true)] [string]$User ) $Request = @{ URI="/users?search=$($User)"; Method='Get'; } QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User' -Version "v4" } Function Set-GitLabUser { [cmdletbinding()] param( [ValidateNotNullOrEmpty()] [Parameter(Mandatory=$true,ParameterSetName='ID')] [string]$ID, [ValidateNotNullOrEmpty()] [Parameter(Mandatory=$true,ParameterSetName='Email')] [string]$Email, [ValidateNotNullOrEmpty()] [Parameter(Mandatory=$true,ParameterSetName='Username')] [string]$Username, #[string]$NewEmail = $null, [string]$Password = $null, [string]$NewUsername = $null, [string]$Name = $null, [string]$SkypeID = $null, [string]$LinkedIn = $null, [string]$Twitter = $null, [string]$WebsiteURL = $null, [int]$ProjectsLimit = 0, [switch]$Admin = $false, [switch]$CanCreateGroup = $false, [switch]$External = $false, [switch]$Passthru = $false ) switch ($PScmdlet.ParameterSetName ) { 'Email' { $User = Get-GitLabUser -Email $Email } 'Username' { $User = Get-GitLabUser -Username $UserName } 'ID' { $User = Get-GitLabUser -id $ID } } $Body = @{} #if ($NewEmail -ne $null ) { $Body.Add('email',$NewEmail) } if ($Password -ne $null ) { $Body.Add('password',$Password) } if ($NewUsername -ne $null ) { $Body.Add('username',$NewUsername) } if ($Name -ne $null ) { $Body.Add('name',$Name) } if ($SkypeID -ne $null ) { $Body.Add('skype',$SkypeID) } if ($LinkedIn -ne $null ) { $Body.Add('linkedin',$LinkedIn) } if ($Twitter -ne $null ) { $Body.Add('twitter',$Twitter) } if ($WebsiteURL -ne $null ) { $Body.Add('website_url',$WebsiteURL) } if ($ProjectsLimit -ne 0 ) { $Body.Add('projects_limit',$ProjectsLimit) } if ($Admin.IsPresent ) { $Body.Add('admin','true') } if ($CanCreateGroup.IsPresent ) { $Body.Add('can_create_group','true') } if ($External.IsPresent ) { $Body.Add('external','true') } $Request = @{ URI = "/users/$($User.ID)" Method = 'PUT' Body = $Body ContentType = 'application/x-www-form-urlencoded' } #Write-Debug -Message "Before Request" Write-Verbose "Body: $( $Body | ConvertTo-Json ) " $Results = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User' if ($Passthru.IsPresent) { $Results } } Function Unblock-GitLabUser { [cmdletbinding(DefaultParameterSetName='ID')] param( [Parameter(Mandatory=$True, ParameterSetName='ID', ValueFromPipelineByPropertyName=$true)] [string]$ID, [Parameter(Mandatory=$True, ParameterSetName='Username')] [string]$Username, [Parameter(Mandatory=$True, ParameterSetName='Email')] [string]$Email, [switch] $Passthru = $false ) BEGIN {} PROCESS { Write-Verbose "$ID" switch ($PSCmdlet.ParameterSetName) { 'ID' { $User = Get-GitLabUser -ID $ID } 'Email' { $User = Get-GitLabUser -ID $Email } 'Username' { $User = Get-GitLabUser -ID $Username } } $request = @{ URI = "/users/$($User.ID)/unblock" Method = 'PUT' } $null = QueryGitLabAPI -Request $Request -ObjectType 'GitLab.User' if ($Passthru.IsPresent) { Get-GitLabuser -id $User.ID } } END {} } ########################## # Private Functions ########################## # https://blogs.msdn.microsoft.com/besidethepoint/2010/09/21/decrypt-secure-strings-in-powershell/ function DecryptString { param( [Parameter(ValueFromPipeline=$true,Mandatory=$true,Position=0)] [System.Security.SecureString] $Token ) $marshal = [System.Runtime.InteropServices.Marshal] $ptr = $marshal::SecureStringToBSTR( $token ) $key = $marshal::PtrToStringBSTR( $ptr ) $marshal::ZeroFreeBSTR( $ptr ) $key Remove-Variable key } Function DownloadFromGitLabAPI { <# .SYNOPSIS Download file from GitLab API .DESCRIPTION Download file from GitLab API .PARAMETER RequestURI The URL for download. .PARAMETER OutFile Where to save the file. .EXAMPLE DownloadFromGitLabAPI -RequestURI /projects/1/repository/archive.zip -OutFile C:\Temp\temp.zip Downloads the whole repo in a zip file for project id 1 .NOTES .LINK .INPUTS .OUTPUTS #> [cmdletbinding()] param( [Parameter(Mandatory, HelpMessage = 'URI', Position = 0)] [ValidateNotNullOrEmpty()] [String]$RequestURI, [Parameter(Mandatory, HelpMessage = 'Output File', Position = 1)] [string]$OutFile ) $GitLabConfig = ImportConfig $Domain = $GitLabConfig.Domain if ( $IsWindows -or ( [version]$PSVersionTable.PSVersion -lt [version]'5.99.0' ) ) { $Token = DecryptString -Token $GitLabConfig.Token } elseif ( $IsLinux ) { $Token = $GitLabConfig.Token } $RequestURI = ('{0}/api/v3{1}' -f $Domain, $RequestURI) try { Write-Verbose -Message ('URL: {0}' -f $RequestURI) $wc = New-Object -TypeName System.Net.WebClient $wc.Headers.Add('PRIVATE-TOKEN',$Token) Write-Verbose -Message ('Downloading File from {0} to {1}' -f $RequestURI, $OutFile) $wc.DownloadFile($RequestURI,$OutFile) Remove-Variable -Name Token Remove-Variable -Name RequestURI } catch { $ErrorMessage = $_.exception.response.statusDescription Write-Warning -Message ('{0}. See {1}/help/api/README.md#status-codes for more information.' -f $ErrorMessage, $Domain) } } Function FormatCommits { param( [Parameter(Mandatory=$true)] [psobject]$dtCommits, [switch]$byAuthor, [switch]$byWeek ) $commits = @() $results = @() if ($byAuthor) { $authors = $dtCommits.author_email.ToLower() | sort | unique -AsString $commitHash = @{} foreach ($name in $authors.author_email) { $commitHash.Add($name, 0) } foreach ($c in $dtcommits) { $tempValue = $null $tempValue = $commitHash[$c.author_email] + 1 $commitHash.Set_Item($c.author_email, $tempValue) } foreach ($k in $commitHash.keys) { $tempObj = new-object psobject Add-Member -InputObject $tempObj -MemberType NoteProperty -Name Author -Value $k Add-Member -InputObject $tempObj -MemberType NoteProperty -Name Commits -Value $commitHash[$k] $commits += $tempObj } $results = $commits } if ($byWeek) { foreach ($c in $dtCommits) { $tempObj = new-object psobject Add-Member -InputObject $tempObj -MemberType NoteProperty -Name Week -Value (GetWeek -DateTime $c.created_at) Add-Member -InputObject $tempObj -MemberType NoteProperty -Name Day -Value (Get-Date ([datetime]($c.created_at)) -UFormat %w) $commits += $tempObj } $weeks = $commits | Sort-Object -Property Week | Group-Object -Property Week foreach ($week in $weeks.Name) { $total = 0 $getWeek = $commits | Where-Object {$_.Week -eq $week} $days = $getWeek | Sort-Object -Property Day | Group-Object -Property Day $output = new-object psobject Add-Member -InputObject $output -MemberType NoteProperty -Name Week -Value $week Add-Member -InputObject $output -MemberType NoteProperty -Name Sun -Value 0 Add-Member -InputObject $output -MemberType NoteProperty -Name Mon -Value 0 Add-Member -InputObject $output -MemberType NoteProperty -Name Tue -Value 0 Add-Member -InputObject $output -MemberType NoteProperty -Name Wed -Value 0 Add-Member -InputObject $output -MemberType NoteProperty -Name Thu -Value 0 Add-Member -InputObject $output -MemberType NoteProperty -Name Fri -Value 0 Add-Member -InputObject $output -MemberType NoteProperty -Name Sat -Value 0 foreach ($day in $days) { if ($day.Name -eq 0) { $output.Sun = $day.Count } elseif ($day.Name -eq 1) { $output.Mon = $day.Count } elseif ($day.Name -eq 2) { $output.Tue = $day.Count } elseif ($day.Name -eq 3) { $output.Wed = $day.Count } elseif ($day.Name -eq 4) { $output.Thu = $day.Count } elseif ($day.Name -eq 5) { $output.Fri = $day.Count } elseif ($day.Name -eq 6) { $output.Sat = $day.Count } $total += $day.Count } Add-Member -InputObject $output -MemberType NoteProperty -Name WeeklyTotal -Value $total if ($weeks.Name.Count -gt 1) { $runningTotal += $total Add-Member -InputObject $output -MemberType NoteProperty -Name RunningTotal -Value $runningTotal } $results += $output } } Write-Output $results } Function GetGitLabStatusCode { param( [Parameter(Mandatory=$true)] [int]$StatusCode ) switch ($StatusCode) { '200' { $Text = 'OK - The GET, PUT or DELETE request was successful, the resource(s) itself is returned as JSON' } '201' { $Text = 'Created - The POST request was successful and the resource is returned as JSON' } '400' { $Text = 'Bad Request - A required attribute of the API request is missing, e.g. the title of an issue is not given' } '401' { $Text = 'Unauthorized - The user is not authenticated, a valid user token is necessary, see above' } '403' { $Text = 'Forbidden - The request is not allowed, e.g. the user is not allowed to delete a project' } '404' { $Text = 'Not Found - A resource could not be accessed, e.g. an ID for a resource could not be found' } '405' { $Text = 'Method Not Allowed - The request is not supported' } '409' { $Text = 'Conflict - A conflicting resource already exists, e.g. creating a project with a name that already exists' } '422' { $Text = 'Unprocessable - The entity could not be processed' } '500' { $Text = 'Server Error - While handling the request something went wrong on the server side' } } $Return = [pscustomobject]@{ StatusCode = $StatusCode; StatusText = $Text; } $Return.pstypenames.insert(0,'PSGitLab.Configuration.StatusCode') Write-Output $Return } Function GetMethodParameters { [cmdletbinding()] param( $GetURLParameters ) $string = '?' foreach ($Param in $GetUrlParameters) { $Param.Keys | ForEach-Object { $key = $_ $value = $Param[$_] } $string += "&" $string += [uri]::EscapeDataString($key) $string += "=" $string += [uri]::EscapeDataString($value) } $string = $string -replace '\?&','?' Write-Output $string } function GetVisibilityLevel { param( [ValidateSet("Public", "Internal", "Private")] $String ) switch ($String) { 'Public' { 20; break; } 'Internal' { 10; break; } 'Private' { 0; break; } } } function GetWeek([datetime]$DateTime = (Get-Date)) { $cultureInfo = [System.Globalization.CultureInfo]::CurrentCulture $cultureInfo.Calendar.GetWeekOfYear($DateTime,$cultureInfo.DateTimeFormat.CalendarWeekRule,$cultureInfo.DateTimeFormat.FirstDayOfWeek) } Function ImportConfig { <# .Synopsis Check for configuration and output the information. .DESCRIPTION Check for configuration and output the information. Goes into the $env:appdata for the configuration file. .EXAMPLE ImportConfig #> if ( $IsWindows -or ( [version]$PSVersionTable.PSVersion -lt [version]"5.99.0" ) ) { $ConfigFile = "{0}\PSGitLab\PSGitLabConfiguration.xml" -f $env:appdata } elseif ( $IsLinux ) { $ConfigFile = "{0}/.psgitlab/PSGitLabConfiguration.xml" -f $HOME } else { Write-Error "Unknown Platform" } if (Test-Path $ConfigFile) { Import-Clixml $ConfigFile } else { Write-Warning 'No Saved Configration Information. Run Save-GitLabAPIConfiguration.' break; } } Function QueryGitLabAPI { [cmdletbinding()] param( [Parameter(Mandatory=$true, HelpMessage='A hash table used for splatting against invoke-restmethod.', Position=0)] [ValidateNotNullOrEmpty()] $Request, [Parameter(Mandatory=$false, HelpMessage='Provide a datatype for the returing objects.', Position=1)] [ValidateNotNullOrEmpty()] [string]$ObjectType, [Parameter(Mandatory=$false, HelpMessage='Provide API version to use', Position=2)] [ValidateNotNullOrEmpty()] [string]$Version = 'v3' ) $GitLabConfig = ImportConfig $Domain = $GitLabConfig.Domain if ( $IsWindows -or ( [version]$PSVersionTable.PSVersion -lt [version]"5.99.0" ) ) { $Token = DecryptString -Token $GitLabConfig.Token } elseif ( $IsLinux ) { $Token = $GitLabConfig.Token } $Headers = @{ 'PRIVATE-TOKEN'=$Token; } $Request.Add('Headers',$Headers) $Request.URI = "$Domain/api/$Version" + $Request.URI $Request.UseBasicParsing = $true try { Write-Verbose "URL: $($Request.URI)" $webContent = Invoke-WebRequest @Request $totalPages = ($webContent).Headers['X-Total-Pages'] -as [int] $Results = $webContent.Content | ConvertFrom-Json for ($i=1; $i -lt $totalPages; $i++) { $newRequest = $Request $newRequest.URI = $newRequest.URI + "&page=$($i+1)" $Results += (Invoke-WebRequest @newRequest).Content | ConvertFrom-Json } Remove-Variable Token Remove-Variable Headers Remove-Variable Request } catch { $ErrorMessage = $_.exception.response.statusDescription Write-Warning -Message "$ErrorMessage. See $Domain/help/api/README.md#status-codes for more information." } foreach ($Result in $Results) { $Result.pstypenames.insert(0,$ObjectType) Write-Output $Result } } |