def pushhook():
    payload_bytes = request.get_data()
    if request.form.get("_csrf_token"):
        # You should not be able to use a CSRF token for this
        abort(400)
    try:
        payload = json.loads(payload_bytes)
        assert isinstance(payload, dict)
        if payload.get("action", "push") != "push":
            logging.warning("Dropped GitHub pushhook payload because action was %s" %
                            str(payload.get("action")))
            return ('', 204)
        ref = payload["ref"]
        before = payload["before"]
        after = payload["after"]
        assert isinstance(ref, basestring)
        assert isinstance(before, basestring)
        assert isinstance(after, basestring)
        repo_name = payload["repository"]["name"]
        assert isinstance(repo_name, basestring)
        file_list = get_diff_file_list(repo_name, before, after)
        if not file_list:
            file_list = []

        # This is a useful hook to use, if you want to add custom logic to determine which jobs get
        # run on a Git push.
        #
        # Arguments:
        #   jobs           -- The original list of jobs (default: empty list)
        #   repo_name      -- The name of the repo that caused the pushhook
        #   ref            -- The name of the ref that was pushed (e.g. "refs/heads/master")
        #   modified_files -- A list of files that were changed in the push, relative to repo root
        #
        # Returns:
        #   A list of job names. (e.g. ["hw0", "hw0-style-check"])
        jobs_to_run = apply_filters("pushhooks-jobs-to-run", [], repo_name, ref, file_list)

        if not jobs_to_run:
            return ('', 204)

        # We could probably grab this from the payload, but let's call this method for the sake
        # of consistency.
        message = get_commit_message(repo_name, after)

        for job_to_run in jobs_to_run:
            while True:
                try:
                    with DbCursor() as c:
                        build_name = create_build(c, job_to_run, repo_name, after, message)
                    break
                except apsw.Error:
                    logging.exception("Failed to create build, retrying...")
            job = Job(build_name, repo_name, "GitHub push")
            dockergrader_queue.enqueue(job)
        return ('', 204)
    except Exception:
        logging.exception("Error occurred while processing GitHub pushhook payload")
        abort(500)
Exemple #2
0
def pushhook():
    payload_bytes = request.get_data()
    if request.form.get("_csrf_token"):
        # You should not be able to use a CSRF token for this
        abort(400)
    try:
        payload = json.loads(payload_bytes)
        assert isinstance(payload, dict)
        if payload.get("action", "push") != "push":
            logging.warning("Dropped GitHub pushhook payload because action was %s" % str(payload.get("action")))
            return ("", 204)
        ref = payload["ref"]
        before = payload["before"]
        after = payload["after"]
        assert isinstance(ref, basestring)
        assert isinstance(before, basestring)
        assert isinstance(after, basestring)
        repo_name = payload["repository"]["name"]
        assert isinstance(repo_name, basestring)
        file_list = get_diff_file_list(repo_name, before, after)
        if not file_list:
            file_list = []

        # This is a useful hook to use, if you want to add custom logic to determine which jobs get
        # run on a Git push.
        #
        # Arguments:
        #   jobs           -- The original list of jobs (default: empty list)
        #   repo_name      -- The name of the repo that caused the pushhook
        #   ref            -- The name of the ref that was pushed (e.g. "refs/heads/master")
        #   modified_files -- A list of files that were changed in the push, relative to repo root
        #
        # Returns:
        #   A list of job names. (e.g. ["hw0", "hw0-style-check"])
        jobs_to_run = apply_filters("pushhooks-jobs-to-run", [], repo_name, ref, file_list)

        if not jobs_to_run:
            return ("", 204)

        # We could probably grab this from the payload, but let's call this method for the sake
        # of consistency.
        message = get_commit_message(repo_name, after)

        for job_to_run in jobs_to_run:
            while True:
                try:
                    with DbCursor() as c:
                        build_name = create_build(c, job_to_run, repo_name, after, message)
                    break
                except apsw.Error:
                    logging.exception("Failed to create build, retrying...")
            job = Job(build_name, repo_name, "GitHub push")
            dockergrader_queue.enqueue(job)
        return ("", 204)
    except Exception:
        logging.exception("Error occurred while processing GitHub pushhook payload")
        abort(500)
Exemple #3
0
def build_now():
    job_name = request.form.get("f_job_name")
    repo = request.form.get("f_repo")
    assignment = get_assignment_by_name(job_name)
    if not assignment:
        abort(400)
    assignment = assignment.student_view(repo)
    if assignment.manual_grading:
        abort(400)

    with DbCursor() as c:
        student = _get_student(c)
        user_id, _, _, login, _, _ = student
        super_value = get_super(c, user_id)
        dropped = super_value is not None and super_value < 0
        if assignment.is_group:
            repos = get_groups(c, user_id)
        else:
            repos = [login]

        if repo not in repos:
            abort(403)

    if now_compare(assignment.not_visible_before,
                   add_grace_period(
                       assignment.cannot_build_after)) != 0 or dropped:
        abort(400)

    branch_hash = get_branch_hash(repo, "master")
    message = None
    if branch_hash:
        message = get_commit_message(repo, branch_hash)

    # This section doesn't absolutely NEED to be consistent with the previous transaction,
    # since we have not specified any actual data constraints. The only possible logical error
    # would be to fulfill a request when the current user's permissions have been revoked
    # between these two transactions.
    with DbCursor() as c:
        build_name = create_build(c, job_name, repo, branch_hash, message)

    if should_limit_source(repo, job_name):
        rate_limit_fail_build(build_name)
    else:
        job = Job(build_name, repo, "Web interface")
        dockergrader_queue.enqueue(job)

    return redirect(url_for("dashboard.builds_one", name=build_name))
Exemple #4
0
def build_now():
    job_name = request.form.get("f_job_name")
    repo = request.form.get("f_repo")
    assignment = get_assignment_by_name(job_name)
    if not assignment:
        abort(400)
    if assignment.manual_grading:
        abort(400)
    if now_compare(assignment.not_visible_before, assignment.cannot_build_after) != 0:
        abort(400)

    with DbCursor() as c:
        student = _get_student(c)
        user_id, _, _, login, _, _ = student
        if assignment.is_group:
            repos = get_groups(c, user_id)
        else:
            repos = [login]

        if repo not in repos:
            abort(403)

    branch_hash = get_branch_hash(repo, "master")
    message = None
    if branch_hash:
        message = get_commit_message(repo, branch_hash)

    # This section doesn't absolutely NEED to be consistent with the previous transaction,
    # since we have not specified any actual data constraints. The only possible logical error
    # would be to fulfill a request when the current user's permissions have been revoked
    # between these two transactions.
    with DbCursor() as c:
        build_name = create_build(c, job_name, repo, branch_hash, message)

    job = Job(build_name, repo, "Web interface")
    dockergrader_queue.enqueue(job)

    return redirect(url_for("dashboard.builds_one", name=build_name))