Skip to content

Commit 0f47961

Browse files
authored
Merge pull request AndyMik90#24 from mojaray2k/fix/github-org-repo-support
Fix GitHub organization repository support
2 parents 9299ee1 + c9745b6 commit 0f47961

File tree

5 files changed

+106
-15
lines changed

5 files changed

+106
-15
lines changed

auto-claude-ui/src/main/ipc-handlers/github/issue-handlers.ts

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ipcMain } from 'electron';
66
import { IPC_CHANNELS } from '../../../shared/constants';
77
import type { IPCResult, GitHubIssue } from '../../../shared/types';
88
import { projectStore } from '../../project-store';
9-
import { getGitHubConfig, githubFetch } from './utils';
9+
import { getGitHubConfig, githubFetch, normalizeRepoReference } from './utils';
1010
import type { GitHubAPIIssue, GitHubAPIComment } from './types';
1111

1212
/**
@@ -57,16 +57,32 @@ export function registerGetIssues(): void {
5757
}
5858

5959
try {
60+
const normalizedRepo = normalizeRepoReference(config.repo);
61+
if (!normalizedRepo) {
62+
return {
63+
success: false,
64+
error: 'Invalid repository format. Use owner/repo or GitHub URL.'
65+
};
66+
}
67+
6068
const issues = await githubFetch(
6169
config.token,
62-
`/repos/${config.repo}/issues?state=${state}&per_page=100&sort=updated`
63-
) as GitHubAPIIssue[];
70+
`/repos/${normalizedRepo}/issues?state=${state}&per_page=100&sort=updated`
71+
);
72+
73+
// Ensure issues is an array
74+
if (!Array.isArray(issues)) {
75+
return {
76+
success: false,
77+
error: 'Unexpected response format from GitHub API'
78+
};
79+
}
6480

6581
// Filter out pull requests
66-
const issuesOnly = issues.filter(issue => !issue.pull_request);
82+
const issuesOnly = issues.filter((issue: GitHubAPIIssue) => !issue.pull_request);
6783

68-
const result: GitHubIssue[] = issuesOnly.map(issue =>
69-
transformIssue(issue, config.repo)
84+
const result: GitHubIssue[] = issuesOnly.map((issue: GitHubAPIIssue) =>
85+
transformIssue(issue, normalizedRepo)
7086
);
7187

7288
return { success: true, data: result };
@@ -98,12 +114,20 @@ export function registerGetIssue(): void {
98114
}
99115

100116
try {
117+
const normalizedRepo = normalizeRepoReference(config.repo);
118+
if (!normalizedRepo) {
119+
return {
120+
success: false,
121+
error: 'Invalid repository format. Use owner/repo or GitHub URL.'
122+
};
123+
}
124+
101125
const issue = await githubFetch(
102126
config.token,
103-
`/repos/${config.repo}/issues/${issueNumber}`
127+
`/repos/${normalizedRepo}/issues/${issueNumber}`
104128
) as GitHubAPIIssue;
105129

106-
const result = transformIssue(issue, config.repo);
130+
const result = transformIssue(issue, normalizedRepo);
107131

108132
return { success: true, data: result };
109133
} catch (error) {
@@ -134,9 +158,17 @@ export function registerGetIssueComments(): void {
134158
}
135159

136160
try {
161+
const normalizedRepo = normalizeRepoReference(config.repo);
162+
if (!normalizedRepo) {
163+
return {
164+
success: false,
165+
error: 'Invalid repository format. Use owner/repo or GitHub URL.'
166+
};
167+
}
168+
137169
const comments = await githubFetch(
138170
config.token,
139-
`/repos/${config.repo}/issues/${issueNumber}/comments`
171+
`/repos/${normalizedRepo}/issues/${issueNumber}/comments`
140172
) as GitHubAPIComment[];
141173

142174
return { success: true, data: comments };

auto-claude-ui/src/main/ipc-handlers/github/repository-handlers.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ipcMain } from 'electron';
66
import { IPC_CHANNELS } from '../../../shared/constants';
77
import type { IPCResult, GitHubRepository, GitHubSyncStatus } from '../../../shared/types';
88
import { projectStore } from '../../project-store';
9-
import { getGitHubConfig, githubFetch } from './utils';
9+
import { getGitHubConfig, githubFetch, normalizeRepoReference } from './utils';
1010
import type { GitHubAPIRepository } from './types';
1111

1212
/**
@@ -33,16 +33,28 @@ export function registerCheckConnection(): void {
3333
}
3434

3535
try {
36+
// Normalize repo reference (handles full URLs, git URLs, etc.)
37+
const normalizedRepo = normalizeRepoReference(config.repo);
38+
if (!normalizedRepo) {
39+
return {
40+
success: true,
41+
data: {
42+
connected: false,
43+
error: 'Invalid repository format. Use owner/repo or GitHub URL.'
44+
}
45+
};
46+
}
47+
3648
// Fetch repo info
3749
const repoData = await githubFetch(
3850
config.token,
39-
`/repos/${config.repo}`
51+
`/repos/${normalizedRepo}`
4052
) as { full_name: string; description?: string };
4153

4254
// Count open issues
4355
const issuesData = await githubFetch(
4456
config.token,
45-
`/repos/${config.repo}/issues?state=open&per_page=1`
57+
`/repos/${normalizedRepo}/issues?state=open&per_page=1`
4658
) as unknown[];
4759

4860
const openCount = Array.isArray(issuesData) ? issuesData.length : 0;
@@ -71,7 +83,7 @@ export function registerCheckConnection(): void {
7183
}
7284

7385
/**
74-
* Get list of GitHub repositories
86+
* Get list of GitHub repositories (personal + organization)
7587
*/
7688
export function registerGetRepositories(): void {
7789
ipcMain.handle(
@@ -88,9 +100,11 @@ export function registerGetRepositories(): void {
88100
}
89101

90102
try {
103+
// Fetch user's personal + organization repos
104+
// affiliation parameter includes: owner, collaborator, organization_member
91105
const repos = await githubFetch(
92106
config.token,
93-
'/user/repos?per_page=100&sort=updated'
107+
'/user/repos?per_page=100&sort=updated&affiliation=owner,collaborator,organization_member'
94108
) as GitHubAPIRepository[];
95109

96110
const result: GitHubRepository[] = repos.map(repo => ({

auto-claude-ui/src/main/ipc-handlers/github/utils.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,32 @@ export function getGitHubConfig(project: Project): GitHubConfig | null {
5454
}
5555
}
5656

57+
/**
58+
* Normalize a GitHub repository reference to owner/repo format
59+
* Handles:
60+
* - owner/repo (already normalized)
61+
* - https://github.com/owner/repo
62+
* - https://github.com/owner/repo.git
63+
* - git@github.com:owner/repo.git
64+
*/
65+
export function normalizeRepoReference(repo: string): string {
66+
if (!repo) return '';
67+
68+
// Remove trailing .git if present
69+
let normalized = repo.replace(/\.git$/, '');
70+
71+
// Handle full GitHub URLs
72+
if (normalized.startsWith('https://github.com/')) {
73+
normalized = normalized.replace('https://github.com/', '');
74+
} else if (normalized.startsWith('http://github.com/')) {
75+
normalized = normalized.replace('http://github.com/', '');
76+
} else if (normalized.startsWith('git@github.com:')) {
77+
normalized = normalized.replace('git@github.com:', '');
78+
}
79+
80+
return normalized.trim();
81+
}
82+
5783
/**
5884
* Make a request to the GitHub API
5985
*/

auto-claude-ui/src/renderer/components/ProjectSettings.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ export function ProjectSettings({ project, open, onOpenChange }: ProjectSettings
238238
onUpdateConfig={updateEnvConfig}
239239
gitHubConnectionStatus={gitHubConnectionStatus}
240240
isCheckingGitHub={isCheckingGitHub}
241+
projectName={project.name}
241242
/>
242243

243244
<Separator />

auto-claude-ui/src/renderer/components/project-settings/GitHubIntegrationSection.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useState } from 'react';
2-
import { Github, RefreshCw, KeyRound } from 'lucide-react';
2+
import { Github, RefreshCw, KeyRound, Info } from 'lucide-react';
33
import { CollapsibleSection } from './CollapsibleSection';
44
import { StatusBadge } from './StatusBadge';
55
import { PasswordInput } from './PasswordInput';
@@ -19,6 +19,7 @@ interface GitHubIntegrationSectionProps {
1919
onUpdateConfig: (updates: Partial<ProjectEnvConfig>) => void;
2020
gitHubConnectionStatus: GitHubSyncStatus | null;
2121
isCheckingGitHub: boolean;
22+
projectName?: string;
2223
}
2324

2425
export function GitHubIntegrationSection({
@@ -28,6 +29,7 @@ export function GitHubIntegrationSection({
2829
onUpdateConfig,
2930
gitHubConnectionStatus,
3031
isCheckingGitHub,
32+
projectName,
3133
}: GitHubIntegrationSectionProps) {
3234
const [showOAuthFlow, setShowOAuthFlow] = useState(false);
3335

@@ -48,6 +50,22 @@ export function GitHubIntegrationSection({
4850
onToggle={onToggle}
4951
badge={badge}
5052
>
53+
{/* Project-Specific Configuration Notice */}
54+
{projectName && (
55+
<div className="rounded-lg border border-info/30 bg-info/5 p-3 mb-4">
56+
<div className="flex items-start gap-2">
57+
<Info className="h-4 w-4 text-info mt-0.5 shrink-0" />
58+
<div className="flex-1">
59+
<p className="text-sm font-medium text-foreground">Project-Specific Configuration</p>
60+
<p className="text-xs text-muted-foreground mt-1">
61+
This GitHub repository is configured only for <span className="font-semibold text-foreground">{projectName}</span>.
62+
Each project can have its own GitHub repository.
63+
</p>
64+
</div>
65+
</div>
66+
</div>
67+
)}
68+
5169
<div className="flex items-center justify-between">
5270
<div className="space-y-0.5">
5371
<Label className="font-normal text-foreground">Enable GitHub Issues</Label>

0 commit comments

Comments
 (0)