Skip to content

Commit

Permalink
Merge branch 'main' into chore/integrate-ldap
Browse files Browse the repository at this point in the history
# Conflicts:
#	.github/workflows/platform-docker-publish-all-features-image.yml
  • Loading branch information
matthewelwell committed Nov 24, 2023
2 parents 6bd7747 + 1592919 commit 3d6463d
Show file tree
Hide file tree
Showing 114 changed files with 5,555 additions and 2,797 deletions.
1 change: 1 addition & 0 deletions .github/workflows/api-deploy-staging-ecs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
- api/**
- .github/**
- infrastructure/aws/staging/**
workflow_dispatch:

jobs:
deploy-staging-ecs:
Expand Down
27 changes: 26 additions & 1 deletion .github/workflows/platform-docker-publish-all-features-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,22 @@ env:
FLAGSMITH_AUTH_CONTROLLER_REVISION: v0.0.1

jobs:
start-runner:
runs-on: ubuntu-latest
outputs:
runner-label: ${{ steps.start.outputs.runner-label }}
instance-id: ${{ steps.start.outputs.instance-id }}
steps:
- uses: Flagsmith/actions/ec2-runner/[email protected]
id: start
with:
github-access-token: ${{ secrets.GH_RUNNER_TOKEN }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_EC2_RUNNER }}

build-dockerhub:
runs-on: self-hosted
name: Platform Publish Docker Image
needs: [start-runner]
runs-on: ${{ needs.start-runner.outputs.runner-label }}

steps:
- name: Cloning repo
Expand Down Expand Up @@ -108,3 +121,15 @@ jobs:
build-args: |
SAML_INSTALLED=1
POETRY_OPTS=--with saml,auth-controller,ldap
stop-runner:
needs: [start-runner, build-dockerhub]
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- uses: Flagsmith/actions/ec2-runner/[email protected]
with:
github-access-token: ${{ secrets.GH_RUNNER_TOKEN }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_EC2_RUNNER }}
runner-label: ${{ needs.start-runner.outputs.runner-label }}
instance-id: ${{ needs.start-runner.outputs.instance-id }}
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "2.82.0"
".": "2.83.0"
}
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## [2.83.0](https://github.com/Flagsmith/flagsmith/compare/v2.82.0...v2.83.0) (2023-11-21)


### Features

* introduce dunning billing status ([#2976](https://github.com/Flagsmith/flagsmith/issues/2976)) ([975c7b0](https://github.com/Flagsmith/flagsmith/commit/975c7b0d6438cd973ccd62b590436e4c2568b9d4))


### Bug Fixes

* **api:** validate before creating projects based on current subscription ([#2869](https://github.com/Flagsmith/flagsmith/issues/2869)) ([f32159e](https://github.com/Flagsmith/flagsmith/commit/f32159e3fd821c6dc7bfbd50a0c3d22374f1b558))
* **edge-identity-view:** reduce max page size to 100 ([#2937](https://github.com/Flagsmith/flagsmith/issues/2937)) ([6c4807f](https://github.com/Flagsmith/flagsmith/commit/6c4807f0b2dd2ee770d2d712b2955a9fd71c37a0))
* Move and merge features tests into proper location ([#3002](https://github.com/Flagsmith/flagsmith/issues/3002)) ([5f3482c](https://github.com/Flagsmith/flagsmith/commit/5f3482c8c376c6dd283ab4aff36dedb67825facc))

## [2.82.0](https://github.com/Flagsmith/flagsmith/compare/v2.81.1...v2.82.0) (2023-11-20)


Expand Down
8 changes: 6 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ COPY frontend/package.json frontend/package-lock.json frontend/.npmrc ./frontend
COPY frontend/bin/ ./frontend/bin/
COPY frontend/env/ ./frontend/env/

RUN cd frontend && npm ci --quiet --production
# since ENV is only used for the purposes of copying the correct
# project_${env}.js file to common/project.js, this is a build arg
# which subsequently gets set as an environment variable. This is
# done to avoid confusion since it is not a required run time var.
ARG ENV=selfhosted
RUN cd frontend && ENV=${ENV} npm ci --quiet --production

# Copy the entire project - Webpack puts compiled assets into the Django folder
COPY . .
ENV ENV=prod
ENV STATIC_ASSET_CDN_URL=/static/
RUN cd frontend && npm run bundledjango

Expand Down
1 change: 1 addition & 0 deletions api/api/urls/v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
SDKEnvironmentAPIView.as_view(),
name="environment-document",
),
url("", include("features.versioning.urls", namespace="versioning")),
# API documentation
url(
r"^swagger(?P<format>\.json|\.yaml)$",
Expand Down
3 changes: 3 additions & 0 deletions api/app/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ def get_paginated_response(self, paginator, response_schema):


class EdgeIdentityPagination(CustomPagination):
max_page_size = 100
page_size = 100

def paginate_queryset(self, dynamo_queryset, request, view=None):
last_evaluated_key = dynamo_queryset.get("LastEvaluatedKey")
if last_evaluated_key:
Expand Down
1 change: 1 addition & 0 deletions api/app/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
"environments.identities.traits",
"features",
"features.multivariate",
"features.versioning",
"features.workflows.core",
"segments",
"app",
Expand Down
3 changes: 3 additions & 0 deletions api/audit/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ def create_audit_log_from_historical_record(
user_model = get_user_model()

instance = history_instance.instance
if instance.get_skip_create_audit_log():
return

history_user = user_model.objects.filter(id=history_user_id).first()

override_author = instance.get_audit_log_author(history_instance)
Expand Down
10 changes: 9 additions & 1 deletion api/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest
from django.contrib.contenttypes.models import ContentType
from django.core.cache import cache
from flag_engine.segments.constants import EQUAL
from rest_framework.authtoken.models import Token
from rest_framework.test import APIClient

Expand All @@ -23,6 +24,7 @@
from features.models import Feature, FeatureSegment, FeatureState
from features.multivariate.models import MultivariateFeatureOption
from features.value_types import STRING
from features.versioning.tasks import enable_v2_versioning
from features.workflows.core.models import ChangeRequest
from metadata.models import (
Metadata,
Expand All @@ -45,7 +47,7 @@
)
from projects.permissions import VIEW_PROJECT
from projects.tags.models import Tag
from segments.models import EQUAL, Condition, Segment, SegmentRule
from segments.models import Condition, Segment, SegmentRule
from task_processor.task_run_method import TaskRunMethod
from users.models import FFAdminUser, UserPermissionGroup

Expand Down Expand Up @@ -224,6 +226,12 @@ def _with_project_permissions(
return _with_project_permissions


@pytest.fixture()
def environment_v2_versioning(environment):
enable_v2_versioning(environment.id)
return environment


@pytest.fixture()
def identity(environment):
return Identity.objects.create(identifier="test_identity", environment=environment)
Expand Down
3 changes: 3 additions & 0 deletions api/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ class _AbstractBaseAuditableModel(models.Model):
class Meta:
abstract = True

def get_skip_create_audit_log(self) -> bool:
return False

def get_create_log_message(self, history_instance) -> typing.Optional[str]:
"""Override if audit log records should be written when model is created"""
return None
Expand Down
11 changes: 10 additions & 1 deletion api/e2etests/e2e_seed_data.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from django.conf import settings
from flag_engine.identities.models import IdentityModel as EngineIdentity

from edge_api.identities.models import EdgeIdentity
from environments.identities.models import Identity
from environments.models import Environment
from organisations.models import Organisation, OrganisationRole, Subscription
Expand Down Expand Up @@ -72,7 +74,14 @@ def seed_data() -> None:
]

for identity_info in identities_test_data:
Identity.objects.create(**identity_info)
if settings.IDENTITIES_TABLE_NAME_DYNAMO:
engine_identity = EngineIdentity(
identifier=identity_info["identifier"],
environment_api_key=identity_info["environment"].api_key,
)
EdgeIdentity(engine_identity).save()
else:
Identity.objects.create(**identity_info)

# Upgrade organisation seats
Subscription.objects.filter(organisation__in=org_admin.organisations.all()).update(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
from core.constants import INTEGER
from django.core.exceptions import ObjectDoesNotExist
from flag_engine.identities.builders import build_identity_model
from flag_engine.segments.constants import IN
from rest_framework.exceptions import NotFound

from environments.dynamodb import DynamoIdentityWrapper
from environments.identities.models import Identity
from environments.identities.traits.models import Trait
from segments.models import IN, Condition, Segment, SegmentRule
from segments.models import Condition, Segment, SegmentRule
from util.mappers import (
map_environment_to_environment_document,
map_identity_to_identity_document,
Expand Down
26 changes: 15 additions & 11 deletions api/environments/identities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,25 @@ def get_all_feature_states(
feature_segment__environment=self.environment,
)
environment_default_query = Q(identity=None, feature_segment=None)
only_live_versions_query = Q(
live_from__lte=timezone.now(), version__isnull=False
)

# define the full query
full_query = (
only_live_versions_query
& belongs_to_environment_query
& (
overridden_for_identity_query
| overridden_for_segment_query
| environment_default_query
)
full_query = belongs_to_environment_query & (
overridden_for_identity_query
| overridden_for_segment_query
| environment_default_query
)

if self.environment.use_v2_feature_versioning:
full_query &= Q(
Q(identity=self) # identity overrides are not versioned
| Q(
environment_feature_version__live_from__isnull=False,
environment_feature_version__live_from__lte=timezone.now(),
),
)
else:
full_query &= Q(live_from__lte=timezone.now(), version__isnull=False)

if additional_filters:
full_query &= additional_filters

Expand Down
18 changes: 8 additions & 10 deletions api/environments/identities/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import pytest
from core.constants import FLOAT
from django.utils import timezone
from flag_engine.segments.constants import (
EQUAL,
GREATER_THAN,
GREATER_THAN_INCLUSIVE,
LESS_THAN_INCLUSIVE,
NOT_EQUAL,
)
from rest_framework.test import APITestCase

from environments.identities.models import Identity
Expand All @@ -15,16 +22,7 @@
from features.value_types import BOOLEAN, INTEGER, STRING
from organisations.models import Organisation
from projects.models import Project
from segments.models import (
EQUAL,
GREATER_THAN,
GREATER_THAN_INCLUSIVE,
LESS_THAN_INCLUSIVE,
NOT_EQUAL,
Condition,
Segment,
SegmentRule,
)
from segments.models import Condition, Segment, SegmentRule

from .helpers import (
create_trait_for_identity,
Expand Down
18 changes: 9 additions & 9 deletions api/environments/identities/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
from unittest.case import TestCase

import pytest
from core.constants import FLAGSMITH_UPDATED_AT_HEADER
from core.constants import FLAGSMITH_UPDATED_AT_HEADER, STRING
from django.test import override_settings
from django.urls import reverse
from flag_engine.segments.constants import PERCENTAGE_SPLIT
from rest_framework import status
from rest_framework.test import APIClient, APITestCase

Expand All @@ -20,7 +21,6 @@
from integrations.amplitude.models import AmplitudeConfiguration
from organisations.models import Organisation, OrganisationRole
from projects.models import Project
from segments import models
from segments.models import Condition, Segment, SegmentRule
from util.tests import Helper

Expand Down Expand Up @@ -370,7 +370,7 @@ def test_identities_endpoint_returns_traits(self, mock_amplitude_wrapper):
trait = Trait.objects.create(
identity=self.identity,
trait_key="trait_key",
value_type="STRING",
value_type=STRING,
string_value="trait_value",
)

Expand Down Expand Up @@ -422,7 +422,7 @@ def test_identities_endpoint_returns_value_for_segment_if_identity_in_segment(
Trait.objects.create(
identity=self.identity,
trait_key=trait_key,
value_type="STRING",
value_type=STRING,
string_value=trait_value,
)
segment = Segment.objects.create(name="Test Segment", project=self.project)
Expand Down Expand Up @@ -476,7 +476,7 @@ def test_identities_endpoint_returns_value_for_segment_if_identity_in_segment_an
Trait.objects.create(
identity=self.identity,
trait_key=trait_key,
value_type="STRING",
value_type=STRING,
string_value=trait_value,
)
segment = Segment.objects.create(name="Test Segment", project=self.project)
Expand Down Expand Up @@ -528,7 +528,7 @@ def test_identities_endpoint_returns_value_for_segment_if_rule_type_percentage_s
[segment.id, self.identity.id]
)
Condition.objects.create(
operator=models.PERCENTAGE_SPLIT,
operator=PERCENTAGE_SPLIT,
value=(identity_percentage_value + (1 - identity_percentage_value) / 2)
* 100.0,
rule=segment_rule,
Expand Down Expand Up @@ -575,7 +575,7 @@ def test_identities_endpoint_returns_default_value_if_rule_type_percentage_split
[segment.id, self.identity.id]
)
Condition.objects.create(
operator=models.PERCENTAGE_SPLIT,
operator=PERCENTAGE_SPLIT,
value=identity_percentage_value / 2,
rule=segment_rule,
)
Expand Down Expand Up @@ -628,13 +628,13 @@ def test_post_identify_deletes_a_trait_if_trait_value_is_none(self):
trait_1 = Trait.objects.create(
identity=self.identity,
trait_key="trait_key_1",
value_type="STRING",
value_type=STRING,
string_value="trait_value",
)
trait_2 = Trait.objects.create(
identity=self.identity,
trait_key="trait_key_2",
value_type="STRING",
value_type=STRING,
string_value="trait_value",
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.23 on 2023-11-21 10:23

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('environments', '0032_rename_use_mv_v2_evaluation_to_use_in_percentage_split_evaluation'),
]

operations = [
migrations.AddField(
model_name='environment',
name='use_v2_feature_versioning',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='historicalenvironment',
name='use_v2_feature_versioning',
field=models.BooleanField(default=False),
),
]
Loading

0 comments on commit 3d6463d

Please sign in to comment.