def test_hash_with_different_list_order_is_equal(): a = LandingAssessment.hash_warning_list( [ { 'id': 'W1', 'message': 'oops 1' }, { 'id': 'W2', 'message': 'oops 2' }, { 'id': 'W3', 'message': 'oops 3' }, ] ) b = LandingAssessment.hash_warning_list( [ { 'id': 'W3', 'message': 'oops 3' }, { 'id': 'W2', 'message': 'oops 2' }, { 'id': 'W1', 'message': 'oops 1' }, ] ) assert a == b
def test_construct_assessment_dict_only_blockers(): warnings = [] blockers = [MockProblem('oops')] assessment = LandingAssessment(warnings, blockers) result = assessment.to_dict() assert result['confirmation_token'] is None assert result['blockers'][0]['message'] == 'oops' assert not result['warnings']
def test_construct_assessment_dict_no_warnings_or_blockers(): assessment = LandingAssessment([], []) expected_dict = { 'confirmation_token': None, 'warnings': [], 'blockers': [], } assert assessment.to_dict() == expected_dict
def test_hash_with_same_id_different_warning_details_are_different(): a = LandingAssessment.hash_warning_list([{ 'id': 'W0', 'message': 'revision 5 problem' }]) b = LandingAssessment.hash_warning_list([{ 'id': 'W0', 'message': 'revision 8 problem' }]) assert a != b
def test_hash_with_duplicate_ids_are_not_stripped(): a = LandingAssessment.hash_warning_list([ { 'id': 'W0', 'message': 'same' }, { 'id': 'W0', 'message': 'same' }, ]) b = LandingAssessment.hash_warning_list([{'id': 'W0', 'message': 'same'}]) assert a != b
def test_token_with_warnings_is_not_none(): assert LandingAssessment.hash_warning_list( [{ 'id': 'W0', 'message': 'oops' }] )
def post(data): """API endpoint at POST /landings to land revision.""" logger.info( 'landing requested by user', extra={ 'path': request.path, 'method': request.method, 'data': data, } ) revision_id, diff_id = unmarshal_landing_request(data) confirmation_token = data.get('confirmation_token') or None phab = g.phabricator get_revision = lazy_get_revision(phab, revision_id) get_latest_diff = lazy_get_latest_diff(phab, get_revision) get_diff = lazy_get_diff(phab, diff_id, get_latest_diff) get_diff_author = lazy_get_diff_author(get_diff) get_latest_landed = lazy(Transplant.legacy_latest_landed)(revision_id) get_repository = lazy_get_repository(phab, get_revision) get_landing_repo = lazy_get_landing_repo( get_repository, current_app.config.get('ENVIRONMENT') ) get_open_parents = lazy_get_open_parents(phab, get_revision) get_reviewers = lazy_get_reviewers(get_revision) get_reviewer_info = lazy_reviewers_search(phab, get_reviewers) get_reviewers_extra_state = lazy_get_reviewers_extra_state( get_reviewers, get_diff ) get_revision_status = lazy_get_revision_status(get_revision) assessment = check_landing_conditions( g.auth0_user, revision_id, diff_id, get_revision, get_latest_diff, get_latest_landed, get_repository, get_landing_repo, get_diff, get_diff_author, get_open_parents, get_reviewers, get_reviewer_info, get_reviewers_extra_state, get_revision_status, short_circuit=True, ) assessment.raise_if_blocked_or_unacknowledged(confirmation_token) if assessment.warnings: # Log any warnings that were acknowledged, for auditing. logger.info( 'Landing with acknowledged warnings is being requested', extra={ 'revision_id': revision_id, 'warnings': [w.serialize() for w in assessment.warnings], } ) # These are guaranteed to return proper data since we're # running after checking_landing_conditions(). revision = get_revision() landing_repo = get_landing_repo() author_name, author_email = get_diff_author() # Collect the usernames of reviewers who have accepted. reviewers = get_reviewers() users, projects = get_reviewer_info() accepted_reviewers = [ reviewer_identity(phid, users, projects).identifier for phid, r in reviewers.items() if r['status'] is ReviewerStatus.ACCEPTED ] # Seconds since Unix Epoch, UTC. date_modified = phab.expect(revision, 'fields', 'dateModified') title = phab.expect(revision, 'fields', 'title') summary = phab.expect(revision, 'fields', 'summary') bug_id = get_bugzilla_bug(revision) human_revision_id = 'D{}'.format(revision_id) revision_url = urllib.parse.urljoin( current_app.config['PHABRICATOR_URL'], human_revision_id ) commit_message = format_commit_message( title, bug_id, accepted_reviewers, summary, revision_url ) # Construct the patch that will be sent to transplant. raw_diff = phab.call_conduit('differential.getrawdiff', diffID=diff_id) patch = build_patch_for_revision( raw_diff, author_name, author_email, commit_message[1], date_modified ) # Upload the patch to S3 patch_url = upload( revision_id, diff_id, patch, current_app.config['PATCH_BUCKET_NAME'], aws_access_key=current_app.config['AWS_ACCESS_KEY'], aws_secret_key=current_app.config['AWS_SECRET_KEY'], ) trans = TransplantClient( current_app.config['TRANSPLANT_URL'], current_app.config['TRANSPLANT_USERNAME'], current_app.config['TRANSPLANT_PASSWORD'], ) submitted_assessment = LandingAssessment( blockers=[ LandingInProgress( 'This revision was submitted for landing by another user at ' 'the same time.' ) ] ) ldap_username = g.auth0_user.email try: # WARNING: Entering critical section, do not add additional # code unless absolutely necessary. Acquires a lock on the # transplants table which gives exclusive write access and # prevents readers who are entering this critical section. # See https://www.postgresql.org/docs/9.3/static/explicit-locking.html # for more details on the specifics of the lock mode. with db.session.begin_nested(): db.session.execute( 'LOCK TABLE transplants IN SHARE ROW EXCLUSIVE MODE;' ) if Transplant.is_revision_submitted(revision_id): submitted_assessment.raise_if_blocked_or_unacknowledged(None) transplant_request_id = trans.land( revision_id=revision_id, ldap_username=ldap_username, patch_urls=[patch_url], tree=landing_repo.tree, pingback=current_app.config['PINGBACK_URL'], push_bookmark=landing_repo.push_bookmark ) transplant = Transplant( request_id=transplant_request_id, revision_to_diff_id={str(revision_id): diff_id}, revision_order=[str(revision_id)], requester_email=ldap_username, tree=landing_repo.tree, repository_url=landing_repo.url, status=TransplantStatus.submitted ) db.session.add(transplant) except TransplantError as exc: logger.info( 'error creating transplant', extra={'revision': revision_id}, exc_info=exc ) return problem( 502, 'Landing not created', 'The requested revision does exist, but landing failed.' 'Please retry your request at a later time.', type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502' ) # Transaction succeeded, commit the session. db.session.commit() logger.info( 'transplant created', extra={ 'revision_id': revision_id, 'transplant_id': transplant.id, } ) return {'id': transplant.id}, 202
def test_token_for_no_issues_is_none(): assert LandingAssessment.hash_warning_list([]) is None
def test_hash_object_throws_error(): with pytest.raises(KeyError): LandingAssessment.hash_warning_list([{'id': object()}])
def test_hash_of_empty_list_is_None(): assert LandingAssessment.hash_warning_list([]) is None