Skip to content

Instantly share code, notes, and snippets.

@neilcampbell
Last active August 12, 2021 08:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neilcampbell/bc1fb7d409425894ece0 to your computer and use it in GitHub Desktop.
Save neilcampbell/bc1fb7d409425894ece0 to your computer and use it in GitHub Desktop.
Pact Broker Publish Script
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
@mefellows
Copy link

Please note that you should explicitly set the TLS version to something better than the default (TLS 1.0)

You can do it like this to set it to TLS 1.2:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

@neilcampbell
Copy link
Author

Updated

@bmcclory
Copy link

bmcclory commented Aug 9, 2020

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.

@bmcclory
Copy link

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

PowerShell/PowerShell#9473

@bethesque
Copy link

If you are able to run Docker, then we recommend using the Pact CLI Docker image https://hub.docker.com/r/pactfoundation/pact-cli

@rajbos
Copy link

rajbos commented Aug 12, 2021

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).

@mefellows
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment