196ff1984SBrad Bishop#! /usr/bin/env python3 2eb8dc403SDave Cobbley# 3eb8dc403SDave Cobbley# BitBake Toaster Implementation 4eb8dc403SDave Cobbley# 5eb8dc403SDave Cobbley# Copyright (C) 2016 Intel Corporation 6eb8dc403SDave Cobbley# 7c342db35SBrad Bishop# SPDX-License-Identifier: GPL-2.0-only 8eb8dc403SDave Cobbley# 9eb8dc403SDave Cobbley 10eb8dc403SDave Cobbleyimport os 11eb8dc403SDave Cobbleyimport sys 12eb8dc403SDave Cobbleyimport time 13eb8dc403SDave Cobbleyimport unittest 14eb8dc403SDave Cobbley 15eb8dc403SDave Cobbleyfrom orm.models import Project, Release, ProjectTarget, Build, ProjectVariable 16eb8dc403SDave Cobbleyfrom bldcontrol.models import BuildEnvironment 17eb8dc403SDave Cobbley 18eb8dc403SDave Cobbleyfrom bldcontrol.management.commands.runbuilds import Command\ 19eb8dc403SDave Cobbley as RunBuildsCommand 20eb8dc403SDave Cobbley 21eb8dc403SDave Cobbleyfrom django.core.management import call_command 22eb8dc403SDave Cobbley 23eb8dc403SDave Cobbleyimport subprocess 24eb8dc403SDave Cobbleyimport logging 25eb8dc403SDave Cobbley 26eb8dc403SDave Cobbleylogger = logging.getLogger("toaster") 27eb8dc403SDave Cobbley 28eb8dc403SDave Cobbley# We use unittest.TestCase instead of django.test.TestCase because we don't 29eb8dc403SDave Cobbley# want to wrap everything in a database transaction as an external process 30eb8dc403SDave Cobbley# (bitbake needs access to the database) 31eb8dc403SDave Cobbley 32eb8dc403SDave Cobbleydef load_build_environment(): 33eb8dc403SDave Cobbley call_command('loaddata', 'settings.xml', app_label="orm") 34eb8dc403SDave Cobbley call_command('loaddata', 'poky.xml', app_label="orm") 35eb8dc403SDave Cobbley 36eb8dc403SDave Cobbley current_builddir = os.environ.get("BUILDDIR") 37eb8dc403SDave Cobbley if current_builddir: 38eb8dc403SDave Cobbley BuildTest.BUILDDIR = current_builddir 39eb8dc403SDave Cobbley else: 40eb8dc403SDave Cobbley # Setup a builddir based on default layout 41eb8dc403SDave Cobbley # bitbake inside openebedded-core 42eb8dc403SDave Cobbley oe_init_build_env_path = os.path.join( 43eb8dc403SDave Cobbley os.path.dirname(os.path.abspath(__file__)), 44eb8dc403SDave Cobbley os.pardir, 45eb8dc403SDave Cobbley os.pardir, 46eb8dc403SDave Cobbley os.pardir, 47eb8dc403SDave Cobbley os.pardir, 48eb8dc403SDave Cobbley os.pardir, 49eb8dc403SDave Cobbley 'oe-init-build-env' 50eb8dc403SDave Cobbley ) 51eb8dc403SDave Cobbley if not os.path.exists(oe_init_build_env_path): 52eb8dc403SDave Cobbley raise Exception("We had no BUILDDIR set and couldn't " 53eb8dc403SDave Cobbley "find oe-init-build-env to set this up " 54eb8dc403SDave Cobbley "ourselves please run oe-init-build-env " 55eb8dc403SDave Cobbley "before running these tests") 56eb8dc403SDave Cobbley 57eb8dc403SDave Cobbley oe_init_build_env_path = os.path.realpath(oe_init_build_env_path) 58eb8dc403SDave Cobbley cmd = "bash -c 'source oe-init-build-env %s'" % BuildTest.BUILDDIR 59eb8dc403SDave Cobbley p = subprocess.Popen( 60eb8dc403SDave Cobbley cmd, 61eb8dc403SDave Cobbley cwd=os.path.dirname(oe_init_build_env_path), 62eb8dc403SDave Cobbley shell=True, 63eb8dc403SDave Cobbley stdout=subprocess.PIPE, 64eb8dc403SDave Cobbley stderr=subprocess.PIPE) 65eb8dc403SDave Cobbley 66eb8dc403SDave Cobbley output, err = p.communicate() 67eb8dc403SDave Cobbley p.wait() 68eb8dc403SDave Cobbley 69eb8dc403SDave Cobbley logger.info("oe-init-build-env %s %s" % (output, err)) 70eb8dc403SDave Cobbley 71eb8dc403SDave Cobbley os.environ['BUILDDIR'] = BuildTest.BUILDDIR 72eb8dc403SDave Cobbley 73eb8dc403SDave Cobbley # Setup the path to bitbake we know where to find this 74eb8dc403SDave Cobbley bitbake_path = os.path.join( 75eb8dc403SDave Cobbley os.path.dirname(os.path.abspath(__file__)), 76eb8dc403SDave Cobbley os.pardir, 77eb8dc403SDave Cobbley os.pardir, 78eb8dc403SDave Cobbley os.pardir, 79eb8dc403SDave Cobbley os.pardir, 80eb8dc403SDave Cobbley 'bin', 81eb8dc403SDave Cobbley 'bitbake') 82eb8dc403SDave Cobbley if not os.path.exists(bitbake_path): 83eb8dc403SDave Cobbley raise Exception("Could not find bitbake at the expected path %s" 84eb8dc403SDave Cobbley % bitbake_path) 85eb8dc403SDave Cobbley 86eb8dc403SDave Cobbley os.environ['BBBASEDIR'] = bitbake_path 87eb8dc403SDave Cobbley 88eb8dc403SDave Cobbleyclass BuildTest(unittest.TestCase): 89eb8dc403SDave Cobbley 90eb8dc403SDave Cobbley PROJECT_NAME = "Testbuild" 91*169d7bccSPatrick Williams BUILDDIR = os.environ.get("BUILDDIR") 92eb8dc403SDave Cobbley 93eb8dc403SDave Cobbley def build(self, target): 94eb8dc403SDave Cobbley # So that the buildinfo helper uses the test database' 95eb8dc403SDave Cobbley self.assertEqual( 96eb8dc403SDave Cobbley os.environ.get('DJANGO_SETTINGS_MODULE', ''), 97eb8dc403SDave Cobbley 'toastermain.settings_test', 98eb8dc403SDave Cobbley "Please initialise django with the tests settings: " 99eb8dc403SDave Cobbley "DJANGO_SETTINGS_MODULE='toastermain.settings_test'") 100eb8dc403SDave Cobbley 101eb8dc403SDave Cobbley built = self.target_already_built(target) 102eb8dc403SDave Cobbley if built: 103eb8dc403SDave Cobbley return built 104eb8dc403SDave Cobbley 105eb8dc403SDave Cobbley load_build_environment() 106eb8dc403SDave Cobbley 107eb8dc403SDave Cobbley BuildEnvironment.objects.get_or_create( 108eb8dc403SDave Cobbley betype=BuildEnvironment.TYPE_LOCAL, 109eb8dc403SDave Cobbley sourcedir=BuildTest.BUILDDIR, 110eb8dc403SDave Cobbley builddir=BuildTest.BUILDDIR 111eb8dc403SDave Cobbley ) 112eb8dc403SDave Cobbley 113eb8dc403SDave Cobbley release = Release.objects.get(name='local') 114eb8dc403SDave Cobbley 115eb8dc403SDave Cobbley # Create a project for this build to run in 116eb8dc403SDave Cobbley project = Project.objects.create_project(name=BuildTest.PROJECT_NAME, 117eb8dc403SDave Cobbley release=release) 118eb8dc403SDave Cobbley 119*169d7bccSPatrick Williams passthrough_variable_names = ["SSTATE_DIR", "DL_DIR", "SSTATE_MIRRORS", "BB_HASHSERVE", "BB_HASHSERVE_UPSTREAM"] 120ac13d5f3SPatrick Williams for variable_name in passthrough_variable_names: 121ac13d5f3SPatrick Williams current_variable = os.environ.get(variable_name) 122ac13d5f3SPatrick Williams if current_variable: 123ac13d5f3SPatrick Williams ProjectVariable.objects.get_or_create( 124ac13d5f3SPatrick Williams name=variable_name, 125ac13d5f3SPatrick Williams value=current_variable, 126ac13d5f3SPatrick Williams project=project) 127ac13d5f3SPatrick Williams 128eb8dc403SDave Cobbley if os.environ.get("TOASTER_TEST_USE_SSTATE_MIRROR"): 129eb8dc403SDave Cobbley ProjectVariable.objects.get_or_create( 130eb8dc403SDave Cobbley name="SSTATE_MIRRORS", 131*169d7bccSPatrick Williams value="file://.* http://cdn.jsdelivr.net/yocto/sstate/all/PATH;downloadfilename=PATH", 132eb8dc403SDave Cobbley project=project) 133eb8dc403SDave Cobbley 134eb8dc403SDave Cobbley ProjectTarget.objects.create(project=project, 135eb8dc403SDave Cobbley target=target, 136eb8dc403SDave Cobbley task="") 137eb8dc403SDave Cobbley build_request = project.schedule_build() 138eb8dc403SDave Cobbley 139eb8dc403SDave Cobbley # run runbuilds command to dispatch the build 140eb8dc403SDave Cobbley # e.g. manage.py runubilds 141eb8dc403SDave Cobbley RunBuildsCommand().runbuild() 142eb8dc403SDave Cobbley 143eb8dc403SDave Cobbley build_pk = build_request.build.pk 144eb8dc403SDave Cobbley while Build.objects.get(pk=build_pk).outcome == Build.IN_PROGRESS: 145eb8dc403SDave Cobbley sys.stdout.write("\rBuilding %s %d%%" % 146eb8dc403SDave Cobbley (target, 147eb8dc403SDave Cobbley build_request.build.completeper())) 148eb8dc403SDave Cobbley sys.stdout.flush() 149eb8dc403SDave Cobbley time.sleep(1) 150eb8dc403SDave Cobbley 151eb8dc403SDave Cobbley self.assertEqual(Build.objects.get(pk=build_pk).outcome, 152eb8dc403SDave Cobbley Build.SUCCEEDED, 153eb8dc403SDave Cobbley "Build did not SUCCEEDED") 154eb8dc403SDave Cobbley 155eb8dc403SDave Cobbley logger.info("\nBuild finished %s" % build_request.build.outcome) 156eb8dc403SDave Cobbley return build_request.build 157eb8dc403SDave Cobbley 158eb8dc403SDave Cobbley def target_already_built(self, target): 159eb8dc403SDave Cobbley """ If the target is already built no need to build it again""" 160eb8dc403SDave Cobbley for build in Build.objects.filter( 161eb8dc403SDave Cobbley project__name=BuildTest.PROJECT_NAME): 162eb8dc403SDave Cobbley targets = build.target_set.values_list('target', flat=True) 163eb8dc403SDave Cobbley if target in targets: 164eb8dc403SDave Cobbley return build 165eb8dc403SDave Cobbley 166eb8dc403SDave Cobbley return None 167