Skip to content

Commit

Permalink
Merge branch 'main' into 11757/draft_preview_flow
Browse files Browse the repository at this point in the history
  • Loading branch information
yashikakhurana authored Dec 24, 2024
2 parents c98ad23 + 6bb383c commit 7cb83f2
Show file tree
Hide file tree
Showing 69 changed files with 4,878 additions and 174 deletions.
22 changes: 20 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,22 @@ jobs:
poetry add pydantic==2.10.3
poetry install
poetry run pytest -k test_ios_integration.py --feature ios_enrollment
- run:
name: Collect XCTest Results
command: |
zip -r results.zip /Users/distiller/Library/Developer/Xcode/DerivedData/**/Logs/Test/*.xcresult
when: always
- run:
name: Collect xcodebuild log
command: |
cp /private/var/folders/**/**/T/pytest-of-distiller/pytest-*/**/xcodebuild.log ./
when: always
- store_artifacts:
path: ~/project/firefox-ios/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests/results/index.html
- store_artifacts:
path: ~/project/xcodebuild.log
- store_artifacts:
path: ~/project/results.zip

integration_nimbus_sdk_targeting:
machine:
Expand Down Expand Up @@ -423,7 +437,11 @@ jobs:
command: |
cp .env.integration-tests .env
export CIRRUS=1
make refresh SKIP_DUMMY=1 PYTEST_SENTRY_DSN=$PYTEST_SENTRY_DSN CIRCLECI=$CIRCLECI up_prod_detached integration_test_nimbus_desktop PYTEST_ARGS="-k test_create_mobile_experiment_for_integration_test"
make refresh SKP_DUMMY=1 PYTEST_SENTRY_DSN=$PYTEST_SENTRY_DSN CIRCLECI=$CIRCLECI up_prod_detached integration_test_nimbus_desktop PYTEST_ARGS="-k test_create_mobile_experiment_for_integration_test"
- store_artifacts:
path: experimenter/tests/integration/ios_recipe.json
- store_artifacts:
path: experimenter/tests/integration/fenix_recipe.json
- persist_to_workspace:
root: experimenter
paths:
Expand Down Expand Up @@ -648,7 +666,7 @@ jobs:
steps:
- checkout
- check_file_paths:
paths: "experimenter/tests/firefox-fenix-build.env"
paths: "experimenter/experimenter/targeting|experimenter/experimenter/experiments|experimenter/tests/firefox_fenix_beta_build.env|experimenter/tests/firefox_fenix_release_build.env"
- docker_login:
username: $DOCKER_USER
password: $DOCKER_PASS
Expand Down
2 changes: 1 addition & 1 deletion application-services/application-services.env
Original file line number Diff line number Diff line change
@@ -1 +1 @@
APPLICATION_SERVICES_BUILD_ID=135.20241212150752
APPLICATION_SERVICES_BUILD_ID=135.20241220191521
14 changes: 7 additions & 7 deletions cirrus/server/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 cirrus/server/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ authors = [""]
python = "^3.10.10"
ruff = "^0.8.0"
fastapi = "^0.115.0"
uvicorn = "^0.32.0"
uvicorn = "^0.34.0"
pytest = "^7.2.2"
httpx = "^0.28.0"
pytest-cov = "^4.0.0"
Expand Down
6 changes: 3 additions & 3 deletions demo-app/frontend/package-lock.json

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

14 changes: 14 additions & 0 deletions docs/experimenter/openapi-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4067,6 +4067,20 @@
},
"hypothesis": {
"type": "string"
},
"takeaways_metric_gain": {
"type": "boolean"
},
"takeaways_gain_amount": {
"type": "string",
"nullable": true
},
"takeaways_qbr_learning": {
"type": "boolean"
},
"takeaways_summary": {
"type": "string",
"nullable": true
}
},
"required": [
Expand Down
14 changes: 14 additions & 0 deletions docs/experimenter/swagger-ui.html
Original file line number Diff line number Diff line change
Expand Up @@ -4079,6 +4079,20 @@
},
"hypothesis": {
"type": "string"
},
"takeaways_metric_gain": {
"type": "boolean"
},
"takeaways_gain_amount": {
"type": "string",
"nullable": true
},
"takeaways_qbr_learning": {
"type": "boolean"
},
"takeaways_summary": {
"type": "string",
"nullable": true
}
},
"required": [
Expand Down
16 changes: 13 additions & 3 deletions experimenter/experimenter/experiments/api/v5/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,10 @@ class Meta:
"experiment_summary",
"rollout",
"hypothesis",
"takeaways_metric_gain",
"takeaways_gain_amount",
"takeaways_qbr_learning",
"takeaways_summary",
]

def get_feature_configs(self, obj):
Expand Down Expand Up @@ -1464,12 +1468,18 @@ def _validate_feature_value(
unsupported_version_strs = [
str(v) for v in schemas_in_range.unsupported_versions
]
min_unsupported_version = min(unsupported_version_strs)
max_unsupported_version = max(unsupported_version_strs)
if len(unsupported_version_strs) == 1:
unsupported_versions = unsupported_version_strs[0]
else:
min_unsupported_version = min(unsupported_version_strs)
max_unsupported_version = max(unsupported_version_strs)
unsupported_versions = (
f"{min_unsupported_version}-{max_unsupported_version}"
)
result.append(
NimbusConstants.ERROR_FEATURE_CONFIG_UNSUPPORTED_IN_VERSIONS.format(
feature_config=feature_config.name,
versions=f"{min_unsupported_version}-{max_unsupported_version}",
versions=unsupported_versions,
),
suppress_errors,
)
Expand Down
84 changes: 62 additions & 22 deletions experimenter/experimenter/experiments/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,9 @@ def get_update_overview_url(self):
def get_update_metrics_url(self):
return reverse("nimbus-new-update-metrics", kwargs={"slug": self.slug})

def get_update_audience_url(self):
return reverse("nimbus-new-update-audience", kwargs={"slug": self.slug})

@property
def experiment_url(self):
return urljoin(f"https://{settings.HOSTNAME}", self.get_absolute_url())
Expand Down Expand Up @@ -541,8 +544,7 @@ def targeting(self):
if self.targeting_config and self.targeting_config.targeting:
sticky_expressions.append(self.targeting_config.targeting)

is_desktop = self.application == self.Application.DESKTOP
if is_desktop and self.channel:
if self.is_desktop and self.channel:
expressions.append(f'browserSettings.update.channel == "{self.channel}"')

sticky_expressions.extend(self._get_targeting_min_version())
Expand All @@ -567,7 +569,7 @@ def targeting(self):
sticky_expressions.append(f"region in {countries}")

enrollments_map_key = "enrollments_map"
if is_desktop:
if self.is_desktop:
enrollments_map_key = "enrollmentsMap"

if excluded_experiments := NimbusExperimentBranchThroughExcluded.objects.filter(
Expand Down Expand Up @@ -601,7 +603,7 @@ def targeting(self):
if self.is_sticky and sticky_expressions:
expressions.append(
make_sticky_targeting_expression(
is_desktop, self.is_rollout, sticky_expressions
self.is_desktop, self.is_rollout, sticky_expressions
)
)
else:
Expand All @@ -610,7 +612,7 @@ def targeting(self):
if prefs := self._get_targeting_pref_conflicts():
expressions.append(
make_sticky_targeting_expression(
is_desktop,
self.is_desktop,
self.is_rollout,
(f"!('{pref}'|preferenceIsUserSet)" for pref in sorted(prefs)),
)
Expand Down Expand Up @@ -643,6 +645,10 @@ def treatment_branches(self):
branches = branches.exclude(id=self.reference_branch.id)
return list(branches)

@property
def is_desktop(self):
return self.application == self.Application.DESKTOP

@property
def is_draft(self):
return (
Expand Down Expand Up @@ -978,6 +984,21 @@ def rollout_monitoring_dashboard_url(self):
slug=self.slug.replace("-", "_")
)

def format_branch_choice(self, branch_slug):
branch_name = "All branches"
if branch_slug is not None:
branch_name = branch_slug.capitalize()
return (
f"{self.slug}:{branch_slug}",
f"{self.name} ({branch_name})",
)

def branch_choices(self):
choices = [self.format_branch_choice(None)]
for branch in self.branches.all():
choices.append(self.format_branch_choice(branch.slug))
return choices

@property
def required_experiments_branches(self):
return NimbusExperimentBranchThroughRequired.objects.filter(
Expand Down Expand Up @@ -1374,7 +1395,7 @@ def clone(self, name, user, rollout_branch_slug=None, changed_on=None):

cloned.feature_configs.add(*self.feature_configs.all())
cloned.countries.add(*self.countries.all())
if self.application == self.Application.DESKTOP:
if self.is_desktop:
cloned.locales.add(*self.locales.all())
cloned.languages.add(*self.languages.all())
cloned.projects.add(*self.projects.all())
Expand Down Expand Up @@ -1820,7 +1841,7 @@ def get_versioned_schema_range(
min_supported_version = NimbusExperiment.Version.parse(min_supported_version)

if min_supported_version > min_version:
if max_version is not None and min_supported_version >= max_version:
if max_version is not None and min_supported_version > max_version:
# We will not have any NimbusVerionedSchemas in this
# version range. The best we can do is use the
# unversioned schema.
Expand Down Expand Up @@ -1905,6 +1926,23 @@ def between_versions_q(
*,
prefix: Optional[str] = None,
) -> Q:
"""Return a query object that can be used to select all versions between lower and
upper bounds (inclusive).
Args:
min_version:
The lower bound (inclusive).
max_version:
The upper bound (inclusive).
prefix:
An optional prefix to prepend to the field names. This allows the Q object
to be used by related models.
Returns:
The query object.
"""
if prefix is not None:

def prefixed(**kwargs: dict[str, Any]):
Expand All @@ -1916,27 +1954,29 @@ def prefixed(**kwargs: dict[str, Any]):
return kwargs

# (a, b, c) >= (d, e, f)
# := (a > b) | (a = b & d > e) | (a = b & d = e & c >= f)
# == (a > b) | (a = b & (d > e | (d = e & c >= f)))
# := (a > d) | (a == d & b > e) | (a == d & b == e & c >= f)
# == (a > d) | (a == d & (b > e | (b == e & c >= f)

# packaging.version.Version uses major.minor.micro, but
# NimbusFeatureVersion uses major.minor.patch (semver).
q = Q(**prefixed(major__gt=min_version.major)) | Q(
**prefixed(major=min_version.major)
) & (
Q(**prefixed(minor__gt=min_version.minor))
| Q(**prefixed(minor=min_version.minor, patch__gte=min_version.micro))
q = Q(**prefixed(major__gt=min_version.major)) | (
Q(**prefixed(major=min_version.major))
& (
Q(**prefixed(minor__gt=min_version.minor))
| Q(**prefixed(minor=min_version.minor, patch__gte=min_version.micro))
)
)

if max_version is not None:
# (a, b, c) < (d, e, f)
# := (a < d) | (a == d & b < e) | (a == d & b == e & c < f)
# == (a < d) | (a == d & (b < e | (b == e & c < f)))
q &= Q(**prefixed(major__lt=max_version.major)) | Q(
**prefixed(major=max_version.major)
) & (
Q(**prefixed(minor__lt=max_version.minor))
| Q(**prefixed(minor=max_version.minor, patch__lt=max_version.micro))
# (a, b, c) <= (d, e, f)
# := (a < d) | (a == d & b < e) | (a = d & b == e & c <= f)
# == (a < d) | (a == d & (b < e | (b == e & c <= f)))
q &= Q(**prefixed(major__lt=max_version.major)) | (
Q(**prefixed(major=max_version.major))
& (
Q(**prefixed(minor__lt=max_version.minor))
| Q(**prefixed(minor=max_version.minor, patch__lte=max_version.micro))
)
)

return q
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ def test_serializer_outputs_expected_schema(self):
"experiment_summary": experiment.experiment_url,
"rollout": experiment.is_rollout,
"hypothesis": experiment.hypothesis,
"takeaways_metric_gain": experiment.takeaways_metric_gain,
"takeaways_gain_amount": experiment.takeaways_gain_amount,
"takeaways_qbr_learning": experiment.takeaways_qbr_learning,
"takeaways_summary": experiment.takeaways_summary,
},
)

Expand Down Expand Up @@ -69,5 +73,9 @@ def test_serializer_outputs_expected_schema_with_results_link(self):
"experiment_summary": experiment.experiment_url,
"rollout": experiment.is_rollout,
"hypothesis": experiment.hypothesis,
"takeaways_metric_gain": experiment.takeaways_metric_gain,
"takeaways_gain_amount": experiment.takeaways_gain_amount,
"takeaways_qbr_learning": experiment.takeaways_qbr_learning,
"takeaways_summary": experiment.takeaways_summary,
},
)
Loading

0 comments on commit 7cb83f2

Please sign in to comment.