

You can (and should!) do exactly the same with “traditional” GitHub Actions style YAML.
Avoid putting commands in the YAML - put those in separate scripts and call them from the YAML. The YAML should only be used for things that can’t be done from scripts (e.g. job matrices, uploading artifacts, reporting status etc.)
It allows the CI engine to determine which jobs to start, what their steps are etc.
To be fair I have worked on one project that had very complex CI and we almost decided to generate the CI graph procedurally with a Python script (Gitlab supports this, somewhat awkwardly). But in the end we decided it wouldn’t be worth the overhead of writing, maintaining and learning a whole new CI system on top of Gitlab’s CI.