distro: set the repository checksum dynamically
Instead of having a static repository checksum, set it dynamically from the metadata that osbuild-composer last saw. This is implemented in dnf-json, which returns the checksums for each repository on every call. This enables the use of repositories that change over time, such as fedora-updates. Note that the osbuild pipeline will break when such a repository changes. This is intentional: pipelines have to be reproducible.
This commit is contained in:
parent
75218ad2d9
commit
d3a0b788a2
20 changed files with 184 additions and 95 deletions
41
dnf-json
41
dnf-json
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import datetime
|
||||
import dnf
|
||||
import hashlib
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
|
@ -24,7 +25,7 @@ def dnfrepo(desc, parent_conf=None):
|
|||
elif "metalink" in desc:
|
||||
repo.metalink = desc["metalink"]
|
||||
elif "mirrorlist" in desc:
|
||||
repo.metalink = desc["mirrorlist"]
|
||||
repo.mirrorlist = desc["mirrorlist"]
|
||||
else:
|
||||
assert False
|
||||
|
||||
|
|
@ -46,6 +47,30 @@ def exit_with_dnf_error(kind: str, reason: str):
|
|||
sys.exit(DNF_ERROR_EXIT_CODE)
|
||||
|
||||
|
||||
def repo_checksums(base):
|
||||
checksums = {}
|
||||
for repo in base.repos.iter_enabled():
|
||||
# Uses the same algorithm as libdnf to find cache dir:
|
||||
# https://github.com/rpm-software-management/libdnf/blob/master/libdnf/repo/Repo.cpp#L1288
|
||||
if repo.metalink:
|
||||
url = repo.metalink
|
||||
elif repo.mirrorlist:
|
||||
url = repo.mirrorlist
|
||||
elif repo.baseurl:
|
||||
url = repo.baseurl[0]
|
||||
else:
|
||||
assert False
|
||||
|
||||
digest = hashlib.sha256(url.encode()).hexdigest()[:16]
|
||||
|
||||
with open(f"{base.conf.cachedir}/{repo.id}-{digest}/repodata/repomd.xml", "rb") as f:
|
||||
repomd = f.read()
|
||||
|
||||
checksums[repo.id] = "sha256:" + hashlib.sha256(repomd).hexdigest()
|
||||
|
||||
return checksums
|
||||
|
||||
|
||||
call = json.load(sys.stdin)
|
||||
command = call["command"]
|
||||
arguments = call.get("arguments", {})
|
||||
|
|
@ -66,7 +91,10 @@ if command == "dump":
|
|||
"buildtime": timestamp_to_rfc3339(package.buildtime),
|
||||
"license": package.license
|
||||
})
|
||||
json.dump(packages, sys.stdout)
|
||||
json.dump({
|
||||
"checksums": repo_checksums(base),
|
||||
"packages": packages
|
||||
}, sys.stdout)
|
||||
|
||||
elif command == "depsolve":
|
||||
base = create_base(arguments.get("repos", {}))
|
||||
|
|
@ -82,13 +110,16 @@ elif command == "depsolve":
|
|||
except dnf.exceptions.DepsolveError as e:
|
||||
exit_with_dnf_error("DepsolveError", f"There was a problem depsolving {arguments['package-specs']}: {e}")
|
||||
|
||||
packages = []
|
||||
dependencies = []
|
||||
for package in base.transaction.install_set:
|
||||
packages.append({
|
||||
dependencies.append({
|
||||
"name": package.name,
|
||||
"epoch": package.epoch,
|
||||
"version": package.version,
|
||||
"release": package.release,
|
||||
"arch": package.arch
|
||||
})
|
||||
json.dump(packages, sys.stdout)
|
||||
json.dump({
|
||||
"checksums": repo_checksums(base),
|
||||
"dependencies": dependencies
|
||||
}, sys.stdout)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue