Hard-coding timestamp in manifest.mf for docker cache

Hi there,

I already have something like this to set each entry inside generated Jars to a constant timestamp:

     tasks.withType(Jar) {
        eachFile { FileCopyDetails details ->
            details.getFile().setLastModified(0L);
            def pf = details.getFile();
            while (pf != null && (pf = pf.getParentFile()) != null) {
                pf.setLastModified(0);
            }
        }
    }

however I can’t find a way to get a handle on META-INF/ and META-INF/MANIFEST.MF entries to set their modification timestamps to a constant too. Is this a bug (because eachFile doesn’t callback on manifest file) or is there some other kind of workaround that I can use?

Use case: the jars are eventually added to a docker image. Because of the timestamp difference in the jar file’s manifest file, the md5 of the file changes and trips up the docker cache.

try using the rootSpec explicitly here:

tasks.withType(Jar) {
    rootSpec.eachFile { FileCopyDetails details ->
        details.getFile().setLastModified(0L);
        def pf = details.getFile();
        while (pf != null && (pf = pf.getParentFile()) != null) {
            pf.setLastModified(0);
        }
    }
}

Thank you, that gives me build/tmp/MANIFEST.MF but unfortunately the resultant entry that gets written to the JAR file still reflects the build time instead of the constant time :frowning:

My current workaround that works (but inefficient):

    jar {
        duplicatesStrategy= DuplicatesStrategy.EXCLUDE
        doLast {
            long ts = 0;
            File newJar = new File(archivePath.parent, 'new-' + archiveName)
            ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(newJar))
            JarFile jf = new JarFile(archivePath)
            jf.entries().each { entry ->
                ZipEntry clone = new ZipEntry(entry)
                clone.time = 0
                def entryIs = jf.getInputStream(entry)
                zos.putNextEntry(clone)
                byte[] buffer = new byte[1024]
                int len = 0
                while((len = entryIs.read(buffer)) != -1) {
                    zos.write(buffer, 0, len)
                }
            }
            zos.finish()
            jf.close()
        }
        doLast {
            new File(archivePath.parent, 'new-' + archiveName).renameTo(new File(archivePath.parent, archiveName))
        }
    }