I had the same issue with Gradle builds. In my case, my .war file included many built .jar files.
In Gradle, the Jar and War tasks both are essentially variants of the Zip task, which has a property called "preserveFileTimestamps" (https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Zip.html#org.gradle.api.tasks.bundling.Zip:preserveFileTimestamps)
To make SHAs the same, use this property for both jar and war tasks, for example, somewhere in the build.gradle:
plugins.withType(WarPlugin).whenPluginAdded {
war {
preserveFileTimestamps = false
}
}
jar {
preserveFileTimestamps = false
}
Also an interesting note, if you build on MacOS, make sure .DS_Store files don't get into the built archive, as it will also cause different SHAs.
To disable on MacOS, run this in the terminal:
defaults write com.apple.desktopservices DSDontWriteNetworkStores true
Then reboot it. You will still have to delete the existing .DS_Store files, so from inside your project folder, run:
find . -name '.DS_Store' -exec rm {} \;
If you want to make the SHAs the same even after building on different operating systems, set the reproducibleFileOrder property to true both for war and jar tasks, and make sure the umask is the same on both systems you build (apparently gradle includes the file attributes inside the war/jar files, and I had different SHAs when those attributes were different).
Finally, I was able to get the same SHAs of artifacts wherever I built.
Cheers