backport
Version:
A CLI tool that automates the process of backporting commits
75 lines • 3.02 kB
JavaScript
import { GraphQLError, print, Kind } from 'graphql';
import pRetry from 'p-retry';
import { logger } from '../../../logger.js';
export async function graphqlRequest({ githubApiBaseUrlV4 = 'https://api.github.com/graphql', githubToken, }, document, variables) {
const query = print(document);
const opDef = document.definitions.find((d) => d.kind === Kind.OPERATION_DEFINITION);
const operationName = opDef?.kind === Kind.OPERATION_DEFINITION ? opDef.name?.value : undefined;
logger.verbose('Query:', query);
logger.verbose('Variables:', variables);
const response = await pRetry(async () => {
const res = await fetch(githubApiBaseUrlV4, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `bearer ${githubToken}`,
},
body: JSON.stringify({ query, variables, operationName }),
});
// Retry on transient server errors and rate limiting
if (res.status >= 500 || res.status === 429) {
throw new Error(`GitHub GraphQL API returned ${res.status} ${res.statusText}`);
}
return res;
}, {
retries: 2,
minTimeout: 1000,
onFailedAttempt: ({ error, attemptNumber, retriesLeft }) => {
logger.info(`GraphQL request failed (attempt ${attemptNumber}/${attemptNumber + retriesLeft}): ${error.message}`);
},
});
const responseHeaders = response.headers;
const statusCode = response.status;
let json;
try {
json = await response.json();
}
catch {
// Non-JSON response (e.g. 502 Bad Gateway HTML page)
const error = {
message: `[Network] ${response.statusText}`,
graphQLErrors: [],
};
logger.error('GraphQL Error:', error.message);
return { data: undefined, error, responseHeaders, statusCode };
}
if (!response.ok && !json.errors) {
const error = {
message: `[Network] ${response.statusText}`,
graphQLErrors: [],
};
logger.error('GraphQL Error:', error.message);
return { data: json.data, error, responseHeaders, statusCode };
}
if (json.errors?.length) {
const graphQLErrors = json.errors.map((e) => {
const originalError = Object.assign(new Error(e.message), {
type: e.type,
});
return new GraphQLError(e.message, {
path: e.path,
extensions: e.extensions,
originalError,
});
});
const error = {
message: `[GraphQL] ${json.errors.at(0).message}`,
graphQLErrors,
};
logger.error('GraphQL Error:', error.message);
return { data: json.data, error, responseHeaders, statusCode };
}
logger.verbose('Data:', json.data);
return { data: json.data, error: undefined, responseHeaders, statusCode };
}
//# sourceMappingURL=graphql-client.js.map