Example #1
0
def add_project_to_archive(z, project, prefix=''):
    source_files = SourceFile.objects.filter(project=project)
    resources = ResourceFile.objects.filter(project=project)
    prefix += re.sub(r'[^\w]+', '_', project.name).strip('_').lower()

    for source in source_files:
        src_dir = 'src'
        if project.project_type == 'native':
            if source.target == 'worker':
                src_dir = 'worker_src'
            elif project.app_modern_multi_js and source.file_name.endswith('.js'):
                src_dir = 'src/js'

        z.writestr('%s/%s/%s' % (prefix, src_dir, source.file_name), source.get_contents())

    for resource in resources:
        res_path = 'resources'
        for variant in resource.variants.all():
            z.writestr('%s/%s/%s' % (prefix, res_path, variant.path), variant.get_contents())

    manifest = generate_manifest(project, resources)
    z.writestr('%s/appinfo.json' % prefix, manifest)
    if project.project_type == 'native':
        # This file is always the same, but needed to build.
        z.writestr('%s/wscript' % prefix, generate_wscript_file(project, for_export=True))
        z.writestr('%s/jshintrc' % prefix, generate_jshint_file(project))
Example #2
0
def assemble_project(project, base_dir, build_result=None):
    """ Copy all files necessary to build a project into a directory. """
    resources = project.resources.all()

    if project.is_standard_project_type:
        # Write out the sources, resources, and wscript and jshint file
        assemble_source_files(project, base_dir)
        if project.project_type != 'rocky':
            assemble_resource_directories(project, base_dir)
            assemble_resources(base_dir, project.resources_path, resources)
        with open(os.path.join(base_dir, 'wscript'), 'w') as wscript:
            wscript.write(generate_wscript_file(project))
        with open(os.path.join(base_dir, 'pebble-jshintrc'), 'w') as jshint:
            jshint.write(generate_jshint_file(project))
    elif project.project_type == 'simplyjs':
        # SimplyJS is a particularly special case
        assemble_simplyjs_sources(project, base_dir, build_result)
    elif project.project_type == 'pebblejs':
        # PebbleJS projects have to import the entire pebblejs library, including its wscript
        assemble_resource_directories(project, base_dir)
        shutil.rmtree(base_dir)
        shutil.copytree(settings.PEBBLEJS_ROOT, base_dir)
        assemble_resources(base_dir, project.resources_path, resources, type_restrictions=('png', 'bitmap'))
        assemble_source_files(project, base_dir)

    # All projects have a manifest
    manifest_filename = manifest_name_for_project(project)
    manifest_dict = generate_manifest_dict(project, resources)

    with open(os.path.join(base_dir, manifest_filename), 'w') as f:
        f.write(json.dumps(manifest_dict))
Example #3
0
def add_project_to_archive(z, project, prefix=''):
    source_files = SourceFile.objects.filter(project=project)
    resources = ResourceFile.objects.filter(project=project)
    prefix += re.sub(r'[^\w]+', '_', project.name).strip('_').lower()

    for source in source_files:
        src_dir = 'src'
        if project.project_type == 'native':
            if source.target == 'worker':
                src_dir = 'worker_src'
            elif project.app_modern_multi_js and source.file_name.endswith(
                    '.js'):
                src_dir = 'src/js'

        z.writestr('%s/%s/%s' % (prefix, src_dir, source.file_name),
                   source.get_contents())

    for resource in resources:
        res_path = 'resources'
        for variant in resource.variants.all():
            z.writestr('%s/%s/%s' % (prefix, res_path, variant.path),
                       variant.get_contents())

    manifest = generate_manifest(project, resources)
    manifest_name = manifest_name_for_project(project)
    z.writestr('%s/%s' % (prefix, manifest_name), manifest)
    if project.project_type == 'native':
        # This file is always the same, but needed to build.
        z.writestr('%s/wscript' % prefix,
                   generate_wscript_file(project, for_export=True))
        z.writestr('%s/jshintrc' % prefix, generate_jshint_file(project))
Example #4
0
def assemble_project(project, base_dir, build_result=None):
    """ Copy all files necessary to build a project into a directory. """
    resources = project.resources.all()

    if project.is_standard_project_type:
        # Write out the sources, resources, and wscript and jshint file
        assemble_source_files(project, base_dir)
        if project.project_type != 'rocky':
            assemble_resource_directories(project, base_dir)
            assemble_resources(base_dir, project.resources_path, resources)
        with open(os.path.join(base_dir, 'wscript'), 'w') as wscript:
            wscript.write(generate_wscript_file(project))
        with open(os.path.join(base_dir, 'pebble-jshintrc'), 'w') as jshint:
            jshint.write(generate_jshint_file(project))
    elif project.project_type == 'simplyjs':
        # SimplyJS is a particularly special case
        assemble_simplyjs_sources(project, base_dir, build_result)
    elif project.project_type == 'pebblejs':
        # PebbleJS projects have to import the entire pebblejs library, including its wscript
        assemble_resource_directories(project, base_dir)
        shutil.rmtree(base_dir)
        shutil.copytree(settings.PEBBLEJS_ROOT, base_dir)
        assemble_resources(base_dir, project.resources_path, resources, type_restrictions=('png', 'bitmap'))
        assemble_source_files(project, base_dir)

    # All projects have a manifest
    manifest_filename = manifest_name_for_project(project)
    manifest_dict = generate_manifest_dict(project, resources)

    with open(os.path.join(base_dir, manifest_filename), 'w') as f:
        f.write(json.dumps(manifest_dict))
Example #5
0
def add_project_to_archive(z, project, prefix=''):
    source_files = SourceFile.objects.filter(project=project)
    resources = ResourceFile.objects.filter(project=project)
    prefix += re.sub(r'[^\w]+', '_', project.name).strip('_').lower()

    for source in source_files:
        src_dir = 'worker_src' if source.target == 'worker' else 'src'
        z.writestr('%s/%s/%s' % (prefix, src_dir, source.file_name), source.get_contents())

    for resource in resources:
        res_path = 'resources'
        z.writestr('%s/%s/%s' % (prefix, res_path, resource.path), resource.get_contents())

    manifest = generate_manifest(project, resources)
    z.writestr('%s/appinfo.json' % prefix, manifest)
    if project.project_type == 'native':
        # This file is always the same, but needed to build.
        z.writestr('%s/wscript' % prefix, generate_wscript_file(project, for_export=True))
        z.writestr('%s/jshintrc' % prefix, generate_jshint_file(project))
Example #6
0
def add_project_to_archive(z, project, prefix=''):
    source_files = SourceFile.objects.filter(project=project)
    resources = ResourceFile.objects.filter(project=project)
    prefix += re.sub(r'[^\w]+', '_', project.name).strip('_').lower()

    for source in source_files:
        path = os.path.join(prefix, source.project_path)
        z.writestr(path, source.get_contents())

    for resource in resources:
        for variant in resource.variants.all():
            z.writestr('%s/%s/%s' % (prefix, project.resources_path, variant.path), variant.get_contents())

    manifest = generate_manifest(project, resources)
    manifest_name = manifest_name_for_project(project)
    z.writestr('%s/%s' % (prefix, manifest_name), manifest)
    if project.is_standard_project_type:
        # This file is always the same, but needed to build.
        z.writestr('%s/wscript' % prefix, generate_wscript_file(project, for_export=True))
        z.writestr('%s/jshintrc' % prefix, generate_jshint_file(project))
Example #7
0
def add_project_to_archive(z, project, prefix=""):
    source_files = SourceFile.objects.filter(project=project)
    resources = ResourceFile.objects.filter(project=project)
    prefix += re.sub(r"[^\w]+", "_", project.name).strip("_").lower()

    for source in source_files:
        src_dir = "worker_src" if source.target == "worker" else "src"
        z.writestr("%s/%s/%s" % (prefix, src_dir, source.file_name), source.get_contents())

    for resource in resources:
        res_path = "resources"
        for variant in resource.variants.all():
            z.writestr("%s/%s/%s" % (prefix, res_path, variant.path), variant.get_contents())

    manifest = generate_manifest(project, resources)
    z.writestr("%s/appinfo.json" % prefix, manifest)
    if project.project_type == "native":
        # This file is always the same, but needed to build.
        z.writestr("%s/wscript" % prefix, generate_wscript_file(project, for_export=True))
        z.writestr("%s/jshintrc" % prefix, generate_jshint_file(project))
Example #8
0
def add_project_to_archive(z, project, prefix='', suffix=''):
    source_files = SourceFile.objects.filter(project=project)
    resources = ResourceFile.objects.filter(project=project)
    prefix += re.sub(r'[^\w]+', '_', project.name).strip('_').lower()
    prefix += suffix

    for source in source_files:
        path = os.path.join(prefix, source.project_path)
        z.writestr(path, source.get_contents())

    for resource in resources:
        for variant in resource.variants.all():
            z.writestr('%s/%s/%s' % (prefix, project.resources_path, variant.path), variant.get_contents())

    manifest = generate_manifest(project, resources)
    manifest_name = manifest_name_for_project(project)
    z.writestr('%s/%s' % (prefix, manifest_name), manifest)
    if project.is_standard_project_type:
        # This file is always the same, but needed to build.
        z.writestr('%s/wscript' % prefix, generate_wscript_file(project, for_export=True))
        z.writestr('%s/jshintrc' % prefix, generate_jshint_file(project))
Example #9
0
def add_project_to_archive(z, project, prefix=''):
    source_files = SourceFile.objects.filter(project=project)
    resources = ResourceFile.objects.filter(project=project)
    prefix += re.sub(r'[^\w]+', '_', project.name).strip('_').lower()

    for source in source_files:
        z.writestr('%s/src/%s' % (prefix, source.file_name), source.get_contents())

    for resource in resources:
        res_path = 'resources/src' if project.sdk_version == '1' else 'resources'
        z.writestr('%s/%s/%s' % (prefix, res_path, resource.path), resource.get_contents())

    if project.sdk_version == '1':
        resource_map = generate_resource_map(project, resources)
        z.writestr('%s/resources/src/resource_map.json' % prefix, resource_map)
    else:
        manifest = generate_v2_manifest(project, resources)
        z.writestr('%s/appinfo.json' % prefix, manifest)
        # This file is always the same, but needed to build.
        z.writestr('%s/wscript' % prefix, generate_wscript_file(project, for_export=True))
        z.writestr('%s/jshintrc' % prefix, generate_jshint_file(project))
Example #10
0
def add_project_to_archive(z, project, prefix=''):
    source_files = SourceFile.objects.filter(project=project)
    resources = ResourceFile.objects.filter(project=project)
    prefix += re.sub(r'[^\w]+', '_', project.name).strip('_').lower()

    for source in source_files:
        z.writestr('%s/src/%s' % (prefix, source.file_name),
                   source.get_contents())

    for resource in resources:
        res_path = 'resources/src' if project.sdk_version == '1' else 'resources'
        z.writestr('%s/%s/%s' % (prefix, res_path, resource.path),
                   resource.get_contents())

    if project.sdk_version == '1':
        resource_map = generate_resource_map(project, resources)
        z.writestr('%s/resources/src/resource_map.json' % prefix, resource_map)
    else:
        manifest = generate_v2_manifest(project, resources)
        z.writestr('%s/appinfo.json' % prefix, manifest)
        # This file is always the same, but needed to build.
        z.writestr('%s/wscript' % prefix,
                   generate_wscript_file(project, for_export=True))
        z.writestr('%s/jshintrc' % prefix, generate_jshint_file(project))
Example #11
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)

    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, 'appinfo.json'),
                 '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, 'appinfo.json'),
                 '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 != 'png':
                    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.copy_to_path(ResourceVariant.VARIANT_DEFAULT, abs_target)

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

        # Build the thing
        cwd = os.getcwd()
        success = False
        output = 'Failed to get output'
        build_start_time = now()
        try:
            os.chdir(base_dir)
            if project.sdk_version == '2':
                tool = settings.SDK2_PEBBLE_TOOL
            elif project.sdk_version == '3':
                tool = settings.SDK3_PEBBLE_TOOL
            else:
                raise Exception("invalid sdk version.")
            output = subprocess.check_output([tool, "build"],
                                             stderr=subprocess.STDOUT,
                                             preexec_fn=_set_resource_limits)
        except subprocess.CalledProcessError as e:
            output = e.output
            print output
            success = False
        except Exception as e:
            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
                print "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(build_result, 'aplite', z)
                        store_size_info(build_result, 'basalt', z)

                except Exception as e:
                    print "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'))

                build_result.save_pbw(temp_file)
            build_result.save_build_log(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_keen_event(['cloudpebble', 'sdk'],
                            event_name,
                            data,
                            project=project)

    except Exception as e:
        print "Build failed due to internal error: %s" % e
        traceback.print_exc()
        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)
        print base_dir
Example #12
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)

    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
            src_dir = os.path.join(base_dir, 'src')
            os.mkdir(src_dir)
            create_source_files(source_files, src_dir)

            manifest_dict = generate_v2_manifest_dict(project, resources)
            open(os.path.join(base_dir, 'appinfo.json'), '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))
                if not abs_target.startswith(target_dir):
                    raise Exception("Suspicious filename: %s" % f.file_name)
                f.copy_to_path(abs_target)

            # 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, 'appinfo.json'), '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(source_files, os.path.join(base_dir, 'src', 'js'))

            for f in resources:
                if f.kind != 'png':
                    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.copy_to_path(abs_target)

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

        # Build the thing
        cwd = os.getcwd()
        success = False
        output = 'Failed to get output'
        build_start_time = now()
        try:
            os.chdir(base_dir)
            output = subprocess.check_output([settings.PEBBLE_TOOL, "build"], stderr=subprocess.STDOUT, preexec_fn=_set_resource_limits)
        except subprocess.CalledProcessError as e:
            output = e.output
            print output
            success = False
        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
                print "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:
                        build_result.binary_size = z.getinfo('pebble-app.bin').file_size
                        build_result.resource_size = z.getinfo('app_resources.pbpack').file_size
                except Exception as e:
                    print "Couldn't extract filesizes: %s" % e
                # Try pulling out debug information.
                elf_file = os.path.join(base_dir, 'build', 'pebble-app.elf')
                if os.path.exists(elf_file):
                    try:
                        debug_info = apptools.addr2lines.create_coalesced_group(elf_file)
                    except:
                        print traceback.format_exc()
                    else:
                        build_result.save_debug_info(debug_info)

                build_result.save_pbw(temp_file)
            build_result.save_build_log(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_keen_event(['cloudpebble', 'sdk'], event_name, data, project=project)

    except Exception as e:
        print "Build failed due to internal error: %s" % e
        traceback.print_exc()
        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)
Example #13
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)

    if project.sdk_version == '1':
        build_result.state = BuildResult.STATE_FAILED
        build_result.finished = now()
        build_result.save()
        return

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

    try:
        if project.project_type == 'native':
            # Source code
            src_dir = os.path.join(base_dir, 'src')
            os.mkdir(src_dir)
            create_source_files(source_files, src_dir)
            # 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'))

            manifest_dict = generate_v2_manifest_dict(project, resources)
            open(os.path.join(base_dir, 'appinfo.json'),
                 '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))
                if not abs_target.startswith(target_dir):
                    raise Exception("Suspicious filename: %s" % f.file_name)
                f.copy_to_path(abs_target)

            # 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':
            os.rmdir(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, 'appinfo.json'),
                 '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':
            os.rmdir(base_dir)
            shutil.copytree(settings.PEBBLEJS_ROOT, base_dir)
            manifest_dict = generate_pebblejs_manifest_dict(project)
            create_source_files(source_files,
                                os.path.join(base_dir, 'src', 'js'))

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

        # Build the thing
        cwd = os.getcwd()
        success = False
        output = 'Failed to get output'
        try:
            if settings.CHROOT_JAIL is not None:
                output = subprocess.check_output([
                    settings.CHROOT_JAIL, project.sdk_version,
                    base_dir[len(settings.CHROOT_ROOT):]
                ],
                                                 stderr=subprocess.STDOUT)
            else:
                os.chdir(base_dir)
                output = subprocess.check_output(
                    [settings.PEBBLE_TOOL, "build"],
                    stderr=subprocess.STDOUT,
                    preexec_fn=_set_resource_limits)
        except subprocess.CalledProcessError as e:
            output = e.output
            print output
            success = False
        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
                print "Success was a lie."
        finally:
            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:
                        build_result.binary_size = z.getinfo(
                            'pebble-app.bin').file_size
                        build_result.resource_size = z.getinfo(
                            'app_resources.pbpack').file_size
                except Exception as e:
                    print "Couldn't extract filesizes: %s" % e
                # Try pulling out debug information.
                elf_file = os.path.join(base_dir, 'build', 'pebble-app.elf')
                if os.path.exists(elf_file):
                    try:
                        debug_info = apptools.addr2lines.create_coalesced_group(
                            elf_file)
                    except:
                        print traceback.format_exc()
                    else:
                        build_result.save_debug_info(debug_info)

                build_result.save_pbw(temp_file)
                send_keen_event(
                    ['cloudpebble', 'sdk'],
                    'app_build_succeeded',
                    data={'data': {
                        'cloudpebble_build_id': build_result.id
                    }},
                    project=project)
            else:
                send_keen_event(
                    ['cloudpebble', 'sdk'],
                    'app_build_failed',
                    data={'data': {
                        'cloudpebble_build_id': build_result.id
                    }},
                    project=project)
            build_result.save_build_log(output)
            build_result.state = BuildResult.STATE_SUCCEEDED if success else BuildResult.STATE_FAILED
            build_result.finished = now()
            build_result.save()
    except Exception as e:
        print "Build failed due to internal error: %s" % e
        traceback.print_exc()
        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)
Example #14
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)

    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, 'appinfo.json'), '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, 'appinfo.json'), '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, 'appinfo.json'), 'w').write(json.dumps(manifest_dict))

        # Build the thing
        cwd = os.getcwd()
        success = False
        output = 'Failed to get output'
        build_start_time = now()
        try:
            os.chdir(base_dir)
            if project.sdk_version == '2':
                environ = os.environ
                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
            print output
            success = False
        except Exception as e:
            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
                print "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:
                    print "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)
            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_keen_event(['cloudpebble', 'sdk'], event_name, data, project=project)

    except Exception as e:
        print "Build failed due to internal error: %s" % e
        traceback.print_exc()
        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)
        print base_dir
Example #15
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)

    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, "appinfo.json"), "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, "appinfo.json"), "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 != "png":
                    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.copy_to_path(ResourceVariant.VARIANT_DEFAULT, abs_target)

            open(os.path.join(base_dir, "appinfo.json"), "w").write(json.dumps(manifest_dict))

        # Build the thing
        cwd = os.getcwd()
        success = False
        output = "Failed to get output"
        build_start_time = now()
        try:
            os.chdir(base_dir)
            if project.sdk_version == "2":
                tool = settings.SDK2_PEBBLE_TOOL
            elif project.sdk_version == "3":
                tool = settings.SDK3_PEBBLE_TOOL
            else:
                raise Exception("invalid sdk version.")
            output = subprocess.check_output([tool, "build"], stderr=subprocess.STDOUT, preexec_fn=_set_resource_limits)
        except subprocess.CalledProcessError as e:
            output = e.output
            print output
            success = False
        except Exception as e:
            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
                print "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(build_result, "aplite", z)
                        store_size_info(build_result, "basalt", z)

                except Exception as e:
                    print "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"),
                    )

                build_result.save_pbw(temp_file)
            build_result.save_build_log(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_keen_event(["cloudpebble", "sdk"], event_name, data, project=project)

    except Exception as e:
        print "Build failed due to internal error: %s" % e
        traceback.print_exc()
        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)
        print base_dir
Example #16
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)