Пример #1
0
    def activate(self):
        super(Summit, self).activate()
        if not self.config:
            # ie. if the plugin is not configured, it cannot activate.
            return

        if ROOMS not in self:
            self[ROOMS] = {}
        self.gh = Github(self.config['github-token'], api_preview=True)
        self.queues = {}  # Those are MergeQueues
        self.rooms_lock = RLock()
        try:
            self.gh_status = self.get_plugin('GHStatus')
        except:
            self.log.info(
                "If you want notifications to your chat users on PRs you can install the companion plugin err-ghstatus."
            )
            self.gh_status = None

        # Reload the state from the storage.
        with self.mutable(ROOMS) as rooms:
            for room_name, repo in rooms.items():
                for room in self[ROOMS]:
                    self.queues[room] = MergeQueue(self.gh.get_repo(repo.name),
                                                   initial_queue=repo.queue)

        self.start_poller(120, method=self.check_pr_states)
Пример #2
0
def test_datadog_bindings():
    repo = FakeGHRepo()
    mq = MergeQueue(repo)
    from datadog_stats import Stats

    mq.stats = Stats(api_key="fdjkfdjkjkfd")
    assert type(mq.stats) == Stats
Пример #3
0
    def build_merge_queue(self):
        """Build a queue of node pairs to be merged in a specific priority.
        
        The queue elements have a specific format in order to allow 'removing'
        of specific elements inside the priority queue. Each element is a list
        of length 4 containing:
            - the merge priority (any ordered type)
            - a 'valid' flag
            - and the two nodes in arbitrary order
        The valid flag allows one to "remove" elements by setting the flag to
        False. Then one checks the flag when popping elements and ignores those
        marked as invalid.

        One other specific feature is that there are back-links from edges to
        their corresponding queue items so that when nodes are merged,
        affected edges can be invalidated and reinserted in the queue.
        """
        queue_items = []
        for l1, l2 in self.real_edges_iter():
            w = self.merge_priority_function(self, l1, l2)
            qitem = [w, True, l1, l2]
            queue_items.append(qitem)
            self[l1][l2]['qlink'] = qitem
            self[l1][l2]['weight'] = w
        return MergeQueue(queue_items, with_progress=self.show_progress)
Пример #4
0
def test_bless_pr():
    mq = MergeQueue(FakeGHRepo())
    mq.ask_pr(12)
    mq.bless_pr(12)
    assert mq.queue[0].blessed

    with pytest.raises(MergeQueueException):
        mq.bless_pr(13)
Пример #5
0
def test_askpr():
    mq = MergeQueue(FakeGHRepo())
    mq.ask_pr(13)
    assert len(mq.queue) == 1
    assert mq.queue[0].nb == 13
    with pytest.raises(MergeQueueException):
        mq.ask_pr(13)
    assert len(mq.queue) == 1
Пример #6
0
def test_simple_rmpr():
    mq = MergeQueue(FakeGHRepo())
    mq.ask_pr(12)
    assert len(mq.queue) == 1

    mq.rm_pr(12)
    assert len(mq.queue) == 0

    with pytest.raises(MergeQueueException):
        mq.rm_pr(14)
Пример #7
0
def test_sink_pr():
    mq = MergeQueue(FakeGHRepo())
    mq.ask_pr(12)
    mq.ask_pr(13)
    assert mq.queue[0].nb == 12
    mq.sink_pr(12)
    assert mq.queue[0].nb == 13
    assert mq.queue[1].nb == 12

    with pytest.raises(MergeQueueException):
        mq.sink_pr(14)
Пример #8
0
def test_check_merged_externally():
    pr_14 = FakeGHPullRequest(14)
    repo = FakeGHRepo(injected_prs=[pr_14])
    mq = MergeQueue(repo)
    mq.ask_pr(14)
    transitions = list(mq.check())
    assert len(transitions) == 0  # nothing changed so nothing should happen

    pr_14.merged = True  # PR has been merged externally
    transitions = list(mq.check())
    assert len(transitions) == 1
    pr, [(transition, params)] = transitions[0]
    assert transition == PRTransition.MERGED
Пример #9
0
def test_bump_pr():
    mq = MergeQueue(FakeGHRepo())
    mq.ask_pr(12)
    mq.ask_pr(13)
    assert mq.queue[0].nb == 12
    with pytest.raises(MergeQueueException):
        mq.bump_pr(13)
    mq.bless_pr(13)
    mq.bump_pr(13)
    assert mq.queue[0].nb == 13
    assert mq.queue[1].nb == 12
    assert mq.pulled_prs[0] == 13
    with pytest.raises(MergeQueueException):
        mq.bump_pr(14)
Пример #10
0
    def merge_config(self, msg, args):
        """
        Configure the merge queue with repo for a room (defaults to the current
        room). Warning: this is killing the queue.
        """
        try:
            repo, room = self.optional_room_precheck(msg, args)
        except Exception as e:
            return f'Error {e}'

        gh_repo = self.gh.get_repo(repo)
        with self.rooms_lock:
            with self.mutable(ROOMS) as rooms:
                rooms[room] = Repo(name=repo,
                                   owner=msg.frm,
                                   queue=[],
                                   saints=[msg.frm.aclattr])
                self.queues[room] = MergeQueue(gh_repo)

        return f'Configured {room} with this repo {gh_repo.name}'
Пример #11
0
def test_check_merged_by_errbot():
    pr_14 = FakeGHPullRequest(14, reviews=[FakeGHReview('user1', APPROVED)])
    repo = FakeGHRepo(injected_prs=[pr_14])
    mq = MergeQueue(repo)
    mq.ask_pr(14)
    transitions = list(mq.check())
    assert len(transitions) == 0  # nothing changed so nothing should happen

    pr_14.mergeable_state = CLEAN
    pr_14.mergeable = True
    transitions = list(mq.check())
    assert len(transitions) == 1
    pr, [(transition, params)] = transitions[0]
    assert transition == PRTransition.NOW_MERGEABLE  # PR is not blessed so nothing else should happen

    mq.bless_pr(14)
    transitions = list(mq.check())
    assert len(transitions) == 1
    assert pr_14.asked_to_be_merged
    pr, [(transition, params)] = transitions[0]
    assert transition == PRTransition.MERGING
Пример #12
0
def test_check_review_counting():
    pr_14 = FakeGHPullRequest(14)
    repo = FakeGHRepo(injected_prs=[pr_14])
    mq = MergeQueue(repo)
    mq.ask_pr(14)
    transitions = list(mq.check())
    assert len(transitions) == 0  # nothing changed so nothing should happen

    pr_14.reviews.append(FakeGHReview('dugenou', APPROVED))

    transitions = list(mq.check())
    assert len(transitions) == 1
    pr, [(transition, params)] = transitions[0]
    assert transition == PRTransition.GOT_POSITIVE

    pr_14.reviews.append(FakeGHReview('dugland', CHANGES_REQUESTED))

    transitions = list(mq.check())
    assert len(transitions) == 1
    pr, [(transition, params)] = transitions[0]
    assert transition == PRTransition.GOT_NEGATIVE
Пример #13
0
 def __init__(self,
              watershed=array([]),
              probabilities=array([]),
              merge_priority_function=None,
              allow_shared_boundaries=True,
              gt_vol=None,
              feature_manager=MomentsFeatureManager(),
              show_progress=False,
              lowmem=False,
              connectivity=1,
              channel_is_oriented=None,
              orientation_map=array([]),
              normalize_probabilities=False):
     """Create a graph from a watershed volume and image volume.
     
     The watershed is assumed to have dams of label 0 in between basins.
     Then, each basin corresponds to a node in the graph and an edge is
     placed between two nodes if there are one or more watershed pixels
     connected to both corresponding basins.
     """
     super(Rag, self).__init__(weighted=False)
     self.show_progress = show_progress
     if merge_priority_function is None:
         self.merge_priority_function = boundary_mean
     else:
         self.merge_priority_function = merge_priority_function
     self.set_watershed(watershed, lowmem, connectivity)
     self.set_probabilities(probabilities, normalize_probabilities)
     self.set_orientations(orientation_map, channel_is_oriented)
     if watershed is None:
         self.ucm = None
     else:
         self.ucm = array(self.watershed == 0, dtype=float)
         self.ucm[self.ucm == 0] = -inf
         self.ucm_r = self.ucm.ravel()
     self.max_merge_score = -inf
     self.build_graph_from_watershed(allow_shared_boundaries)
     self.set_feature_manager(feature_manager)
     self.set_ground_truth(gt_vol)
     self.merge_queue = MergeQueue()
Пример #14
0
def test_reviews():
    pr_1 = FakeGHPullRequest(1,
                             reviews=[FakeGHReview('user1', APPROVED)],
                             mergeable_state=CLEAN)
    repo = FakeGHRepo(injected_prs=[pr_1])
    mq = MergeQueue(repo, max_pulled_prs=2)

    mq.ask_pr(1)
    mq.bless_pr(1)

    transitions = list(mq.check())
    assert len(transitions) == 0

    pr_1.add_review(FakeGHReview('user1', COMMENTED))
    transitions = list(mq.check())
    assert len(transitions) == 0

    pr_1.add_review(FakeGHReview('user1', REQUEST_CHANGES))

    transitions = list(mq.check())
    assert len(transitions) == 1
    pr, review_transitions = transitions[0]
    assert review_transitions[0] == (PRTransition.GOT_POSITIVE, 0)
    assert review_transitions[1] == (PRTransition.GOT_NEGATIVE, 1)
Пример #15
0
def test_init():
    mq = MergeQueue(FakeGHRepo())
    assert mq.get_queue() == []
Пример #16
0
def test_askpr_closed():
    repo = FakeGHRepo(injected_prs=[FakeGHPullRequest(14, state=CLOSED)])
    mq = MergeQueue(repo)
    with pytest.raises(MergeQueueException):
        mq.ask_pr(14)
    assert len(mq.queue) == 0
Пример #17
0
def test_set_stats_plugin():
    """Test setting stats plugin"""
    repo = FakeGHRepo()
    mq = MergeQueue(repo)

    assert type(mq.stats) == NoStats
Пример #18
0
def test_check_queue_depth():
    pr_14 = FakeGHPullRequest(14,
                              reviews=[FakeGHReview('user1', APPROVED)],
                              mergeable_state=BEHIND)
    pr_15 = FakeGHPullRequest(15,
                              reviews=[FakeGHReview('user2', APPROVED)],
                              mergeable_state=BEHIND)
    pr_16 = FakeGHPullRequest(16,
                              reviews=[FakeGHReview('user2', APPROVED)],
                              mergeable_state=BEHIND)
    repo = FakeGHRepo(injected_prs=[pr_15, pr_14, pr_16])
    mq = MergeQueue(repo, max_pulled_prs=2)
    mq.ask_pr(14)
    mq.ask_pr(15)
    mq.ask_pr(16)
    transitions = list(mq.check())
    assert len(transitions) == 0  # nothing changed so nothing should happen

    mq.bless_pr(14)
    mq.bless_pr(15)
    mq.bless_pr(16)

    # It should pull the base branch only on 14 and 15
    transitions = list(mq.check())
    assert len(transitions) == 2
    for pr, trs in transitions:
        assert trs[0][0] == PRTransition.PULLED
        assert trs[1][0] == PRTransition.PULLED_SUCCESS

    # Lets say the first one worked
    pr_14.mergeable_state = CLEAN
    pr_14.mergeable = True

    # Second time around it merge the one mergeable.
    transitions = list(mq.check())
    assert len(transitions) == 2
    for pr, trs in transitions:
        if pr.nb == 14:
            assert trs[0][0] == PRTransition.NOW_MERGEABLE and trs[1][
                0] == PRTransition.MERGING

    assert pr_14.asked_to_be_merged

    pr_14.merged = True  # PR has been merged
    pr_15.mergeable_state = BLOCKED  # CI still catching up

    # Third time around as a slot has been freed up, it should pull the last one.
    transitions = list(mq.check())
    assert len(transitions) == 2
    for pr, trs in transitions:
        if pr.nb == 14:
            assert trs[0][0] == PRTransition.MERGED
        elif pr.nb == 16:
            assert trs[0][0] == PRTransition.PULLED and trs[1][
                0] == PRTransition.PULLED_SUCCESS

    assert len(mq.pulled_prs) == 2
    pr_15.mergeable_state = DIRTY
    transitions = list(mq.check())
    assert len(transitions) == 1
    assert len(mq.pulled_prs) == 1
Пример #19
0
def test_getpr():
    mq = MergeQueue(FakeGHRepo())
    pr, gh_pr = mq.get_pr(12)
    assert pr.nb == 12
    assert gh_pr.number == 12