Skip to content

Commit

Permalink
Throw 400 exposable errors instead of internal errors when Git sync c…
Browse files Browse the repository at this point in the history
…onfig value are missing/incomplete (#634)
  • Loading branch information
jpreynat authored Nov 22, 2024
1 parent 2d5ae22 commit 953d82a
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 21 deletions.
6 changes: 6 additions & 0 deletions .changeset/twelve-balloons-help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@gitbook/integration-github': patch
'@gitbook/integration-gitlab': patch
---

Throw 400 exposable errors instead of internal errors when Git sync config value are missing/incomplete
12 changes: 6 additions & 6 deletions integrations/github/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ export async function getGitHubAppJWT(context: GithubRuntimeContext): Promise<st
* Returns the URL of the Git repository.
*/
export function getRepositoryUrl(config: GitHubSpaceConfiguration, withExtension = false): string {
assertIsDefined(config.accountName, { label: 'config.accountName' });
assertIsDefined(config.repoName, { label: 'config.repoName' });
assertIsDefined(config.accountName, { label: 'config.accountName', statusCode: 400 });
assertIsDefined(config.repoName, { label: 'config.repoName', statusCode: 400 });

return `https://github.com/${config.accountName}/${config.repoName}${
withExtension ? '.git' : ''
Expand All @@ -54,7 +54,7 @@ export async function getRepositoryAuth(
context: GithubRuntimeContext,
config: GitHubSpaceConfiguration,
) {
assertIsDefined(config.installation, { label: 'config.installation' });
assertIsDefined(config.installation, { label: 'config.installation', statusCode: 400 });

const appJWT = await getGitHubAppJWT(context);
const installationAccessToken = await createAppInstallationAccessToken(
Expand Down Expand Up @@ -84,9 +84,9 @@ export async function updateCommitStatus(
description: string;
},
) {
assertIsDefined(config.accountName, { label: 'config.accountName' });
assertIsDefined(config.repoName, { label: 'config.repoName' });
assertIsDefined(config.installation, { label: 'config.installation' });
assertIsDefined(config.accountName, { label: 'config.accountName', statusCode: 400 });
assertIsDefined(config.repoName, { label: 'config.repoName', statusCode: 400 });
assertIsDefined(config.installation, { label: 'config.installation', statusCode: 400 });

const appJWT = await getGitHubAppJWT(context);
const installationAccessToken = await createAppInstallationAccessToken(
Expand Down
4 changes: 2 additions & 2 deletions integrations/github/src/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export async function triggerImport(
return;
}

assertIsDefined(config.branch, { label: 'config.branch' });
assertIsDefined(config.branch, { label: 'config.branch', statusCode: 400 });

logger.info(`Initiating an import from GitHub to GitBook space ${spaceId}`);

Expand Down Expand Up @@ -130,7 +130,7 @@ export async function triggerExport(
return;
}

assertIsDefined(config.branch, { label: 'config.branch' });
assertIsDefined(config.branch, { label: 'config.branch', statusCode: 400 });

logger.info(`Initiating an export from space ${spaceId} to GitHub`);

Expand Down
14 changes: 10 additions & 4 deletions integrations/github/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { GitSyncOperationState, IntegrationSpaceInstallation } from '@gitbook/api';

import type { GitHubSpaceConfiguration } from './types';
import { ExposableError } from '@gitbook/runtime';

export const BRANCH_REF_PREFIX = 'refs/heads/';

Expand Down Expand Up @@ -75,12 +76,17 @@ export function computeConfigQueryKey(

export function assertIsDefined<T>(
value: T,
options: {
label: string;
},
options: { label: string; statusCode?: number },
): asserts value is NonNullable<T> {
const { label, statusCode = 500 } = options;

if (value === undefined || value === null) {
throw new Error(`Expected value (${options.label}) to be defined, but received ${value}`);
const errorMsg = `Expected value (${label}) to be defined, but received ${value}`;
if (statusCode >= 400 && statusCode < 500) {
throw new ExposableError(errorMsg, statusCode);
}

throw new Error(errorMsg);
}
}

Expand Down
8 changes: 4 additions & 4 deletions integrations/gitlab/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function installWebhook(
) {
const config = getSpaceConfigOrThrow(spaceInstallation);

assertIsDefined(config.project, { label: 'config.project' });
assertIsDefined(config.project, { label: 'config.project', statusCode: 400 });

const projectId = config.project;
const id = await addProjectWebhook(config, config.project, webhookUrl, webhookToken);
Expand All @@ -38,8 +38,8 @@ export async function installWebhook(
* project.
*/
export async function uninstallWebhook(config: GitLabSpaceConfiguration) {
assertIsDefined(config.project, { label: 'config.project' });
assertIsDefined(config.webhookId, { label: 'config.webhookId' });
assertIsDefined(config.project, { label: 'config.project', statusCode: 400 });
assertIsDefined(config.webhookId, { label: 'config.webhookId', statusCode: 400 });

const projectId = config.project;
const webhookId = config.webhookId;
Expand All @@ -62,7 +62,7 @@ export async function updateCommitStatus(
description: string;
},
) {
assertIsDefined(config.project, { label: 'config.project' });
assertIsDefined(config.project, { label: 'config.project', statusCode: 400 });

const projectId = config.project;

Expand Down
6 changes: 3 additions & 3 deletions integrations/gitlab/src/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
IntegrationSpaceInstallation,
Revision,
} from '@gitbook/api';
import { Logger } from '@gitbook/runtime';
import { ExposableError, Logger } from '@gitbook/runtime';

import {
getGitCommitURL,
Expand Down Expand Up @@ -68,7 +68,7 @@ export async function triggerImport(
return;
}

assertIsDefined(config.branch, { label: 'config.branch' });
assertIsDefined(config.branch, { label: 'config.branch', statusCode: 400 });

logger.info(`Initiating an import from GitLab to GitBook space ${spaceId}`);

Expand Down Expand Up @@ -130,7 +130,7 @@ export async function triggerExport(
return;
}

assertIsDefined(config.branch, { label: 'config.branch' });
assertIsDefined(config.branch, { label: 'config.branch', statusCode: 400 });

logger.info(`Initiating an export from space ${spaceId} to GitLab`);

Expand Down
12 changes: 10 additions & 2 deletions integrations/gitlab/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { GitSyncOperationState, IntegrationSpaceInstallation } from '@gitbook/api';

import type { GitLabSpaceConfiguration } from './types';
import { ExposableError } from '@gitbook/runtime';

export const BRANCH_REF_PREFIX = 'refs/heads/';

Expand Down Expand Up @@ -100,10 +101,17 @@ export async function verifySignature(

export function assertIsDefined<T>(
value: T,
options: { label: string },
options: { label: string; statusCode?: number },
): asserts value is NonNullable<T> {
const { label, statusCode = 500 } = options;

if (value === undefined || value === null) {
throw new Error(`Expected value (${options.label}) to be defined, but received ${value}`);
const errorMsg = `Expected value (${label}) to be defined, but received ${value}`;
if (statusCode >= 400 && statusCode < 500) {
throw new ExposableError(errorMsg, statusCode);
}

throw new Error(errorMsg);
}
}

Expand Down

0 comments on commit 953d82a

Please sign in to comment.