test(util): add end-to-end and dependency tests for SOURCE_DATE_EPOCH

Add TestSaveWithSourceDateEpoch to both v2 and v3 util packages to
verify the full pipeline: parse the epoch, stamp the chart tree, save
to a tar archive, then assert that every tar entry carries exactly the
expected timestamp. This catches any regression where writeToTar might
silently fall back to time.Now().

Also add TestApplySourceDateEpochDependencies to confirm that the
recursive walk correctly stamps sub-chart entries while preserving
non-zero ModTimes on the parent chart.

Signed-off-by: Maxime Grenu <maxime.grenu@gmail.com>
pull/31845/head
Maxime Grenu 1 month ago
parent dad0b59d43
commit f2d339dfa4
No known key found for this signature in database
GPG Key ID: 532A7B7866CFDC51

@ -156,3 +156,96 @@ func TestApplySourceDateEpochZeroNoop(t *testing.T) {
t.Errorf("Chart.ModTime = %v, want zero", c.ModTime)
}
}
func TestApplySourceDateEpochDependencies(t *testing.T) {
epoch := time.Unix(1700000000, 0)
existing := time.Unix(1600000000, 0)
dep := &chart.Chart{
Metadata: &chart.Metadata{
Name: "dep",
Version: "0.1.0",
},
Templates: []*common.File{
{Name: "templates/dep.yaml"},
},
}
c := &chart.Chart{
Metadata: &chart.Metadata{
Name: "parent",
Version: "1.0.0",
},
ModTime: existing,
Templates: []*common.File{
{Name: "templates/main.yaml"},
},
}
c.AddDependency(dep)
ApplySourceDateEpoch(c, epoch)
// Parent chart already had a ModTime, so it should be preserved.
if !c.ModTime.Equal(existing) {
t.Errorf("parent Chart.ModTime = %v, want existing %v", c.ModTime, existing)
}
// Dependency had a zero ModTime, so it should be stamped.
if !dep.ModTime.Equal(epoch) {
t.Errorf("dep Chart.ModTime = %v, want %v", dep.ModTime, epoch)
}
for _, f := range dep.Templates {
if !f.ModTime.Equal(epoch) {
t.Errorf("dep Template %s ModTime = %v, want %v", f.Name, f.ModTime, epoch)
}
}
}
func TestSaveWithSourceDateEpoch(t *testing.T) {
// End-to-end: parse SOURCE_DATE_EPOCH, apply to a chart with zero
// ModTimes, save as a tar archive, and verify every tar entry carries
// exactly the expected timestamp.
const epochStr = "1700000000"
want := time.Unix(1700000000, 0)
t.Setenv("SOURCE_DATE_EPOCH", epochStr)
epoch, err := ParseSourceDateEpoch()
if err != nil {
t.Fatalf("ParseSourceDateEpoch() error: %v", err)
}
c := &chart.Chart{
Metadata: &chart.Metadata{
APIVersion: chart.APIVersionV3,
Name: "epoch-test",
Version: "0.1.0",
},
Values: map[string]any{"key": "value"},
Schema: []byte(`{"title": "Values"}`),
Files: []*common.File{{Name: "README.md", Data: []byte("# test")}},
Templates: []*common.File{{Name: "templates/test.yaml", Data: []byte("apiVersion: v1")}},
}
ApplySourceDateEpoch(c, epoch)
tmp := t.TempDir()
where, err := Save(c, tmp)
if err != nil {
t.Fatalf("Save() error: %v", err)
}
headers, err := retrieveAllHeadersFromTar(where)
if err != nil {
t.Fatalf("failed to read tar: %v", err)
}
if len(headers) == 0 {
t.Fatal("archive contains no entries")
}
for _, h := range headers {
if !h.ModTime.Equal(want) {
t.Errorf("tar entry %q ModTime = %v, want %v", h.Name, h.ModTime, want)
}
}
}

@ -156,3 +156,98 @@ func TestApplySourceDateEpochZeroNoop(t *testing.T) {
t.Errorf("Chart.ModTime = %v, want zero", c.ModTime)
}
}
func TestApplySourceDateEpochDependencies(t *testing.T) {
epoch := time.Unix(1700000000, 0)
existing := time.Unix(1600000000, 0)
dep := &chart.Chart{
Metadata: &chart.Metadata{
APIVersion: chart.APIVersionV2,
Name: "dep",
Version: "0.1.0",
},
Templates: []*common.File{
{Name: "templates/dep.yaml"},
},
}
c := &chart.Chart{
Metadata: &chart.Metadata{
APIVersion: chart.APIVersionV2,
Name: "parent",
Version: "1.0.0",
},
ModTime: existing,
Templates: []*common.File{
{Name: "templates/main.yaml"},
},
}
c.AddDependency(dep)
ApplySourceDateEpoch(c, epoch)
// Parent chart already had a ModTime, so it should be preserved.
if !c.ModTime.Equal(existing) {
t.Errorf("parent Chart.ModTime = %v, want existing %v", c.ModTime, existing)
}
// Dependency had a zero ModTime, so it should be stamped.
if !dep.ModTime.Equal(epoch) {
t.Errorf("dep Chart.ModTime = %v, want %v", dep.ModTime, epoch)
}
for _, f := range dep.Templates {
if !f.ModTime.Equal(epoch) {
t.Errorf("dep Template %s ModTime = %v, want %v", f.Name, f.ModTime, epoch)
}
}
}
func TestSaveWithSourceDateEpoch(t *testing.T) {
// End-to-end: parse SOURCE_DATE_EPOCH, apply to a chart with zero
// ModTimes, save as a tar archive, and verify every tar entry carries
// exactly the expected timestamp.
const epochStr = "1700000000"
want := time.Unix(1700000000, 0)
t.Setenv("SOURCE_DATE_EPOCH", epochStr)
epoch, err := ParseSourceDateEpoch()
if err != nil {
t.Fatalf("ParseSourceDateEpoch() error: %v", err)
}
c := &chart.Chart{
Metadata: &chart.Metadata{
APIVersion: chart.APIVersionV2,
Name: "epoch-test",
Version: "0.1.0",
},
Values: map[string]any{"key": "value"},
Schema: []byte(`{"title": "Values"}`),
Files: []*common.File{{Name: "README.md", Data: []byte("# test")}},
Templates: []*common.File{{Name: "templates/test.yaml", Data: []byte("apiVersion: v1")}},
}
ApplySourceDateEpoch(c, epoch)
tmp := t.TempDir()
where, err := Save(c, tmp)
if err != nil {
t.Fatalf("Save() error: %v", err)
}
headers, err := retrieveAllHeadersFromTar(where)
if err != nil {
t.Fatalf("failed to read tar: %v", err)
}
if len(headers) == 0 {
t.Fatal("archive contains no entries")
}
for _, h := range headers {
if !h.ModTime.Equal(want) {
t.Errorf("tar entry %q ModTime = %v, want %v", h.Name, h.ModTime, want)
}
}
}

Loading…
Cancel
Save