Add setting for automated OT creation flag (#4122)

* Add setting for automated OT creation toggle

* Update cron.yaml

* add/change tests
This commit is contained in:
Daniel Smith 2024-07-17 15:14:50 -07:00 коммит произвёл GitHub
Родитель ec9a9c1c51
Коммит 85faf4a48f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
7 изменённых файлов: 51 добавлений и 20 удалений

Просмотреть файл

@ -25,6 +25,7 @@ from api import stages_api
from internals.user_models import AppUser
from internals.core_models import FeatureEntry, MilestoneSet, Stage
from internals.review_models import Gate
import settings
test_app = flask.Flask(__name__)
@ -178,7 +179,7 @@ class StagesAPITest(testing_config.CustomTestCase):
with test_app.test_request_context(f'{self.request_path}1/stages/3001'):
with self.assertRaises(werkzeug.exceptions.BadRequest):
self.handler.do_get(feature_id=1, stage_id=3001)
mock_abort.assert_called_once_with(404, description=f'Stage 3001 not found')
mock_abort.assert_called_once_with(404, description='Stage 3001 not found')
@mock.patch('flask.abort')
def test_get__no_id(self, mock_abort):
@ -531,11 +532,11 @@ class StagesAPITest(testing_config.CustomTestCase):
# Existing fields not specified should not be changed.
self.assertEqual(stage.experiment_goals, 'To be the very best.')
@mock.patch('internals.notifier_helpers.send_ot_notification')
def test_patch__ot_creation(self, mock_send_ot_notification):
@mock.patch('internals.notifier_helpers.send_ot_creation_notification')
def test_patch__ot_creation(self, mock_send_ot_creation_notification):
"""A valid PATCH request should update an existing stage."""
testing_config.sign_in('feature_owner@example.com', 123)
mock_send_ot_notification.return_value = None
mock_send_ot_creation_notification.return_value = None
json = {
'ot_action_requested': {
'form_field_name': 'ot_action_requested',
@ -558,16 +559,16 @@ class StagesAPITest(testing_config.CustomTestCase):
# Existing fields not specified should not be changed.
self.assertEqual(stage.experiment_goals, 'To be the very best.')
# OT creation request notification should be sent.
mock_send_ot_notification.assert_called_once()
mock_send_ot_creation_notification.assert_called_once()
@mock.patch('internals.notifier_helpers.send_ot_notification')
def test_patch__ot_extension(self, mock_send_ot_notification):
@mock.patch('internals.notifier_helpers.send_ot_creation_notification')
def test_patch__ot_extension(self, mock_send_ot_creation_notification):
"""A valid PATCH request should update an existing stage."""
testing_config.sign_in('feature_owner@example.com', 123)
# extension stage type.
self.stage_1.stage_type = 151
self.stage_1.put()
mock_send_ot_notification.return_value = None
mock_send_ot_creation_notification.return_value = None
json = {
'ot_action_requested': {
'form_field_name': 'ot_action_requested',
@ -590,7 +591,7 @@ class StagesAPITest(testing_config.CustomTestCase):
# Existing fields not specified should not be changed.
self.assertEqual(stage.experiment_goals, 'To be the very best.')
# OT extension request should NOT send a notification.
mock_send_ot_notification.assert_not_called()
mock_send_ot_creation_notification.assert_not_called()
def test_patch__ot_request_googler(self):
"""A valid OT creation request from a googler should update stage."""

Просмотреть файл

@ -38,11 +38,9 @@ cron:
- description: Send origin trial process reminder emails.
url: /cron/send-ot-process-reminders
schedule: every monday 4:00
# TODO(DanielRyanSmith): Add this job when OT creation is fully implemented.
# - description: Check if any origin trials require creation
# url: /cron/create_origin_trials
# schedule: every 5 minutes
# - description: Check if any origin trials require activation
# url: /cron/activate_origin_trials
# schedule: every day 4:00
- description: Check if any origin trials require creation
url: /cron/create_origin_trials
schedule: every 5 minutes
- description: Check if any origin trials require activation
url: /cron/activate_origin_trials
schedule: every day 9:00

Просмотреть файл

@ -378,9 +378,11 @@ class EntitiesAPIHandler(APIHandler):
stage.put()
# Notify of OT creation request if one was sent.
# This notification is for non-automated OT creation only.
if (ot_action_requested and
stage.stage_type in ALL_ORIGIN_TRIAL_STAGE_TYPES):
notifier_helpers.send_ot_notification(stage)
stage.stage_type in ALL_ORIGIN_TRIAL_STAGE_TYPES and
not settings.AUTOMATED_OT_CREATION):
notifier_helpers.send_ot_creation_notification(stage)
return stage_was_updated

Просмотреть файл

@ -29,6 +29,7 @@ from internals.data_types import StageDict
from internals.review_models import Gate, Vote, Activity
from internals.core_enums import *
from internals.feature_links import batch_index_feature_entries
import settings
class EvaluateGateStatus(FlaskHandler):
@ -571,6 +572,8 @@ class CreateOriginTrials(FlaskHandler):
def get_template_data(self, **kwargs):
"""Create any origin trials that are flagged for creation."""
self.require_cron_header()
if not settings.AUTOMATED_OT_CREATION:
return 'Automated OT creation process is not active.'
# OT stages that are flagged to process a trial creation.
ot_stages: list[Stage] = Stage.query(
@ -597,6 +600,8 @@ class ActivateOriginTrials(FlaskHandler):
them.
"""
self.require_cron_header()
if not settings.AUTOMATED_OT_CREATION:
return 'Automated OT creation process is not active.'
success_count, fail_count = 0, 0
today = self._get_today()

Просмотреть файл

@ -23,6 +23,7 @@ from internals import maintenance_scripts
from internals import core_enums
from internals.core_models import FeatureEntry, Stage, MilestoneSet
from internals.review_models import Gate, Vote
import settings
class AssociateOTsTest(testing_config.CustomTestCase):
@ -278,10 +279,14 @@ class CreateOriginTrialsTest(testing_config.CustomTestCase):
self.ot_stage_3
self.handler = maintenance_scripts.CreateOriginTrials()
# Needs to be set in order to test any functionality here.
settings.AUTOMATED_OT_CREATION = True
def tearDown(self):
for kind in [FeatureEntry, Stage]:
for entity in kind.query():
entity.key.delete()
settings.AUTOMATED_OT_CREATION = False
@mock.patch('framework.cloud_tasks_helpers.enqueue_task')
@mock.patch('internals.maintenance_scripts.CreateOriginTrials._get_today')
@ -432,6 +437,12 @@ class CreateOriginTrialsTest(testing_config.CustomTestCase):
# OT 3 had no action request, so it should not have changed.
self.assertIsNone(self.ot_stage_3.origin_trial_id)
def test_create_trials__automation_not_active(self):
"""Cron job doesn't run when automated creation is not turned on."""
settings.AUTOMATED_OT_CREATION = False
result = self.handler.get_template_data()
self.assertEqual('Automated OT creation process is not active.', result)
class ActivateOriginTrialsTest(testing_config.CustomTestCase):
@ -487,10 +498,14 @@ class ActivateOriginTrialsTest(testing_config.CustomTestCase):
self.ot_stage_3
self.handler = maintenance_scripts.ActivateOriginTrials()
# Needs to be set in order to test any functionality here.
settings.AUTOMATED_OT_CREATION = True
def tearDown(self):
for kind in [FeatureEntry, Stage]:
for entity in kind.query():
entity.key.delete()
settings.AUTOMATED_OT_CREATION = False
@mock.patch('framework.cloud_tasks_helpers.enqueue_task')
@mock.patch('internals.maintenance_scripts.ActivateOriginTrials._get_today')
@ -551,6 +566,13 @@ class ActivateOriginTrialsTest(testing_config.CustomTestCase):
self.assertIsNotNone(self.ot_stage_1.ot_activation_date)
self.assertIsNotNone(self.ot_stage_2.ot_activation_date)
def test_activate_trials__automation_not_active(self):
"""Cron job doesn't run when automated creation is not turned on."""
settings.AUTOMATED_OT_CREATION = False
result = self.handler.get_template_data()
self.assertEqual('Automated OT creation process is not active.', result)
class DeleteEmptyExtensionStagesTest(testing_config.CustomTestCase):

Просмотреть файл

@ -191,7 +191,7 @@ def notify_subscribers_of_new_comments(fe: 'FeatureEntry', gate: Gate,
cloud_tasks_helpers.enqueue_task('/tasks/email-comments', params)
def send_ot_notification(stage: Stage):
def send_ot_creation_notification(stage: Stage):
"""Notify about new trial creation request."""
stage_dict = converters.stage_to_json_dict(stage)
# Add the OT request note, which is usually not publicly visible.

Просмотреть файл

@ -38,6 +38,9 @@ DEFAULT_COMPONENT = 'Blink'
# The default component for enterprise features.
DEFAULT_ENTERPRISE_COMPONENT = 'Enterprise'
# Enable to activate the automated OT creation process
AUTOMATED_OT_CREATION = False
################################################################################