Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save davidwallis/f7bfa21d2c1f223f5f10a0d18d5a2b60 to your computer and use it in GitHub Desktop.
Save davidwallis/f7bfa21d2c1f223f5f10a0d18d5a2b60 to your computer and use it in GitHub Desktop.
New-PowershellModuleWithPipeline.ps1
<#
.SYNOPSIS
New-PowershellModuleWithPipeline.ps1
.DESCRIPTION
Creates a powershell module, git repo, build and branch policies
.PARAMETER Server
The tfs/vsts/azure devops server host name
.PARAMETER ModuleCreationLocation
The folder in which the git repository containing the module will be located.
.PARAMETER PlasterTemplatePath
THe path to the plaster template
.PARAMETER Project
The vsts project name
.PARAMETER BuildQueueName
The vsts build queue name
.PARAMETER AuthorName
Author name for the module manifest
.PARAMETER AuthorEmail
Author email for the module manifest
.PARAMETER ModuleDescription
ModuleDescription
.PARAMETER NoFileCopy
Don't add files to the repo
.EXAMPLE
PS C:\> New-PowershellModuleWithPipeline `
-BuildQueueName BuildQueueName1 `
-Server tfs.something.local
.EXAMPLE
PS C:\> New-PowershellModuleWithPipeline `
-BuildQueueName Generic `
-Server devTfs.something.local
.NOTES
For additional information please contact david@wallis2000.co.uk
.LINK
http://blog.wallis2000.co.uk
#>
[CmdletBinding()]
param (
[ValidateSet("tfs.something.local", "devTfs.something.local")]
[string]$Server = "tfs.something.local",
[Parameter(Mandatory)]
[ValidateScript({ Test-Path $_ -PathType Container})]
[string]$RepoPath,
[Parameter(Mandatory)]
[string]$RepoName,
# TODO validate project name, check url encoding if reqd.
[string]$Project = "ProjectName",
[string]$CollectionName = "MyCollection",
[string]$BuildQueueName = "Generic",
[switch]$NoFileCopy
)
# Get repo before doing anything
$repos = Invoke-RestMethod -Uri "https://$($Server)/tfs/$($CollectionName)$($Project)/_apis/git/repositories?api-version=5.1" -Method GET -ContentType 'application/json' -UseDefaultCredentials -ErrorAction Stop
$repository = $repos.value | where-object {$_.name -eq $RepoName}
if ($null -eq $repository.id) {
throw "Repository not found"
}
Push-Location $RepoPath -ErrorAction Stop
# TODO: create branch.
if (-not $NoFileCopy.IsPresent) {
# THis is hacky - change as you see fit - never intended to publish this code - but a response to a tweet ended up making me do it
git checkout master
git pull
Write-Verbose "Copying build definition to repo"
Copy-Item $PSScriptRoot\build.yaml $RepoPath
Write-Verbose "Adding new psake file to repo"
Copy-Item $PSScriptRoot\build.psake.ps1 $RepoPath
Write-Verbose "Adding .gitignore file to repo"
Copy-Item $PSScriptRoot\.gitignore $RepoPath
Write-Verbose "Adding build yaml file to local git repo and committing module"
git add build.yaml
git add build.psake.ps1
git add .gitignore
git commit -m "Adding build definitions"
Write-Verbose "Pushing repo to remote origin"
git push -u origin master
# Not neeeded currently as commiting to master
# Write-Verbose -NoNewLine 'Create pull req. and press any key to continue...';
# $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
}
Write-Verbose "Getting builds"
$builds = Invoke-RestMethod -Uri "https://$($server)/tfs/$($CollectionName)$($project)/_apis/build/definitions?api-version=5.1" -Method GET -ContentType 'application/json' -UseDefaultCredentials -ErrorAction Stop
$ciBuildJson = @"
{
"name": "$($RepoName)-CI",
"process": {
"type": 2,
"yamlFilename": "build.yaml"
},
"repository": {
"url": "$($repository.remoteUrl)",
"defaultBranch": "refs/heads/master",
"type": "TfsGit",
"id": "$($repository.id)"
},
"type": "build",
"path": "\\",
"queue": {
"name": "$($BuildQueueName)"
},
"project": "$($Project)"
}
"@
Write-Verbose "Finding CI build definition in VSTS"
$ciBuild = $builds.value | where-object {$_.name -eq "$($RepoName)-CI"}
if ($null -ne $ciBuild.id) {
Write-Warning "CI build already exists, Name: $($ciBuild.name) id: $($ciBuild.id) in VSTS"
} else {
Write-Verbose "Configuring CI build in VSTS"
$ciBuild = Invoke-RestMethod -Uri "https://$($Server)/tfs/$($CollectionName)$($Project)/_apis/build/definitions?api-version=5.1" -Headers $header -Body $ciBuildJson -Method Post -ContentType application/json -UseDefaultCredentials -ErrorAction Stop
Write-Verbose "CI build created with id: $($ciBuild.Id)"
}
$releaseBuildJson = @"
{
"name": "$($RepoName)-Release",
"process": {
"type": 2,
"yamlFilename": "build.yaml"
},
"repository": {
"url": "$($repository.remoteUrl)",
"defaultBranch": "refs/heads/master",
"type": "TfsGit",
"id": "$($repository.id)"
},
"type": "build",
"path": "\\",
"queue": {
"name": "$($BuildQueueName)"
},
"project": "$($Project)",
"triggers": [{
"branchFilters": ["+refs/heads/master"],
"pathFilters": [],
"batchChanges": false,
"maxConcurrentBuildsPerBranch": 1,
"pollingInterval": 0,
"triggerType": "continuousIntegration"
}]
}
"@
Write-Verbose "Finding Release build definition in VSTS"
$releaseBuild = $builds.value | where-object {$_.name -eq "$($RepoName)-Release"}
if ($null -ne $releaseBuild.id) {
Write-Warning "Release build already exists, Name: $($releaseBuild.name) id: $($releaseBuild.id) in VSTS"
} else {
Write-Verbose "Configuring Release build in VSTS"
$releaseBuild = Invoke-RestMethod -Uri "https://$($Server)/tfs/$($CollectionName)$($Project)/_apis/build/definitions?api-version=5.1" -Headers $header -Body $releaseBuildJson -Method Post -ContentType application/json -UseDefaultCredentials -ErrorAction Stop
Write-Verbose "Release build created with id: $($releaseBuild.Id)"
}
# Approvers
$minApproversJson= @"
{
"isEnabled": true,
"isBlocking": true,
"type": {
"id": "fa4e907d-c16b-4a4c-9dfa-4906e5d171dd"
},
"settings": {
"minimumApproverCount": 2,
"creatorVoteCounts": true,
"resetOnSourcePush": true,
"allowDownvotes": false,
"scope": [
{
"repositoryId": "$($repository.id)",
"refName": "refs/heads/master",
"matchKind": "exact"
}
]
}
}
"@
Write-Verbose "Setting minimum approvers branch policy"
$null = Invoke-RestMethod -Uri "https://$($Server)/tfs/$($CollectionName)$($Project)/_apis/policy/configurations?api-version=5.1" -Body $minApproversJson -Method Post -ContentType application/json -UseDefaultCredentials -ErrorAction Stop
# https://docs.microsoft.com/en-us/rest/api/azure/devops/policy/configurations/create?view=azure-devops-rest-5.1#approval-count-policy
$approversJSONBody= @"
{
"isEnabled": true,
"isBlocking": true,
"type": {
"id": "fd2167ab-b0be-447a-8ec8-39368250530e"
},
"settings": {
"requiredReviewerIds": [
"40d2cc68-d263-4380-8419-317a9e516f6e"
],
"filenamePatterns": [
"*"
],
"addedFilesOnly": false,
"scope": [
{
"repositoryId": "$($repository.id)",
"refName": "refs/heads/master",
"matchKind": "exact"
}
]
}
}
"@
Write-Verbose "Setting aprovers branch policy"
$null = Invoke-RestMethod -Uri "https://$($Server)/tfs/$($CollectionName)$($Project)/_apis/policy/configurations?api-version=5.1" -Body $approversJSONBody -Method Post -ContentType application/json -UseDefaultCredentials -ErrorAction Stop
$workItemJson = @"
{
"isEnabled": true,
"isBlocking": false,
"type": {
"id": "40e92b44-2fe1-4dd6-b3d8-74a9c21d0c6e"
},
"settings": {
"scope": [
{
"repositoryId": "$($repository.id)",
"refName": "refs/heads/master",
"matchKind": "exact"
}
]
}
}
"@
Write-Verbose "Setting work item branch policy"
$null = Invoke-RestMethod -Uri "https://$($Server)/tfs/$($CollectionName)$($Project)/_apis/policy/configurations?api-version=5.1" -Body $workItemJson -Method Post -ContentType application/json -UseDefaultCredentials -ErrorAction Stop
$buildPolicyJson= @"
{
"isEnabled": true,
"isBlocking": true,
"type": {
"id": "0609b952-1397-4640-95ec-e00a01b2c241"
},
"settings": {
"buildDefinitionId": "$($ciBuild.id)",
"scope": [
{
"repositoryId": "$($repository.id)",
"refName": "refs/heads/master",
"matchKind": "exact"
}
]
}
}
"@
Write-Verbose "Setting build branch policy"
$null = Invoke-RestMethod -Uri "https://$($Server)/tfs/$($CollectionName)$($Project)/_apis/policy/configurations?api-version=5.1" -Body $buildPolicyJson -Method Post -ContentType application/json -UseDefaultCredentials -ErrorAction Stop
$commentJson = @"
{
"isEnabled": true,
"isBlocking": true,
"isDeleted": false,
"type": {
"id": "c6a1889d-b943-4856-b76f-9e46bb6b0df2"
},
"settings": {
"scope": [
{
"repositoryId": "$($repository.id)",
"refName": "refs/heads/master",
"matchKind": "exact"
}
]
}
}
"@
Write-Verbose "Setting comment resolution branch policy"
$null = Invoke-RestMethod -Uri "https://$($Server)/tfs/$($CollectionName)$($Project)/_apis/policy/configurations?api-version=5.1" -Body $commentJson -Method Post -ContentType application/json -UseDefaultCredentials -ErrorAction Stop
pop-location
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment