Skip to content

Commit ec8946b

Browse files
noahsmartinandrewshie-sentry
authored andcommitted
feat(preprod): Add check for updates API (#96950)
Adds API for getting the latest app update, most of the endpoint logic needs to be filled in, this is just the endpoint scaffolding
1 parent c7493c7 commit ec8946b

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import logging
2+
3+
from pydantic import BaseModel
4+
from rest_framework.request import Request
5+
from rest_framework.response import Response
6+
7+
from sentry.api.api_owners import ApiOwner
8+
from sentry.api.api_publish_status import ApiPublishStatus
9+
from sentry.api.base import region_silo_endpoint
10+
from sentry.api.bases.project import ProjectEndpoint, ProjectReleasePermission
11+
from sentry.preprod.models import PreprodArtifact
12+
from sentry.types.ratelimit import RateLimit, RateLimitCategory
13+
14+
logger = logging.getLogger(__name__)
15+
16+
17+
class InstallableBuildDetails(BaseModel):
18+
build_version: str
19+
build_number: int
20+
21+
22+
class CheckForUpdatesApiResponse(BaseModel):
23+
update: InstallableBuildDetails | None = None
24+
current: InstallableBuildDetails | None = None
25+
26+
27+
@region_silo_endpoint
28+
class ProjectPreprodArtifactCheckForUpdatesEndpoint(ProjectEndpoint):
29+
owner = ApiOwner.EMERGE_TOOLS
30+
publish_status = {
31+
"GET": ApiPublishStatus.EXPERIMENTAL,
32+
}
33+
permission_classes = (ProjectReleasePermission,)
34+
35+
enforce_rate_limit = True
36+
rate_limits = {
37+
"GET": {
38+
RateLimitCategory.ORGANIZATION: RateLimit(
39+
limit=100, window=60
40+
), # 100 requests per minute per org
41+
}
42+
}
43+
44+
def get(self, request: Request, project) -> Response:
45+
"""
46+
Check for updates for a preprod artifact
47+
"""
48+
main_binary_identifier = request.GET.get("main_binary_identifier")
49+
if not main_binary_identifier:
50+
# Not implemented yet
51+
return Response(CheckForUpdatesApiResponse().dict())
52+
53+
try:
54+
preprod_artifact = PreprodArtifact.objects.filter(
55+
project=project, main_binary_identifier=main_binary_identifier
56+
).latest("date_added")
57+
except PreprodArtifact.DoesNotExist:
58+
return Response({"error": "Not found"}, status=404)
59+
60+
if preprod_artifact.build_version and preprod_artifact.build_number:
61+
current = InstallableBuildDetails(
62+
build_version=preprod_artifact.build_version,
63+
build_number=preprod_artifact.build_number,
64+
)
65+
else:
66+
current = None
67+
return Response(CheckForUpdatesApiResponse(current=current).dict())

src/sentry/preprod/api/endpoints/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,19 @@
1212
)
1313
from .project_preprod_artifact_update import ProjectPreprodArtifactUpdateEndpoint
1414
from .project_preprod_build_details import ProjectPreprodBuildDetailsEndpoint
15+
from .project_preprod_check_for_updates import ProjectPreprodArtifactCheckForUpdatesEndpoint
1516

1617
preprod_urlpatterns = [
1718
re_path(
1819
r"^(?P<organization_id_or_slug>[^/]+)/(?P<project_id_or_slug>[^/]+)/files/preprodartifacts/assemble/$",
1920
ProjectPreprodArtifactAssembleEndpoint.as_view(),
2021
name="sentry-api-0-assemble-preprod-artifact-files",
2122
),
23+
re_path(
24+
r"^(?P<organization_id_or_slug>[^/]+)/(?P<project_id_or_slug>[^/]+)/preprodartifacts/check-for-updates/$",
25+
ProjectPreprodArtifactCheckForUpdatesEndpoint.as_view(),
26+
name="sentry-api-0-project-preprod-check-for-updates",
27+
),
2228
re_path(
2329
r"^(?P<organization_id_or_slug>[^/]+)/(?P<project_id_or_slug>[^/]+)/files/preprodartifacts/(?P<artifact_id>[^/]+)/size-analysis/$",
2430
ProjectPreprodArtifactSizeAnalysisDownloadEndpoint.as_view(),

0 commit comments

Comments
 (0)