backport
Version:
A CLI tool that automates the process of backporting commits
128 lines • 5.58 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getOptionsFromGithub = void 0;
const generated_1 = require("../../../../graphql/generated");
const BackportError_1 = require("../../../BackportError");
const git_1 = require("../../../git");
const logger_1 = require("../../../logger");
const remoteConfig_1 = require("../../../remoteConfig");
const graphqlClient_1 = require("../client/graphqlClient");
const getInvalidAccessTokenMessage_1 = require("../getInvalidAccessTokenMessage");
async function getOptionsFromGithub(options) {
const { accessToken, githubApiBaseUrlV4, repoName, repoOwner, globalConfigFile, } = options;
const query = (0, generated_1.graphql)(`
query GithubConfigOptions($repoOwner: String!, $repoName: String!) {
viewer {
login
}
repository(owner: $repoOwner, name: $repoName) {
# check to see if a branch named "backport" exists
illegalBackportBranch: ref(qualifiedName: "refs/heads/backport") {
id
}
isPrivate
defaultBranchRef {
name
target {
__typename
...RemoteConfigHistoryFragment
}
}
}
}
`);
const variables = { repoOwner, repoName };
const client = (0, graphqlClient_1.getGraphQLClient)({ accessToken, githubApiBaseUrlV4 });
const result = await client.query(query, variables);
if (result.error) {
const isInvalidAccessTokenMessage = (0, getInvalidAccessTokenMessage_1.getInvalidAccessTokenMessage)({
result,
repoName,
repoOwner,
globalConfigFile,
});
if (isInvalidAccessTokenMessage) {
throw new BackportError_1.BackportError(isInvalidAccessTokenMessage);
}
if (!(0, remoteConfig_1.isMissingConfigFileException)(result)) {
throw new graphqlClient_1.GithubV4Exception(result);
}
}
const insufficientPermissionsErrorMessage = getInsufficientPermissionsErrorMessage(result);
if (insufficientPermissionsErrorMessage) {
throw new BackportError_1.BackportError(insufficientPermissionsErrorMessage);
}
const { data } = result;
// it is not possible to have a branch named "backport"
if (data?.repository?.illegalBackportBranch) {
throw new BackportError_1.BackportError('You must delete the branch "backport" to continue. See https://github.com/sorenlouv/backport/issues/155 for details');
}
const remoteConfig = await getRemoteConfigFileOptions(data, options.cwd, options.skipRemoteConfig);
if (!data) {
throw new BackportError_1.BackportError('Failed to fetch options from GitHub. Please check your access token and repository settings.');
}
return {
authenticatedUsername: data.viewer.login,
sourceBranch: options.sourceBranch ?? data.repository?.defaultBranchRef?.name ?? 'main',
isRepoPrivate: data.repository?.isPrivate,
...remoteConfig,
};
}
exports.getOptionsFromGithub = getOptionsFromGithub;
async function getRemoteConfigFileOptions(res, cwd, skipRemoteConfig) {
if (skipRemoteConfig) {
logger_1.logger.info('Remote config: Skipping. `--skip-remote-config` specified via config file or cli');
return;
}
if (res?.repository?.defaultBranchRef?.target?.__typename !== 'Commit') {
logger_1.logger.info('Remote config: Skipping. Default branch is not a commit');
return;
}
const remoteConfig = res.repository.defaultBranchRef.target.remoteConfigHistory.edges?.[0]
?.remoteConfig;
if (!remoteConfig) {
logger_1.logger.info("Remote config: Skipping. Remote config doesn't exist");
return;
}
if (cwd) {
const [isLocalConfigModified, isLocalConfigUntracked, localCommitDate] = await Promise.all([
(0, git_1.isLocalConfigFileModified)({ cwd }),
(0, git_1.isLocalConfigFileUntracked)({ cwd }),
(0, git_1.getLocalConfigFileCommitDate)({ cwd }),
]);
if (isLocalConfigUntracked) {
logger_1.logger.info('Remote config: Skipping. Local config is new');
return;
}
if (isLocalConfigModified) {
logger_1.logger.info('Remote config: Skipping. Local config is modified');
return;
}
if (localCommitDate &&
localCommitDate > Date.parse(remoteConfig.committedDate)) {
logger_1.logger.info(`Remote config: Skipping. Local config is newer: ${new Date(localCommitDate).toISOString()} > ${remoteConfig.committedDate}`);
return;
}
}
logger_1.logger.info('Remote config: Parsing.');
return (0, remoteConfig_1.parseRemoteConfigFile)(remoteConfig);
}
function getInsufficientPermissionsErrorMessage(res) {
const responseHeaders = res.responseHeaders;
const accessScopesHeader = responseHeaders.get('x-oauth-scopes');
if (accessScopesHeader == null) {
return;
}
const accessTokenScopes = accessScopesHeader
.split(',')
.map((scope) => scope.trim());
const isRepoPrivate = res.data?.repository?.isPrivate;
if (isRepoPrivate && !accessTokenScopes.includes('repo')) {
return `You must grant the "repo" scope to your personal access token`;
}
if (!accessTokenScopes.includes('repo') &&
!accessTokenScopes.includes('public_repo')) {
return `You must grant the "repo" or "public_repo" scope to your personal access token`;
}
}
//# sourceMappingURL=getOptionsFromGithub.js.map