-
Notifications
You must be signed in to change notification settings - Fork 0
348 lines (322 loc) · 16.5 KB
/
deploy-1-setup.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
name: Deploy
on:
# This is invoked by both `on.pull_request` and `on.push` events.
workflow_call:
inputs:
deployment-target:
type: string
required: true
description: |
The target machine for the model being deployed.
Equivalent to the name of the GitHub Environment, minus a Release/Prerelease Type.
deployment-type:
type: string
required: true
description: |
The type of model being deployed.
Can be one of: Release, Prerelease.
deployment-version:
type: string
required: true
description: |
The version of the model being deployed.
Usually takes the form of either a git tag (2024.12.0), or a Prerelease version (pr12-2)
deployment-ref:
type: string
required: true
description: |
The git ref where the spack manifest that will be deployed is located.
In Prereleases, this is the HEAD of the source branch of the PR.
prerelease-compare-ref:
type: string
required: false
description: |
Optional git ref to compare against the current inputs.deployment-ref
Useful for checking that files have been modified appropriately.
spack-manifest-path:
type: string
required: true
default: spack.yaml
description: |
Relative path in the Model Deployment Repository that contains the spack manifest file.
Usually a spack.yaml file.
spack-manifest-root-sbd:
type: string
required: true
description: |
Within the spack manifest, the overarching spack bundle that contains all other packages.
Usually the first entry in the .spack.specs section of the manifest.
outputs:
general-metadata-artifact-glob:
value: ${{ jobs.deployment.outputs.general-metadata-artifact-glob }}
description: |
General pattern for the artifact that contains the deployment metadata files for this invocation of the job.
These files are of the form deploy-metadata.{{inputs.deployment-target}}
general-outputs-artifact-glob:
value: ${{ jobs.outputs-upload.outputs.general-artifact-name }}
description: |
General pattern for the artifact that contains the text outputs for this invocation of the job.
Output files are of the form deploy-outputs.{{inputs.deployment-target}}
# TODO: This is a workaround for matrixed dynamic job outputs. See https://github.com/orgs/community/discussions/17245
# The outputs in the file are below:
# spack-version:
# value: ${{ jobs.check-config.outputs.spack-version }}
# description: |
# Branch of 'access-nri/spack' that is used to deploy the model.
# The VERSION part of the 'releases/VERSION' branch.
# spack-config-version:
# value: ${{ jobs.check-config.outputs.spack-config-version }}
# description: |
# Git ref of 'access-nri/spack-config' that is used to configure spack.
# spack-packages-version:
# value: ${{ jobs.check-config.outputs.spack-packages-version }}
# description: |
# Git ref of 'access-nri/spack-packages' that is used to reference custom packages in spack.
# release-deployment-version:
# value: ${{ jobs.check-spack-yaml.outputs.release }}
# description: |
# Version of the model being deployed as if it were a release version.
# ci-configuration-check-failure:
# value: ${{ jobs.check-config.outputs.config-settings-failures }}
# description: |
# Boolean true/false for whether the configuration check failed for inputs.deployment-target
# spack-environment-name:
# value: ${{ jobs.check-spack-yaml.outputs.spack-env-name }}
# description: |
# Name for the spack environment that contains the deployed model
# deployment-result:
# value: ${{ jobs.deployment.result }}
# description: |
# Result of the deployment - skipped/cancelled/success/failure
# deployment-modules-location:
# value: ${{ jobs.deployment.outputs.module-location }}
# description: |
# Directory containing the modules of the deployed model on the inputs.deployment-target
# deployment-spack-location:
# value: ${{ jobs.deployment.outputs.spack-location }}
# description: |
# Directory containing the spack instance of the deployed model on the inputs.deployment-target
jobs:
check-config:
name: '${{ inputs.deployment-target }}: Check Config'
runs-on: ubuntu-latest
outputs:
spack-version: ${{ steps.spack.outputs.version }}
spack-packages-version: ${{ steps.spack-packages.outputs.version }}
spack-config-version: ${{ steps.spack-config.outputs.version }}
config-settings-failures: ${{ steps.settings.outputs.failures }}
steps:
- name: Checkout ${{ github.repository }} Config
uses: actions/checkout@v4
with:
path: model
ref: ${{ inputs.deployment-ref }}
- name: Validate ${{ github.repository }} config/versions.json
uses: access-nri/schema/.github/actions/validate-with-schema@main
with:
schema-version: ${{ vars.CONFIG_VERSIONS_SCHEMA_VERSION }}
schema-location: au.org.access-nri/model/deployment/config/versions
data-location: ./model/config/versions.json
- name: Validate spack-packages version
id: spack-packages
uses: access-nri/build-cd/.github/actions/validate-repo-version@v4
with:
repo-to-check: spack-packages
pr: ${{ inputs.deployment-ref }}
- name: Validate spack version
id: spack
uses: access-nri/build-cd/.github/actions/validate-repo-version@v4
with:
repo-to-check: spack
pr: ${{ inputs.deployment-ref }}
- name: Checkout build-cd Config
uses: actions/checkout@v4
with:
repository: access-nri/build-cd
path: cd
- name: Get spack-config version
id: spack-config
run: |
version=$(jq --compact-output --raw-output \
--arg spack_version "${{ steps.spack.outputs.version }}" \
'.deployment.${{ inputs.deployment-target }}.${{ inputs.deployment-type }}[$spack_version]."spack-config"' cd/config/settings.json
)
echo $version
echo "version=$version" >> $GITHUB_OUTPUT
- name: Validate build-cd config/settings.json
id: settings
uses: access-nri/build-cd/.github/actions/validate-deployment-settings@v4
with:
settings-path: ./cd/config/settings.json
target: ${{ inputs.deployment-target }}
check-spack-yaml:
name: '${{ inputs.deployment-target }}: Check Spack Manifest'
runs-on: ubuntu-latest
permissions:
pull-requests: write
outputs:
# Release version of the deployment. Inferred if not given in inputs.deployment-version
release: ${{ steps.current.outputs.root-spec-ref }}
# Spack env name in form <model>-<version>
spack-env-name: ${{ steps.get-env-name.outputs.env-name }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.deployment-ref }}
- name: Validate ACCESS-NRI spack.yaml Restrictions
if: >-
(github.event_name == 'pull_request' && !github.event.pull_request.draft) ||
(github.event_name == 'issue_comment' && !github.event.issue.draft)
uses: access-nri/schema/.github/actions/validate-with-schema@main
with:
schema-version: ${{ vars.SPACK_YAML_SCHEMA_VERSION }}
schema-location: au.org.access-nri/model/spack/environment/deployment
data-location: ${{ inputs.spack-manifest-path }}
- name: Get current (${{ inputs.deployment-ref }}) root spec version
id: current
uses: access-nri/build-cd/.github/actions/get-spack-root-spec@v4
- name: Check '@latest' version usage
if: >-
(github.event_name == 'pull_request' && !github.event.pull_request.draft) ||
(github.event_name == 'issue_comment' && !github.event.issue.draft)
run: |
if [[ "${{ steps.current.outputs.root-spec-ref }}" == "latest" ]]; then
echo "::error::The '@latest' version string is not allowed in non-draft PRs. It is reserved for a spack package that moves often and cannot be used as a future release tag"
exit 1
fi
- name: Checkout base (${{ inputs.prerelease-compare-ref }}) spack manifest
if: inputs.deployment-type != 'Release'
continue-on-error: true
id: checkout-base-spack
run: |
git checkout ${{ inputs.prerelease-compare-ref }}
if [ ! -f spack.yaml ]; then
echo "::notice::There is no previous version of the spack.yaml to check at ${{ inputs.prerelease-compare-ref }}, continuing..."
exit 1
fi
- name: Get base root spec version
id: base
if: inputs.deployment-type != 'Release' && steps.checkout-base-spack.outcome != 'failure'
uses: access-nri/build-cd/.github/actions/get-spack-root-spec@v4
- name: Check Model Version Modified
# We don't want to fire off model deployment version checks if the PR is never going to be merged.
# We determine this by checking if either the pull request, or the pull request that a comment
# belongs to, is drafted.
# Yes, github.event.issue.draft refers to the pull request if the comment is made on a pull request!
if: >-
inputs.deployment-type != 'Release' && steps.checkout-base-spack.outcome != 'failure' &&
(github.event_name == 'pull_request' && !github.event.pull_request.draft) ||
(github.event_name == 'issue_comment' && !github.event.issue.draft)
id: version-modified
run: |
if [[ "${{ steps.base.outputs.root-spec-ref }}" == "${{ steps.current.outputs.root-spec-ref }}" ]]; then
echo "::warning::The version string hasn't been modified in this PR, but needs to be before merging."
exit 1
fi
- name: Same Model Version Failure Notifier
if: failure() && steps.version-modified.outcome == 'failure'
uses: access-nri/actions/.github/actions/pr-comment@main
with:
comment: |
The model version in the `${{ inputs.spack-manifest-path }}` has not been updated.
Either update it manually, or comment the following to have it updated and committed automatically:
* `!bump major` for feature releases
* `!bump minor` for bugfixes
- name: Check Projections - Specs
# This step checks that the root spec has an appropriate projection in the spack.yaml file.
run: |
git checkout ${{ inputs.deployment-ref }}
current_projection=$(yq '.spack.modules.default.tcl.projections.${{ steps.current.outputs.root-spec-name }}' ${{ inputs.spack-manifest-path }})
expected_projection_prefix='{name}/${{ steps.current.outputs.root-spec-ref }}'
if [[ "$current_projection" == "$expected_projection_prefix"* ]]; then
echo "Current root spec projection ($current_projection) and expected projection prefix ($expected_projection_prefix) match."
else
echo "::error::Current root spec projection ($current_projection) and expected projection prefix ($expected_projection_prefix) don't match."
exit 1
fi
- name: Check Projections - Packages
# This step checks that the defined projections have the same versions as the referenced packages in the spack.yaml file.
# For example, [email protected] matches with the
# modulefile mom5/2023.12.12 (specifically, the version strings match)
if: >-
(github.event_name == 'pull_request' && !github.event.pull_request.draft) ||
(github.event_name == 'issue_comment' && !github.event.issue.draft)
run: |
FAILED="false"
# Get all the defined projections (minus 'all' and the root spec) and make them suitable for a bash for loop
DEPS=$(yq '.spack.modules.default.tcl.projections | del(.all) | del(.${{ steps.current.outputs.root-spec-name }}) | keys | join(" ")' spack.yaml)
# for each of the module names
for DEP in $DEPS; do
# Capture the section after '@git.' or '@' (if it's not a git-attributed version) and before a possible '=' for a given dependency.
# Ex. '@git.2024.02.11' -> '2024.02.11', '@access-esm1.5' -> 'access-esm1.5', '@git.2024.05.21=access-esm1.5' -> '2024.05.21'
package_ver=$(yq ".spack.packages.\"$DEP\".require[0] | match(\"^@(?:git.)?([^=]*)\").captures[0].string" spack.yaml)
expected_projection_prefix="{name}/$package_ver"
# Projections must start with '{name}/VERSION'. For example, '{name}/2024.11.11', or '{name}/2024.11.11-{hash:7}'
current_projection=$(yq ".spack.modules.default.tcl.projections.\"$DEP\"" spack.yaml)
if [[ "$current_projection" == "$expected_projection_prefix"* ]]; then
echo "$DEP: Current projection ($current_projection) and expected projection prefix ($expected_projection_prefix) match."
else
echo "::error::$DEP: Current projection ($current_projection) and expected projection prefix ($expected_projection_prefix) don't match."
FAILED='true'
fi
done
if [[ "$FAILED" == "true" ]]; then
exit 1
fi
- name: Set Spack Env Name String
id: get-env-name
# replace occurences of '.' with '_' in environment name as spack doesn't support '.'. Ex: 'access-om2-v1.0.0' -> 'access-om2-v1_0_0'.
run: echo "env-name=$(echo '${{ inputs.spack-manifest-root-sbd }}-${{ inputs.deployment-version }}' | tr '.' '_')" >> $GITHUB_OUTPUT
deployment:
name: ${{ inputs.deployment-target }}
needs:
- check-config # Verify configuration information is correct
- check-spack-yaml # Verify spack manifest information is correct
uses: access-nri/build-cd/.github/workflows/deploy-2-start.yml@v4
with:
model: ${{ inputs.spack-manifest-root-sbd }}
ref: ${{ inputs.deployment-ref }}
version: ${{ inputs.deployment-version }}
env-name: ${{ needs.check-spack-yaml.outputs.spack-env-name }}
deployment-target: ${{ inputs.deployment-target }}
deployment-type: ${{ inputs.deployment-type }}
root-sbd: ${{ inputs.spack-manifest-root-sbd }}
secrets: inherit
outputs-upload:
name: '${{ inputs.deployment-target }}:Outputs Upload'
# Creates a JSON artifact with information on the deployment created during this run.
# In workflows that call this as a matrix, one must do a deep merge with all files generated from the matrix,
# using the outputs.general-outputs-artifact-name artifact as part of the workflow run.
if: always()
# always, because we might want to interrogate some of the information even in a failed deployment.
needs:
- check-config
- check-spack-yaml
- deployment
runs-on: ubuntu-latest
env:
UPLOAD_FILE_NAME: deploy-outputs.${{ inputs.deployment-target }}
outputs:
general-artifact-name: deploy-outputs.*
steps:
- name: Create outputs file
# See the on.workflow_call.outputs section for details on the info created.
run: |
jq --null-input '{
spack_version: "${{ needs.check-config.outputs.spack-version }}",
spack_config_version: "${{ needs.check-config.outputs.spack-config-version }}",
spack_packages_version: "${{ needs.check-config.outputs.spack-packages-version }}",
ci_configuration_check_failure: ${{ needs.check-config.outputs.config-settings-failures != '' }},
release_deployment_version: "${{ needs.check-spack-yaml.outputs.release }}",
spack_environment_name: "${{ needs.check-spack-yaml.outputs.spack-env-name }}",
deployment_result: "${{ needs.deployment.result }}",
deployment_modules_location: "${{ needs.deployment.outputs.modules-location }}",
deployment_spack_location: "${{ needs.deployment.outputs.spack-location }}"
}' > ./${{ env.UPLOAD_FILE_NAME }}
- name: Upload
uses: actions/upload-artifact@v4
with:
name: ${{ env.UPLOAD_FILE_NAME }}
path: ./${{ env.UPLOAD_FILE_NAME }}
if-no-files-found: error