This commit is contained in:
bkellam 2025-10-26 15:01:28 -04:00
parent 88ef3fdae0
commit 02ef3b8301
4 changed files with 47 additions and 80 deletions

View file

@ -1,14 +1,13 @@
import { Connection, PrismaClient, ConnectionSyncJobStatus } from "@sourcebot/db";
import { Job, Queue, ReservedJob, Worker } from "groupmq";
import { Settings } from "./types.js";
import { createLogger } from "@sourcebot/logger";
import { Redis } from 'ioredis';
import { RepoData, compileGithubConfig, compileGitlabConfig, compileGiteaConfig, compileGerritConfig, compileBitbucketConfig, compileAzureDevOpsConfig, compileGenericGitHostConfig } from "./repoCompileUtils.js";
import { BackendError, BackendException } from "@sourcebot/error";
import { env } from "./env.js";
import * as Sentry from "@sentry/node"; import * as Sentry from "@sentry/node";
import { loadConfig, syncSearchContexts } from "@sourcebot/shared"; import { Connection, ConnectionSyncJobStatus, PrismaClient } from "@sourcebot/db";
import { createLogger } from "@sourcebot/logger";
import { ConnectionConfig } from "@sourcebot/schemas/v3/connection.type"; import { ConnectionConfig } from "@sourcebot/schemas/v3/connection.type";
import { loadConfig, syncSearchContexts } from "@sourcebot/shared";
import { Job, Queue, ReservedJob, Worker } from "groupmq";
import { Redis } from 'ioredis';
import { env } from "./env.js";
import { compileAzureDevOpsConfig, compileBitbucketConfig, compileGenericGitHostConfig, compileGerritConfig, compileGiteaConfig, compileGithubConfig, compileGitlabConfig } from "./repoCompileUtils.js";
import { Settings } from "./types.js";
import { groupmqLifecycleExceptionWrapper } from "./utils.js"; import { groupmqLifecycleExceptionWrapper } from "./utils.js";
const LOG_TAG = 'connection-manager'; const LOG_TAG = 'connection-manager';
@ -166,53 +165,32 @@ export class ConnectionManager {
const config = rawConnectionConfig as unknown as ConnectionConfig; const config = rawConnectionConfig as unknown as ConnectionConfig;
let result: { const result = await (async () => {
repoData: RepoData[], switch (config.type) {
warnings: string[], case 'github': {
} = { return await compileGithubConfig(config, job.data.connectionId, orgId, this.db, abortController);
repoData: [], }
warnings: [], case 'gitlab': {
}; return await compileGitlabConfig(config, job.data.connectionId, orgId, this.db);
}
try { case 'gitea': {
result = await (async () => { return await compileGiteaConfig(config, job.data.connectionId, orgId, this.db);
switch (config.type) { }
case 'github': { case 'gerrit': {
return await compileGithubConfig(config, job.data.connectionId, orgId, this.db, abortController); return await compileGerritConfig(config, job.data.connectionId, orgId);
} }
case 'gitlab': { case 'bitbucket': {
return await compileGitlabConfig(config, job.data.connectionId, orgId, this.db); return await compileBitbucketConfig(config, job.data.connectionId, orgId, this.db);
} }
case 'gitea': { case 'azuredevops': {
return await compileGiteaConfig(config, job.data.connectionId, orgId, this.db); return await compileAzureDevOpsConfig(config, job.data.connectionId, orgId, this.db);
} }
case 'gerrit': { case 'git': {
return await compileGerritConfig(config, job.data.connectionId, orgId); return await compileGenericGitHostConfig(config, job.data.connectionId, orgId);
}
case 'bitbucket': {
return await compileBitbucketConfig(config, job.data.connectionId, orgId, this.db);
}
case 'azuredevops': {
return await compileAzureDevOpsConfig(config, job.data.connectionId, orgId, this.db);
}
case 'git': {
return await compileGenericGitHostConfig(config, job.data.connectionId, orgId);
}
} }
})();
} catch (err) {
logger.error(`Failed to compile repo data for connection ${job.data.connectionId} (${connectionName}): ${err}`);
Sentry.captureException(err);
if (err instanceof BackendException) {
throw err;
} else {
throw new BackendException(BackendError.CONNECTION_SYNC_SYSTEM_ERROR, {
message: `Failed to compile repo data for connection ${job.data.connectionId}`,
});
} }
} })();
let { repoData, warnings } = result; let { repoData, warnings } = result;
await this.db.connectionSyncJob.update({ await this.db.connectionSyncJob.update({

View file

@ -37,7 +37,6 @@ const logger = createLogger('gerrit');
export const getGerritReposFromConfig = async (config: GerritConnectionConfig): Promise<GerritProject[]> => { export const getGerritReposFromConfig = async (config: GerritConnectionConfig): Promise<GerritProject[]> => {
const url = config.url.endsWith('/') ? config.url : `${config.url}/`; const url = config.url.endsWith('/') ? config.url : `${config.url}/`;
const hostname = new URL(config.url).hostname;
let { durationMs, data: projects } = await measure(async () => { let { durationMs, data: projects } = await measure(async () => {
try { try {

View file

@ -35,6 +35,11 @@ const createGitClientForPath = (path: string, onProgress?: onProgressFn, signal?
* parent directory. * parent directory.
*/ */
GIT_CEILING_DIRECTORIES: parentPath, GIT_CEILING_DIRECTORIES: parentPath,
/**
* Disable git credential prompts. This ensures that git operations will fail
* immediately if credentials are not available, rather than prompting for input.
*/
GIT_TERMINAL_PROMPT: '0',
}) })
.cwd({ .cwd({
path, path,

View file

@ -1,15 +1,14 @@
import { Octokit } from "@octokit/rest"; import { Octokit } from "@octokit/rest";
import { GithubConnectionConfig } from "@sourcebot/schemas/v3/github.type";
import { createLogger } from "@sourcebot/logger";
import { getTokenFromConfig, measure, fetchWithRetry } from "./utils.js";
import micromatch from "micromatch";
import { PrismaClient } from "@sourcebot/db";
import { BackendException, BackendError } from "@sourcebot/error";
import { processPromiseResults, throwIfAnyFailed } from "./connectionUtils.js";
import * as Sentry from "@sentry/node"; import * as Sentry from "@sentry/node";
import { env } from "./env.js"; import { PrismaClient } from "@sourcebot/db";
import { GithubAppManager } from "./ee/githubAppManager.js"; import { createLogger } from "@sourcebot/logger";
import { GithubConnectionConfig } from "@sourcebot/schemas/v3/github.type";
import { hasEntitlement } from "@sourcebot/shared"; import { hasEntitlement } from "@sourcebot/shared";
import micromatch from "micromatch";
import { processPromiseResults, throwIfAnyFailed } from "./connectionUtils.js";
import { GithubAppManager } from "./ee/githubAppManager.js";
import { env } from "./env.js";
import { fetchWithRetry, getTokenFromConfig, measure } from "./utils.js";
export const GITHUB_CLOUD_HOSTNAME = "github.com"; export const GITHUB_CLOUD_HOSTNAME = "github.com";
const logger = createLogger('github'); const logger = createLogger('github');
@ -114,22 +113,8 @@ export const getGitHubReposFromConfig = async (config: GithubConnectionConfig, o
await octokit.rest.users.getAuthenticated(); await octokit.rest.users.getAuthenticated();
} catch (error) { } catch (error) {
Sentry.captureException(error); Sentry.captureException(error);
logger.error(`Failed to authenticate with GitHub`, error);
if (isHttpError(error, 401)) { throw error;
const e = new BackendException(BackendError.CONNECTION_SYNC_INVALID_TOKEN, {
...(config.token && 'secret' in config.token ? {
secretKey: config.token.secret,
} : {}),
});
Sentry.captureException(e);
throw e;
}
const e = new BackendException(BackendError.CONNECTION_SYNC_SYSTEM_ERROR, {
message: `Failed to authenticate with GitHub`,
});
Sentry.captureException(e);
throw e;
} }
} }