CI boilerplate reduction#34272
Conversation
|
@kwryankrattiger Thanks for working on this! One high-level question, based on --- # common/ci.yaml
ci:
variables:
SIZE: "small"
mappings:
- match: [llvm]
runner-attributes:
variables:
SIZE: "medium"
--- # big-env/spack.yaml
spack:
spec:
- llvm targets=all
- paraview
ci:
include: common
variables:
SIZE: "large" # All the packages in this environment are largeIn the generated pipeline, a If this PR doesn't already, is there anything preventing the |
|
@blue42u So the To address the quirky behavior, I think that has more to do with how the "scope" is defined. At the top most level, you don't specify the value the must be applied to each job, you specify the "default" value that is populated to all jobs, including the service jobs and signing job. The next scope that is applied is the job type scope. For the build jobs the The last scope that is applied for build jobs is the mapping scope which will override and append to everything defined in the previous scopes. This is all relatively consistent with how things were done before, but now configurations are allowed to span multiple files to move boilerplate out of the specific stack files. To achieve the desired result of forcing all build jobs to set a variable you could either change the custom configuration scopes passed to the generate step to exclude the default mappings (subtle) or specify a mapping to all discovered packages that sets the One of the things that I am less thrilled about with the default spack merging is that I think maybe I am just reading the config stuff backwards and "source" prepending means the the lower precedence configs are processed last and therefore everything after is appended to it. I will run some tests once I get this working again. But the non-override behavior for script is an issue. @tgamblin @scottwittenburg if either of you have ideas or comments on how this should work. |
|
One the override behavior, I think I found the solution, |
|
@kwryankrattiger It worries me that you're trying to add key-specific merging behavior here, in #32300 I was avoiding that completely (to decouple as much as possible the Spack configuration format from GitLab CI's own schema). There are also weird edge cases I do not believe the Spack config-merge can or should handle, e.g. Regarding "scope," while I understand the explanation and know that the proposed workaround works, I still find it very unintuitive and confusing. It introduces cross-dependencies where one config needs to know where values are set in "previous" configs to even work. Which means a setup using "mixin" configs is more-or-less unmaintainable (or at the very least, really confusing). |
I did check this, and it is handled by checking if one of them is a list, converting the dict value to a list, and then applying the merge. This should be okay.
I don't think there is really a way around this. The way spack configs work in general is read -> merge -> get processed by spack command. Even if each yaml was read and processed in order in the CI module, which is what we decided not to do by moving to the spack config merge instead of the Having to know which configs are being used, the order of precedence they are specified in, and what values they set I think is an okay requirement since that is already a requirement when using configuration scopes in spack. The biggest difference is the CI module has scopes to make it easier to say "do this for everything" once at a high level rather than having to always specify configs at the lower level. Things like |
The most recent changes are trying not to do this because your concerns were echoed by others. The scripts are the only ones that I am a little concerned about the default behavior being applied, but they will probably be fine. |
|
Crazy half-baked idea, what if it was a list of "modifications" applied to the generated pipeline in reverse order: --- # common/ci.yaml
ci:
pipeline-gen: # TODO: Better name for this key
- match_behavior: first
submapping:
- match: [llvm]
build-job-attributes:
+variables: {SIZE: "medium"}
- build-job-attributes:
+variables: {SIZE: "small"}
--- # big-env/spack.yaml
spack:
include: common/ci.yaml
spec:
- llvm targets=all
- paraview
ci:
pipeline-gen:
- +variables: {SIZE: "large"}After the Spack config-merge, the above two should become the unified config: spack:
spec:
- llvm targets=all
- paraview
ci:
pipeline-gen:
- +variables: {SIZE: "large"}
- match_behavior: first
submapping:
- match: [llvm]
build-job-attributes:
+variables: {SIZE: "medium"}
- build-job-attributes:
+variables: {SIZE: "small"}The entries below Still a bit confusing from the reversed order (it would need to be explained as something like "value from first matching key" and " |
From what I can tell, this is exactly like what is already there, but less verbose. The biggest change this is making I think is the contents of the mappings list can either be just a runner attributes dict, or a submapping/matches specification. I do like I like the idea of having a better shorthand for saying "everything gets this mapping if it gets here" that is not the somewhat odd |
|
actually...I think I am seeing the more subtle part of this proposal. There would be no top level runner attributes, except for maybe a subset which we can chose like I think the way this would look then would be --- # common/ci.yaml
ci:
pipeline-gen: # TODO: Better name for this key
- match_behavior: first
submapping:
- match: [llvm]
build-job-attributes:
+variables: {SIZE: "medium"}
# build-job-attrbutes apply all block
- +variables: {SIZE: "small"}
--- # big-env/spack.yaml
spack:
include: common/ci.yaml
spec:
- llvm targets=all
- paraview
ci:
pipeline-gen:
# stack override apply all block
- +variables: {SIZE: "large"} |
|
I wanted to keep the But otherwise, exactly! |
|
Mappings always only apply to the build jobs, so maybe it would make sense to nest the mappings under that section? If we go this route, the idea of having a |
|
There's also The problem with Basically, for #32300 the parts of the config that are GitLab CI attributes should be considered (practically) a opaque blob of data (except in --- # common/ci.yaml
ci:
pipeline-gen: # TODO: Better name for this key
- match_behavior: first
submapping:
- match: [llvm]
build-job-attributes: GITLAB BITS
- build-job-attributes: GITLAB BITS
--- # big-env/spack.yaml
spack:
include: common/ci.yaml
spec:
- llvm targets=all
- paraview
ci:
pipeline-gen:
- build-job-attributes: GITLAB BITSSo, I'm pretty sure all the (It looks like there was a missing |
|
Okay, I think I am seeing more where you are going with this, your idea is taking this quite a bit further than I originally was thinking, but I think that is a good thing. It certainly leans more into your work with handling then merge semantics, which I think is good. I like this idea of the This will make the schema a tad more complicated, because there will be three types of items allowed now instead of one, I would like to get more feedback from @scottwittenburg on this, but I think this is a good direction. |
5788af4 to
286d9fe
Compare
7fb751b to
31475bf
Compare
adamjstewart
left a comment
There was a problem hiding this comment.
I like this a lot! This resolves most of my complaints about adding new pipelines. Some additional ideas (alternatives?) worth considering, either in this PR or more likely a follow-up PR:
Platform based on directory name
I wonder if we could condition arch on pipeline location. For example, move:
share/spack/gitlab/cloud_pipelines/stacks/ml-linux-x86_64-cpu/spack.yaml
to:
share/spack/gitlab/cloud_pipelines/linux/x86_64/ml-cpu/spack.yaml
and have the arch automatically detected based on the file location.
Matrix of platforms
For a lot of (most?) pipelines, we want to build a set of packages on most (all?) platforms. For example, for the ML stack, I'm planning on testing the following cross product:
- platform: linux, darwin
- target: x86_64, aarch64, ppc64le
- variants: +cuda, +rocm,
cudarocm
This requires me to duplicate the list of packages I want to build in 18 files. If I could instead specify a matrix in spack.yaml and exclude known invalid combinations (no such thing as darwin ppc64le, tensorflow doesn't build on aarch64) that would make it much easier to maintain. As is, if I want to add a new package to the list, I would have to update 18 files.
See #32894 and #32893 for details on this.
P.S. Not trying to hold up this wonderful PR by suggesting more work, just wanted to put these ideas out here so people have them in mind while working on this refactor. I'm guessing these will end up being follow-up PRs in the end.
Will review again after this is rebased, the ML pipelines have changed quite a bit since this PR branch was first created and I want to make sure nothing is lost in the refactor.
|
Thanks @adamjstewart for pushing this PR forward! I'd like to request one change to be made before this is merged. Currently this PR changes the ci:
pipeline-gen:
- reindex-job:
script:
- &init_spack
- git clone ...
- source ...
- spack buildcache update-index ...
- build-job:
tags: [foo]
script:
- *init_spack
- spack ci rebuild ...I already raised this request with @kwryankrattiger over Slack DMs, we settled on an idea to reduce surprises when using this format: |
|
I've started that pipeline for you! |
f63411f to
6e5c619
Compare
|
@spackbot rebuild everything |
|
I've started that pipeline for you! |
e32e16b to
223c915
Compare
d836348 to
0d08dbc
Compare
Configuration: - New notation for list concatenation (prepend/append) - New notation for string concatenation (prepend/append) - Break out configuration files for: ci.yaml, cdash.yaml, view.yaml - Spack CI section refactored to improve self-consistency and composability - Scripts are now lists of lists and/or lists of strings - Job attributes are now listed under precedence ordered list that are composed/merged using Spack config merge rules. - "service-jobs" are identified explicitly rather than as a batch CI: - Consolidate common, platform, and architecture configurations for all CI stacks into composable configuration files - Make padding consistent across all stacks (256) - Merge all package -> runner mappings to be consistent across all stacks Unit Test: - Refactor CI module unit-tests for refactor configuration Docs: - Add docs for new notations in configuration.rst - Rewrite docs on CI pipelines to be consistent with refactored CI workflow
0d08dbc to
fee0e36
Compare
|
@spackbot run pipeline |
|
I've started that pipeline for you! |
|
@scottwittenburg quick, review this, CI passed! |
|
Sorry for reviewing this only so late, but regarding >>> a = [1, 2, 3]
>>> a += [4]
>>> a
[1, 2, 3, 4]So, |
It's time. One feature I have been waiting to be merged in upstream Spack (separate CI configuration: spack/spack#34272) has just been merged. The other feature (local binary cache: spack/spack#32136) remains stagant, but the older install-tree caching (https://gitlab.com/hpctoolkit/hpctoolkit/-/merge_requests/828) and the Buildah shared layer cache (https://gitlab.com/hpctoolkit/hpctoolkit/-/merge_requests/810) serve a similar purpose. This commit rips out all use of my custom Spack fork (from November), instead using upstream Spack develop. This unfreezes all the versions of dependencies tested in CI, meaning we will *really* be testing with the latest of all packages. Always.
* CI configuration boilerplate reduction and refactor Configuration: - New notation for list concatenation (prepend/append) - New notation for string concatenation (prepend/append) - Break out configuration files for: ci.yaml, cdash.yaml, view.yaml - Spack CI section refactored to improve self-consistency and composability - Scripts are now lists of lists and/or lists of strings - Job attributes are now listed under precedence ordered list that are composed/merged using Spack config merge rules. - "service-jobs" are identified explicitly rather than as a batch CI: - Consolidate common, platform, and architecture configurations for all CI stacks into composable configuration files - Make padding consistent across all stacks (256) - Merge all package -> runner mappings to be consistent across all stacks Unit Test: - Refactor CI module unit-tests for refactor configuration Docs: - Add docs for new notations in configuration.rst - Rewrite docs on CI pipelines to be consistent with refactored CI workflow * Script verbose environ, dev bootstrap * Port spack#35409
Reduce boilerplate in the CI yaml by allowing composition based on pipeline targets OS/arch
CC: @blue42u