gha-utils 4.17.9__py3-none-any.whl → 4.18.1__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.
Potentially problematic release.
This version of gha-utils might be problematic. Click here for more details.
- gha_utils/__init__.py +1 -1
- gha_utils/cli.py +2 -2
- gha_utils/matrix.py +33 -25
- gha_utils/metadata.py +139 -33
- {gha_utils-4.17.9.dist-info → gha_utils-4.18.1.dist-info}/METADATA +3 -2
- gha_utils-4.18.1.dist-info/RECORD +14 -0
- gha_utils-4.17.9.dist-info/RECORD +0 -14
- {gha_utils-4.17.9.dist-info → gha_utils-4.18.1.dist-info}/WHEEL +0 -0
- {gha_utils-4.17.9.dist-info → gha_utils-4.18.1.dist-info}/entry_points.txt +0 -0
- {gha_utils-4.17.9.dist-info → gha_utils-4.18.1.dist-info}/top_level.txt +0 -0
gha_utils/__init__.py
CHANGED
gha_utils/cli.py
CHANGED
|
@@ -116,8 +116,8 @@ def gha_utils():
|
|
|
116
116
|
)
|
|
117
117
|
@option(
|
|
118
118
|
"--format",
|
|
119
|
-
type=Choice(
|
|
120
|
-
default=
|
|
119
|
+
type=Choice(Dialects, case_sensitive=False), # type: ignore[arg-type]
|
|
120
|
+
default=Dialects.github,
|
|
121
121
|
help="Rendering format of the metadata.",
|
|
122
122
|
)
|
|
123
123
|
@option(
|
gha_utils/matrix.py
CHANGED
|
@@ -27,7 +27,7 @@ from boltons.iterutils import unique
|
|
|
27
27
|
RESERVED_MATRIX_KEYWORDS = ["include", "exclude"]
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class Matrix
|
|
30
|
+
class Matrix:
|
|
31
31
|
"""A matrix as defined by GitHub's actions workflows.
|
|
32
32
|
|
|
33
33
|
See GitHub official documentation on `how-to implement variations of jobs in a
|
|
@@ -47,35 +47,43 @@ class Matrix(FrozenDict):
|
|
|
47
47
|
matrix.
|
|
48
48
|
"""
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
def __init__(self, *args, **kwargs):
|
|
51
|
+
self.variations: dict[str, tuple[str, ...]] = {}
|
|
52
|
+
|
|
53
|
+
# Tuples are used to keep track of the insertion order and force immutability.
|
|
54
|
+
self.include: tuple[dict[str, str], ...] = tuple()
|
|
55
|
+
self.exclude: tuple[dict[str, str], ...] = tuple()
|
|
56
|
+
|
|
57
|
+
self._job_counter = None
|
|
53
58
|
|
|
54
59
|
def matrix(
|
|
55
60
|
self, ignore_includes: bool = False, ignore_excludes: bool = False
|
|
56
|
-
) ->
|
|
61
|
+
) -> FrozenDict[str, str]:
|
|
57
62
|
"""Returns a copy of the matrix.
|
|
58
63
|
|
|
59
64
|
The special ``include`` and ``excludes`` directives will be added by default.
|
|
60
65
|
You can selectively ignore them by passing the corresponding boolean parameters.
|
|
61
66
|
"""
|
|
62
|
-
dict_copy =
|
|
67
|
+
dict_copy = self.variations.copy()
|
|
63
68
|
if not ignore_includes and self.include:
|
|
64
|
-
dict_copy["include"] = self.include
|
|
69
|
+
dict_copy["include"] = self.include # type: ignore[assignment]
|
|
65
70
|
if not ignore_excludes and self.exclude:
|
|
66
|
-
dict_copy["exclude"] = self.exclude
|
|
67
|
-
return dict_copy
|
|
71
|
+
dict_copy["exclude"] = self.exclude # type: ignore[assignment]
|
|
72
|
+
return FrozenDict(dict_copy)
|
|
68
73
|
|
|
69
74
|
def __repr__(self) -> str:
|
|
70
|
-
return (
|
|
71
|
-
f"<{self.__class__.__name__}: {super(FrozenDict, self).__repr__()}; "
|
|
72
|
-
f"include={self.include}; exclude={self.exclude}>"
|
|
73
|
-
)
|
|
75
|
+
return f"<{self.__class__.__name__}: {self.matrix()}>"
|
|
74
76
|
|
|
75
77
|
def __str__(self) -> str:
|
|
76
78
|
"""Render matrix as a JSON string."""
|
|
77
79
|
return json.dumps(self.matrix())
|
|
78
80
|
|
|
81
|
+
def __getitem__(self, key: str) -> tuple[str, ...]:
|
|
82
|
+
"""Returns the values of a variation by its ID."""
|
|
83
|
+
if key in self.variations:
|
|
84
|
+
return self.variations[key]
|
|
85
|
+
raise KeyError(f"Variation {key} not found in matrix")
|
|
86
|
+
|
|
79
87
|
@staticmethod
|
|
80
88
|
def _check_ids(*var_ids: str) -> None:
|
|
81
89
|
for var_id in var_ids:
|
|
@@ -89,8 +97,8 @@ class Matrix(FrozenDict):
|
|
|
89
97
|
if any(type(v) is not str for v in values):
|
|
90
98
|
raise ValueError(f"Only strings are accepted in {values}")
|
|
91
99
|
# Extend variation with values, and deduplicate them along the way.
|
|
92
|
-
var_values = list(self.get(variation_id, [])) + list(values)
|
|
93
|
-
|
|
100
|
+
var_values = list(self.variations.get(variation_id, [])) + list(values)
|
|
101
|
+
self.variations[variation_id] = tuple(unique(var_values))
|
|
94
102
|
|
|
95
103
|
def _add_and_dedup_dicts(
|
|
96
104
|
self, *new_dicts: dict[str, str]
|
|
@@ -123,9 +131,9 @@ class Matrix(FrozenDict):
|
|
|
123
131
|
passing the corresponding ``with_matrix``, ``with_includes`` and
|
|
124
132
|
``with_excludes`` boolean filter parameters.
|
|
125
133
|
"""
|
|
126
|
-
|
|
134
|
+
all_variations = {}
|
|
127
135
|
if with_matrix:
|
|
128
|
-
|
|
136
|
+
all_variations = {k: list(v) for k, v in self.variations.items()}
|
|
129
137
|
|
|
130
138
|
for expand, directives in (
|
|
131
139
|
(with_includes, self.include),
|
|
@@ -134,9 +142,9 @@ class Matrix(FrozenDict):
|
|
|
134
142
|
if expand:
|
|
135
143
|
for value in directives:
|
|
136
144
|
for k, v in value.items():
|
|
137
|
-
|
|
145
|
+
all_variations.setdefault(k, []).append(v)
|
|
138
146
|
|
|
139
|
-
return {k: tuple(unique(v)) for k, v in
|
|
147
|
+
return {k: tuple(unique(v)) for k, v in all_variations.items()}
|
|
140
148
|
|
|
141
149
|
def product(
|
|
142
150
|
self, with_includes: bool = False, with_excludes: bool = False
|
|
@@ -148,17 +156,17 @@ class Matrix(FrozenDict):
|
|
|
148
156
|
|
|
149
157
|
Respects the order of variations and their values.
|
|
150
158
|
"""
|
|
151
|
-
|
|
159
|
+
all_variations = self.all_variations(
|
|
152
160
|
with_includes=with_includes, with_excludes=with_excludes
|
|
153
161
|
)
|
|
154
|
-
if not
|
|
162
|
+
if not all_variations:
|
|
155
163
|
return
|
|
156
164
|
yield from map(
|
|
157
165
|
dict,
|
|
158
166
|
itertools.product(
|
|
159
167
|
*(
|
|
160
168
|
tuple((variant_id, v) for v in variations)
|
|
161
|
-
for variant_id, variations in
|
|
169
|
+
for variant_id, variations in all_variations.items()
|
|
162
170
|
)
|
|
163
171
|
),
|
|
164
172
|
)
|
|
@@ -187,11 +195,11 @@ class Matrix(FrozenDict):
|
|
|
187
195
|
self.all_variations(
|
|
188
196
|
with_matrix=False, with_includes=True, with_excludes=True
|
|
189
197
|
)
|
|
190
|
-
).difference(self)
|
|
198
|
+
).difference(self.variations)
|
|
191
199
|
if unreferenced_keys:
|
|
192
200
|
raise ValueError(
|
|
193
201
|
f"Matrix exclude keys {list(unreferenced_keys)} does not match any "
|
|
194
|
-
f"{
|
|
202
|
+
f"{self.variations.keys()} key within the matrix"
|
|
195
203
|
)
|
|
196
204
|
|
|
197
205
|
# Reset the number of combinations.
|
|
@@ -202,7 +210,7 @@ class Matrix(FrozenDict):
|
|
|
202
210
|
|
|
203
211
|
# The matrix is empty, none of the include directive will match, so condider all
|
|
204
212
|
# directives as un-applicable.
|
|
205
|
-
if not self:
|
|
213
|
+
if not self.variations:
|
|
206
214
|
leftover_includes = list(self.include)
|
|
207
215
|
|
|
208
216
|
# Search for include directives that matches the original matrix variations
|
gha_utils/metadata.py
CHANGED
|
@@ -156,6 +156,7 @@ import json
|
|
|
156
156
|
import logging
|
|
157
157
|
import os
|
|
158
158
|
import re
|
|
159
|
+
import sys
|
|
159
160
|
import tomllib
|
|
160
161
|
from collections.abc import Iterable
|
|
161
162
|
from enum import StrEnum
|
|
@@ -164,8 +165,9 @@ from operator import itemgetter
|
|
|
164
165
|
from pathlib import Path
|
|
165
166
|
from random import randint
|
|
166
167
|
from re import escape
|
|
167
|
-
from typing import Any, Final,
|
|
168
|
+
from typing import Any, Final, cast
|
|
168
169
|
|
|
170
|
+
import gitignore_parser
|
|
169
171
|
from bumpversion.config import get_configuration # type: ignore[import-untyped]
|
|
170
172
|
from bumpversion.config.files import find_config_file # type: ignore[import-untyped]
|
|
171
173
|
from bumpversion.show import resolve_name # type: ignore[import-untyped]
|
|
@@ -196,6 +198,7 @@ SHORT_SHA_LENGTH = 7
|
|
|
196
198
|
depends on the size of the repository.
|
|
197
199
|
"""
|
|
198
200
|
|
|
201
|
+
GITIGNORE_PATH = Path(".gitignore")
|
|
199
202
|
|
|
200
203
|
NUITKA_BUILD_TARGETS = {
|
|
201
204
|
"linux-arm64": {
|
|
@@ -315,7 +318,7 @@ WorkflowEvent = StrEnum(
|
|
|
315
318
|
"""
|
|
316
319
|
|
|
317
320
|
|
|
318
|
-
Dialects = StrEnum("Dialects", ("github", "
|
|
321
|
+
Dialects = StrEnum("Dialects", ("github", "json"))
|
|
319
322
|
"""Dialects in which metadata can be formatted to."""
|
|
320
323
|
|
|
321
324
|
|
|
@@ -347,6 +350,75 @@ MYPY_VERSION_MIN: Final = (3, 8)
|
|
|
347
350
|
"""
|
|
348
351
|
|
|
349
352
|
|
|
353
|
+
# XXX Patch gitignore-parser to support Windows paths. Refs:
|
|
354
|
+
# https://github.com/mherrmann/gitignore_parser/issues/60
|
|
355
|
+
# https://github.com/mherrmann/gitignore_parser/pull/61
|
|
356
|
+
# XXX In the future, replace this with wcmatch once it supports gitignore files:
|
|
357
|
+
# https://github.com/facelessuser/wcmatch/issues/226
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
_OriginalIgnoreRule = gitignore_parser.IgnoreRule
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
class PatchedIgnoreRule(_OriginalIgnoreRule): # type: ignore[misc,valid-type]
|
|
364
|
+
"""Patch version of ``IgnoreRule`` to support Windows paths.
|
|
365
|
+
|
|
366
|
+
Taken from: https://github.com/mherrmann/gitignore_parser/pull/61/files
|
|
367
|
+
"""
|
|
368
|
+
|
|
369
|
+
@staticmethod
|
|
370
|
+
def _count_trailing_symbol(symbol: str, text: str) -> int:
|
|
371
|
+
"""Count the number of trailing characters in a string."""
|
|
372
|
+
count = 0
|
|
373
|
+
for char in reversed(str(text)):
|
|
374
|
+
if char == symbol:
|
|
375
|
+
count += 1
|
|
376
|
+
else:
|
|
377
|
+
break
|
|
378
|
+
return count
|
|
379
|
+
|
|
380
|
+
def match(self, abs_path: str | Path) -> bool:
|
|
381
|
+
matched = False
|
|
382
|
+
if self.base_path:
|
|
383
|
+
rel_path = (
|
|
384
|
+
gitignore_parser._normalize_path(abs_path)
|
|
385
|
+
.relative_to(self.base_path)
|
|
386
|
+
.as_posix()
|
|
387
|
+
)
|
|
388
|
+
else:
|
|
389
|
+
rel_path = gitignore_parser._normalize_path(abs_path).as_posix()
|
|
390
|
+
# Path() strips the trailing following symbols on windows, so we need to
|
|
391
|
+
# preserve it: ' ', '.'
|
|
392
|
+
if sys.platform.startswith("win"):
|
|
393
|
+
rel_path += " " * self._count_trailing_symbol(" ", abs_path)
|
|
394
|
+
rel_path += "." * self._count_trailing_symbol(".", abs_path)
|
|
395
|
+
# Path() strips the trailing slash, so we need to preserve it
|
|
396
|
+
# in case of directory-only negation
|
|
397
|
+
if self.negation and type(abs_path) is str and abs_path[-1] == "/":
|
|
398
|
+
rel_path += "/"
|
|
399
|
+
if rel_path.startswith("./"):
|
|
400
|
+
rel_path = rel_path[2:]
|
|
401
|
+
if re.search(self.regex, rel_path):
|
|
402
|
+
matched = True
|
|
403
|
+
return matched
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
gitignore_parser.IgnoreRule = PatchedIgnoreRule
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
class JSONMetadata(json.JSONEncoder):
|
|
410
|
+
"""Custom JSON encoder for metadata serialization."""
|
|
411
|
+
|
|
412
|
+
def default(self, o: Any) -> Any:
|
|
413
|
+
if isinstance(o, Matrix):
|
|
414
|
+
return o.matrix()
|
|
415
|
+
|
|
416
|
+
if isinstance(o, Path):
|
|
417
|
+
return str(o)
|
|
418
|
+
|
|
419
|
+
return super().default(o)
|
|
420
|
+
|
|
421
|
+
|
|
350
422
|
class Metadata:
|
|
351
423
|
"""Metadata class."""
|
|
352
424
|
|
|
@@ -577,11 +649,15 @@ class Metadata:
|
|
|
577
649
|
events.
|
|
578
650
|
|
|
579
651
|
.. seealso::
|
|
580
|
-
|
|
581
652
|
- https://stackoverflow.com/a/67204539
|
|
582
653
|
- https://stackoverflow.com/a/62953566
|
|
583
654
|
- https://stackoverflow.com/a/61861763
|
|
584
655
|
|
|
656
|
+
.. seealso::
|
|
657
|
+
Pull request events on GitHub are a bit complex, see: `The Many SHAs of a
|
|
658
|
+
GitHub Pull Request
|
|
659
|
+
<https://www.kenmuse.com/blog/the-many-shas-of-a-github-pull-request/>`_.
|
|
660
|
+
|
|
585
661
|
.. todo::
|
|
586
662
|
Refactor so we can get rid of ``self.github_context``. Maybe there's enough
|
|
587
663
|
metadata lying around in the environment variables that we can inspect the
|
|
@@ -642,11 +718,7 @@ class Metadata:
|
|
|
642
718
|
@cached_property
|
|
643
719
|
def new_commits_hash(self) -> tuple[str, ...] | None:
|
|
644
720
|
"""List all hashes of new commits."""
|
|
645
|
-
return
|
|
646
|
-
cast(tuple[str, ...], self.new_commits_matrix["commit"])
|
|
647
|
-
if self.new_commits_matrix
|
|
648
|
-
else None
|
|
649
|
-
)
|
|
721
|
+
return self.new_commits_matrix["commit"] if self.new_commits_matrix else None
|
|
650
722
|
|
|
651
723
|
@cached_property
|
|
652
724
|
def release_commits(self) -> tuple[Commit, ...] | None:
|
|
@@ -680,13 +752,16 @@ class Metadata:
|
|
|
680
752
|
def release_commits_hash(self) -> tuple[str, ...] | None:
|
|
681
753
|
"""List all hashes of release commits."""
|
|
682
754
|
return (
|
|
683
|
-
|
|
755
|
+
self.release_commits_matrix["commit"]
|
|
684
756
|
if self.release_commits_matrix
|
|
685
757
|
else None
|
|
686
758
|
)
|
|
687
759
|
|
|
688
|
-
@
|
|
689
|
-
def
|
|
760
|
+
@cached_property
|
|
761
|
+
def gitignore_exists(self) -> bool:
|
|
762
|
+
return GITIGNORE_PATH.is_file()
|
|
763
|
+
|
|
764
|
+
def glob_files(self, *patterns: str) -> list[Path]:
|
|
690
765
|
"""Return all file path matching the ``patterns``.
|
|
691
766
|
|
|
692
767
|
Patterns are glob patterns supporting ``**`` for recursive search, and ``!``
|
|
@@ -695,46 +770,77 @@ class Metadata:
|
|
|
695
770
|
All directories are traversed, whether they are hidden (i.e. starting with a
|
|
696
771
|
dot ``.``) or not, including symlinks.
|
|
697
772
|
|
|
698
|
-
|
|
773
|
+
Skips:
|
|
774
|
+
|
|
775
|
+
- files which does not exists
|
|
776
|
+
- directories
|
|
777
|
+
- broken symlinks
|
|
778
|
+
- files matching patterns specified by ``.gitignore`` file
|
|
779
|
+
|
|
780
|
+
Returns both hidden and non-hidden files.
|
|
699
781
|
|
|
700
782
|
All files are normalized to their absolute path, so that duplicates produced by
|
|
701
783
|
symlinks are ignored.
|
|
702
784
|
|
|
703
|
-
|
|
785
|
+
File path are returned as relative to the current working directory if
|
|
786
|
+
possible, or as absolute path otherwise.
|
|
787
|
+
|
|
788
|
+
The resulting list of file paths is sorted.
|
|
704
789
|
"""
|
|
790
|
+
current_dir = Path.cwd()
|
|
705
791
|
seen = set()
|
|
792
|
+
|
|
793
|
+
# If the .gitignore file exists, we parse it to filter out ignored files.
|
|
794
|
+
gitignore = None
|
|
795
|
+
if self.gitignore_exists:
|
|
796
|
+
logging.debug(f"Load {GITIGNORE_PATH} to filter out ignored files.")
|
|
797
|
+
gitignore = gitignore_parser.parse_gitignore(GITIGNORE_PATH)
|
|
798
|
+
|
|
706
799
|
for file_path in iglob(
|
|
707
800
|
patterns,
|
|
708
801
|
flags=NODIR | GLOBSTAR | DOTGLOB | GLOBTILDE | BRACE | FOLLOW | NEGATE,
|
|
709
802
|
):
|
|
710
803
|
# Normalize the path to avoid duplicates.
|
|
711
804
|
try:
|
|
712
|
-
|
|
713
|
-
# Skip files that do not
|
|
805
|
+
absolute_path = Path(file_path).resolve(strict=True)
|
|
806
|
+
# Skip files that do not exists and broken symlinks.
|
|
714
807
|
except OSError:
|
|
715
|
-
logging.warning(
|
|
716
|
-
f"Skipping non-existing file / broken symlink: {file_path}"
|
|
717
|
-
)
|
|
808
|
+
logging.warning(f"Skip non-existing file / broken symlink: {file_path}")
|
|
718
809
|
continue
|
|
810
|
+
|
|
811
|
+
# Simplify the path by trying to make it relative to the current location.
|
|
812
|
+
normalized_path = absolute_path
|
|
813
|
+
try:
|
|
814
|
+
normalized_path = absolute_path.relative_to(current_dir)
|
|
815
|
+
except ValueError:
|
|
816
|
+
# If the file is not relative to the current directory, keep its
|
|
817
|
+
# absolute path.
|
|
818
|
+
logging.debug(
|
|
819
|
+
f"{absolute_path} is not relative to {current_dir}. "
|
|
820
|
+
"Keeping the path absolute."
|
|
821
|
+
)
|
|
822
|
+
|
|
719
823
|
if normalized_path in seen:
|
|
720
|
-
logging.debug(f"
|
|
824
|
+
logging.debug(f"Skip duplicate file: {normalized_path}")
|
|
721
825
|
continue
|
|
722
|
-
seen.add(normalized_path)
|
|
723
|
-
yield normalized_path
|
|
724
826
|
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
827
|
+
# Skip files that are ignored by .gitignore.
|
|
828
|
+
if gitignore and gitignore(file_path):
|
|
829
|
+
logging.debug(f"Skip file matching {GITIGNORE_PATH}: {file_path}")
|
|
830
|
+
continue
|
|
831
|
+
|
|
832
|
+
seen.add(normalized_path)
|
|
833
|
+
return sorted(seen)
|
|
728
834
|
|
|
729
835
|
@cached_property
|
|
730
|
-
def python_files(self) ->
|
|
836
|
+
def python_files(self) -> list[Path]:
|
|
731
837
|
"""Returns a list of python files."""
|
|
732
|
-
|
|
838
|
+
return self.glob_files("**/*.py", "!.venv/**")
|
|
733
839
|
|
|
734
840
|
@cached_property
|
|
735
|
-
def doc_files(self) ->
|
|
841
|
+
def doc_files(self) -> list[Path]:
|
|
736
842
|
"""Returns a list of doc files."""
|
|
737
|
-
|
|
843
|
+
return self.glob_files("**/*.{md,markdown,rst,tex}", "!.venv/**")
|
|
738
844
|
|
|
739
845
|
@property
|
|
740
846
|
def is_python_project(self):
|
|
@@ -844,7 +950,7 @@ class Metadata:
|
|
|
844
950
|
return None
|
|
845
951
|
|
|
846
952
|
@cached_property
|
|
847
|
-
def blacken_docs_params(self) ->
|
|
953
|
+
def blacken_docs_params(self) -> str | None:
|
|
848
954
|
"""Generates ``blacken-docs`` parameters.
|
|
849
955
|
|
|
850
956
|
`Blacken-docs reuses Black's --target-version pyXY parameters
|
|
@@ -867,7 +973,7 @@ class Metadata:
|
|
|
867
973
|
<https://github.com/psf/black/issues/751#issuecomment-473066811>`_.
|
|
868
974
|
"""
|
|
869
975
|
if self.py_target_versions:
|
|
870
|
-
return
|
|
976
|
+
return " ".join(
|
|
871
977
|
f"--target-version py{version.major}{version.minor}"
|
|
872
978
|
for version in self.py_target_versions
|
|
873
979
|
)
|
|
@@ -1185,7 +1291,7 @@ class Metadata:
|
|
|
1185
1291
|
for variations in matrix.solve():
|
|
1186
1292
|
# We will re-attach back this binary name to the with an include directive,
|
|
1187
1293
|
# so we need a copy the main variants it corresponds to.
|
|
1188
|
-
bin_name_include = {k: variations[k] for k in matrix}
|
|
1294
|
+
bin_name_include = {k: variations[k] for k in matrix.variations}
|
|
1189
1295
|
bin_name_include["bin_name"] = (
|
|
1190
1296
|
"{cli_id}-{target}-{short_sha}.{extension}"
|
|
1191
1297
|
).format(**variations)
|
|
@@ -1316,8 +1422,8 @@ class Metadata:
|
|
|
1316
1422
|
delimiter = f"ghadelimiter_{randint(10**8, (10**9) - 1)}"
|
|
1317
1423
|
content += f"{env_name}<<{delimiter}\n{env_value}\n{delimiter}\n"
|
|
1318
1424
|
else:
|
|
1319
|
-
assert dialect == Dialects.
|
|
1320
|
-
content =
|
|
1425
|
+
assert dialect == Dialects.json
|
|
1426
|
+
content = json.dumps(metadata, cls=JSONMetadata, indent=2)
|
|
1321
1427
|
|
|
1322
1428
|
logging.debug(f"Formatted metadata:\n{content}")
|
|
1323
1429
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gha-utils
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.18.1
|
|
4
4
|
Summary: ⚙️ CLI helpers for GitHub Actions + reuseable workflows
|
|
5
5
|
Author-email: Kevin Deldycke <kevin@deldycke.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/kdeldycke/workflows
|
|
@@ -48,13 +48,14 @@ Requires-Dist: boltons>=24.0.0
|
|
|
48
48
|
Requires-Dist: bump-my-version<1.1.1,>=0.32.2
|
|
49
49
|
Requires-Dist: click-extra~=5.0.2
|
|
50
50
|
Requires-Dist: extra-platforms~=3.2.0
|
|
51
|
+
Requires-Dist: gitignore-parser~=0.1.12
|
|
51
52
|
Requires-Dist: packaging~=25.0
|
|
52
53
|
Requires-Dist: PyDriller~=2.6
|
|
53
54
|
Requires-Dist: pyproject-metadata~=0.9.0
|
|
54
55
|
Requires-Dist: pyyaml~=6.0.0
|
|
55
56
|
Requires-Dist: wcmatch>=8.5
|
|
56
57
|
Provides-Extra: test
|
|
57
|
-
Requires-Dist: coverage[toml]~=7.
|
|
58
|
+
Requires-Dist: coverage[toml]~=7.10.0; extra == "test"
|
|
58
59
|
Requires-Dist: pytest~=8.4.0; extra == "test"
|
|
59
60
|
Requires-Dist: pytest-cases~=3.9.1; extra == "test"
|
|
60
61
|
Requires-Dist: pytest-cov~=6.2.1; extra == "test"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
gha_utils/__init__.py,sha256=o9J48CI8G5T4jmGN-02kTDdQbhFJhuKtzAu2qUTN3GA,866
|
|
2
|
+
gha_utils/__main__.py,sha256=Dck9BjpLXmIRS83k0mghAMcYVYiMiFLltQdfRuMSP_Q,1703
|
|
3
|
+
gha_utils/changelog.py,sha256=JR7iQrWjLoIOpVNe6iXQSyEii82_hM_zrYpR7QO_Uxo,5777
|
|
4
|
+
gha_utils/cli.py,sha256=WME8vPpWU8ZCe-Y53702Wc6Do5rVliYrOaruDcGOUpY,15299
|
|
5
|
+
gha_utils/mailmap.py,sha256=g3LQiPNjHsAgCbEYOJcQwdlXqxzmFh697vv2sxHZq-s,7014
|
|
6
|
+
gha_utils/matrix.py,sha256=sZq5JLBZ0pRokSXoY5r6zHxWwprilJKlbbzXLjMXfWU,12380
|
|
7
|
+
gha_utils/metadata.py,sha256=HwSjuTl1smjPVLJDtwdBzkqp4iReBIGsZXTNw6VlGt4,56133
|
|
8
|
+
gha_utils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
gha_utils/test_plan.py,sha256=AE8Mf1vSQG5EZTytoTts-gzMwUg2Zy21gUwkMlzXT94,13394
|
|
10
|
+
gha_utils-4.18.1.dist-info/METADATA,sha256=OAuMKGhIkibCE3_VM_Ly53orWBoBtZWmRgfDaWaqCZM,21301
|
|
11
|
+
gha_utils-4.18.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
12
|
+
gha_utils-4.18.1.dist-info/entry_points.txt,sha256=8bJOwQYf9ZqsLhBR6gUCzvwLNI9f8tiiBrJ3AR0EK4o,54
|
|
13
|
+
gha_utils-4.18.1.dist-info/top_level.txt,sha256=C94Blb61YkkyPBwCdM3J_JPDjWH0lnKa5nGZeZ5M6yE,10
|
|
14
|
+
gha_utils-4.18.1.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
gha_utils/__init__.py,sha256=USpmOfv62pqoE9bNW_qKSAekPiCNcPTqNFgpuPn6BtQ,866
|
|
2
|
-
gha_utils/__main__.py,sha256=Dck9BjpLXmIRS83k0mghAMcYVYiMiFLltQdfRuMSP_Q,1703
|
|
3
|
-
gha_utils/changelog.py,sha256=JR7iQrWjLoIOpVNe6iXQSyEii82_hM_zrYpR7QO_Uxo,5777
|
|
4
|
-
gha_utils/cli.py,sha256=1xx7gG0fXwqHQJSQWzBLEKO1p9rAnFnkcuPnmqPS5M4,15296
|
|
5
|
-
gha_utils/mailmap.py,sha256=g3LQiPNjHsAgCbEYOJcQwdlXqxzmFh697vv2sxHZq-s,7014
|
|
6
|
-
gha_utils/matrix.py,sha256=_afJD0K-xZLNxwykVnUhD0Gj9cdO0Z43g3VHa-q_tkI,11941
|
|
7
|
-
gha_utils/metadata.py,sha256=o7vyW8d97PGtoGZ1pyvJQbeKl86mRRfbxJnEo5dxUos,52322
|
|
8
|
-
gha_utils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
gha_utils/test_plan.py,sha256=AE8Mf1vSQG5EZTytoTts-gzMwUg2Zy21gUwkMlzXT94,13394
|
|
10
|
-
gha_utils-4.17.9.dist-info/METADATA,sha256=xcDI8qdaaaJGxnW8DrV6ImnZkrYzWQ1QBit9-WgVmW4,21260
|
|
11
|
-
gha_utils-4.17.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
12
|
-
gha_utils-4.17.9.dist-info/entry_points.txt,sha256=8bJOwQYf9ZqsLhBR6gUCzvwLNI9f8tiiBrJ3AR0EK4o,54
|
|
13
|
-
gha_utils-4.17.9.dist-info/top_level.txt,sha256=C94Blb61YkkyPBwCdM3J_JPDjWH0lnKa5nGZeZ5M6yE,10
|
|
14
|
-
gha_utils-4.17.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|