autopkg-wrapper 2024.6.1__tar.gz → 2024.8.1__tar.gz
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.
- {autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/PKG-INFO +3 -1
- {autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/README.md +2 -0
- autopkg_wrapper-2024.8.1/autopkg_wrapper/__init__.py +1 -0
- {autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/autopkg_wrapper/autopkg_wrapper.py +117 -33
- {autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/autopkg_wrapper/utils/args.py +32 -5
- {autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/pyproject.toml +1 -1
- autopkg_wrapper-2024.6.1/autopkg_wrapper/__init__.py +0 -1
- {autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/LICENSE +0 -0
- {autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/autopkg_wrapper/notifier/__init__.py +0 -0
- {autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/autopkg_wrapper/notifier/slack.py +0 -0
- {autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/autopkg_wrapper/utils/__init__.py +0 -0
- {autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/autopkg_wrapper/utils/git_functions.py +0 -0
- {autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/autopkg_wrapper/utils/logging.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: autopkg-wrapper
|
|
3
|
-
Version: 2024.
|
|
3
|
+
Version: 2024.8.1
|
|
4
4
|
Summary: A package used to execute some autopkg functions, primarily within the context of a GitHub Actions runner.
|
|
5
5
|
Home-page: https://github.com/smithjw/autopkg-wrapper
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -42,6 +42,8 @@ pip install autopkg-wrapper
|
|
|
42
42
|
--branch-name BRANCH_NAME Branch name to be used where recipe overrides have failed their trust verification and need to be updated.
|
|
43
43
|
By default, this will be in the format of "fix/update_trust_information/YYYY-MM-DDTHH-MM-SS"
|
|
44
44
|
--create-pr If enabled, autopkg_wrapper will open a PR for updated trust information
|
|
45
|
+
--autopkg-prefs AW_AUTOPKG_PREFS_FILE
|
|
46
|
+
Path to the autopkg preferences you'd like to use
|
|
45
47
|
--autopkg-overrides-repo-path AUTOPKG_OVERRIDES_REPO_PATH
|
|
46
48
|
The path on disk to the git repository containing the autopkg overrides directory. If none is provided, we will try to determine it for you.
|
|
47
49
|
```
|
|
@@ -20,6 +20,8 @@ pip install autopkg-wrapper
|
|
|
20
20
|
--branch-name BRANCH_NAME Branch name to be used where recipe overrides have failed their trust verification and need to be updated.
|
|
21
21
|
By default, this will be in the format of "fix/update_trust_information/YYYY-MM-DDTHH-MM-SS"
|
|
22
22
|
--create-pr If enabled, autopkg_wrapper will open a PR for updated trust information
|
|
23
|
+
--autopkg-prefs AW_AUTOPKG_PREFS_FILE
|
|
24
|
+
Path to the autopkg preferences you'd like to use
|
|
23
25
|
--autopkg-overrides-repo-path AUTOPKG_OVERRIDES_REPO_PATH
|
|
24
26
|
The path on disk to the git repository containing the autopkg overrides directory. If none is provided, we will try to determine it for you.
|
|
25
27
|
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2024.8.1"
|
|
@@ -33,10 +33,14 @@ class Recipe(object):
|
|
|
33
33
|
|
|
34
34
|
return name
|
|
35
35
|
|
|
36
|
-
def verify_trust_info(self,
|
|
37
|
-
verbose_output = ["-vvvv"]
|
|
36
|
+
def verify_trust_info(self, args):
|
|
37
|
+
verbose_output = ["-vvvv"] if args.debug else None
|
|
38
|
+
prefs_file = (
|
|
39
|
+
["--prefs", args.autopkg_prefs.as_posix()] if args.autopkg_prefs else None
|
|
40
|
+
)
|
|
38
41
|
cmd = ["/usr/local/bin/autopkg", "verify-trust-info", self.filename]
|
|
39
|
-
cmd = cmd + verbose_output if
|
|
42
|
+
cmd = cmd + verbose_output if verbose_output else cmd
|
|
43
|
+
cmd = cmd + prefs_file if prefs_file else cmd
|
|
40
44
|
cmd = " ".join(cmd)
|
|
41
45
|
logging.debug(f"cmd: {str(cmd)}")
|
|
42
46
|
|
|
@@ -53,8 +57,12 @@ class Recipe(object):
|
|
|
53
57
|
self.verified = False
|
|
54
58
|
return self.verified
|
|
55
59
|
|
|
56
|
-
def update_trust_info(self):
|
|
60
|
+
def update_trust_info(self, args):
|
|
61
|
+
prefs_file = (
|
|
62
|
+
["--prefs", args.autopkg_prefs.as_posix()] if args.autopkg_prefs else None
|
|
63
|
+
)
|
|
57
64
|
cmd = ["/usr/local/bin/autopkg", "update-trust-info", self.filename]
|
|
65
|
+
cmd = cmd + prefs_file if prefs_file else cmd
|
|
58
66
|
cmd = " ".join(cmd)
|
|
59
67
|
logging.debug(f"cmd: {str(cmd)}")
|
|
60
68
|
|
|
@@ -80,7 +88,7 @@ class Recipe(object):
|
|
|
80
88
|
|
|
81
89
|
return {"imported": imported_items, "failed": failed_items}
|
|
82
90
|
|
|
83
|
-
def run(self,
|
|
91
|
+
def run(self, args):
|
|
84
92
|
if self.verified is False:
|
|
85
93
|
self.error = True
|
|
86
94
|
self.results["failed"] = True
|
|
@@ -95,8 +103,24 @@ class Recipe(object):
|
|
|
95
103
|
report.touch(exist_ok=True)
|
|
96
104
|
|
|
97
105
|
try:
|
|
98
|
-
|
|
99
|
-
|
|
106
|
+
prefs_file = (
|
|
107
|
+
["--prefs", args.autopkg_prefs.as_posix()]
|
|
108
|
+
if args.autopkg_prefs
|
|
109
|
+
else None
|
|
110
|
+
)
|
|
111
|
+
verbose_output = ["-vvvv"] if args.debug else None
|
|
112
|
+
post_processor_cmd = (
|
|
113
|
+
list(
|
|
114
|
+
chain.from_iterable(
|
|
115
|
+
[
|
|
116
|
+
("--post", processor)
|
|
117
|
+
for processor in self.post_processors
|
|
118
|
+
]
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
if self.post_processors
|
|
122
|
+
else None
|
|
123
|
+
)
|
|
100
124
|
cmd = [
|
|
101
125
|
"/usr/local/bin/autopkg",
|
|
102
126
|
"run",
|
|
@@ -105,7 +129,8 @@ class Recipe(object):
|
|
|
105
129
|
str(report),
|
|
106
130
|
]
|
|
107
131
|
cmd = cmd + post_processor_cmd if post_processor_cmd else cmd
|
|
108
|
-
cmd = cmd + verbose_output if
|
|
132
|
+
cmd = cmd + verbose_output if verbose_output else cmd
|
|
133
|
+
cmd = cmd + prefs_file if prefs_file else cmd
|
|
109
134
|
cmd = " ".join(cmd)
|
|
110
135
|
|
|
111
136
|
logging.debug(f"cmd: {str(cmd)}")
|
|
@@ -129,12 +154,28 @@ def get_override_repo_info(args):
|
|
|
129
154
|
|
|
130
155
|
else:
|
|
131
156
|
logging.debug("Trying to determine overrides dir from default paths")
|
|
132
|
-
user_home = Path.home()
|
|
133
|
-
autopkg_prefs_path = user_home / "Library/Preferences/com.github.autopkg.plist"
|
|
134
157
|
|
|
135
|
-
if
|
|
136
|
-
|
|
158
|
+
if args.autopkg_prefs:
|
|
159
|
+
autopkg_prefs_path = Path(args.autopkg_prefs).resolve()
|
|
137
160
|
|
|
161
|
+
if autopkg_prefs_path.suffix == ".json":
|
|
162
|
+
with open(autopkg_prefs_path, "r") as f:
|
|
163
|
+
autopkg_prefs = json.load(f)
|
|
164
|
+
elif autopkg_prefs_path.suffix == ".plist":
|
|
165
|
+
autopkg_prefs = plistlib.loads(autopkg_prefs_path.read_bytes())
|
|
166
|
+
else:
|
|
167
|
+
user_home = Path.home()
|
|
168
|
+
autopkg_prefs_path = (
|
|
169
|
+
user_home / "Library/Preferences/com.github.autopkg.plist"
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
if autopkg_prefs_path.is_file():
|
|
173
|
+
autopkg_prefs = plistlib.loads(
|
|
174
|
+
autopkg_prefs_path.resolve().read_bytes()
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
logging.debug(f"autopkg prefs path: {autopkg_prefs_path}")
|
|
178
|
+
logging.debug(f"autopkg prefs: {autopkg_prefs}")
|
|
138
179
|
recipe_override_dirs = Path(autopkg_prefs["RECIPE_OVERRIDE_DIRS"]).resolve()
|
|
139
180
|
|
|
140
181
|
if Path(recipe_override_dirs / ".git").is_dir():
|
|
@@ -146,7 +187,9 @@ def get_override_repo_info(args):
|
|
|
146
187
|
|
|
147
188
|
override_repo_git_work_tree = f"--work-tree={override_repo_path}"
|
|
148
189
|
override_repo_git_git_dir = f"--git-dir={override_repo_path / ".git"}"
|
|
149
|
-
override_repo_url, override_repo_remote_ref = git.get_repo_info(
|
|
190
|
+
override_repo_url, override_repo_remote_ref = git.get_repo_info(
|
|
191
|
+
override_repo_git_git_dir
|
|
192
|
+
)
|
|
150
193
|
|
|
151
194
|
git_info = {
|
|
152
195
|
"override_repo_path": override_repo_path,
|
|
@@ -179,22 +222,28 @@ def update_recipe_repo(recipe, git_info, disable_recipe_trust_check, args):
|
|
|
179
222
|
current_branch = git.get_current_branch(git_info)
|
|
180
223
|
|
|
181
224
|
if args.disable_git_commands:
|
|
182
|
-
logging.info(
|
|
225
|
+
logging.info(
|
|
226
|
+
"Not runing git commands as --disable-git-commands has been set"
|
|
227
|
+
)
|
|
183
228
|
return
|
|
184
229
|
|
|
185
230
|
if current_branch != git_info["override_trust_branch"]:
|
|
186
|
-
logging.debug(
|
|
231
|
+
logging.debug(
|
|
232
|
+
f"override_trust_branch: {git_info["override_trust_branch"]}"
|
|
233
|
+
)
|
|
187
234
|
git.create_branch(git_info)
|
|
188
235
|
|
|
189
236
|
git.stage_recipe(git_info)
|
|
190
|
-
git.commit_recipe(
|
|
237
|
+
git.commit_recipe(
|
|
238
|
+
git_info, message=f"Updating Trust Info for {recipe.name}"
|
|
239
|
+
)
|
|
191
240
|
git.pull_branch(git_info)
|
|
192
241
|
git.push_branch(git_info)
|
|
193
242
|
|
|
194
243
|
return
|
|
195
244
|
|
|
196
245
|
|
|
197
|
-
def parse_recipe_list(recipes, recipe_file, post_processors):
|
|
246
|
+
def parse_recipe_list(recipes, recipe_file, post_processors, args):
|
|
198
247
|
"""Parsing list of recipes into a common format"""
|
|
199
248
|
recipe_list = None
|
|
200
249
|
|
|
@@ -214,10 +263,14 @@ def parse_recipe_list(recipes, recipe_file, post_processors):
|
|
|
214
263
|
elif isinstance(recipes, str):
|
|
215
264
|
if recipes.find(",") != -1:
|
|
216
265
|
# Assuming recipes separated by commas
|
|
217
|
-
recipe_list = [
|
|
266
|
+
recipe_list = [
|
|
267
|
+
recipe.strip() for recipe in recipes.split(",") if recipe
|
|
268
|
+
]
|
|
218
269
|
else:
|
|
219
270
|
# Assuming recipes separated by space
|
|
220
|
-
recipe_list = [
|
|
271
|
+
recipe_list = [
|
|
272
|
+
recipe.strip() for recipe in recipes.split(" ") if recipe
|
|
273
|
+
]
|
|
221
274
|
|
|
222
275
|
if recipe_list is None:
|
|
223
276
|
logging.error(
|
|
@@ -233,6 +286,7 @@ def parse_recipe_list(recipes, recipe_file, post_processors):
|
|
|
233
286
|
|
|
234
287
|
return recipe_map
|
|
235
288
|
|
|
289
|
+
|
|
236
290
|
def parse_post_processors(post_processors):
|
|
237
291
|
"""Parsing list of post_processors"""
|
|
238
292
|
logging.debug("Parsing post processors")
|
|
@@ -247,32 +301,42 @@ def parse_post_processors(post_processors):
|
|
|
247
301
|
case list():
|
|
248
302
|
post_processors_list = post_processors
|
|
249
303
|
case str() if post_processors.find(",") != -1:
|
|
250
|
-
post_processors_list = [
|
|
304
|
+
post_processors_list = [
|
|
305
|
+
post_processor.strip()
|
|
306
|
+
for post_processor in post_processors.split(",")
|
|
307
|
+
if post_processor.strip()
|
|
308
|
+
]
|
|
251
309
|
case str():
|
|
252
|
-
post_processors_list = [
|
|
310
|
+
post_processors_list = [
|
|
311
|
+
post_processor.strip()
|
|
312
|
+
for post_processor in post_processors.split(" ")
|
|
313
|
+
if post_processor.strip()
|
|
314
|
+
]
|
|
253
315
|
|
|
254
|
-
logging.info(
|
|
316
|
+
logging.info(
|
|
317
|
+
f"Post Processors List: {post_processors_list}"
|
|
318
|
+
) if post_processors_list else None
|
|
255
319
|
|
|
256
320
|
return post_processors_list
|
|
257
321
|
|
|
258
322
|
|
|
259
|
-
def process_recipe(recipe, disable_recipe_trust_check,
|
|
323
|
+
def process_recipe(recipe, disable_recipe_trust_check, args):
|
|
260
324
|
if disable_recipe_trust_check:
|
|
261
325
|
logging.debug("Setting Recipe verification to None")
|
|
262
326
|
recipe.verified = None
|
|
263
327
|
else:
|
|
264
328
|
logging.debug("Checking Recipe verification")
|
|
265
|
-
recipe.verify_trust_info(
|
|
329
|
+
recipe.verify_trust_info(args)
|
|
266
330
|
|
|
267
331
|
match recipe.verified:
|
|
268
332
|
case False | None if disable_recipe_trust_check:
|
|
269
333
|
logging.debug("Running Recipe without verification")
|
|
270
|
-
recipe.run(
|
|
334
|
+
recipe.run(args)
|
|
271
335
|
case True:
|
|
272
336
|
logging.debug("Running Recipe after successful verification")
|
|
273
|
-
recipe.run(
|
|
337
|
+
recipe.run(args)
|
|
274
338
|
case False:
|
|
275
|
-
recipe.update_trust_info()
|
|
339
|
+
recipe.update_trust_info(args)
|
|
276
340
|
|
|
277
341
|
return recipe
|
|
278
342
|
|
|
@@ -285,15 +349,35 @@ def main():
|
|
|
285
349
|
override_repo_info = get_override_repo_info(args)
|
|
286
350
|
|
|
287
351
|
post_processors_list = parse_post_processors(post_processors=args.post_processors)
|
|
288
|
-
recipe_list = parse_recipe_list(
|
|
352
|
+
recipe_list = parse_recipe_list(
|
|
353
|
+
recipes=args.recipes,
|
|
354
|
+
recipe_file=args.recipe_file,
|
|
355
|
+
post_processors=post_processors_list,
|
|
356
|
+
args=args,
|
|
357
|
+
)
|
|
289
358
|
|
|
290
359
|
for recipe in recipe_list:
|
|
291
360
|
logging.info(f"Processing Recipe: {recipe.name}")
|
|
292
|
-
process_recipe(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
361
|
+
process_recipe(
|
|
362
|
+
recipe=recipe,
|
|
363
|
+
disable_recipe_trust_check=args.disable_recipe_trust_check,
|
|
364
|
+
args=args,
|
|
365
|
+
)
|
|
366
|
+
update_recipe_repo(
|
|
367
|
+
git_info=override_repo_info,
|
|
368
|
+
recipe=recipe,
|
|
369
|
+
disable_recipe_trust_check=args.disable_recipe_trust_check,
|
|
370
|
+
args=args,
|
|
371
|
+
)
|
|
372
|
+
slack.send_notification(
|
|
373
|
+
recipe=recipe, token=args.slack_token
|
|
374
|
+
) if args.slack_token else None
|
|
375
|
+
|
|
376
|
+
recipe.pr_url = (
|
|
377
|
+
git.create_pull_request(git_info=override_repo_info, recipe=recipe)
|
|
378
|
+
if args.create_pr
|
|
379
|
+
else None
|
|
380
|
+
)
|
|
297
381
|
|
|
298
382
|
|
|
299
383
|
if __name__ == "__main__":
|
|
@@ -14,6 +14,7 @@ def validate_file(arg):
|
|
|
14
14
|
message = f"Error! This is not valid file: {arg}"
|
|
15
15
|
raise argparse.ArgumentTypeError(message)
|
|
16
16
|
|
|
17
|
+
|
|
17
18
|
def validate_directory(arg):
|
|
18
19
|
dir_path = Path(arg).resolve()
|
|
19
20
|
dir_exists = dir_path.is_dir()
|
|
@@ -24,14 +25,25 @@ def validate_directory(arg):
|
|
|
24
25
|
message = f"Error! This is not valid directory: {arg}"
|
|
25
26
|
raise argparse.ArgumentTypeError(message)
|
|
26
27
|
|
|
28
|
+
|
|
27
29
|
def validate_bool(arg):
|
|
28
30
|
if isinstance(arg, bool):
|
|
29
31
|
return arg
|
|
30
|
-
elif isinstance(arg, str) and arg.lower() in [
|
|
32
|
+
elif isinstance(arg, str) and arg.lower() in ["0", "false", "no", "f"]:
|
|
31
33
|
return False
|
|
32
|
-
elif isinstance(arg, str) and arg.lower() in [
|
|
34
|
+
elif isinstance(arg, str) and arg.lower() in ["1", "true", "yes", "t"]:
|
|
33
35
|
return True
|
|
34
36
|
|
|
37
|
+
|
|
38
|
+
def find_github_token():
|
|
39
|
+
if os.getenv("GITHUB_TOKEN", None):
|
|
40
|
+
return os.getenv("GITHUB_TOKEN")
|
|
41
|
+
elif os.getenv("GH_TOKEN", None):
|
|
42
|
+
return os.getenv("GH_TOKEN")
|
|
43
|
+
else:
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
|
|
35
47
|
def setup_args():
|
|
36
48
|
parser = argparse.ArgumentParser(description="Run autopkg recipes")
|
|
37
49
|
recipe_arguments = parser.add_mutually_exclusive_group()
|
|
@@ -78,11 +90,18 @@ def setup_args():
|
|
|
78
90
|
If this option is used, git commands won't be run
|
|
79
91
|
""",
|
|
80
92
|
)
|
|
81
|
-
parser.add_argument(
|
|
82
|
-
|
|
93
|
+
parser.add_argument(
|
|
94
|
+
"--slack-token",
|
|
95
|
+
default=os.getenv("SLACK_WEBHOOK_TOKEN", None),
|
|
96
|
+
help=argparse.SUPPRESS,
|
|
97
|
+
)
|
|
98
|
+
parser.add_argument("--github-token", default=find_github_token())
|
|
83
99
|
parser.add_argument(
|
|
84
100
|
"--branch-name",
|
|
85
|
-
default=os.getenv(
|
|
101
|
+
default=os.getenv(
|
|
102
|
+
"AW_TRUST_BRANCH",
|
|
103
|
+
f"fix/update_trust_information/{datetime.now().strftime("%Y-%m-%dT%H-%M-%S")}",
|
|
104
|
+
),
|
|
86
105
|
help="""
|
|
87
106
|
Branch name to be used recipe overrides have failed their trust verification and need to be updated.
|
|
88
107
|
By default, this will be in the format of \"fix/update_trust_information/YYYY-MM-DDTHH-MM-SS\"
|
|
@@ -111,5 +130,13 @@ def setup_args():
|
|
|
111
130
|
One or more autopkg post processors to run after each recipe execution
|
|
112
131
|
""",
|
|
113
132
|
)
|
|
133
|
+
parser.add_argument(
|
|
134
|
+
"--autopkg-prefs",
|
|
135
|
+
default=os.getenv("AW_AUTOPKG_PREFS_FILE", None),
|
|
136
|
+
type=validate_file,
|
|
137
|
+
help="""
|
|
138
|
+
Path to the autopkg preferences you'd like to use
|
|
139
|
+
""",
|
|
140
|
+
)
|
|
114
141
|
|
|
115
142
|
return parser.parse_args()
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
name = "autopkg-wrapper"
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
repository = "https://github.com/smithjw/autopkg-wrapper"
|
|
8
|
-
version = "2024.
|
|
8
|
+
version = "2024.8.1"
|
|
9
9
|
|
|
10
10
|
[tool.poetry.scripts]
|
|
11
11
|
# When built and installed by pip, the command autopkg_wrapper will be availble in to run within that environment
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2024.6.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{autopkg_wrapper-2024.6.1 → autopkg_wrapper-2024.8.1}/autopkg_wrapper/utils/git_functions.py
RENAMED
|
File without changes
|
|
File without changes
|