def test_admin_users(self): """ By default, all users that belong to an organization that owns the server and OCIM admins have access to the sandbox. """ admin_org_handle = 'admin-org' OrganizationFactory(name=admin_org_handle, github_handle=admin_org_handle) users = [ ('user', 'user', admin_org_handle), ('admin2', 'admin2', admin_org_handle), ('no_github_handle', '', admin_org_handle), ('inactive_user', 'inactive_user', admin_org_handle), ('another_org', 'another_org', 'another_org'), ('no_org_1', 'no_org_1', ''), ('no_org_2', 'no_org_2', None), ] admin_users = [ ('admin1', 'admin1', admin_org_handle), ('admin3', 'admin3', 'another_org'), ('admin4', 'admin4', ''), ('admin5', 'admin5', None), ('admin_no_org', '', admin_org_handle), ('inactive_admin', 'inactive_admin', admin_org_handle), ] expected_admin_users = [ 'user', 'admin1', 'admin2', 'admin3', 'admin4', 'admin5' ] for username, github_handle, org_handle in users: make_user_and_organization(username, github_username=github_handle, org_handle=org_handle) for username, github_handle, org_handle in admin_users: profile, _ = make_user_and_organization( username, github_username=github_handle, org_handle=org_handle) profile.user.is_superuser = True profile.user.save() # Mark the inactive user and admin as inactive; they should not be added to the resulting list get_user_model().objects.filter( username__in=('inactive_user', 'inactive_admin')).update(is_active=False) instance = OpenEdXInstanceFactory() organization = Organization.objects.get(github_handle=admin_org_handle) appserver = make_test_appserver(instance, organization=organization) self.assertEqual(len(appserver.admin_users), len(expected_admin_users)) ansible_settings = yaml.load(appserver.configuration_settings) self.assertCountEqual(ansible_settings['COMMON_USER_INFO'], [{ 'name': name, 'github': True, 'type': 'admin' } for name in expected_admin_users])
def test_admin_users(self, mock_consul): """ By default, all users that belong to an organization that owns the server and OCIM admins have access to the sandbox. """ admin_org_handle = 'admin-org' OrganizationFactory(name=admin_org_handle, github_handle=admin_org_handle) users = [ ('user', 'user', admin_org_handle), ('admin2', 'admin2', admin_org_handle), ('no_github_handle', '', admin_org_handle), ('inactive_user', 'inactive_user', admin_org_handle), ('another_org', 'another_org', 'another_org'), ('no_org_1', 'no_org_1', ''), ('no_org_2', 'no_org_2', None), ] admin_users = [ ('admin1', 'admin1', admin_org_handle), ('admin3', 'admin3', 'another_org'), ('admin4', 'admin4', ''), ('admin5', 'admin5', None), ('admin_no_org', '', admin_org_handle), ('admin_no_github', 'invalid_github_user', admin_org_handle), ('inactive_admin', 'inactive_admin', admin_org_handle), ] expected_admin_users = ['user', 'admin1', 'admin2', 'admin3', 'admin4', 'admin5'] for username, github_handle, org_handle in users: make_user_and_organization(username, github_username=github_handle, org_handle=org_handle) for username, github_handle, org_handle in admin_users: profile, _ = make_user_and_organization(username, github_username=github_handle, org_handle=org_handle) profile.user.is_superuser = True profile.user.save() # Mark the inactive user and admin as inactive; they should not be added to the resulting list get_user_model().objects.filter(username__in=('inactive_user', 'inactive_admin')).update(is_active=False) def check(_users): return [_user for _user in _users if _user != 'invalid_github_user'] with patch('instance.models.mixins.openedx_config.check_github_users', check): appserver = make_test_appserver( OpenEdXInstanceFactory(), organization=Organization.objects.get(github_handle=admin_org_handle), ) # Check user with non existant Github hande is removed self.assertEqual(len(appserver.admin_users) - 1, len(expected_admin_users)) ansible_settings = yaml.load(appserver.configuration_settings, Loader=yaml.SafeLoader) self.assertCountEqual(ansible_settings['COMMON_USER_INFO'], [ {'name': name, 'github': True, 'type': 'admin'} for name in expected_admin_users ])
def test_disabled_watchedfork(self, mock_get_pr_list_from_usernames, mock_spawn_appserver, mock_get_commit_id_from_ref): """ Creates WatchedFork with the 'enabled' field set to false and checks that its PRs are not watched. """ ansible_extra_settings = textwrap.dedent("""\ WATCH: true edx_ansible_source_repo: https://github.com/open-craft/configuration configuration_version: named-release/elder """) _, organization = make_user_and_organization() wf = WatchedForkFactory( organization=organization, fork='source/repo', enabled=False, ) pr = PRFactory( number=234, source_fork_name='fork/repo', target_fork_name=wf.fork, branch_name='watch-branch', title='Watched PR title which is very long', username='******', body='Hello watcher!\n- - -\r\n**Settings**\r\n```\r\n{}```\r\nMore...'.format( ansible_extra_settings ), ) mock_get_commit_id_from_ref.return_value = '7' * 40 mock_get_pr_list_from_usernames.return_value = [pr] tasks.watch_pr() self.assertEqual(mock_spawn_appserver.call_count, 0) self.assertEqual(WatchedPullRequest.objects.count(), 0)
def test_create_from_pr(self): """ Create an instance from a pull request """ pr = PRFactory() _, organization = make_user_and_organization() watched_fork = WatchedForkFactory(fork=pr.fork_name, organization=organization) instance, created = WatchedPullRequest.objects.get_or_create_from_pr(pr, watched_fork) self.assertTrue(created) watched_pr = instance.watchedpullrequest self.assertEqual(watched_pr.instance, instance) self.assertEqual(watched_pr.github_pr_number, pr.number) self.assertEqual(watched_pr.fork_name, pr.fork_name) self.assertEqual(watched_pr.branch_name, pr.branch_name) internal_lms_domain = 'pr{}.sandbox.basedomain.com'.format(pr.number) self.assertEqual(instance.internal_lms_domain, internal_lms_domain) self.assertEqual(instance.internal_lms_preview_domain, 'lms-preview.{}'.format(internal_lms_domain)) self.assertEqual(instance.internal_studio_domain, 'studio-{}'.format(internal_lms_domain)) self.assertRegex(instance.name, r'^PR') self.assertEqual(instance.edx_platform_commit, '9' * 40) same_instance, created = WatchedPullRequest.objects.get_or_create_from_pr(pr, watched_fork) self.assertEqual(instance, same_instance) self.assertFalse(created)
def test_create_from_pr_and_watchedfork_values(self): """ Create an instance from a pull request, and check that the default values from the watched fork are used. """ pr = PRFactory() _, organization = make_user_and_organization() watched_fork = WatchedForkFactory( fork=pr.fork_name, organization=organization, configuration_source_repo_url= 'https://github.com/open-craft/configuration-fromwatchedfork', configuration_version='named-release/elder-fromwatchedfork', configuration_extra_settings=textwrap.dedent("""\ PHRASE: "Hello" """), openedx_release='ginkgo.8', ) with patch( 'instance.models.openedx_instance.OpenEdXInstance._write_metadata_to_consul', return_value=(1, True)): instance, created = WatchedPullRequest.objects.get_or_create_from_pr( pr, watched_fork) self.assertTrue(created) self.assertEqual( instance.configuration_source_repo_url, 'https://github.com/open-craft/configuration-fromwatchedfork') self.assertEqual(instance.configuration_version, 'named-release/elder-fromwatchedfork') self.assertEqual(instance.openedx_release, 'ginkgo.8') self.assertEqual( yaml.load(instance.configuration_extra_settings, Loader=yaml.SafeLoader), {'PHRASE': 'Hello'})
def test_unique_constraints_allow_multiple_per_branch(self): """ Verifies that the unique constraint on a pull request allows for multiple copies of the same branch, but different URLs. """ pr = PRFactory() _, organization = make_user_and_organization() watched_fork = WatchedForkFactory( fork=pr.fork_name, organization=organization, configuration_source_repo_url= 'https://github.com/open-craft/configuration-fromwatchedfork', ) watched_pr1 = WatchedPullRequest.objects.create( github_organization_name='get-by', github_repository_name='fork-name', branch_name='test', github_pr_url='https://github.com/open-craft/opencraft/pull/123/', watched_fork=watched_fork, ) watched_pr2 = WatchedPullRequest.objects.create( github_organization_name='get-by', github_repository_name='fork-name', branch_name='test', github_pr_url='https://github.com/open-craft/opencraft/pull/1234/', watched_fork=watched_fork, ) self.assertNotEqual(watched_pr1, watched_pr2)
def test_unique_constraints(self): """ Verifies that we cannot create multiple database entries for following a specific pull request. """ pr = PRFactory() _, organization = make_user_and_organization() watched_fork = WatchedForkFactory( fork=pr.fork_name, organization=organization, configuration_source_repo_url= 'https://github.com/open-craft/configuration-fromwatchedfork', ) WatchedPullRequest.objects.create( github_organization_name='get-by', github_repository_name='fork-name', branch_name='test', github_pr_url='https://github.com/open-craft/opencraft/pull/123/', watched_fork=watched_fork, ) self.assertRaises( IntegrityError, WatchedPullRequest.objects.create, github_organization_name='get-by', github_repository_name='fork-name', branch_name='test', github_pr_url='https://github.com/open-craft/opencraft/pull/123/', watched_fork=watched_fork, )
def test_watch_pr_new(self, mock_get_pr_list_from_usernames, mock_spawn_appserver, mock_get_commit_id_from_ref): """ New PR created on the watched repo """ ansible_extra_settings = textwrap.dedent("""\ WATCH: true edx_ansible_source_repo: https://github.com/open-craft/configuration configuration_version: named-release/elder """) _, organization = make_user_and_organization(github_username='******') WatchedForkFactory(organization=organization, fork='source/repo') pr = PRFactory( number=234, source_fork_name='fork/repo', target_fork_name='source/repo', branch_name='watch-branch', title='Watched PR title which is very long', username='******', body='Hello watcher!\n- - -\r\n**Settings**\r\n```\r\n{}```\r\nMore...'.format( ansible_extra_settings ), ) pr_url = 'https://github.com/source/repo/pull/234' self.assertEqual(pr.github_pr_url, pr_url) mock_get_pr_list_from_usernames.return_value = [pr] mock_get_commit_id_from_ref.return_value = '7' * 40 tasks.watch_pr() self.assertEqual(mock_spawn_appserver.call_count, 1) new_instance_ref_id = mock_spawn_appserver.mock_calls[0][1][0] instance = OpenEdXInstance.objects.get(ref_set__pk=new_instance_ref_id) self.assertEqual(instance.internal_lms_domain, 'pr234.sandbox.awesome.hosting.org') self.assertEqual(instance.internal_lms_preview_domain, 'preview.pr234.sandbox.awesome.hosting.org') self.assertEqual(instance.internal_studio_domain, 'studio.pr234.sandbox.awesome.hosting.org') self.assertEqual(instance.edx_platform_repository_url, 'https://github.com/fork/repo.git') self.assertEqual(instance.edx_platform_commit, '7' * 40) self.assertEqual(instance.openedx_release, 'master') self.assertEqual( yaml.load(instance.configuration_extra_settings, Loader=yaml.SafeLoader), yaml.load(ansible_extra_settings, Loader=yaml.SafeLoader)) self.assertEqual(instance.configuration_source_repo_url, 'https://github.com/open-craft/configuration') self.assertEqual(instance.configuration_version, 'named-release/elder') self.assertEqual( instance.name, 'PR#234: Watched PR title which … (bradenmacdonald) - fork/watch-branch (7777777)') # Also check the WatchedPullRequest object: watched_pr = WatchedPullRequest.objects.get(github_pr_url=pr_url) self.assertEqual(watched_pr.github_pr_number, 234) self.assertEqual(watched_pr.github_pr_url, 'https://github.com/source/repo/pull/234') self.assertEqual(watched_pr.github_base_url, 'https://github.com/fork/repo') self.assertEqual(watched_pr.branch_name, 'watch-branch') self.assertEqual(watched_pr.instance_id, instance.id) # Once the new instance/appserver has been spawned, it shouldn't spawn again: tasks.watch_pr() self.assertEqual(mock_spawn_appserver.call_count, 1)
def create_test_data(number): """ Return some data about a fork and repository. The data is almost the same, but values have a "1" or "2" (or the number you pass) appended. Also, the PR's id is 23001 for PR1, 23002 for PR2 etc. """ pr_extra_settings = textwrap.dedent("""\ PHRASE: "I am the value defined in PR{}" edx_ansible_source_repo: https://github.com/open-craft/configuration configuration_version: named-release/elder """.format(number)) _, organization = make_user_and_organization( github_username='******') wf = WatchedForkFactory( organization=organization, fork='source/repo{}'.format(number), # These 2 values will be replaced by the ones from the PR because the PR ones have more precedence configuration_source_repo_url= 'https://github.com/open-craft/configuration-fromwatchedfork', configuration_version='named-release/elder-fromwatchedfork', configuration_extra_settings=textwrap.dedent("""\ PHRASE: "I am a setting which was set up the watched fork {} (but will be overriden by the PR)" FORK_SPECIFIC_PHRASE: "I am another setting which was set up in watched fork {}" """.format(number, number)), openedx_release='ginkgo.8', ) pr_number = 23000 + number pr = PRFactory( number=pr_number, source_fork_name='fork/repo', target_fork_name=wf.fork, branch_name='watch-branch', title='Watched PR title which is very long', username='******', body= 'Hello watcher!\n- - -\r\n**Settings**\r\n```\r\n{}```\r\nMore...' .format(pr_extra_settings), ) pr_url = 'https://github.com/{}/pull/{}'.format(wf.fork, pr_number) pr_expected_resulting_settings = { 'PHRASE': "I am the value defined in PR{}".format(number), 'FORK_SPECIFIC_PHRASE': "I am another setting which was set up in watched fork {}". format(number), 'edx_ansible_source_repo': 'https://github.com/open-craft/configuration', 'configuration_version': 'named-release/elder', } return { 'wf': wf, 'pr': pr, 'url': pr_url, 'expected_settings': pr_expected_resulting_settings }
def setUp(self): """ Mock the 'get_commit_id_from_ref' method so it doesn't make a GitHub API call """ super().setUp() patcher = patch('pr_watch.models.github.get_commit_id_from_ref') self.addCleanup(patcher.stop) self.mock_get_commit_id_from_ref = patcher.start() self.mock_get_commit_id_from_ref.return_value = '9' * 40 _, self.organization = make_user_and_organization()
def test_get_by_fork_name(self): """ Use `fork_name` to get an instance object from the ORM """ _, organization = make_user_and_organization(org_name="Get by", org_handle="get-by") watched_fork = WatchedForkFactory(organization=organization, fork='fork-name') WatchedPullRequest.objects.create( github_organization_name='get-by', github_repository_name='fork-name', watched_fork=watched_fork, ) watched_pr = WatchedPullRequest.objects.get(fork_name='get-by/fork-name') self.assertEqual(watched_pr.fork_name, 'get-by/fork-name')
def test_create_from_pr_and_watchedfork_values(self): """ Create an instance from a pull request, and check that the default values from the watched fork are used. """ pr = PRFactory() _, organization = make_user_and_organization() watched_fork = WatchedForkFactory( fork=pr.fork_name, organization=organization, ansible_appserver_repo_url= 'https://github.com/open-craft/ansible-playbooks.git', ansible_appserver_playbook='playbooks/appserver.yml', ansible_appserver_requirements_path='requirements.txt', ansible_appserver_version='ansible2.8.17', openstack_server_base_image= '{"name_or_id":"focal-20.04-unmodified"}', configuration_source_repo_url= 'https://github.com/open-craft/configuration-fromwatchedfork', configuration_version='named-release/elder-fromwatchedfork', configuration_extra_settings=textwrap.dedent("""\ PHRASE: "Hello" """), openedx_release='ginkgo.8', ) with patch( 'instance.models.openedx_instance.OpenEdXInstance._write_metadata_to_consul', return_value=(1, True)): instance, created = WatchedPullRequest.objects.get_or_create_from_pr( pr, watched_fork) self.assertTrue(created) self.assertEqual( instance.ansible_appserver_repo_url, 'https://github.com/open-craft/ansible-playbooks.git') self.assertEqual(instance.ansible_appserver_playbook, 'playbooks/appserver.yml') self.assertEqual(instance.ansible_appserver_requirements_path, 'requirements.txt') self.assertEqual(instance.ansible_appserver_version, 'ansible2.8.17') self.assertEqual(json.loads(instance.openstack_server_base_image), {"name_or_id": "focal-20.04-unmodified"}) self.assertEqual( instance.configuration_source_repo_url, 'https://github.com/open-craft/configuration-fromwatchedfork') self.assertEqual(instance.configuration_version, 'named-release/elder-fromwatchedfork') self.assertEqual(instance.openedx_release, 'ginkgo.8') self.assertEqual( yaml.load(instance.configuration_extra_settings, Loader=yaml.SafeLoader), {'PHRASE': 'Hello'})
def test_set_fork_name(self): """ Set org & repo using the fork name """ _, organization = make_user_and_organization(org_name="Org2", org_handle="org2") watched_fork = WatchedForkFactory(organization=organization, fork='some-name') watched_pr = WatchedPullRequest(watched_fork=watched_fork) watched_pr.set_fork_name('org2/another-repo') self.assertEqual(watched_pr.github_organization_name, 'org2') self.assertEqual(watched_pr.github_repository_name, 'another-repo') watched_pr.save() # Check values in DB watched_pr = WatchedPullRequest.objects.get(pk=watched_pr.pk) self.assertEqual(watched_pr.github_organization_name, 'org2') self.assertEqual(watched_pr.github_repository_name, 'another-repo')
def make_watched_pr_and_instance(organization=None, **kwargs): """ Create a WatchedPullRequest and associated OpenEdXInstance It associates them to the given organization if given, otherwise creates a new one (plus a user). """ pr = PRFactory(**kwargs) if not organization: # creates user, user profile, and organization needed to be referenced _, organization = make_user_and_organization() watched_fork = WatchedForkFactory(fork=pr.fork_name, organization=organization) watched_fork.save() with patch('pr_watch.github.get_commit_id_from_ref', return_value=('5' * 40)): instance, dummy = WatchedPullRequest.objects.get_or_create_from_pr( pr, watched_fork) return instance.watchedpullrequest
def test_get_branch_tip_with_tag(self): """ Set the commit id to a tag. TODO: Is this 'ref_type' code used for anything? """ self.mock_get_commit_id_from_ref.return_value = 'c' * 40 _, organization = make_user_and_organization(org_name="Org9", org_handle="org9") watched_fork = WatchedForkFactory(organization=organization, fork='org9/repo') instance = WatchedPullRequest.objects.create(fork_name='org9/repo', branch_name='new-tag', ref_type='tag', watched_fork=watched_fork) self.assertEqual(instance.get_branch_tip(), 'c' * 40) self.assertEqual(self.mock_get_commit_id_from_ref.mock_calls, [ call('org9/repo', 'new-tag', ref_type='tag'), ]) self.assertEqual(instance.branch_name, 'new-tag') self.assertEqual(instance.ref_type, 'tag')