| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 8d76028 commit be68285
18 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,7 +24,7 @@ API examples | |||
| 24 | 24 | gl_objects/environments | |
| 25 | 25 | gl_objects/events | |
| 26 | 26 | gl_objects/epics | |
| 27 | - gl_objects/features | ||
| 27 | + gl_objects/gitlab_features | ||
| 28 | 28 | gl_objects/geo_nodes | |
| 29 | 29 | gl_objects/groups | |
| 30 | 30 | gl_objects/group_access_tokens | |
@@ -49,6 +49,8 @@ API examples | |||
| 49 | 49 | gl_objects/pipelines_and_jobs | |
| 50 | 50 | gl_objects/projects | |
| 51 | 51 | gl_objects/project_access_tokens | |
| 52 | + gl_objects/project_feature_flags | ||
| 53 | + gl_objects/project_feature_flag_user_lists | ||
| 52 | 54 | gl_objects/protected_branches | |
| 53 | 55 | gl_objects/protected_container_repositories | |
| 54 | 56 | gl_objects/protected_environments | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,11 @@ | |||
| 1 | - ############## | ||
| 2 | - Features flags | ||
| 3 | - ############## | ||
| 1 | + ################################ | ||
| 2 | + GitLab Development Feature Flags | ||
| 3 | + ################################ | ||
| 4 | + | ||
| 5 | + .. note:: | ||
| 6 | + | ||
| 7 | + This API is for managing GitLab's internal development feature flags and requires administrator access. | ||
| 8 | + For project-level feature flags, see :doc:`project_feature_flags`. | ||
| 4 | 9 | ||
| 5 | 10 | Reference | |
| 6 | 11 | --------- | |
@@ -29,4 +34,4 @@ Create or set a feature:: | |||
| 29 | 34 | ||
| 30 | 35 | Delete a feature:: | |
| 31 | 36 | ||
| 32 | - feature.delete() | ||
| 37 | + feature.delete() | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,51 @@ | |||
| 1 | + ############################### | ||
| 2 | + Project Feature Flag User Lists | ||
| 3 | + ############################### | ||
| 4 | + | ||
| 5 | + Reference | ||
| 6 | + --------- | ||
| 7 | + | ||
| 8 | + * v4 API: | ||
| 9 | + | ||
| 10 | + + :class:`gitlab.v4.objects.ProjectFeatureFlagUserList` | ||
| 11 | + + :class:`gitlab.v4.objects.ProjectFeatureFlagUserListManager` | ||
| 12 | + + :attr:`gitlab.v4.objects.Project.feature_flags_user_lists` | ||
| 13 | + | ||
| 14 | + * GitLab API: https://docs.gitlab.com/api/feature_flag_user_lists | ||
| 15 | + | ||
| 16 | + Examples | ||
| 17 | + -------- | ||
| 18 | + | ||
| 19 | + List user lists:: | ||
| 20 | + | ||
| 21 | + user_lists = project.feature_flags_user_lists.list() | ||
| 22 | + | ||
| 23 | + Get a user list:: | ||
| 24 | + | ||
| 25 | + user_list = project.feature_flags_user_lists.get(list_iid) | ||
| 26 | + | ||
| 27 | + Create a user list:: | ||
| 28 | + | ||
| 29 | + user_list = project.feature_flags_user_lists.create({ | ||
| 30 | + 'name': 'my_user_list', | ||
| 31 | + 'user_xids': 'user1,user2,user3' | ||
| 32 | + }) | ||
| 33 | + | ||
| 34 | + Update a user list:: | ||
| 35 | + | ||
| 36 | + user_list.name = 'updated_list_name' | ||
| 37 | + user_list.user_xids = 'user1,user2' | ||
| 38 | + user_list.save() | ||
| 39 | + | ||
| 40 | + Delete a user list:: | ||
| 41 | + | ||
| 42 | + user_list.delete() | ||
| 43 | + | ||
| 44 | + Search for a user list:: | ||
| 45 | + | ||
| 46 | + user_lists = project.feature_flags_user_lists.list(search='my_list') | ||
| 47 | + | ||
| 48 | + See also | ||
| 49 | + -------- | ||
| 50 | + | ||
| 51 | + * :doc:`project_feature_flags` | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,63 @@ | |||
| 1 | + ##################### | ||
| 2 | + Project Feature Flags | ||
| 3 | + ##################### | ||
| 4 | + | ||
| 5 | + Reference | ||
| 6 | + --------- | ||
| 7 | + | ||
| 8 | + * v4 API: | ||
| 9 | + | ||
| 10 | + + :class:`gitlab.v4.objects.ProjectFeatureFlag` | ||
| 11 | + + :class:`gitlab.v4.objects.ProjectFeatureFlagManager` | ||
| 12 | + + :attr:`gitlab.v4.objects.Project.feature_flags` | ||
| 13 | + | ||
| 14 | + * GitLab API: https://docs.gitlab.com/api/feature_flags | ||
| 15 | + | ||
| 16 | + Examples | ||
| 17 | + -------- | ||
| 18 | + | ||
| 19 | + List feature flags:: | ||
| 20 | + | ||
| 21 | + flags = project.feature_flags.list() | ||
| 22 | + | ||
| 23 | + Get a feature flag:: | ||
| 24 | + | ||
| 25 | + flag = project.feature_flags.get('my_feature_flag') | ||
| 26 | + | ||
| 27 | + Create a feature flag:: | ||
| 28 | + | ||
| 29 | + flag = project.feature_flags.create({'name': 'my_feature_flag', 'version': 'new_version_flag'}) | ||
| 30 | + | ||
| 31 | + Create a feature flag with strategies:: | ||
| 32 | + | ||
| 33 | + flag = project.feature_flags.create({ | ||
| 34 | + 'name': 'my_complex_flag', | ||
| 35 | + 'version': 'new_version_flag', | ||
| 36 | + 'strategies': [{ | ||
| 37 | + 'name': 'userWithId', | ||
| 38 | + 'parameters': {'userIds': 'user1,user2'} | ||
| 39 | + }] | ||
| 40 | + }) | ||
| 41 | + | ||
| 42 | + Update a feature flag:: | ||
| 43 | + | ||
| 44 | + flag.description = 'Updated description' | ||
| 45 | + flag.save() | ||
| 46 | + | ||
| 47 | + Rename a feature flag:: | ||
| 48 | + | ||
| 49 | + # You can rename a flag by changing its name attribute and calling save() | ||
| 50 | + flag.name = 'new_flag_name' | ||
| 51 | + flag.save() | ||
| 52 | + | ||
| 53 | + # Alternatively, you can use the manager's update method | ||
| 54 | + project.feature_flags.update('old_flag_name', {'name': 'new_flag_name'}) | ||
| 55 | + | ||
| 56 | + Delete a feature flag:: | ||
| 57 | + | ||
| 58 | + flag.delete() | ||
| 59 | + | ||
| 60 | + See also | ||
| 61 | + -------- | ||
| 62 | + | ||
| 63 | + * :doc:`project_feature_flag_user_lists` | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -409,6 +409,44 @@ Search projects by custom attribute:: | |||
| 409 | 409 | project.customattributes.set('type', 'internal') | |
| 410 | 410 | gl.projects.list(custom_attributes={'type': 'internal'}, get_all=True) | |
| 411 | 411 | ||
| 412 | + Project feature flags | ||
| 413 | + ===================== | ||
| 414 | + | ||
| 415 | + Reference | ||
| 416 | + --------- | ||
| 417 | + | ||
| 418 | + * v4 API: | ||
| 419 | + | ||
| 420 | + + :class:`gitlab.v4.objects.ProjectFeatureFlag` | ||
| 421 | + + :class:`gitlab.v4.objects.ProjectFeatureFlagManager` | ||
| 422 | + + :attr:`gitlab.v4.objects.Project.feature_flags` | ||
| 423 | + | ||
| 424 | + * GitLab API: https://docs.gitlab.com/api/feature_flags | ||
| 425 | + | ||
| 426 | + Examples | ||
| 427 | + -------- | ||
| 428 | + | ||
| 429 | + See :doc:`project_feature_flags`. | ||
| 430 | + | ||
| 431 | + Project feature flag user lists | ||
| 432 | + =============================== | ||
| 433 | + | ||
| 434 | + Reference | ||
| 435 | + --------- | ||
| 436 | + | ||
| 437 | + * v4 API: | ||
| 438 | + | ||
| 439 | + + :class:`gitlab.v4.objects.ProjectFeatureFlagUserList` | ||
| 440 | + + :class:`gitlab.v4.objects.ProjectFeatureFlagUserListManager` | ||
| 441 | + + :attr:`gitlab.v4.objects.Project.feature_flags_user_lists` | ||
| 442 | + | ||
| 443 | + * GitLab API: https://docs.gitlab.com/api/feature_flag_user_lists | ||
| 444 | + | ||
| 445 | + Examples | ||
| 446 | + -------- | ||
| 447 | + | ||
| 448 | + See :doc:`project_feature_flag_user_lists`. | ||
| 449 | + | ||
| 412 | 450 | Project files | |
| 413 | 451 | ============= | |
| 414 | 452 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,8 +1,11 @@ | |||
| 1 | 1 | from __future__ import annotations | |
| 2 | 2 | ||
| 3 | 3 | import dataclasses | |
| 4 | + import json | ||
| 4 | 5 | from typing import Any, TYPE_CHECKING | |
| 5 | 6 | ||
| 7 | + from gitlab import exceptions | ||
| 8 | + | ||
| 6 | 9 | ||
| 7 | 10 | @dataclasses.dataclass(frozen=True) | |
| 8 | 11 | class RequiredOptional: | |
@@ -36,6 +39,13 @@ def validate_attrs( | |||
| 36 | 39 | ||
| 37 | 40 | ||
| 38 | 41 | class GitlabAttribute: | |
| 42 | + # Used in utils._transform_types() to decide if we should call get_for_api() | ||
| 43 | + # on the attribute when transform_data is False (e.g. for POST/PUT/PATCH). | ||
| 44 | + # | ||
| 45 | + # This allows us to force transformation of data even when sending JSON bodies, | ||
| 46 | + # which is useful for types like CommaSeparatedStringAttribute. | ||
| 47 | + transform_in_body = False | ||
| 48 | + | ||
| 39 | 49 | def __init__(self, value: Any = None) -> None: | |
| 40 | 50 | self._value = value | |
| 41 | 51 | ||
@@ -49,6 +59,16 @@ def get_for_api(self, *, key: str) -> tuple[str, Any]: | |||
| 49 | 59 | return (key, self._value) | |
| 50 | 60 | ||
| 51 | 61 | ||
| 62 | + class JsonAttribute(GitlabAttribute): | ||
| 63 | + def set_from_cli(self, cli_value: str) -> None: | ||
| 64 | + try: | ||
| 65 | + self._value = json.loads(cli_value) | ||
| 66 | + except (ValueError, TypeError) as e: | ||
| 67 | + raise exceptions.GitlabParsingError( | ||
| 68 | + f"Could not parse JSON data: {e}" | ||
| 69 | + ) from e | ||
| 70 | + | ||
| 71 | + | ||
| 52 | 72 | class _ListArrayAttribute(GitlabAttribute): | |
| 53 | 73 | """Helper class to support `list` / `array` types.""" | |
| 54 | 74 | ||
@@ -82,9 +102,23 @@ def get_for_api(self, *, key: str) -> tuple[str, Any]: | |||
| 82 | 102 | ||
| 83 | 103 | ||
| 84 | 104 | class CommaSeparatedListAttribute(_ListArrayAttribute): | |
| 85 | - """For values which are sent to the server as a Comma Separated Values | ||
| 86 | - (CSV) string. We allow them to be specified as a list and we convert it | ||
| 87 | - into a CSV""" | ||
| 105 | + """ | ||
| 106 | + For values which are sent to the server as a Comma Separated Values (CSV) string | ||
| 107 | + in query parameters (GET), but as a list/array in JSON bodies (POST/PUT). | ||
| 108 | + """ | ||
| 109 | + | ||
| 110 | + | ||
| 111 | + class CommaSeparatedStringAttribute(_ListArrayAttribute): | ||
| 112 | + """ | ||
| 113 | + For values which are sent to the server as a Comma Separated Values (CSV) string. | ||
| 114 | + Unlike CommaSeparatedListAttribute, this type ensures the value is converted | ||
| 115 | + to a string even in JSON bodies (POST/PUT requests). | ||
| 116 | + """ | ||
| 117 | + | ||
| 118 | + # Used in utils._transform_types() to ensure the value is converted to a string | ||
| 119 | + # via get_for_api() even when transform_data is False (e.g. for POST/PUT/PATCH). | ||
| 120 | + # This is needed because some APIs require a CSV string instead of a JSON array. | ||
| 121 | + transform_in_body = True | ||
| 88 | 122 | ||
| 89 | 123 | ||
| 90 | 124 | class LowercaseStringAttribute(GitlabAttribute): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -198,7 +198,15 @@ def _transform_types( | |||
| 198 | 198 | files[attr_name] = (key, data.pop(attr_name)) | |
| 199 | 199 | continue | |
| 200 | 200 | ||
| 201 | - if not transform_data: | ||
| 201 | + # If transform_data is False, it means we are preparing data for a JSON body | ||
| 202 | + # (POST/PUT/PATCH). In this case, we normally skip transformation because | ||
| 203 | + # most types (like ArrayAttribute) only need transformation for query | ||
| 204 | + # parameters (GET). | ||
| 205 | + # | ||
| 206 | + # However, some types (like CommaSeparatedStringAttribute) need to be | ||
| 207 | + # transformed even in JSON bodies (e.g. converting a list to a CSV string). | ||
| 208 | + # The 'transform_in_body' flag on the attribute class controls this behavior. | ||
| 209 | + if not transform_data and not gitlab_attribute.transform_in_body: | ||
| 202 | 210 | continue | |
| 203 | 211 | ||
| 204 | 212 | if isinstance(gitlab_attribute, types.GitlabAttribute): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,6 +24,8 @@ | |||
| 24 | 24 | from .epics import * | |
| 25 | 25 | from .events import * | |
| 26 | 26 | from .export_import import * | |
| 27 | + from .feature_flag_user_lists import * | ||
| 28 | + from .feature_flags import * | ||
| 27 | 29 | from .features import * | |
| 28 | 30 | from .files import * | |
| 29 | 31 | from .geo_nodes import * | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,27 @@ | |||
| 1 | + """ | ||
| 2 | + GitLab API: | ||
| 3 | + https://docs.gitlab.com/api/feature_flag_user_lists | ||
| 4 | + """ | ||
| 5 | + | ||
| 6 | + from __future__ import annotations | ||
| 7 | + | ||
| 8 | + from gitlab import types | ||
| 9 | + from gitlab.base import RESTObject | ||
| 10 | + from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin | ||
| 11 | + from gitlab.types import RequiredOptional | ||
| 12 | + | ||
| 13 | + __all__ = ["ProjectFeatureFlagUserList", "ProjectFeatureFlagUserListManager"] | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + class ProjectFeatureFlagUserList(SaveMixin, ObjectDeleteMixin, RESTObject): | ||
| 17 | + _id_attr = "iid" | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + class ProjectFeatureFlagUserListManager(CRUDMixin[ProjectFeatureFlagUserList]): | ||
| 21 | + _path = "/projects/{project_id}/feature_flags_user_lists" | ||
| 22 | + _obj_cls = ProjectFeatureFlagUserList | ||
| 23 | + _from_parent_attrs = {"project_id": "id"} | ||
| 24 | + _create_attrs = RequiredOptional(required=("name", "user_xids")) | ||
| 25 | + _update_attrs = RequiredOptional(optional=("name", "user_xids")) | ||
| 26 | + _list_filters = ("search",) | ||
| 27 | + _types = {"user_xids": types.CommaSeparatedStringAttribute} | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments