1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-19 14:48:08 +02:00

Implement reproducibility for the release builds

The release builds are currently not reproducible because ZIP files
record the modification date of files generated during the build
process, meaning that two builds from identical source code, made
at different times, result in different output.

This is undesirable because it makes detecting differences in the output
harder, for instance recently during the Gulp 5 efforts, because the
modification date differences are irrelevant and could obscure actually
important differences in the output during e.g. code changes. Moreover,
reprodicibility of build artifacts has become increasingly important;
please refer to the Reproducible Builds initiative at
https://reproducible-builds.org (note the "Why does it matter?" section
specifically) and https://reproducible-builds.org/docs/timestamps which
further explains the problem of timestamps in build artifacts.

This commit fixes the issue by configuring the ZIP file creation to use
the (fixed) date of the last Git commit for which the release is being
made. With this the build is fully reproducible so that identical source
code builds result in bit-by-bit identical output artifacts.

To improve readability we convert the compression method to take a
parameter object and use template strings where useful.
This commit is contained in:
Tim van der Meij 2024-06-16 16:51:56 +02:00
parent ee94391794
commit 44e0fae9d1
No known key found for this signature in database
GPG key ID: 8C3FD2925A5F2762

View file

@ -18,7 +18,7 @@ import {
babelPluginPDFJSPreprocessor,
preprocessPDFJSCode,
} from "./external/builder/babel-plugin-pdfjs-preprocessor.mjs";
import { exec, spawn, spawnSync } from "child_process";
import { exec, execSync, spawn, spawnSync } from "child_process";
import autoprefixer from "autoprefixer";
import babel from "@babel/core";
import crypto from "crypto";
@ -1682,13 +1682,13 @@ gulp.task(
)
);
function compressPublish(targetName, dir) {
function compressPublish({ sourceDirectory, targetFile, modifiedTime }) {
return gulp
.src(dir + "**", { encoding: false })
.pipe(zip(targetName))
.src(`${sourceDirectory}**`, { encoding: false })
.pipe(zip(targetFile, { modifiedTime }))
.pipe(gulp.dest(BUILD_DIR))
.on("end", function () {
console.log("Built distribution file: " + targetName);
console.log(`Built distribution file: ${targetFile}`);
});
}
@ -1701,15 +1701,34 @@ gulp.task(
config.stableVersion = version;
// ZIP files record the modification date of the source files, so if files
// are generated during the build process the output is not reproducible.
// To avoid this, the modification dates should be replaced with a fixed
// date, in our case the last Git commit date, so that builds from identical
// source code result in bit-by-bit identical output. The `gulp-zip` library
// supports providing a different modification date to enable reproducible
// builds. Note that the Git command below outputs the last Git commit date
// as a Unix timestamp (in seconds since epoch), but the `Date` constructor
// in JavaScript requires millisecond input, so we have to multiply by 1000.
const lastCommitTimestamp = execSync('git log --format="%at" -n 1')
.toString()
.replace("\n", "");
const lastCommitDate = new Date(parseInt(lastCommitTimestamp, 10) * 1000);
return ordered([
createStringSource(CONFIG_FILE, JSON.stringify(config, null, 2)).pipe(
gulp.dest(".")
),
compressPublish("pdfjs-" + version + "-dist.zip", GENERIC_DIR),
compressPublish(
"pdfjs-" + version + "-legacy-dist.zip",
GENERIC_LEGACY_DIR
),
compressPublish({
sourceDirectory: GENERIC_DIR,
targetFile: `pdfjs-${version}-dist.zip`,
modifiedTime: lastCommitDate,
}),
compressPublish({
sourceDirectory: GENERIC_LEGACY_DIR,
targetFile: `pdfjs-${version}-legacy-dist.zip`,
modifiedTime: lastCommitDate,
}),
]);
})
);