Пример #1
0
def test_check_connection_success():
    phab = PhabricatorClient(api_key='api-key')
    success_json = CANNED_EMPTY_RESULT.copy()
    with requests_mock.mock() as m:
        m.get(phab_url('conduit.ping'), status_code=200, json=success_json)
        phab.check_connection()
        assert m.called
Пример #2
0
def test_get_rawdiff_by_id(phabfactory):
    patch = "diff --git a/hello.c b/hello.c..."
    # The raw patch's diffID is encoded in the Diff URI.
    phabfactory.diff(id='12345', patch=patch)
    phab = PhabricatorClient(api_key='api-key')
    returned_patch = phab.get_rawdiff('12345')
    assert returned_patch == patch
Пример #3
0
def test_get_revision_with_200_response():
    phab = PhabricatorClient(api_key='api-key')
    with requests_mock.mock() as m:
        m.get(phab_url('differential.query'),
              status_code=200,
              json=CANNED_REVISION_1)
        revision = phab.get_revision(id=CANNED_REVISION_1['result'][0]['id'])
        assert revision == CANNED_REVISION_1['result'][0]
Пример #4
0
def test_get_current_user_with_200_response():
    phab = PhabricatorClient(api_key='api-key')
    with requests_mock.mock() as m:
        m.get(phab_url('user.whoami'),
              status_code=200,
              json=CANNED_USER_WHOAMI_1)
        user = phab.get_current_user()
        assert user == CANNED_USER_WHOAMI_1['result']
Пример #5
0
def test_get_user_returns_with_200_response(phabfactory):
    user_response = phabfactory.user()
    expected_user = first_result_in_response(user_response)
    phid = phid_for_response(user_response)

    phab = PhabricatorClient(api_key='api-key')
    user = phab.get_user(phid)

    assert user == expected_user
Пример #6
0
def test_get_repo_for_revision(phabfactory):
    repo_response = phabfactory.repo()
    phabfactory.revision(id='D5')
    expected_repo = first_result_in_response(repo_response)

    phab = PhabricatorClient(api_key='api-key')
    revision = phab.get_revision(id='D5')
    repo = phab.get_revision_repo(revision)

    assert repo == expected_repo
Пример #7
0
def test_get_author_for_revision(phabfactory):
    user_response = phabfactory.user()
    phabfactory.revision(id='D5')
    expected_user = first_result_in_response(user_response)

    phab = PhabricatorClient(api_key='api-key')
    revision = phab.get_revision(id='D5')
    author = phab.get_revision_author(revision)

    assert author == expected_user
Пример #8
0
def test_get_repo_returns_with_200_response():
    phab = PhabricatorClient(api_key='api-key')
    with requests_mock.mock() as m:
        m.get(phab_url('phid.query'),
              status_code=200,
              json=CANNED_REPO_MOZCENTRAL)
        canned_response_repo = \
            list(CANNED_REPO_MOZCENTRAL['result'].values())[0]
        repo = phab.get_repo(phid=canned_response_repo['phid'])
        assert repo == canned_response_repo
Пример #9
0
def test_raise_exception_if_api_ping_times_out():
    phab = PhabricatorClient(api_key='api-key')
    with requests_mock.mock() as m:
        # Test with the generic Timeout exception, which all other timeout
        # exceptions derive from.
        m.get(phab_url('conduit.ping'), exc=requests.Timeout)

        with pytest.raises(PhabricatorAPIException):
            phab.check_connection()
        assert m.called
Пример #10
0
def test_raise_exception_if_ping_encounters_connection_error():
    phab = PhabricatorClient(api_key='api-key')
    with requests_mock.mock() as m:
        # Test with the generic ConnectionError, which is a superclass for
        # other connection error types.
        m.get(phab_url('conduit.ping'), exc=requests.ConnectionError)

        with pytest.raises(PhabricatorAPIException):
            phab.check_connection()
        assert m.called
Пример #11
0
def test_build_patch(phabfactory, docker_env_vars):
    phabfactory.user(username='******', phid='PHID-USER-mpm')
    phabfactory.revision(id='D5', author_phid='PHID-USER-mpm')

    phab = PhabricatorClient(api_key='api-key')
    revision = phab.get_revision(id='D5')
    revision['summary'] = "Express great joy at existence of Mercurial"
    author = phab.get_revision_author(revision)

    patch = build_patch_for_revision(git_diff_from_revision, author, revision)

    assert patch == hg_patch
Пример #12
0
def test_phabricator_exception():
    """ Ensures that the PhabricatorClient converts JSON errors from Phabricator
    into proper exceptions with the error_code and error_message in tact.
    """
    phab = PhabricatorClient(api_key='api-key')
    with requests_mock.mock() as m:
        m.get(phab_url('differential.query'),
              status_code=200,
              json=CANNED_ERROR_1)
        with pytest.raises(PhabricatorAPIException) as e_info:
            phab.get_revision(id=CANNED_REVISION_1['result'][0]['id'])
        assert e_info.value.error_code == CANNED_ERROR_1['error_code']
        assert e_info.value.error_info == CANNED_ERROR_1['error_info']
Пример #13
0
def test_patch_uploads_to_s3(db, phabfactory, s3):
    phabfactory.user()
    phabfactory.revision()
    phabfactory.rawdiff(1)

    phab = PhabricatorClient(None)
    revision = phab.get_revision(1)
    patch = Patch(1, revision, 1)
    expected_body = patch.build(phab)
    patch.upload(phab)

    assert patch.s3_url == 's3://landoapi.test.bucket/L1_D1_1.patch'
    body = s3.Object('landoapi.test.bucket', 'L1_D1_1.patch').get()['Body'].read().decode("utf-8")
    assert body == expected_body
Пример #14
0
def test_raise_exception_if_api_returns_error_json_response():
    phab = PhabricatorClient(api_key='api-key')
    error_json = {
        "result": None,
        "error_code": "ERR-CONDUIT-CORE",
        "error_info": "BOOM"
    }

    with requests_mock.mock() as m:
        # Test with the generic Timeout exception, which all other timeout
        # exceptions derive from.
        m.get(phab_url('conduit.ping'), status_code=500, json=error_json)

        with pytest.raises(PhabricatorAPIException):
            phab.check_connection()
        assert m.called
Пример #15
0
def test_landing_revision_calls_transplant_service(db, client, phabfactory,
                                                   monkeypatch, s3):
    # Mock the phabricator response data
    phabfactory.revision()

    # Build the patch we expect to see
    phabclient = PhabricatorClient('someapi')
    revision = phabclient.get_revision('D1')
    diff_id = phabclient.get_diff(phid=revision['activeDiffPHID'])['id']
    gitdiff = phabclient.get_rawdiff(diff_id)
    author = phabclient.get_revision_author(revision)
    hgpatch = build_patch_for_revision(gitdiff, author, revision)
    patch_url = 's3://landoapi.test.bucket/L1_D1_1.patch'

    # The repo we expect to see
    repo_uri = phabclient.get_revision_repo(revision)['uri']

    tsclient = MagicMock(spec=TransplantClient)
    tsclient().land.return_value = 1
    monkeypatch.setattr('landoapi.models.landing.TransplantClient', tsclient)
    client.post('/landings?api_key=api-key',
                data=json.dumps({
                    'revision_id': 'D1',
                    'diff_id': int(diff_id)
                }),
                content_type='application/json')
    tsclient().land.assert_called_once_with(
        '*****@*****.**', patch_url, repo_uri,
        '{}/landings/1/update'.format(os.getenv('PINGBACK_HOST_URL')))
    body = s3.Object('landoapi.test.bucket',
                     'L1_D1_1.patch').get()['Body'].read().decode("utf-8")
    assert body == hgpatch
Пример #16
0
def get(revision_id, api_key=None):
    """ Gets revision from Phabricator.

    Returns None or revision.
    """
    phab = PhabricatorClient(api_key)
    revision = phab.get_revision(id=revision_id)

    if not revision:
        # We could not find a matching revision.
        return problem(
            404,
            'Revision not found',
            'The requested revision does not exist',
            type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404'
        )

    return _format_revision(phab, revision, include_parents=True), 200
Пример #17
0
def heartbeat():
    """Perform an in-depth service health check.

    This should check all the services that this service depends on
    and return a 200 iff those services and the app itself are
    performing normally. Return a 5XX if something goes wrong.
    """
    phab = PhabricatorClient(api_key='')
    try:
        phab.check_connection()
    except PhabricatorAPIException:
        logger.warning(
            {
                'msg': 'problem connecting to Phabricator',
            }, 'heartbeat'
        )
        return 'heartbeat: problem', 502
    logger.info({'msg': 'ok, all services are up'}, 'heartbeat')
    return 'heartbeat: ok', 200
Пример #18
0
def test_get_revision_with_200_response(phabfactory):
    revision_response = phabfactory.revision(id='D1234')
    expected_revision = first_result_in_response(revision_response)
    phab = PhabricatorClient(api_key='api-key')
    revision = phab.get_revision(id=1234)
    assert revision == expected_revision
Пример #19
0
def test_get_user_returns_with_200_response():
    phab = PhabricatorClient(api_key='api-key')
    with requests_mock.mock() as m:
        m.get(phab_url('user.query'), status_code=200, json=CANNED_USER_1)
        user = phab.get_user(phid=CANNED_USER_1['result'][0]['phid'])
        assert user == CANNED_USER_1['result'][0]
Пример #20
0
def test_get_diff_by_id(phabfactory):
    expected = phabfactory.diff(id='9001')
    phab = PhabricatorClient(api_key='api-key')
    result = phab.get_diff(id='9001')
    assert result == expected['result']['9001']
Пример #21
0
    def create(cls, revision_id, diff_id, phabricator_api_key=None):
        """Land revision.

        A typical successful story:
            * Revision and Diff are loaded from Phabricator.
            * Patch is created and uploaded to S3 bucket.
            * Landing object is created (without request_id)
            * A request to land the patch is send to Transplant client.
            * Created landing object is updated with returned `request_id`,
              it is then saved and returned.

        Args:
            revision_id: The id of the revision to be landed
            diff_id: The id of the diff to be landed
            phabricator_api_key: API Key to identify in Phabricator

        Returns:
            A new Landing object

        Raises:
            RevisionNotFoundException: PhabricatorClient returned no revision
                for given revision_id
            LandingNotCreatedException: landing request in Transplant failed
        """
        phab = PhabricatorClient(phabricator_api_key)
        revision = phab.get_revision(id=revision_id)

        if not revision:
            raise RevisionNotFoundException(revision_id)

        repo = phab.get_revision_repo(revision)

        # Save landing to make sure we've got the callback URL.
        landing = cls(revision_id=revision_id, diff_id=diff_id)
        landing.save()

        patch = Patch(landing.id, revision, diff_id)
        patch.upload(phab)

        # Define the pingback URL with the port.
        callback = '{host_url}/landings/{id}/update'.format(
            host_url=current_app.config['PINGBACK_HOST_URL'], id=landing.id)

        trans = TransplantClient()
        # The LDAP username used here has to be the username of the patch
        # pusher (the person who pushed the 'Land it!' button).
        # FIXME: change [email protected] to the real data retrieved
        #        from Auth0 userinfo
        request_id = trans.land('*****@*****.**', patch.s3_url,
                                repo['uri'], callback)
        if not request_id:
            raise LandingNotCreatedException

        landing.request_id = request_id
        landing.status = TRANSPLANT_JOB_STARTED
        landing.save()

        logger.info(
            {
                'revision_id': revision_id,
                'landing_id': landing.id,
                'msg': 'landing created for revision'
            }, 'landing.success')

        return landing