mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 12:03:53 +00:00
foundry: async app repo import on org select
This commit is contained in:
parent
fa4ed388d2
commit
6e216a9f86
2 changed files with 93 additions and 43 deletions
|
|
@ -66,6 +66,7 @@ const WORKSPACE_QUEUE_NAMES = [
|
|||
"workspace.command.addRepo",
|
||||
"workspace.command.createTask",
|
||||
"workspace.command.refreshProviderProfiles",
|
||||
"workspace.command.syncGithubOrganizationRepos",
|
||||
"workspace.command.syncGithubSession",
|
||||
] as const;
|
||||
const SANDBOX_AGENT_REPO = "rivet-dev/sandbox-agent";
|
||||
|
|
@ -387,6 +388,19 @@ export async function runWorkspaceWorkflow(ctx: any): Promise<void> {
|
|||
return Loop.continue(undefined);
|
||||
}
|
||||
|
||||
if (msg.name === "workspace.command.syncGithubOrganizationRepos") {
|
||||
await loopCtx.step({
|
||||
name: "workspace-sync-github-organization-repos",
|
||||
timeout: 60_000,
|
||||
run: async () => {
|
||||
const { syncGithubOrganizationRepos } = await import("./app-shell.js");
|
||||
await syncGithubOrganizationRepos(loopCtx, msg.body as { sessionId: string; organizationId: string });
|
||||
},
|
||||
});
|
||||
await msg.complete({ ok: true });
|
||||
return Loop.continue(undefined);
|
||||
}
|
||||
|
||||
return Loop.continue(undefined);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -469,6 +469,58 @@ export async function syncGithubOrganizations(c: any, input: { sessionId: string
|
|||
});
|
||||
}
|
||||
|
||||
export async function syncGithubOrganizationRepos(c: any, input: { sessionId: string; organizationId: string }): Promise<void> {
|
||||
assertAppWorkspace(c);
|
||||
const session = await requireSignedInSession(c, input.sessionId);
|
||||
requireEligibleOrganization(session, input.organizationId);
|
||||
|
||||
const { appShell } = getActorRuntimeContext();
|
||||
const workspace = await getOrCreateWorkspace(c, input.organizationId);
|
||||
const organization = await getOrganizationState(workspace);
|
||||
|
||||
try {
|
||||
let repositories;
|
||||
let installationStatus = organization.snapshot.github.installationStatus;
|
||||
|
||||
if (organization.snapshot.kind === "personal") {
|
||||
repositories = await appShell.github.listUserRepositories(session.githubAccessToken);
|
||||
installationStatus = "connected";
|
||||
} else if (organization.githubInstallationId) {
|
||||
try {
|
||||
repositories = await appShell.github.listInstallationRepositories(organization.githubInstallationId);
|
||||
} catch (error) {
|
||||
if (!(error instanceof GitHubAppError) || (error.status !== 403 && error.status !== 404)) {
|
||||
throw error;
|
||||
}
|
||||
repositories = (await appShell.github.listUserRepositories(session.githubAccessToken)).filter((repository) =>
|
||||
repository.fullName.startsWith(`${organization.githubLogin}/`),
|
||||
);
|
||||
installationStatus = "reconnect_required";
|
||||
}
|
||||
} else {
|
||||
repositories = (await appShell.github.listUserRepositories(session.githubAccessToken)).filter((repository) =>
|
||||
repository.fullName.startsWith(`${organization.githubLogin}/`),
|
||||
);
|
||||
installationStatus = "reconnect_required";
|
||||
}
|
||||
|
||||
await workspace.applyOrganizationSyncCompleted({
|
||||
repositories,
|
||||
installationStatus,
|
||||
lastSyncLabel: repositories.length > 0 ? "Synced just now" : "No repositories available",
|
||||
});
|
||||
} catch (error) {
|
||||
const installationStatus =
|
||||
error instanceof GitHubAppError && (error.status === 403 || error.status === 404)
|
||||
? "reconnect_required"
|
||||
: organization.snapshot.github.installationStatus;
|
||||
await workspace.markOrganizationSyncFailed({
|
||||
message: error instanceof Error ? error.message : "GitHub import failed",
|
||||
installationStatus,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Full synchronous sync: init session + sync orgs in one call.
|
||||
* Used by bootstrapAppGithubSession (dev-only) where there is no proxy
|
||||
|
|
@ -766,7 +818,22 @@ export const workspaceAppActions = {
|
|||
const workspace = await getOrCreateWorkspace(c, input.organizationId);
|
||||
const organization = await getOrganizationState(workspace);
|
||||
if (organization.snapshot.github.syncStatus !== "synced") {
|
||||
return await workspaceAppActions.triggerAppRepoImport(c, input);
|
||||
if (organization.snapshot.github.syncStatus !== "syncing") {
|
||||
await workspace.markOrganizationSyncStarted({
|
||||
label: "Importing repository catalog...",
|
||||
});
|
||||
|
||||
const self = selfWorkspace(c);
|
||||
await self.send(
|
||||
"workspace.command.syncGithubOrganizationRepos",
|
||||
{ sessionId: input.sessionId, organizationId: input.organizationId },
|
||||
{
|
||||
wait: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return await buildAppSnapshot(c, input.sessionId);
|
||||
}
|
||||
return await buildAppSnapshot(c, input.sessionId);
|
||||
},
|
||||
|
|
@ -792,55 +859,24 @@ export const workspaceAppActions = {
|
|||
const session = await requireSignedInSession(c, input.sessionId);
|
||||
requireEligibleOrganization(session, input.organizationId);
|
||||
|
||||
const { appShell } = getActorRuntimeContext();
|
||||
const workspace = await getOrCreateWorkspace(c, input.organizationId);
|
||||
const organization = await getOrganizationState(workspace);
|
||||
if (organization.snapshot.github.syncStatus === "syncing") {
|
||||
return await buildAppSnapshot(c, input.sessionId);
|
||||
}
|
||||
|
||||
await workspace.markOrganizationSyncStarted({
|
||||
label: "Importing repository catalog...",
|
||||
});
|
||||
|
||||
try {
|
||||
let repositories;
|
||||
let installationStatus = organization.snapshot.github.installationStatus;
|
||||
|
||||
if (organization.snapshot.kind === "personal") {
|
||||
repositories = await appShell.github.listUserRepositories(session.githubAccessToken);
|
||||
installationStatus = "connected";
|
||||
} else if (organization.githubInstallationId) {
|
||||
try {
|
||||
repositories = await appShell.github.listInstallationRepositories(organization.githubInstallationId);
|
||||
} catch (error) {
|
||||
if (!(error instanceof GitHubAppError) || (error.status !== 403 && error.status !== 404)) {
|
||||
throw error;
|
||||
}
|
||||
repositories = (await appShell.github.listUserRepositories(session.githubAccessToken)).filter((repository) =>
|
||||
repository.fullName.startsWith(`${organization.githubLogin}/`),
|
||||
);
|
||||
installationStatus = "reconnect_required";
|
||||
}
|
||||
} else {
|
||||
repositories = (await appShell.github.listUserRepositories(session.githubAccessToken)).filter((repository) =>
|
||||
repository.fullName.startsWith(`${organization.githubLogin}/`),
|
||||
);
|
||||
installationStatus = "reconnect_required";
|
||||
}
|
||||
|
||||
await workspace.applyOrganizationSyncCompleted({
|
||||
repositories,
|
||||
installationStatus,
|
||||
lastSyncLabel: repositories.length > 0 ? "Synced just now" : "No repositories available",
|
||||
});
|
||||
} catch (error) {
|
||||
const installationStatus =
|
||||
error instanceof GitHubAppError && (error.status === 403 || error.status === 404)
|
||||
? "reconnect_required"
|
||||
: organization.snapshot.github.installationStatus;
|
||||
await workspace.markOrganizationSyncFailed({
|
||||
message: error instanceof Error ? error.message : "GitHub import failed",
|
||||
installationStatus,
|
||||
});
|
||||
}
|
||||
const self = selfWorkspace(c);
|
||||
await self.send(
|
||||
"workspace.command.syncGithubOrganizationRepos",
|
||||
{ sessionId: input.sessionId, organizationId: input.organizationId },
|
||||
{
|
||||
wait: false,
|
||||
},
|
||||
);
|
||||
|
||||
return await buildAppSnapshot(c, input.sessionId);
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue