-
Notifications
You must be signed in to change notification settings - Fork 1
365 lines (327 loc) · 14.9 KB
/
verify_consumer_pacts.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
name: Verify consumer pacts
# The purpose of this workflow is to verify ANY consumer contract(s) dependent on BPM provider using Pact framework.
#
# This workflow is triggered when
#
# 1. Consumer makes a change that results in a new pact published to Pact Broker (will verify ONLY the changed pact and publish the verification results back to the broker)
# 2. Provider makes a change (runs verification tests against ALL DEPLOYED consumer pact versions and publishes corresponding verification results)
#
#
# The workflow requires Pact broker credentials
# - PACT_BROKER_USERNAME - the Pact Broker username
# - PACT_BROKER_PASSWORD - the Pact Broker password
on:
pull_request:
branches: [ main ]
paths-ignore: [ '**.md' ]
push:
branches: [ main ]
paths-ignore: [ '**.md' ]
merge_group:
branches: [ main ]
paths-ignore: [ '**.md' ]
workflow_dispatch:
inputs:
pb-event-type:
description: 'the Pact Broker event type that triggers this workflow'
required: true
type: string
consumer-name:
description: 'the consumer name'
required: true
type: string
provider-version-number:
description: 'the provider version number for the verification result'
required: true
type: string
consumer-version-branch:
description: 'the name of the branch for most recent consumer version associated with the pact content'
required: true
type: string
# Optional / Deprecated Inputs
consumer-labels:
description: 'the list of labels for the consumer associated with the pact content, separated by ", "'
required: false
type: string
provider-labels:
description: 'the list of labels for the provider associated with the pact content, separated by ", "'
required: false
type: string
pact-url:
description: 'Optional. Verify contracts at a specific url. https://docs.pact.io/implementation_guides/javascript/docs/provider'
required: false
type: string
consumer-version-number:
description: 'DEPRECATED'
required: false
type: string
consumer-version-tags:
description: 'DEPRECATED'
required: false
type: string
provider-version-branch:
description: 'DEPRECATED'
required: false
type: string
env:
CAN_I_DEPLOY_RUN_NAME: 'can-i-deploy-${{ github.event.repository.name }}-${{ github.run_id }}-${{ github.run_attempt }}'
RELEASE_BRANCH: 'main'
PACTS_ARTIFACT: bpm-pacts-${{ github.event.repository.name }}-${{ github.run_id }}
PACTS_OUTPUT_DIR: service/build/pacts
jobs:
#################################################
# VERSIONING, BRANCH MANAGEMENT, INIT AND SETUP #
#################################################
bump-check:
runs-on: ubuntu-latest
outputs:
is-bump: ${{ steps.skiptest.outputs.is-bump }}
steps:
- uses: actions/checkout@v3
- name: Skip version bump merges
id: skiptest
uses: ./.github/actions/bump-skip
with:
event-name: ${{ github.event_name }}
init-github-context:
runs-on: ubuntu-latest
needs: [ bump-check ]
if: ${{ needs.bump-check.outputs.is-bump == 'no' }}
outputs:
repo-branch: ${{ steps.extract-branch.outputs.repo-branch }}
verify-provider-side-contracts-only: ${{ steps.set-environment.outputs.verify-provider-side-contracts-only }}
# gha branch - usaully main.
# PR will call pr version of GHA
# workflowdispatch can call branch versions of GHA.
# code checkout branch/gitref for bpm as a consumer
# code checkout branch/gitref for bpm as a provider
steps:
- id: extract-branch
run: |
GITHUB_EVENT_NAME=${{ github.event_name }}
if [[ "$GITHUB_EVENT_NAME" == "push" ]]; then
GITHUB_REF=${{ github.ref }}
GITHUB_SHA=${{ github.sha }}
elif [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then
GITHUB_REF=refs/heads/${{ github.head_ref }}
GITHUB_SHA=${{ github.event.pull_request.head.sha }}
elif [[ "$GITHUB_EVENT_NAME" == "merge_group" ]]; then
GITHUB_REF=refs/heads/${{ github.head_ref }} # Merge Queue support
elif [[ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]]; then
GITHUB_REF=${{ github.ref }} # The Git Ref that this workflow runs on
else
echo "Failed to extract branch information"
exit 1
fi
echo "repo-branch=${GITHUB_REF/refs\/heads\//""}" >> $GITHUB_OUTPUT
echo "repo-version=${GITHUB_SHA}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v4
with:
ref: ${{ steps.extract-branch.outputs.repo-branch }}
- name: set various output settings
id: set-environment
run: |
echo "verify-provider-side-contracts-only=${{ inputs.pb-event-type != '' }}" >> $GITHUB_OUTPUT
- name: Echo repo and branch information
run: |
echo "repo-owner=${{ github.repository_owner }}"
echo "repo-name=${{ github.event.repository.name }}"
echo "repo-branch=${{ steps.extract-branch.outputs.repo-branch }}"
echo "repo-version=${{ steps.extract-branch.outputs.repo-version }}"
# We only need a new version tag when this workflow is triggered by opening, updating a PR or PR merge.
# When triggered by a Pact Broker webhook, the provider version (GIT hash or release tag)
# is already included in the payload, then a new version tag wouldn't be needed.
#
regulated-tag-job:
needs: [ init-github-context ]
if: ${{ needs.bump-check.outputs.is-bump == 'no' }}
uses: ./.github/workflows/tag.yml
with:
# The 'ref' parameter ensures that the provider version is postfixed with the HEAD commit of the PR branch,
# facilitating cross-referencing of a pact between Pact Broker and GitHub.
ref: ${{ needs.init-github-context.outputs.repo-branch || '' }}
# The 'dry-run' parameter prevents the new tag from being dispatched.
dry-run: true
release-branches: main
secrets: inherit
#################################
# CONSUMER CONTRACT PUBLISHING #
#################################
run-consumer-contract-tests:
runs-on: ubuntu-latest
needs: [ bump-check, init-github-context ]
if: ${{ needs.init-github-context.outputs.verify-provider-side-contracts-only == 'false' }}
outputs:
pact-paths: ${{ steps.locate-pacts.outputs.pact-paths }}
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'temurin'
- name: Run consumer tests
run: ./gradlew pactTests
- name: Locate pact files
id: locate-pacts
run: |
pactPaths=$(find "$PACTS_OUTPUT_DIR" -type f -name "*.json" | jq -cnR "[inputs]")
echo "pact-paths=$pactPaths" >> $GITHUB_OUTPUT
- name: Upload pact files to artifact
id: upload-pacts
uses: actions/upload-artifact@v4
with:
name: ${{ env.PACTS_ARTIFACT }}
path: ${{ env.PACTS_OUTPUT_DIR }}
retention-days: 1
publish-contracts:
runs-on: ubuntu-latest
needs: [ bump-check, init-github-context, run-consumer-contract-tests, regulated-tag-job ]
strategy:
matrix:
pact_path: ${{ fromJson(needs.run-consumer-contract-tests.outputs.pact-paths) }}
if: ${{ needs.bump-check.outputs.is-bump == 'no' }}
steps:
- name: Download pact files from artifact
id: download-pacts
uses: actions/download-artifact@v4
with:
name: ${{ env.PACTS_ARTIFACT }}
path: ${{ env.PACTS_OUTPUT_DIR }}
- name: Encode pact as non-breaking base64 string
id: encode-pact
run: |
nonBreakingB64=$(cat "${{ matrix.pact_path }}" | base64 -w 0)
echo "pact-b64=${nonBreakingB64}" >> $GITHUB_OUTPUT
- name: Publish contracts
id: publish-contracts
uses: broadinstitute/dsp-reusable-workflows/.github/actions/run-publish-contracts@main
with:
PACT_B64: ${{ steps.encode-pact.outputs.pact-b64 }}
REPO_OWNER: ${{ github.repository_owner }}
REPO_NAME: ${{ github.event.repository.name }}
REPO_BRANCH: ${{ needs.init-github-context.outputs.repo-branch }}
BROADBOT_TOKEN: ${{ secrets.BROADBOT_TOKEN }}
PACT_BROKER_USERNAME: ${{ secrets.PACT_BROKER_USERNAME }}
PACT_BROKER_PASSWORD: ${{ secrets.PACT_BROKER_PASSWORD }}
RELEASE_TAG: ${{ needs.regulated-tag-job.outputs.new-tag }}
###############################
# PROVIDER VERIFICATION STEPS #
###############################
verify-consumer-pact:
needs: [ bump-check, regulated-tag-job, init-github-context ]
if: ${{ needs.bump-check.outputs.is-bump == 'no' }}
runs-on: ubuntu-latest
permissions:
contents: 'read'
id-token: 'write'
env:
CURRENT_BRANCH: "${{ needs.init-github-context.outputs.repo-branch }}" # This only gets used for non-webhooks calls
outputs:
provider-version: ${{ steps.render-provider-version.outputs.provider-version }}
steps:
# For PR flow, this will checkout current PR code
# For Webhook, this will checkout `main` which will need to be re-checked out later to the correct provider versions.
- name: Checkout current code
uses: actions/checkout@v4
with:
fetch-depth: 0
# Only runs for webhook calls
- name: Capture webhook event payload as envvars
if: ${{ inputs.pb-event-type != '' }}
run: |
# Save webhook event parameters as envvars
echo "CONSUMER_BRANCH=${{ inputs.consumer-version-branch }}" >> $GITHUB_ENV
echo "CONSUMER_NAME=${{ inputs.consumer-name }}" >> $GITHUB_ENV
# Check out the correct version of the provider to test against for webhook flows
echo "git checkout tags/${{ inputs.provider-version-number }}"
git checkout tags/${{ inputs.provider-version-number }}
# Debug Outputs
echo "pb-event-type=${{ inputs.pb-event-type }}"
echo "consumer-name=${{ inputs.consumer-name }}"
# The consumer-version-branch and consumer-version-number identify the most recent
# consumer branch and version associated with the pact content.
echo "consumer-version-branch/consumer-version-number=${{ inputs.consumer-version-branch }}/${{ inputs.consumer-version-number }}"
# The provider-version-number represents the provider version number in the webhook event payload.
# This corresponds to the GitHub release tag recorded by Sherlock for the corresponding
# deployment environment (dev, staging, and prod).
echo "provider-version-branch/provider-version-number=${{ inputs.provider-version-branch }}/${{ inputs.provider-version-number }}"
# The pact-url is included here in case future pact4s client supports it.
echo "pact-url=${{ inputs.pact-url }}"
# if pb-event-type is null, then do this
# basically, PR flow.
- name: Set PROVIDER_VERSION envvar
id: render-provider-version
run: |
# The PROVIDER_VERSION envvar is used to identify the provider version
# for publishing the results of provider verification.
if [[ -z "${{ inputs.pb-event-type }}" ]]; then
PROVIDER_VERSION=${{ needs.regulated-tag-job.outputs.new-tag }}
else
PROVIDER_VERSION=${{ inputs.provider-version-number }}
fi
# set env for future steps
echo "PROVIDER_VERSION=${PROVIDER_VERSION}"
echo "PROVIDER_VERSION=${PROVIDER_VERSION}" >> $GITHUB_ENV
# set output for can-i-deploy
echo "provider-version=${PROVIDER_VERSION}"
echo "provider-version=${PROVIDER_VERSION}" >> $GITHUB_OUTPUT
# Output current branch and other debug info
- name: Current Branch Debug Outputs
run: |
echo "This workflow has been triggered by '${{ github.event_name }}' event."
# Echo the HEAD commit of the provider branch that has been switched to.
echo "git rev-parse HEAD $(git rev-parse HEAD)"
echo "git rev-parse --abbrev-ref HEAD: $(git rev-parse --abbrev-ref HEAD)"
echo "current github ref: ${GITHUB_REF#refs/heads/}"
# Break out this into it's own job as this is the actual run
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'temurin'
- name: Gradle cache
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: v1-${{ runner.os }}-gradle-${{ github.ref }}-${{ github.sha }}
restore-keys: v1-${{ runner.os }}-gradle-${{ github.ref }}
- name: Verify consumer pacts and publish verification status to Pact Broker
id: verification-test
# The PACT_... envvars are being consumed by build.gradle to configure the
# following System properties (https://docs.pact.io/implementation_guides/jvm/docs/system-properties)
# pact.provider.{branch, version}
# pactbroker.{host, scheme}
# pactbroker.auth.{username, password}
# If no CONSUMER_BRANCH given, will just verify all deployed consumer versions.
env:
PACT_BROKER_URL: pact-broker.dsp-eng-tools.broadinstitute.org
PACT_PROVIDER_VERSION: ${{ env.PROVIDER_VERSION }}
PACT_BROKER_USERNAME: ${{ secrets.PACT_BROKER_USERNAME }}
PACT_BROKER_PASSWORD: ${{ secrets.PACT_BROKER_PASSWORD }}
run: |
# debug outputs
# see readme for info: https://github.com/pact-foundation/pact-jvm/tree/master/provider/junit5
echo "env.CONSUMER_BRANCH=${{ env.CONSUMER_BRANCH }} # This reflects the consumer branch to test against, should only exist on webhook calls."
echo "env.PROVIDER_VERSION=${{ env.PROVIDER_VERSION }} # Pact Version to advertise back to the broker for test results"
echo "env.CONSUMER_NAME=${{ env.CONSUMER_NAME }} # Pact uses this to find the correct consumer to test against"
# actual run
./gradlew --build-cache verifyPacts
################
# CAN-I-DEPLOY #
################
can-i-deploy:
uses: broadinstitute/dsp-reusable-workflows/.github/workflows/can-i-deploy.yaml@main
if: ${{
needs.init-github-context.outputs.verify-provider-side-contracts-only == 'false' &&
needs.bump-check.outputs.is-bump == 'no'
}}
needs: [ verify-consumer-pact, bump-check, init-github-context, publish-contracts, regulated-tag-job ]
secrets:
PACT_BROKER_USERNAME: ${{ secrets.PACT_BROKER_USERNAME }}
PACT_BROKER_PASSWORD: ${{ secrets.PACT_BROKER_PASSWORD }}
with:
pacticipant: "bpm"
version: "${{ needs.verify-consumer-pact.outputs.provider-version }}"