33import asyncio
44import argparse
55import os
6+ import platform
67import re
78import shlex
89import shutil
@@ -272,6 +273,16 @@ def clean_all(context):
272273 clean (host )
273274
274275
276+ def setup_ci ():
277+ # https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/
278+ if "GITHUB_ACTIONS" in os .environ and platform .system () == "Linux" :
279+ Path ("/etc/udev/rules.d/99-kvm4all.rules" ).write_text (
280+ 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"\n '
281+ )
282+ run (["sudo" , "udevadm" , "control" , "--reload-rules" ])
283+ run (["sudo" , "udevadm" , "trigger" , "--name-match=kvm" ])
284+
285+
275286def setup_sdk ():
276287 sdkmanager = android_home / (
277288 "cmdline-tools/latest/bin/sdkmanager"
@@ -584,6 +595,7 @@ async def gradle_task(context):
584595
585596
586597async def run_testbed (context ):
598+ setup_ci ()
587599 setup_sdk ()
588600 setup_testbed ()
589601
@@ -692,6 +704,53 @@ def package(context):
692704 f"{ dist_dir } /python-{ version } -{ context .host } " , "gztar" , temp_dir
693705 )
694706 print (f"Wrote { package_path } " )
707+ return package_path
708+
709+
710+ def ci (context ):
711+ for step in [
712+ configure_build_python ,
713+ make_build_python ,
714+ configure_host_python ,
715+ make_host_python ,
716+ package ,
717+ ]:
718+ caption = (
719+ step .__name__ .replace ("_" , " " )
720+ .capitalize ()
721+ .replace ("python" , "Python" )
722+ )
723+ print (f"::group::{ caption } " )
724+ result = step (context )
725+ if step is package :
726+ package_path = result
727+ print ("::endgroup::" )
728+
729+ if (
730+ "GITHUB_ACTIONS" in os .environ
731+ and (platform .system (), platform .machine ()) != ("Linux" , "x86_64" )
732+ ):
733+ print (
734+ "Skipping test: GitHub Actions does not supports the Android "
735+ "emulator on this platform."
736+ )
737+ else :
738+ with TemporaryDirectory (prefix = SCRIPT_NAME ) as temp_dir :
739+ print ("::group::Tests" )
740+ # Prove the package is self-contained by using it to run the tests.
741+ shutil .unpack_archive (package_path , temp_dir )
742+
743+ # Arguments are similar to --fast-ci, but in single-process mode.
744+ launcher_args = ["--managed" , "maxVersion" , "-v" ]
745+ test_args = [
746+ "--single-process" , "--fail-env-changed" , "--rerun" , "--slowest" ,
747+ "--verbose3" , "-u" , "all,-cpu" , "--timeout=600"
748+ ]
749+ run (
750+ ["./android.py" , "test" , * launcher_args , "--" , * test_args ],
751+ cwd = temp_dir
752+ )
753+ print ("::endgroup::" )
695754
696755
697756def env (context ):
@@ -735,23 +794,24 @@ def add_parser(*args, **kwargs):
735794 add_parser ("build-testbed" , help = "Build the testbed app" )
736795 test = add_parser ("test" , help = "Run the testbed app" )
737796 package = add_parser ("package" , help = "Make a release package" )
797+ ci = add_parser ("ci" , help = "Run build, package and test" )
738798 env = add_parser ("env" , help = "Print environment variables" )
739799
740800 # Common arguments
741- for subcommand in build , configure_build , configure_host :
801+ for subcommand in [ build , configure_build , configure_host , ci ] :
742802 subcommand .add_argument (
743803 "--clean" , action = "store_true" , default = False , dest = "clean" ,
744804 help = "Delete the relevant build directories first" )
745805
746- host_commands = [build , configure_host , make_host , package ]
806+ host_commands = [build , configure_host , make_host , package , ci ]
747807 if in_source_tree :
748808 host_commands .append (env )
749809 for subcommand in host_commands :
750810 subcommand .add_argument (
751811 "host" , metavar = "HOST" , choices = HOSTS ,
752812 help = "Host triplet: choices=[%(choices)s]" )
753813
754- for subcommand in build , configure_build , configure_host :
814+ for subcommand in [ build , configure_build , configure_host , ci ] :
755815 subcommand .add_argument ("args" , nargs = "*" ,
756816 help = "Extra arguments to pass to `configure`" )
757817
@@ -784,9 +844,10 @@ def add_parser(*args, **kwargs):
784844 f"Separate them from { SCRIPT_NAME } 's own arguments with `--`." )
785845
786846 # Package arguments.
787- package .add_argument (
788- "-g" , action = "store_true" , default = False , dest = "debug" ,
789- help = "Include debug information" )
847+ for subcommand in [package , ci ]:
848+ subcommand .add_argument (
849+ "-g" , action = "store_true" , default = False , dest = "debug" ,
850+ help = "Include debug information in package" )
790851
791852 return parser .parse_args ()
792853
@@ -811,6 +872,7 @@ def main():
811872 "build-testbed" : build_testbed ,
812873 "test" : run_testbed ,
813874 "package" : package ,
875+ "ci" : ci ,
814876 "env" : env ,
815877 }
816878
0 commit comments