How to insert deterministic unique buildId into java jar Gradle manifest?

We have a cache of computed data stored on disk. We want to know if this calculated data came from this version or another version of the assembly. We are currently using the commit + timestamp stored in MANIFEST.MF as a relatively unique way to identify an assembly. However, the timestamp causes incremental build problems in gradle as gradle knows the time has changed, rebuilds the MANIFEST.MF, and re-jars even if nothing has changed.

We want to replace the timestamp with the best "buildId" in MANIFEST.MF. Requirements:

  • Unique to different builds : commit on its own is not good enough as there may be uncommitted changes in dev machines.
  • Deterministic : the timestamp does not work as gradle will see this as a "change" in the dependencies and rebuild the jar even if the other dependencies do not change.

I think the correct solution is to use a hash of the actual dependencies for the "jar" task, which is the "classes", which is all the compiled class files that will be included in the jar.

I could theoretically create a task that takes a hash of all classes and injects that into the manifest.

However, gradle already does this, and this is how it determines if a task is current. It takes an input hash and an output hash and checks if the combo is in the database. So, is there a way to access this information with some rare gradle API, or with reflection?

Or maybe some other solution?

+3


source to share


2 answers


I think you might want to step back and reevaluate what you would like to achieve by adding buildIds to your manifest files. In particular, the first requirement you stated regarding building on dev machines doesn't make a lot of sense. The reason you would usually like to add some sort of buildIds file to your manifest file is so that you can keep track of where and when the jar was built so you can determine which set of sources to look for and see when something will go wrong. If you create assemblies based on the contents of the dev filesystem, you can never go back and determine where that assembly came from. If the buildId is based on the generated class files, or even the source files themselves on the developer machine, then all developers must do this to change one symbol in one file.and this assembly is gone forever and cannot be re-generated unless this developer can undo, which will return the file system to the form it was originally.

Instead, you should base your buildIds on something that can be recreated without the need for developers to remember anything. For this to happen, buildIds must be searchable and easily accessible to all team members at all times. Controls a control that meets all of these requirements, and by sounds, this is what you are already using, so there is no additional overhead to add to your workflow.



I would recommend forgetting about how to base your buildIds on the contents of the filesystem and base on the commit instead. If you are concerned that developers might create a build that does not come from master / trunk / etc, all major revision control systems provide some branching method that will still allow the developer to check out code that will not interfere with the production of primary production. If you use the version number / hash to keep track of the jar version, you have the option to go back and reproduce the build exactly, even if it's only from a local branch on the developer machine. I don't recommend the last bit about using a local branch unless you know the build will be very short, however, since buildIds are based on branches local to the same dev machine.cannot be searched by anyone else on the team. Instead, if you are using a distributed version control system, I would recommend that you use any changes used in the assembly in a central location so that anyone else who has a problem shooting the assembly has access to the code used to do so.

+2


source


You can create a task to create an assembly id and use the classes as input and the output is a file with the assembly id.

The assembly ID does not have to be a hash of the inputs, but can only be a timestamp.



However, because the task of generating the assembly ID is class-specific, it only restores the timestamp of the assembly when the changes occurred.

0


source







All Articles