From 8596f1a001766e437b6fc25af80e093b2f7193fc Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Fri, 27 Sep 2024 14:05:15 +0100 Subject: [PATCH 1/2] build: valid SOURCE_DATE_EPOCH Set the floor of SOURCE_DATE_EPOCH to 1980, as ZIP file format does not support timestamps prior to 1980, meaning zip, jar, egg, wheel all fail to be created or used. Without this fix, if one removes the hand override of SOURCE_DATE_EPOCH from py3-userpath, the build fails: ```console melange build py3-userpath.yaml --arch x86_64 --pipeline-dir ./pipelines/ -k https://packages.wolfi.dev/os/wolfi-signing.rsa.pub -r https://packages.wolfi.dev/os --source-dir ./py3-userpath/ ... 2024/09/27 14:55:33 INFO * Building wheel... name="Python Build" 2024/09/27 14:55:33 WARN Traceback (most recent call last): name="Python Build" 2024/09/27 14:55:33 WARN File "/usr/lib/python3.12/site-packages/pyproject_hooks/_in_process/_in_process.py", line 373, in name="Python Build" 2024/09/27 14:55:33 WARN main() name="Python Build" 2024/09/27 14:55:33 WARN File "/usr/lib/python3.12/site-packages/pyproject_hooks/_in_process/_in_process.py", line 357, in main name="Python Build" 2024/09/27 14:55:33 WARN json_out["return_val"] = hook(**hook_input["kwargs"]) name="Python Build" 2024/09/27 14:55:33 WARN ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ name="Python Build" 2024/09/27 14:55:33 WARN File "/usr/lib/python3.12/site-packages/pyproject_hooks/_in_process/_in_process.py", line 271, in build_wheel name="Python Build" 2024/09/27 14:55:33 WARN return _build_backend().build_wheel( name="Python Build" 2024/09/27 14:55:33 WARN ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ name="Python Build" 2024/09/27 14:55:33 WARN File "/tmp/build-env-u9wepgmk/lib/python3.12/site-packages/hatchling/build.py", line 58, in build_wheel name="Python Build" 2024/09/27 14:55:33 WARN return os.path.basename(next(builder.build(directory=wheel_directory, versions=['standard']))) name="Python Build" 2024/09/27 14:55:33 WARN ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ name="Python Build" 2024/09/27 14:55:33 WARN File "/tmp/build-env-u9wepgmk/lib/python3.12/site-packages/hatchling/builders/plugin/interface.py", line 155, in build name="Python Build" 2024/09/27 14:55:33 WARN artifact = version_api[version](directory, **build_data) name="Python Build" 2024/09/27 14:55:33 WARN ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ name="Python Build" 2024/09/27 14:55:33 WARN File "/tmp/build-env-u9wepgmk/lib/python3.12/site-packages/hatchling/builders/wheel.py", line 476, in build_standard name="Python Build" 2024/09/27 14:55:33 WARN record = archive.add_file(included_file) name="Python Build" 2024/09/27 14:55:33 WARN ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ name="Python Build" 2024/09/27 14:55:33 WARN File "/tmp/build-env-u9wepgmk/lib/python3.12/site-packages/hatchling/builders/wheel.py", line 98, in add_file name="Python Build" 2024/09/27 14:55:33 WARN zip_info = zipfile.ZipInfo(relative_path, cast(TIME_TUPLE, self.time_tuple)) name="Python Build" 2024/09/27 14:55:33 WARN ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ name="Python Build" 2024/09/27 14:55:33 WARN File "/usr/lib/python3.12/zipfile/__init__.py", line 398, in __init__ name="Python Build" 2024/09/27 14:55:33 WARN raise ValueError('ZIP does not support timestamps before 1980') name="Python Build" 2024/09/27 14:55:33 WARN ValueError: ZIP does not support timestamps before 1980 name="Python Build" 2024/09/27 14:55:33 INFO name="Python Build" 2024/09/27 14:55:33 INFO ERROR Backend subprocess exited when trying to invoke build_wheel name="Python Build" 2024/09/27 14:55:33 ERRO ERROR: failed to build package. the build environment has been preserved: 2024/09/27 14:55:33 INFO workspace dir: /tmp/melange-workspace-1020228742 2024/09/27 14:55:33 INFO guest dir: /tmp/melange-guest-609671933 2024/09/27 14:55:33 ERRO failed to build package: unable to run package py3-userpath pipeline: unable to run pipeline: exit status 1 ``` With this fix inplace it just builds correctly. This will remove many custom overrides of SOURCE_DATE_EPOCH in wolfi-dev/os, and prevent any developer hitting such pitfall. This is similar to what was done in NixOS, Debian, Python and probably other projects. In Wolfi this will fix building brand new packages, and building things directly with melange/wolfictl outside of pipelines and makefiles. See for example https://github.com/NixOS/nixpkgs/pull/89794 --- pkg/build/build.go | 3 +++ pkg/build/build_test.go | 10 +++++----- pkg/build/options.go | 2 +- pkg/build/pipelines/git-checkout.yaml | 2 +- pkg/build/sign_test.go | 2 +- pkg/cli/scan.go | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/pkg/build/build.go b/pkg/build/build.go index e6a38cbaa..c26cf6472 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -1196,6 +1196,9 @@ func sourceDateEpoch(defaultTime time.Time) (time.Time, error) { // SHOULD exit with a non-zero error code. return defaultTime, fmt.Errorf("failed to parse SOURCE_DATE_EPOCH: %w", err) } + if sec < 315532800 { + return defaultTime, fmt.Errorf("SOURCE_DATE_EPOCH prior to 1980-01-01 12:00:00 not supported: %v", sec) + } return time.Unix(sec, 0).UTC(), nil } diff --git a/pkg/build/build_test.go b/pkg/build/build_test.go index f1ab61be4..e52ae8c79 100644 --- a/pkg/build/build_test.go +++ b/pkg/build/build_test.go @@ -343,10 +343,10 @@ func TestSourceDateEpoch(t *testing.T) { want: time.Unix(1234567890, 0), }, { - name: "0", - sourceDateEpoch: "0", + name: "Min time", + sourceDateEpoch: "315532800", defaultTime: time.Unix(1234567890, 0), - want: time.Unix(0, 0), + want: time.Unix(315532800, 0), }, { name: "1234567890", @@ -369,12 +369,12 @@ func TestSourceDateEpoch(t *testing.T) { got, err := sourceDateEpoch(tt.defaultTime) if err != nil { if !tt.wantErr { - t.Fatalf("SourceDateEpoch() error = %v, wantErr %v", err, tt.wantErr) + t.Fatalf("%s: SourceDateEpoch() error = %v, wantErr %v", tt.name, err, tt.wantErr) } return } if !got.Equal(tt.want) { - t.Errorf("SourceDateEpoch() = %v, want %v", got, tt.want) + t.Errorf("%s: SourceDateEpoch() = %v, want %v", tt.name, got, tt.want) } }) } diff --git a/pkg/build/options.go b/pkg/build/options.go index df1f929ed..feb3ae598 100644 --- a/pkg/build/options.go +++ b/pkg/build/options.go @@ -58,7 +58,7 @@ func WithBuildDate(s string) Option { return func(bc *Build) error { // default to 0 for reproducibility if s == "" { - bc.SourceDateEpoch = time.Unix(0, 0) + bc.SourceDateEpoch = time.Unix(315532800, 0) return nil } diff --git a/pkg/build/pipelines/git-checkout.yaml b/pkg/build/pipelines/git-checkout.yaml index ee425009c..c8ca967a1 100644 --- a/pkg/build/pipelines/git-checkout.yaml +++ b/pkg/build/pipelines/git-checkout.yaml @@ -62,7 +62,7 @@ pipeline: process_cherry_picks() { local cpicksf="$1" oifs="$IFS" count=0 local fetched_branches="" - local sdate=${SOURCE_DATE_EPOCH:-0} + local sdate=${SOURCE_DATE_EPOCH:-315532800} if [ "$sdate" -lt 315532800 ]; then msg "Setting commit date to Jan 1, 1980 (SOURCE_DATE_EPOCH found ${SOURCE_DATE_EPOCH})" sdate=315532800 diff --git a/pkg/build/sign_test.go b/pkg/build/sign_test.go index 4a5291f94..d91a63e9b 100644 --- a/pkg/build/sign_test.go +++ b/pkg/build/sign_test.go @@ -19,7 +19,7 @@ const MockName = "mockiavelli" func TestEmitSignature(t *testing.T) { ctx := slogtest.Context(t) - sde := time.Unix(12345678, 0) + sde := time.Unix(1234567890, 0) controlData := []byte("donkey") diff --git a/pkg/cli/scan.go b/pkg/cli/scan.go index eb6be59c4..a599a67d2 100644 --- a/pkg/cli/scan.go +++ b/pkg/cli/scan.go @@ -148,7 +148,7 @@ func scanCmd(ctx context.Context, file string, sc *scanConfig) error { bb := &build.Build{ WorkspaceDir: dir, - SourceDateEpoch: time.Unix(0, 0), + SourceDateEpoch: time.Unix(315532800, 0), Configuration: *cfg, } From bc8641153835222f61ca23bcd87fd221df37bf05 Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Sun, 29 Sep 2024 22:22:33 +0100 Subject: [PATCH 2/2] Add below min test --- pkg/build/build_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/build/build_test.go b/pkg/build/build_test.go index e52ae8c79..a2a0e0898 100644 --- a/pkg/build/build_test.go +++ b/pkg/build/build_test.go @@ -348,6 +348,12 @@ func TestSourceDateEpoch(t *testing.T) { defaultTime: time.Unix(1234567890, 0), want: time.Unix(315532800, 0), }, + { + name: "Below min time", + sourceDateEpoch: "0", + defaultTime: time.Unix(1234567890, 0), + wantErr: true, + }, { name: "1234567890", sourceDateEpoch: "1234567890",