Having recently guided my team through a migration from Travis CI to GitHub Actions, one of the most nuanced and tricky aspects to translate was our use of build matrices. Travis's `matrix.include` and `matrix.allow_failures` were central to our testing strategy, and replicating that behavior elsewhere required some careful thought. I'm curious how others have tackled this, and what patterns you've found most maintainable.
The core challenge is that the new platforms (GitHub Actions, GitLab CI, CircleCI, etc.) have fundamentally different primitives for parallel and matrix builds. It's not a simple find-and-replace. Here are the key translation points I had to consider:
* **From `env:` and `matrix.include` to Strategy Matrices:** In GitHub Actions, the `matrix` is defined within a `strategy` block on a single job. This is a more structured approach compared to Travis's flat list. You lose some of the free-form mixing, but gain clarity. The `include` keyword still exists in GitHub Actions, but its role is to *add* combinations to an existing matrix, which is a subtle but important difference.
* **Handling `matrix.allow_failures`:** This was crucial for us to test against beta versions of dependencies without failing the entire build. In GitHub Actions, you can use `continue-on-error: ${{ matrix.experimental }}` where `experimental` is a matrix parameter you define. You then use a conditional step or job to report that it failed but didn't block the pipeline, which is a bit more manual.
* **Job Configuration vs. Global Configuration:** In Travis, the matrix expands the entire `.travis.yml` configuration. In most newer systems, the matrix is defined per *job*. This means you might need to refactor your pipeline to be more job-centric, which can actually be a benefit for observability and runtime.
For example, a Travis matrix that tested against multiple Node.js versions and two distinct environment variables might be restructured in GitHub Actions with the matrix defined at the job level, and then environment-specific steps conditionally run based on the matrix parameters. The mental shift is from a "matrix of builds" to a "single job with a matrix of executions."
How did you all approach the migration of complex build matrices? Did you find that migrating forced you to simplify or improve your testing matrix? Were there any specific Travis CI matrix features you found particularly difficult to replicate, and what was your workaround? I'm especially interested in how this intersects with cost management, as matrix builds can quickly consume a lot of compute minutes in the new systems.
~jason
~jason
I'm looking at a similar migration now. The point about `include` in GitHub Actions being additive is a gotcha we just hit. It seems like you can't easily define a single, sparse matrix of specific combinations like you could with Travis's flat list. You have to define a base matrix first and then add the outliers, which feels a bit backward.
How did you handle the case where you need a few, completely distinct environment setups that don't logically share axes? Did you just create separate jobs?