-
-
Save neilcampbell/bc1fb7d409425894ece0 to your computer and use it in GitHub Desktop.
param( | |
$buildMetadataFile = "package.json", | |
$workingDir = (Get-Location), | |
$pactsDir = (Join-Path $workingDir "pacts"), | |
$pactBroker = "http://my-pact-broker", | |
$templateUrl = "$pactBroker/pacts/provider/:provider/consumer/:consumer/version/:version", | |
$tagTemplateUrl = "$pactBroker/pacticipants/:consumer/versions/:version/tags/:tag" | |
) | |
$ErrorActionPreference = "Stop" | |
trap | |
{ | |
# this script is called via -File in the powershell params which will not always return a valid exit code on exception | |
# catch any exception and force the exit code. | |
write-output $_ | |
exit 1 | |
} | |
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 | |
function Get-TagFromMetadata { | |
param( | |
[Parameter(Position=1,Mandatory=1)]$metadata | |
) | |
process { | |
$tagSplit = $metadata.version.Split('{+}') | |
$tag = if($tagSplit[1] -ne $null) { $tagSplit[1] } else { 'master' } | |
# Returns the tag in a format like MyTag or master if not specified for version 0.1.183-beta+MyTag | |
return "$($tag)" | |
} | |
} | |
function Get-CompatibleVersionFromMetadata { | |
param( | |
[Parameter(Position=1,Mandatory=1)]$metadata | |
) | |
process { | |
$versionSplit = $metadata.version.Split('{-}') | |
# Returns the version in a format like 0.1.183 instead of 0.1.183-beta+MyTag | |
return "$($versionSplit[0])" | |
} | |
} | |
$pacts = Get-ChildItem $pactsDir -Filter "*.json" -Recurse | |
if ($pacts.Length -eq 0) { | |
throw "No pacts found in directory '$pactsDir'. Looked recursively for mask '*.json'." | |
} | |
$buildMetadataFilePath = Join-Path $workingDir $buildMetadataFile | |
$metadata = Get-Content $buildMetadataFilePath | Out-String | ConvertFrom-Json | |
$version = Get-CompatibleVersionFromMetadata $metadata | |
$tag = Get-TagFromMetadata $metadata | |
$pactContent = Get-Content $pacts[0].FullName | Out-String | |
$pactJson = $pactContent | ConvertFrom-Json | |
$consumer = $pactJson.consumer.name | |
$encodedConsumer = [Uri]::EscapeDataString($consumer) | |
foreach($pact in $pacts){ | |
$content = Get-Content $pact.FullName | Out-String | |
$json = $content | ConvertFrom-Json | |
$provider = $json.provider.name | |
Write-Host "Publishing pact:" | |
Write-Host "`t[$consumer => $provider], #$version" | |
$encodedBranch = [Uri]::EscapeDataString(($tag -Replace "/", "")) | |
$encodedProvider = [Uri]::EscapeDataString($provider) | |
$url = (($templateUrl -Replace ":provider", $encodedProvider) -Replace ":consumer", $encodedConsumer) -Replace ":version", $version | |
Write-Host "`t$url" | |
Invoke-RestMethod $url -Body $content -Method "PUT" -Headers @{"Content-Type"= "application/json"} | |
} | |
$tagUrl = (($tagTemplateUrl -Replace ":consumer", $encodedConsumer) -Replace ":tag", $encodedBranch) -Replace ":version", $version | |
Write-Host "Tagging pact consumer $($consumer) with tag $($tag) for version $($version)" | |
Write-Host "`t$tagUrl" | |
$headers = @{ | |
"Content-Type"= "application/json" | |
"Accept"= "application/hal+json" | |
} | |
Invoke-RestMethod $tagUrl -Method "PUT" -Headers $headers |
Broker API docs for the tag operation state:
Tags must be applied before pacts or verification results are published to ensure that the webhook fires with the correct metadata.
Also a "gotcha" for PowerShell Core 6.x Invoke-RestMethod
-- headers aren't sent when request body is empty (as is the case with the PUT tag request). I.e. the "Content-Type: application/json" gets dropped, causing the Pact Broker to return a 415.
Workaround is to explicitly set -Body ""
(empty string) argument. Fixed in PowerShell 7
If you are able to run Docker, then we recommend using the Pact CLI Docker image https://hub.docker.com/r/pactfoundation/pact-cli
Note: we had to PUT the pacts to the /interactions
endpoints on the Broker URL with the latest image of pactfoundation/pact-mock-service
. We couldn't get the templateUrl working (still testing things out).
Pact mock service is a different thing, you don't publish a pact to it. It's for running pact tests locally (almost certainly you don't want to be using that directly) and running a mock server.
You publish pacts to a pact broker, which might be generated by the mock service
Updated