-
Notifications
You must be signed in to change notification settings - Fork 7
358 lines (336 loc) · 15.5 KB
/
build-main.yaml
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
---
name: build main
# Actions that take place after a workflow trigger on the master/main branch.
# If a DOCKERHUB_USERNAME secret is defined the image is pushed.
# If a TRIGGER_AWX secret is defined the image is deployed to Kubernetes.
# Actions also run if the repository is tagged.
# Every tag is deployed to staging and every production-grade tag
# (of the form N.N.N) is deployed to production.
# ---------------
# Control secrets
# ---------------
#
# At the GitHub 'organisation' or 'project' level you are expected to
# have the following GitHub 'Repository Secrets' defined
# (i.e. via 'Settings -> Secrets'): -
#
# BE_IMAGE_TAG optional - default is a valid version
# BE_NAMESPACE optional - default xchem
# FE_IMAGE_TAG optional - default is a valid version
# FE_NAMESPACE optional - default xchem
# STACK_NAMESPACE optional - default xchem
#
# DOCKERHUB_USERNAME optional
# DOCKERHUB_TOKEN optional - required if DOCKERHUB_USERNAME
#
# TRIGGER_AWX optional - set to 'yes' to deploy 'official' builds via AWX
# you also need to define the repository environments
# 'awx/fragalysis-staging' and 'awx/fragalysis-production'.
# You should not set this and TRIGGER_DEVELOPER_AWX.
# TRIGGER_DEVELOPER_AWX optional - set to 'yes' to deploy a developer-specific build via AWX
# you also need to set the repository environment
# 'awx/fragalysis-developer'.
# You should not set this and TRIGGER_AWX.
#
# SLACK_NOTIFY_STAGING_WEBHOOK optional - required for Slack notifications
# SLACK_NOTIFY_PRODUCTION_WEBHOOK optional - required for Slack notifications
#
# -----------
# Environment (GitHub Environments)
# -----------
#
# Environment awx/fragalysis-staging
# Environment awx/fragalysis-production
# Environment awx/fragalysis-developer
#
# For automated deployment we expect the following in the environment: -
#
# AWX_HOST The fully-qualified URL to AWX.
# If not set, AWX triggering does not take place.
# AWX_USER The username of someone that can execute the AWX Job.
# AWX_USER_PASSWORD The user's password.
# AWX_TEMPLATE_NAME The template to run (for developer environments)
on:
push:
tags:
- '**'
# Build if triggered externally.
# The trigger can provide a number of (optional) inputs...
workflow_dispatch:
inputs:
be_namespace:
description: The fragalysis-backend namespace (to pull from)
required: false
be_image_tag:
description: The fragalysis-backend image container tag (to pull from)
required: false
fe_namespace:
description: The fragalysis-frontend namespace (to clone from)
required: false
fe_image_tag:
description: The fragalysis-frontend image container tag (to pull from)
required: false
stack_namespace:
description: The fragalysis-stack Docker Hub namespace (to publish to)
required: false
stack_image_tag:
description: The image tag to apply to the fragalysis-stack image
required: false
env:
# The following 'defaults' are used in the 'Initialise workflow variables' step,
# which creates 'outputs' for use in steps and jobs that follow it.
# The values set here are used unless a matching secret is found.
# Secrets are the way users dynamically control the behaviour of this Action.
#
# For Jobs conditional on the presence of a secret see this Gist...
# https://gist.github.com/jonico/24ffebee6d2fa2e679389fac8aef50a3
#
# New (tagged) production stack builds should always be preceded by a change to one
# or both of the Backend or Frontend tags. i.e. before we make a production
# release the author needs to change one or both of: -
#
# - BE_IMAGE_TAG
# - FE_IMAGE_TAG
#
#
# Commit the changes and then tag or make a release from the stack repository.
BE_IMAGE_TAG: 2025.01.1
FE_IMAGE_TAG: 2025.01.1
BE_NAMESPACE: xchem
FE_NAMESPACE: xchem
STACK_NAMESPACE: xchem
jobs:
build:
runs-on: ubuntu-latest
outputs:
deploy: ${{ steps.vars.outputs.deploy }}
deploy_developer: ${{ steps.vars.outputs.deploy_developer }}
production_tag: ${{ steps.vars.outputs.production_tag }}
push: ${{ steps.vars.outputs.push }}
tag: ${{ steps.vars.outputs.tag }}
version: ${{ steps.vars.outputs.version }}
steps:
- name: Inject slug/short variables
uses: rlespinasse/github-slug-action@v4
- name: Initialise workflow variables
id: vars
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
TRIGGER_AWX: ${{ secrets.TRIGGER_AWX }}
TRIGGER_DEVELOPER_AWX: ${{ secrets.TRIGGER_DEVELOPER_AWX }}
run: |
# BE_NAMESPACE
BE_NAMESPACE="${{ env.BE_NAMESPACE }}"
if [ -n "${{ github.event.inputs.be_namespace }}" ]; then BE_NAMESPACE="${{ github.event.inputs.be_namespace }}";
elif [ -n "${{ secrets.BE_NAMESPACE }}" ]; then BE_NAMESPACE="${{ secrets.BE_NAMESPACE }}"; fi
echo BE_NAMESPACE=${BE_NAMESPACE}
echo "BE_NAMESPACE=${BE_NAMESPACE}" >> $GITHUB_OUTPUT
# BE_IMAGE_TAG
BE_IMAGE_TAG="${{ env.BE_IMAGE_TAG }}"
if [ -n "${{ github.event.inputs.be_image_tag }}" ]; then BE_IMAGE_TAG="${{ github.event.inputs.be_image_tag }}";
elif [ -n "${{ secrets.BE_IMAGE_TAG }}" ]; then BE_IMAGE_TAG="${{ secrets.BE_IMAGE_TAG }}"; fi
echo BE_IMAGE_TAG=${BE_IMAGE_TAG}
echo "BE_IMAGE_TAG=${BE_IMAGE_TAG}" >> $GITHUB_OUTPUT
# FE_NAMESPACE
FE_NAMESPACE="${{ env.FE_NAMESPACE }}"
if [ -n "${{ github.event.inputs.fe_namespace }}" ]; then FE_NAMESPACE="${{ github.event.inputs.fe_namespace }}";
elif [ -n "${{ secrets.FE_NAMESPACE }}" ]; then FE_NAMESPACE="${{ secrets.FE_NAMESPACE }}"; fi
echo FE_NAMESPACE=${FE_NAMESPACE}
echo "FE_NAMESPACE=${FE_NAMESPACE}" >> $GITHUB_OUTPUT
# FE_IMAGE_TAG
FE_IMAGE_TAG="${{ env.FE_IMAGE_TAG }}"
if [ -n "${{ github.event.inputs.fe_image_tag }}" ]; then FE_IMAGE_TAG="${{ github.event.inputs.fe_image_tag }}";
elif [ -n "${{ secrets.FE_IMAGE_TAG }}" ]; then FE_IMAGE_TAG="${{ secrets.FE_IMAGE_TAG }}"; fi
echo FE_IMAGE_TAG=${FE_IMAGE_TAG}
echo "FE_IMAGE_TAG=${FE_IMAGE_TAG}" >> $GITHUB_OUTPUT
# STACK_NAMESPACE
STACK_NAMESPACE="${{ env.STACK_NAMESPACE }}"
if [ -n "${{ github.event.inputs.stack_namespace }}" ]; then STACK_NAMESPACE="${{ github.event.inputs.stack_namespace }}";
elif [ -n "${{ secrets.STACK_NAMESPACE }}" ]; then STACK_NAMESPACE="${{ secrets.STACK_NAMESPACE }}"; fi
echo STACK_NAMESPACE=${STACK_NAMESPACE}
echo "STACK_NAMESPACE=${STACK_NAMESPACE}" >> $GITHUB_OUTPUT
# Set a version
STACK_VERSION="0.0.0"
if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then STACK_VERSION="${{ env.GITHUB_REF_SLUG }}";
else STACK_VERSION="${{ github.ref_name }}.${{ github.run_number }}"; fi
echo STACK_VERSION=${STACK_VERSION}
echo "STACK_VERSION=${STACK_VERSION}" >> $GITHUB_OUTPUT
# What image tag are we creating? 'latest' (if not tagged) or a GitHub tag?
TAG="latest"
if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then TAG="${{ env.GITHUB_REF_SLUG }}"; fi
echo tag=${TAG}
echo "tag=${TAG}" >> $GITHUB_OUTPUT
# Do we push, i.e. is DOCKERHUB_USERNAME defined?
echo push=${{ env.DOCKERHUB_USERNAME != '' }}
echo "push=${{ env.DOCKERHUB_USERNAME != '' }}" >> $GITHUB_OUTPUT
# Do we deploy official images, i.e. is TRIGGER_AWX 'yes'?
echo deploy=${{ env.TRIGGER_AWX == 'yes' }}
echo "deploy=${{ env.TRIGGER_AWX == 'yes' }}" >> $GITHUB_OUTPUT
# Do we deploy developer images, i.e. is TRIGGER_DEVELOPER_AWX 'yes'?
echo deploy_developer=${{ env.TRIGGER_DEVELOPER_AWX == 'yes' }}
echo "deploy_developer=${{ env.TRIGGER_DEVELOPER_AWX == 'yes' }}" >> $GITHUB_OUTPUT
# Do we deploy to production, i.e. is there a TAG of the form N.N.N?
HAS_PRODUCTION_TAG=false
if [[ ${{ env.GITHUB_REF_SLUG }} =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then HAS_PRODUCTION_TAG=true; fi
echo production_tag=${HAS_PRODUCTION_TAG}
echo "production_tag=${HAS_PRODUCTION_TAG}" >> $GITHUB_OUTPUT
# Do we send Slack notifications, i.e. is SLACK_NOTIFY_WEBHOOK defined?
echo notify=${{ env.SLACK_NOTIFY_WEBHOOK != '' }}
echo "notify=${{ env.SLACK_NOTIFY_WEBHOOK != '' }}" >> $GITHUB_OUTPUT
- name: Checkout
uses: actions/checkout@v4
- name: Display build args
run: |
echo BE_NAMESPACE=${{ steps.vars.outputs.BE_NAMESPACE }}
echo BE_IMAGE_TAG=${{ steps.vars.outputs.BE_IMAGE_TAG }}
echo FE_NAMESPACE=${{ steps.vars.outputs.FE_NAMESPACE }}
echo FE_IMAGE_TAG=${{ steps.vars.outputs.FE_IMAGE_TAG }}
echo STACK_NAMESPACE=${{ steps.vars.outputs.STACK_NAMESPACE }}
echo STACK_VERSION=${{ steps.vars.outputs.STACK_VERSION }}
- name: Build
uses: docker/build-push-action@v5
with:
tags: ${{ steps.vars.outputs.STACK_NAMESPACE }}/fragalysis-stack:${{ steps.vars.outputs.tag }}
build-args: |
BE_NAMESPACE=${{ steps.vars.outputs.BE_NAMESPACE }}
BE_IMAGE_TAG=${{ steps.vars.outputs.BE_IMAGE_TAG }}
FE_NAMESPACE=${{ steps.vars.outputs.FE_NAMESPACE }}
FE_IMAGE_TAG=${{ steps.vars.outputs.FE_IMAGE_TAG }}
STACK_NAMESPACE=${{ steps.vars.outputs.STACK_NAMESPACE }}
STACK_VERSION=${{ steps.vars.outputs.tag }}
- name: Login to DockerHub
if: steps.vars.outputs.push == 'true'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Push
if: steps.vars.outputs.push == 'true'
run: docker push ${{ steps.vars.outputs.STACK_NAMESPACE }}/fragalysis-stack:${{ steps.vars.outputs.tag }}
deploy-staging:
# A fixed job that deploys to the Fragalysis Staging Kubernetes Namespace
# using a pre-defined AWX Job Template name,
# and the awx/fragalysis-production environment.
#
# All builds, tagged or otherwise, are deployed to staging.
needs: build
if: |
needs.build.outputs.push == 'true' &&
needs.build.outputs.deploy == 'true'
runs-on: ubuntu-latest
environment: awx/fragalysis-production
env:
slack_notify_staging_webhook: ${{ secrets.SLACK_NOTIFY_STAGING_WEBHOOK }}
steps:
- name: Notify staging deployment started
if: ${{ env.slack_notify_staging_webhook != '' }}
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ env.slack_notify_staging_webhook }}
SLACK_TITLE: A new STAGING deployment has begun
SLACK_MESSAGE: Image tag is "${{ needs.build.outputs.tag }}"
SLACK_FOOTER: ''
MSG_MINIMAL: true
- name: Deploy staging
id: deploy_staging
uses: informaticsmatters/trigger-awx-action@v2
with:
template: Staging Fragalysis Stack
template-host: ${{ secrets.AWX_HOST }}
template-user: ${{ secrets.AWX_USER }}
template-user-password: ${{ secrets.AWX_USER_PASSWORD }}
template-var: stack_image_tag
template-var-value: ${{ needs.build.outputs.tag }}
continue-on-error: true
- name: Notify staging deployment failure
if: ${{ env.slack_notify_staging_webhook != '' && steps.deploy_staging.outcome == 'failure' }}
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ env.slack_notify_staging_webhook }}
SLACK_TITLE: The STAGING deployment FAILED
SLACK_MESSAGE: Please review the corresponding fragalysis-stack GitHuib Action Log
SLACK_FOOTER: ''
MSG_MINIMAL: true
- name: Notify staging deployment complete
if: ${{ env.slack_notify_staging_webhook != '' && steps.deploy_staging.outcome == 'success' }}
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ env.slack_notify_staging_webhook }}
SLACK_TITLE: A new STAGING deployment is ready
SLACK_MESSAGE: Image tag is "${{ needs.build.outputs.tag }}"
SLACK_FOOTER: ''
MSG_MINIMAL: true
deploy-production:
# A fixed job that deploys to the Fragalysis Production Kubernetes Namespace
# using a pre-defined AWX Job Template name,
# and the awx/fragalysis-production environment.
#
# Only builds triggered by production-grade tags are deployed to production.
needs: build
if: |
needs.build.outputs.push == 'true' &&
needs.build.outputs.deploy == 'true' &&
needs.build.outputs.production_tag == 'true'
runs-on: ubuntu-latest
environment: awx/fragalysis-production
env:
slack_notify_production_webhook: ${{ secrets.SLACK_NOTIFY_PRODUCTION_WEBHOOK }}
steps:
- name: Notify production deployment started
if: ${{ env.slack_notify_production_webhook != '' }}
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ env.slack_notify_production_webhook }}
SLACK_TITLE: A new PRODUCTION deployment has begun
SLACK_MESSAGE: Image tag is "${{ needs.build.outputs.tag }}"
SLACK_FOOTER: ''
MSG_MINIMAL: true
- name: Deploy production
id: deploy_production
uses: informaticsmatters/trigger-awx-action@v2
with:
template: Production Fragalysis Stack
template-host: ${{ secrets.AWX_HOST }}
template-user: ${{ secrets.AWX_USER }}
template-user-password: ${{ secrets.AWX_USER_PASSWORD }}
template-var: stack_image_tag
template-var-value: ${{ needs.build.outputs.tag }}
continue-on-error: true
- name: Notify production deployment failure
if: ${{ env.slack_notify_production_webhook != '' && steps.deploy_production.outcome == 'failure' }}
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ env.slack_notify_production_webhook }}
SLACK_TITLE: The PRODUCTION deployment FAILED
SLACK_MESSAGE: Please review the corresponding fragalysis-stack GitHuib Action Log
SLACK_FOOTER: ''
MSG_MINIMAL: true
- name: Notify production deployment complete
if: ${{ env.slack_notify_production_webhook != '' && steps.deploy_production.outcome == 'success'}}
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ env.slack_notify_production_webhook }}
SLACK_TITLE: A new PRODUCTION deployment is ready
SLACK_MESSAGE: Image tag is "${{ needs.build.outputs.tag }}"
SLACK_FOOTER: ''
MSG_MINIMAL: true
deploy-developer:
# Deploys to a developer's Fragalysis Kubernetes Namespace
# using an environment-defined AWX Job Template name,
# and the awx/fragalysis-developer environment.
needs: build
if: |
needs.build.outputs.push == 'true' &&
needs.build.outputs.deploy_developer == 'true'
runs-on: ubuntu-latest
environment: awx/fragalysis-developer
steps:
- name: Deploy developer
uses: informaticsmatters/trigger-awx-action@v2
with:
template: ${{ secrets.AWX_TEMPLATE_NAME }}
template-host: ${{ secrets.AWX_HOST }}
template-user: ${{ secrets.AWX_USER }}
template-user-password: ${{ secrets.AWX_USER_PASSWORD }}
template-var: stack_image_tag
template-var-value: ${{ needs.build.outputs.tag }}