-
Notifications
You must be signed in to change notification settings - Fork 368
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: integrate flagsmith client into API layer (#2447)
Co-authored-by: Kim Gustyr <[email protected]>
- Loading branch information
1 parent
316ac80
commit e71efbb
Showing
15 changed files
with
467 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
name: Update Flagsmith Defaults | ||
|
||
on: | ||
schedule: | ||
- cron: 0 8 * * * | ||
|
||
defaults: | ||
run: | ||
working-directory: api | ||
|
||
jobs: | ||
update_server_defaults: | ||
runs-on: ubuntu-latest | ||
name: Update API Flagsmith Defaults | ||
env: | ||
FLAGSMITH_ON_FLAGSMITH_SERVER_API_URL: https://edge.api.flagsmith.com/api/v1 | ||
FLAGSMITH_ON_FLAGSMITH_SERVER_KEY: ${{ secrets.FLAGSMITH_ON_FLAGSMITH_SERVER_KEY }} | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Set up Python 3.11 | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: 3.11 | ||
cache: pip | ||
|
||
- name: Install Dependencies | ||
run: make install | ||
|
||
- name: Update defaults | ||
run: python manage.py updateflagsmithenvironment | ||
|
||
- name: Create Pull Request | ||
uses: peter-evans/create-pull-request@v5 | ||
with: | ||
commit-message: Update API Flagsmith Defaults | ||
branch: chore/update-api-flagsmith-environment | ||
delete-branch: true | ||
title: 'chore: update Flagsmith environment document' | ||
labels: api |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
""" | ||
Wrapper module for the flagsmith client to implement singleton behaviour and provide some | ||
additional logic by wrapping the client. | ||
Usage: | ||
``` | ||
environment_flags = get_client().get_environment_flags() | ||
identity_flags = get_client().get_identity_flags() | ||
``` | ||
Possible extensions: | ||
- Allow for multiple clients? | ||
""" | ||
import typing | ||
|
||
from django.conf import settings | ||
from flagsmith import Flagsmith | ||
from flagsmith.offline_handlers import LocalFileHandler | ||
|
||
from integrations.flagsmith.exceptions import FlagsmithIntegrationError | ||
from integrations.flagsmith.flagsmith_service import ENVIRONMENT_JSON_PATH | ||
|
||
_flagsmith_client: typing.Optional[Flagsmith] = None | ||
|
||
|
||
def get_client() -> Flagsmith: | ||
global _flagsmith_client | ||
|
||
if not _flagsmith_client: | ||
_flagsmith_client = Flagsmith(**_get_client_kwargs()) | ||
|
||
return _flagsmith_client | ||
|
||
|
||
def _get_client_kwargs() -> dict[str, typing.Any]: | ||
_default_kwargs = {"offline_handler": LocalFileHandler(ENVIRONMENT_JSON_PATH)} | ||
|
||
if settings.FLAGSMITH_ON_FLAGSMITH_SERVER_OFFLINE_MODE: | ||
return {"offline_mode": True, **_default_kwargs} | ||
elif ( | ||
settings.FLAGSMITH_ON_FLAGSMITH_SERVER_KEY | ||
and settings.FLAGSMITH_ON_FLAGSMITH_SERVER_API_URL | ||
): | ||
return { | ||
"environment_key": settings.FLAGSMITH_ON_FLAGSMITH_SERVER_KEY, | ||
"api_url": settings.FLAGSMITH_ON_FLAGSMITH_SERVER_API_URL, | ||
**_default_kwargs, | ||
} | ||
|
||
raise FlagsmithIntegrationError( | ||
"Must either use offline mode, or provide " | ||
"FLAGSMITH_ON_FLAGSMITH_SERVER_KEY and FLAGSMITH_ON_FLAGSMITH_SERVER_API_URL." | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"api_key": "masked", | ||
"feature_states": [ | ||
{ | ||
"feature": { | ||
"id": 51089, | ||
"name": "test", | ||
"type": "STANDARD" | ||
}, | ||
"enabled": false, | ||
"django_id": 286268, | ||
"feature_segment": null, | ||
"featurestate_uuid": "ec33a926-0b7e-4eb7-b02b-bf9df2ffa53e", | ||
"feature_state_value": null, | ||
"multivariate_feature_state_values": [] | ||
} | ||
], | ||
"id": 0, | ||
"name": "Development", | ||
"project": { | ||
"id": 0, | ||
"name": "Flagsmith API", | ||
"hide_disabled_flags": false, | ||
"organisation": { | ||
"id": 0, | ||
"name": "Flagsmith", | ||
"feature_analytics": false, | ||
"stop_serving_flags": false, | ||
"persist_trait_data": true | ||
}, | ||
"segments": [] | ||
}, | ||
"use_identity_composite_key_for_hashing": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
class FlagsmithIntegrationError(Exception): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import json | ||
import os | ||
|
||
import requests | ||
from django.conf import settings | ||
|
||
from integrations.flagsmith.exceptions import FlagsmithIntegrationError | ||
|
||
ENVIRONMENT_JSON_PATH = os.path.join( | ||
os.path.dirname(os.path.realpath(__file__)), "data/environment.json" | ||
) | ||
|
||
KEEP_ENVIRONMENT_FIELDS = ( | ||
"name", | ||
"feature_states", | ||
"use_identity_composite_key_for_hashing", | ||
) | ||
KEEP_PROJECT_FIELDS = ("name", "organisation", "hide_disabled_flags") | ||
KEEP_ORGANISATION_FIELDS = ( | ||
"name", | ||
"feature_analytics", | ||
"stop_serving_flags", | ||
"persist_trait_data", | ||
) | ||
|
||
|
||
def update_environment_json(environment_key: str = None, api_url: str = None) -> None: | ||
environment_key = environment_key or settings.FLAGSMITH_ON_FLAGSMITH_SERVER_KEY | ||
api_url = api_url or settings.FLAGSMITH_ON_FLAGSMITH_SERVER_API_URL | ||
|
||
response = requests.get( | ||
f"{api_url}/environment-document", | ||
headers={"X-Environment-Key": environment_key}, | ||
) | ||
if response.status_code != 200: | ||
raise FlagsmithIntegrationError( | ||
f"Couldn't get defaults from Flagsmith. Got {response.status_code} response." | ||
) | ||
|
||
environment_json = _get_masked_environment_data(response.json()) | ||
with open(ENVIRONMENT_JSON_PATH, "w+") as defaults: | ||
defaults.write(json.dumps(environment_json, indent=2, sort_keys=True)) | ||
|
||
|
||
def _get_masked_environment_data(environment_document: dict) -> dict: | ||
""" | ||
Return a cut down / masked version of the environment | ||
document which can be committed to VCS. | ||
""" | ||
|
||
project_json = environment_document.pop("project") | ||
organisation_json = project_json.pop("organisation") | ||
|
||
return { | ||
"id": 0, | ||
"api_key": "masked", | ||
**{ | ||
k: v | ||
for k, v in environment_document.items() | ||
if k in KEEP_ENVIRONMENT_FIELDS | ||
}, | ||
"project": { | ||
"id": 0, | ||
**{k: v for k, v in project_json.items() if k in KEEP_PROJECT_FIELDS}, | ||
"organisation": { | ||
"id": 0, | ||
**{ | ||
k: v | ||
for k, v in organisation_json.items() | ||
if k in KEEP_ORGANISATION_FIELDS | ||
}, | ||
}, | ||
"segments": [], | ||
}, | ||
} |
Empty file.
Empty file.
8 changes: 8 additions & 0 deletions
8
api/integrations/flagsmith/management/commands/updateflagsmithenvironment.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from django.core.management import BaseCommand | ||
|
||
from integrations.flagsmith.flagsmith_service import update_environment_json | ||
|
||
|
||
class Command(BaseCommand): | ||
def handle(self, *args, **options): | ||
update_environment_json() |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.
e71efbb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
flagsmith-frontend-staging – ./frontend
flagsmith-frontend-staging-git-main-flagsmith.vercel.app
flagsmith-staging-frontend.vercel.app
staging.flagsmith.com
flagsmith-frontend-staging-flagsmith.vercel.app
e71efbb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
docs – ./docs
docs-flagsmith.vercel.app
docs-git-main-flagsmith.vercel.app
docs.flagsmith.com
docs.bullet-train.io
e71efbb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
flagsmith-frontend-preview – ./frontend
flagsmith-frontend-preview-git-main-flagsmith.vercel.app
flagsmith-frontend-preview-flagsmith.vercel.app
flagsmith-frontend-production-native.vercel.app