def check_approval_state( phab: PhabricatorClient, revision_id: int, target_repository_name: str ) -> dict: """Helper to load the Phabricator revision and check its approval requirement state * if the revision's target repository is the same as its current repository, it's an approval * otherwise it's an uplift request """ # Load target repo from Phabricator target_repo = phab.call_conduit( "diffusion.repository.search", constraints={"shortNames": [target_repository_name]}, ) target_repo = phab.single(target_repo, "data") target_repo_phid = phab.expect(target_repo, "phid") # Load base revision details from Phabricator revision = phab.call_conduit( "differential.revision.search", constraints={"ids": [revision_id]} ) revision = phab.single(revision, "data") revision_repo_phid = phab.expect(revision, "fields", "repositoryPHID") # Lookup if this is an uplift or an approval request is_approval = target_repo_phid == revision_repo_phid return (is_approval, revision, target_repo)
def test_find_txn_with_comment_in_phabricator(phabdouble): phab = phabdouble.get_phabricator_client() # A sec-approval request adds a comment to a revision. mock_comment = phabdouble.comment("my sec-approval request") revision = phabdouble.revision() # Add the two sec-approval request transactions to Phabricator. This also links the # comment transaction to the revision. comment_txn = phabdouble.api_object_for( phabdouble.transaction("comment", revision, comments=[mock_comment]) ) review_txn = phabdouble.api_object_for( phabdouble.transaction("reviewers.add", revision) ) # Fetch our comment transaction comment = PhabricatorClient.single(comment_txn, "comments") # Add the sec-approval request transactions to the database. revision = phabdouble.api_object_for(revision) sec_approval_request = SecApprovalRequest.build(revision, [comment_txn, review_txn]) # Search the list of sec-approval transactions for the comment. matching_comment = search_sec_approval_request_for_comment( phab, sec_approval_request ) assert matching_comment == comment
def test_integrated_secure_stack_has_alternate_commit_message( db, client, phabdouble, mock_repo_config, secure_project, authed_headers, monkeypatch, ): sanitized_title = "my secure commit title" revision_title = "my insecure revision title" # Build a revision with an active sec-approval request. diff, secure_revision = _make_sec_approval_request( sanitized_title, revision_title, authed_headers, client, monkeypatch, phabdouble, secure_project, ) # Request the revision from Lando. It should have our new title and summary. response = client.get("/stacks/D{}".format(secure_revision["id"])) assert response == 200 revision = PhabricatorClient.single(response.json, "revisions") assert revision["is_secure"] assert revision["is_using_secure_commit_message"] assert revision["title"] == sanitized_title assert revision["summary"] == ""
def _get_comment(phabdouble, msg): """Retrieve the Phabricator API representation of a raw comment string.""" revision = phabdouble.revision() mock_comment = phabdouble.comment(msg) phabdouble.transaction("dummy", revision, comments=[mock_comment]) transaction = phabdouble.api_object_for( phabdouble.transaction("dummy", revision, comments=[mock_comment]) ) comment = PhabricatorClient.single(transaction, "comments") return comment
def test_integrated_secure_stack_without_sec_approval_does_not_use_secure_message( db, client, phabdouble, mock_repo_config, secure_project): # Build a plain old secure message, no sec-approval requests made. secure_revision = phabdouble.revision(repo=phabdouble.repo(), projects=[secure_project]) response = client.get("/stacks/D{}".format(secure_revision["id"])) assert response == 200 revision = PhabricatorClient.single(response.json, "revisions") assert revision["is_secure"] assert not revision["is_using_secure_commit_message"]
def get_release_managers(phab: PhabricatorClient) -> dict: """Load the release-managers group details from Phabricator""" groups = phab.call_conduit( "project.search", constraints={"slugs": ["release-managers"]} ) return phab.single(groups, "data")
def test_integrated_secure_stack_has_alternate_commit_message( db, client, phabdouble, mock_repo_config, secure_project, authed_headers, monkeypatch, ): # Build a specially formatted sec-approval request comment. sanitized_title = "my secure commit title" sec_approval_comment = SECURE_COMMENT_TEMPLATE.format( message=sanitized_title) mock_comment = phabdouble.comment(sec_approval_comment) # Build a secure revision. secure_revision = phabdouble.revision( repo=phabdouble.repo(), projects=[secure_project], title="my insecure revision title", ) # Add the two sec-approval request transactions to Phabricator. This also links # the sec-approval request comment to the secure revision. comment_txn = phabdouble.api_object_for( phabdouble.transaction("comment", secure_revision, comments=[mock_comment])) review_txn = phabdouble.api_object_for( phabdouble.transaction("reviewers.add", secure_revision)) # PhabricatorDouble does not return valid transaction data after editing a # revision to ask for sec-approval. Instead of using the PhabricatorDouble fake # API call to get the transactions we want we'll use a traditional mock to get # them. def fake_send_message_for_review(revision_phid, message, phabclient): # Respond with the two transactions that should be generated by a successful # sec-approval request. return [comment_txn, review_txn] monkeypatch.setattr( "landoapi.api.revisions.send_sanitized_commit_message_for_review", fake_send_message_for_review, ) # Post the sec-approval request so that it gets saved into the database. response = client.post( "/requestSecApproval", json={ "revision_id": f"D{secure_revision['id']}", "sanitized_message": sanitized_title, }, headers=authed_headers, ) assert response == 200 # Request the revision from Lando. It should have our new title and summary. response = client.get("/stacks/D{}".format(secure_revision["id"])) assert response == 200 revision = PhabricatorClient.single(response.json, "revisions") assert revision["is_secure"] assert revision["is_using_secure_commit_message"] assert revision["title"] == sanitized_title assert revision["summary"] == ""