Beispiel #1
0
def build_detail(build_id):
    build = ComplexLogic.get_build_safe(build_id)

    chroots = {}
    results_by_chroot = {}
    for chroot in build.build_chroots:
        chroots[chroot.name] = chroot.state
        results_by_chroot[chroot.name] = chroot.result_dir_url

    built_packages = None
    if build.built_packages:
        built_packages = build.built_packages.split("\n")

    output = {
        "output": "ok",
        "status": build.state,
        "project": build.copr.name,
        "owner": build.copr.user.name,
        "results": build.results,
        "built_pkgs": built_packages,
        "src_version": build.pkg_version,
        "chroots": chroots,
        "submitted_on": build.submitted_on,
        "started_on": build.min_started_on,
        "ended_on": build.max_ended_on,
        "src_pkg": build.pkgs,
        "submitted_by": build.user.name,
        "results_by_chroot": results_by_chroot
    }
    return flask.jsonify(output)
Beispiel #2
0
def reschedule_build_chroot():
    response = {}
    if "build_id" in flask.request.json and "chroot" in flask.request.json:
        build = ComplexLogic.get_build_safe(flask.request.json["build_id"])
    else:
        response["result"] = "bad request"
        response["msg"] = "Request missing  `build_id` and/or `chroot`"
        return flask.jsonify(response)

    if build:
        if build.canceled:
            response["result"] = "noop"
            response["msg"] = "build was cancelled, ignoring"
        else:
            chroot = flask.request.json["chroot"]
            build_chroot = build.chroots_dict_by_name.get(chroot)
            run_statuses = set([StatusEnum("starting"), StatusEnum("running")])
            if build_chroot and build_chroot.status in run_statuses:
                log.info("rescheduling build {} chroot: {}".format(build.id, build_chroot.name))
                BuildsLogic.update_state_from_dict(build, {
                    "chroot": chroot,
                    "status": StatusEnum("pending")
                })
                db.session.commit()
                response["result"] = "done"
            else:
                response["result"] = "noop"
                response["msg"] = "build is not in running states, ignoring"

    else:
        response["result"] = "noop"
        response["msg"] = "Build {} wasn't found".format(flask.request.json["build_id"])

    return flask.jsonify(response)
Beispiel #3
0
def process_rebuild(copr, build_id, view, url_on_success):
    source_build = ComplexLogic.get_build_safe(build_id)
    form = forms.BuildFormRebuildFactory.create_form_cls(copr.active_chroots)()

    if form.validate_on_submit():
        try:
            build_options = {
                "enable_net": form.enable_net.data,
                "timeout": form.timeout.data,
            }

            BuildsLogic.create_new_from_other_build(
                flask.g.user, copr, source_build,
                chroot_names=form.selected_chroots,
                **build_options
            )

        except (ActionInProgressException, InsufficientRightsException) as e:
            flask.flash(str(e), "error")
            db.session.rollback()
        else:
            flask.flash("New build has been created", "success")

            db.session.commit()

        return flask.redirect(url_on_success)
    else:
        return render_add_build(copr, form, view)
Beispiel #4
0
def process_copr_repeat_build(build_id, copr):
    build = ComplexLogic.get_build_safe(build_id)
    if not flask.g.user.can_build_in(build.copr):
        flask.flash("You are not allowed to repeat this build.")
    form = forms.BuildFormRebuildFactory.create_form_cls(build.chroots)(
        build_id=build_id,
        enable_net=build.enable_net,
    )
    # remove all checkboxes by default
    for ch in build.chroots:
        field = getattr(form, ch.name)
        field.data = False
    chroot_to_build = request.args.get("chroot")
    app.logger.debug("got param chroot: {}".format(chroot_to_build))
    if chroot_to_build:
        # set single checkbox if chroot query arg was provided
        if hasattr(form, chroot_to_build):
            getattr(form, chroot_to_build).data = True
    else:
        # set checkbox on the failed chroots
        chroots_to_select = set(ch.name for ch in build.get_chroots_by_status([
            helpers.StatusEnum('failed'),
            helpers.StatusEnum('canceled'),
        ]))

        for ch in build.chroots:
            if ch.name in chroots_to_select:
                getattr(form, ch.name).data = True
    return flask.render_template("coprs/detail/add_build/rebuild.html",
                                 copr=copr,
                                 build=build,
                                 form=form)
Beispiel #5
0
def dist_git_upload_completed():
    app.logger.debug(flask.request.json)
    build_id = flask.request.json.get("build_id")

    try:
        build = ComplexLogic.get_build_safe(build_id)
    except ObjectNotFound:
        return flask.jsonify({"updated": False})

    collected_branch_chroots = []
    for branch, git_hash in flask.request.json.get("branch_commits",
                                                   {}).items():
        branch_chroots = BuildsLogic.get_buildchroots_by_build_id_and_branch(
            build_id, branch)
        for ch in branch_chroots:
            ch.status = StatusEnum("pending")
            ch.git_hash = git_hash
            db.session.add(ch)
            collected_branch_chroots.append((ch.task_id))

    final_source_status = StatusEnum("succeeded")
    for ch in build.build_chroots:
        if ch.task_id not in collected_branch_chroots:
            final_source_status = StatusEnum("failed")
            ch.status = StatusEnum("failed")
            db.session.add(ch)

    build.source_status = final_source_status
    db.session.add(build)
    db.session.commit()

    BuildsLogic.delete_local_source(build)
    return flask.jsonify({"updated": True})
Beispiel #6
0
def process_copr_repeat_build(build_id, copr):
    build = ComplexLogic.get_build_safe(build_id)
    if not flask.g.user.can_build_in(build.copr):
        flask.flash("You are not allowed to repeat this build.")
    form = forms.BuildFormRebuildFactory.create_form_cls(build.chroots)(
        build_id=build_id, enable_net=build.enable_net,
    )
    # remove all checkboxes by default
    for ch in build.chroots:
        field = getattr(form, ch.name)
        field.data = False
    chroot_to_build = request.args.get("chroot")
    app.logger.debug("got param chroot: {}".format(chroot_to_build))
    if chroot_to_build:
        # set single checkbox if chroot query arg was provided
        if hasattr(form, chroot_to_build):
            getattr(form, chroot_to_build).data = True
    else:
        # set checkbox on the failed chroots
        chroots_to_select = set(ch.name for ch in build.get_chroots_by_status([
            helpers.StatusEnum('failed'), helpers.StatusEnum('canceled'),
        ]))

        for ch in build.chroots:
            if ch.name in chroots_to_select:
                getattr(form, ch.name).data = True
    return flask.render_template(
        "coprs/detail/add_build/rebuild.html",
        copr=copr, build=build, form=form)
Beispiel #7
0
 def factory(**build_options):
     source_build = ComplexLogic.get_build_safe(build_id)
     BuildsLogic.create_new_from_other_build(
         flask.g.user, copr, source_build,
         chroot_names=form.selected_chroots,
         **build_options
     )
Beispiel #8
0
def build_detail(build_id):
    build = ComplexLogic.get_build_safe(build_id)

    chroots = {}
    results_by_chroot = {}
    for chroot in build.build_chroots:
        chroots[chroot.name] = chroot.state
        results_by_chroot[chroot.name] = chroot.result_dir_url

    built_packages = None
    if build.built_packages:
        built_packages = build.built_packages.split("\n")

    output = {
        "output": "ok",
        "status": build.state,
        "project": build.copr.name,
        "owner": build.copr.owner.name,
        "results": build.results,
        "built_pkgs": built_packages,
        "src_version": build.pkg_version,
        "chroots": chroots,
        "submitted_on": build.submitted_on,
        "started_on": build.min_started_on,
        "ended_on": build.ended_on,
        "src_pkg": build.pkgs,
        "submitted_by": build.user.name,
        "results_by_chroot": results_by_chroot
    }
    return flask.jsonify(output)
Beispiel #9
0
def build_detail(build_id):
    build = ComplexLogic.get_build_safe(build_id)

    chroots = {}
    results_by_chroot = {}
    for chroot in build.build_chroots:
        chroots[chroot.name] = chroot.state
        results_by_chroot[chroot.name] = chroot.result_dir_url

    built_packages = None
    if build.built_packages:
        built_packages = build.built_packages.split("\n")

    output = {
        "output": "ok",
        "status": build.state,
        "project": build.copr_name,
        "project_dirname": build.copr_dirname,
        "owner": build.copr.owner_name,
        "results":
        build.copr.repo_url,  # TODO: in new api return build results url
        "built_pkgs": built_packages,
        "src_version": build.pkg_version,
        "chroots": chroots,
        "submitted_on": build.submitted_on,
        "started_on": build.min_started_on,
        "ended_on": build.max_ended_on,
        "src_pkg": build.pkgs,
        "submitted_by": build.user.name
        if build.user else None,  # there is no user for webhook builds
        "results_by_chroot": results_by_chroot
    }
    return flask.jsonify(output)
Beispiel #10
0
def reschedule_build_chroot():
    response = {}
    if "build_id" in flask.request.json and "chroot" in flask.request.json:
        build = ComplexLogic.get_build_safe(flask.request.json["build_id"])
    else:
        response["result"] = "bad request"
        response["msg"] = "Request missing  `build_id` and/or `chroot`"
        return flask.jsonify(response)

    if build:
        if build.canceled:
            response["result"] = "noop"
            response["msg"] = "build was cancelled, ignoring"
        else:
            chroot = flask.request.json["chroot"]
            build_chroot = build.chroots_dict_by_name.get(chroot)
            run_statuses = set([StatusEnum("starting"), StatusEnum("running")])
            if build_chroot and build_chroot.status in run_statuses:
                log.info("rescheduling build {} chroot: {}".format(build.id, build_chroot.name))
                BuildsLogic.update_state_from_dict(build, {
                    "chroot": chroot,
                    "status": StatusEnum("pending")
                })
                db.session.commit()
                response["result"] = "done"
            else:
                response["result"] = "noop"
                response["msg"] = "build is not in running states, ignoring"

    else:
        response["result"] = "noop"
        response["msg"] = "Build {} wasn't found".format(flask.request.json["build_id"])

    return flask.jsonify(response)
Beispiel #11
0
def process_rebuild(copr, build_id, view, url_on_success):
    source_build = ComplexLogic.get_build_safe(build_id)
    form = forms.BuildFormRebuildFactory.create_form_cls(copr.active_chroots)()

    if form.validate_on_submit():
        try:
            build_options = {
                "enable_net": form.enable_net.data,
                "timeout": form.timeout.data,
            }

            BuildsLogic.create_new_from_other_build(
                flask.g.user,
                copr,
                source_build,
                chroot_names=form.selected_chroots,
                **build_options)

        except (ActionInProgressException, InsufficientRightsException) as e:
            flask.flash(str(e), "error")
            db.session.rollback()
        else:
            flask.flash("New build has been created", "success")

            db.session.commit()

        return flask.redirect(url_on_success)
    else:
        return render_add_build(copr, form, view)
Beispiel #12
0
 def factory(**build_options):
     source_build = ComplexLogic.get_build_safe(build_id)
     BuildsLogic.create_new_from_other_build(
         flask.g.user,
         copr,
         source_build,
         chroot_names=form.selected_chroots,
         **build_options)
Beispiel #13
0
def cancel_build(build_id):
    build = ComplexLogic.get_build_safe(build_id)

    try:
        builds_logic.BuildsLogic.cancel_build(flask.g.user, build)
        db.session.commit()
    except exceptions.InsufficientRightsException as e:
        raise LegacyApiError("Invalid request: {}".format(e))

    output = {'output': 'ok', 'status': "Build canceled"}
    return flask.jsonify(output)
Beispiel #14
0
def cancel_build(build_id):
    build = ComplexLogic.get_build_safe(build_id)

    try:
        builds_logic.BuildsLogic.cancel_build(flask.g.user, build)
        db.session.commit()
    except exceptions.InsufficientRightsException as e:
        raise LegacyApiError("Invalid request: {}".format(e))

    output = {'output': 'ok', 'status': "Build canceled"}
    return flask.jsonify(output)
Beispiel #15
0
def copr_delete_build(username, coprname, build_id):
    build = ComplexLogic.get_build_safe(build_id)

    try:
        builds_logic.BuildsLogic.delete_build(flask.g.user, build)
    except (InsufficientRightsException, ActionInProgressException) as e:
        flask.flash(str(e), "error")
    else:
        db.session.commit()
        flask.flash("Build has been deleted successfully.", "success")

    return flask.redirect(url_for_copr_builds(build.copr))
Beispiel #16
0
def copr_delete_build(username, coprname, build_id):
    build = ComplexLogic.get_build_safe(build_id)

    try:
        builds_logic.BuildsLogic.delete_build(flask.g.user, build)
    except (InsufficientRightsException, ActionInProgressException) as e:
        flask.flash(str(e), "error")
    else:
        db.session.commit()
        flask.flash("Build has been deleted successfully.", "success")

    return flask.redirect(url_for_copr_builds(build.copr))
Beispiel #17
0
def reschedule_build_chroot():
    response = {}
    build_id = flask.request.json.get("build_id")
    task_id = flask.request.json.get("task_id")
    chroot = flask.request.json.get("chroot")

    try:
        build = ComplexLogic.get_build_safe(build_id)
    except ObjectNotFound:
        response["result"] = "noop"
        response["msg"] = "Build {} wasn't found".format(build_id)
        return flask.jsonify(response)

    if build.canceled:
        response["result"] = "noop"
        response["msg"] = "build was cancelled, ignoring"
        return flask.jsonify(response)

    run_statuses = set([StatusEnum("starting"), StatusEnum("running")])

    if task_id == build.task_id:
        if build.source_status in run_statuses:
            log.info("rescheduling srpm build {}".format(build.id))
            BuildsLogic.update_state_from_dict(build, {
                "task_id": task_id,
                "status": StatusEnum("pending")
            })
            db.session.commit()
            response["result"] = "done"
        else:
            response["result"] = "noop"
            response["msg"] = "build is not in running states, ignoring"
    else:
        build_chroot = build.chroots_dict_by_name.get(chroot)
        if build_chroot and build_chroot.status in run_statuses:
            log.info("rescheduling build {} chroot: {}".format(
                build.id, build_chroot.name))
            BuildsLogic.update_state_from_dict(
                build, {
                    "task_id": task_id,
                    "chroot": chroot,
                    "status": StatusEnum("pending")
                })
            db.session.commit()
            response["result"] = "done"
        else:
            response["result"] = "noop"
            response["msg"] = "build chroot is not in running states, ignoring"

    return flask.jsonify(response)
Beispiel #18
0
def copr_build_redirect(build_id):
    build = ComplexLogic.get_build_safe(build_id)
    copr = build.copr
    if copr.is_a_group_project:
        return flask.redirect(url_for(
            "coprs_ns.group_copr_build",
            group_name=build.copr.group.name,
            coprname=build.copr.name,
            build_id=build_id))
    else:
        return flask.redirect(url_for(
            "coprs_ns.copr_build",
            username=build.copr.user.name,
            coprname=build.copr.name,
            build_id=build_id))
Beispiel #19
0
def copr_build_redirect(build_id):
    build = ComplexLogic.get_build_safe(build_id)
    copr = build.copr
    if copr.is_a_group_project:
        return flask.redirect(
            url_for("coprs_ns.group_copr_build",
                    group_name=build.copr.group.name,
                    coprname=build.copr.name,
                    build_id=build_id))
    else:
        return flask.redirect(
            url_for("coprs_ns.copr_build",
                    username=build.copr.user.name,
                    coprname=build.copr.name,
                    build_id=build_id))
Beispiel #20
0
def copr_delete_builds(copr):
    build_ids = flask.request.form.getlist("build_ids[]")

    for build_id in build_ids:
        build = ComplexLogic.get_build_safe(build_id)
        try:
            builds_logic.BuildsLogic.delete_build(flask.g.user, build)
        except (InsufficientRightsException, ActionInProgressException) as e:
            flask.flash(str(e), "error")

    db.session.commit()
    build_ids_str = ", ".join(build_ids).strip(", ")
    flask.flash(
        "Builds {} have been deleted successfully.".format(build_ids_str),
        "success")
    return flask.jsonify({"msg": "success"})
Beispiel #21
0
def copr_delete_builds(copr):
    build_ids = flask.request.form.getlist("build_ids[]")

    to_delete = []
    for build_id in build_ids:
        build = ComplexLogic.get_build_safe(build_id)
        to_delete.append(build)

    builds_logic.BuildsLogic.delete_multiple_builds(flask.g.user, to_delete)

    db.session.commit()
    build_ids_str = ", ".join(build_ids).strip(", ")
    flask.flash(
        "Builds {} have been deleted successfully.".format(build_ids_str),
        "success")
    return flask.jsonify({"msg": "success"})
Beispiel #22
0
def starting_build():
    """
    Check if the build is not cancelled and set it to starting state
    """
    data = flask.request.json

    try:
        build = ComplexLogic.get_build_safe(data.get('build_id'))
    except ObjectNotFound:
        return flask.jsonify({"can_start": False})

    if build.canceled:
        return flask.jsonify({"can_start": False})

    BuildsLogic.update_state_from_dict(build, data)
    db.session.commit()
    return flask.jsonify({"can_start": True})
Beispiel #23
0
def process_copr_repeat_build(build_id, copr):
    build = ComplexLogic.get_build_safe(build_id)
    if not flask.g.user.can_build_in(build.copr):
        flask.flash("You are not allowed to repeat this build.")

    if build.source_type == helpers.BuildSourceEnum('srpm_upload'):
        # If the original build's source is 'srpm_upload', we will show only the
        # original build's chroots and skip import.
        available_chroots = build.chroots

    else:
        # For all other sources, we will show all chroots enabled in the project
        # and proceed with import.
        available_chroots = copr.active_chroots

    form = forms.BuildFormRebuildFactory.create_form_cls(available_chroots)(
        build_id=build_id, enable_net=build.enable_net)

    # remove all checkboxes by default
    for ch in available_chroots:
        field = getattr(form, ch.name)
        field.data = False
    chroot_to_build = request.args.get("chroot")
    app.logger.debug("got param chroot: {}".format(chroot_to_build))
    if chroot_to_build:
        # set single checkbox if chroot query arg was provided
        if hasattr(form, chroot_to_build):
            getattr(form, chroot_to_build).data = True
    else:
        build_chroot_names = set(ch.name for ch in build.chroots)
        build_failed_chroot_names = set(ch.name
                                        for ch in build.get_chroots_by_status([
                                            helpers.StatusEnum('failed'),
                                            helpers.StatusEnum('canceled'),
                                        ]))
        for ch in available_chroots:
            # check checkbox on all the chroots that have not been (successfully) built before
            if (ch.name not in build_chroot_names) or (
                    ch.name in build_failed_chroot_names):
                getattr(form, ch.name).data = True
    return flask.render_template("coprs/detail/add_build/rebuild.html",
                                 copr=copr,
                                 build=build,
                                 form=form)
Beispiel #24
0
def defer_build():
    """
    Defer build (keep it out of waiting jobs for some time).
    """

    result = {"was_deferred": False}

    if "build_id" in flask.request.json and "chroot" in flask.request.json:
        build = ComplexLogic.get_build_safe(flask.request.json["build_id"])
        chroot = flask.request.json.get("chroot")

        if build and chroot:
            log.info("Defer build {}, chroot {}".format(build.id, chroot))
            BuildsLogic.update_state_from_dict(build, {
                "chroot": chroot,
                "last_deferred": int(time.time()),
            })
            db.session.commit()
            result["was_deferred"] = True

    return flask.jsonify(result)
Beispiel #25
0
def starting_build():
    """
    Check if the build is not cancelled and set it to running state
    """

    result = {"can_start": False}

    if "build_id" in flask.request.json and "chroot" in flask.request.json:
        build = ComplexLogic.get_build_safe(flask.request.json["build_id"])
        chroot = flask.request.json.get("chroot")

        if build and chroot and not build.canceled:
            log.info("mark build {} chroot {} as starting".format(build.id, chroot))
            BuildsLogic.update_state_from_dict(build, {
                "chroot": chroot,
                "status": StatusEnum("starting")
            })
            db.session.commit()
            result["can_start"] = True

    return flask.jsonify(result)
Beispiel #26
0
def starting_build():
    """
    Check if the build is not cancelled and set it to running state
    """

    result = {"can_start": False}

    if "build_id" in flask.request.json and "chroot" in flask.request.json:
        build = ComplexLogic.get_build_safe(flask.request.json["build_id"])
        chroot = flask.request.json.get("chroot")

        if build and chroot and not build.canceled:
            log.info("mark build {} chroot {} as starting".format(build.id, chroot))
            BuildsLogic.update_state_from_dict(build, {
                "chroot": chroot,
                "status": StatusEnum("starting")
            })
            db.session.commit()
            result["can_start"] = True

    return flask.jsonify(result)
Beispiel #27
0
def process_copr_repeat_build(build_id, copr):
    build = ComplexLogic.get_build_safe(build_id)
    if not flask.g.user.can_build_in(build.copr):
        flask.flash("You are not allowed to repeat this build.")

    if build.source_type == helpers.BuildSourceEnum('srpm_upload'):
        # If the original build's source is 'srpm_upload', we will show only the
        # original build's chroots and skip import.
        available_chroots = build.chroots

    else:
        # For all other sources, we will show all chroots enabled in the project
        # and proceed with import.
        available_chroots = copr.active_chroots

    form = forms.BuildFormRebuildFactory.create_form_cls(available_chroots)(
        build_id=build_id, enable_net=build.enable_net)

    # remove all checkboxes by default
    for ch in available_chroots:
        field = getattr(form, ch.name)
        field.data = False
    chroot_to_build = request.args.get("chroot")
    app.logger.debug("got param chroot: {}".format(chroot_to_build))
    if chroot_to_build:
        # set single checkbox if chroot query arg was provided
        if hasattr(form, chroot_to_build):
            getattr(form, chroot_to_build).data = True
    else:
        build_chroot_names = set(ch.name for ch in build.chroots)
        build_failed_chroot_names = set(ch.name for ch in build.get_chroots_by_status([
            helpers.StatusEnum('failed'), helpers.StatusEnum('canceled'),
        ]))
        for ch in available_chroots:
            # check checkbox on all the chroots that have not been (successfully) built before
            if (ch.name not in build_chroot_names) or (ch.name in build_failed_chroot_names):
                getattr(form, ch.name).data = True
    return flask.render_template(
        "coprs/detail/add_build/rebuild.html",
        copr=copr, build=build, form=form)
Beispiel #28
0
def copr_cancel_build(username, coprname, build_id):
    # only the user who ran the build can cancel it
    build = ComplexLogic.get_build_safe(build_id)
    return process_cancel_build(build)
Beispiel #29
0
def group_copr_cancel_build(group_name, coprname, build_id):
    build = ComplexLogic.get_build_safe(build_id)
    return process_cancel_build(build)
Beispiel #30
0
def get_build(build_id):
    build = ComplexLogic.get_build_safe(build_id)
    return render_build(build)
Beispiel #31
0
def build_status(build_id):
    build = ComplexLogic.get_build_safe(build_id)
    output = {"output": "ok", "status": build.state}
    return flask.jsonify(output)
Beispiel #32
0
def cancel_build(build_id):
    build = ComplexLogic.get_build_safe(build_id)
    BuildsLogic.cancel_build(flask.g.user, build)
    db.session.commit()
    return render_build(build)
Beispiel #33
0
def delete_build(build_id):
    build = ComplexLogic.get_build_safe(build_id)
    build_dict = to_dict(build)
    BuildsLogic.delete_build(flask.g.user, build)
    db.session.commit()
    return flask.jsonify(build_dict)
Beispiel #34
0
def build_status(build_id):
    build = ComplexLogic.get_build_safe(build_id)
    output = {"output": "ok",
              "status": build.state}
    return flask.jsonify(output)
Beispiel #35
0
def get_source_build_config(build_id):
    build = ComplexLogic.get_build_safe(build_id)
    return flask.jsonify(to_source_build_config(build))
Beispiel #36
0
def render_copr_build(build_id, copr):
    build = ComplexLogic.get_build_safe(build_id)
    return render_template("coprs/detail/build.html", build=build, copr=copr)
Beispiel #37
0
def render_copr_build(build_id, copr):
    build = ComplexLogic.get_build_safe(build_id)
    return render_template("coprs/detail/build.html", build=build, copr=copr)
Beispiel #38
0
def group_copr_cancel_build(group_name, coprname, build_id):
    build = ComplexLogic.get_build_safe(build_id)
    return process_cancel_build(build)
Beispiel #39
0
def copr_cancel_build(username, coprname, build_id):
    # only the user who ran the build can cancel it
    build = ComplexLogic.get_build_safe(build_id)
    return process_cancel_build(build)
Beispiel #40
0
def copr_build_redirect(build_id):
    build = ComplexLogic.get_build_safe(build_id)
    copr = build.copr
    return flask.redirect(
        helpers.copr_url("coprs_ns.copr_build", copr, build_id=build_id))