Build
Building software projects is hard. Here are some best practices: Make it fast
There is the continuous struggle between make it right and make it fast. Some buildsystems promise to combine both goals.
We all know that multitasking is evil. Every build that runs longer than 10s enhances the chance that we drift off an start multitasking.
While a builddate is very convenient for humans to process it is a hard to do reproducible builds with this, unless you inject the date from the outside into the product. Inversion of control do not just call /usr/bin/date but let the buildserver prepare the date for you e.g. in an environment variable.
Just to be on the safe side a release build should start from scratch.
Just to make sure, that everything including licenses and os updates still works as expected.
Less data is always better. Faster clones, less resources taken, opens the option to have more builds in parallel.
Make it even smaller for the buildserver. It probably does not need all the docs that you have checked in.
If it behaves in unexpected ways, fix it.
Interesting example for incorrect builds.
Normally a buildserver is not interested in the history of the repository. On the other hand it needs some context, to show what was changed. For me the best option is a shallow clone, that can be also used to incrementally pull. Because a pull with not much changes will still be faster than a full shallow clone.
The build should be as simple as possible. e.g. make is better than make clean generate build test release
The buildfile should work for all parties. Its a wide range from developers to buildservers. If all use the same, errors are found earlier on and the project makes sure that all important steps are in git.
My first choice is to not depend on preinstalled tools but put everything into the workspace and make it self contained. Another option is using docker images, but this has another set of drawbacks.
Every gap between different buildsystems makes the whole image less correct / efficient. E.g. recursive make considered harmful.
Put all build artifacts to a common folder structure that is outside of the source folders. This makes your gitignore files very straight forward + you do not even need a clean buildstep, because you just can delete one folder.
Make your buildlogs meaningful. Reduce warnings, remove debug output.
The results of a build should be as compact as possible. Saving everything without a requirement is not fast and not cheap.
Do not hardcode -j16 or something into your build. This should be possible for the buildservers to decide. They know best what resources they have and how many parallel jobs they have to serve.
A viable compromis might be to do some edges of the build in a dirty way, if it really brings speed. E.g. create dockerimages with a snapshot, so that not all work has to be done from scratch.