-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
docs(api): Update create project api doc #50454
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
Changes from all commits
52470e8
3e7c6dd
4c32c82
0d0cfe1
fb5ec04
4772db5
5491878
b955ea6
c39c9ab
ffd3ec3
db9edfe
7754286
0ae45ed
8a923c9
440ea04
c6aa55b
c2b4ebf
62fe5f5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
from django.db import IntegrityError, transaction | ||
from drf_spectacular.utils import OpenApiResponse, extend_schema | ||
from rest_framework import serializers, status | ||
from rest_framework.request import Request | ||
from rest_framework.response import Response | ||
|
@@ -8,6 +9,12 @@ | |
from sentry.api.bases.team import TeamEndpoint, TeamPermission | ||
from sentry.api.paginator import OffsetPaginator | ||
from sentry.api.serializers import ProjectSummarySerializer, serialize | ||
from sentry.api.serializers.models.project import ( | ||
ProjectSerializer as SentryProjectResponseSerializer, | ||
) | ||
from sentry.apidocs.constants import RESPONSE_BAD_REQUEST, RESPONSE_FORBIDDEN | ||
from sentry.apidocs.examples.project_examples import ProjectExamples | ||
from sentry.apidocs.parameters import GLOBAL_PARAMS, PROJECT_PARAMS | ||
from sentry.constants import ObjectStatus | ||
from sentry.models import Project | ||
from sentry.signals import project_created | ||
|
@@ -16,7 +23,7 @@ | |
ERR_INVALID_STATS_PERIOD = "Invalid stats_period. Valid choices are '', '24h', '14d', and '30d'" | ||
|
||
|
||
class ProjectSerializer(serializers.Serializer): | ||
class ProjectPostSerializer(serializers.Serializer): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're required to change the name of this serializer b/c there is a duplicate |
||
name = serializers.CharField(max_length=50, required=True) | ||
slug = serializers.RegexField(r"^[a-z0-9_\-]+$", max_length=50, required=False, allow_null=True) | ||
platform = serializers.CharField(required=False, allow_blank=True, allow_null=True) | ||
|
@@ -47,6 +54,7 @@ class TeamProjectPermission(TeamPermission): | |
|
||
@region_silo_endpoint | ||
class TeamProjectsEndpoint(TeamEndpoint, EnvironmentMixin): | ||
public = {"POST"} | ||
permission_classes = (TeamProjectPermission,) | ||
|
||
def get(self, request: Request, team) -> Response: | ||
|
@@ -93,24 +101,35 @@ def get(self, request: Request, team) -> Response: | |
paginator_cls=OffsetPaginator, | ||
) | ||
|
||
@extend_schema( | ||
# Ensure POST is in the projects tab | ||
tags=["Projects"], | ||
operation_id="Create a New Project", | ||
parameters=[ | ||
GLOBAL_PARAMS.ORG_SLUG, | ||
GLOBAL_PARAMS.TEAM_SLUG, | ||
GLOBAL_PARAMS.name("The name of the project.", required=True), | ||
GLOBAL_PARAMS.slug( | ||
"Optional slug for the project. If not provided a slug is generated from the name." | ||
), | ||
PROJECT_PARAMS.platform("The platform for the project."), | ||
PROJECT_PARAMS.DEFAULT_RULES, | ||
], | ||
request=ProjectPostSerializer, | ||
responses={ | ||
201: SentryProjectResponseSerializer, | ||
400: RESPONSE_BAD_REQUEST, | ||
403: RESPONSE_FORBIDDEN, | ||
404: OpenApiResponse(description="Team not found."), | ||
409: OpenApiResponse(description="A project with this slug already exists."), | ||
}, | ||
examples=ProjectExamples.CREATE_PROJECT, | ||
) | ||
def post(self, request: Request, team) -> Response: | ||
""" | ||
Create a New Project | ||
```````````````````` | ||
|
||
Create a new project bound to a team. | ||
|
||
:pparam string organization_slug: the slug of the organization the | ||
team belongs to. | ||
:pparam string team_slug: the slug of the team to create a new project | ||
for. | ||
:param string name: the name for the new project. | ||
:param string slug: optionally a slug for the new project. If it's | ||
not provided a slug is generated from the name. | ||
:param bool default_rules: create default rules (defaults to True) | ||
:auth: required | ||
""" | ||
serializer = ProjectSerializer(data=request.data) | ||
serializer = ProjectPostSerializer(data=request.data) | ||
|
||
if not serializer.is_valid(): | ||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
from drf_spectacular.utils import OpenApiExample | ||
|
||
|
||
class ProjectExamples: | ||
CREATE_PROJECT = [ | ||
OpenApiExample( | ||
"Project successfully created", | ||
{ | ||
"id": "4505321021243392", | ||
"slug": "the-spoiled-yoghurt", | ||
"name": "The Spoiled Yoghurt", | ||
"platform": "python", | ||
"dateCreated": "2023-06-08T00:13:06.004534Z", | ||
"isBookmarked": False, | ||
"isMember": True, | ||
"features": [ | ||
"alert-filters", | ||
"custom-inbound-filters", | ||
"data-forwarding", | ||
"discard-groups", | ||
"minidump", | ||
"race-free-group-creation", | ||
"rate-limits", | ||
"servicehooks", | ||
"similarity-indexing", | ||
"similarity-indexing-v2", | ||
"similarity-view", | ||
"similarity-view-v2", | ||
], | ||
"firstEvent": None, | ||
"firstTransactionEvent": False, | ||
"access": [ | ||
"member:read", | ||
"event:read", | ||
"project:admin", | ||
"team:write", | ||
"project:write", | ||
"team:admin", | ||
"project:read", | ||
"org:integrations", | ||
"org:read", | ||
"project:releases", | ||
"team:read", | ||
"alerts:write", | ||
"event:admin", | ||
"event:write", | ||
"alerts:read", | ||
], | ||
"hasAccess": True, | ||
"hasMinifiedStackTrace": False, | ||
"hasMonitors": False, | ||
"hasProfiles": False, | ||
"hasReplays": False, | ||
"hasSessions": False, | ||
"isInternal": False, | ||
"isPublic": False, | ||
"avatar": {"avatarType": "letter_avatar", "avatarUuid": None}, | ||
"color": "#3f70bf", | ||
"status": "active", | ||
}, | ||
status_codes=["201"], | ||
), | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,10 +21,3 @@ def test_get(self): | |
request = RequestFactory().get(self.url) | ||
|
||
self.validate_schema(request, response) | ||
|
||
def test_post(self): | ||
data = {"name": "foo"} | ||
response = self.client.post(self.url, data) | ||
request = RequestFactory().post(self.url, data) | ||
|
||
self.validate_schema(request, response) | ||
Comment on lines
-24
to
-30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test can be safely deleted b/c typing is verified through drf/open-api |
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.
The
make watch-api-docs
command was broken before so this fixes it