From 88c662c3f03fa29d4d30f76c5c9f46cae54d303b Mon Sep 17 00:00:00 2001 From: Simon Kelly Date: Fri, 10 Jan 2025 22:50:32 +0200 Subject: [PATCH 1/8] rollout command --- .../commands/enable_versioning_for_teams.py | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 apps/experiments/management/commands/enable_versioning_for_teams.py diff --git a/apps/experiments/management/commands/enable_versioning_for_teams.py b/apps/experiments/management/commands/enable_versioning_for_teams.py new file mode 100644 index 000000000..30c92fa3f --- /dev/null +++ b/apps/experiments/management/commands/enable_versioning_for_teams.py @@ -0,0 +1,56 @@ +import traceback + +from django.core.management import BaseCommand + +from apps.experiments.models import Experiment +from apps.teams.models import Flag +from apps.teams.utils import current_team + + +class Command(BaseCommand): + def add_arguments(self, parser): + parser.add_argument("teams", help="The team slug to enable versioning for.") + parser.add_argument("--force", action="store_true", help="Force enable versioning.") + + def handle(self, teams, **options): + team_slugs = teams.split(",") + for slug in team_slugs: + if not slug.strip(): + continue + self._enable_for_team(slug.strip(), **options) + + def _enable_for_team(self, team_slug, **options): + from apps.teams.models import Team + + try: + team = Team.objects.get(slug=team_slug) + except Team.DoesNotExist: + self.stderr.write(f"Team {team} does not exist.") + return + + flag = Flag.get("experiment_versions") + flag_is_active = flag.is_active_for_team(team) + if flag_is_active: + self.stdout.write(f"Versioning is already enabled for team {team.slug}.") + if not options["force"]: + return + else: + self.stdout.write("Forcing versioning.") + + with current_team(team): + for experiment in Experiment.objects.filter(team=team, working_version_id=None).order_by("-id"): + if not Experiment.objects.filter(working_version=experiment).exists(): + self.stdout.write(f"Creating version for experiment {experiment.name} ({experiment.id}).") + try: + experiment.create_new_version() + except Exception as e: + traceback.print_exception(type(e), e, e.__traceback__) + self.stderr.write( + f"Failed to create version for experiment {experiment.name} ({experiment.id}): {e}" + ) + + if not flag_is_active: + flag.teams.add(team) + flag.flush() + + self.stdout.write(f"Versioning enabled for team {team.slug}.") From a1c7fe43f44963b8b44eada14f532a7a2fa489ea Mon Sep 17 00:00:00 2001 From: Simon Kelly Date: Fri, 10 Jan 2025 22:50:46 +0200 Subject: [PATCH 2/8] remove rollout commands --- .../commands/enable_versioning_for_team.py | 52 ----------------- .../commands/enable_versioning_for_teams.py | 56 ------------------- 2 files changed, 108 deletions(-) delete mode 100644 apps/experiments/management/commands/enable_versioning_for_team.py delete mode 100644 apps/experiments/management/commands/enable_versioning_for_teams.py diff --git a/apps/experiments/management/commands/enable_versioning_for_team.py b/apps/experiments/management/commands/enable_versioning_for_team.py deleted file mode 100644 index 92892b898..000000000 --- a/apps/experiments/management/commands/enable_versioning_for_team.py +++ /dev/null @@ -1,52 +0,0 @@ -import traceback - -from django.core.management import BaseCommand, CommandError - -from apps.experiments.models import Experiment -from apps.teams.models import Flag -from apps.teams.utils import current_team - - -class Command(BaseCommand): - def add_arguments(self, parser): - parser.add_argument("team", help="The team slug to enable versioning for.") - parser.add_argument("--force", action="store_true", help="Force enable versioning.") - parser.add_argument( - "--continue-on-error", action="store_true", help="Continue creating versions even if an error occurs." - ) - - def handle(self, team, **options): - from apps.teams.models import Team - - try: - team = Team.objects.get(slug=team) - except Team.DoesNotExist: - raise CommandError(f"Team {team} does not exist.") - - flag = Flag.get("experiment_versions") - flag_is_active = flag.is_active_for_team(team) - if flag_is_active and not options["force"]: - raise CommandError(f"Versioning is already enabled for team {team.slug}.") - - with current_team(team): - for experiment in Experiment.objects.filter(team=team, working_version_id=None).order_by("-id"): - if not Experiment.objects.filter(working_version=experiment).exists(): - self.stdout.write(f"Creating version for experiment {experiment.name} ({experiment.id}).") - try: - experiment.create_new_version() - except Exception as e: - traceback.print_exception(type(e), e, e.__traceback__) - if options["continue_on_error"]: - self.stderr.write( - f"Failed to create version for experiment {experiment.name} ({experiment.id}): {e}" - ) - else: - raise CommandError( - f"Failed to create version for experiment {experiment.name} ({experiment.id}): {e}" - ) - - if not flag_is_active: - flag.teams.add(team) - flag.flush() - - self.stdout.write(f"Versioning enabled for team {team.slug}.") diff --git a/apps/experiments/management/commands/enable_versioning_for_teams.py b/apps/experiments/management/commands/enable_versioning_for_teams.py deleted file mode 100644 index 30c92fa3f..000000000 --- a/apps/experiments/management/commands/enable_versioning_for_teams.py +++ /dev/null @@ -1,56 +0,0 @@ -import traceback - -from django.core.management import BaseCommand - -from apps.experiments.models import Experiment -from apps.teams.models import Flag -from apps.teams.utils import current_team - - -class Command(BaseCommand): - def add_arguments(self, parser): - parser.add_argument("teams", help="The team slug to enable versioning for.") - parser.add_argument("--force", action="store_true", help="Force enable versioning.") - - def handle(self, teams, **options): - team_slugs = teams.split(",") - for slug in team_slugs: - if not slug.strip(): - continue - self._enable_for_team(slug.strip(), **options) - - def _enable_for_team(self, team_slug, **options): - from apps.teams.models import Team - - try: - team = Team.objects.get(slug=team_slug) - except Team.DoesNotExist: - self.stderr.write(f"Team {team} does not exist.") - return - - flag = Flag.get("experiment_versions") - flag_is_active = flag.is_active_for_team(team) - if flag_is_active: - self.stdout.write(f"Versioning is already enabled for team {team.slug}.") - if not options["force"]: - return - else: - self.stdout.write("Forcing versioning.") - - with current_team(team): - for experiment in Experiment.objects.filter(team=team, working_version_id=None).order_by("-id"): - if not Experiment.objects.filter(working_version=experiment).exists(): - self.stdout.write(f"Creating version for experiment {experiment.name} ({experiment.id}).") - try: - experiment.create_new_version() - except Exception as e: - traceback.print_exception(type(e), e, e.__traceback__) - self.stderr.write( - f"Failed to create version for experiment {experiment.name} ({experiment.id}): {e}" - ) - - if not flag_is_active: - flag.teams.add(team) - flag.flush() - - self.stdout.write(f"Versioning enabled for team {team.slug}.") From 2903738ea05c4e2e13f6074c596d798de60b0695 Mon Sep 17 00:00:00 2001 From: Simon Kelly Date: Fri, 10 Jan 2025 22:52:54 +0200 Subject: [PATCH 3/8] remove feature flag --- apps/experiments/tests/test_views.py | 1 - apps/experiments/views/experiment.py | 11 ++-- templates/experiments/experiment_form.html | 4 +- .../experiments/single_experiment_home.html | 60 +++++++++---------- 4 files changed, 34 insertions(+), 42 deletions(-) diff --git a/apps/experiments/tests/test_views.py b/apps/experiments/tests/test_views.py index e00debec2..117f1bbfd 100644 --- a/apps/experiments/tests/test_views.py +++ b/apps/experiments/tests/test_views.py @@ -75,7 +75,6 @@ def test_create_experiment_success(client, team_with_users): experiment.tools == [AgentTools.ONE_OFF_REMINDER] -@override_flag("experiment_versions", active=True) @override_settings(CELERY_TASK_ALWAYS_EAGER=True) @pytest.mark.django_db() def test_create_experiment_creates_first_version(client, team_with_users): diff --git a/apps/experiments/views/experiment.py b/apps/experiments/views/experiment.py index 1b480e4fa..f871481a6 100644 --- a/apps/experiments/views/experiment.py +++ b/apps/experiments/views/experiment.py @@ -468,12 +468,11 @@ def form_valid(self, form, file_formset): files = file_formset.save(self.request) self.object.files.set(files) - if flag_is_active(self.request, "experiment_versions"): - task_id = async_create_experiment_version.delay( - experiment_id=self.object.id, version_description="", make_default=True - ) - self.object.create_version_task_id = task_id - self.object.save(update_fields=["create_version_task_id"]) + task_id = async_create_experiment_version.delay( + experiment_id=self.object.id, version_description="", make_default=True + ) + self.object.create_version_task_id = task_id + self.object.save(update_fields=["create_version_task_id"]) return HttpResponseRedirect(self.get_success_url()) diff --git a/templates/experiments/experiment_form.html b/templates/experiments/experiment_form.html index f8af187bd..4cf0cf635 100644 --- a/templates/experiments/experiment_form.html +++ b/templates/experiments/experiment_form.html @@ -130,9 +130,7 @@

{% translate "Please note" %}

{% if experiment.id %} - {% flag "experiment_versions" %} - - {% endflag %} + {% endif %}
diff --git a/templates/experiments/single_experiment_home.html b/templates/experiments/single_experiment_home.html index 81af9d299..737026f6d 100644 --- a/templates/experiments/single_experiment_home.html +++ b/templates/experiments/single_experiment_home.html @@ -18,28 +18,26 @@

{{ experiment.name }}

- {% flag "experiment_versions" %} - {% if experiment.is_archived %} -
- Archived + {% if experiment.is_archived %} +
+ Archived +
+ {% elif deployed_version %} +
+ - {% elif deployed_version %} -
- -
-
+
- {% endif %} - {% endflag %} +
+ {% endif %}
@@ -299,20 +297,18 @@

Parent Experiments:

- {% flag "experiment_versions" %} - -
-
-
-
+ +
+
+
- {% endflag %} +
{% flag "events" %} From 219344fcac35161e61195856b3a91722f8000220 Mon Sep 17 00:00:00 2001 From: Simon Kelly Date: Fri, 10 Jan 2025 22:54:24 +0200 Subject: [PATCH 4/8] only disable button if version create is in progress --- apps/experiments/views/experiment.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/experiments/views/experiment.py b/apps/experiments/views/experiment.py index f871481a6..f6a286d1a 100644 --- a/apps/experiments/views/experiment.py +++ b/apps/experiments/views/experiment.py @@ -377,9 +377,6 @@ def extra_context(self): if self.object: team_participant_identifiers.extend(self.object.participant_allowlist) team_participant_identifiers = set(team_participant_identifiers) - fields_changed = self.object.compare_with_latest() - else: - fields_changed = [] return { **{ @@ -389,7 +386,7 @@ def extra_context(self): "experiment_type": experiment_type, "available_tools": AgentTools.choices, "team_participant_identifiers": team_participant_identifiers, - "disable_version_button": (not bool(fields_changed)) or self.object.create_version_task_id, + "disable_version_button": self.object.create_version_task_id, }, **_get_voice_provider_alpine_context(self.request), } From 957e04d37db014dc6dd1a5a8eb5ca83e41321881 Mon Sep 17 00:00:00 2001 From: Simon Kelly Date: Fri, 10 Jan 2025 22:55:33 +0200 Subject: [PATCH 5/8] make description optional --- apps/experiments/views/experiment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/experiments/views/experiment.py b/apps/experiments/views/experiment.py index f6a286d1a..b8ab608f0 100644 --- a/apps/experiments/views/experiment.py +++ b/apps/experiments/views/experiment.py @@ -551,7 +551,7 @@ class DeleteFileFromExperiment(BaseDeleteFileView): # TODO: complete form class ExperimentVersionForm(forms.ModelForm): - version_description = forms.CharField(widget=forms.Textarea(attrs={"rows": 2})) + version_description = forms.CharField(widget=forms.Textarea(attrs={"rows": 2}), required=False) is_default_version = forms.BooleanField(required=False, label="Set as Published Version") class Meta: From 8d3148db6b62c67a9485bac46fef8ef59e4d7185 Mon Sep 17 00:00:00 2001 From: Simon Kelly Date: Fri, 10 Jan 2025 22:56:23 +0200 Subject: [PATCH 6/8] remove TODO --- apps/experiments/views/experiment.py | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/experiments/views/experiment.py b/apps/experiments/views/experiment.py index b8ab608f0..cbfc67251 100644 --- a/apps/experiments/views/experiment.py +++ b/apps/experiments/views/experiment.py @@ -549,7 +549,6 @@ class DeleteFileFromExperiment(BaseDeleteFileView): pass -# TODO: complete form class ExperimentVersionForm(forms.ModelForm): version_description = forms.CharField(widget=forms.Textarea(attrs={"rows": 2}), required=False) is_default_version = forms.BooleanField(required=False, label="Set as Published Version") From 95e7ed8a0310460631d520cdb52e557dbaf46bfd Mon Sep 17 00:00:00 2001 From: Simon Kelly Date: Fri, 10 Jan 2025 23:00:09 +0200 Subject: [PATCH 7/8] hide form on create version page if task ID set --- .../experiments/create_version_form.html | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/templates/experiments/create_version_form.html b/templates/experiments/create_version_form.html index f4c8680df..d2863f0fc 100644 --- a/templates/experiments/create_version_form.html +++ b/templates/experiments/create_version_form.html @@ -15,25 +15,29 @@ {% block app %}

Create New Version

- {% if not version_details.instance.has_versions or version_details.fields_changed %} -
- {% csrf_token %} - {% render_form_fields form %} -
-

- -

-
-
- {% endif %} - {% if version_details.instance.has_versions %} - {% if version_details.fields_changed %} -

Changes since version {{ version_details.previous_instance.version_number }}

-
- {% include 'experiments/components/versions/compare.html' %} -
- {% else %} -

No changes since version {{ version_details.previous_instance.version_number }}

+ {% if experiment.create_version_task_id %} +

A new version being created. Please wait until it is complete before making another version.

+ {% else %} + {% if not version_details.instance.has_versions or version_details.fields_changed %} +
+ {% csrf_token %} + {% render_form_fields form %} +
+

+ +

+
+
+ {% endif %} + {% if version_details.instance.has_versions %} + {% if version_details.fields_changed %} +

Changes since version {{ version_details.previous_instance.version_number }}

+
+ {% include 'experiments/components/versions/compare.html' %} +
+ {% else %} +

No changes since version {{ version_details.previous_instance.version_number }}

+ {% endif %} {% endif %} {% endif %}
From 1915833b0bc60a3a5f2ee18d753da7bedf5f4da1 Mon Sep 17 00:00:00 2001 From: Simon Kelly Date: Fri, 10 Jan 2025 23:16:41 +0200 Subject: [PATCH 8/8] display building status in title badge --- templates/experiments/create_version_button.html | 5 +++++ templates/experiments/single_experiment_home.html | 1 + 2 files changed, 6 insertions(+) diff --git a/templates/experiments/create_version_button.html b/templates/experiments/create_version_button.html index cb7c9d8cd..3003c4a03 100644 --- a/templates/experiments/create_version_button.html +++ b/templates/experiments/create_version_button.html @@ -11,6 +11,11 @@
+
+
+
Building new version
+
+
{% else %} {{ experiment.name }}