mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-19 06:01:21 +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.addRepo",
|
||||||
"workspace.command.createTask",
|
"workspace.command.createTask",
|
||||||
"workspace.command.refreshProviderProfiles",
|
"workspace.command.refreshProviderProfiles",
|
||||||
|
"workspace.command.syncGithubOrganizationRepos",
|
||||||
"workspace.command.syncGithubSession",
|
"workspace.command.syncGithubSession",
|
||||||
] as const;
|
] as const;
|
||||||
const SANDBOX_AGENT_REPO = "rivet-dev/sandbox-agent";
|
const SANDBOX_AGENT_REPO = "rivet-dev/sandbox-agent";
|
||||||
|
|
@ -387,6 +388,19 @@ export async function runWorkspaceWorkflow(ctx: any): Promise<void> {
|
||||||
return Loop.continue(undefined);
|
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);
|
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.
|
* Full synchronous sync: init session + sync orgs in one call.
|
||||||
* Used by bootstrapAppGithubSession (dev-only) where there is no proxy
|
* 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 workspace = await getOrCreateWorkspace(c, input.organizationId);
|
||||||
const organization = await getOrganizationState(workspace);
|
const organization = await getOrganizationState(workspace);
|
||||||
if (organization.snapshot.github.syncStatus !== "synced") {
|
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);
|
return await buildAppSnapshot(c, input.sessionId);
|
||||||
},
|
},
|
||||||
|
|
@ -792,55 +859,24 @@ export const workspaceAppActions = {
|
||||||
const session = await requireSignedInSession(c, input.sessionId);
|
const session = await requireSignedInSession(c, input.sessionId);
|
||||||
requireEligibleOrganization(session, input.organizationId);
|
requireEligibleOrganization(session, input.organizationId);
|
||||||
|
|
||||||
const { appShell } = getActorRuntimeContext();
|
|
||||||
const workspace = await getOrCreateWorkspace(c, input.organizationId);
|
const workspace = await getOrCreateWorkspace(c, input.organizationId);
|
||||||
const organization = await getOrganizationState(workspace);
|
const organization = await getOrganizationState(workspace);
|
||||||
|
if (organization.snapshot.github.syncStatus === "syncing") {
|
||||||
|
return await buildAppSnapshot(c, input.sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
await workspace.markOrganizationSyncStarted({
|
await workspace.markOrganizationSyncStarted({
|
||||||
label: "Importing repository catalog...",
|
label: "Importing repository catalog...",
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
const self = selfWorkspace(c);
|
||||||
let repositories;
|
await self.send(
|
||||||
let installationStatus = organization.snapshot.github.installationStatus;
|
"workspace.command.syncGithubOrganizationRepos",
|
||||||
|
{ sessionId: input.sessionId, organizationId: input.organizationId },
|
||||||
if (organization.snapshot.kind === "personal") {
|
{
|
||||||
repositories = await appShell.github.listUserRepositories(session.githubAccessToken);
|
wait: false,
|
||||||
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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return await buildAppSnapshot(c, input.sessionId);
|
return await buildAppSnapshot(c, input.sessionId);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue