Esempio n. 1
0
def run_compile(build_result):
    build_result = BuildResult.objects.get(pk=build_result)
    project = build_result.project

    # Assemble the project somewhere
    base_dir = tempfile.mkdtemp(dir=os.path.join(settings.CHROOT_ROOT, 'tmp')
                                if settings.CHROOT_ROOT else None)

    try:
        assemble_project(project, base_dir, build_result)
        # Build the thing
        cwd = os.getcwd()
        success = False
        output = ''
        build_start_time = now()

        try:
            os.chdir(base_dir)

            environ = os.environ.copy()
            environ.update({
                'LD_PRELOAD': settings.C_PRELOAD_ROOT + 'libpreload.so',
                'ALLOWED_FOR_CREATE': '/tmp',
                'ALLOWED_FOR_READ': '/usr/local/include:/usr/include:/usr/lib:/lib:/lib64:/tmp' \
                                    ':/dev/urandom:/proc/self:/proc/self/maps:/proc/mounts' \
                                    ':/app/.heroku:/app/sdk2:/app/sdk3:/app/arm-cs-tools',
                'PATH': '{}:{}'.format(settings.ARM_CS_TOOLS, environ['PATH']),
                'HOME': '/app'
            })

            # Install dependencies if there are any
            dependencies = project.get_dependencies()
            if dependencies:
                # Checking for path-based dependencies is performed by the database so in theory we shouldn't need to do
                # it here but we will do it anyway just to be extra safe.
                for version in dependencies.values():
                    validate_dependency_version(version)
                npm_command = [
                    settings.NPM_BINARY, "install", "--ignore-scripts",
                    "--no-bin-links"
                ]
                output = subprocess.check_output(
                    npm_command,
                    stderr=subprocess.STDOUT,
                    preexec_fn=_set_resource_limits,
                    env=environ)
                subprocess.check_output([settings.NPM_BINARY, "dedupe"],
                                        stderr=subprocess.STDOUT,
                                        preexec_fn=_set_resource_limits,
                                        env=environ)

            if project.sdk_version == '2':
                command = [settings.SDK2_PEBBLE_WAF, "configure", "build"]
            elif project.sdk_version == '3':
                if settings.WAF_NODE_PATH:
                    environ['NODE_PATH'] = settings.WAF_NODE_PATH
                command = [settings.SDK3_PEBBLE_WAF, "configure", "build"]
            else:
                raise Exception("invalid sdk version.")

            output += subprocess.check_output(command,
                                              stderr=subprocess.STDOUT,
                                              preexec_fn=_set_resource_limits,
                                              env=environ)
        except subprocess.CalledProcessError as e:
            output = e.output
            logger.warning("Build command failed with error:\n%s\n", output)
            success = False
        except Exception as e:
            logger.exception("Unexpected exception during build")
            success = False
            output = str(e)
        else:
            success = True
            if project.project_type == 'package':
                temp_file = os.path.join(base_dir, 'dist.zip')
            else:
                temp_file = os.path.join(base_dir, 'build',
                                         '%s.pbw' % os.path.basename(base_dir))
            if not os.path.exists(temp_file):
                success = False
                logger.warning("Success was a lie.")
        finally:
            build_end_time = now()
            os.chdir(cwd)

            if success:
                # Try reading file sizes out of it first.
                if project.project_type != 'package':
                    try:
                        s = os.stat(temp_file)
                        build_result.total_size = s.st_size
                        # Now peek into the zip to see the component parts
                        with zipfile.ZipFile(temp_file, 'r') as z:
                            for platform in [
                                    'aplite', 'basalt', 'chalk', 'diorite',
                                    'emery'
                            ]:
                                store_size_info(project, build_result,
                                                platform, z)

                    except Exception as e:
                        logger.warning("Couldn't extract filesizes: %s", e)

                    # Try pulling out debug information.
                    if project.sdk_version == '2':
                        save_debug_info(
                            base_dir, build_result, BuildResult.DEBUG_APP,
                            'aplite',
                            os.path.join(base_dir, 'build', 'pebble-app.elf'))
                        save_debug_info(
                            base_dir, build_result, BuildResult.DEBUG_WORKER,
                            'aplite',
                            os.path.join(base_dir, 'build',
                                         'pebble-worker.elf'))
                    else:
                        for platform in [
                                'aplite', 'basalt', 'chalk', 'diorite', 'emery'
                        ]:
                            save_debug_info(
                                base_dir, build_result, BuildResult.DEBUG_APP,
                                platform,
                                os.path.join(base_dir, 'build',
                                             '%s/pebble-app.elf' % platform))
                            save_debug_info(
                                base_dir, build_result,
                                BuildResult.DEBUG_WORKER, platform,
                                os.path.join(base_dir, 'build',
                                             '%s/pebble-worker.elf' %
                                             platform))

                    build_result.save_pbw(temp_file)
                else:
                    # tar.gz up the entire built project directory as the build result.
                    archive = shutil.make_archive(
                        os.path.join(base_dir, "package"), 'gztar', base_dir)
                    build_result.save_package(archive)

            build_result.save_build_log(output or 'Failed to get output')
            build_result.state = BuildResult.STATE_SUCCEEDED if success else BuildResult.STATE_FAILED
            build_result.finished = now()
            build_result.save()

            data = {
                'data': {
                    'cloudpebble': {
                        'build_id':
                        build_result.id,
                        'job_run_time': (build_result.finished -
                                         build_result.started).total_seconds(),
                    },
                    'build_time':
                    (build_end_time - build_start_time).total_seconds(),
                }
            }

            event_name = 'app_build_succeeded' if success else 'app_build_failed'

            send_td_event(event_name, data, project=project)

    except Exception as e:
        logger.exception("Build failed due to internal error: %s", e)
        build_result.state = BuildResult.STATE_FAILED
        build_result.finished = now()
        try:
            build_result.save_build_log("Something broke:\n%s" % e)
        except:
            pass
        build_result.save()
    finally:
        shutil.rmtree(base_dir)
Esempio n. 2
0
def run_compile(build_result):
    build_result = BuildResult.objects.get(pk=build_result)
    project = build_result.project
    source_files = SourceFile.objects.filter(project=project)
    resources = ResourceFile.objects.filter(project=project)

    # Assemble the project somewhere
    base_dir = tempfile.mkdtemp(dir=os.path.join(settings.CHROOT_ROOT, 'tmp')
                                if settings.CHROOT_ROOT else None)

    manifest_filename = manifest_name_for_project(project)
    try:
        # Resources
        resource_root = 'resources'
        os.makedirs(os.path.join(base_dir, resource_root, 'images'))
        os.makedirs(os.path.join(base_dir, resource_root, 'fonts'))
        os.makedirs(os.path.join(base_dir, resource_root, 'data'))

        if project.project_type == 'native':
            # Source code
            create_source_files(project, base_dir)

            manifest_dict = generate_manifest_dict(project, resources)
            open(os.path.join(base_dir, manifest_filename),
                 'w').write(json.dumps(manifest_dict))

            for f in resources:
                target_dir = os.path.abspath(
                    os.path.join(base_dir, resource_root,
                                 ResourceFile.DIR_MAP[f.kind]))
                abs_target = os.path.abspath(
                    os.path.join(target_dir, f.file_name))
                f.copy_all_variants_to_dir(target_dir)

            # Reconstitute the SDK
            open(os.path.join(base_dir, 'wscript'),
                 'w').write(generate_wscript_file(project))
            open(os.path.join(base_dir, 'pebble-jshintrc'),
                 'w').write(generate_jshint_file(project))
        elif project.project_type == 'simplyjs':
            shutil.rmtree(base_dir)
            shutil.copytree(settings.SIMPLYJS_ROOT, base_dir)
            manifest_dict = generate_simplyjs_manifest_dict(project)

            js = '\n\n'.join(x.get_contents() for x in source_files
                             if x.file_name.endswith('.js'))
            escaped_js = json.dumps(js)
            build_result.save_simplyjs(js)

            open(os.path.join(base_dir, manifest_filename),
                 'w').write(json.dumps(manifest_dict))
            open(os.path.join(base_dir, 'src', 'js', 'zzz_userscript.js'),
                 'w').write("""
            (function() {
                simply.mainScriptSource = %s;
            })();
            """ % escaped_js)
        elif project.project_type == 'pebblejs':
            shutil.rmtree(base_dir)
            shutil.copytree(settings.PEBBLEJS_ROOT, base_dir)
            manifest_dict = generate_pebblejs_manifest_dict(project, resources)
            create_source_files(project, base_dir)

            for f in resources:
                if f.kind not in ('png', 'bitmap'):
                    continue
                target_dir = os.path.abspath(
                    os.path.join(base_dir, resource_root,
                                 ResourceFile.DIR_MAP[f.kind]))
                abs_target = os.path.abspath(
                    os.path.join(target_dir, f.file_name))
                if not abs_target.startswith(target_dir):
                    raise Exception("Suspicious filename: %s" % f.file_name)
                f.get_default_variant().copy_to_path(abs_target)

            open(os.path.join(base_dir, manifest_filename),
                 'w').write(json.dumps(manifest_dict))

        # Build the thing
        cwd = os.getcwd()
        success = False
        output = ''
        build_start_time = now()

        try:
            os.chdir(base_dir)

            # Install dependencies if there are any
            dependencies = project.get_dependencies()
            if dependencies:
                # Checking for path-based dependencies is performed by the database so in theory we shouldn't need to do
                # it here but we will do it anyway just to be extra safe.
                for version in dependencies.values():
                    validate_dependency_version(version)
                npm_command = [
                    settings.NPM_BINARY, "install", "--ignore-scripts"
                ]
                output = subprocess.check_output(
                    npm_command,
                    stderr=subprocess.STDOUT,
                    preexec_fn=_set_resource_limits)
                subprocess.check_output([settings.NPM_BINARY, "dedupe"],
                                        stderr=subprocess.STDOUT,
                                        preexec_fn=_set_resource_limits)

            if project.sdk_version == '2':
                environ = os.environ.copy()
                environ['PATH'] = '{}:{}'.format(settings.ARM_CS_TOOLS,
                                                 environ['PATH'])
                command = [settings.SDK2_PEBBLE_WAF, "configure", "build"]
            elif project.sdk_version == '3':
                environ = os.environ.copy()
                environ['PATH'] = '{}:{}'.format(settings.ARM_CS_TOOLS,
                                                 environ['PATH'])
                command = [settings.SDK3_PEBBLE_WAF, "configure", "build"]
            else:
                raise Exception("invalid sdk version.")

            output += subprocess.check_output(command,
                                              stderr=subprocess.STDOUT,
                                              preexec_fn=_set_resource_limits,
                                              env=environ)
        except subprocess.CalledProcessError as e:
            output = e.output
            logger.warning("Build command failed with error:\n%s\n", output)
            success = False
        except Exception as e:
            logger.exception("Unexpected exception during build")
            success = False
            output = str(e)
        else:
            success = True
            temp_file = os.path.join(base_dir, 'build',
                                     '%s.pbw' % os.path.basename(base_dir))
            if not os.path.exists(temp_file):
                success = False
                logger.warning("Success was a lie.")
        finally:
            build_end_time = now()
            os.chdir(cwd)

            if success:
                # Try reading file sizes out of it first.
                try:
                    s = os.stat(temp_file)
                    build_result.total_size = s.st_size
                    # Now peek into the zip to see the component parts
                    with zipfile.ZipFile(temp_file, 'r') as z:
                        store_size_info(project, build_result, 'aplite', z)
                        store_size_info(project, build_result, 'basalt', z)
                        store_size_info(project, build_result, 'chalk', z)

                except Exception as e:
                    logger.warning("Couldn't extract filesizes: %s", e)

                # Try pulling out debug information.
                if project.sdk_version == '2':
                    save_debug_info(
                        base_dir, build_result, BuildResult.DEBUG_APP,
                        'aplite',
                        os.path.join(base_dir, 'build', 'pebble-app.elf'))
                    save_debug_info(
                        base_dir, build_result, BuildResult.DEBUG_WORKER,
                        'aplite',
                        os.path.join(base_dir, 'build', 'pebble-worker.elf'))
                else:
                    save_debug_info(
                        base_dir, build_result, BuildResult.DEBUG_APP,
                        'aplite',
                        os.path.join(base_dir, 'build',
                                     'aplite/pebble-app.elf'))
                    save_debug_info(
                        base_dir, build_result, BuildResult.DEBUG_WORKER,
                        'aplite',
                        os.path.join(base_dir, 'build',
                                     'aplite/pebble-worker.elf'))
                    save_debug_info(
                        base_dir, build_result, BuildResult.DEBUG_APP,
                        'basalt',
                        os.path.join(base_dir, 'build',
                                     'basalt/pebble-app.elf'))
                    save_debug_info(
                        base_dir, build_result, BuildResult.DEBUG_WORKER,
                        'basalt',
                        os.path.join(base_dir, 'build',
                                     'basalt/pebble-worker.elf'))
                    save_debug_info(
                        base_dir, build_result, BuildResult.DEBUG_APP, 'chalk',
                        os.path.join(base_dir, 'build',
                                     'chalk/pebble-app.elf'))
                    save_debug_info(
                        base_dir, build_result, BuildResult.DEBUG_WORKER,
                        'chalk',
                        os.path.join(base_dir, 'build',
                                     'chalk/pebble-worker.elf'))

                build_result.save_pbw(temp_file)
            build_result.save_build_log(output or 'Failed to get output')
            build_result.state = BuildResult.STATE_SUCCEEDED if success else BuildResult.STATE_FAILED
            build_result.finished = now()
            build_result.save()

            data = {
                'data': {
                    'cloudpebble': {
                        'build_id':
                        build_result.id,
                        'job_run_time': (build_result.finished -
                                         build_result.started).total_seconds(),
                    },
                    'build_time':
                    (build_end_time - build_start_time).total_seconds(),
                }
            }

            event_name = 'app_build_succeeded' if success else 'app_build_failed'

            send_td_event(event_name, data, project=project)

    except Exception as e:
        logger.exception("Build failed due to internal error: %s", e)
        build_result.state = BuildResult.STATE_FAILED
        build_result.finished = now()
        try:
            build_result.save_build_log("Something broke:\n%s" % e)
        except:
            pass
        build_result.save()
    finally:
        shutil.rmtree(base_dir)
Esempio n. 3
0
def run_compile(build_result):
    build_result = BuildResult.objects.get(pk=build_result)
    project = build_result.project

    # Assemble the project somewhere
    base_dir = tempfile.mkdtemp(dir=os.path.join(settings.CHROOT_ROOT, 'tmp') if settings.CHROOT_ROOT else None)

    try:
        assemble_project(project, base_dir, build_result)
        # Build the thing
        cwd = os.getcwd()
        success = False
        output = ''
        build_start_time = now()

        try:
            os.chdir(base_dir)

            # Install dependencies if there are any
            dependencies = project.get_dependencies()
            if dependencies:
                # Checking for path-based dependencies is performed by the database so in theory we shouldn't need to do
                # it here but we will do it anyway just to be extra safe.
                for version in dependencies.values():
                    validate_dependency_version(version)
                npm_command = [settings.NPM_BINARY, "install", "--ignore-scripts", "--no-bin-links"]
                output = subprocess.check_output(npm_command, stderr=subprocess.STDOUT, preexec_fn=_set_resource_limits)
                subprocess.check_output([settings.NPM_BINARY, "dedupe"], stderr=subprocess.STDOUT, preexec_fn=_set_resource_limits)

            if project.sdk_version == '2':
                environ = os.environ.copy()
                environ['PATH'] = '{}:{}'.format(settings.ARM_CS_TOOLS, environ['PATH'])
                command = [settings.SDK2_PEBBLE_WAF, "configure", "build"]
            elif project.sdk_version == '3':
                environ = os.environ.copy()
                environ['PATH'] = '{}:{}'.format(settings.ARM_CS_TOOLS, environ['PATH'])
                if settings.WAF_NODE_PATH:
                    environ['NODE_PATH'] = settings.WAF_NODE_PATH
                command = [settings.SDK3_PEBBLE_WAF, "configure", "build"]
            else:
                raise Exception("invalid sdk version.")
            output += subprocess.check_output(command, stderr=subprocess.STDOUT, preexec_fn=_set_resource_limits,
                                              env=environ)
        except subprocess.CalledProcessError as e:
            output = e.output
            logger.warning("Build command failed with error:\n%s\n", output)
            success = False
        except Exception as e:
            logger.exception("Unexpected exception during build")
            success = False
            output = str(e)
        else:
            success = True
            if project.project_type == 'package':
                temp_file = os.path.join(base_dir, 'dist.zip')
            else:
                temp_file = os.path.join(base_dir, 'build', '%s.pbw' % os.path.basename(base_dir))
            if not os.path.exists(temp_file):
                success = False
                logger.warning("Success was a lie.")
        finally:
            build_end_time = now()
            os.chdir(cwd)

            if success:
                # Try reading file sizes out of it first.
                if project.project_type != 'package':
                    try:
                        s = os.stat(temp_file)
                        build_result.total_size = s.st_size
                        # Now peek into the zip to see the component parts
                        with zipfile.ZipFile(temp_file, 'r') as z:
                            for platform in ['aplite', 'basalt', 'chalk', 'diorite', 'emery']:
                                store_size_info(project, build_result, platform, z)

                    except Exception as e:
                        logger.warning("Couldn't extract filesizes: %s", e)

                    # Try pulling out debug information.
                    if project.sdk_version == '2':
                        save_debug_info(base_dir, build_result, BuildResult.DEBUG_APP, 'aplite', os.path.join(base_dir, 'build', 'pebble-app.elf'))
                        save_debug_info(base_dir, build_result, BuildResult.DEBUG_WORKER, 'aplite', os.path.join(base_dir, 'build', 'pebble-worker.elf'))
                    else:
                        for platform in ['aplite', 'basalt', 'chalk', 'diorite', 'emery']:
                            save_debug_info(base_dir, build_result, BuildResult.DEBUG_APP, platform, os.path.join(base_dir, 'build', '%s/pebble-app.elf' % platform))
                            save_debug_info(base_dir, build_result, BuildResult.DEBUG_WORKER, platform, os.path.join(base_dir, 'build', '%s/pebble-worker.elf' % platform))

                    build_result.save_pbw(temp_file)
                else:
                    # tar.gz up the entire built project directory as the build result.
                    archive = shutil.make_archive(os.path.join(base_dir, "package"), 'gztar', base_dir)
                    build_result.save_package(archive)

            build_result.save_build_log(output or 'Failed to get output')
            build_result.state = BuildResult.STATE_SUCCEEDED if success else BuildResult.STATE_FAILED
            build_result.finished = now()
            build_result.save()

            data = {
                'data': {
                    'cloudpebble': {
                        'build_id': build_result.id,
                        'job_run_time': (build_result.finished - build_result.started).total_seconds(),
                    },
                    'build_time': (build_end_time - build_start_time).total_seconds(),
                }
            }

            event_name = 'app_build_succeeded' if success else 'app_build_failed'

            send_td_event(event_name, data, project=project)

    except Exception as e:
        logger.exception("Build failed due to internal error: %s", e)
        build_result.state = BuildResult.STATE_FAILED
        build_result.finished = now()
        try:
            build_result.save_build_log("Something broke:\n%s" % e)
        except:
            pass
        build_result.save()
    finally:
        shutil.rmtree(base_dir)
Esempio n. 4
0
def run_compile(build_result):
    build_result = BuildResult.objects.get(pk=build_result)
    project = build_result.project
    source_files = SourceFile.objects.filter(project=project)
    resources = ResourceFile.objects.filter(project=project)

    # Assemble the project somewhere
    base_dir = tempfile.mkdtemp(dir=os.path.join(settings.CHROOT_ROOT, 'tmp') if settings.CHROOT_ROOT else None)

    manifest_filename = manifest_name_for_project(project)
    try:
        # Resources
        resource_root = 'resources'
        os.makedirs(os.path.join(base_dir, resource_root, 'images'))
        os.makedirs(os.path.join(base_dir, resource_root, 'fonts'))
        os.makedirs(os.path.join(base_dir, resource_root, 'data'))

        if project.project_type == 'native':
            # Source code
            create_source_files(project, base_dir)

            manifest_dict = generate_manifest_dict(project, resources)
            open(os.path.join(base_dir, manifest_filename), 'w').write(json.dumps(manifest_dict))

            for f in resources:
                target_dir = os.path.abspath(os.path.join(base_dir, resource_root, ResourceFile.DIR_MAP[f.kind]))
                abs_target = os.path.abspath(os.path.join(target_dir, f.file_name))
                f.copy_all_variants_to_dir(target_dir)

            # Reconstitute the SDK
            open(os.path.join(base_dir, 'wscript'), 'w').write(generate_wscript_file(project))
            open(os.path.join(base_dir, 'pebble-jshintrc'), 'w').write(generate_jshint_file(project))
        elif project.project_type == 'simplyjs':
            shutil.rmtree(base_dir)
            shutil.copytree(settings.SIMPLYJS_ROOT, base_dir)
            manifest_dict = generate_simplyjs_manifest_dict(project)

            js = '\n\n'.join(x.get_contents() for x in source_files if x.file_name.endswith('.js'))
            escaped_js = json.dumps(js)
            build_result.save_simplyjs(js)

            open(os.path.join(base_dir, manifest_filename), 'w').write(json.dumps(manifest_dict))
            open(os.path.join(base_dir, 'src', 'js', 'zzz_userscript.js'), 'w').write("""
            (function() {
                simply.mainScriptSource = %s;
            })();
            """ % escaped_js)
        elif project.project_type == 'pebblejs':
            shutil.rmtree(base_dir)
            shutil.copytree(settings.PEBBLEJS_ROOT, base_dir)
            manifest_dict = generate_pebblejs_manifest_dict(project, resources)
            create_source_files(project, base_dir)

            for f in resources:
                if f.kind not in ('png', 'bitmap'):
                    continue
                target_dir = os.path.abspath(os.path.join(base_dir, resource_root, ResourceFile.DIR_MAP[f.kind]))
                abs_target = os.path.abspath(os.path.join(target_dir, f.file_name))
                if not abs_target.startswith(target_dir):
                    raise Exception("Suspicious filename: %s" % f.file_name)
                f.get_default_variant().copy_to_path(abs_target)

            open(os.path.join(base_dir, manifest_filename), 'w').write(json.dumps(manifest_dict))

        # Build the thing
        cwd = os.getcwd()
        success = False
        output = ''
        build_start_time = now()

        try:
            os.chdir(base_dir)

            # Install dependencies if there are any
            dependencies = project.get_dependencies()
            if dependencies:
                # Checking for path-based dependencies is performed by the database so in theory we shouldn't need to do
                # it here but we will do it anyway just to be extra safe.
                for version in dependencies.values():
                    validate_dependency_version(version)
                npm_command = [settings.NPM_BINARY, "install", "--ignore-scripts"]
                output = subprocess.check_output(npm_command, stderr=subprocess.STDOUT, preexec_fn=_set_resource_limits)
                subprocess.check_output([settings.NPM_BINARY, "dedupe"], stderr=subprocess.STDOUT, preexec_fn=_set_resource_limits)

            if project.sdk_version == '2':
                environ = os.environ.copy()
                environ['PATH'] = '{}:{}'.format(settings.ARM_CS_TOOLS, environ['PATH'])
                command = [settings.SDK2_PEBBLE_WAF, "configure", "build"]
            elif project.sdk_version == '3':
                environ = os.environ.copy()
                environ['PATH'] = '{}:{}'.format(settings.ARM_CS_TOOLS, environ['PATH'])
                command = [settings.SDK3_PEBBLE_WAF, "configure", "build"]
            else:
                raise Exception("invalid sdk version.")

            output += subprocess.check_output(command, stderr=subprocess.STDOUT, preexec_fn=_set_resource_limits,
                                              env=environ)
        except subprocess.CalledProcessError as e:
            output = e.output
            logger.warning("Build command failed with error:\n%s\n", output)
            success = False
        except Exception as e:
            logger.exception("Unexpected exception during build")
            success = False
            output = str(e)
        else:
            success = True
            temp_file = os.path.join(base_dir, 'build', '%s.pbw' % os.path.basename(base_dir))
            if not os.path.exists(temp_file):
                success = False
                logger.warning("Success was a lie.")
        finally:
            build_end_time = now()
            os.chdir(cwd)

            if success:
                # Try reading file sizes out of it first.
                try:
                    s = os.stat(temp_file)
                    build_result.total_size = s.st_size
                    # Now peek into the zip to see the component parts
                    with zipfile.ZipFile(temp_file, 'r') as z:
                        store_size_info(project, build_result, 'aplite', z)
                        store_size_info(project, build_result, 'basalt', z)
                        store_size_info(project, build_result, 'chalk', z)

                except Exception as e:
                    logger.warning("Couldn't extract filesizes: %s", e)

                # Try pulling out debug information.
                if project.sdk_version == '2':
                    save_debug_info(base_dir, build_result, BuildResult.DEBUG_APP, 'aplite', os.path.join(base_dir, 'build', 'pebble-app.elf'))
                    save_debug_info(base_dir, build_result, BuildResult.DEBUG_WORKER, 'aplite', os.path.join(base_dir, 'build', 'pebble-worker.elf'))
                else:
                    save_debug_info(base_dir, build_result, BuildResult.DEBUG_APP, 'aplite', os.path.join(base_dir, 'build', 'aplite/pebble-app.elf'))
                    save_debug_info(base_dir, build_result, BuildResult.DEBUG_WORKER, 'aplite', os.path.join(base_dir, 'build', 'aplite/pebble-worker.elf'))
                    save_debug_info(base_dir, build_result, BuildResult.DEBUG_APP, 'basalt', os.path.join(base_dir, 'build', 'basalt/pebble-app.elf'))
                    save_debug_info(base_dir, build_result, BuildResult.DEBUG_WORKER, 'basalt', os.path.join(base_dir, 'build', 'basalt/pebble-worker.elf'))
                    save_debug_info(base_dir, build_result, BuildResult.DEBUG_APP, 'chalk', os.path.join(base_dir, 'build', 'chalk/pebble-app.elf'))
                    save_debug_info(base_dir, build_result, BuildResult.DEBUG_WORKER, 'chalk', os.path.join(base_dir, 'build', 'chalk/pebble-worker.elf'))

                build_result.save_pbw(temp_file)
            build_result.save_build_log(output or 'Failed to get output')
            build_result.state = BuildResult.STATE_SUCCEEDED if success else BuildResult.STATE_FAILED
            build_result.finished = now()
            build_result.save()

            data = {
                'data': {
                    'cloudpebble': {
                        'build_id': build_result.id,
                        'job_run_time': (build_result.finished - build_result.started).total_seconds(),
                    },
                    'build_time': (build_end_time - build_start_time).total_seconds(),
                }
            }

            event_name = 'app_build_succeeded' if success else 'app_build_failed'

            send_td_event(event_name, data, project=project)

    except Exception as e:
        logger.exception("Build failed due to internal error: %s", e)
        build_result.state = BuildResult.STATE_FAILED
        build_result.finished = now()
        try:
            build_result.save_build_log("Something broke:\n%s" % e)
        except:
            pass
        build_result.save()
    finally:
        shutil.rmtree(base_dir)