feat: Issues disabled warning banner (#682)

* Apply patch [skip ci]

* Apply patch [skip ci]

* Apply patch [skip ci]

* Apply patch [skip ci]

* Apply patch [skip ci]

* Empty commit to trigger CI

* cr

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: bracesproul <braceasproul@gmail.com>
This commit is contained in:
open-swe[bot] 2025-08-06 10:53:29 -07:00 • committed by GitHub
parent 8af9ae9e76
commit d00dde3ada
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 93 additions and 1 deletions

View file

@ -97,6 +97,8 @@ export async function GET(request: NextRequest) {
html_url: repo.html_url,
default_branch: repo.default_branch,
permissions: repo.permissions,
fork: repo.fork,
has_issues: repo.has_issues,
}));
return NextResponse.json({

View file

@ -0,0 +1,57 @@
"use client";
import { AlertTriangle } from "lucide-react";
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
import { useGitHubAppProvider } from "@/providers/GitHubApp";
import { repoHasIssuesEnabled } from "@/lib/repo-has-issues";
const GITHUB_DOCS_LINK_ENABLING_ISSUES =
"https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/disabling-issues";
export function IssuesRequiredBanner() {
const { selectedRepository, repositories } = useGitHubAppProvider();
const currentRepo = repositories.find(
(repo) =>
selectedRepository &&
repo.full_name ===
`${selectedRepository.owner}/${selectedRepository.repo}`,
);
// If the repo has issues enabled, we support it.
if (
!selectedRepository ||
!currentRepo ||
repoHasIssuesEnabled(currentRepo)
) {
return null;
}
return (
<Alert
variant="warning"
className="relative"
>
<AlertTriangle className="h-4 w-4" />
<AlertTitle>Issues Must Be Enabled</AlertTitle>
<AlertDescription>
<p>
Open SWE requires issues to be enabled on the repository. Please
enable issues on the repository to use Open SWE.
</p>
<p>
See{" "}
<a
className="font-semibold underline underline-offset-2"
href={GITHUB_DOCS_LINK_ENABLING_ISSUES}
target="_blank"
>
here
</a>{" "}
for how to enable issues (docs show how to disable them, but the
process is the same).
</p>
</AlertDescription>
</Alert>
);
}

View file

@ -17,6 +17,7 @@ import { ThemeToggle } from "../theme-toggle";
import { ThreadCard, ThreadCardLoading } from "./thread-card";
import { GitHubInstallationBanner } from "../github/installation-banner";
import { ApiKeyBanner } from "../api-key-banner";
import { IssuesRequiredBanner } from "../github/forked-repository-banner";
import { QuickActions } from "./quick-actions";
import { DraftsSection } from "./drafts-section";
import { MANAGER_GRAPH_ID } from "@open-swe/shared/constants";
@ -142,6 +143,7 @@ export function DefaultView({ threads, threadsLoading }: DefaultViewProps) {
<div className="mx-auto max-w-4xl space-y-6 p-4">
<GitHubInstallationBanner />
<ApiKeyBanner />
<IssuesRequiredBanner />
{/* Terminal Chat Input */}
<Card
className={cn(

View file

@ -23,6 +23,7 @@ import { useDraftStorage } from "@/hooks/useDraftStorage";
import { hasApiKeySet } from "@/lib/api-keys";
import { useUser } from "@/hooks/useUser";
import { isAllowedUser } from "@open-swe/shared/github/allowed-users";
import { repoHasIssuesEnabled } from "@/lib/repo-has-issues";
interface TerminalInputProps {
placeholder?: string;
@ -74,7 +75,7 @@ export function TerminalInput({
const { push } = useRouter();
const { message, setMessage, clearCurrentDraft } = useDraftStorage();
const { getConfig } = useConfigStore();
const { selectedRepository } = useGitHubAppProvider();
const { selectedRepository, repositories } = useGitHubAppProvider();
const [loading, setLoading] = useState(false);
const { user, isLoading: isUserLoading } = useUser();
@ -112,6 +113,24 @@ export function TerminalInput({
return;
}
const selectedRepo = repositories.find(
(repo) =>
repo.full_name ===
`${selectedRepository.owner}/${selectedRepository.repo}`,
);
const issuesDisabled = selectedRepo && !repoHasIssuesEnabled(selectedRepo);
if (issuesDisabled) {
toast.error(
"Open SWE requires issues to be enabled on the repository. Please enable issues on the repository to use Open SWE.",
{
richColors: true,
closeButton: true,
duration: 30_000,
},
);
return;
}
setLoading(true);
const trimmedMessage = message.trim();

View file

@ -0,0 +1,10 @@
import { Repository } from "@/utils/github";
/**
* Returns true if the repository has issues enabled
* @param repo The repository to check
* @returns True if the repository has issues enabled
*/
export function repoHasIssuesEnabled(repo: Repository): boolean {
return repo.has_issues;
}

View file

@ -203,6 +203,7 @@ export interface Repository {
full_name: string;
description: string | null;
private: boolean;
fork: boolean;
html_url: string;
default_branch: string;
permissions: {
@ -212,6 +213,7 @@ export interface Repository {
triage: boolean;
pull: boolean;
};
has_issues: boolean;
}
/**