Skip to content

Commit

Permalink
Allow overriding image creation time
Browse files Browse the repository at this point in the history
If the SOURCE_DATE_EPOCH env var is set (to a number of seconds since
the Unix epoch), its value will be used as the creation time of the
image produced, and of config history values for each layer.

This matches the behavior of tools like ko[0] and is the recommendation
of https://reproducible-builds.org/

0: https://github.com/google/ko#why-are-my-images-all-created-in-1970
  • Loading branch information
imjasonh committed Feb 3, 2022
1 parent 14fe798 commit 58865dd
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
20 changes: 18 additions & 2 deletions remote/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"io"
"net/http"
"os"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -629,12 +631,26 @@ func findLayerWithSha(layers []v1.Layer, diffID string) (v1.Layer, error) {
return nil, fmt.Errorf("previous image did not have layer with diff id %q", diffID)
}

func getCreationTimeFromEnv() v1.Time {
epoch := os.Getenv("SOURCE_DATE_EPOCH")
if epoch == "" {
return v1.Time{Time: imgutil.NormalizedDateTime}
}

seconds, err := strconv.ParseInt(epoch, 10, 64)
if err != nil {
return v1.Time{Time: imgutil.NormalizedDateTime}
}
return v1.Time{Time: time.Unix(seconds, 0)}
}

func (i *Image) Save(additionalNames ...string) error {
var err error

allNames := append([]string{i.repoName}, additionalNames...)

i.image, err = mutate.CreatedAt(i.image, v1.Time{Time: imgutil.NormalizedDateTime})
creationTime := getCreationTimeFromEnv()
i.image, err = mutate.CreatedAt(i.image, creationTime)
if err != nil {
return errors.Wrap(err, "set creation time")
}
Expand All @@ -652,7 +668,7 @@ func (i *Image) Save(additionalNames ...string) error {
cfg.History = make([]v1.History, len(layers))
for i := range cfg.History {
cfg.History[i] = v1.History{
Created: v1.Time{Time: imgutil.NormalizedDateTime},
Created: creationTime,
}
}

Expand Down
24 changes: 24 additions & 0 deletions remote/remote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,30 @@ func testImage(t *testing.T, when spec.G, it spec.S) {
h.AssertEq(t, item.Created.Unix(), imgutil.NormalizedDateTime.Unix())
}
})

it("can override creation time", func() {
img, err := remote.NewImage(repoName, authn.DefaultKeychain)
h.AssertNil(t, err)

tarPath, err := h.CreateSingleFileLayerTar("/new-layer.txt", "new-layer", "linux")
h.AssertNil(t, err)
defer os.Remove(tarPath)

h.AssertNil(t, img.AddLayer(tarPath))

epoch := time.Now().Unix()
os.Setenv("SOURCE_DATE_EPOCH", fmt.Sprintf("%d", epoch))
h.AssertNil(t, img.Save())

configFile := h.FetchManifestImageConfigFile(t, repoName)

h.AssertEq(t, configFile.Created.Time.Unix(), epoch)

h.AssertEq(t, len(configFile.History), len(configFile.RootFS.DiffIDs))
for _, item := range configFile.History {
h.AssertEq(t, item.Created.Unix(), epoch)
}
})
})

when("additional names are provided", func() {
Expand Down

0 comments on commit 58865dd

Please sign in to comment.