Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reset timestamps to 1970-01-01 during packaging for repeatable builds #5344

Merged
merged 6 commits into from
Dec 29, 2019

Conversation

eed3si9n
Copy link
Member

@eed3si9n eed3si9n commented Dec 29, 2019

Ref sbt/io#279
This is a resend of #5233

original description

This is a continuation of the work in sbt/io#58 , which I decided to get back into partly because Maven has been adding features to the core plugins, and it would be good to be on par :).

As discussed in sbt/io#58, we should be careful about the risk of breaking incremental builds - I haven't found any such issues yet though. Note that this PR only affects the timestamps of entries in jars: timestamps of classes on the filesystem and the filesystem timestamp of the jar itself are not affected.

Discussing this with @eed3si9n, there could be special-purposes build configurations that (for example in order to avoid deleting/creating many files) compile classes directly into a jar rather than first to individual files. I haven't seen this configuration yet, but I suspect it wouldn't use Defaults.packageTask, but a custom Package/IO invocation. Any custom build configuration that requires non-static timestamps can pass None as the time parameter to keep the original behavior.

This PR requires sbt/io#279

@eed3si9n eed3si9n merged commit bf9225b into sbt:develop Dec 29, 2019
@eed3si9n eed3si9n deleted the wip/repeatable branch December 29, 2019 07:58
bjaglin pushed a commit to bjaglin/sbt-memoize that referenced this pull request May 26, 2020
We need a nightly containing sbt/sbt#5344
if we want children projects to be insensitive to repackaging.
@eed3si9n eed3si9n added this to the 1.4.0 milestone Jun 10, 2020
Copy link

@bollinger bollinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the orElse(Some(0L) is incorrect, causing files in the output jar to have a timestamp of 0.
Shouldn't None should be used when there is no SOURCE_DATE_EPOCH to get the pre 1.4.0 behaviour?
Peter.

@eed3si9n
Copy link
Member Author

I think the orElse(Some(0L) is incorrect, causing files in the output jar to have a timestamp of 0.

Timestamp 0 is the intended behavior of sbt 1.4.0 to make the build more repeatable.

@SethTisue
Copy link
Member

SethTisue commented Nov 30, 2020

commenting and saying "1970" so it comes up in search results :)

(since 1970 is the date all the files get)

1970 1970 1970 1970 !!!

@eed3si9n eed3si9n changed the title Don't emit timestamps when packaging to jar, take 2 Reset timestamps to 1970-01-01 during packaging for repeatable builds Nov 30, 2020
@dontgitit
Copy link

+1 to the previous comments and the linked play issue playframework/playframework#10572, this change breaks etag computation in play. while the suggested fix in that thread (of setting an environment variable) does work, it's frustrating that there's no way to do it directly from sbt. it might be nicer if there was an sbt setting for this, useEpochTimestamp in packageBin or something of the sort?

also, since the new code always provides Some(0) as a backup, it seems there's no way to go back to the old behavior of preserving asset timestamps; you must either choose a static date for all of them, or you get the epoch by default. this seems suboptimal - it would be ideal to preserve asset timestamps since they rarely change.

@eed3si9n
Copy link
Member Author

eed3si9n commented Jan 1, 2021

@dontgitit I've created a new issue for this - #6235

eed3si9n added a commit to eed3si9n/sbt that referenced this pull request Jan 3, 2021
Fixes sbt#6235

In sbt 1.4.0 (sbt#5344) we started wiping out the timestamps in JAR to make the builds more repeatable. This had an unintended consequence of breaking Play's last-modified response header (playframework/playframework#10572).

This adds an opt-out from the default:

```scala
Compile / packageBin / packageOptions += Package.keepTimestamps
```

### before

```
$ ll example
total 32
-rw-r--r--  1 eed3si9n  wheel   901 Jan  1  1970 Greeting.class
-rw-r--r--  1 eed3si9n  wheel  3079 Jan  1  1970 Hello$.class
-rw-r--r--  1 eed3si9n  wheel   738 Jan  1  1970 Hello$delayedInit$body.class
-rw-r--r--  1 eed3si9n  wheel   875 Jan  1  1970 Hello.class
```

### after

```
$ ll target/scala-2.13/hello_2.13-0.1.0-SNAPSHOT/example
total 32
-rwxr-xr-x  1 eed3si9n  wheel   901 Jan  3 12:20 Greeting.class*
-rwxr-xr-x  1 eed3si9n  wheel  3079 Jan  3 12:20 Hello$.class*
-rwxr-xr-x  1 eed3si9n  wheel   738 Jan  3 12:20 Hello$delayedInit$body.class*
-rwxr-xr-x  1 eed3si9n  wheel   875 Jan  3 12:20 Hello.class*
```
eed3si9n added a commit to eed3si9n/sbt that referenced this pull request Jan 25, 2021
…mmitDate

Fixes sbt#6235

In sbt 1.4.0 (sbt#5344) we started wiping out the timestamps in JAR to make the builds more repeatable. This had an unintended consequence of breaking Play's last-modified response header (playframework/playframework#10572).

This adds an opt-out from the default:

```scala
ThisBuild / packageOptions += Package.keepTimestamps
```

Before
------

```
$ ll example
total 32
-rw-r--r--  1 eed3si9n  wheel   901 Jan  1  1970 Greeting.class
-rw-r--r--  1 eed3si9n  wheel  3079 Jan  1  1970 Hello$.class
-rw-r--r--  1 eed3si9n  wheel   738 Jan  1  1970 Hello$delayedInit$body.class
-rw-r--r--  1 eed3si9n  wheel   875 Jan  1  1970 Hello.class
```

After
-----

```
$ ll target/scala-2.13/hello_2.13-0.1.0-SNAPSHOT/example
total 32
-rwxr-xr-x  1 eed3si9n  wheel   901 Jan  3 12:20 Greeting.class*
-rwxr-xr-x  1 eed3si9n  wheel  3079 Jan  3 12:20 Hello$.class*
-rwxr-xr-x  1 eed3si9n  wheel   738 Jan  3 12:20 Hello$delayedInit$body.class*
-rwxr-xr-x  1 eed3si9n  wheel   875 Jan  3 12:20 Hello.class*
```
eed3si9n added a commit to eed3si9n/sbt that referenced this pull request Jan 25, 2021
Fixes sbt#6235

In sbt 1.4.0 (sbt#5344) we started wiping out the timestamps in JAR
to make the builds more repeatable.
This had an unintended consequence of breaking Play's last-modified response header (playframework/playframework#10572).

This adds a global setting called `packageTimestamp`, which is
initialized as follows:

```scala
packageTimestamp :== Package.defaultTimestamp,
```

Here the `Package.defaultTimestamp` would pick either the value from the
`SOURCE_DATE_EPOCH` environment variable or 2010-01-01.

To opt out of this default, the user can use:

```scala
ThisBuild / packageTimestamp := Package.keepTimestamps

// or

ThisBuild / packageTimestamp := Package.gitCommitDateTimestamp
```

Before (sbt 1.4.6)
------------------

```
$ ll example
total 32
-rw-r--r--  1 eed3si9n  wheel   901 Jan  1  1970 Greeting.class
-rw-r--r--  1 eed3si9n  wheel  3079 Jan  1  1970 Hello$.class
-rw-r--r--  1 eed3si9n  wheel   738 Jan  1  1970 Hello$delayedInit$body.class
-rw-r--r--  1 eed3si9n  wheel   875 Jan  1  1970 Hello.class
```

After (using Package.gitCommitDateTimestamp)
--------------------------------------------

```
$ unzip -v target/scala-2.13/root_2.13-0.1.0-SNAPSHOT.jar
Archive:  target/scala-2.13/root_2.13-0.1.0-SNAPSHOT.jar
 Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
--------  ------  ------- ---- ---------- ----- --------  ----
     288  Defl:N      136  53% 01-25-2021 03:09 888682a9  META-INF/MANIFEST.MF
       0  Stored        0   0% 01-25-2021 03:09 00000000  example/
     901  Defl:N      601  33% 01-25-2021 03:09 3543f377  example/Greeting.class
    3079  Defl:N     1279  59% 01-25-2021 03:09 848b4386  example/Hello$.class
     738  Defl:N      464  37% 01-25-2021 03:09 571f4288  example/Hello$delayedInit$body.class
     875  Defl:N      594  32% 01-25-2021 03:09 ad295259  example/Hello.class
--------          -------  ---                            -------
    5881             3074  48%                            6 files
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants