Skip to content

Commit 6d79011

Browse files
authored
Build: make zip task output reproducible (darkreader#10188)
- Adjust archive timestamps for user time zone - Explicitly set file permissions in archive contents
1 parent 191b5e4 commit 6d79011

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

tasks/zip.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ const {getDestDir, PLATFORM} = paths;
1111
* @param {object} details
1212
* @returns {Promise<void>}
1313
*/
14-
function archiveFiles({files, dest, cwd, date}) {
14+
function archiveFiles({files, dest, cwd, date, mode}) {
1515
return new Promise((resolve) => {
1616
const archive = new yazl.ZipFile();
17+
// Rproducible builds: sort filenames so files appear in the same order in zip
1718
files.sort();
1819
files.forEach((file) => archive.addFile(
1920
file,
2021
file.startsWith(`${cwd}/`) ? file.substring(cwd.length + 1) : file,
21-
{mtime: date}
22+
{mtime: date, mode}
2223
));
2324
/** @type {any} */
2425
const writeStream = fs.createWriteStream(dest);
@@ -27,15 +28,22 @@ function archiveFiles({files, dest, cwd, date}) {
2728
});
2829
}
2930

30-
async function archiveDirectory({dir, dest, date}) {
31+
async function archiveDirectory({dir, dest, date, mode}) {
3132
const files = await getPaths(`${dir}/**/*.*`);
32-
await archiveFiles({files, dest, cwd: dir, date});
33+
await archiveFiles({files, dest, cwd: dir, date, mode});
3334
}
3435

36+
/**
37+
* Reproducible builds: set file timestamp to last commit timestamp
38+
* Returns the date of the last git commit to be used as archive file timestamp
39+
* @returns {Promise<Date>} JavaScript Date object with date adjusted to counterbalance user's time zone
40+
*/
3541
async function getLastCommitTime() {
42+
// We need to offset the user's time zone since yazl can not represent time zone in produced archive
3643
return new Promise((resolve) =>
37-
exec('git log -1 --format=%ct', (_, stdout) => resolve(new Date(Number(stdout) * 1000)))
38-
);
44+
exec('git log -1 --format=%ct', (_, stdout) => resolve(new Date(
45+
(Number(stdout) + (new Date()).getTimezoneOffset() * 60) * 1000
46+
))));
3947
}
4048

4149
async function zip({platforms, debug}) {
@@ -52,6 +60,9 @@ async function zip({platforms, debug}) {
5260
dir: getDestDir({debug, platform}),
5361
dest: `${releaseDir}/darkreader-${platform}.${format}`,
5462
date,
63+
// Reproducible builds: set permission flags on file like chmod 644 or -rw-r--r--
64+
// This is needed because the built file might have different flags on different systems
65+
mode: 0o644,
5566
}));
5667
}
5768
await Promise.all(promises);

0 commit comments

Comments
 (0)