antsibull-nox 0.1.0__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. antsibull_nox/__init__.py +17 -14
  2. antsibull_nox/_pydantic.py +98 -0
  3. antsibull_nox/ansible.py +260 -0
  4. antsibull_nox/cli.py +132 -0
  5. antsibull_nox/collection/__init__.py +56 -0
  6. antsibull_nox/collection/data.py +106 -0
  7. antsibull_nox/collection/extract.py +23 -0
  8. antsibull_nox/collection/install.py +523 -0
  9. antsibull_nox/collection/search.py +460 -0
  10. antsibull_nox/config.py +378 -0
  11. antsibull_nox/data/action-groups.py +3 -3
  12. antsibull_nox/data/antsibull-nox-lint-config.py +29 -0
  13. antsibull_nox/data/antsibull_nox_data_util.py +91 -0
  14. antsibull_nox/data/license-check.py +6 -2
  15. antsibull_nox/data/no-unwanted-files.py +5 -1
  16. antsibull_nox/data/plugin-yamllint.py +247 -0
  17. antsibull_nox/data_util.py +0 -77
  18. antsibull_nox/init.py +83 -0
  19. antsibull_nox/interpret_config.py +244 -0
  20. antsibull_nox/lint_config.py +113 -0
  21. antsibull_nox/paths.py +19 -0
  22. antsibull_nox/python.py +81 -0
  23. antsibull_nox/sessions/__init__.py +70 -0
  24. antsibull_nox/sessions/ansible_lint.py +58 -0
  25. antsibull_nox/sessions/ansible_test.py +568 -0
  26. antsibull_nox/sessions/build_import_check.py +147 -0
  27. antsibull_nox/sessions/collections.py +137 -0
  28. antsibull_nox/sessions/docs_check.py +78 -0
  29. antsibull_nox/sessions/extra_checks.py +127 -0
  30. antsibull_nox/sessions/license_check.py +73 -0
  31. antsibull_nox/sessions/lint.py +627 -0
  32. antsibull_nox/sessions/utils.py +206 -0
  33. antsibull_nox/utils.py +85 -0
  34. {antsibull_nox-0.1.0.dist-info → antsibull_nox-0.3.0.dist-info}/METADATA +4 -2
  35. antsibull_nox-0.3.0.dist-info/RECORD +40 -0
  36. antsibull_nox-0.3.0.dist-info/entry_points.txt +2 -0
  37. antsibull_nox/collection.py +0 -545
  38. antsibull_nox/sessions.py +0 -840
  39. antsibull_nox-0.1.0.dist-info/RECORD +0 -14
  40. {antsibull_nox-0.1.0.dist-info → antsibull_nox-0.3.0.dist-info}/WHEEL +0 -0
  41. {antsibull_nox-0.1.0.dist-info → antsibull_nox-0.3.0.dist-info}/licenses/LICENSES/GPL-3.0-or-later.txt +0 -0
antsibull_nox/sessions.py DELETED
@@ -1,840 +0,0 @@
1
- # Author: Felix Fontein <felix@fontein.de>
2
- # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or
3
- # https://www.gnu.org/licenses/gpl-3.0.txt)
4
- # SPDX-License-Identifier: GPL-3.0-or-later
5
- # SPDX-FileCopyrightText: 2025, Ansible Project
6
-
7
- """
8
- Create nox sessions.
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- import os
14
- import shlex
15
- import subprocess
16
- import sys
17
- import typing as t
18
- from dataclasses import asdict, dataclass
19
- from pathlib import Path
20
-
21
- import nox
22
-
23
- from .collection import (
24
- CollectionData,
25
- force_collection_version,
26
- load_collection_data_from_disk,
27
- setup_collections,
28
- setup_current_tree,
29
- )
30
- from .data_util import prepare_data_script
31
- from .paths import (
32
- copy_collection,
33
- create_temp_directory,
34
- filter_paths,
35
- find_data_directory,
36
- list_all_files,
37
- remove_path,
38
- )
39
-
40
- # https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables
41
- # https://docs.gitlab.com/ci/variables/predefined_variables/#predefined-variables
42
- # https://docs.travis-ci.com/user/environment-variables/#default-environment-variables
43
- IN_CI = os.environ.get("CI") == "true"
44
- ALLOW_EDITABLE = os.environ.get("ALLOW_EDITABLE", str(not IN_CI)).lower() in (
45
- "1",
46
- "true",
47
- )
48
-
49
- COLLECTION_NAME = "community.dns"
50
-
51
- CODE_FILES = [
52
- "plugins",
53
- "tests/unit",
54
- ]
55
-
56
- MODULE_PATHS = [
57
- "plugins/modules/",
58
- "plugins/module_utils/",
59
- "tests/unit/plugins/modules/",
60
- "tests/unit/plugins/module_utils/",
61
- ]
62
-
63
-
64
- def install(session: nox.Session, *args: str, editable: bool = False, **kwargs):
65
- """
66
- Install Python packages.
67
- """
68
- # nox --no-venv
69
- if isinstance(session.virtualenv, nox.virtualenv.PassthroughEnv):
70
- session.warn(f"No venv. Skipping installation of {args}")
71
- return
72
- # Don't install in editable mode in CI or if it's explicitly disabled.
73
- # This ensures that the wheel contains all of the correct files.
74
- if editable and ALLOW_EDITABLE:
75
- args = ("-e", *args)
76
- session.install(*args, "-U", **kwargs)
77
-
78
-
79
- @dataclass
80
- class CollectionSetup:
81
- """
82
- Information on the setup collections.
83
- """
84
-
85
- # The path of the ansible_collections directory where all dependent collections
86
- # are installed. Is currently identical to current_root, but that might change
87
- # or depend on options in the future.
88
- collections_root: Path
89
-
90
- # The directory in which ansible_collections can be found, as well as
91
- # ansible_collections/<namespace>/<name> points to a copy of the current collection.
92
- current_place: Path
93
-
94
- # The path of the ansible_collections directory that contains the current collection.
95
- # The following is always true:
96
- # current_root == current_place / "ansible_collections"
97
- current_root: Path
98
-
99
- # Data on the current collection (as in the repository).
100
- current_collection: CollectionData
101
-
102
- # The path of the current collection inside the collection tree below current_root.
103
- # The following is always true:
104
- # current_path == current_root / current_collection.namespace / current_collection.name
105
- current_path: Path
106
-
107
- def prefix_current_paths(self, paths: list[str]) -> list[str]:
108
- """
109
- Prefix the list of given paths with ``current_path``.
110
- """
111
- result = []
112
- for path in paths:
113
- prefixed_path = (self.current_path / path).relative_to(self.current_place)
114
- if prefixed_path.exists():
115
- result.append(str(prefixed_path))
116
- return result
117
-
118
-
119
- def _run_subprocess(args: list[str]) -> tuple[bytes, bytes]:
120
- p = subprocess.run(args, check=True, capture_output=True)
121
- return p.stdout, p.stderr
122
-
123
-
124
- def prepare_collections(
125
- session: nox.Session,
126
- *,
127
- install_in_site_packages: bool,
128
- extra_deps_files: list[str | os.PathLike] | None = None,
129
- extra_collections: list[str] | None = None,
130
- install_out_of_tree: bool = False, # can not be used with install_in_site_packages=True
131
- ) -> CollectionSetup | None:
132
- """
133
- Install collections in site-packages.
134
- """
135
- if install_out_of_tree and install_in_site_packages:
136
- raise ValueError(
137
- "install_out_of_tree=True cannot be combined with install_in_site_packages=True"
138
- )
139
- if isinstance(session.virtualenv, nox.virtualenv.PassthroughEnv):
140
- session.warn("No venv. Skip preparing collections...")
141
- return None
142
- if install_in_site_packages:
143
- purelib = (
144
- session.run(
145
- "python",
146
- "-c",
147
- "import sysconfig; print(sysconfig.get_path('purelib'))",
148
- silent=True,
149
- )
150
- or ""
151
- ).strip()
152
- if not purelib:
153
- session.warn(
154
- "Cannot find site-packages (probably due to install-only run)."
155
- " Skip preparing collections..."
156
- )
157
- return None
158
- place = Path(purelib)
159
- elif install_out_of_tree:
160
- place = create_temp_directory(f"antsibull-nox-{session.name}-collection-root-")
161
- else:
162
- place = Path(session.virtualenv.location) / "collection-root"
163
- place.mkdir(exist_ok=True)
164
- setup = setup_collections(
165
- place,
166
- _run_subprocess,
167
- extra_deps_files=extra_deps_files,
168
- extra_collections=extra_collections,
169
- with_current=False,
170
- )
171
- current_setup = setup_current_tree(place, setup.current_collection)
172
- return CollectionSetup(
173
- collections_root=setup.root,
174
- current_place=place,
175
- current_root=current_setup.root,
176
- current_collection=setup.current_collection,
177
- current_path=t.cast(Path, current_setup.current_path),
178
- )
179
-
180
-
181
- def _run_bare_script(
182
- session: nox.Session, /, name: str, *, extra_data: dict[str, t.Any] | None = None
183
- ) -> None:
184
- files = list_all_files()
185
- data = prepare_data_script(
186
- session,
187
- base_name=name,
188
- paths=files,
189
- extra_data=extra_data,
190
- )
191
- session.run(
192
- sys.executable,
193
- find_data_directory() / f"{name}.py",
194
- "--data",
195
- data,
196
- external=True,
197
- )
198
-
199
-
200
- def add_lint(
201
- *, make_lint_default: bool, has_formatters: bool, has_codeqa: bool, has_typing: bool
202
- ) -> None:
203
- """
204
- Add nox meta session for linting.
205
- """
206
-
207
- def lint(session: nox.Session) -> None: # pylint: disable=unused-argument
208
- pass # this session is deliberately empty
209
-
210
- dependent_sessions = []
211
- if has_formatters:
212
- dependent_sessions.append("formatters")
213
- if has_codeqa:
214
- dependent_sessions.append("codeqa")
215
- if has_typing:
216
- dependent_sessions.append("typing")
217
- nox.session( # type: ignore
218
- lint, name="lint", default=make_lint_default, requires=dependent_sessions
219
- )
220
-
221
-
222
- def add_formatters(
223
- *,
224
- extra_code_files: list[str],
225
- # isort:
226
- run_isort: bool,
227
- isort_config: str | os.PathLike | None,
228
- isort_package: str,
229
- # black:
230
- run_black: bool,
231
- run_black_modules: bool | None,
232
- black_config: str | os.PathLike | None,
233
- black_package: str,
234
- ) -> None:
235
- """
236
- Add nox session for formatters.
237
- """
238
- if run_black_modules is None:
239
- run_black_modules = run_black
240
- run_check = IN_CI
241
-
242
- def compose_dependencies() -> list[str]:
243
- deps = []
244
- if run_isort:
245
- deps.append(isort_package)
246
- if run_black or run_black_modules:
247
- deps.append(black_package)
248
- return deps
249
-
250
- def execute_isort(session: nox.Session) -> None:
251
- command: list[str] = [
252
- "isort",
253
- ]
254
- if run_check:
255
- command.append("--check")
256
- if isort_config is not None:
257
- command.extend(["--settings-file", str(isort_config)])
258
- command.extend(session.posargs)
259
- command.extend(filter_paths(CODE_FILES + ["noxfile.py"] + extra_code_files))
260
- session.run(*command)
261
-
262
- def execute_black_for(session: nox.Session, paths: list[str]) -> None:
263
- if not paths:
264
- return
265
- command = ["black"]
266
- if run_check:
267
- command.append("--check")
268
- if black_config is not None:
269
- command.extend(["--config", str(black_config)])
270
- command.extend(session.posargs)
271
- command.extend(paths)
272
- session.run(*command)
273
-
274
- def execute_black(session: nox.Session) -> None:
275
- if run_black and run_black_modules:
276
- execute_black_for(
277
- session, filter_paths(CODE_FILES + ["noxfile.py"] + extra_code_files)
278
- )
279
- return
280
- if run_black:
281
- paths = filter_paths(
282
- CODE_FILES,
283
- remove=MODULE_PATHS,
284
- extensions=[".py"],
285
- ) + ["noxfile.py"]
286
- execute_black_for(session, paths)
287
- if run_black_modules:
288
- paths = filter_paths(
289
- CODE_FILES,
290
- restrict=MODULE_PATHS,
291
- extensions=[".py"],
292
- )
293
- execute_black_for(session, paths)
294
-
295
- def formatters(session: nox.Session) -> None:
296
- install(session, *compose_dependencies())
297
- if run_isort:
298
- execute_isort(session)
299
- if run_black or run_black_modules:
300
- execute_black(session)
301
-
302
- nox.session(formatters, name="formatters", default=False) # type: ignore
303
-
304
-
305
- def add_codeqa( # noqa: C901
306
- *,
307
- extra_code_files: list[str],
308
- # flake8:
309
- run_flake8: bool,
310
- flake8_config: str | os.PathLike | None,
311
- flake8_package: str,
312
- # pylint:
313
- run_pylint: bool,
314
- pylint_rcfile: str | os.PathLike | None,
315
- pylint_modules_rcfile: str | os.PathLike | None,
316
- pylint_package: str,
317
- pylint_ansible_core_package: str | None,
318
- pylint_extra_deps: list[str],
319
- ) -> None:
320
- """
321
- Add nox session for codeqa.
322
- """
323
-
324
- def compose_dependencies() -> list[str]:
325
- deps = []
326
- if run_flake8:
327
- deps.append(flake8_package)
328
- if run_pylint:
329
- deps.append(pylint_package)
330
- if pylint_ansible_core_package is not None:
331
- deps.append(pylint_ansible_core_package)
332
- if os.path.isdir("tests/unit"):
333
- deps.append("pytest")
334
- if os.path.isfile("tests/unit/requirements.txt"):
335
- deps.extend(["-r", "tests/unit/requirements.txt"])
336
- for extra_dep in pylint_extra_deps:
337
- deps.extend(shlex.split(extra_dep))
338
- return deps
339
-
340
- def execute_flake8(session: nox.Session) -> None:
341
- command: list[str] = [
342
- "flake8",
343
- ]
344
- if flake8_config is not None:
345
- command.extend(["--config", str(flake8_config)])
346
- command.extend(session.posargs)
347
- command.extend(filter_paths(CODE_FILES + ["noxfile.py"] + extra_code_files))
348
- session.run(*command)
349
-
350
- def execute_pylint_impl(
351
- session: nox.Session,
352
- prepared_collections: CollectionSetup,
353
- config: os.PathLike | str | None,
354
- paths: list[str],
355
- ) -> None:
356
- command = ["pylint"]
357
- if config is not None:
358
- command.extend(
359
- [
360
- "--rcfile",
361
- os.path.join(prepared_collections.current_collection.path, config),
362
- ]
363
- )
364
- command.extend(["--source-roots", "."])
365
- command.extend(session.posargs)
366
- command.extend(prepared_collections.prefix_current_paths(paths))
367
- session.run(*command)
368
-
369
- def execute_pylint(
370
- session: nox.Session, prepared_collections: CollectionSetup
371
- ) -> None:
372
- if pylint_modules_rcfile is not None and pylint_modules_rcfile != pylint_rcfile:
373
- # Only run pylint twice when using different configurations
374
- module_paths = filter_paths(
375
- CODE_FILES, restrict=MODULE_PATHS, extensions=[".py"]
376
- )
377
- other_paths = filter_paths(
378
- CODE_FILES, remove=MODULE_PATHS, extensions=[".py"]
379
- )
380
- else:
381
- # Otherwise run it only once using the general configuration
382
- module_paths = []
383
- other_paths = filter_paths(CODE_FILES)
384
-
385
- with session.chdir(prepared_collections.current_place):
386
- if module_paths:
387
- execute_pylint_impl(
388
- session,
389
- prepared_collections,
390
- pylint_modules_rcfile or pylint_rcfile,
391
- module_paths,
392
- )
393
-
394
- if other_paths:
395
- execute_pylint_impl(
396
- session, prepared_collections, pylint_rcfile, other_paths
397
- )
398
-
399
- def codeqa(session: nox.Session) -> None:
400
- install(session, *compose_dependencies())
401
- prepared_collections: CollectionSetup | None = None
402
- if run_pylint:
403
- prepared_collections = prepare_collections(
404
- session,
405
- install_in_site_packages=False,
406
- extra_deps_files=["tests/unit/requirements.yml"],
407
- )
408
- if not prepared_collections:
409
- session.warn("Skipping pylint...")
410
- if run_flake8:
411
- execute_flake8(session)
412
- if run_pylint and prepared_collections:
413
- execute_pylint(session, prepared_collections)
414
-
415
- nox.session(codeqa, name="codeqa", default=False) # type: ignore
416
-
417
-
418
- def add_typing(
419
- *,
420
- extra_code_files: list[str],
421
- run_mypy: bool,
422
- mypy_config: str | os.PathLike | None,
423
- mypy_package: str,
424
- mypy_ansible_core_package: str | None,
425
- mypy_extra_deps: list[str],
426
- ) -> None:
427
- """
428
- Add nox session for typing.
429
- """
430
-
431
- def compose_dependencies() -> list[str]:
432
- deps = []
433
- if run_mypy:
434
- deps.append(mypy_package)
435
- if mypy_ansible_core_package is not None:
436
- deps.append(mypy_ansible_core_package)
437
- if os.path.isdir("tests/unit"):
438
- deps.append("pytest")
439
- if os.path.isfile("tests/unit/requirements.txt"):
440
- deps.extend(["-r", "tests/unit/requirements.txt"])
441
- for extra_dep in mypy_extra_deps:
442
- deps.extend(shlex.split(extra_dep))
443
- return deps
444
-
445
- def execute_mypy(
446
- session: nox.Session, prepared_collections: CollectionSetup
447
- ) -> None:
448
- # Run mypy
449
- with session.chdir(prepared_collections.current_place):
450
- command = ["mypy"]
451
- if mypy_config is not None:
452
- command.extend(
453
- [
454
- "--config-file",
455
- os.path.join(
456
- prepared_collections.current_collection.path, mypy_config
457
- ),
458
- ]
459
- )
460
- command.append("--namespace-packages")
461
- command.append("--explicit-package-bases")
462
- command.extend(session.posargs)
463
- command.extend(
464
- prepared_collections.prefix_current_paths(CODE_FILES + extra_code_files)
465
- )
466
- session.run(
467
- *command, env={"MYPYPATH": str(prepared_collections.current_place)}
468
- )
469
-
470
- def typing(session: nox.Session) -> None:
471
- install(session, *compose_dependencies())
472
- prepared_collections = prepare_collections(
473
- session,
474
- install_in_site_packages=False,
475
- extra_deps_files=["tests/unit/requirements.yml"],
476
- )
477
- if not prepared_collections:
478
- session.warn("Skipping mypy...")
479
- if run_mypy and prepared_collections:
480
- execute_mypy(session, prepared_collections)
481
-
482
- nox.session(typing, name="typing", default=False) # type: ignore
483
-
484
-
485
- def add_lint_sessions(
486
- *,
487
- make_lint_default: bool = True,
488
- extra_code_files: list[str] | None = None,
489
- # isort:
490
- run_isort: bool = True,
491
- isort_config: str | os.PathLike | None = None,
492
- isort_package: str = "isort",
493
- # black:
494
- run_black: bool = True,
495
- run_black_modules: bool | None = None,
496
- black_config: str | os.PathLike | None = None,
497
- black_package: str = "black",
498
- # flake8:
499
- run_flake8: bool = True,
500
- flake8_config: str | os.PathLike | None = None,
501
- flake8_package: str = "flake8",
502
- # pylint:
503
- run_pylint: bool = True,
504
- pylint_rcfile: str | os.PathLike | None = None,
505
- pylint_modules_rcfile: str | os.PathLike | None = None,
506
- pylint_package: str = "pylint",
507
- pylint_ansible_core_package: str | None = "ansible-core",
508
- pylint_extra_deps: list[str] | None = None,
509
- # mypy:
510
- run_mypy: bool = True,
511
- mypy_config: str | os.PathLike | None = None,
512
- mypy_package: str = "mypy",
513
- mypy_ansible_core_package: str | None = "ansible-core",
514
- mypy_extra_deps: list[str] | None = None,
515
- ) -> None:
516
- """
517
- Add nox sessions for linting.
518
- """
519
- has_formatters = run_isort or run_black or run_black_modules or False
520
- has_codeqa = run_flake8 or run_pylint
521
- has_typing = run_mypy
522
-
523
- add_lint(
524
- has_formatters=has_formatters,
525
- has_codeqa=has_codeqa,
526
- has_typing=has_typing,
527
- make_lint_default=make_lint_default,
528
- )
529
-
530
- if has_formatters:
531
- add_formatters(
532
- extra_code_files=extra_code_files or [],
533
- run_isort=run_isort,
534
- isort_config=isort_config,
535
- isort_package=isort_package,
536
- run_black=run_black,
537
- run_black_modules=run_black_modules,
538
- black_config=black_config,
539
- black_package=black_package,
540
- )
541
-
542
- if has_codeqa:
543
- add_codeqa(
544
- extra_code_files=extra_code_files or [],
545
- run_flake8=run_flake8,
546
- flake8_config=flake8_config,
547
- flake8_package=flake8_package,
548
- run_pylint=run_pylint,
549
- pylint_rcfile=pylint_rcfile,
550
- pylint_modules_rcfile=pylint_modules_rcfile,
551
- pylint_package=pylint_package,
552
- pylint_ansible_core_package=pylint_ansible_core_package,
553
- pylint_extra_deps=pylint_extra_deps or [],
554
- )
555
-
556
- if has_typing:
557
- add_typing(
558
- extra_code_files=extra_code_files or [],
559
- run_mypy=run_mypy,
560
- mypy_config=mypy_config,
561
- mypy_package=mypy_package,
562
- mypy_ansible_core_package=mypy_ansible_core_package,
563
- mypy_extra_deps=mypy_extra_deps or [],
564
- )
565
-
566
-
567
- def add_docs_check(
568
- *,
569
- make_docs_check_default: bool = True,
570
- antsibull_docs_package: str = "antsibull-docs",
571
- ansible_core_package: str = "ansible-core",
572
- validate_collection_refs: t.Literal["self", "dependent", "all"] | None = None,
573
- extra_collections: list[str] | None = None,
574
- ):
575
- """
576
- Add docs-check session for linting.
577
- """
578
-
579
- def compose_dependencies() -> list[str]:
580
- deps = [antsibull_docs_package, ansible_core_package]
581
- return deps
582
-
583
- def execute_antsibull_docs(
584
- session: nox.Session, prepared_collections: CollectionSetup
585
- ) -> None:
586
- with session.chdir(prepared_collections.current_path):
587
- collections_path = f"{prepared_collections.current_place}"
588
- command = [
589
- "antsibull-docs",
590
- "lint-collection-docs",
591
- "--plugin-docs",
592
- "--skip-rstcheck",
593
- ".",
594
- ]
595
- if validate_collection_refs:
596
- command.extend(["--validate-collection-refs", validate_collection_refs])
597
- session.run(*command, env={"ANSIBLE_COLLECTIONS_PATH": collections_path})
598
-
599
- def docs_check(session: nox.Session) -> None:
600
- install(session, *compose_dependencies())
601
- prepared_collections = prepare_collections(
602
- session,
603
- install_in_site_packages=False,
604
- extra_collections=extra_collections,
605
- install_out_of_tree=True,
606
- )
607
- if not prepared_collections:
608
- session.warn("Skipping antsibull-docs...")
609
- if prepared_collections:
610
- execute_antsibull_docs(session, prepared_collections)
611
-
612
- nox.session( # type: ignore
613
- docs_check, name="docs-check", default=make_docs_check_default
614
- )
615
-
616
-
617
- def add_license_check(
618
- *,
619
- make_license_check_default: bool = True,
620
- run_reuse: bool = True,
621
- reuse_package: str = "reuse",
622
- run_license_check: bool = True,
623
- license_check_extra_ignore_paths: list[str] | None = None,
624
- ):
625
- """
626
- Add license-check session for license checks.
627
- """
628
-
629
- def compose_dependencies() -> list[str]:
630
- deps = []
631
- if run_reuse:
632
- deps.append(reuse_package)
633
- return deps
634
-
635
- def license_check(session: nox.Session) -> None:
636
- install(session, *compose_dependencies())
637
- if run_reuse:
638
- session.run("reuse", "lint")
639
- if run_license_check:
640
- _run_bare_script(
641
- session,
642
- "license-check",
643
- extra_data={
644
- "extra_ignore_paths": license_check_extra_ignore_paths or [],
645
- },
646
- )
647
-
648
- nox.session( # type: ignore
649
- license_check, name="license-check", default=make_license_check_default
650
- )
651
-
652
-
653
- @dataclass
654
- class ActionGroup:
655
- """
656
- Defines an action group.
657
- """
658
-
659
- # Name of the action group.
660
- name: str
661
- # Regex pattern to match modules that could belong to this action group.
662
- pattern: str
663
- # Doc fragment that members of the action group must have, but no other module
664
- # must have
665
- doc_fragment: str
666
- # Exclusion list of modules that match the regex, but should not be part of the
667
- # action group. All other modules matching the regex are assumed to be part of
668
- # the action group.
669
- exclusions: list[str] | None = None
670
-
671
-
672
- def add_extra_checks(
673
- *,
674
- make_extra_checks_default: bool = True,
675
- # no-unwanted-files:
676
- run_no_unwanted_files: bool = True,
677
- no_unwanted_files_module_extensions: (
678
- list[str] | None
679
- ) = None, # default: .cs, .ps1, .psm1, .py
680
- no_unwanted_files_other_extensions: list[str] | None = None, # default: .py, .pyi
681
- no_unwanted_files_yaml_extensions: list[str] | None = None, # default: .yml, .yaml
682
- no_unwanted_files_skip_paths: list[str] | None = None, # default: []
683
- no_unwanted_files_skip_directories: list[str] | None = None, # default: []
684
- no_unwanted_files_yaml_directories: (
685
- list[str] | None
686
- ) = None, # default: plugins/test/, plugins/filter/
687
- no_unwanted_files_allow_symlinks: bool = False,
688
- # action-groups:
689
- run_action_groups: bool = False,
690
- action_groups_config: list[ActionGroup] | None = None,
691
- ):
692
- """
693
- Add extra-checks session for extra checks.
694
- """
695
-
696
- def execute_no_unwanted_files(session: nox.Session) -> None:
697
- _run_bare_script(
698
- session,
699
- "no-unwanted-files",
700
- extra_data={
701
- "module_extensions": no_unwanted_files_module_extensions
702
- or [".cs", ".ps1", ".psm1", ".py"],
703
- "other_extensions": no_unwanted_files_other_extensions
704
- or [".py", ".pyi"],
705
- "yaml_extensions": no_unwanted_files_yaml_extensions
706
- or [".yml", ".yaml"],
707
- "skip_paths": no_unwanted_files_skip_paths or [],
708
- "skip_directories": no_unwanted_files_skip_directories or [],
709
- "yaml_directories": no_unwanted_files_yaml_directories
710
- or ["plugins/test/", "plugins/filter/"],
711
- "allow_symlinks": no_unwanted_files_allow_symlinks,
712
- },
713
- )
714
-
715
- def execute_action_groups(session: nox.Session) -> None:
716
- if action_groups_config is None:
717
- session.warn("Skipping action-groups since config is not provided...")
718
- return
719
- _run_bare_script(
720
- session,
721
- "action-groups",
722
- extra_data={
723
- "config": [asdict(cfg) for cfg in action_groups_config],
724
- },
725
- )
726
-
727
- def extra_checks(session: nox.Session) -> None:
728
- if run_no_unwanted_files:
729
- execute_no_unwanted_files(session)
730
- if run_action_groups:
731
- execute_action_groups(session)
732
-
733
- nox.session( # type: ignore
734
- extra_checks,
735
- name="extra-checks",
736
- python=False,
737
- default=make_extra_checks_default,
738
- )
739
-
740
-
741
- def add_build_import_check(
742
- *,
743
- make_build_import_check_default: bool = True,
744
- ansible_core_package: str = "ansible-core",
745
- run_galaxy_importer: bool = True,
746
- galaxy_importer_package: str = "galaxy-importer",
747
- galaxy_importer_config_path: (
748
- str | None
749
- ) = None, # https://github.com/ansible/galaxy-importer#configuration
750
- ):
751
- """
752
- Add license-check session for license checks.
753
- """
754
-
755
- def compose_dependencies() -> list[str]:
756
- deps = [ansible_core_package]
757
- if run_galaxy_importer:
758
- deps.append(galaxy_importer_package)
759
- return deps
760
-
761
- def build_import_check(session: nox.Session) -> None:
762
- install(session, *compose_dependencies())
763
-
764
- tmp = Path(session.create_tmp())
765
- collection_dir = tmp / "collection"
766
- remove_path(collection_dir)
767
- copy_collection(Path.cwd(), collection_dir)
768
-
769
- collection = load_collection_data_from_disk(
770
- collection_dir, accept_manifest=False
771
- )
772
- version = collection.version
773
- if not version:
774
- version = "0.0.1"
775
- force_collection_version(collection_dir, version=version)
776
-
777
- with session.chdir(collection_dir):
778
- build_ran = session.run("ansible-galaxy", "collection", "build") is not None
779
-
780
- tarball = (
781
- collection_dir
782
- / f"{collection.namespace}-{collection.name}-{version}.tar.gz"
783
- )
784
- if build_ran and not tarball.is_file():
785
- files = "\n".join(
786
- f"* {path.name}"
787
- for path in collection_dir.iterdir()
788
- if not path.is_dir()
789
- )
790
- session.error(f"Cannot find file {tarball}! List of all files:\n{files}")
791
-
792
- if run_galaxy_importer and tarball.is_file():
793
- env = {}
794
- if galaxy_importer_config_path:
795
- env["GALAXY_IMPORTER_CONFIG"] = str(
796
- Path.cwd() / galaxy_importer_config_path
797
- )
798
- with session.chdir(collection_dir):
799
- import_log = (
800
- session.run(
801
- "python",
802
- "-m",
803
- "galaxy_importer.main",
804
- tarball.name,
805
- env=env,
806
- silent=True,
807
- )
808
- or ""
809
- )
810
- if import_log:
811
- print(import_log)
812
- error_prefix = "ERROR:"
813
- errors = []
814
- for line in import_log.splitlines():
815
- if line.startswith(error_prefix):
816
- errors.append(line[len(error_prefix) :].strip())
817
- if errors:
818
- messages = "\n".join(f"* {error}" for error in errors)
819
- session.warn(
820
- "Galaxy importer emitted the following non-fatal"
821
- f" error{'' if len(errors) == 1 else 's'}:\n{messages}"
822
- )
823
-
824
- nox.session( # type: ignore
825
- build_import_check,
826
- name="build-import-check",
827
- default=make_build_import_check_default,
828
- )
829
-
830
-
831
- __all__ = [
832
- "ActionGroup",
833
- "add_build_import_check",
834
- "add_docs_check",
835
- "add_extra_checks",
836
- "add_license_check",
837
- "add_lint_sessions",
838
- "install",
839
- "prepare_collections",
840
- ]