It seems best practice is to build the final artifact, in full, at the earliest stage. And then the stages that follow (testing, deployment) should use same artifact throughout, to protect against some sort of mismatch between what was tested, and what gets deployed. How do runtimes come to play here? My specific case is with java, but I assume other languages have similar concern. With java, I have the option of making just fatjar artifact, but I also have the option of making a bundle of that fatjar + minimal / treeshaken jdk (using jlink).
My concerns for making artifacts of just jar:
Prod might have different versions (eg older build of same minor version), resulting in issues being caught only after deployment
Somewhat related to above; harder orchestration of java upgrade (ie, starting using new features, and be assured those new features will be working upon deployment)
Unclear reproducibility; if some time down the line older version needs to be deployed, it must track the required jdk version, somehow. While java code is backwards compatible, the builds aren't since jdk occasionally deprecates and moves out certain classes, requiring a new build for old code to run on new version
My concerns for making artifacts of bundle of both jar and runtime:
Ties itself to OS; builds need be duplicated for all OS that are intended to be supported
Runtime isn't that small (~100 mb), which might slow down work as it gets copied around all the time, and rarely changes
More responsibility for updating software if/when java runtime security patches are released on developers