Repeatable Builds
The underlying premise of the question is that the product getting built requires repeatable builds.
Why should you care about repeatable builds? In general, that question deserves a thread of its own. But one common use case is the hot fix.
Say you have a customer running 5 year old version of your product Foo-Widget v3.2.1
. Your most recent release was v5.4.3
and you stopped supporting 3.x
last year. But, ok, the customer hits a bug, does not want to upgrade and is waving a checkbook at the sales team to get them a fix. You get marching orders to deliver that fix. How does that work?
From the source code perspective, you have a tag Foo-Widget-v3.2.1
you can use to check out the exact sources. So, that's cool. But some bright person said, "thou shalt not check in binaries with source code", and your build system was updated to new compilers, etc. with version 4.x. Hmmm ...
One good approach would be to use container images to build your products. These images have source code of their own kept in a separate module/repo and have a build of their own. The result is a container image stored in your local container image repository. Your build system executes builds by firing up a fresh container from the image in question and running your build script. So, in the product source tree, the build script keeps a reference to the container image required to build it. Note, developers should be able to run the same image on their development machines.
So, all inputs to the build come from controlled sources and the artifacts generated, likewise, store the products in a shared repository. Welcome to the wonderful world of DevOps.
There are other ways to achieve that result without resorting to checked in binaries - as described by several other good answers to this question. They all involve controlled, long term storage for your build and runtime artifacts and referring to those binaries within the product source code.
Even if you just have an old-fashioned "build machine", with all the required tools installed, where your official builds are performed, there is another simple approach: backups. After updating the build system, simply take a full backup and keep it in a very safe place. When the requirement to build a hotfix for an ancient release comes in, stand up a new build system and restore the backup to it. Run your build.
Point is there are many solid ways to implement repeatable builds without trashing your source code.
Problems with Checked In Binaries
Some problems with checked in binaries include:
- Lack of provenance
- Sclerosis of the source code
- Change analysis is difficult
Lack of Provenance
Where did the binary come from? How do we know it is clean from malware, spyware, worms, etc.? Artifact repositories, like Artifactory, Maven repos, container repos have audit logs, keep hash codes of every binary. For replicated artifacts, there is a clear chain of custody from the original source. These are all basic requirements for organizations that care about their own security and that of their customers.
Sclerosis of the Source Code
It takes a looong time to clone the repo. Even switching branches can slow down. The slowdown can especially affect teams in remote offices. Developers' time matters, too.
Change Analysis is Difficult
Binary files are not comparable in any useful way. Instead, you need to refer to the release notes, change log and even source code of the product. Having links back to the full source, where possible, is really important for understanding what goes into a new binary. Checked in binaries can easily lose all of that important information.