Skip to content

Commit f6d3d50

Browse files
authored
feat(preprod): Add codesigning type to check for updates filter (#103727)
Uses code signing type to return the most relevant update Closes https://linear.app/getsentry/issue/EME-653/use-provisioning-type-for-distribution-updates
1 parent 8e863ac commit f6d3d50

File tree

2 files changed

+207
-0
lines changed

2 files changed

+207
-0
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ def get(self, request: Request, project: Project) -> Response:
6666
provided_build_version = request.GET.get("build_version")
6767
provided_build_number = request.GET.get("build_number")
6868
provided_build_configuration = request.GET.get("build_configuration")
69+
provided_codesigning_type = request.GET.get("codesigning_type")
6970

7071
if not provided_app_id or not provided_platform or not provided_build_version:
7172
return Response({"error": "Missing required parameters"}, status=400)
@@ -105,6 +106,9 @@ def get_base_filters() -> dict[str, Any]:
105106
elif provided_platform == "ios":
106107
filter_kwargs["artifact_type"] = PreprodArtifact.ArtifactType.XCARCHIVE
107108

109+
if provided_codesigning_type:
110+
filter_kwargs["extras__codesigning_type"] = provided_codesigning_type
111+
108112
return filter_kwargs
109113

110114
try:
@@ -157,6 +161,10 @@ def get_base_filters() -> dict[str, Any]:
157161
new_build_filter_kwargs = get_base_filters()
158162
if preprod_artifact:
159163
new_build_filter_kwargs["build_configuration"] = preprod_artifact.build_configuration
164+
if preprod_artifact.extras:
165+
codesigning_type = preprod_artifact.extras.get("codesigning_type")
166+
if codesigning_type:
167+
new_build_filter_kwargs["extras__codesigning_type"] = codesigning_type
160168
elif build_configuration:
161169
new_build_filter_kwargs["build_configuration"] = build_configuration
162170
all_versions = (

tests/sentry/preprod/api/endpoints/test_project_preprod_check_for_updates.py

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,3 +442,202 @@ def test_missing_both_main_binary_identifier_and_build_number(self):
442442
"Either main_binary_identifier or build_number must be provided"
443443
in response.json()["error"]
444444
)
445+
446+
def test_codesigning_type_filters_current_artifact(self):
447+
"""Test that codesigning_type parameter filters the current artifact correctly"""
448+
# Create an iOS artifact with development codesigning
449+
self._create_ios_artifact(
450+
main_binary_identifier="test-identifier",
451+
build_version="1.0.0",
452+
build_number=42,
453+
extras={"codesigning_type": "development"},
454+
)
455+
456+
# Create another artifact with app-store codesigning
457+
self._create_ios_artifact(
458+
main_binary_identifier="test-identifier",
459+
build_version="1.0.0",
460+
build_number=42,
461+
extras={"codesigning_type": "app-store"},
462+
)
463+
464+
url = self._get_url()
465+
response = self.client.get(
466+
url
467+
+ "?app_id=com.example.app&platform=ios&build_version=1.0.0&main_binary_identifier=test-identifier&codesigning_type=development",
468+
format="json",
469+
HTTP_AUTHORIZATION=f"Bearer {self.api_token}",
470+
)
471+
472+
assert response.status_code == 200
473+
data = response.json()
474+
475+
# Should only find the development artifact
476+
assert data["current"] is not None
477+
assert data["current"]["build_version"] == "1.0.0"
478+
assert data["current"]["build_number"] == 42
479+
480+
def test_codesigning_type_filters_updates(self):
481+
"""Test that updates are filtered by the same codesigning_type as the current artifact"""
482+
# Create current iOS artifact with development codesigning
483+
self._create_ios_artifact(
484+
main_binary_identifier="test-identifier",
485+
build_version="1.0.0",
486+
build_number=42,
487+
extras={"codesigning_type": "development"},
488+
)
489+
490+
# Create update with development codesigning (should be returned)
491+
self._create_ios_artifact(
492+
main_binary_identifier="different-identifier",
493+
build_version="1.1.0",
494+
build_number=50,
495+
extras={"codesigning_type": "development"},
496+
)
497+
498+
# Create update with app-store codesigning (should NOT be returned)
499+
self._create_ios_artifact(
500+
main_binary_identifier="another-identifier",
501+
build_version="1.2.0",
502+
build_number=60,
503+
extras={"codesigning_type": "app-store"},
504+
)
505+
506+
url = self._get_url()
507+
response = self.client.get(
508+
url
509+
+ "?app_id=com.example.app&platform=ios&build_version=1.0.0&main_binary_identifier=test-identifier",
510+
format="json",
511+
HTTP_AUTHORIZATION=f"Bearer {self.api_token}",
512+
)
513+
514+
assert response.status_code == 200
515+
data = response.json()
516+
517+
assert data["current"] is not None
518+
assert data["current"]["build_version"] == "1.0.0"
519+
520+
# Should only return the development update (1.1.0), not app-store (1.2.0)
521+
assert data["update"] is not None
522+
assert data["update"]["build_version"] == "1.1.0"
523+
assert data["update"]["build_number"] == 50
524+
525+
def test_codesigning_type_no_matching_update(self):
526+
"""Test that no update is returned when codesigning_type doesn't match"""
527+
# Create current iOS artifact with development codesigning
528+
self._create_ios_artifact(
529+
main_binary_identifier="test-identifier",
530+
build_version="1.0.0",
531+
build_number=42,
532+
extras={"codesigning_type": "development"},
533+
)
534+
535+
# Create update with app-store codesigning only
536+
self._create_ios_artifact(
537+
main_binary_identifier="different-identifier",
538+
build_version="1.1.0",
539+
build_number=50,
540+
extras={"codesigning_type": "app-store"},
541+
)
542+
543+
url = self._get_url()
544+
response = self.client.get(
545+
url
546+
+ "?app_id=com.example.app&platform=ios&build_version=1.0.0&main_binary_identifier=test-identifier",
547+
format="json",
548+
HTTP_AUTHORIZATION=f"Bearer {self.api_token}",
549+
)
550+
551+
assert response.status_code == 200
552+
data = response.json()
553+
554+
assert data["current"] is not None
555+
assert data["current"]["build_version"] == "1.0.0"
556+
557+
# Should not return update because codesigning_type doesn't match
558+
assert data["update"] is None
559+
560+
def test_codesigning_type_with_build_configuration(self):
561+
"""Test that codesigning_type works correctly with build configurations"""
562+
debug_config, _ = PreprodBuildConfiguration.objects.get_or_create(
563+
project=self.project, name="debug"
564+
)
565+
566+
# Create current artifact with debug configuration and development codesigning
567+
self._create_ios_artifact(
568+
main_binary_identifier="test-identifier",
569+
build_version="1.0.0",
570+
build_number=42,
571+
build_configuration=debug_config,
572+
extras={"codesigning_type": "development"},
573+
)
574+
575+
# Create update with same configuration and codesigning type
576+
self._create_ios_artifact(
577+
main_binary_identifier="different-identifier",
578+
build_version="1.1.0",
579+
build_number=50,
580+
build_configuration=debug_config,
581+
extras={"codesigning_type": "development"},
582+
)
583+
584+
# Create update with same configuration but different codesigning type
585+
self._create_ios_artifact(
586+
main_binary_identifier="another-identifier",
587+
build_version="1.2.0",
588+
build_number=60,
589+
build_configuration=debug_config,
590+
extras={"codesigning_type": "app-store"},
591+
)
592+
593+
url = self._get_url()
594+
response = self.client.get(
595+
url
596+
+ "?app_id=com.example.app&platform=ios&build_version=1.0.0&main_binary_identifier=test-identifier&build_configuration=debug",
597+
format="json",
598+
HTTP_AUTHORIZATION=f"Bearer {self.api_token}",
599+
)
600+
601+
assert response.status_code == 200
602+
data = response.json()
603+
604+
assert data["current"] is not None
605+
assert data["current"]["build_version"] == "1.0.0"
606+
607+
# Should return 1.1.0 (matching codesigning_type), not 1.2.0
608+
assert data["update"] is not None
609+
assert data["update"]["build_version"] == "1.1.0"
610+
assert data["update"]["build_number"] == 50
611+
612+
def test_codesigning_type_provided_explicitly(self):
613+
"""Test that explicitly provided codesigning_type parameter is used for filtering"""
614+
# Create artifact with development codesigning
615+
self._create_ios_artifact(
616+
main_binary_identifier="test-identifier",
617+
build_version="1.0.0",
618+
build_number=42,
619+
extras={"codesigning_type": "development"},
620+
)
621+
622+
# Create artifact with app-store codesigning
623+
self._create_ios_artifact(
624+
main_binary_identifier="test-identifier",
625+
build_version="1.0.0",
626+
build_number=42,
627+
extras={"codesigning_type": "app-store"},
628+
)
629+
630+
# Request specifically for app-store
631+
url = self._get_url()
632+
response = self.client.get(
633+
url
634+
+ "?app_id=com.example.app&platform=ios&build_version=1.0.0&main_binary_identifier=test-identifier&codesigning_type=app-store",
635+
format="json",
636+
HTTP_AUTHORIZATION=f"Bearer {self.api_token}",
637+
)
638+
639+
assert response.status_code == 200
640+
data = response.json()
641+
642+
# Should find the app-store artifact
643+
assert data["current"] is not None

0 commit comments

Comments
 (0)