feat(gh-85): take git tokens from environment (#88)

This commit is contained in:
Andrea Lamparelli 2023-12-10 22:05:53 +01:00 committed by GitHub
parent aac73bf7c5
commit 70da575afc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 456 additions and 24 deletions

View file

@ -13,7 +13,7 @@ export default class CLIArgsParser extends ArgsParser {
.option("-tb, --target-branch <branches>", "comma separated list of branches where changes must be backported to")
.option("-pr, --pull-request <pr-url>", "pull request url, e.g., https://github.com/kiegroup/git-backporting/pull/1")
.option("-d, --dry-run", "if enabled the tool does not create any pull request nor push anything remotely")
.option("-a, --auth <auth>", "git service authentication string, e.g., github token")
.option("-a, --auth <auth>", "git authentication string, if not provided fallback by looking for existing env variables like GITHUB_TOKEN")
.option("-gu, --git-user <git-user>", "local git user name, default is 'GitHub'")
.option("-ge, --git-email <git-email>", "local git user email, default is 'noreply@github.com'")
.option("-f, --folder <folder>", "local folder where the repo will be checked out, e.g., /tmp/folder")

View file

@ -1,7 +1,8 @@
import { Args } from "@bp/service/args/args.types";
import { Configs } from "@bp/service/configs/configs.types";
import { AuthTokenId, Configs } from "@bp/service/configs/configs.types";
import LoggerService from "../logger/logger-service";
import LoggerServiceFactory from "../logger/logger-service-factory";
import { GitClientType } from "../git/git.types";
/**
* Abstract configuration parser class in charge to parse
@ -34,4 +35,42 @@ import LoggerServiceFactory from "../logger/logger-service-factory";
return Promise.resolve(configs);
}
/**
* Retrieve the git token from env variable, the default is taken from GIT_TOKEN env.
* All specific git env variable have precedence and override the default one.
* @param gitType
* @returns tuple where
* - the first element is the corresponding env value
* - the second element is true if the value is not undefined nor empty
*/
public getGitTokenFromEnv(gitType: GitClientType): string | undefined {
let [token] = this.getEnv(AuthTokenId.GIT_TOKEN);
let [specToken, specOk]: [string | undefined, boolean] = [undefined, false];
if (GitClientType.GITHUB == gitType) {
[specToken, specOk] = this.getEnv(AuthTokenId.GITHUB_TOKEN);
} else if (GitClientType.GITLAB == gitType) {
[specToken, specOk] = this.getEnv(AuthTokenId.GITLAB_TOKEN);
} else if (GitClientType.CODEBERG == gitType) {
[specToken, specOk] = this.getEnv(AuthTokenId.CODEBERG_TOKEN);
}
if (specOk) {
token = specToken;
}
return token;
}
/**
* Get process env variable given the input key string
* @param key
* @returns tuple where
* - the first element is the corresponding env value
* - the second element is true if the value is not undefined nor empty
*/
public getEnv(key: string): [string | undefined, boolean] {
const val = process.env[key];
return [val, val !== undefined && val !== ""];
}
}

View file

@ -21,3 +21,13 @@ export interface Configs {
backportPullRequests: BackportPullRequest[],
}
export enum AuthTokenId {
// github specific token
GITHUB_TOKEN = "GITHUB_TOKEN",
// gitlab specific token
GITLAB_TOKEN = "GITLAB_TOKEN",
// codeberg specific token
CODEBERG_TOKEN = "CODEBERG_TOKEN",
// generic git token
GIT_TOKEN = "GIT_TOKEN",
}

View file

@ -33,9 +33,19 @@ export default class PullRequestConfigsParser extends ConfigsParser {
throw new Error(`The number of backport branch names, if provided, must match the number of target branches or just one, provided ${bpBranchNames.length} branch names instead`);
}
// setup the auth token
let token = args.auth;
if (token === undefined) {
this.logger.info("Auth argument not provided, checking available tokens from env..");
token = this.getGitTokenFromEnv(this.gitClient.getClientType());
if (!token) {
this.logger.info("Git token not set in the env");
}
}
return {
dryRun: args.dryRun!,
auth: args.auth,
auth: token,
folder: `${folder.startsWith("/") ? "" : process.cwd() + "/"}${args.folder ?? this.getDefaultFolder()}`,
mergeStrategy: args.strategy,
mergeStrategyOption: args.strategyOption,

View file

@ -44,7 +44,7 @@ export default class GitClientFactory {
GitClientFactory.instance = new GitLabClient(authToken, apiUrl);
break;
case GitClientType.CODEBERG:
GitClientFactory.instance = new GitHubService(authToken, apiUrl);
GitClientFactory.instance = new GitHubService(authToken, apiUrl, true);
break;
default:
throw new Error(`Invalid git service type received: ${type}`);

View file

@ -1,4 +1,4 @@
import { BackportPullRequest, GitPullRequest } from "@bp/service/git/git.types";
import { BackportPullRequest, GitClientType, GitPullRequest } from "@bp/service/git/git.types";
/**
* Git management service interface, which provides a common API for interacting
@ -6,6 +6,11 @@ import { BackportPullRequest, GitPullRequest } from "@bp/service/git/git.types";
*/
export default interface GitClient {
/**
* @returns {GitClientType} specific git client enum type
*/
getClientType(): GitClientType
// READ
getDefaultGitUser(): string;

View file

@ -11,16 +11,22 @@ export default class GitHubClient implements GitClient {
private logger: LoggerService;
private apiUrl: string;
private isForCodeberg: boolean;
private octokit: Octokit;
private mapper: GitHubMapper;
constructor(token: string | undefined, apiUrl: string) {
constructor(token: string | undefined, apiUrl: string, isForCodeberg = false) {
this.apiUrl = apiUrl;
this.isForCodeberg = isForCodeberg;
this.logger = LoggerServiceFactory.getLogger();
this.octokit = OctokitFactory.getOctokit(token, this.apiUrl);
this.mapper = new GitHubMapper();
}
getClientType(): GitClientType {
return this.isForCodeberg ? GitClientType.CODEBERG : GitClientType.GITHUB;
}
// READ
getDefaultGitUser(): string {

View file

@ -1,6 +1,6 @@
import LoggerService from "@bp/service/logger/logger-service";
import GitClient from "@bp/service/git/git-client";
import { GitPullRequest, BackportPullRequest } from "@bp/service/git/git.types";
import { GitPullRequest, BackportPullRequest, GitClientType } from "@bp/service/git/git.types";
import LoggerServiceFactory from "@bp/service/logger/logger-service-factory";
import { CommitSchema, MergeRequestSchema, UserSchema } from "@gitbeaker/rest";
import GitLabMapper from "@bp/service/git/gitlab/gitlab-mapper";
@ -30,6 +30,10 @@ export default class GitLabClient implements GitClient {
this.mapper = new GitLabMapper(this.client);
}
getClientType(): GitClientType {
return GitClientType.GITLAB;
}
getDefaultGitUser(): string {
return "Gitlab";
}