Skip to content

Commit 2dcbdaa

Browse files
authored
Merge pull request #14 from victormlg/add_generate_release_info
ENT-13632: Added generate release information
2 parents 70307e2 + ec67267 commit 2dcbdaa

File tree

8 files changed

+594
-1
lines changed

8 files changed

+594
-1
lines changed

src/cfengine_cli/dev.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import os
2-
from cfbs.commands import generate_release_information_command
2+
from cfengine_cli.masterfiles.generate_release_information import (
3+
generate_release_information_impl,
4+
)
35
from cfengine_cli.utils import UserError
46
from cfengine_cli.deptool import (
57
update_dependency_tables as _update_dependency_tables,
@@ -8,6 +10,13 @@
810
from cfengine_cli.docs import update_docs, check_docs
911

1012

13+
def generate_release_information_command(
14+
omit_download=False, check=False, min_version=None
15+
):
16+
generate_release_information_impl(omit_download, check, min_version)
17+
return 0
18+
19+
1120
def _continue_prompt() -> bool:
1221
answer = None
1322
while answer not in ("y", "n", "yes", "no"):

src/cfengine_cli/masterfiles/__init__.py

Whitespace-only changes.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
from collections import OrderedDict
2+
import os
3+
4+
from cfbs.utils import dict_sorted_by_key, file_sha256, version_as_comparable_list
5+
6+
Version = str
7+
8+
9+
def initialize_vcf():
10+
versions_dict = {"versions": {}}
11+
checksums_dict = {"checksums": {}}
12+
files_dict = {"files": {}}
13+
14+
return versions_dict, checksums_dict, files_dict
15+
16+
17+
def versions_checksums_files(
18+
files_dir_path, version, versions_dict, checksums_dict, files_dict
19+
):
20+
for root, _, files in os.walk(files_dir_path):
21+
for name in files:
22+
full_relpath = os.path.join(root, name)
23+
tarball_relpath = os.path.relpath(full_relpath, files_dir_path)
24+
file_checksum = file_sha256(full_relpath)
25+
26+
if version not in versions_dict["versions"]:
27+
versions_dict["versions"][version] = {}
28+
versions_dict["versions"][version][tarball_relpath] = file_checksum
29+
30+
if file_checksum not in checksums_dict["checksums"]:
31+
checksums_dict["checksums"][file_checksum] = {}
32+
if tarball_relpath not in checksums_dict["checksums"][file_checksum]:
33+
checksums_dict["checksums"][file_checksum][tarball_relpath] = []
34+
checksums_dict["checksums"][file_checksum][tarball_relpath].append(version)
35+
36+
if tarball_relpath not in files_dict["files"]:
37+
files_dict["files"][tarball_relpath] = {}
38+
if file_checksum not in files_dict["files"][tarball_relpath]:
39+
files_dict["files"][tarball_relpath][file_checksum] = []
40+
files_dict["files"][tarball_relpath][file_checksum].append(version)
41+
42+
return versions_dict, checksums_dict, files_dict
43+
44+
45+
def finalize_vcf(versions_dict, checksums_dict, files_dict):
46+
# explicitly sort VCF data to ensure determinism
47+
48+
# checksums.json:
49+
working_dict = checksums_dict["checksums"]
50+
for c in working_dict.keys():
51+
for f in working_dict[c].keys():
52+
# sort each version list, descending
53+
working_dict[c][f] = sorted(
54+
working_dict[c][f],
55+
key=lambda v: version_as_comparable_list(v),
56+
reverse=True,
57+
)
58+
# sort filepaths, alphabetically
59+
working_dict[c] = dict_sorted_by_key(working_dict[c])
60+
# sort checksums
61+
checksums_dict["checksums"] = dict_sorted_by_key(working_dict)
62+
63+
# files.json:
64+
working_dict = files_dict["files"]
65+
# sort each list, first by version descending, then by checksum
66+
for f in working_dict.keys():
67+
for c in working_dict[f].keys():
68+
# sort each version list, descending
69+
working_dict[f][c] = sorted(
70+
working_dict[f][c],
71+
key=lambda v: version_as_comparable_list(v),
72+
reverse=True,
73+
)
74+
# sort checksums
75+
working_dict[f] = dict_sorted_by_key(working_dict[f])
76+
# sort files, alphabetically
77+
files_dict["files"] = dict_sorted_by_key(working_dict)
78+
79+
# versions.json:
80+
working_dict = versions_dict["versions"]
81+
# sort files of each version
82+
for v in working_dict.keys():
83+
working_dict[v] = dict_sorted_by_key(working_dict[v])
84+
# sort version numbers, in decreasing order
85+
versions_dict["versions"] = OrderedDict(
86+
sorted(
87+
working_dict.items(),
88+
key=lambda p: version_as_comparable_list(p[0]),
89+
reverse=True,
90+
)
91+
)
92+
93+
return versions_dict, checksums_dict, files_dict
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import os
2+
from collections import OrderedDict
3+
4+
from cfbs.utils import (
5+
dict_diff,
6+
read_json,
7+
CFBSExitError,
8+
write_json,
9+
version_as_comparable_list,
10+
)
11+
12+
13+
def check_download_matches_git(versions):
14+
"""Check that the downloadable files match the git files.
15+
16+
This can be used to monitor / detect if something has been changed, accidentally or maliciously.
17+
18+
Generates a `differences-*.txt` file for each version.
19+
"""
20+
assert os.path.isfile("versions.json")
21+
assert os.path.isfile("versions-git.json")
22+
23+
download_versions_dict = read_json("versions.json")
24+
git_versions_dict = read_json("versions-git.json")
25+
26+
assert download_versions_dict is not None
27+
assert git_versions_dict is not None
28+
29+
diffs_dict = {"differences": {}}
30+
31+
nonmatching_versions = []
32+
extraneous_count = 0
33+
differing_count = 0
34+
35+
for version in versions:
36+
dl_version_files_dict = download_versions_dict["versions"][version]
37+
git_version_files_dict = git_versions_dict["versions"][version]
38+
39+
# normalize downloaded version dictionary filepaths
40+
# necessary because the downloaded version and git version dictionaries have filepaths of different forms
41+
new_download_dict = {}
42+
for key, value in dl_version_files_dict.items():
43+
if key.startswith("masterfiles/"):
44+
key = key[12:]
45+
new_download_dict[key] = value
46+
dl_version_files_dict = new_download_dict
47+
48+
version_diffs_dict = {}
49+
version_diffs_dict["files_only_in_downloads"] = []
50+
version_diffs_dict["files_only_in_git"] = []
51+
version_diffs_dict["files_with_different_content"] = []
52+
53+
only_dl, only_git, value_diff = dict_diff(
54+
dl_version_files_dict, git_version_files_dict
55+
)
56+
57+
for filepath in only_dl:
58+
version_diffs_dict["files_only_in_downloads"].append(filepath)
59+
for filepath in only_git:
60+
version_diffs_dict["files_only_in_git"].append(filepath)
61+
for filepath, _, _ in value_diff:
62+
version_diffs_dict["files_with_different_content"].append(filepath)
63+
64+
diffs_dict["differences"][version] = version_diffs_dict
65+
66+
if len(only_dl) > 0 or len(value_diff) > 0:
67+
nonmatching_versions.append(version)
68+
extraneous_count += len(only_dl)
69+
differing_count += len(value_diff)
70+
71+
nonmatching_versions.sort(key=lambda v: version_as_comparable_list(v), reverse=True)
72+
73+
# fully sort differences.json:
74+
working_dict = diffs_dict["differences"]
75+
# sort filepaths of each version, alphabetically
76+
for k in working_dict.keys():
77+
working_dict[k]["files_only_in_downloads"].sort()
78+
working_dict[k]["files_only_in_git"].sort()
79+
working_dict[k]["files_with_different_content"].sort()
80+
# sort version numbers, in decreasing order
81+
diffs_dict["differences"] = OrderedDict(
82+
sorted(
83+
working_dict.items(),
84+
key=lambda p: version_as_comparable_list(p[0]),
85+
reverse=True,
86+
)
87+
)
88+
89+
write_json("differences.json", diffs_dict)
90+
91+
if len(nonmatching_versions) > 0:
92+
raise CFBSExitError(
93+
"The masterfiles downloaded from github.com and cfengine.com do not match - found "
94+
+ str(extraneous_count)
95+
+ " extraneous file"
96+
+ ("" if extraneous_count == 1 else "s")
97+
+ " and "
98+
+ str(differing_count)
99+
+ " differing file"
100+
+ ("" if differing_count == 1 else "s")
101+
+ " across "
102+
+ str(len(nonmatching_versions))
103+
+ " version"
104+
+ ("" if len(nonmatching_versions) == 1 else "s")
105+
+ " ("
106+
+ ", ".join(nonmatching_versions)
107+
+ "). See ./differences.json"
108+
)

0 commit comments

Comments
 (0)