This is why I personally like to use none of the CI features, and mostly use it like a shell script executor. Images? Stick to OS images only so that you can easily spin them up with `docker run` locally. Artifacts? Read and write them into S3 buckets and avoid the native artifact features.
This is obviously more difficult in the Github actions ecosystem, but I have mostly used Gitlab CI so far. My CI pipelines mostly look like this:
image: ubuntu:24.04
before_script:
- apt-get install ...
script:
- ./ci/build-project.sh
after_script:
- ./ci/upload-build-artifacts.sh