Production was getting a branch to pass unit and system tests locally. Then run in an acceptance test environment against the official test exchange. Test exchange wasn't always totally realistic. You'd typically have to mirror some captured production traffic to make it somewhat realistic. Also, some exchanges had slightly different production versus test versions. Trapped us once with some spaces being insignificant in Canada in the spec and the official test exchange but not allowed in production. Uggh. No real way to test for that.
It evolved to linux repo deployment where a yum command would summon the versions & scripts. Convenient for rollbacks too.
Another aspect was testing the ML parameter set. This would typically be updated daily and even though it was not a code change it is like one as it affects behaviour. ML parameter sets would have to pass profit simulation benchmarks to make it to production which was often a challenge in construction and testing on the grid to meet deadlines.