def process(self, version): """Process a single version, figuring out if it should be auto-approved and calling the approval code if necessary.""" already_locked = AutoApprovalSummary.check_is_locked(version) if not already_locked: # Lock the addon for ourselves if possible. Even though # AutoApprovalSummary.create_summary_for_version() will do # call check_is_locked() again later when calculating the verdict, # we have to do it now to prevent overwriting an existing lock with # our own. set_reviewing_cache(version.addon.pk, settings.TASK_USER_ID) try: log.info('Processing %s version %s...', unicode(version.addon.name), unicode(version.version)) summary, info = AutoApprovalSummary.create_summary_for_version( version, dry_run=self.dry_run) log.info('Auto Approval for %s version %s: %s', unicode(version.addon.name), unicode(version.version), summary.get_verdict_display()) self.stats.update({k: int(v) for k, v in info.items()}) if summary.verdict == self.successful_verdict: self.stats['auto_approved'] += 1 if summary.verdict == amo.AUTO_APPROVED: self.approve(version) except (AutoApprovalNotEnoughFilesError, AutoApprovalNoValidationResultError): log.info( 'Version %s was skipped either because it had no ' 'file or because it had no validation attached.', version) self.stats['error'] += 1 finally: # Always clear our own lock no matter what happens (but only ours). if not already_locked: clear_reviewing_cache(version.addon.pk)
def test_create_summary_no_previously_approved_versions( self, calculate_verdict_mock): AddonApprovalsCounter.objects.all().delete() self.version.reload() calculate_verdict_mock.return_value = {'dummy_verdict': True} summary, info = AutoApprovalSummary.create_summary_for_version( self.version, max_average_daily_users=111, min_approved_updates=222) assert summary.pk assert summary.approved_updates == 0 assert info == {'dummy_verdict': True}
def test_create_summary_already_existing(self): # Create a dummy summary manually, then call the method to create a # real one. It should have just updated the previous instance. summary = AutoApprovalSummary.objects.create( version=self.version, uses_custom_csp=True, uses_native_messaging=True, uses_content_script_for_all_urls=True) assert summary.pk assert summary.version == self.version assert summary.uses_custom_csp is True assert summary.uses_native_messaging is True assert summary.uses_content_script_for_all_urls is True assert summary.average_daily_users == 0 assert summary.approved_updates == 0 assert summary.verdict == amo.NOT_AUTO_APPROVED previous_summary_pk = summary.pk summary, info = AutoApprovalSummary.create_summary_for_version( self.version, max_average_daily_users=self.addon.average_daily_users + 1, min_approved_updates=1) assert summary.pk == previous_summary_pk assert summary.version == self.version assert summary.uses_custom_csp is False assert summary.uses_native_messaging is False assert summary.uses_content_script_for_all_urls is False assert summary.average_daily_users == self.addon.average_daily_users assert summary.approved_updates == 1 assert summary.verdict == amo.AUTO_APPROVED assert info == { 'too_few_approved_updates': False, 'too_many_average_daily_users': False, 'uses_content_script_for_all_urls': False, 'uses_custom_csp': False, 'uses_native_messaging': False, 'has_info_request': False, 'is_locked': False, 'is_under_admin_review': False, }
def test_create_summary_for_version(self, calculate_verdict_mock): calculate_verdict_mock.return_value = {'dummy_verdict': True} summary, info = AutoApprovalSummary.create_summary_for_version( self.version, max_average_daily_users=111, min_approved_updates=222) assert calculate_verdict_mock.call_count == 1 assert calculate_verdict_mock.call_args == ({ 'max_average_daily_users': 111, 'min_approved_updates': 222, 'dry_run': False },) assert summary.pk assert summary.version == self.version assert summary.uses_custom_csp is False assert summary.uses_native_messaging is False assert summary.uses_content_script_for_all_urls is False assert summary.average_daily_users == self.addon.average_daily_users assert (summary.approved_updates == self.addon.addonapprovalscounter.counter) assert info == {'dummy_verdict': True}
def process(self, version): """Process a single version, figuring out if it should be auto-approved and calling the approval code if necessary.""" already_locked = AutoApprovalSummary.check_is_locked(version) if not already_locked: # Lock the addon for ourselves if possible. Even though # AutoApprovalSummary.create_summary_for_version() will do # call check_is_locked() again later when calculating the verdict, # we have to do it now to prevent overwriting an existing lock with # our own. set_reviewing_cache(version.addon.pk, settings.TASK_USER_ID) try: log.info('Processing %s version %s...', unicode(version.addon.name), unicode(version.version)) summary, info = AutoApprovalSummary.create_summary_for_version( version, max_average_daily_users=self.max_average_daily_users, min_approved_updates=self.min_approved_updates, dry_run=self.dry_run, post_review=waffle.switch_is_active('post-review')) log.info('Auto Approval for %s version %s: %s', unicode(version.addon.name), unicode(version.version), summary.get_verdict_display()) self.stats.update({k: int(v) for k, v in info.items()}) if summary.verdict == self.successful_verdict: self.stats['auto_approved'] += 1 if summary.verdict == amo.AUTO_APPROVED: self.approve(version) except (AutoApprovalNotEnoughFilesError, AutoApprovalNoValidationResultError): log.info( 'Version %s was skipped either because it had no ' 'file or because it had no validation attached.', version) self.stats['error'] += 1 finally: # Always clear our own lock no matter what happens (but only ours). if not already_locked: clear_reviewing_cache(version.addon.pk)
def test_create_summary_no_files(self): self.file.delete() del self.version.all_files with self.assertRaises(AutoApprovalNotEnoughFilesError): AutoApprovalSummary.create_summary_for_version(self.version)
def handle(self, *args, **options): dry_run = options.get('dry_run', False) max_average_daily_users = int( get_config('AUTO_APPROVAL_MAX_AVERAGE_DAILY_USERS') or 0) min_approved_updates = int( get_config('AUTO_APPROVAL_MIN_APPROVED_UPDATES') or 0) if min_approved_updates <= 0 or max_average_daily_users <= 0: # Auto approval are shut down if one of those values is not present # or <= 0. url = '%s%s' % (settings.SITE_URL, reverse('admin:zadmin_config_changelist')) raise CommandError( 'Auto-approvals are deactivated because either ' 'AUTO_APPROVAL_MAX_AVERAGE_DAILY_USERS or ' 'AUTO_APPROVAL_MIN_APPROVED_UPDATES have not been ' 'set or were set to 0. Use the admin tools Config model to ' 'set them by going to %s.' % url) stats = Counter() qs = self.fetch_candidates() stats['total'] = len(qs) successful_verdict = (amo.WOULD_HAVE_BEEN_AUTO_APPROVED if dry_run else amo.AUTO_APPROVED) for version in qs: # Is the addon already locked by a reviewer ? if get_reviewing_cache(version.addon.pk): stats['locked'] += 1 continue # If admin review or more information was requested, skip this # version, let a human handle it. if version.addon.admin_review or version.has_info_request: stats['flagged'] += 1 continue # Lock the addon for ourselves, no reviewer should touch it. set_reviewing_cache(version.addon.pk, settings.TASK_USER_ID) try: log.info('Processing %s version %s...', unicode(version.addon.name), unicode(version.version)) summary, info = AutoApprovalSummary.create_summary_for_version( version, max_average_daily_users=max_average_daily_users, min_approved_updates=min_approved_updates, dry_run=dry_run) log.info('Auto Approval for %s version %s: %s', unicode(version.addon.name), unicode(version.version), summary.get_verdict_display()) stats.update({k: int(v) for k, v in info.items()}) if summary.verdict == successful_verdict: stats['auto_approved'] += 1 # FIXME: implement auto-approve if verdict is amo.AUTO_APPROVED except (AutoApprovalNotEnoughFilesError, AutoApprovalNoValidationResultError): log.info( 'Version %s was skipped either because it had no ' 'file or because it had no validation attached.', version) stats['error'] += 1 finally: clear_reviewing_cache(version.addon.pk) self.log_final_summary(stats, dry_run=dry_run)