fiftyone.geolocation 4.2.1 → 4.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/.gitmodules +3 -0
  2. package/README.md +2 -2
  3. package/ci/README.md +2 -0
  4. package/ci/build-and-test.yml +34 -0
  5. package/ci/common-ci/.github/labels.yml +59 -0
  6. package/ci/common-ci/.github/workflows/sync-labels.yml +49 -0
  7. package/ci/common-ci/CiTips.md +34 -0
  8. package/ci/common-ci/GitVersion.yml +18 -0
  9. package/ci/common-ci/LICENSE +286 -0
  10. package/ci/common-ci/README.md +365 -0
  11. package/ci/common-ci/build-and-test.yml +65 -0
  12. package/ci/common-ci/check-merge-commit-format.yml +50 -0
  13. package/ci/common-ci/cloud-release-config.json +51 -0
  14. package/ci/common-ci/create-tag.yml +41 -0
  15. package/ci/common-ci/deploy.yml +25 -0
  16. package/ci/common-ci/dotnet/shared-code-signing-steps.yml +20 -0
  17. package/ci/common-ci/dotnet/shared-extract-and-publish-packages.yml +29 -0
  18. package/ci/common-ci/go/shared-go-list-stage.yml +64 -0
  19. package/ci/common-ci/java/readme.md +22 -0
  20. package/ci/common-ci/java/shared-code-signing-steps.yml +17 -0
  21. package/ci/common-ci/node/shared-extract-and-publish-packages.yml +26 -0
  22. package/ci/common-ci/php/readme.md +15 -0
  23. package/ci/common-ci/release-config-schema.json +52 -0
  24. package/ci/common-ci/release-config-template.json +310 -0
  25. package/ci/common-ci/release-config.json +128 -0
  26. package/ci/common-ci/release-process.drawio +165 -0
  27. package/ci/common-ci/release-process.png +0 -0
  28. package/ci/common-ci/scripts/azure/checkSlot.ps1 +28 -0
  29. package/ci/common-ci/scripts/modules/51DAuthorizationModule/51DAuthorizationModule.Tests.ps1 +1 -0
  30. package/ci/common-ci/scripts/modules/51DAuthorizationModule/51DAuthorizationModule.psm1 +16 -0
  31. package/ci/common-ci/scripts/modules/51DBuildModule/51DBuildModule.Tests.ps1 +3 -0
  32. package/ci/common-ci/scripts/modules/51DBuildModule/51DBuildModule.psm1 +200 -0
  33. package/ci/common-ci/scripts/modules/51DDeployModule/51DDeployModule.psm1 +66 -0
  34. package/ci/common-ci/scripts/modules/51DDownloadDataFileModule/51DDownloadDataFileModule.psm1 +58 -0
  35. package/ci/common-ci/scripts/modules/51DEnvironmentModule/51DEnvironmentModule.Tests.ps1 +25 -0
  36. package/ci/common-ci/scripts/modules/51DEnvironmentModule/51DEnvironmentModule.psm1 +22 -0
  37. package/ci/common-ci/scripts/modules/51DErrorHandleModule/51DErrorHandleModule.Tests.ps1 +1 -0
  38. package/ci/common-ci/scripts/modules/51DErrorHandleModule/51DErrorHandleModule.psm1 +41 -0
  39. package/ci/common-ci/scripts/modules/51DGitModule/51DGitModule.Tests.ps1 +5 -0
  40. package/ci/common-ci/scripts/modules/51DGitModule/51DGitModule.psm1 +698 -0
  41. package/ci/common-ci/scripts/modules/51DPackageModule/51DPackageModule.Tests.ps1 +842 -0
  42. package/ci/common-ci/scripts/modules/51DPackageModule/51DPackageModule.psm1 +926 -0
  43. package/ci/common-ci/scripts/modules/51DPipelineModule/51DPipelineModule.Tests.ps1 +1 -0
  44. package/ci/common-ci/scripts/modules/51DPipelineModule/51DPipelineModule.psm1 +87 -0
  45. package/ci/common-ci/scripts/modules/51DPullRequestModule/51DPullRequestModule.Tests.ps1 +194 -0
  46. package/ci/common-ci/scripts/modules/51DPullRequestModule/51DPullRequestModule.psm1 +653 -0
  47. package/ci/common-ci/scripts/modules/51DReleaseModule/51DReleaseModule.Tests.ps1 +277 -0
  48. package/ci/common-ci/scripts/modules/51DReleaseModule/51DReleaseModule.psm1 +554 -0
  49. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/51DReleaseTestEnvModule.Tests.ps1 +1141 -0
  50. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/51DReleaseTestEnvModule.psd1 +0 -0
  51. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/51DReleaseTestEnvModule.psm1 +1465 -0
  52. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/ConfigurationVerifier.Tests.ps1 +318 -0
  53. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/ConfigurationVerifier.psm1 +344 -0
  54. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/ReleaseVerifier.Tests.ps1 +1186 -0
  55. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/ReleaseVerifier.psm1 +900 -0
  56. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/SharedVariables.psm1 +139 -0
  57. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/c-test-env-config.json +268 -0
  58. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/dotnet-deploy-test-env-config.json +700 -0
  59. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/dotnet-test-env-config.json +533 -0
  60. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/go-deploy-test-env-config.json +290 -0
  61. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/go-test-env-config.json +260 -0
  62. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/java-deploy-test-env-config.json +511 -0
  63. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/java-test-env-config.json +388 -0
  64. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/node-deploy-test-env-config.json +419 -0
  65. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/node-test-env-config.json +329 -0
  66. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/php-test-env-config.json +540 -0
  67. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/python-deploy-test-env-config.json +411 -0
  68. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/python-test-env-config.json +321 -0
  69. package/ci/common-ci/scripts/modules/51DReleaseTestEnvModule/config/test-env-config.json +457 -0
  70. package/ci/common-ci/scripts/modules/51DRestModule/51DRestModule.psm1 +38 -0
  71. package/ci/common-ci/scripts/modules/AzurePortalModules/51DApplicationInsightsModule/51DApplicationInsightsModule.psm1 +104 -0
  72. package/ci/common-ci/scripts/modules/AzurePortalModules/51DChecksModule/51DChecksModule.psm1 +68 -0
  73. package/ci/common-ci/scripts/modules/AzurePortalModules/51DCloudModule/51DCloudModule.psm1 +155 -0
  74. package/ci/common-ci/scripts/modules/AzurePortalModules/51DConnectAzureModule/51DConnectAzureModule.psm1 +45 -0
  75. package/ci/common-ci/scripts/modules/AzurePortalModules/51DSSLBindingsModule/51DSSLBIndingsModule.psm1 +100 -0
  76. package/ci/common-ci/scripts/modules/AzurePortalModules/51DStagingSlotModule/51DStagingSlotModule.psm1 +50 -0
  77. package/ci/common-ci/scripts/modules/AzurePortalModules/51DStorageAccountModule/51DStorageAccountModule.psm1 +248 -0
  78. package/ci/common-ci/scripts/modules/AzurePortalModules/51DTrafficManagerModule/51DTrafficManagerModule.psm1 +58 -0
  79. package/ci/common-ci/shared-auto-complete-pr-stage.yml +61 -0
  80. package/ci/common-ci/shared-create-tag-job.yml +23 -0
  81. package/ci/common-ci/shared-docker-build-steps.yml +34 -0
  82. package/ci/common-ci/shared-docker-push-steps.yml +32 -0
  83. package/ci/common-ci/shared-docker-test-http-steps.yml +69 -0
  84. package/ci/common-ci/shared-git-tag-job.yml +38 -0
  85. package/ci/common-ci/shared-git-version-job.yml +71 -0
  86. package/ci/common-ci/shared-publish-github-stage.yml +107 -0
  87. package/ci/common-ci/shared-submodule-trigger-stage.yml +110 -0
  88. package/ci/common-ci/shared-variables.yml +3 -0
  89. package/ci/common-ci/trigger-release-apis.yml +39 -0
  90. package/ci/create-packages.yml +109 -0
  91. package/ci/deploy-external.yml +55 -0
  92. package/ci/deploy-internal.yml +50 -0
  93. package/ci/shared-build-and-test-platforms.yml +26 -0
  94. package/ci/shared-build-and-test-stage.yml +128 -0
  95. package/ci/shared-variables.yml +7 -0
  96. package/ci/submodule-trigger.yml +12 -0
  97. package/docs/Doxyfile +3 -3
  98. package/docs/DoxygenLayout.xml +1 -1
  99. package/examples/examples.test.js +3 -3
  100. package/geoLocationPipelineBuilder.js +16 -13
  101. package/package.json +14 -6
  102. package/setup.js +1 -0
  103. package/tests/geoLocationCloud.test.js +192 -0
  104. package/tsconfig.json +21 -0
  105. package/types/geoLocationCloud.d.ts +7 -0
  106. package/types/geoLocationPipelineBuilder.d.ts +17 -0
  107. package/types/index.d.ts +2 -0
  108. package/build-and-test.yml +0 -112
  109. package/publish-packages.yml +0 -87
@@ -0,0 +1,1465 @@
1
+ <#
2
+ ===================== Testing =====================
3
+ .Description
4
+ This module contains functions that supports testing
5
+ of the release process.
6
+ For more information, please read description of
7
+ each function.
8
+ #>
9
+
10
+ Using module 51DAuthorizationModule
11
+ Using module .\SharedVariables.psm1
12
+
13
+ <#
14
+ .Description
15
+ This function removes all Cross-Repository 'Required reviewers' policies
16
+ of Release Test Environment, as other policies are most likely default
17
+ policies.
18
+
19
+ .Outputs
20
+ true or false
21
+ #>
22
+ function Remove-AllPolicies {
23
+ Write-Host ""
24
+ Write-Host "Remove all Cross-Repository policies"
25
+ Write-Host "===================================="
26
+
27
+ $url = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/policy/configurations?api-version=6.0"
28
+
29
+ $response = Invoke-WebRequest `
30
+ -URI $url `
31
+ -Headers @{
32
+ Authorization = "$([Authorization]::AuthorizationString)"
33
+ } `
34
+ -Method GET
35
+ if (!$(Test-RestResponse `
36
+ -Response $response `
37
+ -ErrorMessage "Failed to get all policies.")) {
38
+ return $false
39
+ }
40
+
41
+ $content = $response.content | Out-String | ConvertFrom-Json
42
+ foreach ($policy in $content.value) {
43
+ # Only remove policies that adds required reviewers
44
+ if ($policy.type.name -ne "Required reviewer") {
45
+ $url = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/policy/configurations/$($policy.id)?api-version=6.0"
46
+ $response = Invoke-WebRequest `
47
+ -URI $url `
48
+ -Headers @{
49
+ Authorization = "$([Authorization]::AuthorizationString)"
50
+ } `
51
+ -Method DELETE
52
+ if (!$(Test-RestResponse `
53
+ -Response $response `
54
+ -ErrorMessage "Failed to delete policy $($policy.id).")) {
55
+ return $false
56
+ }
57
+ }
58
+ }
59
+ return $true
60
+ }
61
+
62
+ <#
63
+ .Description
64
+ This function removes all definitions of Release Test
65
+ Environments
66
+
67
+ .Outputs
68
+ true or false
69
+ #>
70
+ function Remove-AllDefinitions {
71
+ Write-Host ""
72
+ Write-Host "Remove all definitions"
73
+ Write-Host "======================"
74
+
75
+ $url = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/build/definitions?api-version=6.0"
76
+
77
+ $response = Invoke-WebRequest `
78
+ -URI $url `
79
+ -Headers @{
80
+ Authorization = "$([Authorization]::AuthorizationString)"
81
+ } `
82
+ -Method GET
83
+ if (!$(Test-RestResponse `
84
+ -Response $response `
85
+ -ErrorMessage "Failed to get all definitions.")) {
86
+ return $false
87
+ }
88
+
89
+ $content = $response.content | Out-String | ConvertFrom-Json
90
+ foreach ($definition in $content.value) {
91
+ $url = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/build/definitions/$($definition.id)?api-version=6.0"
92
+ $response = Invoke-WebRequest `
93
+ -URI $url `
94
+ -Headers @{
95
+ Authorization = "$([Authorization]::AuthorizationString)"
96
+ } `
97
+ -Method DELETE
98
+ if (!$(Test-RestResponse `
99
+ -Response $response `
100
+ -ErrorMessage "Failed to delete definition $($definition.id).")) {
101
+ return $false
102
+ }
103
+ }
104
+ return $true
105
+ }
106
+
107
+ <#
108
+ .Description
109
+ WARNINGS: Be very careful when using this function. This function
110
+ will try it best to prevent deleting anything related to Production,
111
+ but user should also take caution when using it. User Account used
112
+ to run this function should never be granted permission to 'Force Push'
113
+ in Production environment. Deleted repositories will be moved to
114
+ 'Recycle Bin' so it is possible to restore them once they have been
115
+ deleted. However, if they have been deleted from the 'Recycle Bin'
116
+ then unless a copy of the repository is kept elsewhere, the repository
117
+ cannot be restored.
118
+ Remove a repository from a test environment.
119
+
120
+ .Parameter Repository
121
+ A repository object returned by the AzureDevops api
122
+
123
+ .Outputs
124
+ true or false
125
+ #>
126
+ function Remove-Repository {
127
+ param (
128
+ [Parameter(Mandatory)]
129
+ [object]$Repository
130
+ )
131
+
132
+ Write-Host ""
133
+ Write-Host "Deleting repository '$($Repository.name)'"
134
+ Write-Host "======================================="
135
+ if ($Repository.name -eq $([TestEnvPredefinedVariables]::MandatoryRepositoryName)) {
136
+ Write-Host "# ERROR: '$([TestEnvPredefinedVariables]::MandatoryRepositoryName)' is a mandatory, so cannot be deleted."
137
+ return $false
138
+ }
139
+
140
+ $url = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/git/repositories/$($Repository.id)?api-version=6.0"
141
+
142
+ $response = Invoke-WebRequest `
143
+ -URI $url `
144
+ -Headers @{
145
+ Authorization = "$([Authorization]::AuthorizationString)"
146
+ } `
147
+ -Method DELETE
148
+
149
+ return $(Test-RestResponse `
150
+ -Response $response `
151
+ -ErrorMessage "Failed to delete repository '$($Repository.name)'.")
152
+ }
153
+
154
+ <#
155
+ .Description
156
+ WARNINGS: Be very careful when using this function. This function
157
+ will try it best to prevent deleting anything related to Production,
158
+ but user should also take caution when using it. User Account used
159
+ to run this function should never be granted permission to 'Force Push'
160
+ in Production environment. Deleted repositories will be moved to
161
+ 'Recycle Bin' so it is possible to restore them once they have been
162
+ deleted. However, if they have been deleted from the 'Recycle Bin'
163
+ then unless a copy of the repository is kept elsewhere, the repository
164
+ cannot be restored.
165
+ Remove all repositories and the properties that associate with them.
166
+
167
+ .Parameter Force
168
+ Force to perform delete. Bypass prompt.
169
+ WARNINGS: Be very careful when eanble this parameter.
170
+
171
+ .Outputs
172
+ true or false
173
+ #>
174
+ function Clear-TestEnvironment {
175
+ param (
176
+ [switch]$Force = $false
177
+ )
178
+ Write-Host ""
179
+ Write-Host "Remove all repositories and their associated attributes"
180
+ Write-Host "======================================================="
181
+ Write-Host "# All repositories in project $([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject) will be deleted."
182
+ Write-Host "# Please confirm that you want to proceed."
183
+ Write-Host "# Y[Yes] N[No]"
184
+ if (!$Force) {
185
+ $answer = Read-Host -Prompt "# Answer"
186
+ if (!$($answer -match "Y|Yes")) {
187
+ Write-Host "# Stopped"
188
+ return $true
189
+ }
190
+ }
191
+
192
+ Write-Host "# Proceed to delete..."
193
+ # Get all existing repositories
194
+ $url = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/git/repositories?api-version=6.0"
195
+
196
+ $response = Invoke-WebRequest `
197
+ -URI $url `
198
+ -Headers @{
199
+ Authorization = "$([Authorization]::AuthorizationString)"
200
+ } `
201
+ -Method GET
202
+
203
+ if ($(Test-RestResponse `
204
+ -Response $response `
205
+ -ErrorMessage "Failed to get all repositories.")){
206
+ $content = $response.content | Out-String | ConvertFrom-Json
207
+ foreach ($repository in $content.value) {
208
+ # Remove the repository except the mandatory one.
209
+ if ($repository.name -ne $([TestEnvPredefinedVariables]::MandatoryRepositoryName) `
210
+ -and !$(Remove-Repository -Repository $repository)) {
211
+ Write-Host "# ERROR: Failed to remove repository '$($repository.name)'"
212
+ return $false
213
+ }
214
+ }
215
+ } else {
216
+ return $false
217
+ }
218
+
219
+ # Clear all pipelines
220
+ if (!$(Remove-AllDefinitions)) {
221
+ Write-Host "# ERROR: Failed to remove all pipelines."
222
+ return $false
223
+ }
224
+
225
+ # Clear all policies
226
+ if (!$(Remove-AllPolicies)) {
227
+ Write-Host "# ERROR: Failed to remove all policies."
228
+ return $false
229
+ }
230
+
231
+ return $true
232
+ }
233
+
234
+ <#
235
+ .Description
236
+ Get a branch object of a repository
237
+
238
+ .Parameter RepositoryName
239
+ Name of a repository that a branch belongs to
240
+
241
+ .Parameter BranchName
242
+ Name of a branch
243
+
244
+ .Outputs
245
+ A branch object or $null
246
+ #>
247
+ function Get-Branch {
248
+ param (
249
+ [Parameter(mandatory)]
250
+ [string]$RepositoryName,
251
+ [Parameter(Mandatory)]
252
+ [string]$BranchName
253
+ )
254
+ # Get based branch id
255
+ $uri = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/git/repositories/$RepositoryName/refs?filter=heads/$($BranchName)&api-version=6.0"
256
+ $response = Invoke-WebRequest -URI $uri `
257
+ -Headers @{
258
+ Authorization = "$([Authorization]::AuthorizationString)"
259
+ } `
260
+ -Method GET
261
+
262
+ $branchObj = $null
263
+ if (!$(Test-RestResponse `
264
+ -Response $response `
265
+ -ErrorMessage "Failed to get objectId of $BranchName of repository $RepositoryName")) {
266
+ return $null
267
+ } else {
268
+ $content = $($response.content | Out-String | ConvertFrom-Json)
269
+ if ($content.value.count -eq 0) {
270
+ Write-Host "# ERROR: No branch matches branch $BranchName"
271
+ return $null
272
+ }
273
+ $branchObj = $content.value[0]
274
+ }
275
+ return $branchObj
276
+ }
277
+
278
+ <#
279
+ .Description
280
+ Add branch to a repository.
281
+
282
+ .Parameter RepositoryName
283
+ Name of a repository object specified in the configuration file.
284
+
285
+ .Parameter Branch
286
+ Branch object from config file.
287
+
288
+ .Outputs
289
+ true or false
290
+ #>
291
+ function Add-RepositoryBranch {
292
+ param (
293
+ [Parameter(Mandatory)]
294
+ [string]$RepositoryName,
295
+ [Parameter(Mandatory)]
296
+ [object]$Branch
297
+ )
298
+
299
+ $branchObj = Get-Branch -RepositoryName $RepositoryName -BranchName $Branch.base
300
+ if ($branchObj -eq $null) {
301
+ Write-Host "# ERROR: Failed to get base branch $($Branch.base) of repository $RepositoryName"
302
+ return $false
303
+ }
304
+
305
+ # Create the branch
306
+ $uri = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/git/repositories/$RepositoryName/refs?api-version=6.0"
307
+ $jsonBody = @"
308
+ [
309
+ {
310
+ "name": "refs/heads/$($Branch.name)",
311
+ "oldObjectId": "0000000000000000000000000000000000000000",
312
+ "newObjectId": "$($branchObj.objectId)"
313
+ }
314
+ ]
315
+ "@
316
+
317
+ $response = Invoke-WebRequest -URI $uri `
318
+ -Headers @{
319
+ Authorization = "$([Authorization]::AuthorizationString)"
320
+ } `
321
+ -Method POST `
322
+ -Body $jsonBody `
323
+ -ContentType "application/json"
324
+
325
+ if (!$(Test-RestResponse `
326
+ -Response $response `
327
+ -ErrorMessage "Failed to add branch $($Branch.name) to repository $RepositoryName")) {
328
+ return $false
329
+ }
330
+ return $true
331
+ }
332
+
333
+ <#
334
+ .Description
335
+ Add branches to a repository.
336
+
337
+ .Parameter RepositoryName
338
+ Name of a repository object specified in the configuration file.
339
+
340
+ .Parameter RepositoryConfig
341
+ The configuration associated with the repository.
342
+
343
+ .Outputs
344
+ true or false
345
+ #>
346
+ function Add-RepositoryBranches {
347
+ param (
348
+ [Parameter(Mandatory)]
349
+ [string]$RepositoryName,
350
+ [Parameter(Mandatory)]
351
+ [object]$RepositoryConfig
352
+ )
353
+ Write-Host ""
354
+ Write-Host "# Adding branches for repository $RepositoryName"
355
+ foreach ($branch in $RepositoryConfig.branches) {
356
+ if (!$(Add-RepositoryBranch -RepositoryName $RepositoryName -Branch $branch)) {
357
+ Write-Host "# ERROR: Failed to create branch $($branch.refName) for repository $RepositoryName"
358
+ return $false;
359
+ }
360
+ }
361
+
362
+ return $true
363
+ }
364
+
365
+ <#
366
+ .Description
367
+ Add a tag to a repository. This will always
368
+ be done on the main|master branch at the last
369
+ commit.
370
+
371
+ .Parameter RepositoryName
372
+ Name of a repository object specified in the configuration file.
373
+
374
+ .Parameter Tag
375
+ Tag name.
376
+
377
+ .Outputs
378
+ true or false
379
+ #>
380
+ function Add-RepositoryTag {
381
+ param (
382
+ [Parameter(Mandatory)]
383
+ [string]$RepositoryName,
384
+ [Parameter(Mandatory)]
385
+ [string]$Tag
386
+ )
387
+
388
+ # Get 'main' branch id
389
+ $mainBranch = Get-MainBranch `
390
+ -TeamProjectName $([TestEnvPredefinedVariables]::TestProject) `
391
+ -RepositoryName $RepositoryName `
392
+ -AuthorizationHeader $([Authorization]::AuthorizationString)
393
+ if ($mainBranch -eq $null) {
394
+ Write-Host "# ERROR: a 'main' or 'master' branch does not exist."
395
+ return $false
396
+ }
397
+
398
+ # Create the tag
399
+ $uri = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/git/repositories/$($RepositoryName)/annotatedtags?api-version=6.1-preview.1"
400
+ $jsonBody = @"
401
+ {
402
+ "name": "$Tag",
403
+ "taggedObject": {
404
+ "objectId": "$($mainBranch.objectId)"
405
+ },
406
+ "message": "$Tag"
407
+ }
408
+ "@
409
+
410
+ $response = Invoke-WebRequest -URI $uri `
411
+ -Headers @{
412
+ Authorization = "$([Authorization]::AuthorizationString)"
413
+ } `
414
+ -Method POST `
415
+ -Body $jsonBody `
416
+ -ContentType "application/json"
417
+
418
+ if (!$(Test-RestResponse `
419
+ -Response $response `
420
+ -ErrorMessage "Failed to add tag $Tag to repository $RepositoryName")) {
421
+ return $false
422
+ }
423
+ return $true
424
+ }
425
+
426
+ <#
427
+ .Description
428
+ Add tags to a repository.
429
+
430
+ .Parameter RepositoryName
431
+ Name of a repository object specified in the configuration file.
432
+
433
+ .Parameter RepositoryConfig
434
+ The configuration associated with the repository.
435
+
436
+ .Outputs
437
+ true or false
438
+ #>
439
+ function Add-RepositoryTags {
440
+ param (
441
+ [Parameter(Mandatory)]
442
+ [string]$RepositoryName,
443
+ [Parameter(Mandatory)]
444
+ [object]$RepositoryConfig
445
+ )
446
+ Write-Host ""
447
+ Write-Host "# Adding tags to repository $RepositoryName"
448
+ foreach ($tag in $RepositoryConfig.tags) {
449
+ if (!$(Add-RepositoryTag -RepositoryName $RepositoryName -Tag $tag)) {
450
+ Write-Host "# ERROR: Failed to create tag $tag for repository $RepositoryName"
451
+ return $false;
452
+ }
453
+ }
454
+
455
+ return $true
456
+ }
457
+
458
+ <#
459
+ .Description
460
+ Update package versions of repository.
461
+
462
+ .Parameter RepositoryName
463
+ Name of a repository object specified in the configuration file.
464
+
465
+ .Parameter RepositoryConfig
466
+ The configuration associated with the repository.
467
+
468
+ .Outputs
469
+ true or false
470
+ #>
471
+ function Update-RepositoryPackageVersions {
472
+ param (
473
+ [Parameter(Mandatory)]
474
+ [string]$RepositoryName,
475
+ [Parameter(Mandatory)]
476
+ [object]$RepositoryConfig
477
+ )
478
+ # NOTE: Currently not needed as updateing versions does not
479
+ # depend on original veresion number.
480
+ return $true
481
+ }
482
+
483
+ <#
484
+ .Description
485
+ Add a repository. The repository will first be cloned from the
486
+ 'Production' environment. They will then be configured accordingly.
487
+
488
+ .Parameter RepositoryName
489
+ Name of a repository object specified in the configuration file.
490
+
491
+ .Parameter RepositoryConfig
492
+ The configuration associated with the repository.
493
+
494
+ .Outputs
495
+ true or false
496
+ #>
497
+ function Add-Repository {
498
+ param (
499
+ [Parameter(Mandatory)]
500
+ [string]$RepositoryName,
501
+ [Parameter(Mandatory)]
502
+ [object]$RepositoryConfig
503
+ )
504
+ Write-Host ""
505
+ Write-Host "Add repository $RepositoryName"
506
+ Write-Host "=============================="
507
+
508
+ # Get repository id
509
+ $repoId = Get-RepositoryId -ProjectName $([TestEnvPredefinedVariables]::ProductionProject) -RepositoryName $RepositoryName
510
+ if ($repoId -eq $null) {
511
+ Write-Host "# ERROR: Failed to get Id of repository $RepositoryName from project $([TestEnvPredefinedVariables]::ProductionProject)"
512
+ return $false
513
+ }
514
+
515
+ # Fork from production
516
+ $uri = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/git/repositories?api-version=6.1-preview.1"
517
+ $jsonBody = @"
518
+ {
519
+ "name": "$RepositoryName",
520
+ "project": {
521
+ "id": "$(Get-TestProjectId)"
522
+ },
523
+ "parentRepository": {
524
+ "id": "$repoId",
525
+ "name": "$($repositoryName)",
526
+ "project": {
527
+ "id": "$(Get-ProductionProjectId)"
528
+ }
529
+ }
530
+ }
531
+ "@
532
+ $response = Invoke-WebRequest -URI $uri `
533
+ -Headers @{
534
+ Authorization = "$([Authorization]::AuthorizationString)"
535
+ } `
536
+ -Method POST `
537
+ -Body $jsonBody `
538
+ -ContentType "application/json"
539
+
540
+ if (!$(Test-RestResponse `
541
+ -Response $response `
542
+ -ErrorMessage "Failed fork the repository $RepositoryName from production environment")) {
543
+ return $false
544
+ }
545
+
546
+ # Sleep for 2 seconds to allow time for branch to be created.
547
+ Start-Sleep 2
548
+
549
+ # Added information to config the repositories such as tag, trugger, definition...
550
+
551
+ # Add branches
552
+ if (!$(Add-RepositoryBranches -RepositoryName $RepositoryName -RepositoryConfig $repositoryConfig)) {
553
+ Write-Host "# ERROR: Failed to add specified branches."
554
+ return $false
555
+ }
556
+
557
+ # Add tags
558
+ if (!$(Add-RepositoryTags -RepositoryName $RepositoryName -RepositoryConfig $repositoryConfig)) {
559
+ Write-Host "# ERROR: Failed to add specified tags."
560
+ return $false
561
+ }
562
+
563
+ # Update package versions
564
+ if (!$(Update-RepositoryPackageVersions -RepositoryName $RepositoryName -RepositoryConfig $repositoryConfig)) {
565
+ Write-Host "# ERROR: Failed to update specified package version."
566
+ return $false
567
+ }
568
+
569
+ return $true
570
+ }
571
+
572
+ <#
573
+ .Description
574
+ Add the repositories based on what specified in the configuration file.
575
+ Repositories will first be cloned from the 'Production' environment. They
576
+ will then be configured accordingly.
577
+
578
+ .Parameter Configuration
579
+ A configuration object, reflecting what is specified in the configuration file
580
+
581
+ .Outputs
582
+ true or false
583
+ #>
584
+ function Add-Repositories {
585
+ param (
586
+ [Parameter(Mandatory)]
587
+ [object]$Configuration
588
+ )
589
+
590
+ Write-Host ""
591
+ Write-Host "Add repositories"
592
+ Write-Host "================"
593
+ if ($Configuration.repositories -ne $null) {
594
+ foreach ($repoProperty in $($Configuration.repositories | Get-Member -MemberType NoteProperty)) {
595
+ if (!(Add-Repository -RepositoryName $repoProperty.Name -RepositoryConfig $Configuration.repositories."$($repoProperty.Name)")) {
596
+ Write-Host "# ERROR: Failed to add repository $repository"
597
+ return $false
598
+ }
599
+ }
600
+ }
601
+
602
+ return $true
603
+ }
604
+
605
+ <#
606
+ .Description
607
+ Get a definition object
608
+
609
+ .Parameter DefinitionName
610
+ Name of a definition
611
+
612
+ .Outputs
613
+ A definition object based on response from Azure Devops api. $null if fails
614
+ #>
615
+ function Get-Definition {
616
+ param (
617
+ [Parameter(Mandatory)]
618
+ [string]$DefinitionName
619
+ )
620
+
621
+ # Get all definitions
622
+ $uri = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/build/definitions?api-version=6"
623
+ $response = Invoke-WebRequest -URI $uri `
624
+ -Headers @{
625
+ Authorization = "$([Authorization]::AuthorizationString)"
626
+ } `
627
+ -Method GET
628
+
629
+ if (Test-RestResponse `
630
+ -Response $response `
631
+ -ErrorMessage "Failed to get all definitions") {
632
+ $content = $response.content | Out-String | ConvertFrom-Json
633
+ # Get the definition that match the definition name
634
+ $definition = $($content.value | Where-Object {$_.name -eq "$DefinitionName"})
635
+ if ($definition -ne $null) {
636
+ return $definition[0]
637
+ } else {
638
+ Write-Host "# ERROR: No definition has been found for name $DefinitionName"
639
+ return $null
640
+ }
641
+ } else {
642
+ return $null
643
+ }
644
+ return $null
645
+ }
646
+
647
+ <#
648
+ .Description
649
+ Get Id of an agent pool
650
+
651
+ .Parameter AgentPoolName
652
+ Name of an agent pool
653
+
654
+ .Outputs
655
+ Id of an agent or $null
656
+ #>
657
+ function Get-AgentPoolId {
658
+ param (
659
+ [Parameter(Mandatory)]
660
+ [string]$AgentPoolName
661
+ )
662
+
663
+ $uri = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)/_apis/distributedtask/pools?api-version=6"
664
+ $response = Invoke-WebRequest -URI $uri `
665
+ -Headers @{
666
+ Authorization = "$([Authorization]::AuthorizationString)"
667
+ } `
668
+ -Method GET
669
+
670
+ $poolId = $null
671
+ if (Test-RestResponse `
672
+ -Response $response `
673
+ -ErrorMessage "Failed to get agent pools") {
674
+ $content = $response.content | Out-String | ConvertFrom-Json
675
+ $poolId = $($content.value | Where-Object { $_.name -eq $AgentPoolName })[0].id
676
+ } else {
677
+ return $null
678
+ }
679
+ return $poolId
680
+ }
681
+
682
+ <#
683
+ .Description
684
+ Get Agent queue object
685
+
686
+ .Parameter AgentQueueName
687
+ Name of an agent queue
688
+
689
+ .Outputs
690
+ An agent queue object or $null
691
+ #>
692
+ function Get-AgentQueue {
693
+ param (
694
+ [Parameter(Mandatory)]
695
+ [string]$AgentQueueName
696
+ )
697
+
698
+ $uri = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/distributedtask/queues?api-version=6.0-preview.1"
699
+ $response = Invoke-WebRequest -URI $uri `
700
+ -Headers @{
701
+ Authorization = "$([Authorization]::AuthorizationString)"
702
+ } `
703
+ -Method GET
704
+
705
+ $queue = $null
706
+ if (Test-RestResponse `
707
+ -Response $response `
708
+ -ErrorMessage "Failed to get agent queues") {
709
+ $content = $response.content | Out-String | ConvertFrom-Json
710
+ $queue = $($content.value | Where-Object { $_.name -eq $AgentQueueName })[0]
711
+ } else {
712
+ return $null
713
+ }
714
+ return $queue
715
+ }
716
+
717
+ <#
718
+ .Description
719
+ Add a definition for a repository.
720
+ NOTE: This currently only copy with buildCompletion trigger type.
721
+
722
+ .Parameter RepositoryName
723
+ Name of a repository that the definitions belong to.
724
+
725
+ .Parameter Definition
726
+ The definition object as specified in the config file.
727
+
728
+ .Outputs
729
+ true or false
730
+ #>
731
+ function Add-RepositoryDefinition {
732
+ param (
733
+ [Parameter(Mandatory)]
734
+ [string]$RepositoryName,
735
+ [Parameter(Mandatory)]
736
+ [object]$Definition
737
+ )
738
+ # Sleep for 1 second to make sure all definitions are available
739
+ Start-Sleep 1
740
+
741
+ # Get default queue
742
+ $queue = Get-AgentQueue -AgentQueueName $([TestEnvPredefinedVariables]::DefaultQueueName)
743
+ if ($queue -eq $null) {
744
+ Write-Host "# ERROR: Would not find the default queue of '$defaultQueueName'"
745
+ return $false
746
+ }
747
+
748
+ # Create a definition
749
+ $uri = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/build/definitions?api-version=6.0 "
750
+
751
+ # Construct the json body
752
+ $jsonBody = @"
753
+ {
754
+ "name": "$($Definition.name)",
755
+ "repository": {
756
+ "defaultBranch": "$($Definition.defaultBranch)",
757
+ "name": "$RepositoryName",
758
+ "type": "TfsGit"
759
+ },
760
+ "process":{
761
+ "yamlFilename":"$($Definition.yamlFilename)",
762
+ "type":2
763
+ },
764
+ "type": "build",
765
+ "queue": $($queue | ConvertTo-Json),
766
+ "triggers": [
767
+ $([TestEnvPredefinedVariables]::YamlCiTrigger)
768
+ ]
769
+ }
770
+ "@
771
+
772
+ $response = Invoke-WebRequest -URI $uri `
773
+ -Headers @{
774
+ Authorization = "$([Authorization]::AuthorizationString)"
775
+ } `
776
+ -Method POST `
777
+ -Body $jsonBody `
778
+ -ContentType "application/json"
779
+
780
+ if (!$(Test-RestResponse `
781
+ -Response $response `
782
+ -ErrorMessage "Failed to add definition $($Definition.name) for repository $RepositoryName")) {
783
+ return $false
784
+ }
785
+ return $true
786
+ }
787
+
788
+ <#
789
+ .Description
790
+ Add definitions for a repository.
791
+
792
+ .Parameter RepositoryName
793
+ Name of a repository that the definitions belong to.
794
+
795
+ .Parameter RepositoryConfig
796
+ The configuration object of each repository.
797
+
798
+ .Outputs
799
+ true or false
800
+ #>
801
+ function Add-RepositoryDefinitions {
802
+ param (
803
+ [Parameter(Mandatory)]
804
+ [string]$RepositoryName,
805
+ [Parameter(Mandatory)]
806
+ [object]$RepositoryConfig
807
+ )
808
+ foreach ($definition in $RepositoryConfig.definitions) {
809
+ if (!$(Add-RepositoryDefinition `
810
+ -RepositoryName $RepositoryName `
811
+ -Definition $definition)) {
812
+ Write-Host "# ERROR: Failed to add definition $($definition.name) for repository $RepositoryName"
813
+ return $false
814
+ }
815
+ }
816
+
817
+ return $true
818
+ }
819
+
820
+ <#
821
+ .Description
822
+ Add definitions.
823
+
824
+ .Parameter Configuration
825
+ A configuration object, reflecting what is specified in the configuration file
826
+
827
+ .Outputs
828
+ true or false
829
+ #>
830
+ function Add-Definitions {
831
+ param (
832
+ [Parameter(Mandatory)]
833
+ [object]$Configuration
834
+ )
835
+
836
+ Write-Host ""
837
+ Write-Host "Add definitions"
838
+ Write-Host "==============="
839
+ foreach ($repoProperty in $($Configuration.repositories | Get-Member -MemberType NoteProperty)) {
840
+ Write-Host ""
841
+ Write-Host "# Adding build definitions for repository $($repoProperty.Name)"
842
+ if (!(Add-RepositoryDefinitions -RepositoryName $repoProperty.Name -RepositoryConfig $Configuration.repositories."$($repoProperty.Name)")) {
843
+ Write-Host "# ERROR: Failed to add definitions for repository $repository"
844
+ return $false
845
+ }
846
+ }
847
+
848
+ return $true
849
+ }
850
+
851
+ <#
852
+ .Description
853
+ Add build triggers for a definition of a repository.
854
+ NOTE: This currently only copy with buildCompletion trigger type.
855
+
856
+ .Parameter RepositoryName
857
+ Name of a repository that the definitions belong to.
858
+
859
+ .Parameter Definition
860
+ The definition object as specified in the config file.
861
+
862
+ .Outputs
863
+ true or false
864
+ #>
865
+ function Add-RepositoryDefinitionBuildTriggers {
866
+ param (
867
+ [Parameter(Mandatory)]
868
+ [string]$RepositoryName,
869
+ [Parameter(Mandatory)]
870
+ [object]$Definition
871
+ )
872
+ # Sleep for 1 second to make sure all definitions are available
873
+ Start-Sleep 1
874
+
875
+ # Get current details of the definition
876
+ $curDefinition = Get-Definition -DefinitionName $Definition.name
877
+ if ($curDefinition -eq $null) {
878
+ Write-Host "# ERROR: Failed to get Id for definition $($Definition.name)"
879
+ return $false
880
+ }
881
+
882
+ # Create a definition
883
+ $uri = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/build/definitions/$($curDefinition.id)?api-version=6.0 "
884
+
885
+ # Construct triggers
886
+ $triggers = "[`n"
887
+ if ($Definition.triggers -ne $null) {
888
+ [int32]$validTriggerFound = 0
889
+ for ($i = 0; $i -lt $Definition.triggers.count; $i++) {
890
+ $trigger = $Definition.triggers[$i]
891
+ switch ($trigger.triggerType) {
892
+ "buildCompletion"
893
+ {
894
+ Write-Host "# Including 'buildCompletion' trigger."
895
+ $triggerDefinition = Get-Definition -DefinitionName $trigger.definitionName
896
+ if ($triggerDefinition -eq $null) {
897
+ Write-Host "# ERROR: Failed to get Id for trigger definition $($trigger.name)"
898
+ return $false
899
+ }
900
+
901
+ # Add square brackets for branchFilters array
902
+ $branchFilters = ""
903
+ if ($trigger.branchFilters.count -eq 1) {
904
+ $branchFilters += "["
905
+ }
906
+ $branchFilters += $($trigger.branchFilters | ConvertTo-Json | Out-String)
907
+ if ($trigger.branchFilters.count -eq 1) {
908
+ $branchFilters += "]"
909
+ }
910
+
911
+ $triggerDef = @"
912
+ {
913
+ "definition": {
914
+ "id": $($triggerDefinition.id),
915
+ "path": "\\",
916
+ "queueStatus": "enabled",
917
+ "project": {
918
+ "id": "$(Get-TestProjectId)",
919
+ "state": "wellFormed",
920
+ "visibility": "private"
921
+ }
922
+ },
923
+ "requiresSuccessfulBuild": $($trigger.requiresSuccessfulBuild | ConvertTo-Json),
924
+ "branchFilters": $branchFilters,
925
+ "triggerType": "$($trigger.triggerType)"
926
+ }
927
+
928
+ "@
929
+ if ($validTriggerFound -gt 0) {
930
+ $triggers += ",`n"
931
+ }
932
+ $triggers += $triggerDef
933
+ $validTriggerFound += 1
934
+ }
935
+ }
936
+ }
937
+ }
938
+
939
+ # Make sure to includ the CI trigger defined in yaml file.
940
+ if ($validTriggerFound -gt 0) {
941
+ $triggers += ",`n"
942
+ }
943
+ $triggers += $([TestEnvPredefinedVariables]::YamlCiTrigger)
944
+
945
+ $triggers += "`n]"
946
+
947
+ # Construct the json body
948
+ $jsonBody = @"
949
+ {
950
+ "id": $($curDefinition.id),
951
+ "revision": $($curDefinition.revision),
952
+ "name": "$($Definition.name)",
953
+ "repository": {
954
+ "defaultBranch": "$($Definition.defaultBranch)",
955
+ "name": "$RepositoryName",
956
+ "type": "TfsGit"
957
+ },
958
+ "process":{
959
+ "yamlFilename":"$($Definition.yamlFilename)",
960
+ "type":2
961
+ },
962
+ "triggers": $triggers,
963
+ "type": "build",
964
+ "queue": $($curDefinition.queue | ConvertTo-Json)
965
+ }
966
+ "@
967
+
968
+ $response = Invoke-WebRequest -URI $uri `
969
+ -Headers @{
970
+ Authorization = "$([Authorization]::AuthorizationString)"
971
+ } `
972
+ -Method PUT `
973
+ -Body $jsonBody `
974
+ -ContentType "application/json"
975
+
976
+ if (!$(Test-RestResponse `
977
+ -Response $response `
978
+ -ErrorMessage "Failed to add definition $($Definition.name) for repository $RepositoryName")) {
979
+ return $false
980
+ }
981
+ return $true
982
+ }
983
+
984
+ <#
985
+ .Description
986
+ Add build triggers for a repository.
987
+
988
+ .Parameter RepositoryName
989
+ Name of a repository that the definitions belong to.
990
+
991
+ .Parameter RepositoryConfig
992
+ The configuration object of each repository.
993
+
994
+ .Outputs
995
+ true or false
996
+ #>
997
+ function Add-RepositoryBuildTriggers {
998
+ param (
999
+ [Parameter(Mandatory)]
1000
+ [string]$RepositoryName,
1001
+ [Parameter(Mandatory)]
1002
+ [object]$RepositoryConfig
1003
+ )
1004
+ foreach ($definition in $RepositoryConfig.definitions) {
1005
+ if (!$(Add-RepositoryDefinitionBuildTriggers `
1006
+ -RepositoryName $RepositoryName `
1007
+ -Definition $definition)) {
1008
+ Write-Host "# ERROR: Failed to add build triggers for definition $($definition.name) for repository $RepositoryName"
1009
+ return $false
1010
+ }
1011
+ }
1012
+
1013
+ return $true
1014
+ }
1015
+
1016
+ <#
1017
+ .Description
1018
+ Add build triggers.
1019
+
1020
+ .Parameter Configuration
1021
+ A configuration object, reflecting what is specified in the configuration file
1022
+
1023
+ .Outputs
1024
+ true or false
1025
+ #>
1026
+ function Add-BuildTriggers {
1027
+ param (
1028
+ [Parameter(Mandatory)]
1029
+ [object]$Configuration
1030
+ )
1031
+
1032
+ Write-Host ""
1033
+ Write-Host "Add build triggers"
1034
+ Write-Host "=================="
1035
+ foreach ($repoProperty in $($Configuration.repositories | Get-Member -MemberType NoteProperty)) {
1036
+ Write-Host ""
1037
+ Write-Host "# Adding build triggers for repository $($repoProperty.Name)"
1038
+ if (!(Add-RepositoryBuildTriggers -RepositoryName $repoProperty.Name -RepositoryConfig $Configuration.repositories."$($repoProperty.Name)")) {
1039
+ Write-Host "# ERROR: Failed to add build triggers for repository $repository"
1040
+ return $false
1041
+ }
1042
+ }
1043
+
1044
+ return $true
1045
+ }
1046
+
1047
+ <#
1048
+ .Description
1049
+ Return an Id of a repository
1050
+
1051
+ .Parameter ProjectName
1052
+ Name of a team project
1053
+
1054
+ .Parameter RepositoryName
1055
+ Name of a repository
1056
+
1057
+ .Outputs
1058
+ Id of a repository or $null
1059
+ #>
1060
+ function Get-RepositoryId {
1061
+ param (
1062
+ [Parameter(Mandatory)]
1063
+ [string]$ProjectName,
1064
+ [Parameter(Mandatory)]
1065
+ [string]$RepositoryName
1066
+ )
1067
+
1068
+ # Get all existing repositories
1069
+ $url = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$ProjectName/_apis/git/repositories?api-version=6.0"
1070
+
1071
+ $response = Invoke-WebRequest `
1072
+ -URI $url `
1073
+ -Headers @{
1074
+ Authorization = "$([Authorization]::AuthorizationString)"
1075
+ } `
1076
+ -Method GET
1077
+
1078
+ if (Test-RestResponse `
1079
+ -Response $response `
1080
+ -ErrorMessage "Failed to get all repositories") {
1081
+ # Get the definition that match the definition name
1082
+ $content = $response.content | Out-String | ConvertFrom-Json
1083
+ $definition = $($content.value | Where-Object {$_.name -eq "$RepositoryName"})
1084
+ if ($definition -ne $null) {
1085
+ return $definition[0].id
1086
+ } else {
1087
+ Write-Host "# ERROR: No repository name match $RepositoryName"
1088
+ return $null
1089
+ }
1090
+ }
1091
+ return $null
1092
+ }
1093
+
1094
+ <#
1095
+ .Description
1096
+ Get an ID of a policy type
1097
+
1098
+ .Parameter TypeName
1099
+ Name of a policy type
1100
+
1101
+ .Outputs
1102
+ An id of the input policy or $null
1103
+ #>
1104
+ function Get-PolicyTypeId {
1105
+ param (
1106
+ [Parameter(Mandatory)]
1107
+ [string]$TypeName
1108
+ )
1109
+
1110
+ $url = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/policy/types?api-version=6.1-preview.1"
1111
+ $response = Invoke-WebRequest `
1112
+ -URI $url `
1113
+ -Headers @{
1114
+ Authorization = "$([Authorization]::AuthorizationString)"
1115
+ } `
1116
+ -Method GET
1117
+
1118
+ if (Test-RestResponse `
1119
+ -Response $response `
1120
+ -ErrorMessage "Failed to get all policy types") {
1121
+ # Get the definition that match the definition name
1122
+ $content = $response.content | Out-String | ConvertFrom-Json
1123
+ $policy = $($content.value | Where-Object {$_.displayName -eq "$TypeName"})
1124
+ if ($policy -ne $null) {
1125
+ return $policy[0].id
1126
+ } else {
1127
+ Write-Host "# ERROR: No policy type matched $TypeName"
1128
+ return $null
1129
+ }
1130
+ }
1131
+ }
1132
+
1133
+ <#
1134
+ .Description
1135
+ Add policy to a repository. If a repository name is not
1136
+ supplied, create a generic one.
1137
+
1138
+ .Parameter RepositoryName
1139
+ Name of a repository. Null if want to apply to everything.
1140
+
1141
+ .Parameter Policy
1142
+ A policy object based on the configuration file.
1143
+
1144
+ .Outputs
1145
+ true or false
1146
+ #>
1147
+ function Add-RepositoryPolicy {
1148
+ param (
1149
+ [string]$RepositoryName,
1150
+ [Parameter(Mandatory)]
1151
+ [object]$Policy
1152
+ )
1153
+
1154
+ Write-Host "# Adding policy '$($Policy.type)' to repository $RepositoryName"
1155
+
1156
+ # Obtain repository Id
1157
+ $repositoryId = $null
1158
+ if (![string]::IsNullOrEmpty($RepositoryName)) {
1159
+ $repositoryId = Get-RepositoryId -ProjectName $([TestEnvPredefinedVariables]::TestProject) -RepositoryName $RepositoryName
1160
+ if ($repositoryId -eq $null) {
1161
+ Write-Host "# Failed to get id of repository $RepositoryName"
1162
+ return $false
1163
+ }
1164
+ }
1165
+
1166
+ # Get the type id
1167
+ $typeId = Get-PolicyTypeId -TypeName $Policy.type
1168
+ if ($typeId -eq $null) {
1169
+ Write-Host "# ERROR Invalid policy type $($Policy.type)"
1170
+ return $false
1171
+ }
1172
+
1173
+ # Build policy settings
1174
+ $settings = $null
1175
+ switch ($Policy.type) {
1176
+ "Build"
1177
+ {
1178
+ $definition = Get-Definition -DefinitionName $Policy.definition
1179
+ if ($definition -ne $null) {
1180
+ $settings = @"
1181
+ {
1182
+ "buildDefinitionId": $($definition.id),
1183
+ "queueOnSourceUpdateOnly": false,
1184
+ "manualQueueOnly": false,
1185
+ "displayName": null,
1186
+ "validDuration": 0.0,
1187
+ "scope": [
1188
+ {
1189
+ "refName": "$($Policy.refName)",
1190
+ "matchKind": "$($Policy.matchKind)",
1191
+ "repositoryId": "$repositoryId"
1192
+ }
1193
+ ]
1194
+ }
1195
+ "@
1196
+ } else {
1197
+ Write-Host "# ERROR: Failed to obtain id for definition $($Policy.definition)"
1198
+ return $false
1199
+ }
1200
+ }
1201
+ "Required reviewers"
1202
+ {
1203
+ $settings = @"
1204
+ {
1205
+ "requiredReviewerIds": [
1206
+ "$(Get-ReviewerId)"
1207
+ ],
1208
+ "minimumApproverCount": 1,
1209
+ "creatorVoteCounts": false,
1210
+ "scope": [
1211
+ {
1212
+ "refName": null,
1213
+ "matchKind": "DefaultBranch",
1214
+ "repositoryId": "$repositoryId"
1215
+ }
1216
+ ]
1217
+ }
1218
+ "@
1219
+ }
1220
+ Default
1221
+ {
1222
+ Write-Host "# ERROR: $($Policy.type) is not supported"
1223
+ return $false
1224
+ }
1225
+ }
1226
+
1227
+ # Add the policy
1228
+ $url = "$([TestEnvPredefinedVariables]::TeamFoundationCollectionUri)$([TestEnvPredefinedVariables]::TestProject)/_apis/policy/configurations?api-version=6.1-preview.1"
1229
+ $jsonBody = @"
1230
+ {
1231
+ "isEnabled": true,
1232
+ "isBlocking": true,
1233
+ "isDeleted": false,
1234
+ "settings": $settings,
1235
+ "isEnterpriseManaged": false,
1236
+ "type": {
1237
+ "id": "$typeId",
1238
+ }
1239
+ }
1240
+ "@
1241
+
1242
+ $response = Invoke-WebRequest -URI $url `
1243
+ -Headers @{
1244
+ Authorization = "$([Authorization]::AuthorizationString)"
1245
+ } `
1246
+ -Method POST `
1247
+ -Body $jsonBody `
1248
+ -ContentType "application/json"
1249
+
1250
+ if (!$(Test-RestResponse `
1251
+ -Response $response `
1252
+ -ErrorMessage "Failed fork the repository $RepositoryName from production environment")) {
1253
+ return $false
1254
+ }
1255
+
1256
+ return $true
1257
+ }
1258
+
1259
+ <#
1260
+ .Description
1261
+ Add repository branch policies.
1262
+
1263
+ .Parameter RepositoryName
1264
+ Name of a repository object specified in the configuration file.
1265
+
1266
+ .Parameter RepositoryConfig
1267
+ The configuration associated with the repository.
1268
+
1269
+ .Outputs
1270
+ true or false
1271
+ #>
1272
+ function Add-RepositoryPolicies {
1273
+ param (
1274
+ [Parameter(Mandatory)]
1275
+ [string]$RepositoryName,
1276
+ [Parameter(Mandatory)]
1277
+ [object]$RepositoryConfig
1278
+ )
1279
+
1280
+ foreach ($policy in $RepositoryConfig.policies) {
1281
+ if (!$(Add-RepositoryPolicy -RepositoryName $RepositoryName -Policy $policy)) {
1282
+ Write-Host "# ERROR: Failed to add policy for repository $Repository"
1283
+ return $false
1284
+ }
1285
+ }
1286
+ return $true
1287
+ }
1288
+
1289
+ <#
1290
+ .Description
1291
+ Add policies
1292
+
1293
+ .Parameter Configuration
1294
+ A configuration object, reflecting what is specified in the configuration file
1295
+
1296
+ .Outputs
1297
+ true or false
1298
+ #>
1299
+ function Add-Policies {
1300
+ param (
1301
+ [Parameter(Mandatory)]
1302
+ [object]$Configuration
1303
+ )
1304
+
1305
+ Write-Host ""
1306
+ Write-Host "Add policies"
1307
+ Write-Host "============"
1308
+ # Add general policies which apply on all repository and branches
1309
+ Write-Host ""
1310
+ Write-Host "# Adding cross-repository policies"
1311
+ foreach ($policy in $Configuration.policies) {
1312
+ if (!(Add-RepositoryPolicy -RepositoryName $null -Policy $policy)) {
1313
+ Write-Host "# ERROR: Failed to add general policy '$policy'"
1314
+ return $false
1315
+ }
1316
+ }
1317
+
1318
+ # Add policies which are specific to each repository
1319
+ foreach ($repoProperty in $($Configuration.repositories | Get-Member -MemberType NoteProperty)) {
1320
+ Write-Host ""
1321
+ Write-Host "# Adding policies for repository $($repoProperty.Name)"
1322
+ if (!(Add-RepositoryPolicies -RepositoryName $repoProperty.Name -RepositoryConfig $Configuration.repositories."$($repoProperty.Name)")) {
1323
+ Write-Host "# ERROR: Failed to add policies for repository $repository"
1324
+ return $false
1325
+ }
1326
+ }
1327
+
1328
+ return $true
1329
+ }
1330
+
1331
+ <#
1332
+ .Description
1333
+ Add PullRequests..
1334
+
1335
+ .Parameter Configuration
1336
+ A configuration object, reflecting what is specified in the configuration file
1337
+
1338
+ .Outputs
1339
+ true or false
1340
+ #>
1341
+ function Add-PullRequests {
1342
+ param (
1343
+ [Parameter(Mandatory)]
1344
+ [object]$Configuration
1345
+ )
1346
+
1347
+ Write-Host ""
1348
+ Write-Host "Add pull requests"
1349
+ Write-Host "============"
1350
+ foreach ($repoProperty in $($Configuration.repositories | Get-Member -MemberType NoteProperty)) {
1351
+ Write-Host ""
1352
+ Write-Host "# Adding pull request for repository $($repoProperty.Name)"
1353
+ $repositoryConfig = $Configuration.repositories."$($repoProperty.Name)"
1354
+ foreach ($pullRequest in $repositoryConfig.pullrequests) {
1355
+ Write-Host "# Add pull request from $($pullRequest.source) to $($pullRequest.target) for repository $($repoProperty.Name)"
1356
+ $response = $(New-PullRequest `
1357
+ -TeamProjectName $([TestEnvPredefinedVariables]::TestProject) `
1358
+ -RepositoryName $repoProperty.Name `
1359
+ -SourceBranchRef "refs/heads/$($pullRequest.source)" `
1360
+ -TargetBranchRef "refs/heads/$($pullRequest.target)" `
1361
+ -AuthorizationHeader $([Authorization]::AuthorizationString))
1362
+ if ($response -eq $null) {
1363
+ Write-Host "# ERROR: Failed to create pull request from $($pullRequest.source) to $($pullRequest.target) for repository $($repoProperty.Name)"
1364
+ return $false;
1365
+ }
1366
+
1367
+ # At the moment, we only allow adding a comment to indicate
1368
+ # there is unresolved issue.
1369
+ if ($pullRequest.comment) {
1370
+ if (!(Add-PullRequestComment `
1371
+ -TeamProjectName $([TestEnvPredefinedVariables]::TestProject) `
1372
+ -RepositoryName $repoProperty.Name `
1373
+ -PullRequestId $response.pullRequestId `
1374
+ -Comment "Comment" `
1375
+ -AuthorizationHeader $([Authorization]::AuthorizationString))) {
1376
+ Write-Host "# ERROR: Failed to add comments to pull request"
1377
+ return $false
1378
+ }
1379
+ }
1380
+
1381
+ # NOTE: Vote cannot be added through Rest API as voting for others is not allowed
1382
+ }
1383
+ }
1384
+
1385
+ return $true
1386
+ }
1387
+
1388
+ <#
1389
+ .Description
1390
+ Create a new test environment
1391
+
1392
+ .Parameter ConfigurationFile
1393
+ A full path to a configuration file
1394
+
1395
+ .Outputs
1396
+ true or false
1397
+ #>
1398
+ function New-TestEnvironment {
1399
+ param (
1400
+ [Parameter(Mandatory)]
1401
+ [string]$ConfigurationFile
1402
+ )
1403
+
1404
+ Write-Host ""
1405
+ Write-Host "Read input configuration file"
1406
+ Write-Host "============================="
1407
+ # Check file existance
1408
+ if (!(Test-Path $ConfigurationFile)) {
1409
+ Write-Host "# ERROR: File $ConfigurationFile does not exist."
1410
+ return $false
1411
+ }
1412
+
1413
+ # Get content of configuration file
1414
+ $config = Get-Content $ConfigurationFile | Out-String | ConvertFrom-Json
1415
+ if (!$?) {
1416
+ Write-Host "# ERROR: Failed to get content of the configuration file $ConfigurationFile."
1417
+ return $false
1418
+ }
1419
+
1420
+ # Validate configuration file
1421
+ if (!(Test-ConfigFile -Configuration $config)) {
1422
+ Write-Host "# ERROR: $ConfigurationFile is invalid."
1423
+ return $false
1424
+ }
1425
+
1426
+ # NOTE: The reason the creation is done in the order of
1427
+ # repositories, definitions, build triggers, policies and pull requests
1428
+ # because:
1429
+ # 1. Definitions depend on all repositories to be available.
1430
+ # 2. Build triggers depend on all definitions to be available.
1431
+ # 3. Policies depend on all definitions to be available.
1432
+ # 4. Pull requests depends on everything before.
1433
+
1434
+ # Process repositories
1435
+ if (!(Add-Repositories -Configuration $config)) {
1436
+ Write-Host "# ERROR: Failed to add the specified repositories."
1437
+ return $false
1438
+ }
1439
+
1440
+ # Add definitions
1441
+ if (!(Add-Definitions -Configuration $config)) {
1442
+ Write-Host "# ERROR: Failed to add the specified definitions."
1443
+ return $false
1444
+ }
1445
+
1446
+ # Add build triggers
1447
+ if (!(Add-BuildTriggers -Configuration $config)) {
1448
+ Write-Host "# ERROR: Failed to add the specified triggers."
1449
+ return $false
1450
+ }
1451
+
1452
+ # Add policies
1453
+ if (!(Add-Policies -Configuration $config)) {
1454
+ Write-Host "# ERROR: Failed to add the specified policies."
1455
+ return $false
1456
+ }
1457
+
1458
+ # Add pull requests
1459
+ if (!(Add-PullRequests -Configuration $config)) {
1460
+ Write-Host "# ERROR: Failed to add the specified pull requests."
1461
+ return $false
1462
+ }
1463
+
1464
+ return $true
1465
+ }