Skip to content

Commit c13c639

Browse files
CodeGatjo-basevi
andauthored
Multi-HPC Workflows (#218)
* Move jobs around so they can be part of a single parallel workflow (#203) * settings-1-update.yml: Validate settings in parallel based on target * deploy-2-start.yml: Output modules and spack location from workflow * deploy-2-start.yml: Capitalize inputs.type values to keep in line with callers * deploy-1-setup.yml: Update inputs/outputs to be suitable for a matrix job. This matrix job must have the required I/O to do pre-deploy checks, as well as a deployment. * Move check-spack-yaml and check-config jobs from ci.yml to deploy-1-setup.yml * deploy-1-setup.yml: Use new inputs as inputs to deploy-2-start.yml * deploy-1-start.yml: Upload 'outputs' of workflow as an artifact. This is due to dynamic matrix job outputs not being collected appropriately. See https://github.com/orgs/community/discussions/17245 * cd.yml: Run checks of target config in parallel * ci.yml: Dynamically generate deployment comment, start matrix of deployment jobs, misc changes * cd.yml: Update deployment matrix jq * ci.yml: Add newline to deployment comment to fix formatting * Update job names to include deploy target * deploy-2-start.yml: Remove `release` and `build-db` jobs, output new general metadata artifact glob * deploy-1-setup.yml: Output `general-metadata-artifact-glob` from `deploy-2-start.yml` invocation * cd.yml: Add `release`, `build-db` jobs from `deploy-2-start.yml` * deploy-2-start.yml: Prepend metadata artifacts with deployment environment * cd.yml: Generate release notes based on deployment targets * .gitignore venv, pytest metadata * Create j2 templates for release notes and deployment comments Co-authoured-by: Tom McAdam <[email protected]> * Add scripts for jinja generation, requirements, created modules * Update ci/cd to use templating script * Add testing infrastructure * Updated ci/cd calls to use script notation, removed --type arg * ci.yml: Use output file as comment due to ACCESS-NRI/actions#20 * Add test validating non-collection of variables with the wrong `template_prefix` * Remove outputs folder as it is unused * Update requirements.txt filepath * Added backslashes to multiline script invocation * Update template * Replace `env.SPACK_YAML_MODEL_YQ` to accomodate for multi-target-format `spack.yaml` * Uppercase ROOT_PACKAGE * Update target matrix generation to take into account model repos deployment targets * Added comments * Added new get-target-matrix action * Update ci.yml, cd.yml to use get-target-matrix * Simplify undeploy workflow * cd.yml: Updated output variable * Updated workflow reference to `undeploy-1-start.yml` * get-target-matrix: Made vars more generic * generate-build-metadata.bash: Reference explicit Gadi.* files * tests/scripts/generate-build-metadata: Updated test data inputs/outputs * cd.yml: Use Gadi-specific outputs/metadata for build-db upload * Update README.md with information on this repository and it's workflows * Add config/README.md to explain files within the folder * Apply suggestions from code review Co-authored-by: jo-basevi <[email protected]> Signed-off-by: Tommy Gatti <[email protected]> * Add GitHub search link * Small scale fixes from ACCESS-TEST E2E Testing * Split `deployment-environment` input into `deployment-target` and `deployment-type` * Update all build-cd refs to latest `v4`, get latest default branch ref for non-action calls * Use default `inputs.ref` for `checkout` action to get default branch * Remove conditional logic for `deployment-type`s This is because all environment are now of the form SUPERCOMPUTER TYPE --------- Signed-off-by: Tommy Gatti <[email protected]> Co-authored-by: jo-basevi <[email protected]>
1 parent 25d79af commit c13c639

35 files changed

+1285
-602
lines changed

.github/actions/get-deploy-paths/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
steps:
3131
- name: Get Deployment Paths
3232
id: paths
33-
uses: access-nri/build-cd/.github/actions/get-deploy-paths@main
33+
uses: access-nri/build-cd/.github/actions/get-deploy-paths@vX
3434
with:
3535
spack-installs-root-path: ${{ vars.SPACK_INSTALLS_ROOT_PATH }}
3636
spack-version: "0.21"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Get Deployment Target Matrix Action
2+
3+
Action that returns a matrix of deployment targets based on the caller's input and the valid targets in the build-cd repository.
4+
5+
## Inputs
6+
7+
| Name | Type | Description | Required | Default | Example |
8+
| ---- | ---- | ----------- | -------- | ------- | ------- |
9+
| `targets` | `string` (space-separated) | A space-separated list of deployment targets for the model deployment repository. | `true` | N/A | `"Gadi Setonix"` |
10+
11+
## Outputs
12+
13+
| Name | Type | Description | Example |
14+
| ---- | ---- | ----------- | ------- |
15+
| `valid-targets` | `string` | A JSON array of valid deployment targets, suitable for use as a matrix. | `"["Gadi", "Setonix"]"` |
16+
17+
## Example
18+
19+
```yaml
20+
# ...
21+
jobs:
22+
generate-matrix:
23+
runs-on: ubuntu-latest
24+
outputs:
25+
valid-targets: ${{ steps.generate.outputs.valid-targets }}
26+
steps:
27+
- id: generate
28+
uses: access-nri/build-cd/.github/actions/get-target-matrix@vX
29+
with:
30+
targets: ${{ vars.MODEL_REPO_TARGETS }}
31+
32+
matrix:
33+
runs-on: ubuntu-latest
34+
needs: [generate-matrix]
35+
strategy:
36+
matrix:
37+
target: ${{ fromJson(needs.generate-matrix.outputs.valid-targets) }}
38+
steps:
39+
- run: echo "Wow, this is running in ${{ matrix.target }}!"
40+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Get Deployment Target Matrix
2+
description: Action that returns a matrix of deployment targets based on the caller's input and the valid targets in the build-cd repository.
3+
author: Tommy Gatti
4+
inputs:
5+
targets:
6+
type: string
7+
required: true
8+
description: A space-separated list of deployment targets for the model deployment repository.
9+
outputs:
10+
valid-targets:
11+
description: A JSON array of valid deployment targets, suitable for use as a matrix.
12+
value: ${{ steps.generate.outputs.targets }}
13+
runs:
14+
using: composite
15+
steps:
16+
- name: Get deployment settings.json
17+
uses: actions/checkout@v4
18+
with:
19+
repository: access-nri/build-cd
20+
21+
- name: Generate Deployment Target Matrix
22+
shell: bash
23+
id: generate
24+
# These are used in the deploy job to determine the targets to deploy to - irrespective of the type of deployment.
25+
# We use the list of valid targets (from build-cd) intersected with targets set in the caller repository to determine the final list.
26+
run: |
27+
valid_targets=$(jq --raw-output --compact-output \
28+
'.deployment | keys' \
29+
config/settings.json
30+
)
31+
repo_targets=$(jq --null-input --raw-output --compact-output \
32+
--arg valids "${{ inputs.targets }}" \
33+
'$valids | split(" ")'
34+
)
35+
# This is the intersection between the valid and caller-defined targets
36+
targets=$(jq --null-input --raw-output --compact-output\
37+
--argjson valid "$valid_targets" \
38+
--argjson ours "$repo_targets" \
39+
'$valid - ($valid - $ours)'
40+
)
41+
42+
echo "From build-cd's valid targets: $valid_targets, and ${{ github.repository }}s chosen targets: $repo_targets, we will deploy to $targets"
43+
echo "targets=$targets" >> $GITHUB_OUTPUT

.github/actions/validate-deployment-settings/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ This action validates various `ACCESS-NRI/build-cd` deployment settings.
2222
# ...
2323
- name: Validate settings
2424
id: settings
25-
uses: access-nri/build-cd/.github/actions/validate-deployment-settings@main
25+
uses: access-nri/build-cd/.github/actions/validate-deployment-settings@vX
2626
with:
2727
settings-path: ./some/settings.json
2828
target: Supercomputer

.github/actions/validate-repo-version/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ This action checks that the tags specified in a models `config/versions.json` is
2020
```yaml
2121
# ...
2222
- id: validate
23-
uses: access-nri/build-cd/.github/actions/validate-repo-version@main
23+
uses: access-nri/build-cd/.github/actions/validate-repo-version@vX
2424
with:
2525
repo-to-check: spack-packages
2626
pr: 12

.github/workflows/cd.yml

+165-10
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,19 @@ on:
2727
# - spack.yaml
2828

2929
env:
30-
SPACK_YAML_MODEL_YQ: .spack.specs[0]
30+
# This attempts to get the spack.yaml model first via the multi-target
31+
# .spack.definitions.root_package method, then the traditional '.spack.specs[0]'.
32+
SPACK_YAML_MODEL_YQ: (.spack.definitions[] | select(."ROOT_PACKAGE") | .[][]) // .spack.specs[0]
33+
METADATA_PATH: /opt/metadata
34+
OUTPUTS_PATH: /opt/outputs
3135
jobs:
3236
defaults:
3337
name: Set Defaults
3438
# Unfortunately, you can't set a dynamic default value based on `inputs` yet
3539
runs-on: ubuntu-latest
3640
outputs:
3741
root-sbd: ${{ steps.root-sbd.outputs.default }}
42+
targets: ${{ steps.target.outputs.valid-targets }}
3843
steps:
3944
- name: root-sbd
4045
id: root-sbd
@@ -45,20 +50,29 @@ jobs:
4550
echo "default=${{ inputs.root-sbd }}" >> $GITHUB_OUTPUT
4651
fi
4752
53+
- name: Generate Deployment Target Matrix
54+
id: target
55+
uses: access-nri/build-cd/.github/actions/get-target-matrix@v4
56+
with:
57+
targets: ${{ vars.RELEASE_DEPLOYMENT_TARGETS }}
58+
4859
verify-settings:
4960
name: Verify Deployment Settings
5061
runs-on: ubuntu-latest
62+
needs:
63+
- defaults
64+
strategy:
65+
matrix:
66+
target: ${{ fromJson(needs.defaults.outputs.targets) }}
5167
steps:
5268
- uses: actions/checkout@v4
5369
with:
54-
repository: ACCESS-NRI/build-cd
55-
ref: main
70+
repository: access-nri/build-cd
5671

57-
- uses: access-nri/build-cd/.github/actions/validate-deployment-settings@main
72+
- uses: access-nri/build-cd/.github/actions/validate-deployment-settings@v4
5873
with:
5974
settings-path: ./config/settings.json
60-
# TODO: Turn this into a matrix job of targets
61-
target: Gadi
75+
target: ${{ matrix.target }}
6276
error-level: error
6377

6478
push-tag:
@@ -103,11 +117,152 @@ jobs:
103117
needs:
104118
- defaults
105119
- push-tag
106-
uses: access-nri/build-cd/.github/workflows/deploy-1-setup.yml@main
120+
strategy:
121+
matrix:
122+
target: ${{ fromJson(needs.defaults.outputs.targets) }}
123+
uses: access-nri/build-cd/.github/workflows/deploy-1-setup.yml@v4
107124
with:
108-
ref: ${{ github.ref_name }}
109-
version: ${{ needs.push-tag.outputs.name }}
110-
root-sbd: ${{ needs.defaults.outputs.root-sbd }}
125+
deployment-target: ${{ matrix.target }}
126+
deployment-ref: ${{ github.ref_name }}
127+
deployment-type: Release
128+
deployment-version: ${{ needs.push-tag.outputs.name }}
129+
spack-manifest-path: ./spack.yaml
130+
spack-manifest-root-sbd: ${{ needs.defaults.outputs.root-sbd }}
111131
secrets: inherit
112132
permissions:
113133
contents: write
134+
# We require pull-requests:write despite not using it in this path,
135+
# because it is needed by the pull_request invocation of the workflow.
136+
pull-requests: write
137+
138+
release:
139+
name: Create Release
140+
needs:
141+
- defaults
142+
- push-tag
143+
- deploy-release
144+
runs-on: ubuntu-latest
145+
env:
146+
TEMPLATED_RELEASE_BODY_PATH: /opt/release-body.md
147+
outputs:
148+
url: ${{ steps.release.outputs.url }}
149+
created-at: ${{ steps.metadata.outputs.created-at }}
150+
steps:
151+
- name: Checkout build-cd
152+
uses: actions/checkout@v4
153+
with:
154+
repository: access-nri/build-cd
155+
156+
- name: Download Metadata Artifacts
157+
uses: actions/download-artifact@v4
158+
with:
159+
pattern: ${{ needs.deploy-release.outputs.general-metadata-artifact-glob }}
160+
path: ${{ env.METADATA_PATH }}
161+
merge-multiple: true
162+
163+
- name: Download Outputs Artifacts
164+
uses: actions/download-artifact@v4
165+
with:
166+
pattern: ${{ needs.deploy-release.outputs.general-outputs-artifact-glob }}
167+
path: ${{ env.OUTPUTS_PATH }}
168+
merge-multiple: true
169+
170+
- name: Set up Python
171+
uses: actions/setup-python@v5
172+
with:
173+
python-version: 3.12
174+
cache: pip
175+
176+
- name: Install Dependencies
177+
run: |
178+
python -m pip install --upgrade pip
179+
pip install -q -q -r scripts/jinja_template/requirements.txt
180+
181+
- name: Generate Release Notes
182+
id: release-body
183+
env:
184+
J2_MODEL: ${{ inputs.model }}
185+
J2_VERSION: ${{ needs.push-tag.outputs.name }}
186+
J2_ROOT_SBD: ${{ needs.defaults.outputs.root-sbd }}
187+
run: |
188+
python -m scripts.jinja_template.render_deployment_info \
189+
--template scripts/jinja_template/templates/release-body.md.j2 \
190+
--deployment-outputs ${{ env.OUTPUTS_PATH }} \
191+
--output ${{ env.TEMPLATED_RELEASE_BODY_PATH }}
192+
193+
- name: Create Release
194+
id: release
195+
uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 # v2.0.5
196+
with:
197+
tag_name: ${{ needs.push-tag.outputs.name }}
198+
name: ${{ inputs.model}} ${{ needs.push-tag.outputs.name }}
199+
body_path: ${{ env.TEMPLATED_RELEASE_BODY_PATH }}
200+
generate_release_notes: true
201+
fail_on_unmatched_files: true
202+
files: |
203+
${{ env.METADATA_PATH }}/*.spack.yaml
204+
${{ env.METADATA_PATH }}/*.spack.lock
205+
${{ env.METADATA_PATH }}/*.spack.location
206+
${{ env.METADATA_PATH }}/*.spack.location.json
207+
208+
- name: Release Metadata
209+
id: metadata
210+
env:
211+
GH_TOKEN: ${{ github.token }}
212+
run: echo "created-at=$(gh release view --json createdAt --jq '.createdAt' --repo ${{ github.repository }})" >> $GITHUB_OUTPUT
213+
214+
# TODO: This will only upload data related to the Gadi deployment
215+
build-db:
216+
name: Build DB Metadata Upload
217+
needs:
218+
- defaults
219+
- deploy-release
220+
- release
221+
runs-on: ubuntu-latest
222+
steps:
223+
- name: Download Metadata Artifact
224+
uses: actions/download-artifact@v4
225+
with:
226+
pattern: ${{ needs.deploy-release.outputs.general-metadata-artifact-glob }}
227+
path: ${{ env.METADATA_PATH }}
228+
merge-multiple: true
229+
230+
- name: Download Outputs Artifact
231+
uses: actions/download-artifact@v4
232+
with:
233+
pattern: ${{ needs.deploy-release.outputs.general-outputs-artifact-glob }}
234+
path: ${{ env.OUTPUTS_PATH }}
235+
merge-multiple: true
236+
237+
- name: 'Get Gadi spack-* Repo Versions'
238+
id: spack-versions
239+
run: |
240+
echo "packages-version=$(jq --raw-output --compact-output '.spack_packages_version' ${{ env.OUTPUTS_PATH }}/deploy-outputs.Gadi)" >> $GITHUB_OUTPUT
241+
echo "config-version=$(jq --raw-output --compact-output '.spack_config_version' ${{ env.OUTPUTS_PATH }}/deploy-outputs.Gadi)" >> $GITHUB_OUTPUT
242+
243+
- name: Checkout Upload Script
244+
uses: actions/checkout@v4
245+
with:
246+
repository: access-nri/build-cd
247+
248+
- name: Setup Python
249+
uses: actions/setup-python@v5
250+
with:
251+
python-version: ${{ vars.PYTHON_VERSION }}
252+
cache: pip
253+
254+
- name: Install Build Metadata Script Requirements
255+
run: pip install -r tools/release_provenance/requirements.txt
256+
257+
- name: Upload Build Metadata
258+
env:
259+
BUILD_DB_CONNECTION_STR: ${{ secrets.BUILD_DB_CONNECTION_STR }}
260+
run: |
261+
./scripts/generate-build-metadata.bash \
262+
${{ needs.release.outputs.url }} ${{ needs.release.outputs.created-at }} \
263+
${{ steps.spack-versions.outputs.packages-version }} ${{ steps.spack-versions.outputs.config-version }} \
264+
${{ env.METADATA_PATH }} ${{ env.OUTPUTS_PATH }} \
265+
${{ needs.defaults.outputs.root-sbd }} ${{ vars.BUILD_DB_PACKAGES }}
266+
267+
echo "Attempting upload of build_metadata.json"
268+
python ./tools/release_provenance/save_release.py "${{ env.OUTPUTS_PATH }}/build_metadata.json"

.github/workflows/ci-closed.yml

+19-8
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ run-name: ${{ inputs.model }} PR Closed Cleanup
99
on:
1010
workflow_call:
1111
inputs:
12-
model:
12+
root-sbd:
1313
type: string
1414
required: true
15-
description: The model that is being tested and deployed
15+
description: The model package name that is going to be removed
1616
# Callers usually have the trigger:
1717
# pull_request:
1818
# types:
@@ -29,19 +29,30 @@ jobs:
2929
runs-on: ubuntu-latest
3030
outputs:
3131
version-pattern: ${{ steps.version.outputs.pattern }}
32+
targets: ${{ steps.target.outputs.valid-targets }}
3233
steps:
33-
- name: Version Pattern
34+
- name: Get Version Pattern
3435
id: version
3536
# For example, `access-om3-pr12-*`
36-
run: |
37-
repo_name_sanitized=$(echo ${{ github.event.repository.name }} | tr [:upper:] [:lower:] | tr '.' 'p' )
38-
echo "pattern=${repo_name_sanitized}-pr${{ github.event.pull_request.number }}-*" >> $GITHUB_OUTPUT
37+
run: echo "pattern=${{ inputs.root-sbd }}-pr${{ github.event.pull_request.number }}-*" >> $GITHUB_OUTPUT
38+
39+
- name: Generate Deployment Target Matrix
40+
id: target
41+
uses: access-nri/build-cd/.github/actions/get-target-matrix@v4
42+
with:
43+
targets: ${{ vars.PRERELEASE_DEPLOYMENT_TARGETS }}
3944

4045
undeploy-prereleases:
4146
name: Undeploy Prereleases Matching ${{ needs.setup.outputs.version-pattern }}
4247
needs:
4348
- setup
44-
uses: access-nri/build-cd/.github/workflows/undeploy-1-setup.yml@main
49+
strategy:
50+
matrix:
51+
target: ${{ fromJson(needs.setup.outputs.targets) }}
52+
fail-fast: false
53+
uses: access-nri/build-cd/.github/workflows/undeploy-1-start.yml@v4
4554
with:
46-
version-pattern: ${{ needs.setup.outputs.version-pattern }}
55+
version-pattern: ${{ inputs.root-sbd }}-pr${{ github.event.pull_request.number }}-*
56+
target: ${{ matrix.target }}
57+
type: Prerelease
4758
secrets: inherit

.github/workflows/ci-comment.yml

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ on:
1313
root-sbd:
1414
type: string
1515
required: false
16-
# The equivalent default is set in the defaults job below.
16+
# The equivalent default is set in the defaults job below.
1717
# default: ${{ inputs.model }}
1818
description: |
1919
The name of the root Spack Bundle Definition, if it is different from the model name.
@@ -53,7 +53,9 @@ jobs:
5353
contents: write
5454
env:
5555
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
56-
SPACK_YAML_MODEL_YQ: .spack.specs[0]
56+
# This attempts to get the spack.yaml model first via the multi-target
57+
# .spack.definitions.root_package method, then the traditional '.spack.specs[0]'.
58+
SPACK_YAML_MODEL_YQ: (.spack.definitions[] | select(."ROOT_PACKAGE") | .[][]) // .spack.specs[0]
5759
SPACK_YAML_MODEL_PROJECTION_YQ: .spack.modules.default.tcl.projections.${{ needs.defaults.outputs.root-sbd }}
5860
steps:
5961
- uses: actions/checkout@v4

0 commit comments

Comments
 (0)