Documenter et typer un endpoint API Sentry
Ajouter ou corriger la documentation OpenAPI pour un endpoint Sentry avec drf-spectacular. La référence complète se trouve à https://develop.sentry.dev/backend/api/public/, la section la plus utile pour vous sera https://develop.sentry.dev/backend/api/public/#5-method-decorator. Cette skill capture les leçons non évidentes en supplément. L'essentiel du travail consiste à faire correspondre le schéma déclaré à ce que l'endpoint retourne réellement. Avant de documenter, identifiez quelle classe d'endpoint sert la route et ce qu'elle fait ; l'outil MCP qui l'appelle est généralement le moyen le plus rapide de confirmer son comportement. Promouvoir un endpoint PRIVATE/EXPERIMENTAL en PUBLIC est une application (voir ci-dessous).
Workflow
@extend_schema(tags=[...])au niveau de la classe — utilisez l'entréeOPENAPI_TAGSexistante la plus proche.@extend_schema(operation_id=..., parameters=[...], responses={...}, examples=...)au niveau de la méthode.- Réutilisez
src/sentry/apidocs/parameters.pyetexamples/*.py; assurez-vous queowner = ApiOwner.<TEAM>est défini. - Si un
api-docs/paths/**/*.jsonhérité couvre le chemin, supprimez-le (voir leçon 4). - Validez, puis vérifiez par rapport à l'endpoint en direct (leçon 1).
Leçons
1. Comparez attentivement ce que le code fait vs les types déclarés
Idéalement, appelez l'endpoint en direct avec un vrai token et faites un diff des clés et types par rapport à votre TypedDict. Les serializers sont parfois imprécis. Guettez les counts qui reviennent en float au lieu d'integer, les IDs déclarés int émis en string, les types imbriqués déclarant un mauvais nombre de champs. Corrigez le type déclaré pour qu'il corresponde au runtime.
curl -s -H "Authorization: Bearer $TOKEN" "https://us.sentry.io/api/0/<endpoint>" | jq 'keys'
2. Réutilisez le type de réponse canonique
Faites correspondre le mixin XxxResponseOptional(TypedDict, total=False) de la base de code (la classe principale déclare les champs requis). Nullable-vs-absent : T | None = clé toujours présente, valeur peut être null ; NotRequired[T] = clé définie seulement sous condition (par ex. un paramètre query expand). Réutilisez le type canonique existant au lieu de re-déclarer une deuxième ou troisième copie dans un *_types.py. S'il n'y a pas de type canonique propre à réutiliser (par ex. une payload proxifiée depuis un autre service comme vroom/profiling), typez-la dict[str, Any] plutôt que d'inventer un nouveau miroir, et confirmez la forme depuis le repo du service propriétaire, pas juste le serializer.
3. Déduisez le type. Évitez cast et # type: ignore
Quand un serializer retourne un type de base plus des champs supplémentaires, refactorisez le code producteur pour que le type de réponse soit déduit plutôt que forcé.
4. La migration de doc hérité est tout-ou-rien par chemin
Supprimez le fichier api-docs/paths/**/*.json ET sa $ref dans api-docs/openapi.json. Le APPEND_PATHS de drf-spectacular ne fusionne pas les méthodes HTTP, donc une fois qu'une méthode sur un chemin utilise @extend_schema, toutes les méthodes héritées sur ce chemin disparaissent — migrez chaque méthode du chemin en un seul commit.
Promotion en PUBLIC
Faites le workflow ci-dessus, puis sur l'endpoint concret uniquement (laissez les siblings PRIVATE) :
- Augmentez
publish_status[<METHOD>]→PUBLICet définissezowner = ApiOwner.<TEAM>. - Supprimez la méthode de
API_OWNERSHIP_ALLOWLIST_DONT_MODIFYdans le même changement que le flip. - Si l'endpoint est redondant ou en cours de renommage, supprimez ou dépréciez d'abord l'ancienne version dans son propre changement, puis empilez la publication par-dessus.
- Notez dans la PR si les scopes s'élargissent (
event:read→event:{admin,read,write}) — c'est drf-spectacular qui régénère depuispermission_classes, documentation seulement.
Le changement atteint le SDK @sentry/api / MCP seulement après la régénération de sentry-api-schema en aval.
Valider
make build-api-docs
pnpm run validate-api-examples
.venv/bin/pytest -q --reuse-db tests/apidocs/endpoints/<area>/test_<name>.py
.venv/bin/prek run -q --files <changed paths>