Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Import / export of features across environments and orgs #3026

Merged
merged 44 commits into from
Dec 7, 2023

Conversation

zachaysan
Copy link
Contributor

Thanks for submitting a PR! Please check the boxes below:

  • I have run pre-commit to check linting
  • I have filled in the "Changes" section below?
  • I have filled in the "How did you test this code" section below?
  • I have used a Conventional Commit title for this Pull Request

Changes

This PR allows someone using Flagsmith to export the information around their feature flags from a given environment in order to import them into another environment even at a different organisation or instance of flagsmith. Changes include:

  1. An endpoint to create a new feature export. This takes in an environment_id and a list of tag_ids as part of a post body and kicks off a job to generate the export.
  2. An endpoint to list the feature exports that have been successfully generated. For readability, the name of the export is the environment name then a timestamp to the minute. For example, "Production | 2023-11-23 15:36 UTC".
  3. An endpoint to download the export as a file via FeatureExport id.
  4. An endpoint to upload a exported and downloaded file for a given environment with the option to specify one of two strategies for conflicting feature names. The first is called SKIP which skips any existing features that are named the same thing. The second is called OVERWRITE which discards an existing feature and related objects before creating a new one to load with.
  5. A task that generates exports into a fairly flat file structure. The only nesting that was necessary was around multivariate options.
  6. A task that processes imports abiding by the strategy specified above.
  7. A task that cleans up stale exports after they've aged two weeks.

How did you test this code?

Many individual tests for the views and the tasks. To test import and export tasks I elected to test them together to verify the process worked from download to upload. I also manually tested the file download endpoint to make sure the header was correctly set to initiate a download.

I was unable to test the JavaScript friendly file upload API, so although I tried my best to follow guides, the implementer of the frontend (Novak) may want to have me on a video call when he's wiring that part up.

Copy link

vercel bot commented Nov 23, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 7, 2023 4:37pm
flagsmith-frontend-preview ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 7, 2023 4:37pm
flagsmith-frontend-staging ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 7, 2023 4:37pm

@github-actions github-actions bot added the api Issue related to the REST API label Nov 23, 2023
api/features/models.py Outdated Show resolved Hide resolved
api/features/tasks.py Outdated Show resolved Hide resolved
api/features/views.py Outdated Show resolved Hide resolved
Copy link
Contributor

github-actions bot commented Nov 23, 2023

Uffizzi Preview deployment-42301 was deleted.

api/features/import_export/serializers.py Outdated Show resolved Hide resolved
api/features/import_export/views.py Outdated Show resolved Hide resolved
api/features/import_export/views.py Outdated Show resolved Hide resolved
api/features/import_export/views.py Outdated Show resolved Hide resolved
@permission_classes([FeatureImportPermissions])
def feature_import(request: Request, environment_id: int) -> Response:
upload_serializer = FeatureImportUploadSerializer(data=request.data)
upload_serializer.is_valid(raise_exception=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zachaysan I moved this check here to follow standard DRF patterns.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. Okay yeah that makes more sense.

def feature_import(request: Request, environment_id: int) -> Response:
upload_serializer = FeatureImportUploadSerializer(data=request.data)
upload_serializer.is_valid(raise_exception=True)
_feature_import = upload_serializer.save(environment_id=environment_id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the name of this variable to stop my IDE complaining about it shadowing the name from the outer scope.

@zachaysan zachaysan added this pull request to the merge queue Dec 7, 2023
Merged via the queue into main with commit c4bdc0f Dec 7, 2023
17 checks passed
@zachaysan zachaysan deleted the feat/import_export_of_features_from_environments branch December 7, 2023 18:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Issue related to the REST API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants