-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathAutoPkgReviewAndRun.py
executable file
·141 lines (128 loc) · 5.4 KB
/
AutoPkgReviewAndRun.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/Library/AutoPkg/Python3/Python.framework/Versions/Current/bin/python3
### This script updates AutoPkg repos, verifies trust info (with prompt to update after
### review), and runs recipes in a recipe list
import argparse
import os
import subprocess
import sys
# Where is the recipe list (one recipe per line) located?
# Recipe list should be one recipe per line, separated by a carriage return ("\n")
recipe_locations = [ os.path.expanduser('~/Library/AutoPkg/recipe_list.txt'),
os.path.expanduser('~/Library/Application Support/AutoPkgr/recipe_list.txt') ]
# Acceptable affirmative responses
affirmative_responses = ["y", "yes", "sure", "definitely"]
def get_options():
parser = argparse.ArgumentParser(description="Verifies and runs recipes in a recipe \
list. Either a specified recipe list or one in ~/Library/AutoPkg/recipe_list.txt \
or in ~/Library/Application Support/AutoPkgr/recipe_list.txt")
parser.add_argument('--verifyonly', '--reviewonly', help="Only verify/review the recipes. Do not run AutoPkg.",
action="store_true")
parser.add_argument('--runonly', help="Only run the recipe list. Do not verify trust \
info.", action="store_true")
parser.add_argument('--recipe-list', '-l', help="Path to recipe list file. If not specified, \
the default location of ~/Library/AutoPkg/recipe_list.txt will be used instead")
args = parser.parse_args()
# If it's verify only and run only, give an error message
if args.verifyonly and args.runonly:
print("The verify only and run only options are mutually exclusive.")
sys.exit(1)
# If it's verify only, don't run
elif args.verifyonly:
recipeverify = True
reciperun = False
# If it's run only, don't verify
elif args.runonly:
recipeverify = False
reciperun = True
# If it's neither verify only or run only, do both
else:
recipeverify = True
reciperun = True
# See if there's a recipe list specified
if args.recipe_list:
recipelist = args.recipe_list
else:
recipelist = False
return recipeverify, reciperun, recipelist
def get_recipe_list(recipelist, recipe_locations):
# Double-check the recipe list file exists
recipe_list = False
if os.path.isfile(recipelist):
print("Using specified {} file".format(recipelist))
recipe_list = recipelist
else:
print("No recipe list specified. Trying default locations...")
for recipe_location in recipe_locations:
if os.path.isfile(recipe_location):
print("Using {}".format(recipe_location))
recipe_list = recipe_location
break
if recipe_list:
# Put the recipes into a list
try:
recipes = [recipe.rstrip('\n') for recipe in open(recipe_list)]
except:
print("Unable to get recipe list {} into a list. Aborting run.".format(recipe_list))
sys.exit(1)
return recipes
else:
print("Could not find a valid recipe list")
sys.exit(1)
def verify_recipes(recipes, affirmative_responses):
# Update the repos
print("Updating recipe repos...")
subprocess.call([ "/usr/local/bin/autopkg", "repo-update", "all" ])
# Loop through the recipes and see which ones need to be verified
for recipe in recipes:
print("Verifying trust info for {}".format(recipe))
# See what the verified trust info looks like
cmd = [ "/usr/local/bin/autopkg", "verify-trust-info", "-vv", recipe ]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
encoding='utf8')
out, err = p.communicate()
if err:
verify_result = "Verification failure"
else:
verify_result = out
desired_result = recipe + ": OK"
if desired_result not in verify_result:
print(err)
confirmation = input("Do you trust these changes? (y/n) ")
if confirmation.lower().strip() in affirmative_responses:
print("Updating trust info for {}".format(recipe))
cmd = [ "/usr/local/bin/autopkg", "update-trust-info", recipe ]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
encoding='utf8')
out, err = p.communicate()
if err:
print("Unable to update trust info: {}".format(err))
else:
print("Okay. Not updating trust for {}".format(recipe))
# Remove it from the list of recipes to run... no point in running it if
# the trust info isn't good
recipes.remove(recipe)
else:
print(verify_result)
return recipes
def run_recipes(recipes):
print("Running recipes...")
cmd = [ "/usr/local/bin/autopkg", "run" ]
cmd.extend(recipes)
try:
subprocess.call(cmd)
except:
print("Unable to run recipes. Aborting run.")
sys.exit(1)
def main():
# Get arguments
recipeverify, reciperun, recipelist = get_options()
# Get recipe list
recipes = get_recipe_list(recipelist, recipe_locations)
if recipeverify:
# Get verified recipes
recipes = verify_recipes(recipes, affirmative_responses)
if reciperun:
# Run the recipes
run_recipes(recipes)
if __name__ == "__main__":
main()