stages/dnf4.versionlock: respect SOURCE_DATE_EPOCH

Respect the SOURCE_DATE_EPOCH environment variable for reproducible
builds.

https://reproducible-builds.org/docs/source-date-epoch/
This commit is contained in:
Achilleas Koutsou 2025-07-02 15:17:57 +02:00 committed by Tomáš Hozza
parent ece618d0d0
commit a4061f831e
3 changed files with 14 additions and 7 deletions

11
stages/org.osbuild.dnf4.versionlock Normal file → Executable file
View file

@ -1,7 +1,8 @@
#!/usr/bin/python3
import os
import pathlib
import sys
import time
from datetime import datetime, timezone
import osbuild.api
@ -11,7 +12,13 @@ def main(tree, options):
tree = pathlib.Path(tree)
locklist = tree / "etc/dnf/plugins/versionlock.list"
nowstr = time.ctime()
# respect SOURCE_DATE_EPOCH for the timestamp in the comment for reproducible builds
source_date_epoch = os.environ.get("SOURCE_DATE_EPOCH")
nowstr = datetime.now().ctime()
if source_date_epoch:
nowstr = datetime.fromtimestamp(int(source_date_epoch), tz=timezone.utc).ctime()
with locklist.open(mode="a", encoding="utf-8") as locklist_fp:
for item in add:
# the plugin adds an empty line followed by a comment with a timestamp above each item, let's replicate the

View file

@ -8,7 +8,9 @@
"Notes:",
" - This stage is only valid for dnf4 and will have no effect on distributions that use dnf5.",
" - Items are written as is. This is unlike adding items by calling 'dnf versionlock add',",
" which uses the dnf cache to retrieve version information for the listed packages."
" which uses the dnf cache to retrieve version information for the listed packages.",
" - The stage respects SOURCE_DATE_EPOCH for reproducible builds, which affects the timestamps",
" that are included as comments in the file."
],
"schema": {
"additionalProperties": false,

View file

@ -34,6 +34,7 @@ def test_schema_validation_dnf4_versionlock(stage_schema, test_data, expected_er
({"add": ["proto-1:1.1", "deftero-0:2.2", "trito-3:3.3-3.fc33"]}),
])
def test_locklist_dnf4_versionlock(tmp_path, stage_module, test_data):
os.environ["SOURCE_DATE_EPOCH"] = "1554721380"
plugins_dir = os.path.join(tmp_path, "etc/dnf/plugins/")
locklist_path = os.path.join(plugins_dir, "versionlock.list")
os.makedirs(plugins_dir)
@ -44,8 +45,5 @@ def test_locklist_dnf4_versionlock(tmp_path, stage_module, test_data):
for idx, package in enumerate(test_data["add"]):
assert locklist_data[idx * 3] == "\n"
# let's ignore the timestamp, just check that the comment was written
assert locklist_data[idx * 3 + 1].startswith("# Added lock on")
assert locklist_data[idx * 3 + 1] == "# Added lock on Mon Apr 8 11:03:00 2019\n"
assert locklist_data[idx * 3 + 2] == package + "\n"