(request, organisation_pk: int)
| 303 | @permission_classes([IsAuthenticated, HasPermissionToGithubConfiguration]) |
| 304 | @github_api_call_error_handler(error="Failed to create GitHub cleanup issue.") |
| 305 | def create_cleanup_issue(request, organisation_pk: int) -> Response: # type: ignore[no-untyped-def] |
| 306 | serializer = CreateCleanupIssueSerializer(data=request.data) |
| 307 | if not serializer.is_valid(): |
| 308 | return Response( |
| 309 | {"error": serializer.errors}, status=status.HTTP_400_BAD_REQUEST |
| 310 | ) |
| 311 | |
| 312 | github_pat: str = settings.FEATURE_LIFECYCLE_GITHUB_PAT |
| 313 | if not github_pat: |
| 314 | return Response( |
| 315 | data={"detail": "GitHub PAT is not configured."}, |
| 316 | status=status.HTTP_400_BAD_REQUEST, |
| 317 | ) |
| 318 | |
| 319 | feature_id: int = serializer.validated_data["feature_id"] |
| 320 | |
| 321 | # Validate the feature exists and belongs to this org. |
| 322 | try: |
| 323 | feature = Feature.objects.get( |
| 324 | id=feature_id, |
| 325 | project__organisation_id=organisation_pk, |
| 326 | ) |
| 327 | except Feature.DoesNotExist: |
| 328 | return Response( |
| 329 | data={"detail": "Feature not found in this organisation."}, |
| 330 | status=status.HTTP_404_NOT_FOUND, |
| 331 | ) |
| 332 | |
| 333 | # Get code references for the feature across all repositories. |
| 334 | summaries = [ |
| 335 | summary |
| 336 | for summary in get_code_references_for_feature_flag(feature) |
| 337 | if summary.code_references |
| 338 | ] |
| 339 | if not summaries: |
| 340 | return Response( |
| 341 | data={"detail": "No code references found for this feature."}, |
| 342 | status=status.HTTP_400_BAD_REQUEST, |
| 343 | ) |
| 344 | |
| 345 | issue_title = CLEANUP_ISSUE_TITLE % feature.name |
| 346 | |
| 347 | for summary in summaries: |
| 348 | # Format code references as markdown list. |
| 349 | references_text = "\n".join( |
| 350 | f"- [`{ref.file_path}#L{ref.line_number}`]({ref.permalink})" |
| 351 | for ref in summary.code_references |
| 352 | ) |
| 353 | issue_body = CLEANUP_ISSUE_BODY % (feature.name, references_text) |
| 354 | |
| 355 | # Parse owner/name from repository_url. |
| 356 | url_parts = summary.repository_url.rstrip("/").split("/") |
| 357 | owner = url_parts[-2] |
| 358 | repo = url_parts[-1] |
| 359 | |
| 360 | api_url = _get_github_api_url(summary.repository_url) |
| 361 | github_response = create_github_issue( |
| 362 | github_pat=github_pat, |
nothing calls this directly
no test coverage detected
searching dependent graphs…