Skip to content

Commit 6a10dae

Browse files
JoshFergeclaude
andauthored
ref(api): Convert release deploys endpoint to drf-spectacular documentation (#94700)
## Summary Convert the release deploys endpoint from legacy OpenAPI JSON documentation to the modern drf-spectacular approach. ### Changes Made: - Remove legacy OpenAPI JSON reference for `/api/0/organizations/{organization_id_or_slug}/releases/{version}/deploys/` - Add drf-spectacular decorators with proper parameters and responses - Add `help_text` to `DeploySerializer` fields for complete API documentation - Set `ApiOwner.UNOWNED` and `ApiPublishStatus.PUBLIC` for proper API ownership - Use predefined parameters (`GlobalParams.ORG_ID_OR_SLUG`, `ReleaseParams.VERSION`) and response constants for consistency ### Documentation Improvements: - Endpoint now properly documented in the new drf-spectacular system - All serializer fields have descriptive help text for better API docs - Uses standardized parameter and response definitions - Maintains backward compatibility while improving documentation quality ## Test plan - [x] API documentation builds successfully with `make build-api-docs` - [x] No diff issues with `make diff-api-docs` - [x] All linting and type checking passes - [x] Deploy endpoint appears correctly in spectacular documentation - [x] Legacy deploy endpoint reference removed from OpenAPI JSON 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude <noreply@anthropic.com>
1 parent cb28ac6 commit 6a10dae

File tree

2 files changed

+66
-34
lines changed

2 files changed

+66
-34
lines changed

api-docs/openapi.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,6 @@
166166
"/api/0/organizations/{organization_id_or_slug}/releases/{version}/commitfiles/": {
167167
"$ref": "paths/releases/organization-release-commit-files.json"
168168
},
169-
"/api/0/organizations/{organization_id_or_slug}/releases/{version}/deploys/": {
170-
"$ref": "paths/releases/deploys.json"
171-
},
172169
"/api/0/organizations/{organization_id_or_slug}/sentry-app-installations/": {
173170
"$ref": "paths/integration-platform/sentry-app-installations.json"
174171
},

src/sentry/api/endpoints/release_deploys.py

Lines changed: 66 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,21 @@
22

33
from django.db.models import F
44
from django.utils import timezone
5+
from drf_spectacular.utils import extend_schema
56
from rest_framework import serializers
67
from rest_framework.request import Request
78
from rest_framework.response import Response
89

10+
from sentry.api.api_owners import ApiOwner
911
from sentry.api.api_publish_status import ApiPublishStatus
1012
from sentry.api.base import region_silo_endpoint
1113
from sentry.api.bases.organization import OrganizationReleasesBaseEndpoint
1214
from sentry.api.exceptions import ParameterValidationError, ResourceDoesNotExist
1315
from sentry.api.paginator import OffsetPaginator
1416
from sentry.api.serializers import serialize
1517
from sentry.api.serializers.rest_framework.project import ProjectField
18+
from sentry.apidocs.constants import RESPONSE_BAD_REQUEST
19+
from sentry.apidocs.parameters import GlobalParams, ReleaseParams
1620
from sentry.models.deploy import Deploy
1721
from sentry.models.environment import Environment
1822
from sentry.models.organization import Organization
@@ -23,14 +27,55 @@
2327
logger = logging.getLogger(__name__)
2428

2529

30+
class DeployResponseSerializer(serializers.Serializer):
31+
"""Serializer for Deploy response objects"""
32+
33+
id = serializers.CharField(help_text="The ID of the deploy")
34+
environment = serializers.CharField(help_text="The environment name")
35+
dateStarted = serializers.DateTimeField(
36+
allow_null=True, help_text="An optional date that indicates when the deploy started"
37+
)
38+
dateFinished = serializers.DateTimeField(
39+
help_text="An optional date that indicates when the deploy ended"
40+
)
41+
name = serializers.CharField(allow_null=True, help_text="The optional name of the deploy")
42+
url = serializers.URLField(
43+
allow_null=True, help_text="The optional URL that points to the deploy"
44+
)
45+
46+
2647
class DeploySerializer(serializers.Serializer):
27-
name = serializers.CharField(max_length=64, required=False, allow_blank=True, allow_null=True)
28-
environment = serializers.CharField(max_length=64)
29-
url = serializers.URLField(required=False, allow_blank=True, allow_null=True)
30-
dateStarted = serializers.DateTimeField(required=False, allow_null=True)
31-
dateFinished = serializers.DateTimeField(required=False, allow_null=True)
48+
name = serializers.CharField(
49+
max_length=64,
50+
required=False,
51+
allow_blank=True,
52+
allow_null=True,
53+
help_text="The optional name of the deploy",
54+
)
55+
environment = serializers.CharField(
56+
max_length=64, help_text="The environment you're deploying to"
57+
)
58+
url = serializers.URLField(
59+
required=False,
60+
allow_blank=True,
61+
allow_null=True,
62+
help_text="The optional URL that points to the deploy",
63+
)
64+
dateStarted = serializers.DateTimeField(
65+
required=False,
66+
allow_null=True,
67+
help_text="An optional date that indicates when the deploy started",
68+
)
69+
dateFinished = serializers.DateTimeField(
70+
required=False,
71+
allow_null=True,
72+
help_text="An optional date that indicates when the deploy ended. If not provided, the current time is used.",
73+
)
3274
projects = serializers.ListField(
33-
child=ProjectField(scope="project:read", id_allowed=True), required=False, allow_empty=False
75+
child=ProjectField(scope="project:read", id_allowed=True),
76+
required=False,
77+
allow_empty=False,
78+
help_text="The optional list of project slugs to create a deploy within. If not provided, deploys are created for all of the release's projects.",
3479
)
3580

3681
def validate_environment(self, value):
@@ -89,22 +134,23 @@ def create_deploy(
89134
return deploy
90135

91136

137+
@extend_schema(tags=["Releases"])
92138
@region_silo_endpoint
93139
class ReleaseDeploysEndpoint(OrganizationReleasesBaseEndpoint):
140+
owner = ApiOwner.UNOWNED
94141
publish_status = {
95-
"GET": ApiPublishStatus.UNKNOWN,
96-
"POST": ApiPublishStatus.UNKNOWN,
142+
"GET": ApiPublishStatus.PUBLIC,
143+
"POST": ApiPublishStatus.PUBLIC,
97144
}
98145

146+
@extend_schema(
147+
operation_id="List a Release's Deploys",
148+
parameters=[GlobalParams.ORG_ID_OR_SLUG, ReleaseParams.VERSION],
149+
responses={200: DeployResponseSerializer(many=True)},
150+
)
99151
def get(self, request: Request, organization, version) -> Response:
100152
"""
101-
List a Release's Deploys
102-
````````````````````````
103-
104153
Returns a list of deploys based on the organization, version, and project.
105-
106-
:pparam string organization_id_or_slug: the id or slug of the organization
107-
:pparam string version: the version identifier of the release.
108154
"""
109155
try:
110156
release = Release.objects.get(version=version, organization=organization)
@@ -136,26 +182,15 @@ def get(self, request: Request, organization, version) -> Response:
136182
on_results=lambda x: serialize(x, request.user),
137183
)
138184

185+
@extend_schema(
186+
operation_id="Create a Deploy",
187+
parameters=[GlobalParams.ORG_ID_OR_SLUG, ReleaseParams.VERSION],
188+
request=DeploySerializer,
189+
responses={201: DeployResponseSerializer, 400: RESPONSE_BAD_REQUEST},
190+
)
139191
def post(self, request: Request, organization, version) -> Response:
140192
"""
141-
Create a Deploy
142-
```````````````
143-
144193
Create a deploy for a given release.
145-
146-
:pparam string organization_id_or_slug: the id or slug of the organization
147-
:pparam string version: the version identifier of the release.
148-
:param string environment: the environment you're deploying to
149-
:param string name: the optional name of the deploy
150-
:param list projects: the optional list of project slugs to
151-
create a deploy within. If not provided, deploys
152-
are created for all of the release's projects.
153-
:param url url: the optional url that points to the deploy
154-
:param datetime dateStarted: an optional date that indicates when
155-
the deploy started
156-
:param datetime dateFinished: an optional date that indicates when
157-
the deploy ended. If not provided, the
158-
current time is used.
159194
"""
160195
logging_info = {
161196
"org_slug": organization.slug,

0 commit comments

Comments
 (0)