Skip to content

Commit 6ea16c7

Browse files
authored
Build: Avoid non-deterministic timestamp in published builds
Make QUnit releases deterministic by embedding a known date instead of the "current" date and time. Adopt the standard mechanism for this based on <https://reproducible-builds.org/docs/source-date-epoch/> which involves an environment variable named `SOURCE_DATE_EPOCH` set to a UNIX timestamp. This requires one line of code to then reformat to the ISO date were prefer, but this seems worth it. In an earlier iteration on this patch, I had the Git CLI format it that way from the start, like so: ``` QUNIT_RELEASE_DATE="$(git show -s --format=%cd --date=short HEAD)" //> 2021-01-09 ``` Instead, we use: ``` SOURCE_DATE_EPOCH="$(git log -s --format=%at -1)" //> 1610349865 ``` ... and dist-replace.js reformats it as needed. Also add a badge to the README, inspired by <https://github.com/jvm-repo-rebuild/reproducible-central>, but with improved color contrast, using the same dark blue as for the reproducible-builds.org logo, and the same green as used for other "success" badges (e.g. CI, license check, etc.) Fixes #1538.
1 parent 4a2e830 commit 6ea16c7

File tree

3 files changed

+33
-6
lines changed

3 files changed

+33
-6
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<img src="/docs/img/QUnit-Logo-Large.png" width="250" height="auto">
22

33
[![Build Status](https://travis-ci.com/qunitjs/qunit.svg?branch=master)](https://travis-ci.com/qunitjs/qunit)
4+
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fqunitjs%2Fqunit.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fqunitjs%2Fqunit?ref=badge_shield)
5+
[![Reproducible Builds](https://img.shields.io/badge/Reproducible_Builds-ok-success?labelColor=1e5b96)](https://reproducible-builds.org/)
46
[![Coverage Status](https://coveralls.io/repos/qunitjs/qunit/badge.svg)](https://coveralls.io/github/qunitjs/qunit)
57
[![Chat on Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/qunitjs/qunit?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6-
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fqunitjs%2Fqunit.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fqunitjs%2Fqunit?ref=badge_shield)
78
[![npm](https://img.shields.io/npm/v/qunit.svg?style=flat)](https://www.npmjs.com/package/qunit)
89

910
# [QUnit](https://qunitjs.com) - A JavaScript Unit Testing Framework.

RELEASE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ Prerequisites:
7979
8080
4. Generate the release artifacts:
8181
```
82+
export SOURCE_DATE_EPOCH="$(git log -s --format=%at -1)"
8283
npm run build
8384
```
8485

build/dist-replace.js

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,37 @@
1-
// Used for JS files by rollup.config.js
2-
// Used for CSS files by Gruntfile.js via preprocess()
1+
// Helper used for JS files by rollup.config.js,
2+
// and for CSS files by Gruntfile.js via preprocess()
3+
4+
const distVersion = require( "../package.json" ).version;
5+
6+
let distEpoch;
7+
let distDate;
8+
if ( /pre/.test( distVersion ) ) {
9+
10+
// During development, insert a detailed timestamp.
11+
//
12+
// Format as 0000-00-00T00:00Z
13+
distDate = ( new Date() ).toISOString().replace( /:\d+\.\d+Z$/, "Z" );
14+
} else {
15+
16+
// Release builds should be deterministic and reproducible.
17+
// Use the date of the release prep commit via an environment variable
18+
// See RELEASE.md and <https://reproducible-builds.org/docs/source-date-epoch/>.
19+
//
20+
// Format as 0000-00-00
21+
distEpoch = process.env.SOURCE_DATE_EPOCH;
22+
if ( !/^\d{7,}$/.test( distEpoch ) ) {
23+
throw new Error( "SOURCE_DATE_EPOCH must be set to a UNIX timestamp" );
24+
}
25+
distDate = ( new Date( distEpoch * 1000 ) ).toISOString().replace( /T.+$/, "" );
26+
}
27+
328
const replacements = {
429

530
// Embed version
6-
"@VERSION": require( "../package.json" ).version,
31+
"@VERSION": distVersion,
732

8-
// Embed date (yyyy-mm-ddThh:mmZ)
9-
"@DATE": ( new Date() ).toISOString().replace( /:\d+\.\d+Z$/, "Z" )
33+
// Embed date
34+
"@DATE": distDate
1035
};
1136

1237
function preprocess( code ) {

0 commit comments

Comments
 (0)