Skip to content

Commit

Permalink
Merge branch 'main' into fix/invalid-tag-colour
Browse files Browse the repository at this point in the history
  • Loading branch information
rolodato authored Nov 8, 2024
2 parents 7a62be0 + 0f9b24b commit 2388983
Show file tree
Hide file tree
Showing 60 changed files with 1,234 additions and 734 deletions.
77 changes: 0 additions & 77 deletions .github/actions/trivy-scan-image/action.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/.reusable-docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ jobs:

- name: Scan ${{ steps.image-tag.outputs.image-tag }} image
id: trivy
uses: ./.github/actions/trivy-scan-image
uses: Flagsmith/actions/trivy-scan-image@v0.3.0
if: inputs.scan
with:
image-tag: ${{ steps.image-tag.outputs.image-tag }}
Expand Down
13 changes: 13 additions & 0 deletions .github/workflows/docs-cron-vercel-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Docs - update SDK versions

on:
workflow_dispatch:
schedule:
# At 12:00 on Tuesday https://crontab.guru/#0_12_*_*_2
- cron: '0 12 * * 2'
jobs:
vercel-deploy:
runs-on: ubuntu-latest
steps:
- name: Run Vercel deploy hook
run: curl -X POST "${{ secrets.VERCEL_SDK_VERSIONS_DEPLOY_HOOKS_URL }}"
2 changes: 1 addition & 1 deletion .github/workflows/platform-docker-trivy-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ jobs:

- name: Scan ${{ matrix.image-name }}:main image
id: trivy
uses: ./.github/actions/trivy-scan-image
uses: Flagsmith/actions/trivy-scan-image@v0.3.0
with:
image-tag: ${{ env.REGISTRY_URL }}/flagsmith/${{ matrix.image-name }}:main
category: ${{ matrix.image-name }}
Expand Down
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.150.0"
".": "2.152.0"
}
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
# Changelog

## [2.152.0](https://github.com/Flagsmith/flagsmith/compare/v2.151.0...v2.152.0) (2024-11-06)


### Features

* add environment processing UI ([#4812](https://github.com/Flagsmith/flagsmith/issues/4812)) ([9db91ae](https://github.com/Flagsmith/flagsmith/commit/9db91ae980ae3bf9fe445f68c8aaf438c68a47b9))
* Manage user's groups ([#4312](https://github.com/Flagsmith/flagsmith/issues/4312)) ([89b153c](https://github.com/Flagsmith/flagsmith/commit/89b153cb3694bf893a24e6d3e047992a6d456eae))
* restrict versioning by days ([#4547](https://github.com/Flagsmith/flagsmith/issues/4547)) ([dad864a](https://github.com/Flagsmith/flagsmith/commit/dad864aa2de0ed6ab704c8b83796ee0a7a8a780a))


### Bug Fixes

* feature stale message not showing ([#4801](https://github.com/Flagsmith/flagsmith/issues/4801)) ([70a7d81](https://github.com/Flagsmith/flagsmith/commit/70a7d81355f8787a68de52b53caf476a5c984103))
* Fix organisation meta ([#4802](https://github.com/Flagsmith/flagsmith/issues/4802)) ([c2fdc5b](https://github.com/Flagsmith/flagsmith/commit/c2fdc5b3e3485a22e8599e904800ca8c238a11b8))
* permanent tag icons ([#4804](https://github.com/Flagsmith/flagsmith/issues/4804)) ([57ad28c](https://github.com/Flagsmith/flagsmith/commit/57ad28cf033b2ec9554ad60bcade4bd40cedb117))
* users with VIEW_ENVIRONMENT should be able to retrieve environment ([#4814](https://github.com/Flagsmith/flagsmith/issues/4814)) ([e6f1bac](https://github.com/Flagsmith/flagsmith/commit/e6f1bac2f264ebdc1d012ad61539efb76ac43fd7))

## [2.151.0](https://github.com/Flagsmith/flagsmith/compare/v2.150.0...v2.151.0) (2024-11-04)


### Features

* async the logic for cloning feature states into a cloned environment ([#4005](https://github.com/Flagsmith/flagsmith/issues/4005)) ([02f5f71](https://github.com/Flagsmith/flagsmith/commit/02f5f71f82bae1ec3536cb522fc0b684a2c27605))
* **ci:** add command to rollback migrations ([#4768](https://github.com/Flagsmith/flagsmith/issues/4768)) ([483cc87](https://github.com/Flagsmith/flagsmith/commit/483cc87fde03d2da465f9ec799bdbc746533f8d2))
* **export:** Add support for edge identities data ([#4654](https://github.com/Flagsmith/flagsmith/issues/4654)) ([f72c764](https://github.com/Flagsmith/flagsmith/commit/f72c764e59d44f3c50bafd0cd2aef2dcf51af07b))
* **permissions:** update endpoints to expose tag-supported perms ([#4788](https://github.com/Flagsmith/flagsmith/issues/4788)) ([43e68c1](https://github.com/Flagsmith/flagsmith/commit/43e68c1b67eeb5587440cbe5017035b60d897212))


### Bug Fixes

* Extend user first name length to 150 characters ([#4797](https://github.com/Flagsmith/flagsmith/issues/4797)) ([364c565](https://github.com/Flagsmith/flagsmith/commit/364c565fed5ebdb0da86927a25d56631502b3792))
* hide view features from associated segment overrides ([#4786](https://github.com/Flagsmith/flagsmith/issues/4786)) ([49ff569](https://github.com/Flagsmith/flagsmith/commit/49ff569cabac19f70c0688f1fe58c3511ce8801b))
* Set tag to get or create ([#4790](https://github.com/Flagsmith/flagsmith/issues/4790)) ([fedd296](https://github.com/Flagsmith/flagsmith/commit/fedd296a5cc8eb07aa1db4a2cbb5eca8f124c098))

## [2.150.0](https://github.com/Flagsmith/flagsmith/compare/v2.149.0...v2.150.0) (2024-10-30)


Expand Down
2 changes: 1 addition & 1 deletion api/environments/permissions/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def has_permission(self, request, view):
def has_object_permission(self, request, view, obj):
if view.action == "clone":
return request.user.has_project_permission(CREATE_ENVIRONMENT, obj.project)
elif view.action == "get_document":
elif view.action in ("get_document", "retrieve", "trait_keys"):
return request.user.has_environment_permission(VIEW_ENVIRONMENT, obj)

return request.user.is_environment_admin(obj) or view.action in [
Expand Down
1 change: 1 addition & 0 deletions api/environments/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ class CloneEnvironmentSerializer(EnvironmentSerializerLight):
help_text="If True, the environment will be created immediately, but the feature states "
"will be created asynchronously. Environment will have `is_creating: true` until "
"this process is completed.",
write_only=True,
)

class Meta:
Expand Down
7 changes: 5 additions & 2 deletions api/environments/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from rest_framework.request import Request
from rest_framework.response import Response

from environments.permissions.constants import TAG_SUPPORTED_PERMISSIONS
from environments.permissions.permissions import (
EnvironmentAdminPermission,
EnvironmentPermissions,
Expand Down Expand Up @@ -189,12 +190,14 @@ def delete_traits(self, request, *args, **kwargs):
status=status.HTTP_400_BAD_REQUEST,
)

@swagger_auto_schema(responses={200: PermissionModelSerializer})
@swagger_auto_schema(responses={200: PermissionModelSerializer(many=True)})
@action(detail=False, methods=["GET"])
def permissions(self, *args, **kwargs):
return Response(
PermissionModelSerializer(
instance=EnvironmentPermissionModel.objects.all(), many=True
instance=EnvironmentPermissionModel.objects.all(),
many=True,
context={"tag_supported_permissions": TAG_SUPPORTED_PERMISSIONS},
).data
)

Expand Down
2 changes: 1 addition & 1 deletion api/features/feature_external_resources/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def execute_after_save_actions(self):
repository_name=repo,
)
if github_repo.tagging_enabled:
github_tag = Tag.objects.get(
github_tag, _ = Tag.objects.get_or_create(
label=tag_by_type_and_state[self.type][state],
project=self.feature.project,
is_system_tag=True,
Expand Down
7 changes: 6 additions & 1 deletion api/permissions/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@


class PermissionModelSerializer(serializers.ModelSerializer):
supports_tag = serializers.SerializerMethodField()

class Meta:
model = PermissionModel
fields = ("key", "description")
fields = ("key", "description", "supports_tag")

def get_supports_tag(self, obj: PermissionModel) -> bool:
return obj.key in self.context.get("tag_supported_permissions", [])


class CreateUpdateUserPermissionSerializerABC(serializers.ModelSerializer):
Expand Down
7 changes: 5 additions & 2 deletions api/projects/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
UserProjectPermission,
)
from projects.permissions import (
TAG_SUPPORTED_PERMISSIONS,
VIEW_PROJECT,
IsProjectAdmin,
ProjectPermissions,
Expand Down Expand Up @@ -126,13 +127,15 @@ def environments(self, request, pk):
return Response(EnvironmentSerializerLight(environments, many=True).data)

@swagger_auto_schema(
responses={200: PermissionModelSerializer}, request_body=no_body
responses={200: PermissionModelSerializer(many=True)}, request_body=no_body
)
@action(detail=False, methods=["GET"])
def permissions(self, *args, **kwargs):
return Response(
PermissionModelSerializer(
instance=ProjectPermissionModel.objects.all(), many=True
instance=ProjectPermissionModel.objects.all(),
many=True,
context={"tag_supported_permissions": TAG_SUPPORTED_PERMISSIONS},
).data
)

Expand Down
13 changes: 10 additions & 3 deletions api/tests/integration/environments/test_clone_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
[lazy_fixture("admin_master_api_key_client"), lazy_fixture("admin_client")],
)
def test_clone_environment_clones_feature_states_with_value(
client, project, environment, environment_api_key, feature
client: APIClient,
project: int,
environment: int,
environment_api_key: str,
feature: int,
):
# Firstly, let's update feature state value of the source environment
# fetch the feature state id to update
Expand All @@ -43,11 +47,14 @@ def test_clone_environment_clones_feature_states_with_value(
# Now, clone the environment
env_name = "Cloned env"
url = reverse("api-v1:environments:environment-clone", args=[environment_api_key])
res = client.post(url, {"name": env_name})
res = client.post(url, {"name": env_name, "clone_feature_states_async": False})

# Then, check that the clone was successful
assert res.status_code == status.HTTP_200_OK

# And check that the write only field wasn't returned
assert "clone_feature_states_async" not in res.json()

# Now, fetch the feature states of the source environment
source_env_feature_states = get_env_feature_states_list_with_api(
client, {"environment": environment}
Expand All @@ -58,7 +65,7 @@ def test_clone_environment_clones_feature_states_with_value(
client, {"environment": res.json()["id"]}
)

# Finaly, compare the responses
# Finally, compare the responses
assert source_env_feature_states["count"] == 1
assert (
source_env_feature_states["results"][0]["id"]
Expand Down
50 changes: 49 additions & 1 deletion api/tests/unit/environments/test_unit_environments_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
from environments.identities.models import Identity
from environments.identities.traits.models import Trait
from environments.models import Environment, EnvironmentAPIKey, Webhook
from environments.permissions.constants import VIEW_ENVIRONMENT
from environments.permissions.constants import (
TAG_SUPPORTED_PERMISSIONS,
VIEW_ENVIRONMENT,
)
from environments.permissions.models import UserEnvironmentPermission
from features.models import Feature, FeatureState
from features.versioning.models import EnvironmentFeatureVersion
Expand Down Expand Up @@ -73,6 +76,23 @@ def test_retrieve_environment(
)


def test_user_with_view_environment_permission_can_retrieve_environment(
staff_client: APIClient,
environment: Environment,
with_environment_permissions: WithEnvironmentPermissionsCallable,
) -> None:
# Given
url = reverse("api-v1:environments:environment-detail", args=[environment.api_key])

with_environment_permissions([VIEW_ENVIRONMENT])

# When
response = staff_client.get(url)

# Then
assert response.status_code == status.HTTP_200_OK


def test_can_clone_environment_with_create_environment_permission(
test_user,
test_user_client,
Expand Down Expand Up @@ -917,6 +937,27 @@ def test_get_all_trait_keys_for_environment_only_returns_distinct_keys(
assert len(res.json().get("keys")) == 2


def test_user_with_view_environment_can_get_trait_keys(
identity: Identity,
staff_client: APIClient,
trait: Trait,
environment: Environment,
with_environment_permissions: WithEnvironmentPermissionsCallable,
) -> None:
# Given
url = reverse(
"api-v1:environments:environment-trait-keys", args=[environment.api_key]
)

with_environment_permissions([VIEW_ENVIRONMENT])

# When
res = staff_client.get(url)

# Then
assert res.status_code == status.HTTP_200_OK


def test_delete_trait_keys_deletes_traits_matching_provided_key_only(
identity: Identity,
admin_client_new: APIClient,
Expand Down Expand Up @@ -962,6 +1003,13 @@ def test_user_can_list_environment_permission(
assert response.status_code == status.HTTP_200_OK
assert len(response.json()) == 7

returned_supported_permissions = [
permission["key"]
for permission in response.json()
if permission["supports_tag"] is True
]
assert set(returned_supported_permissions) == set(TAG_SUPPORTED_PERMISSIONS)


def test_environment_my_permissions_reruns_400_for_master_api_key(
admin_master_api_key_client: APIClient, environment: Environment
Expand Down
Loading

0 comments on commit 2388983

Please sign in to comment.