v30.3-roots.1 · Commit 66: [PATCH 66/68] fix(release): validate notices and reuse proven promotion CI
ci/release/runner-notices.py
Before: ci/release/runner-notices.py · After: ci/release/runner-notices.py
File metadata
index 4876f59c3fb520b360d662b0a1c5b7a3c2082e3f..c4d73139b6d2d8a2bcd8eabf7df70e5a6bf02c78 100755
Download original patch · Release notes
Diff rows 1–56 of 56. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.
ci/release/runner-notices.py
CHANGED
|
@@ -47,14 +47,17 @@ def source_notices(archive, expected_hash, destination):
|
|
|
47
47
|
if not member.isfile():
|
|
48
48
|
continue
|
|
49
49
|
path = PurePosixPath(member.name)
|
|
50
|
-
if path.is_absolute() or '..' in path.parts or '\\' in member.name or ':' in member.name:
|
|
51
|
-
raise ValueError('Unsafe source archive member')
|
|
52
|
-
name = path.name.lower()
|
|
50
|
+
scan_path = PurePosixPath(member.name.replace('\\', '/'))
|
|
51
|
+
name = scan_path.name.lower()
|
|
53
52
|
selected = bool(re.fullmatch(r'(?:copying|licen[cs]e|copyright|notice)(?:[._-].*)?', name))
|
|
54
|
-
selected |= 'LICENSES' in path.parts or name in {'ftl.txt', 'gplv2.txt'}
|
|
55
|
-
header = name == 'sqlite3.c' or path.as_posix().endswith('/keysyms/keysyms.c')
|
|
53
|
+
selected |= 'LICENSES' in scan_path.parts or name in {'ftl.txt', 'gplv2.txt'}
|
|
54
|
+
header = name == 'sqlite3.c' or scan_path.as_posix().endswith('/keysyms/keysyms.c')
|
|
56
55
|
if not selected and not header:
|
|
57
56
|
continue
|
|
57
|
+
# Source tarballs can contain irrelevant manpage names such as
|
|
58
|
+
# SystemTap's function::HZ.3stap. Never write those members.
|
|
59
|
+
if path.is_absolute() or '..' in path.parts or '\\' in member.name or ':' in member.name:
|
|
60
|
+
raise ValueError(f'Unsafe source archive notice: {archive.name}: {member.name}')
|
|
58
61
|
data = package.extractfile(member).read()
|
|
59
62
|
if header:
|
|
60
63
|
data = data.split(b'*/', 1)[0] + b'*/\n'
|
|
@@ -80,9 +83,16 @@ def acquire(url, checksum, destination):
|
|
|
80
83
|
|
|
81
84
|
|
|
82
85
|
def depends_notices(depends, host, destination):
|
|
83
|
-
def variables(names):
|
|
86
|
+
def variables(names, packages=()):
|
|
87
|
+
bindings = []
|
|
88
|
+
for name in names:
|
|
89
|
+
package = next((p for p in sorted(packages, key=len, reverse=True)
|
|
90
|
+
if name.startswith(p + '_')), None)
|
|
91
|
+
if package:
|
|
92
|
+
# Recipes defer $(package)-based expansion until a target runs.
|
|
93
|
+
bindings.append(f'--eval=print-{name}: package={package}')
|
|
84
94
|
output = run('make', '--no-print-directory', '-C', str(depends), f'HOST={host}',
|
|
85
|
-
*[f'print-{name}' for name in names])
|
|
95
|
+
*bindings, *[f'print-{name}' for name in names])
|
|
86
96
|
return dict(line.split('=', 1) for line in output.splitlines() if '=' in line)
|
|
87
97
|
selected = variables(['packages', 'host_prefix', 'SOURCES_PATH'])
|
|
88
98
|
if not (Path(selected['host_prefix']) / 'toolchain.cmake').is_file():
|
|
@@ -90,7 +100,7 @@ def depends_notices(depends, host, destination):
|
|
|
90
100
|
packages = selected['packages'].split()
|
|
91
101
|
names = [f'{p}_{suffix}' for p in packages for suffix in
|
|
92
102
|
('version', 'source', 'sha256_hash', 'download_path', 'download_file', 'extra_sources')]
|
|
93
|
-
values = variables(names)
|
|
103
|
+
values = variables(names, packages)
|
|
94
104
|
result = {}
|
|
95
105
|
for package in packages:
|
|
96
106
|
source = Path(values[f'{package}_source'])
|
|
@@ -100,7 +110,7 @@ def depends_notices(depends, host, destination):
|
|
|
100
110
|
# Qt translations/tools are separately fetched and bundled by the recipe.
|
|
101
111
|
if package == 'qt':
|
|
102
112
|
extras = variables(['qt_qttranslations_file_name', 'qt_qttranslations_sha256_hash',
|
|
103
|
-
'qt_qttools_file_name', 'qt_qttools_sha256_hash'])
|
|
113
|
+
'qt_qttools_file_name', 'qt_qttools_sha256_hash'], ['qt'])
|
|
104
114
|
for part in ('qttranslations', 'qttools'):
|
|
105
115
|
filename = extras[f'qt_{part}_file_name']
|
|
106
116
|
extra_hash = extras[f'qt_{part}_sha256_hash']
|