@@ -1272,6 +1272,7 @@ def test_get_account_id_backfill_missing(self):
1272
1272
integration = Integration .objects .get (id = integration_id )
1273
1273
assert integration .metadata ["account_id" ] == 60591805
1274
1274
1275
+ @with_feature ("organizations:integrations-scm-multi-org" )
1275
1276
@with_feature ("organizations:github-multi-org" )
1276
1277
@responses .activate
1277
1278
@patch ("sentry.integrations.utils.metrics.EventLifecycle.record_event" )
@@ -1315,12 +1316,13 @@ def test_github_installation_calls_ui(self, mock_render, mock_record):
1315
1316
mock_render .assert_called_with (
1316
1317
request = ANY ,
1317
1318
pipeline_name = "githubInstallationSelect" ,
1318
- props = {"installation_info" : installations },
1319
+ props = {"installation_info" : installations , "has_scm_multi_org" : True },
1319
1320
)
1320
1321
1321
1322
# SLO assertions
1322
1323
assert_success_metric (mock_record )
1323
1324
1325
+ @with_feature ("organizations:integrations-scm-multi-org" )
1324
1326
@with_feature ("organizations:github-multi-org" )
1325
1327
@responses .activate
1326
1328
@patch ("sentry.integrations.utils.metrics.EventLifecycle.record_event" )
@@ -1405,6 +1407,7 @@ def test_github_installation_stores_chosen_installation(self, mock_record):
1405
1407
# SLO assertions
1406
1408
assert_success_metric (mock_record )
1407
1409
1410
+ @with_feature ("organizations:integrations-scm-multi-org" )
1408
1411
@with_feature ("organizations:github-multi-org" )
1409
1412
@responses .activate
1410
1413
@patch ("sentry.integrations.utils.metrics.EventLifecycle.record_event" )
@@ -1449,7 +1452,7 @@ def test_github_installation_fails_on_invalid_installation(self, mock_record):
1449
1452
1450
1453
self .assertTemplateUsed (resp , "sentry/integrations/github-integration-failed.html" )
1451
1454
assert (
1452
- b'{"success":false,"data":{"error":"User does not have access to given installation"}'
1455
+ b'{"success":false,"data":{"error":"User does not have access to given installation. "}'
1453
1456
in resp .content
1454
1457
)
1455
1458
assert (
@@ -1476,6 +1479,128 @@ def test_github_installation_fails_on_invalid_installation(self, mock_record):
1476
1479
1477
1480
assert_failure_metric (mock_record , GitHubInstallationError .INVALID_INSTALLATION )
1478
1481
1482
+ @with_feature (
1483
+ {"organizations:github-multi-org" : True , "organizations:integrations-scm-multi-org" : False }
1484
+ )
1485
+ @responses .activate
1486
+ @patch ("sentry.integrations.utils.metrics.EventLifecycle.record_event" )
1487
+ @patch .object (PipelineView , "render_react_view" , return_value = HttpResponse ())
1488
+ def test_github_installation_calls_ui_no_biz_plan (self , mock_render , mock_record ):
1489
+ self ._setup_with_existing_installations ()
1490
+ installations = [
1491
+ {
1492
+ "installation_id" : "1" ,
1493
+ "github_account" : "santry" ,
1494
+ "avatar_url" : "https://github.com/knobiknows/all-the-bufo/raw/main/all-the-bufo/bufo-pitchforks.png" ,
1495
+ },
1496
+ {
1497
+ "installation_id" : "2" ,
1498
+ "github_account" : "bufo-bot" ,
1499
+ "avatar_url" : "https://github.com/knobiknows/all-the-bufo/raw/main/all-the-bufo/bufo-pog.png" ,
1500
+ },
1501
+ {
1502
+ "installation_id" : "-1" ,
1503
+ "github_account" : "Integrate with a new GitHub organization" ,
1504
+ "avatar_url" : "" ,
1505
+ },
1506
+ ]
1507
+
1508
+ resp = self .client .get (self .init_path )
1509
+ assert resp .status_code == 302
1510
+ redirect = urlparse (resp ["Location" ])
1511
+ assert redirect .scheme == "https"
1512
+ assert redirect .netloc == "github.com"
1513
+ assert redirect .path == "/login/oauth/authorize"
1514
+ assert (
1515
+ redirect .query
1516
+ == f"client_id=github-client-id&state={ self .pipeline .signature } &redirect_uri=http://testserver/extensions/github/setup/"
1517
+ )
1518
+ resp = self .client .get (
1519
+ "{}?{}" .format (
1520
+ self .setup_path ,
1521
+ urlencode ({"code" : "12345678901234567890" , "state" : self .pipeline .signature }),
1522
+ )
1523
+ )
1524
+ mock_render .assert_called_with (
1525
+ request = ANY ,
1526
+ pipeline_name = "githubInstallationSelect" ,
1527
+ props = {"installation_info" : installations , "has_scm_multi_org" : False },
1528
+ )
1529
+
1530
+ # SLO assertions
1531
+ assert_success_metric (mock_record )
1532
+
1533
+ @with_feature (
1534
+ {"organizations:github-multi-org" : True , "organizations:integrations-scm-multi-org" : False }
1535
+ )
1536
+ @responses .activate
1537
+ @patch ("sentry.integrations.utils.metrics.EventLifecycle.record_event" )
1538
+ @patch .object (PipelineView , "render_react_view" , return_value = HttpResponse ())
1539
+ def test_errors_when_invalid_access_to_multi_org (self , mock_render , mock_record ):
1540
+ self ._setup_with_existing_installations ()
1541
+ installations = [
1542
+ {
1543
+ "installation_id" : "1" ,
1544
+ "github_account" : "santry" ,
1545
+ "avatar_url" : "https://github.com/knobiknows/all-the-bufo/raw/main/all-the-bufo/bufo-pitchforks.png" ,
1546
+ },
1547
+ {
1548
+ "installation_id" : "2" ,
1549
+ "github_account" : "bufo-bot" ,
1550
+ "avatar_url" : "https://github.com/knobiknows/all-the-bufo/raw/main/all-the-bufo/bufo-pog.png" ,
1551
+ },
1552
+ {
1553
+ "installation_id" : "-1" ,
1554
+ "github_account" : "Integrate with a new GitHub organization" ,
1555
+ "avatar_url" : "" ,
1556
+ },
1557
+ ]
1558
+
1559
+ resp = self .client .get (self .init_path )
1560
+ assert resp .status_code == 302
1561
+ redirect = urlparse (resp ["Location" ])
1562
+ assert redirect .scheme == "https"
1563
+ assert redirect .netloc == "github.com"
1564
+ assert redirect .path == "/login/oauth/authorize"
1565
+ assert (
1566
+ redirect .query
1567
+ == f"client_id=github-client-id&state={ self .pipeline .signature } &redirect_uri=http://testserver/extensions/github/setup/"
1568
+ )
1569
+ resp = self .client .get (
1570
+ "{}?{}" .format (
1571
+ self .setup_path ,
1572
+ urlencode ({"code" : "12345678901234567890" , "state" : self .pipeline .signature }),
1573
+ )
1574
+ )
1575
+ mock_render .assert_called_with (
1576
+ request = ANY ,
1577
+ pipeline_name = "githubInstallationSelect" ,
1578
+ props = {"installation_info" : installations , "has_scm_multi_org" : False },
1579
+ )
1580
+
1581
+ # We rendered the GithubOrganizationSelection UI and the user chose to skip
1582
+ resp = self .client .get (
1583
+ "{}?{}" .format (
1584
+ self .setup_path ,
1585
+ urlencode (
1586
+ {
1587
+ "code" : "12345678901234567890" ,
1588
+ "state" : self .pipeline .signature ,
1589
+ "chosen_installation_id" : "12345" ,
1590
+ }
1591
+ ),
1592
+ )
1593
+ )
1594
+
1595
+ self .assertTemplateUsed (resp , "sentry/integrations/github-integration-failed.html" )
1596
+ assert (
1597
+ b'{"success":false,"data":{"error":"Your organization does not have access to this feature."}}'
1598
+ in resp .content
1599
+ )
1600
+ assert b'window.opener.postMessage({"success":false' in resp .content
1601
+ assert_failure_metric (mock_record , GitHubInstallationError .FEATURE_NOT_AVAILABLE )
1602
+
1603
+ @with_feature ("organizations:integrations-scm-multi-org" )
1479
1604
@with_feature ("organizations:github-multi-org" )
1480
1605
@responses .activate
1481
1606
@patch ("sentry.integrations.utils.metrics.EventLifecycle.record_event" )
@@ -1543,6 +1668,7 @@ def test_github_installation_skips_chosen_installation(self, mock_record):
1543
1668
# SLO assertions
1544
1669
assert_success_metric (mock_record )
1545
1670
1671
+ @with_feature ("organizations:integrations-scm-multi-org" )
1546
1672
@with_feature ("organizations:github-multi-org" )
1547
1673
@responses .activate
1548
1674
def test_github_installation_gets_owner_orgs (self ):
@@ -1554,6 +1680,7 @@ def test_github_installation_gets_owner_orgs(self):
1554
1680
1555
1681
assert owner_orgs == ["santry" ]
1556
1682
1683
+ @with_feature ("organizations:integrations-scm-multi-org" )
1557
1684
@with_feature ("organizations:github-multi-org" )
1558
1685
@responses .activate
1559
1686
def test_github_installation_filters_valid_installations (self ):
0 commit comments