Beispiel #1
0
def do_retrigger(git_gecko, git_wpt, **kwargs):
    import errors
    import update
    import upstream
    from landing import load_sync_point, unlanded_with_type

    update_repositories(git_gecko, git_wpt, True)

    print("Retriggering upstream syncs with errors")
    for sync in upstream.UpstreamSync.load_all(git_gecko,
                                               git_wpt,
                                               status="open"):
        if sync.error:
            try:
                upstream.update_sync(git_gecko, git_wpt, sync)
            except errors.AbortError as e:
                print("Update failed:\n%s" % e)
                pass

    print("Retriggering downstream syncs on master")
    sync_point = load_sync_point(git_gecko, git_wpt)
    prev_wpt_head = sync_point["upstream"]
    unlandable = unlanded_with_type(git_gecko, git_wpt, None, prev_wpt_head)

    errors = update.retrigger(git_gecko, git_wpt, unlandable)
    if errors:
        print("The following PRs have errors:\n%s" % "\n".join(errors))
Beispiel #2
0
 def __call__(self, git_gecko, git_wpt):
     logger.info("Running retrigger")
     update_repositories(git_gecko, git_wpt)
     sync_point = landing.load_sync_point(git_gecko, git_wpt)
     prev_wpt_head = sync_point["upstream"]
     unlanded = landing.unlanded_with_type(git_gecko, git_gecko, None,
                                           prev_wpt_head)
     update.retrigger(git_gecko, git_wpt, unlanded)
Beispiel #3
0
 def __call__(self, git_gecko, git_wpt):
     newrelic.agent.set_transaction_name("RetriggerHandler")
     logger.info("Running retrigger")
     update_repositories(git_gecko, git_wpt)
     sync_point = landing.load_sync_point(git_gecko, git_wpt)
     prev_wpt_head = sync_point["upstream"]
     unlanded = landing.unlanded_with_type(git_gecko, git_gecko, None,
                                           prev_wpt_head)
     update.retrigger(git_gecko, git_wpt, unlanded)
Beispiel #4
0
def do_landable(git_gecko, git_wpt, *args, **kwargs):
    import update
    from base import LandableStatus
    from downstream import DownstreamAction, DownstreamSync
    from landing import load_sync_point, landable_commits, unlanded_with_type

    if kwargs["prev_wpt_head"] is None:
        sync_point = load_sync_point(git_gecko, git_wpt)
        prev_wpt_head = sync_point["upstream"]
        print("Last sync was to commit %s" % sync_point["upstream"])
    else:
        prev_wpt_head = kwargs["prev_wpt_head"]
    landable = landable_commits(
        git_gecko,
        git_wpt,
        prev_wpt_head,
        include_incomplete=kwargs["include_incomplete"])

    if landable is None:
        print("Landing will not add any new commits")
        wpt_head = None
    else:
        wpt_head, commits = landable
        print("Landing will update wpt head to %s, adding %i new PRs" %
              (wpt_head, len(commits)))

    if kwargs["all"] or kwargs["retrigger"]:
        unlandable = unlanded_with_type(git_gecko, git_wpt, wpt_head,
                                        prev_wpt_head)
        count = 0
        for pr, _, status in unlandable:
            count += 1
            msg = status.reason_str()
            if status == LandableStatus.missing_try_results:
                sync = DownstreamSync.for_pr(git_gecko, git_wpt, pr)
                next_action = sync.next_action
                reason = next_action.reason_str()
                if next_action == DownstreamAction.wait_try:
                    latest_try_push = sync.latest_try_push
                    reason = "%s %s" % (reason,
                                        latest_try_push.treeherder_url(
                                            latest_try_push.try_rev))
                msg = "%s (%s)" % (msg, reason)
            elif status == LandableStatus.error:
                sync = DownstreamSync.for_pr(git_gecko, git_wpt, pr)
                msg = "%s (%s)" % (msg, sync.error["message"].split("\n")[0])
            print("%s: %s" % (pr, msg))

        print("%i PRs are unlandable:" % count)

        if kwargs["retrigger"]:
            errors = update.retrigger(git_gecko, git_wpt, unlandable)
            if errors:
                print("The following PRs have errors:\n%s" % "\n".join(errors))
Beispiel #5
0
def update_modified_sync(git_gecko, git_wpt, sync):
    assert sync._lock is not None
    if len(sync.gecko_commits) == 0:
        # In the case that there are no gecko commits, we presumably had a backout
        # In this case we don't touch the wpt commits, but just mark the PR
        # as closed. That's pretty counterintuitive, but it turns out that GitHub
        # will only let you reopen a closed PR if you don't change the branch head in
        # the meantime. So we carefully avoid touching the wpt side until something
        # relands and we have a chance to reopen the PR
        logger.info("Sync has no commits, so marking as incomplete")
        sync.status = "incomplete"
        if not sync.pr:
            logger.info(
                "Sync was already fully applied upstream, not creating a PR")
            return
    else:
        sync.status = "open"
        try:
            sync.update_wpt_commits()
        except AbortError:
            # If we got a merge conflict and the PR doesn't exist yet then try
            # recreating the commits on top of the current sync point in order that
            # we get a PR and it's visible that it fails
            if not sync.pr:
                logger.info("Applying to origin/master failed; "
                            "retrying with the current sync point")
                from landing import load_sync_point
                sync_point = load_sync_point(git_gecko, git_wpt)
                sync.set_wpt_base(sync_point["upstream"])
                try:
                    sync.update_wpt_commits()
                except AbortError:
                    # Reset the base to origin/master
                    sync.set_wpt_base("origin/master")
                    with env.bz.bug_ctx(sync.bug) as bug:
                        bug.add_comment(
                            "Failed to create upstream wpt PR due to "
                            "merge conflicts. This requires fixup from a wpt sync "
                            "admin.")
                        needinfo_users = [
                            item.strip()
                            for item in (env.config["gecko"]["needinfo"].get(
                                "upstream", "").split(","))
                        ]
                        needinfo_users = [
                            item for item in needinfo_users if item
                        ]
                        bug.needinfo(*needinfo_users)
                    raise

    sync.update_github()
Beispiel #6
0
    def unlanded_commits_same_files(self):
        import landing

        sync_point = landing.load_sync_point(self.git_gecko, self.git_wpt)
        base = sync_point["upstream"]
        head = "origin/master"
        changed = self.wpt_commits.files_changed
        commits = []
        for commit in self.git_wpt.iter_commits("%s..%s" % (base, head),
                                                reverse=True,
                                                paths=list(changed)):
            commit = sync_commit.WptCommit(self.git_wpt, commit)
            # Check for same-pr rather than same-commit because we always
            # use the commits on the PR branch, not the merged commits.
            # The other option is to use the GH API to decide if the PR
            # merged and if so what the merge commit was, although in that
            # case we would still not know the commit prior to merge, which
            # is what we need
            if commit.pr() == str(self.pr):
                break
            commits.append(commit)
        return commits
Beispiel #7
0
def do_retrigger(git_gecko, git_wpt, **kwargs):
    import errors
    import update
    import upstream
    from landing import current, load_sync_point, unlanded_with_type

    update_repositories(git_gecko, git_wpt)

    if kwargs["upstream"]:
        print("Retriggering upstream syncs with errors")
        for sync in upstream.UpstreamSync.load_by_status(
                git_gecko, git_wpt, "open"):
            if sync.error:
                with SyncLock.for_process(sync.process_name) as lock:
                    with sync.as_mut(lock):
                        try:
                            upstream.update_sync(git_gecko,
                                                 git_wpt,
                                                 sync,
                                                 repo_update=False)
                        except errors.AbortError as e:
                            print("Update failed:\n%s" % e)
                            pass

    if kwargs["downstream"]:
        print("Retriggering downstream syncs on master")
        current_landing = current(git_gecko, git_wpt)
        if current_landing is None:
            sync_point = load_sync_point(git_gecko, git_wpt)
            prev_wpt_head = sync_point["upstream"]
        else:
            prev_wpt_head = current_landing.wpt_commits.head.sha1
        unlandable = unlanded_with_type(git_gecko, git_wpt, None,
                                        prev_wpt_head)

        errors = update.retrigger(git_gecko, git_wpt, unlandable)
        if errors:
            print("The following PRs have errors:\n%s" % "\n".join(errors))
Beispiel #8
0
def update_modified_sync(git_gecko, git_wpt, sync):
    if len(sync.gecko_commits) == 0:
        # In the case that there are no gecko commits, we presumably had a backout
        # In this case we don't touch the wpt commits, but just mark the PR
        # as closed. That's pretty counterintuitive, but it turns out that GitHub
        # will only let you reopen a closed PR if you don't change the branch head in
        # the meantime. So we carefully avoid touching the wpt side until something
        # relands and we have a chance to reopen the PR
        logger.info("Sync has no commits, so marking as incomplete")
        sync.status = "incomplete"
        if not sync.pr:
            logger.info(
                "Sync was already fully applied upstream, not creating a PR")
            return
    else:
        sync.status = "open"
        try:
            sync.update_wpt_commits()
        except AbortError:
            # If we got a merge conflict and the PR doesn't exist yet then try
            # recreating the commits on top of the current sync point in order that
            # we get a PR and it's visible that it fails
            if not sync.pr:
                logger.info("Applying to origin/master failed; "
                            "retrying with the current sync point")
                from landing import load_sync_point
                sync_point = load_sync_point(git_gecko, git_wpt)
                sync.set_wpt_base(sync_point["upstream"])
                try:
                    sync.update_wpt_commits()
                except AbortError:
                    # Reset the base to origin/master
                    sync.set_wpt_base("origin/master")
                    raise

    sync.update_github()
Beispiel #9
0
def update_pr(git_gecko, git_wpt, pr, force_rebase=False):
    sync = get_pr_sync(git_gecko, git_wpt, pr.number)

    if sync and sync.status == "complete":
        logger.info("Sync already landed")
        return
    if sync:
        logger.info("sync status %s" % sync.landable_status)
    sync_point = landing.load_sync_point(git_gecko, git_wpt)

    if not sync:
        # If this looks like something that came from gecko, create
        # a corresponding sync
        upstream_sync = upstream.UpstreamSync.from_pr(git_gecko, git_wpt, pr.number, pr.body)
        if upstream_sync is not None:
            upstream.update_pr(git_gecko, git_wpt, upstream_sync, pr.state, pr.merged)
        else:
            if pr.state != "open" and not pr.merged:
                return
            schedule_pr_task("opened", pr)
            update_for_status(pr)
    elif isinstance(sync, downstream.DownstreamSync):
        if force_rebase:
            sync.gecko_rebase(sync.gecko_integration_branch())

        if len(sync.wpt_commits) == 0:
            sync.update_wpt_commits()

        if not sync.bug and not (pr.state == "closed" and not pr.merged):
            sync.create_bug(git_wpt, pr.number, pr.title, pr.body)

        if pr.state == "open" or pr.merged:
            if pr.head.sha != sync.wpt_commits.head:
                # Upstream has different commits, so run a push handler
                schedule_pr_task("push", pr)

            elif sync.latest_valid_try_push:
                if not sync.latest_valid_try_push.taskgroup_id:
                    update_taskgroup_ids(git_gecko, git_wpt)

                if (sync.latest_valid_try_push.taskgroup_id and
                    not sync.latest_valid_try_push.status == "complete"):
                    update_tasks(git_gecko, git_wpt, sync=sync)

        if not pr.merged:
            update_for_status(pr)
        else:
            update_for_action(pr, "closed")

    elif isinstance(sync, upstream.UpstreamSync):
        merge_sha = pr.merge_commit_sha if pr.merged else None
        upstream.update_pr(git_gecko, git_wpt, sync, pr.state, merge_sha)
        sync.try_land_pr()
        if merge_sha:
            if git_wpt.is_ancestor(merge_sha, sync_point["upstream"]):
                # This sync already landed, so it should be finished
                sync.finish()
            else:
                if sync.status == "complete":
                    # We bypass the setter here because we have some cases where the
                    # status must go from complete to wpt-merged which is otherwise forbidden
                    sync._process_name.status = "wpt-merged"
                else:
                    sync.status = "wpt-merged"