def test_sync_starter_configs_success_partial_failure(mocker, mock_github): """sync_starter_configs should detect & gracefully handle an invalid config""" config_filenames = ["site-1/ocw-studio.yaml", "site-2/ocw-studio.yaml"] git_url = "https://github.com/testorg/ocws-configs" mock_log = mocker.patch("content_sync.apis.github.log.exception") mock_github.return_value.get_organization.return_value.get_repo.return_value.get_contents.side_effect = [ mocker.Mock( path=config_filenames[0], decoded_content=b"---\ncollections: []\nroot-url-path: sites", ), mocker.Mock(path=config_filenames[1], decoded_content=b"---\nfcollections: []\nfoo: bar"), ] sync_starter_configs(git_url, config_filenames) mock_log.assert_called_once_with("Invalid site config YAML found in %s", config_filenames[1]) assert WebsiteStarter.objects.filter( source=STARTER_SOURCE_GITHUB, path=f"{git_url}/site-1", slug="site-1", name="site-1", config={ "collections": [], "root-url-path": "sites" }, ).exists() assert not WebsiteStarter.objects.filter( path=f"{git_url}/site-2", ).exists()
def sync_github_site_configs(url: str, files: List[str], commit: Optional[str] = None): """ Sync WebsiteStarter objects from github """ github.sync_starter_configs(url, files, commit=commit)
def test_sync_starter_configs_success_create(mocker, mock_github): """sync_starter_configs should successfully create new WebsiteStarter objects""" config_filenames = [ "site-1/ocw-studio.yaml", "site-2/ocw-studio.yaml", "ocw-studio.yaml", ] git_url = "https://github.com/testorg/ocws-configs" config_content = b"---\nroot-url-path: sites\ncollections: []" mock_github.return_value.get_organization.return_value.get_repo.return_value.get_contents.side_effect = [ mocker.Mock(path=config_filenames[0], decoded_content=config_content), mocker.Mock(path=config_filenames[1], decoded_content=config_content), mocker.Mock(path=config_filenames[2], decoded_content=config_content), ] sync_starter_configs(git_url, config_filenames) for filename in config_filenames: expected_slug = filename.split( "/")[0] if "/" in filename else "ocws-configs" assert WebsiteStarter.objects.filter( source=STARTER_SOURCE_GITHUB, path="/".join([git_url, expected_slug]), slug=expected_slug, name=expected_slug, config={ "root-url-path": "sites", "collections": [] }, ).exists()
def test_sync_starter_configs_exception(mocker, mock_github): """sync_starter_configs should detect & gracefully handle any exception""" config_filenames = ["site-1/ocw-studio.yaml", "site-2/ocw-studio.yaml"] git_url = "https://github.com/testorg/ocws-configs" mock_log = mocker.patch("content_sync.apis.github.log.exception") mock_github.return_value.get_organization.return_value.get_repo.return_value.get_contents.side_effect = [ KeyError("invalid key") ] sync_starter_configs(git_url, config_filenames) for filename in config_filenames: mock_log.assert_any_call("Error processing config file %s", filename)
def test_sync_starter_configs_webhook_branch_hash_mismatch( mocker, mock_github): """A push to a branch other than the default branch without GITHUB_WEBHOOK_BRANCH should not trigger a starter update""" git_url = "https://github.com/testorg/ocws-configs" config_filenames = ["site-1/ocw-studio.yaml", "site-2/ocw-studio.yaml"] mock_github.return_value.get_organization.return_value.get_repo.return_value.default_branch.return_value = ( settings.GIT_BRANCH_MAIN) mock_github.return_value.get_organization.return_value.get_repo.return_value.get_branch.return_value = mocker.Mock( commit=mocker.Mock(sha="abc123")) fake_commit = "def456" sync_starter_configs(git_url, config_filenames, fake_commit) mock_github.return_value.get_organization.return_value.get_repo.return_value.get_contents.assert_not_called( )
def test_sync_starter_configs_webhook_branch_hash_match(mocker, mock_github): """ A push to the branch set in settings.GITHUB_WEBHOOK_BRANCH should trigger getting that branch and then the config files themselves """ git_url = "https://github.com/testorg/ocws-configs" config_filenames = ["site-1/ocw-studio.yaml", "site-2/ocw-studio.yaml"] fake_commit = "abc123" release_branch = "release" config_content = b"---\ncollections: []" mock_github.return_value.get_organization.return_value.get_repo.return_value.get_contents.side_effect = [ mocker.Mock(path=config_filenames[0], decoded_content=config_content), mocker.Mock(path=config_filenames[1], decoded_content=config_content), ] settings.GITHUB_WEBHOOK_BRANCH = release_branch mock_github.return_value.get_organization.return_value.get_repo.return_value.get_branch.return_value = mocker.Mock( commit=mocker.Mock(sha=fake_commit)) sync_starter_configs(git_url, config_filenames, fake_commit) mock_github.return_value.get_organization.return_value.get_repo.return_value.get_branch.assert_called_once_with( release_branch) for config_file in config_filenames: mock_github.return_value.get_organization.return_value.get_repo.return_value.get_contents.assert_any_call( config_file, fake_commit)
def test_sync_starter_configs_success_update(mocker, mock_github): """sync_starter_configs should successfully update a WebsiteStarter object""" git_url = "https://github.com/testorg/ocws-configs" slug = "site-1" config_content = b"---\nroot-url-path: sites\ncollections: []" file_list = [f"{slug}/ocw-studio.yaml"] starter = WebsiteStarterFactory.create( source=STARTER_SOURCE_GITHUB, path=f"{git_url}/{slug}", slug=slug, name="Site 1", config={"foo": "bar"}, ) starter_count = WebsiteStarter.objects.count() mock_github.return_value.get_organization.return_value.get_repo.return_value.get_contents.return_value = mocker.Mock( path=file_list[0], decoded_content=config_content) sync_starter_configs(git_url, file_list) assert WebsiteStarter.objects.count() == starter_count starter.refresh_from_db() assert starter.name == "Site 1" assert starter.config == {"root-url-path": "sites", "collections": []}