Skip to content

Commit c343478

Browse files
iamrajjoshigetsantry[bot]
authored andcommitted
✨ feat(integrations): add github domain checker (#14011)
Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
1 parent a21b785 commit c343478

File tree

3 files changed

+153
-0
lines changed

3 files changed

+153
-0
lines changed

docs/organization/integrations/source-code-mgmt/github/index.mdx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,24 @@ There are two types of GitHub integrations, so make sure you're choosing the cor
1212
- `https://ghe.example.com/`
1313

1414
For these accounts, follow the '[Installing GitHub Enterprise](#installing-github-enterprise)' instructions.
15+
16+
17+
### Check Your Domain
18+
19+
To determine which integration to use, enter your GitHub domain below:
20+
21+
<GitHubDomainChecker />
22+
23+
<br />
1524

1625
<Alert>
1726

1827
Sentry owner, manager, or admin permissions, and GitHub owner permissions are required to install this integration.
1928

2029
</Alert>
2130

31+
## Installing GitHub
32+
2233
1. Navigate to **Settings > Integrations > [GitHub](https://sentry.io/orgredirect/organizations/:orgslug/settings/integrations/github)**.
2334

2435
![Install GitHub integration](./img/github-install-page.png)
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
'use client';
2+
3+
import {useState} from 'react';
4+
5+
interface GitHubDomainCheckerProps {
6+
id?: string;
7+
}
8+
9+
export function GitHubDomainChecker({id}: GitHubDomainCheckerProps = {}) {
10+
const [domain, setDomain] = useState('');
11+
const [isValidDomain, setIsValidDomain] = useState(false);
12+
13+
// Safe function to check if domain is github.com or its subdomain
14+
const isValidGitHubDomain = (input_domain: string): boolean => {
15+
try {
16+
const url = new URL(
17+
input_domain.startsWith('http') ? input_domain : `https://${input_domain}`
18+
);
19+
const hostname = url.hostname.toLowerCase();
20+
21+
// Exact match for github.com or valid subdomain (like gist.github.com)
22+
return hostname === 'github.com' || hostname.endsWith('.github.com');
23+
} catch {
24+
return false;
25+
}
26+
};
27+
28+
// Safe function to check if it's an enterprise GitHub domain
29+
const isValidEnterpriseDomain = (input_domain: string): boolean => {
30+
try {
31+
const url = new URL(
32+
input_domain.startsWith('http') ? input_domain : `https://${input_domain}`
33+
);
34+
const hostname = url.hostname.toLowerCase();
35+
36+
// Must be a valid domain with TLD, but not github.com
37+
const domainPattern = /^[\w\-\.]+\.[\w]{2,}$/;
38+
return (
39+
domainPattern.test(hostname) &&
40+
!hostname.endsWith('.github.com') &&
41+
hostname !== 'github.com'
42+
);
43+
} catch {
44+
return false;
45+
}
46+
};
47+
48+
const isGitHubCom = (() => {
49+
const trimmedDomain = domain.toLowerCase().trim();
50+
if (!trimmedDomain) return false;
51+
52+
return isValidGitHubDomain(trimmedDomain);
53+
})();
54+
55+
const hasInput = domain.trim().length > 0;
56+
57+
// Validate domain format
58+
const validateDomain = (inputDomain: string) => {
59+
const trimmedDomain = inputDomain.trim();
60+
if (!trimmedDomain) {
61+
setIsValidDomain(false);
62+
return;
63+
}
64+
65+
// Check if it's a valid GitHub.com domain or subdomain
66+
if (isValidGitHubDomain(trimmedDomain)) {
67+
setIsValidDomain(true);
68+
return;
69+
}
70+
71+
// For enterprise, validate as proper domain
72+
if (isValidEnterpriseDomain(trimmedDomain)) {
73+
setIsValidDomain(true);
74+
return;
75+
}
76+
77+
setIsValidDomain(false);
78+
};
79+
80+
const handleDomainChange = ev => {
81+
const newDomain = ev.target.value;
82+
setDomain(newDomain);
83+
validateDomain(newDomain);
84+
};
85+
86+
// Improved input styling with dark mode support
87+
const inputClassName =
88+
'form-input w-full rounded-md border-[1.5px] focus:ring-2 focus:ring-accent-purple/20 border-gray-200 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-400';
89+
90+
// Use provided id or generate a fallback
91+
const inputId = id || `gh-domain-${Date.now()}`;
92+
93+
return (
94+
<div className="space-y-4 p-6 border border-gray-100 dark:border-gray-700 rounded">
95+
<div className="flex w-full">
96+
<div className="flex items-center min-w-[16ch] px-4">
97+
<label htmlFor={inputId} className="text-nowrap">
98+
GitHub Domain
99+
</label>
100+
</div>
101+
<input
102+
id={inputId}
103+
value={domain}
104+
placeholder="https://github.com or https://ghe.example.com"
105+
className={inputClassName}
106+
onChange={handleDomainChange}
107+
/>
108+
</div>
109+
110+
{hasInput && (
111+
<div className="mt-4 p-4 rounded-md border dark:border-gray-600">
112+
{isValidDomain ? (
113+
<div>
114+
<div className="text-sm font-medium mb-2">Recommended Installation:</div>
115+
{isGitHubCom ? (
116+
<div className="text-green-700 bg-green-50 dark:text-green-300 dark:bg-green-900/30 p-3 rounded-md">
117+
<div>
118+
<strong>GitHub</strong> - Use the standard GitHub integration for
119+
github.com
120+
</div>
121+
</div>
122+
) : (
123+
<div className="text-blue-700 bg-blue-50 dark:text-blue-300 dark:bg-blue-900/30 p-3 rounded-md">
124+
<div>
125+
<strong>GitHub Enterprise</strong> - Use GitHub Enterprise integration
126+
for your domain
127+
</div>
128+
</div>
129+
)}
130+
</div>
131+
) : (
132+
<div className="text-red-700 bg-red-50 dark:text-red-300 dark:bg-red-900/30 p-3 rounded-md">
133+
<strong>Invalid Domain</strong> - Please enter a valid GitHub domain or URL
134+
</div>
135+
)}
136+
</div>
137+
)}
138+
</div>
139+
);
140+
}

src/mdxComponents.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {DefinitionList} from './components/definitionList';
1313
import {DevDocsCardGrid} from './components/devDocsCardGrid';
1414
import DocImage from './components/docImage';
1515
import {Expandable} from './components/expandable';
16+
import {GitHubDomainChecker} from './components/githubDomainChecker';
1617
import {GuideGrid} from './components/guideGrid';
1718
import {JsBundleList} from './components/jsBundleList';
1819
import {LambdaLayerDetail} from './components/lambdaLayerDetail';
@@ -60,6 +61,7 @@ export function mdxComponents(
6061
SdkApi,
6162
TableOfContents,
6263
CreateGitHubAppForm,
64+
GitHubDomainChecker,
6365
ConfigValue,
6466
DefinitionList,
6567
Expandable,

0 commit comments

Comments
 (0)