@@ -1351,10 +1351,41 @@ class UpdateStatusForm(NimbusChangeLogFormMixin, forms.ModelForm):
13511351 publish_status = None
13521352 is_paused = None
13531353
1354+ required_status = None
1355+ required_status_next = None
1356+ required_publish_status = None
1357+ required_is_paused = None
1358+
13541359 class Meta :
13551360 model = NimbusExperiment
13561361 fields = []
13571362
1363+ def clean (self ):
1364+ cleaned_data = super ().clean ()
1365+
1366+ required_state = (
1367+ self .required_status ,
1368+ self .required_status_next ,
1369+ self .required_publish_status ,
1370+ self .required_is_paused ,
1371+ )
1372+ current_state = (
1373+ self .instance .status ,
1374+ self .instance .status_next ,
1375+ self .instance .publish_status ,
1376+ self .instance .is_paused ,
1377+ )
1378+
1379+ if required_state != current_state :
1380+ raise forms .ValidationError (
1381+ NimbusUIConstants .ERROR_INVALID_STATE_TRANSITION .format (
1382+ required_state = required_state ,
1383+ current_state = current_state ,
1384+ )
1385+ )
1386+
1387+ return cleaned_data
1388+
13581389 @transaction .atomic
13591390 def save (self , commit = True ):
13601391 self .instance .status = self .status
@@ -1386,9 +1417,15 @@ def save(self, commit=True):
13861417
13871418
13881419class DraftToPreviewForm (UpdateStatusForm ):
1420+ required_status = NimbusExperiment .Status .DRAFT
1421+ required_status_next = None
1422+ required_publish_status = NimbusExperiment .PublishStatus .IDLE
1423+ required_is_paused = False
1424+
13891425 status = NimbusExperiment .Status .PREVIEW
1390- status_next = NimbusExperiment . Status . PREVIEW
1426+ status_next = None
13911427 publish_status = NimbusExperiment .PublishStatus .IDLE
1428+ is_paused = False
13921429
13931430 def get_changelog_message (self ):
13941431 return f"{ self .request .user } launched experiment to Preview"
@@ -1403,29 +1440,49 @@ def save(self, commit=True):
14031440
14041441
14051442class DraftToReviewForm (SlackNotificationMixin , UpdateStatusForm ):
1443+ required_status = NimbusExperiment .Status .DRAFT
1444+ required_status_next = None
1445+ required_publish_status = NimbusExperiment .PublishStatus .IDLE
1446+ required_is_paused = False
1447+
14061448 status = NimbusExperiment .Status .DRAFT
14071449 status_next = NimbusExperiment .Status .LIVE
14081450 publish_status = NimbusExperiment .PublishStatus .REVIEW
1451+ is_paused = False
1452+
14091453 slack_action = NimbusConstants .SLACK_ACTION_LAUNCH_REQUEST
14101454
14111455 def get_changelog_message (self ):
14121456 return f"{ self .request .user } requested launch without Preview"
14131457
14141458
14151459class PreviewToReviewForm (SlackNotificationMixin , UpdateStatusForm ):
1460+ required_status = NimbusExperiment .Status .PREVIEW
1461+ required_status_next = None
1462+ required_publish_status = NimbusExperiment .PublishStatus .IDLE
1463+ required_is_paused = False
1464+
14161465 status = NimbusExperiment .Status .DRAFT
14171466 status_next = NimbusExperiment .Status .LIVE
14181467 publish_status = NimbusExperiment .PublishStatus .REVIEW
1468+ is_paused = False
1469+
14191470 slack_action = NimbusConstants .SLACK_ACTION_LAUNCH_REQUEST
14201471
14211472 def get_changelog_message (self ):
14221473 return f"{ self .request .user } requested launch from Preview"
14231474
14241475
14251476class PreviewToDraftForm (UpdateStatusForm ):
1477+ required_status = NimbusExperiment .Status .PREVIEW
1478+ required_status_next = None
1479+ required_publish_status = NimbusExperiment .PublishStatus .IDLE
1480+ required_is_paused = False
1481+
14261482 status = NimbusExperiment .Status .DRAFT
1427- status_next = NimbusExperiment . Status . DRAFT
1483+ status_next = None
14281484 publish_status = NimbusExperiment .PublishStatus .IDLE
1485+ is_paused = False
14291486
14301487 def get_changelog_message (self ):
14311488 return f"{ self .request .user } moved the experiment back to Draft"
@@ -1438,9 +1495,16 @@ def save(self, commit=True):
14381495
14391496
14401497class ReviewToDraftForm (UpdateStatusForm ):
1498+ required_status = NimbusExperiment .Status .DRAFT
1499+ required_status_next = NimbusExperiment .Status .LIVE
1500+ required_publish_status = NimbusExperiment .PublishStatus .REVIEW
1501+ required_is_paused = False
1502+
14411503 status = NimbusExperiment .Status .DRAFT
1442- status_next = NimbusExperiment . Status . DRAFT
1504+ status_next = None
14431505 publish_status = NimbusExperiment .PublishStatus .IDLE
1506+ is_paused = False
1507+
14441508 changelog_message = forms .CharField (
14451509 required = False , label = "Changelog Message" , max_length = 1000
14461510 )
@@ -1459,9 +1523,15 @@ def get_changelog_message(self):
14591523
14601524
14611525class ReviewToApproveForm (UpdateStatusForm ):
1526+ required_status = NimbusExperiment .Status .DRAFT
1527+ required_status_next = NimbusExperiment .Status .LIVE
1528+ required_publish_status = NimbusExperiment .PublishStatus .REVIEW
1529+ required_is_paused = False
1530+
14621531 status = NimbusExperiment .Status .DRAFT
14631532 status_next = NimbusExperiment .Status .LIVE
14641533 publish_status = NimbusExperiment .PublishStatus .APPROVED
1534+ is_paused = False
14651535
14661536 def get_changelog_message (self ):
14671537 return f"{ self .request .user } approved the review."
@@ -1478,46 +1548,43 @@ def save(self, commit=True):
14781548
14791549
14801550class LiveToEndEnrollmentForm (SlackNotificationMixin , UpdateStatusForm ):
1551+ required_status = NimbusExperiment .Status .LIVE
1552+ required_status_next = None
1553+ required_publish_status = NimbusExperiment .PublishStatus .IDLE
1554+ required_is_paused = False
1555+
14811556 status = NimbusExperiment .Status .LIVE
14821557 status_next = NimbusExperiment .Status .LIVE
14831558 publish_status = NimbusExperiment .PublishStatus .REVIEW
14841559 is_paused = True
1560+
14851561 slack_action = NimbusConstants .SLACK_ACTION_END_ENROLLMENT_REQUEST
14861562
14871563 def clean (self ):
1564+ cleaned_data = super ().clean ()
1565+
14881566 if self .instance and self .instance .is_rollout_dirty :
14891567 raise forms .ValidationError (NimbusExperiment .ERROR_CANNOT_PAUSE_UNPUBLISHED )
14901568
1491- if not self .instance .should_show_end_enrollment :
1492- if (
1493- self .instance .is_draft
1494- or self .instance .is_preview
1495- or self .instance .is_complete
1496- ):
1497- raise forms .ValidationError (NimbusExperiment .ERROR_CANNOT_PAUSE_NOT_LIVE )
1498-
1499- if not self .instance .is_enrolling :
1500- raise forms .ValidationError (NimbusExperiment .ERROR_CANNOT_PAUSE_PAUSED )
1501-
1502- if self .instance .is_rollout and not self .instance .is_firefox_labs_opt_in :
1503- raise forms .ValidationError (NimbusExperiment .ERROR_CANNOT_PAUSE_ROLLOUT )
1569+ if self .instance .is_rollout and not self .instance .is_firefox_labs_opt_in :
1570+ raise forms .ValidationError (NimbusExperiment .ERROR_CANNOT_PAUSE_ROLLOUT )
15041571
1505- # The conditions for Experiment.should_show_enrollment have changed
1506- # but this function has become out of sync.
1507- raise forms .ValidationError (
1508- NimbusExperiment .ERROR_CANNOT_PAUSE_INVALID
1509- ) # pragma: no cover
1510-
1511- return super ().clean ()
1572+ return cleaned_data
15121573
15131574 def get_changelog_message (self ):
15141575 return f"{ self .request .user } requested review to end enrollment"
15151576
15161577
15171578class ApproveEndEnrollmentForm (UpdateStatusForm ):
1579+ required_status = NimbusExperiment .Status .LIVE
1580+ required_status_next = NimbusExperiment .Status .LIVE
1581+ required_publish_status = NimbusExperiment .PublishStatus .REVIEW
1582+ required_is_paused = True
1583+
15181584 status = NimbusExperiment .Status .LIVE
15191585 status_next = NimbusExperiment .Status .LIVE
15201586 publish_status = NimbusExperiment .PublishStatus .APPROVED
1587+ is_paused = True
15211588
15221589 def get_changelog_message (self ):
15231590 return f"{ self .request .user } approved the end enrollment request"
@@ -1532,19 +1599,32 @@ def save(self, commit=True):
15321599
15331600
15341601class LiveToCompleteForm (SlackNotificationMixin , UpdateStatusForm ):
1602+ required_status = NimbusExperiment .Status .LIVE
1603+ required_status_next = None
1604+ required_publish_status = NimbusExperiment .PublishStatus .IDLE
1605+ required_is_paused = False
1606+
15351607 status = NimbusExperiment .Status .LIVE
15361608 status_next = NimbusExperiment .Status .COMPLETE
15371609 publish_status = NimbusExperiment .PublishStatus .REVIEW
1610+ is_paused = False
1611+
15381612 slack_action = NimbusConstants .SLACK_ACTION_END_EXPERIMENT_REQUEST
15391613
15401614 def get_changelog_message (self ):
15411615 return f"{ self .request .user } requested review to end experiment"
15421616
15431617
15441618class ApproveEndExperimentForm (UpdateStatusForm ):
1619+ required_status = NimbusExperiment .Status .LIVE
1620+ required_status_next = NimbusExperiment .Status .COMPLETE
1621+ required_publish_status = NimbusExperiment .PublishStatus .REVIEW
1622+ required_is_paused = True
1623+
15451624 status = NimbusExperiment .Status .LIVE
15461625 status_next = NimbusExperiment .Status .COMPLETE
15471626 publish_status = NimbusExperiment .PublishStatus .APPROVED
1627+ is_paused = True
15481628
15491629 def get_changelog_message (self ):
15501630 return f"{ self .request .user } approved the end experiment request"
@@ -1559,10 +1639,16 @@ def save(self, commit=True):
15591639
15601640
15611641class CancelEndEnrollmentForm (UpdateStatusForm ):
1642+ required_status = NimbusExperiment .Status .LIVE
1643+ required_status_next = NimbusExperiment .Status .LIVE
1644+ required_publish_status = NimbusExperiment .PublishStatus .REVIEW
1645+ required_is_paused = True
1646+
15621647 status = NimbusExperiment .Status .LIVE
15631648 status_next = None
15641649 publish_status = NimbusExperiment .PublishStatus .IDLE
15651650 is_paused = False
1651+
15661652 changelog_message = forms .CharField (
15671653 required = False , label = "Changelog Message" , max_length = 1000
15681654 )
@@ -1581,9 +1667,15 @@ def get_changelog_message(self):
15811667
15821668
15831669class CancelEndExperimentForm (UpdateStatusForm ):
1670+ required_status = NimbusExperiment .Status .LIVE
1671+ required_status_next = NimbusExperiment .Status .COMPLETE
1672+ required_publish_status = NimbusExperiment .PublishStatus .REVIEW
1673+ required_is_paused = True
1674+
15841675 status = NimbusExperiment .Status .LIVE
15851676 status_next = None
15861677 publish_status = NimbusExperiment .PublishStatus .IDLE
1678+
15871679 changelog_message = forms .CharField (
15881680 required = False , label = "Changelog Message" , max_length = 1000
15891681 )
@@ -1606,19 +1698,33 @@ def get_changelog_message(self):
16061698
16071699
16081700class LiveToUpdateRolloutForm (SlackNotificationMixin , UpdateStatusForm ):
1701+ required_status = NimbusExperiment .Status .LIVE
1702+ required_status_next = None
1703+ required_publish_status = NimbusExperiment .PublishStatus .IDLE
1704+ required_is_paused = False
1705+
16091706 status = NimbusExperiment .Status .LIVE
16101707 status_next = NimbusExperiment .Status .LIVE
16111708 publish_status = NimbusExperiment .PublishStatus .REVIEW
1709+ is_paused = False
1710+
16121711 slack_action = NimbusConstants .SLACK_ACTION_UPDATE_REQUEST
16131712
16141713 def get_changelog_message (self ):
16151714 return f"{ self .request .user } requested review to update Audience"
16161715
16171716
16181717class CancelUpdateRolloutForm (UpdateStatusForm ):
1718+ required_status = NimbusExperiment .Status .LIVE
1719+ required_status_next = NimbusExperiment .Status .LIVE
1720+ required_publish_status = NimbusExperiment .PublishStatus .REVIEW
1721+ required_is_paused = False
1722+
16191723 status = NimbusExperiment .Status .LIVE
16201724 status_next = None
16211725 publish_status = NimbusExperiment .PublishStatus .IDLE
1726+ is_paused = False
1727+
16221728 changelog_message = forms .CharField (
16231729 required = False , label = "Changelog Message" , max_length = 1000
16241730 )
@@ -1637,9 +1743,15 @@ def get_changelog_message(self):
16371743
16381744
16391745class ApproveUpdateRolloutForm (UpdateStatusForm ):
1746+ required_status = NimbusExperiment .Status .LIVE
1747+ required_status_next = NimbusExperiment .Status .LIVE
1748+ required_publish_status = NimbusExperiment .PublishStatus .REVIEW
1749+ required_is_paused = False
1750+
16401751 status = NimbusExperiment .Status .LIVE
16411752 status_next = NimbusExperiment .Status .LIVE
16421753 publish_status = NimbusExperiment .PublishStatus .APPROVED
1754+ is_paused = False
16431755
16441756 def get_changelog_message (self ):
16451757 return f"{ self .request .user } approved the update review request"
0 commit comments