-
Notifications
You must be signed in to change notification settings - Fork 12
310 lines (292 loc) · 14.5 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
name: Verify consumer pacts
# The purpose of this workflow is to verify ANY consumer contract(s) dependent on Sam provider using Pact framework.
#
# The workflow meets the criteria of Pact Broker *Platinum* as described in https://docs.pact.io/pact_nirvana/step_6.
# The can-i-deploy job has been added to this workflow to gate the merge of PRs into develop branch.
#
# 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:
- develop
paths-ignore:
- 'README.md'
push:
branches:
- develop
paths-ignore:
- 'README.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
consumer-version-number:
description: 'the version number of the most recent consumer version associated with the pact content'
required: true
type: string
provider-version-number:
description: 'the provider version number for the verification result'
required: false
type: string
consumer-version-tags:
description: 'the list of tag names for the most recent consumer version associated with the pact content, separated by ", "'
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
provider-version-branch:
description: 'the name of the branch for the provider version associated with the verification result'
required: false
type: string
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: 'the "permalink" URL to the newly published pact (the URL specifying the consumer version URL, rather than the "/latest" format'
required: true
type: string
env:
PACT_BROKER_URL: https://pact-broker.dsp-eng-tools.broadinstitute.org
COURSIER_CACHE: $HOME/.cache
SBT_CACHE: $HOME/.sbt
jobs:
verify-consumer-pact:
runs-on: ubuntu-latest
permissions:
contents: 'read'
id-token: 'write'
outputs:
provider-sha: ${{ steps.verification-test.outputs.provider-sha }}
steps:
- name: Checkout current code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Extract branch
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" == "workflow_dispatch" ]]; then
GITHUB_REF=${{ github.ref }} # The Git Ref that this workflow runs on
GITHUB_SHA=${{ github.sha }} # The Git Sha that this workflow runs on
else
echo "Failed to extract branch information"
exit 1
fi
echo "CURRENT_BRANCH=${GITHUB_REF/refs\/heads\//""}" >> $GITHUB_ENV
echo "CURRENT_SHA=$GITHUB_SHA" >> $GITHUB_ENV
- name: "This step will only run when this workflow is triggered by a Pact Broker webhook event"
if: ${{ inputs.pb-event-type != '' }}
run: |
echo "pb-event-type=${{ inputs.pb-event-type }}"
echo "consumer-name=${{ inputs.consumer-name }}"
echo "consumer-version-branch/consumer-version-number=${{ inputs.consumer-version-branch }}/${{ inputs.consumer-version-number }}"
echo "provider-version-branch/provider-version-number=${{ inputs.provider-version-branch }}/${{ inputs.provider-version-number }}"
# The consumer-version-branch/consumer-version-number is practically sufficient.
# The pact-url is included here in case future pact4s client supports it.
echo "pact-url=${{ inputs.pact-url }}"
if [[ ! -z "${{ inputs.provider-version-branch }}" ]]; then
echo "PROVIDER_BRANCH=${{ inputs.provider-version-branch }}" >> $GITHUB_ENV
echo "CHECKOUT_BRANCH=${{ inputs.provider-version-branch }}" >> $GITHUB_ENV
fi
if [[ ! -z "${{ inputs.provider-version-number }}" ]]; then
echo "PROVIDER_SHA=${{ inputs.provider-version-number }}" >> $GITHUB_ENV
echo "CHECKOUT_SHA=${{ inputs.provider-version-number }}" >> $GITHUB_ENV
fi
echo "CONSUMER_NAME=${{ inputs.consumer-name }}" >> $GITHUB_ENV
echo "CONSUMER_BRANCH=${{ inputs.consumer-version-branch }}" >> $GITHUB_ENV
echo "CONSUMER_SHA=${{ inputs.consumer-version-number }}" >> $GITHUB_ENV
- name: Switch to appropriate branch
run: |
if [[ -z "${{ env.PROVIDER_BRANCH }}" ]]; then
echo "PROVIDER_BRANCH=${{ env.CURRENT_BRANCH }}" >> $GITHUB_ENV
fi
if [[ -z "${{ env.PROVIDER_SHA }}" ]]; then
echo "PROVIDER_SHA=${{ env.CURRENT_SHA }}" >> $GITHUB_ENV
fi
git fetch
if [[ ! -z "${{ env.CHECKOUT_BRANCH }}" ]] && [[ ! -z "${{ env.CHECKOUT_SHA }}" ]]; then
echo "git checkout -b ${{ env.CHECKOUT_BRANCH }} ${{ env.CHECKOUT_SHA }}"
git checkout -b ${{ env.CHECKOUT_BRANCH }} ${{ env.CHECKOUT_SHA }}
echo "git branch"
git branch
else
if [[ "${{ github.event_name }}" == "push" ]]; then
echo "git checkout ${{ env.CURRENT_BRANCH }}"
git checkout ${{ env.CURRENT_BRANCH }}
else
echo "git checkout ${{ env.CURRENT_BRANCH }} ${{ env.CURRENT_SHA }}"
git checkout -b ${{ env.CURRENT_BRANCH }} ${{ env.CURRENT_SHA }}
fi
fi
echo "git rev-parse HEAD"
git rev-parse HEAD
- name: Setup envvars for Pact Broker
run: |
echo "PACT_BROKER_USERNAME=${{ secrets.PACT_BROKER_USERNAME }}" >> $GITHUB_ENV
echo "PACT_BROKER_PASSWORD=${{ secrets.PACT_BROKER_PASSWORD }}" >> $GITHUB_ENV
# Caching Coursier
# Recent sbt versions use Coursier instead of Ivy for dependency management.
# The .coursier cache in the sbtscala docker container is located under its .cache directory, which is mounted to the host $PWD/.cache dir.
# The hashFiles function calculates the hash based on the file contents from
# .sbt, .scala, build.properties
# under the project root directory.
#
# Any changes to these files will result in a different cache key, triggering a cache update.
- name: Coursier cache
id: coursier-cache
uses: actions/cache@v3
with:
path: |
~/.cache
key: sam-${{ runner.os }}-coursier-cache-${{ hashFiles('**/*.sbt', '**/project/*.scala', '**/project/build.properties') }}
- name: Check coursier-cache hit
run: |
if [ "${{ steps.coursier-cache.outputs.cache-hit }}" == 'true' ]; then
echo "Coursier cache ${{ env.COURSIER_CACHE }} restored!"
else
echo "Coursier cache ${{ env.COURSIER_CACHE }} needs update!"
fi
# Caching .sbt directory
# The hashFiles function calculates the hash based on the file contents from all
# .sbt, .scala
# files under the project root directory.
#
# In general, you would include all relevant files that affect the build,
# such as build definition files (build.sbt), project files (*.scala),
# and any other files that impact the build process.
#
# Any changes to these files will result in a different cache key, triggering a cache update.
- name: Cache .sbt directory
id: sbt-cache
uses: actions/cache@v3
with:
path: |
~/.sbt
key: sam-${{ runner.os }}-sbt-cache-${{ hashFiles('**/*.sbt', '**/*.scala') }}
- name: Check sbt cache hit
run: |
if [ "${{ steps.sbt-cache.outputs.cache-hit }}" == 'true' ]; then
echo "${{ env.SBT_CACHE }} cache restored!"
else
echo "${{ env.SBT_CACHE }} cache needs update!"
fi
# Caching sbt target directories
# The hashFiles function calculates the hash based on the file contents from all
# .sbt, src/, project/
# files under the project root directory.
#
# In general, you would include all relevant files that affect the build targets,
# such as build definition files (build.sbt), project files (*.scala),
# and any other files that impact the build process.
#
# Any changes to these files will result in a different cache key, triggering a cache update.
#
# Caching target directories offers significant performance improvements by avoiding
# unnecessary compilation and task executions, enabling incremental compilation, and ensuring
# consistent and reproducible build outputs.
- name: Cache sbt targets
id: sbt-targets
uses: actions/cache@v3
with:
path: |
**/target
key: sam-${{ runner.os }}-sbt-targets-${{ hashFiles('*.sbt', 'src/**/*', '**/project/*.sbt', '**/project/*.scala', '**/project/build.properties') }}
- name: Check sbt targets cache hit
run: |
if [ "${{ steps.sbt-targets.outputs.cache-hit }}" == 'true' ]; then
echo "sbt targets restored!"
else
echo "sbt targets need update!"
fi
# Caching sbt pact4s target directory
# The hashFiles function calculates the hash based on the file contents from all
# pact4s/src/
# files under the project root directory.
#
# This is similar to sbt-targets cache but limited to pact4s targets.
- name: Cache pact4s targets
id: sbt-pact4s-targets
uses: actions/cache@v3
with:
path: |
pact4s/**/target
key: sam-${{ runner.os }}-sbt-pact4s-targets-${{ hashFiles('pact4s/src/**/*') }}
- name: Check sbt pact4s targets cache hit
run: |
if [ "${{ steps.sbt-pact4s-targets.outputs.cache-hit }}" == 'true' ]; then
echo "sbt pact4s targets restored!"
else
echo "sbt pact4s targets need update!"
fi
- name: Verify consumer pacts and publish verification status to Pact Broker
id: verification-test
run: |
echo "provider-sha=${{ env.PROVIDER_SHA }}" >> $GITHUB_OUTPUT
echo "env.CHECKOUT_BRANCH=${{ env.CHECKOUT_BRANCH }} # If not empty, this reflects the branch being checked out (generated by Pact Broker)"
echo "env.CHECKOUT_SHA=${{ env.CHECKOUT_SHA }} # If not empty, this reflects the git commit hash of the branch being checked out (generated by Pact Broker)"
echo "env.CURRENT_BRANCH=${{ env.CURRENT_BRANCH }} # This reflects the branch being checked out if CHECKOUT_BRANCH is empty"
echo "env.CURRENT_SHA=${{ env.CURRENT_SHA }} # This reflects the git commit hash of the branch being checked out if CHECKOUT_BRANCH is empty"
echo "env.PROVIDER_BRANCH=${{ env.PROVIDER_BRANCH }} # This reflects the provider branch for pact verification"
echo "env.PROVIDER_SHA=${{ env.PROVIDER_SHA }} # This reflects the provider version for pact verification"
echo "env.CONSUMER_BRANCH=${{ env.CONSUMER_BRANCH }} # This reflects the consumer branch for pact verification (generated by Pact Broker)"
echo "env.CONSUMER_SHA=${{ env.CONSUMER_SHA }} # This reflects the consumer version for pact verification (generated by Pact Broker)"
# Refer to https://github.com/sbt/docker-sbt on this Docker image
# Recent sbt versions use Coursier instead of Ivy for dependency management.
# On Linux, the location is
# sbt "show csrCacheDirectory"
# with a default value of ~/.cache/coursier/v1
docker run --rm -w /working/sam \
-v "$PWD":/working/sam \
-v ${{ env.COURSIER_CACHE }}:/root/.cache \
-v ${{ env.SBT_CACHE }}:/root/.sbt \
-e PROVIDER_BRANCH=${{ env.PROVIDER_BRANCH }} \
-e PROVIDER_SHA=${{ env.PROVIDER_SHA }} \
-e CONSUMER_NAME=${{ env.CONSUMER_NAME }} \
-e CONSUMER_BRANCH=${{ env.CONSUMER_BRANCH }} \
-e CONSUMER_SHA=${{ env.CONSUMER_SHA }} \
-e PACT_BROKER_URL=${{ env.PACT_BROKER_URL }} \
-e PACT_BROKER_USERNAME=${{ env.PACT_BROKER_USERNAME }} \
-e PACT_BROKER_PASSWORD=${{ env.PACT_BROKER_PASSWORD }} \
sbtscala/scala-sbt:openjdk-17.0.2_1.7.2_2.13.10 \
sbt "set scalafmtOnCompile := false" "project pact4s" "testOnly *SamProviderSpec"
can-i-deploy: # The can-i-deploy job will run as a result of a Sam PR. It reports the pact verification statuses on all deployed environments.
runs-on: ubuntu-latest
if: ${{ inputs.pb-event-type == '' }}
needs: [ verify-consumer-pact ]
steps:
- name: Dispatch to terra-github-workflows
uses: broadinstitute/workflow-dispatch@v3
with:
workflow: .github/workflows/can-i-deploy.yaml
repo: broadinstitute/terra-github-workflows
ref: refs/heads/main
token: ${{ secrets.BROADBOT_TOKEN }} # github token for access to kick off a job in the private repo
inputs: '{ "pacticipant": "sam-provider", "version": "${{ needs.verify-consumer-pact.outputs.provider-sha }}" }'