forked from opencost/opencost
-
Notifications
You must be signed in to change notification settings - Fork 1
297 lines (273 loc) · 14.2 KB
/
integration-testing.yaml
File metadata and controls
297 lines (273 loc) · 14.2 KB
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
name: Run OpenCost Integration Tests
on:
schedule:
- cron: '0 14 * * *'
push:
branches:
- develop
pull_request_target:
branches:
- develop
merge_group:
types: [checks_requested]
concurrency:
group: ${{ github.event.merge_group.head.sha || github.event.pull_request.head.sha || github.ref }}-intg-tests
cancel-in-progress: false
permissions: {}
jobs:
check_actor_permissions:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request_target' }}
outputs:
ismaintainer: ${{ steps.determine-maintainer.outputs.ismaintainer }}
steps:
- name: Check team membership
uses: tspascoal/get-user-teams-membership@v2
id: teamAffiliation
with:
GITHUB_TOKEN: ${{ secrets.ORG_READER_PAT }}
username: ${{ github.actor }}
organization: opencost
- name: determine if actor is a maintainer
id: determine-maintainer
env:
TEAMS: ${{ join(steps.teamAffiliation.outputs.teams, ',') }}
ACTOR: ${{ github.actor }}
IS_MAINTAINER: ${{ contains(join(steps.teamAffiliation.outputs.teams, ','), 'OpenCost Maintainers') || github.actor == 'dependabot[bot]' }}
run: |
echo "Actor: $ACTOR"
echo "Is maintainer: $IS_MAINTAINER"
echo "ismaintainer=$IS_MAINTAINER" >> $GITHUB_OUTPUT
noop-tests:
needs: check_actor_permissions
permissions: {}
runs-on: ubuntu-latest
if: ${{ (always() && !cancelled()) && github.event_name == 'pull_request_target' && needs.check_actor_permissions.outputs.ismaintainer == 'false' }}
outputs:
is_noop: ${{ steps.noop-tests.outputs.is_noop }}
steps:
- name: Tests Not Needed
id: noop-tests
run: |
echo "integration tests not running because you are not a maintainer. they will run automatically when a PR is merged."
echo "is_noop=true" >> $GITHUB_OUTPUT
wait_for_image_ready:
runs-on: ubuntu-latest
permissions: {}
needs: check_actor_permissions
if: ${{ (always() && !cancelled()) && ( github.event.event_name == 'schedule' || github.event_name == 'push' || github.event_name == 'merge_group' || (github.event_name == 'pull_request_target' && needs.check_actor_permissions.outputs.ismaintainer == 'true')) }}
outputs:
IMAGE_TAG: ${{ steps.set_image_tags.outputs.IMAGE_TAG }}
NAMESPACE: ${{ steps.set_image_tags.outputs.NAMESPACE }}
MAINBRANCH: ${{ steps.set_image_tags.outputs.mainbranch }}
passed: ${{ steps.wait_for_image_ready.outputs.passed }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.merge_group.head.sha || github.event.pull_request.head.sha || github.ref }}
- name: Set OC SHA
id: sha
run: |
echo "OC_SHORTHASH=$(git rev-parse --short HEAD)"
echo "OC_SHORTHASH=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Set image tags
id: set_image_tags
env:
OC_SHORTHASH: ${{ steps.sha.outputs.OC_SHORTHASH }}
REPO_OWNER: ${{ github.repository_owner }}
EVENT_NAME: ${{ github.event_name }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
echo "github.event_name: $EVENT_NAME"
if [[ "$EVENT_NAME" == "merge_group" ]]; then
echo "IMAGE_TAG=ghcr.io/$REPO_OWNER/opencost:test-$OC_SHORTHASH" >> $GITHUB_OUTPUT
echo "NAMESPACE=merge-queue-oc-$OC_SHORTHASH" >> $GITHUB_OUTPUT
echo "mainbranch=false" >> $GITHUB_OUTPUT
elif [[ "$EVENT_NAME" == "pull_request_target" ]]; then
echo "building on maintainer pull request branch"
echo "IMAGE_TAG=ghcr.io/$REPO_OWNER/opencost:test-$OC_SHORTHASH" >> $GITHUB_OUTPUT
echo "NAMESPACE=pr-$PR_NUMBER-oc-$OC_SHORTHASH" >> $GITHUB_OUTPUT
echo "mainbranch=false" >> $GITHUB_OUTPUT
else
echo "building on develop branch"
echo "IMAGE_TAG=ghcr.io/$REPO_OWNER/opencost:develop-$OC_SHORTHASH" >> $GITHUB_OUTPUT
echo "NAMESPACE=develop-oc-$OC_SHORTHASH" >> $GITHUB_OUTPUT
echo "mainbranch=true" >> $GITHUB_OUTPUT
fi
- name: Log into ghcr.io
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: wait for docker image to be ready
id: wait_for_image_ready
env:
IMAGE_TAG: ${{ steps.set_image_tags.outputs.IMAGE_TAG }}
run: |
max_attempts=100
# Loop until the Docker image can be pulled
until docker manifest inspect $IMAGE_TAG; do
echo "Waiting for Docker image $IMAGE_TAG to be available, $max_attempts tries remain..."
sleep 6
max_attempts=$((max_attempts - 1))
if [[ $max_attempts -eq 0 ]]; then
echo "Docker image $IMAGE_TAG is not available after 10 minutes. Exiting..."
exit 1
fi
done
echo "Docker image $IMAGE_TAG is ready!"
echo "passed=true" >> $GITHUB_OUTPUT
build-test-stack:
needs: wait_for_image_ready
if: ${{ (always() && !cancelled()) && ( github.event.event_name == 'schedule' || github.event_name == 'push' || github.event_name == 'merge_group' || (github.event_name == 'pull_request_target' && needs.check_actor_permissions.outputs.ismaintainer == 'true')) }}
uses: opencost/opencost-infra/.github/workflows/build-stack.yaml@main
secrets: inherit
with:
oc-container-version: "${{ needs.wait_for_image_ready.outputs.IMAGE_TAG }}"
namespace: "${{ needs.wait_for_image_ready.outputs.NAMESPACE }}"
build-test-stack-promless:
needs: wait_for_image_ready
if: ${{ (always() && !cancelled()) && ( github.event.event_name == 'schedule' || github.event_name == 'push' || github.event_name == 'merge_group' || (github.event_name == 'pull_request_target' && needs.check_actor_permissions.outputs.ismaintainer == 'true')) }}
uses: opencost/opencost-infra/.github/workflows/build-stack.yaml@main
secrets: inherit
with:
oc-container-version: "${{ needs.wait_for_image_ready.outputs.IMAGE_TAG }}"
namespace: "${{ needs.wait_for_image_ready.outputs.NAMESPACE }}-promless"
prometheus: false
wait-for-dns:
needs: [wait_for_image_ready, build-test-stack]
runs-on: ubuntu-latest
if: ${{ (always() && !cancelled()) && ( github.event.event_name == 'schedule' || github.event_name == 'push' || github.event_name == 'merge_group' || (github.event_name == 'pull_request_target' && needs.check_actor_permissions.outputs.ismaintainer == 'true')) }}
permissions: {}
steps:
- name: Wait for DNS to resolve
id: wait-for-dns
env:
NAMESPACE: ${{ needs.wait_for_image_ready.outputs.NAMESPACE }}
run: |
echo "Waiting for $NAMESPACE.infra.opencost.io to resolve in DNS..."
max_attempts=60
until host $NAMESPACE.infra.opencost.io; do
echo "DNS not yet resolved for $NAMESPACE.infra.opencost.io, $max_attempts tries remain..."
sleep 10
max_attempts=$((max_attempts - 1))
if [[ $max_attempts -eq 0 ]]; then
echo "DNS resolution failed for $NAMESPACE.infra.opencost.io after 10 minutes. Exiting..."
exit 1
fi
done
echo "DNS resolved successfully for $NAMESPACE.infra.opencost.io!"
run-tests:
needs: [wait_for_image_ready, build-test-stack, wait-for-dns]
if: ${{ (always() && !cancelled()) && ( github.event.event_name == 'schedule' || github.event_name == 'push' || github.event_name == 'merge_group' || (github.event_name == 'pull_request_target' && needs.check_actor_permissions.outputs.ismaintainer == 'true')) }}
permissions: {}
uses: opencost/opencost-infra/.github/workflows/test-stack.yaml@main
secrets: inherit
with:
namespace: "${{ needs.wait_for_image_ready.outputs.NAMESPACE }}"
target_branch: "${{ github.event.pull_request.head.ref || 'main' }}"
wait-for-data-collection:
needs: [wait_for_image_ready, build-test-stack, build-test-stack-promless]
runs-on: ubuntu-latest
if: ${{ (always() && !cancelled()) && ( github.event.event_name == 'schedule' || github.event_name == 'push' || github.event_name == 'merge_group' || (github.event_name == 'pull_request_target' && needs.check_actor_permissions.outputs.ismaintainer == 'true')) }}
permissions: {}
steps:
- name: Wait 22 minutes for promless data collection
run: |
sleep 1320
run-comparison-tests:
needs: [wait_for_image_ready, build-test-stack, build-test-stack-promless, wait-for-data-collection]
if: ${{ (always() && !cancelled()) && ( github.event.event_name == 'schedule' || github.event_name == 'push' || github.event_name == 'merge_group' || (github.event_name == 'pull_request_target' && needs.check_actor_permissions.outputs.ismaintainer == 'true')) }}
permissions: {}
uses: opencost/opencost-infra/.github/workflows/test-stack.yaml@main
secrets: inherit
with:
namespace: "${{ needs.wait_for_image_ready.outputs.NAMESPACE }}"
comparison_namespace: "${{ needs.wait_for_image_ready.outputs.NAMESPACE }}-promless"
target_branch: "${{ github.event.pull_request.head.ref || 'main' }}"
comparison: true
hold-on-failure:
needs: [wait_for_image_ready, run-tests, run-comparison-tests]
if: ${{ needs.run-tests.outputs.passed == 'false' || needs.run-comparison-tests.outputs.passed == 'false' }}
runs-on: ubuntu-latest
permissions: {}
steps:
- name: Hold stack for investigation
env:
NAMESPACE: ${{ needs.wait_for_image_ready.outputs.NAMESPACE }}
run: |
echo "Tests failed. Holding stacks up for 1 hour for investigation..."
echo "Stack namespace: $NAMESPACE"
echo "Stack will be automatically torn down after 1 hour"
sleep 3600
teardown-test-stack:
needs: [wait_for_image_ready, run-tests, run-comparison-tests, hold-on-failure]
if: ${{ (always() && !cancelled()) && ( github.event.event_name == 'schedule' || github.event_name == 'push' || github.event_name == 'merge_group' || (github.event_name == 'pull_request_target' && needs.check_actor_permissions.outputs.ismaintainer == 'true')) }}
uses: opencost/opencost-infra/.github/workflows/destroy-stack.yaml@main
secrets: inherit
permissions: {}
with:
namespace: "${{ needs.wait_for_image_ready.outputs.NAMESPACE }}"
teardown-test-stack-comparison:
needs: [wait_for_image_ready, run-comparison-tests, hold-on-failure]
if: ${{ (always() && !cancelled()) && ( github.event.event_name == 'schedule' || github.event_name == 'push' || github.event_name == 'merge_group' || (github.event_name == 'pull_request_target' && needs.check_actor_permissions.outputs.ismaintainer == 'true')) }}
uses: opencost/opencost-infra/.github/workflows/destroy-stack.yaml@main
secrets: inherit
permissions: {}
with:
namespace: "${{ needs.wait_for_image_ready.outputs.NAMESPACE }}-promless"
check-success:
needs: [noop-tests, run-tests]
permissions: {}
runs-on: ubuntu-latest
if: ${{ always() }}
steps:
- name: Check success
id: check-success
env:
IS_NOOP: ${{ needs.noop-tests.outputs.is_noop }}
PASSED: ${{ needs.run-tests.outputs.passed }}
run: |
if [[ "$IS_NOOP" == "true" ]]; then
echo "No-op tests, skipping success check"
exit 0
fi
if [[ "$PASSED" != "true" ]]; then
echo "One or more integration tests failed"
exit 1
fi
# if [[ "${{ needs.run-comparison-tests.outputs.passed }}" != "true" ]]; then
# echo "One or more comparison tests failed"
# exit 1
# fi
echo "All integration tests passed"
exit 0
set-labels:
needs: [noop-tests, run-tests, run-comparison-tests]
if: ${{ (always() && !cancelled()) && ( github.event_name == 'pull_request_target' && needs.check_actor_permissions.outputs.ismaintainer == 'true') }}
runs-on: ubuntu-latest
permissions: {}
steps:
- name: label integration tests failing
if: ${{ always() && contains(needs.*.result, 'failure') && !cancelled()}}
uses: andymckay/[email protected]
with:
add-labels: "integration tests failed"
- uses: mondeja/remove-labels-gh-action@v2
if: ${{ always() && contains(needs.*.result, 'failure') && !cancelled()}}
with:
token: ${{ secrets.GITHUB_TOKEN }}
labels: |
integration tests passed
- name: Label integration tests passing
if: ${{ always() && !contains(needs.*.result, 'failure') && !cancelled()}}
uses: andymckay/[email protected]
with:
add-labels: "integration tests passed"
- uses: mondeja/remove-labels-gh-action@v2
if: ${{ always() && !contains(needs.*.result, 'failure') && !cancelled()}}
with:
token: ${{ secrets.GITHUB_TOKEN }}
labels: |
integration tests failed