Beispiel #1
0
def cancel_event(request, event_id):
    """
    Cancel all jobs attached to an event
    """
    if request.method != 'POST':
        return HttpResponseNotAllowed(['POST'])

    ev = get_object_or_404(models.Event, pk=event_id)
    allowed = Permissions.is_collaborator(request.session, ev.build_user, ev.base.repo())

    if not allowed:
        messages.error(request, 'You are not allowed to cancel this event')
        return redirect('ci:view_event', event_id=ev.pk)

    signed_in_user = ev.base.server().signed_in_user(request.session)
    comment = escape(request.POST.get("comment"))
    post_to_pr = request.POST.get("post_to_pr") == "on"
    event_url = reverse("ci:view_event", args=[ev.pk])
    message = "Parent <a href='%s'>event</a> canceled by %s" % (event_url, signed_in_user)
    if comment:
        message += " with comment: %s" % comment
    if post_to_pr:
        post_event_change_to_pr(request, ev, "canceled", comment, signed_in_user)

    event.cancel_event(ev, message, True)
    logger.info('Event {}: {} canceled by {}'.format(ev.pk, ev, signed_in_user))
    messages.info(request, 'Event {} canceled'.format(ev))

    return redirect('ci:view_event', event_id=ev.pk)
Beispiel #2
0
def activate_job(request, job_id):
    """
    Endpoint for activating a job
    """
    if request.method != 'POST':
        return HttpResponseNotAllowed(['POST'])

    job = get_object_or_404(models.Job, pk=job_id)
    server = job.recipe.repository.server()
    user = server.signed_in_user(request.session)
    if not user:
        raise PermissionDenied('You need to be signed in to activate a job')

    collab = Permissions.is_collaborator(request.session,
                                         job.event.build_user,
                                         job.recipe.repository,
                                         user=user)
    if collab:
        if set_job_active(request, job, user):
            job.init_pr_status()
        job.event.make_jobs_ready()
    else:
        raise PermissionDenied(
            'Activate job: {} is NOT a collaborator on {}'.format(
                user, job.recipe.repository))

    return redirect('ci:view_job', job_id=job.pk)
Beispiel #3
0
def activate_event(request, event_id):
    """
    Endpoint for activating all jobs on an event
    """
    if request.method != 'POST':
        return HttpResponseNotAllowed(['POST'])

    ev = get_object_or_404(models.Event, pk=event_id)
    jobs = ev.jobs.filter(active=False).order_by('-created')
    if jobs.count() == 0:
        messages.info(request, 'No jobs to activate')
        return redirect('ci:view_event', event_id=ev.pk)

    repo = jobs.first().recipe.repository
    user = repo.server().signed_in_user(request.session)
    if not user:
        raise PermissionDenied('You need to be signed in to activate jobs')

    collab = Permissions.is_collaborator(request.session, ev.build_user, repo, user=user)
    if collab:
        activated_jobs = []
        for j in jobs.all():
            if set_job_active(request, j, user):
                activated_jobs.append(j)
        for j in activated_jobs:
            j.init_pr_status()
        ev.make_jobs_ready()
    else:
        raise PermissionDenied('Activate event: {} is NOT a collaborator on {}'.format(user, repo))

    return redirect('ci:view_event', event_id=ev.pk)
Beispiel #4
0
def cancel_job(request, job_id):
    if request.method != 'POST':
        return HttpResponseNotAllowed(['POST'])

    job = get_object_or_404(models.Job, pk=job_id)
    allowed = Permissions.is_collaborator(request.session,
                                          job.event.build_user,
                                          job.event.base.repo())
    if not allowed:
        return HttpResponseForbidden('Not allowed to cancel this job')

    signed_in_user = job.event.base.server().signed_in_user(request.session)
    message = "Canceled by %s" % signed_in_user
    comment = escape(request.POST.get('comment'))

    post_to_pr = request.POST.get('post_to_pr') == 'on'
    if post_to_pr:
        post_job_change_to_pr(request, job, "canceled", comment,
                              signed_in_user)

    if comment:
        message += "\nwith comment: %s" % comment
    set_job_canceled(job, message)
    UpdateRemoteStatus.job_complete(job)
    logger.info('Job {}: {} on {} canceled by {}'.format(
        job.pk, job, job.recipe.repository, signed_in_user))
    messages.info(request, 'Job {} canceled'.format(job))
    return redirect('ci:view_job', job_id=job.pk)
Beispiel #5
0
def view_event(request, event_id):
    """
    Show the details of an Event
    """
    ev = get_object_or_404(EventsStatus.events_with_head(), pk=event_id)
    evs_info = EventsStatus.multiline_events_info([ev])
    allowed = Permissions.is_collaborator(request.session, ev.build_user, ev.base.repo())
    has_unactivated = ev.jobs.filter(active=False).count() != 0
    context = {'event': ev,
        'events': evs_info,
        'allowed_to_cancel': allowed,
        "update_interval": settings.EVENT_PAGE_UPDATE_INTERVAL,
        "has_unactivated": has_unactivated,
        }
    return render(request, 'ci/event.html', context)
Beispiel #6
0
def invalidate_event(request, event_id):
    """
    Invalidate all the jobs of an event.
    The user must be signed in.
    Input:
      request: django.http.HttpRequest
      event_id. models.Event.pk: PK of the event to be invalidated
    Return: django.http.HttpResponse based object
    """
    if request.method != 'POST':
        return HttpResponseNotAllowed(['POST'])

    ev = get_object_or_404(models.Event, pk=event_id)
    allowed = Permissions.is_collaborator(request.session, ev.build_user,
                                          ev.base.repo())
    if not allowed:
        messages.error(
            request,
            'You need to be signed in and be a collaborator to invalidate results.'
        )
        return redirect('ci:view_event', event_id=ev.pk)

    signed_in_user = ev.base.server().signed_in_user(request.session)
    comment = escape(request.POST.get("comment"))
    logger.info('Event {}: {} invalidated by {}'.format(
        ev.pk, ev, signed_in_user))
    event_url = reverse("ci:view_event", args=[ev.pk])
    message = "Parent <a href='%s'>event</a> invalidated by %s" % (
        event_url, signed_in_user)
    if comment:
        message += " with comment: %s" % comment

    post_to_pr = request.POST.get("post_to_pr") == "on"
    if post_to_pr:
        post_event_change_to_pr(request, ev, "invalidated", comment,
                                signed_in_user)

    same_client = request.POST.get('same_client') == "on"
    for job in ev.jobs.all():
        invalidate_job(request, job, message, same_client, check_ready=False)
    # Only do this once so that we get the job dependencies setup correctly.
    ev.make_jobs_ready()

    return redirect('ci:view_event', event_id=ev.pk)
Beispiel #7
0
def invalidate(request, job_id):
    """
    Invalidate the results of a Job.
    The user must be signed in.
    Input:
      request: django.http.HttpRequest
      job_id: models.Job.pk
    """
    if request.method != 'POST':
        return HttpResponseNotAllowed(['POST'])

    job = get_object_or_404(models.Job, pk=job_id)
    allowed = Permissions.is_collaborator(request.session,
                                          job.event.build_user,
                                          job.event.base.repo())
    if not allowed:
        raise PermissionDenied('You are not allowed to invalidate results.')
    same_client = request.POST.get('same_client') == 'on'
    selected_client = request.POST.get('client_list')
    comment = escape(request.POST.get('comment'))
    post_to_pr = request.POST.get('post_to_pr') == 'on'
    client = None
    if selected_client:
        try:
            client = models.Client.objects.get(pk=int(selected_client))
            same_client = True
        except:
            pass
    signed_in_user = job.event.base.server().signed_in_user(request.session)
    message = "Invalidated by %s" % signed_in_user
    if comment:
        message += "\nwith comment: %s" % comment

    if post_to_pr:
        post_job_change_to_pr(request, job, "invalidated", comment,
                              signed_in_user)

    logger.info('Job {}: {} on {} invalidated by {}'.format(
        job.pk, job, job.recipe.repository, signed_in_user))
    invalidate_job(request, job, message, same_client, client)
    return redirect('ci:view_job', job_id=job.pk)
Beispiel #8
0
def update_remote_job_status(request, job_id):
    """
    End point for manually update the remote status of a job.
    This is needed since sometimes the git server doesn't
    get updated properly due to timeouts, etc.
    """
    job = get_object_or_404(models.Job.objects, pk=job_id)
    allowed = Permissions.is_collaborator(request.session,
                                          job.event.build_user,
                                          job.event.base.repo())

    if request.method == "GET":
        return render(request, 'ci/job_update.html', {
            "job": job,
            "allowed": allowed
        })
    elif request.method == "POST":
        if allowed:
            UpdateRemoteStatus.job_complete_pr_status(job)
        else:
            return HttpResponseNotAllowed("Not allowed")
    return redirect('ci:view_job', job_id=job.pk)
Beispiel #9
0
def view_pr(request, pr_id):
    """
    Show the details of a PR
    Input:
      request: django.http.HttpRequest
      pr_id: pk of models.PullRequest
    Return:
      django.http.HttpResponse based object
    """
    pr = get_object_or_404(models.PullRequest.objects.select_related('repository__user'), pk=pr_id)
    ev = pr.events.select_related('build_user', 'base__branch__repository__user__server').latest()
    allowed = Permissions.is_collaborator(request.session, ev.build_user, ev.base.repo())
    current_alt = []
    alt_choices = []
    default_choices = []
    if allowed:
        alt_recipes = (models.Recipe.objects
                .filter(repository=pr.repository,
                    build_user=ev.build_user,
                    current=True,
                    active=True,
                    cause=models.Recipe.CAUSE_PULL_REQUEST_ALT,)
                .order_by("display_name"))

        default_recipes = (models.Recipe.objects
                .filter(repository=pr.repository,
                    build_user=ev.build_user,
                    current=True,
                    active=True,
                    cause=models.Recipe.CAUSE_PULL_REQUEST,)
                .order_by("display_name"))

        push_recipes = (models.Recipe.objects
                .filter(repository=pr.repository,
                    build_user=ev.build_user,
                    current=True,
                    active=True,
                    cause=models.Recipe.CAUSE_PUSH,)
                .order_by("display_name"))

        default_recipes = [r for r in default_recipes.all()]
        current_alt = [ r.pk for r in pr.alternate_recipes.all() ]
        current_default = [j.recipe.filename for j in pr.events.latest("created").jobs.all() ]
        push_map = {r.filename: r.branch for r in push_recipes.all()}
        alt_choices = []
        for r in alt_recipes:
            alt_choices.append({"recipe": r,
                "selected": r.pk in current_alt,
                "push_branch": push_map.get(r.filename),
                })

        default_choices = []
        for r in default_recipes:
            default_choices.append({"recipe": r,
                "pk": r.pk,
                "disabled": r.filename in current_default,
                "push_branch": push_map.get(r.filename),
                })

        if alt_choices and request.method == "POST":
            form_choices = [ (r.pk, r.display_name) for r in alt_recipes ]
            form = forms.AlternateRecipesForm(request.POST)
            form.fields["recipes"].choices = form_choices
            form_default_choices = []
            for r in default_choices:
                if not r["disabled"]:
                    form_default_choices.append((r["pk"], r["recipe"].display_name))
            form.fields["default_recipes"].choices = form_default_choices
            if form.is_valid():
                pr.alternate_recipes.clear()
                for pk in form.cleaned_data["recipes"]:
                    alt = models.Recipe.objects.get(pk=pk)
                    pr.alternate_recipes.add(alt)
                # do some saves to update the timestamp so that the javascript updater gets activated
                pr.save()
                pr.events.latest('created').save()
                messages.info(request, "Success")
                pr_event = PullRequestEvent.PullRequestEvent()
                selected_default_recipes = []
                if form.cleaned_data["default_recipes"]:
                    q = models.Recipe.objects.filter(pk__in=form.cleaned_data["default_recipes"])
                    selected_default_recipes = [r for r in q]
                pr_event.create_pr_alternates(pr, default_recipes=selected_default_recipes)
                # update the choices so the new form is correct
                current_alt = [ r.pk for r in pr.alternate_recipes.all() ]
                alt_choices = [ {"recipe": r, "selected": r.pk in current_alt} for r in alt_recipes ]
            else:
                messages.warning(request, "Invalid form")
                logger.warning("Invalid form")
                for field, errors in form.errors.items():
                    logger.warning("Form error in field: %s: %s" % (field, errors))

    events = EventsStatus.events_with_head(pr.events)
    evs_info = EventsStatus.multiline_events_info(events, events_url=True)
    context = { "pr": pr,
        "events": evs_info,
        "allowed": allowed,
        "update_interval": settings.EVENT_PAGE_UPDATE_INTERVAL,
        "alt_choices": alt_choices,
        "default_choices": default_choices,
        }
    return render(request, 'ci/pr.html', context)
Beispiel #10
0
    def _check_recipe(self, session, git_api, pr, ev, recipe):
        """
        Check if an individual recipe is active for the PR.
        If it is not then set a comment on the PR saying that they
        need to activate the recipe.
        Input:
          session[dict]: Session to store collaborator information
          git_api[GitAPI]: Git API for the build_user
          pr: models.PullRequest that we are processing
          ev: models.Event that is attached to this pull request
          recipe: models.Recipe that we need to process
        """
        if not recipe.active:
            return []
        active = False
        server = pr.repository.user.server
        if recipe.automatic == models.Recipe.FULL_AUTO:
            active = True
        elif recipe.automatic == models.Recipe.MANUAL:
            active = False
        elif recipe.automatic == models.Recipe.AUTO_FOR_AUTHORIZED:
            if ev.trigger_user:
                pr_user, created = models.GitUser.objects.get_or_create(
                    name=ev.trigger_user, server=server)
                if pr_user in recipe.auto_authorized.all():
                    active = True
                else:
                    active = Permissions.is_collaborator(session,
                                                         recipe.build_user,
                                                         recipe.repository,
                                                         user=pr_user)
                if active:
                    logger.info(
                        'User {} is allowed to activate recipe: {}: {}'.format(
                            pr_user, recipe.pk, recipe))
                else:
                    logger.info(
                        'User {} is NOT allowed to activate recipe {}: {}'.
                        format(pr_user, recipe.pk, recipe))
                if created:
                    pr_user.delete()
            else:
                logger.info(
                    'Recipe: {}: {}: not activated because trigger_user is blank'
                    .format(recipe.pk, recipe))

        jobs = []
        for config in recipe.build_configs.order_by("name").all():
            job, created = models.Job.objects.get_or_create(recipe=recipe,
                                                            event=ev,
                                                            config=config)
            if created:
                job.active = active
                job.ready = False
                job.complete = False
                if job.active:
                    job.status = models.JobStatus.NOT_STARTED
                else:
                    job.status = models.JobStatus.ACTIVATION_REQUIRED
                job.save()
                logger.info('Created job {}: {}: on {}'.format(
                    job.pk, job, recipe.repository))
                jobs.append(job)

            else:
                logger.info('Job {}: {}: on {} already exists'.format(
                    job.pk, job, recipe.repository))
        return jobs