Skip to content

Commit

Permalink
feat(nimbus): Add firefox_labs_group field (#11899)
Browse files Browse the repository at this point in the history
Because:

- We need to expose the firefoxLabsGroup field on experiments; and
- there is a typo in the `isFirefoxLabsOptIn` description

This commit:

- fixes the typo
- adds the firefox_labs_group field to the NimbusExperiment model; and
- exposes the field to the v6 and v8 APIs.

Fixes #11778
Fixes #11896
  • Loading branch information
brennie authored Dec 6, 2024
1 parent 5541d46 commit 4a72b46
Show file tree
Hide file tree
Showing 13 changed files with 111 additions and 14 deletions.
4 changes: 4 additions & 0 deletions docs/experimenter/openapi-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4249,6 +4249,10 @@
"firefoxLabsDescription": {
"type": "string",
"readOnly": true
},
"firefoxLabsGroup": {
"type": "string",
"readOnly": true
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions docs/experimenter/swagger-ui.html
Original file line number Diff line number Diff line change
Expand Up @@ -4261,6 +4261,10 @@
"firefoxLabsDescription": {
"type": "string",
"readOnly": true
},
"firefoxLabsGroup": {
"type": "string",
"readOnly": true
}
},
"required": [
Expand Down
2 changes: 2 additions & 0 deletions experimenter/experimenter/experiments/api/v6/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class NimbusExperimentSerializer(serializers.ModelSerializer):
isFirefoxLabsOptIn = serializers.ReadOnlyField(source="is_firefox_labs_opt_in")
firefoxLabsTitle = serializers.ReadOnlyField(source="firefox_labs_title")
firefoxLabsDescription = serializers.ReadOnlyField(source="firefox_labs_description")
firefoxLabsGroup = serializers.ReadOnlyField(source="firefox_labs_group")

class Meta:
model = NimbusExperiment
Expand Down Expand Up @@ -150,6 +151,7 @@ class Meta:
"isFirefoxLabsOptIn",
"firefoxLabsTitle",
"firefoxLabsDescription",
"firefoxLabsGroup",
)

def get_application(self, obj):
Expand Down
2 changes: 2 additions & 0 deletions experimenter/experimenter/experiments/api/v8/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class NimbusExperimentSerializer(serializers.ModelSerializer):
isFirefoxLabsOptIn = serializers.ReadOnlyField(source="is_firefox_labs_opt_in")
firefoxLabsTitle = serializers.ReadOnlyField(source="firefox_labs_title")
firefoxLabsDescription = serializers.ReadOnlyField(source="firefox_labs_description")
firefoxLabsGroup = serializers.ReadOnlyField(source="firefox_labs_group")

class Meta:
model = NimbusExperiment
Expand Down Expand Up @@ -152,6 +153,7 @@ class Meta:
"isFirefoxLabsOptIn",
"firefoxLabsTitle",
"firefoxLabsDescription",
"firefoxLabsGroup",
)

def get_application(self, obj):
Expand Down
5 changes: 5 additions & 0 deletions experimenter/experimenter/experiments/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,11 @@ class EmailType(models.TextChoices):
EXPERIMENT_END = "experiment end"
ENROLLMENT_END = "enrollment end"

class FirefoxLabsGroups(models.TextChoices):
CUSTOMIZE_BROWSING = "experimental-features-group-customize-browsing"
WEBPAGE_DISPLAY = "experimental-features-group-webpage-display"
DEVELOPER_TOOLS = "experimental-features-group-developer-tools"

EMAIL_EXPERIMENT_END_SUBJECT = "Action required: Please turn off your Experiment"
EMAIL_ENROLLMENT_END_SUBJECT = "Action required: Please end experiment enrollment"

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Generated by Django 5.1.1 on 2024-12-06 00:48

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("experiments", "0274_nimbusbranch_firefox_labs_title_and_more"),
]

operations = [
migrations.AddField(
model_name="nimbusexperiment",
name="firefox_labs_group",
field=models.CharField(
blank=True,
choices=[
(
"experimental-features-group-customize-browsing",
"Customize Browsing",
),
("experimental-features-group-webpage-display", "Webpage Display"),
("experimental-features-group-developer-tools", "Developer Tools"),
],
max_length=255,
null=True,
verbose_name="The group this should appear under in Firefox Labs",
),
),
migrations.AlterField(
model_name="nimbusexperiment",
name="firefox_labs_description",
field=models.TextField(
blank=True,
null=True,
verbose_name="The description to display in Firefox Labs (Fluent ID)",
),
),
migrations.AlterField(
model_name="nimbusexperiment",
name="firefox_labs_title",
field=models.TextField(
blank=True,
null=True,
verbose_name="The title to display in Firefox Labs (Fluent ID)",
),
),
migrations.AlterField(
model_name="nimbusexperiment",
name="is_firefox_labs_opt_in",
field=models.BooleanField(
default=False, verbose_name="Is Experiment a Firefox Labs Opt-In?"
),
),
]
14 changes: 10 additions & 4 deletions experimenter/experimenter/experiments/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,19 +372,25 @@ class NimbusExperiment(NimbusConstants, TargetingConstants, FilterMixin, models.
use_group_id = models.BooleanField(default=False)
objects = NimbusExperimentManager()
is_firefox_labs_opt_in = models.BooleanField(
"Is Experiment a Firefox Labs opt-n", default=False
"Is Experiment a Firefox Labs Opt-In?", default=False
)
firefox_labs_title = models.TextField(
"An optional string containing the Fluent ID for the title of the opt-in",
"The title to display in Firefox Labs (Fluent ID)",
blank=True,
null=True,
)
firefox_labs_description = models.TextField(
"An optional string containing the Fluent ID "
"for the description of the opt-in",
"The description to display in Firefox Labs (Fluent ID)",
blank=True,
null=True,
)
firefox_labs_group = models.CharField(
"The group this should appear under in Firefox Labs",
blank=True,
null=True,
max_length=255,
choices=NimbusConstants.FirefoxLabsGroups.choices,
)

class Meta:
verbose_name = "Nimbus Experiment"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ def test_expected_schema_with_desktop(self):
locales=[locale_en_us],
_enrollment_end_date=datetime.date(2022, 1, 5),
is_firefox_labs_opt_in=False,
firefox_labs_title=None,
firefox_labs_description=None,
)
serializer = NimbusExperimentSerializer(experiment)
experiment_data = serializer.data.copy()
Expand Down Expand Up @@ -119,6 +117,7 @@ def test_expected_schema_with_desktop(self):
"isFirefoxLabsOptIn": False,
"firefoxLabsTitle": None,
"firefoxLabsDescription": None,
"firefoxLabsGroup": None,
},
)

Expand Down Expand Up @@ -183,6 +182,7 @@ def test_expected_schema_with_desktop_with_non_default_fxlabs_fields(self):
is_firefox_labs_opt_in=True,
firefox_labs_title="test-fx-labs-title",
firefox_labs_description="test-fx-labs-description",
firefox_labs_group="group",
)
serializer = NimbusExperimentSerializer(experiment)
experiment_data = serializer.data.copy()
Expand All @@ -196,6 +196,7 @@ def test_expected_schema_with_desktop_with_non_default_fxlabs_fields(self):
"isFirefoxLabsOptIn": True,
"firefoxLabsTitle": "test-fx-labs-title",
"firefoxLabsDescription": "test-fx-labs-description",
"firefoxLabsGroup": "group",
}
)

Expand Down Expand Up @@ -489,4 +490,5 @@ def _experiment_data_without_branches_and_featureIds(
"isFirefoxLabsOptIn": False,
"firefoxLabsTitle": None,
"firefoxLabsDescription": None,
"firefoxLabsGroup": None,
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ def test_expected_schema_with_desktop_with_non_default_fxlabs_fields(self):
is_firefox_labs_opt_in=True,
firefox_labs_title="test-fx-labs-title",
firefox_labs_description="test-fx-labs-description",
firefox_labs_group="group",
)
serializer = NimbusExperimentSerializer(experiment)
experiment_data = serializer.data.copy()
Expand All @@ -129,6 +130,7 @@ def test_expected_schema_with_desktop_with_non_default_fxlabs_fields(self):
"isFirefoxLabsOptIn": True,
"firefoxLabsTitle": "test-fx-labs-title",
"firefoxLabsDescription": "test-fx-labs-description",
"firefoxLabsGroup": "group",
}
)

Expand Down Expand Up @@ -419,4 +421,5 @@ def _experiment_data_without_branches_and_featureIds(
"isFirefoxLabsOptIn": False,
"firefoxLabsTitle": None,
"firefoxLabsDescription": None,
"firefoxLabsGroup": None,
}
15 changes: 13 additions & 2 deletions experimenter/experimenter/experiments/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,19 @@ class NimbusExperimentFactory(factory.django.DjangoModelFactory):
lambda o: random.choice(list(NimbusExperiment.QAStatus)).value
)
is_firefox_labs_opt_in = factory.LazyAttribute(lambda o: False)
firefox_labs_title = factory.LazyAttribute(lambda o: faker.catch_phrase())
firefox_labs_description = factory.LazyAttribute(lambda o: faker.catch_phrase())
firefox_labs_title = factory.LazyAttribute(
lambda o: faker.catch_phrase() if o.is_firefox_labs_opt_in else None
)
firefox_labs_description = factory.LazyAttribute(
lambda o: faker.catch_phrase() if o.is_firefox_labs_opt_in else None
)
firefox_labs_group = factory.LazyAttribute(
lambda o: (
random.choice(NimbusExperiment.FirefoxLabsGroups.choices)[0]
if o.is_firefox_labs_opt_in
else None
)
)

class Meta:
model = NimbusExperiment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def test_outputs_expected_schema_for_empty_experiment(self):
"firefox_min_version": NimbusExperiment.Version.NO_VERSION,
"firefox_labs_title": experiment.firefox_labs_title,
"firefox_labs_description": experiment.firefox_labs_description,
"firefox_labs_group": experiment.firefox_labs_group,
"hypothesis": NimbusExperiment.HYPOTHESIS_DEFAULT,
"is_archived": experiment.is_archived,
"is_client_schema_disabled": experiment.is_client_schema_disabled,
Expand Down Expand Up @@ -171,6 +172,7 @@ def test_outputs_expected_schema_for_complete_experiment(self):
"firefox_min_version": experiment.firefox_min_version,
"firefox_labs_title": experiment.firefox_labs_title,
"firefox_labs_description": experiment.firefox_labs_description,
"firefox_labs_group": experiment.firefox_labs_group,
"hypothesis": experiment.hypothesis,
"is_archived": experiment.is_archived,
"is_client_schema_disabled": experiment.is_client_schema_disabled,
Expand Down
10 changes: 5 additions & 5 deletions experimenter/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion experimenter/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ djangorestframework-dataclasses = "^1.3.0"
graphene-django = "^3.2.0"
pyright = "^1.1.291"
django-types = "^0.19.1"
mozilla-nimbus-schemas = "2024.11.5"
mozilla-nimbus-schemas = "2024.12.1"
mozilla-metric-config-parser = "^2024.11.1"
django-redis = "^5.4.0"
fontawesomefree = "6.6.0"
Expand Down

0 comments on commit 4a72b46

Please sign in to comment.