Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion develop-docs/integrations/github.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ For local development make sure to use your ngrok URL as the prefix.
</Alert>

<CreateGitHubAppForm
url="https://github.com/organizations/:org/settings/apps/new?name=:org-Sentry-Integration&public=false&members=read&emails=read&administration=read&contents=read&issues=write&pull_requests=write&repository_hooks=write&url=:url-prefix&callback_url=:url-prefix%2Fauth%2Fsso%2F&setup_url=:url-prefix%2Fextensions%2Fgithub%2Fsetup%2F&webhook_url=:url-prefix%2Fextensions%2Fgithub%2Fwebhook%2F&events[]=push&events[]=pull_request&webhook_active=true"
url="https://github.com/organizations/:org/settings/apps/new?name=:org-Sentry-Integration&public=false&members=read&emails=read&administration=read&contents=read&checks=write&statuses=write&issues=write&pull_requests=write&repository_hooks=write&url=:url-prefix&callback_urls[]=:url-prefix%2Fauth%2Fsso%2F&callback_urls[]=:url-prefix%2Fextensions%2Fgithub%2Fsetup%2F&setup_url=:url-prefix%2Fextensions%2Fgithub%2Fsetup%2F&webhook_url=:url-prefix%2Fextensions%2Fgithub%2Fwebhook%2F&events[]=push&events[]=pull_request&webhook_active=true"
defaultOrg="your-organization"
defaultUrlPrefix="https://your-sentry-url-prefix.com"
/>
Expand Down
2 changes: 1 addition & 1 deletion develop-docs/self-hosted/configuration/sso.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ As of [Sentry 10](https://github.com/getsentry/self-hosted/releases/tag/10.0.1),
The GitHub App name must not contain any spaces.
</Alert>

<CreateGitHubAppForm url="https://github.com/organizations/:org/settings/apps/new?name=:org-Sentry-Integration&public=false&members=read&emails=read&administration=read&contents=read&issues=write&pull_requests=write&repository_hooks=write&url=:url-prefix&callback_url=:url-prefix%2Fauth%2Fsso%2F&setup_url=:url-prefix%2Fextensions%2Fgithub%2Fsetup%2F&webhook_url=:url-prefix%2Fextensions%2Fgithub%2Fwebhook%2F&events[]=push&events[]=pull_request&webhook_active=true" defaultOrg="your-organization" defaultUrlPrefix="https://your-sentry-url-prefix.com" />
<CreateGitHubAppForm url="https://github.com/organizations/:org/settings/apps/new?name=:org-Sentry-Integration&public=false&members=read&emails=read&administration=read&contents=read&issues=write&pull_requests=write&repository_hooks=write&url=:url-prefix&callback_urls[]=:url-prefix%2Fauth%2Fsso%2F&callback_urls[]=:url-prefix%2Fextensions%2Fgithub%2Fsetup%2F&setup_url=:url-prefix%2Fextensions%2Fgithub%2Fsetup%2F&webhook_url=:url-prefix%2Fextensions%2Fgithub%2Fwebhook%2F&events[]=push&events[]=pull_request&webhook_active=true" defaultOrg="your-organization" defaultUrlPrefix="https://your-sentry-url-prefix.com" />


If the form above does not work for you, you need the following settings for your GitHub Application:
Expand Down
80 changes: 64 additions & 16 deletions src/components/createGitHubAppForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,85 @@ import {Button} from '@radix-ui/themes';

const MAX_COMPONENTS_ON_PAGE = 100;

type AccountType = 'personal' | 'organization';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks great. I didn't realize there were two ways of doing this.

When would someone prefer personal vs organization?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well in my case I don't have an organisation account so I created the GitHub app on my own personal GitHub account, I didn't have permissions to do this on our main Sentry account.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah exactly I was thinking a note saying that if you are an individual or testing you should do the personal otherwise use organization.
On second thought maybe that's too much info. It is good as is!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Funnily enough the Sentry bot said the same thing, I think it's self explanatory tbh.


export function CreateGitHubAppForm({url, defaultOrg, defaultUrlPrefix}) {
const [accountType, setAccountType] = useState<AccountType>('organization');
const [orgSlug, setOrgSlug] = useState('');
const [urlPrefix, setUrlPrefix] = useState('');
const renderedUrl = url
.replace(/:org(?=\W)/g, orgSlug)
.replace(/:url-prefix(?=\W)/g, encodeURIComponent(urlPrefix));

const isPersonal = accountType === 'personal';

const renderedUrl = (() => {
let processedUrl = url;
if (isPersonal) {
// For personal accounts, remove the organizations/:org/ path segment
processedUrl = processedUrl
.replace('organizations/:org/', '')
.replace(':org-Sentry', 'Sentry');
} else {
processedUrl = processedUrl.replace(/:org(?=\W)/g, orgSlug);
}
return processedUrl.replace(/:url-prefix(?=\W)/g, encodeURIComponent(urlPrefix));
})();

const inputClassName =
'form-input w-full rounded-md border-[1.5px] focus:ring-2 focus:ring-accent-purple/20 border-gray-200';
'form-input w-full rounded-md border-[1.5px] focus:ring-2 focus:ring-accent-purple/20 border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 placeholder:text-gray-400 dark:placeholder:text-gray-500';
// This is to avoid in case multiple instances of this component are used on the page
const randomCounter = Math.round(Math.random() * MAX_COMPONENTS_ON_PAGE);

const isValid = isPersonal ? !!urlPrefix : !!orgSlug && !!urlPrefix;

return (
<div className="space-y-4 p-6 border border-gray-100 rounded">
<div className="space-y-4 p-6 border border-gray-200 dark:border-gray-700 rounded">
<div className="flex w-full">
<div className="flex items-center min-w-[16ch] px-4">
<label htmlFor={`gh-org-slug-${randomCounter}`} className="text-nowrap">
GitHub Org Slug
<span className="text-nowrap">Account Type</span>
</div>
<div className="flex gap-4">
<label className="flex items-center gap-2 cursor-pointer">
<input
type="radio"
name={`account-type-${randomCounter}`}
value="organization"
checked={accountType === 'organization'}
onChange={() => setAccountType('organization')}
className="accent-accent-purple"
/>
Organization
</label>
<label className="flex items-center gap-2 cursor-pointer">
<input
type="radio"
name={`account-type-${randomCounter}`}
value="personal"
checked={accountType === 'personal'}
onChange={() => setAccountType('personal')}
className="accent-accent-purple"
/>
Personal
</label>
</div>
<input
id={`gh-org-slug-${randomCounter}`}
value={orgSlug}
placeholder={defaultOrg}
className={inputClassName}
onChange={ev => setOrgSlug(ev.target.value)}
/>
</div>
{!isPersonal && (
<div className="flex w-full">
<div className="flex items-center min-w-[16ch] px-4">
<label htmlFor={`gh-org-slug-${randomCounter}`} className="text-nowrap">
GitHub Org Slug
</label>
</div>
<input
id={`gh-org-slug-${randomCounter}`}
value={orgSlug}
placeholder={defaultOrg}
className={inputClassName}
onChange={ev => setOrgSlug(ev.target.value)}
/>
</div>
)}
<div className="flex w-full">
<div className="flex items-center min-w-[16ch] px-4">
<label htmlFor={`gh-org-slug-${randomCounter}`} className="text-nowrap">
<label htmlFor={`sentry-url-prefix-${randomCounter}`} className="text-nowrap">
Sentry <code>url-prefix</code>
</label>
</div>
Expand All @@ -54,7 +102,7 @@ export function CreateGitHubAppForm({url, defaultOrg, defaultUrlPrefix}) {
type="button"
size="3"
onClick={() => window.open(renderedUrl, '_blank', 'noopener')}
disabled={!orgSlug || !urlPrefix}
disabled={!isValid}
className="rounded-md"
>
Create GitHub App
Expand Down
Loading