Add SOURCE_DATE_EPOCH support for reproducible builds

Implement support for the SOURCE_DATE_EPOCH environment variable as
specified by reproducible-builds.org. When set, this variable overrides
the current timestamp in the Release file's Date and Valid-Until fields,
enabling reproducible filesystem publishes.

- Read SOURCE_DATE_EPOCH environment variable in Publish()
- Use the epoch timestamp for both Date and Valid-Until fields
- Gracefully fallback to current time if unset or invalid
- Add comprehensive tests for valid and invalid SOURCE_DATE_EPOCH values
This commit is contained in:
Tim Foerster
2026-02-20 06:01:53 +00:00
parent a65f79eb79
commit 49f342878a
8 changed files with 119 additions and 3 deletions
+10 -3
View File
@@ -9,6 +9,7 @@ import (
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
@@ -1136,8 +1137,14 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
release["Suite"] = p.GetSuite()
release["Codename"] = p.GetCodename()
datetime_format := "Mon, 2 Jan 2006 15:04:05 MST"
date_now := time.Now().UTC()
release["Date"] = date_now.Format(datetime_format)
publishDate := time.Now().UTC()
if epoch := os.Getenv("SOURCE_DATE_EPOCH"); epoch != "" {
if sec, err := strconv.ParseInt(epoch, 10, 64); err == nil {
publishDate = time.Unix(sec, 0).UTC()
}
}
release["Date"] = publishDate.Format(datetime_format)
release["Architectures"] = strings.Join(utils.StrSlicesSubstract(p.Architectures, []string{ArchitectureSource}), " ")
if p.AcquireByHash {
release["Acquire-By-Hash"] = "yes"
@@ -1149,7 +1156,7 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
// is not present or if it is expired."
release["Signed-By"] = p.SignedBy
// Let's use a century as a "forever" value.
release["Valid-Until"] = date_now.AddDate(100, 0, 0).Format(datetime_format)
release["Valid-Until"] = publishDate.AddDate(100, 0, 0).Format(datetime_format)
}
release["Description"] = " Generated by aptly\n"
release["MD5Sum"] = ""