Skip to content

Commit 01d26cc

Browse files
committed
tools: add ci_config.json TypedDict wrapper
Avoid duplicated code for reading ci_config.json, and ensure the type checker has information about its contents.
1 parent 9ab0285 commit 01d26cc

File tree

4 files changed

+36
-36
lines changed

4 files changed

+36
-36
lines changed

ci_config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"_comment": [
33
"This is intentionally undocumented in README.md, do not use it.",
44
"Using it is an automatic CI error.",
5-
"broken_linux, broken_windows and broken_macos are lists of wraps that are known",
5+
"broken_linux, broken_windows and broken_darwin are lists of wraps that are known",
66
"to be broken on the CI and ***MUST*** get repaired before updates",
77
"will be accepted. If upstream does not support an Operating System,",
88
"explicitly disable that Operating System in build_on.",

tools/create_release.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import json
2727

2828
from pathlib import Path
29-
from utils import Releases, is_ci, is_debianlike, read_wrap, write_wrap
29+
from utils import CIConfig, Releases, is_ci, is_debianlike, read_wrap, write_wrap
3030

3131
class CreateRelease:
3232
def __init__(self, repo: T.Optional[str], token: T.Optional[str], tag: str):
@@ -59,11 +59,9 @@ def create_patch_zip(self) -> None:
5959
generator = Path(srcdir, 'generator.sh')
6060
if generator.exists():
6161
try:
62-
fn = 'ci_config.json'
63-
with open(fn, 'r') as f:
64-
ci = json.load(f)
65-
except json.decoder.JSONDecodeError:
66-
raise RuntimeError(f'file {fn} is malformed')
62+
ci = CIConfig.load()
63+
except json.decoder.JSONDecodeError as ex:
64+
raise RuntimeError(f'CI config is malformed') from ex
6765

6866
debian_packages = ci.get(self.name, {}).get('debian_packages', [])
6967
if debian_packages and is_debianlike():

tools/sanity_checks.py

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import shutil
3030

3131
from pathlib import Path
32-
from utils import Releases, Version, ci_group, is_ci, is_alpinelike, is_debianlike, is_macos, is_windows, is_msys, read_wrap, FormattingError, format_meson
32+
from utils import CIConfig, ProjectCIConfig, Releases, Version, ci_group, is_ci, is_alpinelike, is_debianlike, is_macos, is_windows, is_msys, read_wrap, FormattingError, format_meson
3333

3434
PERMITTED_FILES = {'generator.sh', 'meson.build', 'meson_options.txt', 'meson.options', 'LICENSE.build'}
3535
PER_PROJECT_PERMITTED_FILES: dict[str, set[str]] = {
@@ -163,27 +163,8 @@
163163
IGNORE_SETUP_WARNINGS = None # or re.compile(r'something')
164164

165165

166-
if T.TYPE_CHECKING:
167-
class CiConfigProject(T.TypedDict, total=False):
168-
build_options: list[str]
169-
build_on: dict[str, bool]
170-
alpine_packages: list[str]
171-
brew_packages: list[str]
172-
choco_packages: list[str]
173-
debian_packages: list[str]
174-
msys_packages: list[str]
175-
python_packages: list[str]
176-
fatal_warnings: bool
177-
has_provides: bool
178-
skip_dependency_check: list[str]
179-
skip_program_check: list[str]
180-
test_options: list[str]
181-
skip_tests: bool
182-
183-
184166
class TestReleases(unittest.TestCase):
185-
# requires casts for special keys e.g. broken_*
186-
ci_config: dict[str, CiConfigProject]
167+
ci_config: CIConfig
187168
fatal_warnings: bool
188169
annotate_context: bool
189170
skip_build: bool
@@ -211,14 +192,10 @@ def setUpClass(cls):
211192

212193
try:
213194
cls.releases = Releases.load()
214-
fn = 'ci_config.json'
215-
with open(fn, 'r', encoding='utf-8') as f:
216-
cls.ci_config = json.load(f)
195+
cls.ci_config = CIConfig.load()
217196
except json.decoder.JSONDecodeError as ex:
218197
raise RuntimeError('metadata is malformed') from ex
219198

220-
system = platform.system().lower()
221-
cls.skip = T.cast(T.List[str], cls.ci_config[f'broken_{system}'])
222199
cls.fatal_warnings = os.environ.get('TEST_FATAL_WARNINGS', 'yes') == 'yes'
223200
cls.annotate_context = os.environ.get('TEST_ANNOTATE_CONTEXT') == 'yes'
224201
cls.skip_build = os.environ.get('TEST_SKIP_BUILD') == 'yes'
@@ -345,7 +322,7 @@ def test_releases(self) -> None:
345322
if not self.skip_build:
346323
self.check_new_release(name, deps=deps, progs=progs)
347324
with self.subTest(f'If this works now, please remove it from broken_{platform.system().lower()}!'):
348-
self.assertNotIn(name, self.skip)
325+
self.assertNotIn(name, self.ci_config.broken)
349326
self.check_meson_version(name, ver, patch_path)
350327
if patch_path:
351328
self.check_project_args(name, Path('subprojects') / wrap_section['directory'])
@@ -367,7 +344,7 @@ def test_build_all(self):
367344
failed = []
368345
errored = []
369346
for name, info in self.releases.items():
370-
if name in self.skip:
347+
if name in self.ci_config.broken:
371348
skipped.append(name)
372349
continue
373350
try:
@@ -550,7 +527,7 @@ def do_setup(builddir, options, meson_env):
550527
raise
551528
subprocess.check_call(['meson', 'install', '-C', builddir, '--destdir', 'pkg'])
552529

553-
def install_packages(self, ci: CiConfigProject) -> dict[str, str]:
530+
def install_packages(self, ci: ProjectCIConfig) -> dict[str, str]:
554531
debian_packages = ci.get('debian_packages', [])
555532
brew_packages = ci.get('brew_packages', [])
556533
choco_packages = ci.get('choco_packages', [])

tools/utils.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,31 @@ class ProjectReleases(T.TypedDict):
134134
class Releases(dict[str, ProjectReleases], _JSONFile):
135135
FILENAME = 'releases.json'
136136

137+
class ProjectCIConfig(T.TypedDict):
138+
build_on: T.NotRequired[dict[str, bool]]
139+
build_options: T.NotRequired[list[str]]
140+
fatal_warnings: T.NotRequired[bool]
141+
has_provides: T.NotRequired[bool]
142+
skip_dependency_check: T.NotRequired[list[str]]
143+
skip_program_check: T.NotRequired[list[str]]
144+
skip_tests: T.NotRequired[bool]
145+
test_options: T.NotRequired[list[str]]
146+
147+
alpine_packages: T.NotRequired[list[str]]
148+
brew_packages: T.NotRequired[list[str]]
149+
choco_packages: T.NotRequired[list[str]]
150+
debian_packages: T.NotRequired[list[str]]
151+
msys_packages: T.NotRequired[list[str]]
152+
python_packages: T.NotRequired[list[str]]
153+
154+
class CIConfig(dict[str, ProjectCIConfig], _JSONFile):
155+
FILENAME = 'ci_config.json'
156+
157+
@property
158+
def broken(self) -> list[str]:
159+
system = platform.system().lower()
160+
return T.cast('list[str]', self.get(f'broken_{system}', []))
161+
137162
def wrap_path(name: str) -> Path:
138163
return Path('subprojects', f'{name}.wrap')
139164

0 commit comments

Comments
 (0)