-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathrebuild_updated_recipes.py
executable file
·99 lines (89 loc) · 3.63 KB
/
rebuild_updated_recipes.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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Continuous Integration helper script.
Automatically detects recipes modified in a changeset (compares with master)
and recompiles them.
To run locally, set the environment variables before running:
```
ANDROID_SDK_HOME=~/.buildozer/android/platform/android-sdk-20
ANDROID_NDK_HOME=~/.buildozer/android/platform/android-ndk-r9c
./ci/rebuild_update_recipes.py
```
Current limitations:
- will fail on conflicting requirements
e.g. https://travis-ci.org/AndreMiras/python-for-android/builds/438840800
the list of recipes was huge and result was:
[ERROR]: Didn't find any valid dependency graphs.
[ERROR]: This means that some of your requirements pull in conflicting dependencies.
- only rebuilds on sdl2 bootstrap
- supports mainly python3 with fallback to python2
"""
import sh
import os
from pythonforandroid.build import Context
from pythonforandroid import logger
from pythonforandroid.graph import get_recipe_order_and_bootstrap
from pythonforandroid.toolchain import current_directory
from pythonforandroid.util import BuildInterruptingException
from ci.constants import TargetPython, CORE_RECIPES, BROKEN_RECIPES
def modified_recipes(branch='origin/master'):
"""
Returns a set of modified recipes between the current branch and the one
in param.
"""
# using the contrib version on purpose rather than sh.git, since it comes
# with a bunch of fixes, e.g. disabled TTY, see:
# https://stackoverflow.com/a/20128598/185510
git_diff = sh.contrib.git.diff('--name-only', branch)
recipes = set()
for file_path in git_diff:
if 'pythonforandroid/recipes/' in file_path:
recipe = file_path.split('/')[2]
recipes.add(recipe)
return recipes
def build(target_python, requirements):
"""
Builds an APK given a target Python and a set of requirements.
"""
if not requirements:
return
testapp = 'setup_testapp_python2.py'
android_sdk_home = os.environ['ANDROID_SDK_HOME']
android_ndk_home = os.environ['ANDROID_NDK_HOME']
if target_python == TargetPython.python3:
testapp = 'setup_testapp_python3.py'
requirements.add(target_python.name)
requirements = ','.join(requirements)
logger.info('requirements: {}'.format(requirements))
with current_directory('testapps/'):
# iterates to stream the output
for line in sh.python(
testapp, 'apk', '--sdk-dir', android_sdk_home,
'--ndk-dir', android_ndk_home, '--bootstrap', 'sdl2', '--requirements',
requirements, _err_to_out=True, _iter=True):
print(line)
def main():
target_python = TargetPython.python3
recipes = modified_recipes()
logger.info('recipes modified: {}'.format(recipes))
recipes -= CORE_RECIPES
logger.info('recipes to build: {}'.format(recipes))
context = Context()
# forces the default target
recipes_and_target = recipes | set([target_python.name])
try:
build_order, python_modules, bs = get_recipe_order_and_bootstrap(
context, recipes_and_target, None)
except BuildInterruptingException:
# fallback to python2 if default target is not compatible
logger.info('incompatible with {}'.format(target_python.name))
target_python = TargetPython.python2
logger.info('falling back to {}'.format(target_python.name))
# removing the known broken recipe for the given target
broken_recipes = BROKEN_RECIPES[target_python]
recipes -= broken_recipes
logger.info('recipes to build (no broken): {}'.format(recipes))
build(target_python, recipes)
if __name__ == '__main__':
main()