feat: add --git-client to explicitly set the type of forge

codeberg is running Forgejo and it may not be possible to infer that
from the URL alone. The same is true for GitHub Enterprise Server.
This commit is contained in:
Earl Warren 2024-03-23 15:38:46 +01:00
parent 646d8fe41c
commit 5f12c50c45
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
11 changed files with 70 additions and 3 deletions

View file

@ -99,6 +99,7 @@ This tool comes with some inputs that allow users to override the default behavi
| Configuration File | -cf, --config-file | N | Configuration file, in JSON format, containing all options to be overridded, note that if provided all other CLI options will be ignored | | | Configuration File | -cf, --config-file | N | Configuration file, in JSON format, containing all options to be overridded, note that if provided all other CLI options will be ignored | |
| Auth | -a, --auth | N | Git access/authorization token, if provided all token env variables will be ignored. See [auth token](#authorization-token) section for more details | "" | | Auth | -a, --auth | N | Git access/authorization token, if provided all token env variables will be ignored. See [auth token](#authorization-token) section for more details | "" |
| Folder | -f, --folder | N | Local folder full name of the repository that will be checked out, e.g., /tmp/folder | {cwd}/bp | | Folder | -f, --folder | N | Local folder full name of the repository that will be checked out, e.g., /tmp/folder | {cwd}/bp |
| Git Client | --git-client | N | Git client type <github|gitlab|codeberg>, if not set it is infered from pull-request
| Git User | -gu, --git-user | N | Local git user name | "GitHub" | | Git User | -gu, --git-user | N | Local git user name | "GitHub" |
| Git Email | -ge, --git-email | N | Local git user email | "noreply@github.com" | | Git Email | -ge, --git-email | N | Local git user email | "noreply@github.com" |
| Title | --title | N | Backporting pull request title | "{original-pr-title}" | | Title | --title | N | Backporting pull request title | "{original-pr-title}" |

View file

@ -18,6 +18,9 @@ inputs:
description: "GITHUB_TOKEN or a `repo` scoped Personal Access Token (PAT), if not provided will look for existing env variables like GITHUB_TOKEN" description: "GITHUB_TOKEN or a `repo` scoped Personal Access Token (PAT), if not provided will look for existing env variables like GITHUB_TOKEN"
default: ${{ github.token }} default: ${{ github.token }}
required: false required: false
git-client:
description: "Git client type <github|gitlab|codeberg>, if not set it is infered from pull-request"
required: false
git-user: git-user:
description: "Local git user name" description: "Local git user name"
default: "GitHub" default: "GitHub"

11
dist/cli/index.js vendored
View file

@ -49,6 +49,7 @@ class ArgsParser {
dryRun: this.getOrDefault(args.dryRun, false), dryRun: this.getOrDefault(args.dryRun, false),
auth: this.getOrDefault(args.auth), auth: this.getOrDefault(args.auth),
folder: this.getOrDefault(args.folder), folder: this.getOrDefault(args.folder),
gitClient: this.getOrDefault(args.gitClient),
gitUser: this.getOrDefault(args.gitUser), gitUser: this.getOrDefault(args.gitUser),
gitEmail: this.getOrDefault(args.gitEmail), gitEmail: this.getOrDefault(args.gitEmail),
title: this.getOrDefault(args.title), title: this.getOrDefault(args.title),
@ -183,6 +184,7 @@ class CLIArgsParser extends args_parser_1.default {
.option("-pr, --pull-request <pr-url>", "pull request url, e.g., https://github.com/kiegroup/git-backporting/pull/1") .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("-d, --dry-run", "if enabled the tool does not create any pull request nor push anything remotely")
.option("-a, --auth <auth>", "git authentication string, if not provided fallback by looking for existing env variables like GITHUB_TOKEN") .option("-a, --auth <auth>", "git authentication string, if not provided fallback by looking for existing env variables like GITHUB_TOKEN")
.option("--git-client <github|gitlab|codeberg>", "git client type, if not set it is infered from --pull-request")
.option("-gu, --git-user <git-user>", "local git user name, default is 'GitHub'") .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("-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") .option("-f, --folder <folder>", "local folder where the repo will be checked out, e.g., /tmp/folder")
@ -217,6 +219,7 @@ class CLIArgsParser extends args_parser_1.default {
pullRequest: opts.pullRequest, pullRequest: opts.pullRequest,
targetBranch: opts.targetBranch, targetBranch: opts.targetBranch,
folder: opts.folder, folder: opts.folder,
gitClient: opts.gitClient,
gitUser: opts.gitUser, gitUser: opts.gitUser,
gitEmail: opts.gitEmail, gitEmail: opts.gitEmail,
title: opts.title, title: opts.title,
@ -1343,7 +1346,13 @@ class Runner {
this.logger.warn("Dry run enabled"); this.logger.warn("Dry run enabled");
} }
// 2. init git service // 2. init git service
const gitClientType = (0, git_util_1.inferGitClient)(args.pullRequest); let gitClientType;
if (args.gitClient === undefined) {
gitClientType = (0, git_util_1.inferGitClient)(args.pullRequest);
}
else {
gitClientType = args.gitClient;
}
// the api version is ignored in case of github // the api version is ignored in case of github
const apiUrl = (0, git_util_1.inferGitApiUrl)(args.pullRequest, gitClientType === git_types_1.GitClientType.CODEBERG ? "v1" : undefined); const apiUrl = (0, git_util_1.inferGitApiUrl)(args.pullRequest, gitClientType === git_types_1.GitClientType.CODEBERG ? "v1" : undefined);
const token = this.fetchToken(args, gitClientType); const token = this.fetchToken(args, gitClientType);

10
dist/gha/index.js vendored
View file

@ -49,6 +49,7 @@ class ArgsParser {
dryRun: this.getOrDefault(args.dryRun, false), dryRun: this.getOrDefault(args.dryRun, false),
auth: this.getOrDefault(args.auth), auth: this.getOrDefault(args.auth),
folder: this.getOrDefault(args.folder), folder: this.getOrDefault(args.folder),
gitClient: this.getOrDefault(args.gitClient),
gitUser: this.getOrDefault(args.gitUser), gitUser: this.getOrDefault(args.gitUser),
gitEmail: this.getOrDefault(args.gitEmail), gitEmail: this.getOrDefault(args.gitEmail),
title: this.getOrDefault(args.title), title: this.getOrDefault(args.title),
@ -187,6 +188,7 @@ class GHAArgsParser extends args_parser_1.default {
pullRequest: (0, core_1.getInput)("pull-request"), pullRequest: (0, core_1.getInput)("pull-request"),
targetBranch: (0, core_1.getInput)("target-branch"), targetBranch: (0, core_1.getInput)("target-branch"),
folder: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("folder")), folder: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("folder")),
gitClient: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("git-client")),
gitUser: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("git-user")), gitUser: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("git-user")),
gitEmail: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("git-email")), gitEmail: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("git-email")),
title: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("title")), title: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("title")),
@ -1313,7 +1315,13 @@ class Runner {
this.logger.warn("Dry run enabled"); this.logger.warn("Dry run enabled");
} }
// 2. init git service // 2. init git service
const gitClientType = (0, git_util_1.inferGitClient)(args.pullRequest); let gitClientType;
if (args.gitClient === undefined) {
gitClientType = (0, git_util_1.inferGitClient)(args.pullRequest);
}
else {
gitClientType = args.gitClient;
}
// the api version is ignored in case of github // the api version is ignored in case of github
const apiUrl = (0, git_util_1.inferGitApiUrl)(args.pullRequest, gitClientType === git_types_1.GitClientType.CODEBERG ? "v1" : undefined); const apiUrl = (0, git_util_1.inferGitApiUrl)(args.pullRequest, gitClientType === git_types_1.GitClientType.CODEBERG ? "v1" : undefined);
const token = this.fetchToken(args, gitClientType); const token = this.fetchToken(args, gitClientType);

View file

@ -27,6 +27,7 @@ export default abstract class ArgsParser {
dryRun: this.getOrDefault(args.dryRun, false), dryRun: this.getOrDefault(args.dryRun, false),
auth: this.getOrDefault(args.auth), auth: this.getOrDefault(args.auth),
folder: this.getOrDefault(args.folder), folder: this.getOrDefault(args.folder),
gitClient: this.getOrDefault(args.gitClient),
gitUser: this.getOrDefault(args.gitUser), gitUser: this.getOrDefault(args.gitUser),
gitEmail: this.getOrDefault(args.gitEmail), gitEmail: this.getOrDefault(args.gitEmail),
title: this.getOrDefault(args.title), title: this.getOrDefault(args.title),

View file

@ -8,6 +8,7 @@ export interface Args {
dryRun?: boolean, // if enabled do not push anything remotely dryRun?: boolean, // if enabled do not push anything remotely
auth?: string, // git service auth, like github token auth?: string, // git service auth, like github token
folder?: string, // local folder where the repositories should be cloned folder?: string, // local folder where the repositories should be cloned
gitClient?: string, // git client
gitUser?: string, // local git user, default 'GitHub' gitUser?: string, // local git user, default 'GitHub'
gitEmail?: string, // local git email, default 'noreply@github.com' gitEmail?: string, // local git email, default 'noreply@github.com'
title?: string, // backport pr title, default original pr title prefixed by target branch title?: string, // backport pr title, default original pr title prefixed by target branch

View file

@ -14,6 +14,7 @@ export default class CLIArgsParser extends ArgsParser {
.option("-pr, --pull-request <pr-url>", "pull request url, e.g., https://github.com/kiegroup/git-backporting/pull/1") .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("-d, --dry-run", "if enabled the tool does not create any pull request nor push anything remotely")
.option("-a, --auth <auth>", "git authentication string, if not provided fallback by looking for existing env variables like GITHUB_TOKEN") .option("-a, --auth <auth>", "git authentication string, if not provided fallback by looking for existing env variables like GITHUB_TOKEN")
.option("--git-client <github|gitlab|codeberg>", "git client type, if not set it is infered from --pull-request")
.option("-gu, --git-user <git-user>", "local git user name, default is 'GitHub'") .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("-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") .option("-f, --folder <folder>", "local folder where the repo will be checked out, e.g., /tmp/folder")
@ -49,6 +50,7 @@ export default class CLIArgsParser extends ArgsParser {
pullRequest: opts.pullRequest, pullRequest: opts.pullRequest,
targetBranch: opts.targetBranch, targetBranch: opts.targetBranch,
folder: opts.folder, folder: opts.folder,
gitClient: opts.gitClient,
gitUser: opts.gitUser, gitUser: opts.gitUser,
gitEmail: opts.gitEmail, gitEmail: opts.gitEmail,
title: opts.title, title: opts.title,

View file

@ -18,6 +18,7 @@ export default class GHAArgsParser extends ArgsParser {
pullRequest: getInput("pull-request"), pullRequest: getInput("pull-request"),
targetBranch: getInput("target-branch"), targetBranch: getInput("target-branch"),
folder: getOrUndefined(getInput("folder")), folder: getOrUndefined(getInput("folder")),
gitClient: getOrUndefined(getInput("git-client")),
gitUser: getOrUndefined(getInput("git-user")), gitUser: getOrUndefined(getInput("git-user")),
gitEmail: getOrUndefined(getInput("git-email")), gitEmail: getOrUndefined(getInput("git-email")),
title: getOrUndefined(getInput("title")), title: getOrUndefined(getInput("title")),

View file

@ -60,7 +60,12 @@ export default class Runner {
} }
// 2. init git service // 2. init git service
const gitClientType: GitClientType = inferGitClient(args.pullRequest); let gitClientType: GitClientType;
if (args.gitClient === undefined) {
gitClientType = inferGitClient(args.pullRequest);
} else {
gitClientType = args.gitClient as GitClientType;
}
// the api version is ignored in case of github // the api version is ignored in case of github
const apiUrl = inferGitApiUrl(args.pullRequest, gitClientType === GitClientType.CODEBERG ? "v1" : undefined); const apiUrl = inferGitApiUrl(args.pullRequest, gitClientType === GitClientType.CODEBERG ? "v1" : undefined);
const token = this.fetchToken(args, gitClientType); const token = this.fetchToken(args, gitClientType);

View file

@ -15,6 +15,7 @@ const RANDOM_CONFIG_FILE_CONTENT = {
"targetBranch": "target-branch-name", "targetBranch": "target-branch-name",
"pullRequest": "https://github.com/user/repo/pull/123", "pullRequest": "https://github.com/user/repo/pull/123",
"folder": "/path/to/local/folder", "folder": "/path/to/local/folder",
"gitClient": "codeberg",
"gitUser": "YourGitUser", "gitUser": "YourGitUser",
"gitEmail": "your-email@example.com", "gitEmail": "your-email@example.com",
"title": "Backport: Original PR Title", "title": "Backport: Original PR Title",
@ -62,6 +63,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(false); expect(args.dryRun).toEqual(false);
expect(args.auth).toEqual(undefined); expect(args.auth).toEqual(undefined);
expect(args.gitClient).toEqual(undefined);
expect(args.gitUser).toEqual(undefined); expect(args.gitUser).toEqual(undefined);
expect(args.gitEmail).toEqual(undefined); expect(args.gitEmail).toEqual(undefined);
expect(args.folder).toEqual(undefined); expect(args.folder).toEqual(undefined);
@ -90,6 +92,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(false); expect(args.dryRun).toEqual(false);
expect(args.auth).toEqual(undefined); expect(args.auth).toEqual(undefined);
expect(args.gitClient).toEqual(undefined);
expect(args.gitUser).toEqual(undefined); expect(args.gitUser).toEqual(undefined);
expect(args.gitEmail).toEqual(undefined); expect(args.gitEmail).toEqual(undefined);
expect(args.folder).toEqual(undefined); expect(args.folder).toEqual(undefined);
@ -120,6 +123,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(false); expect(args.dryRun).toEqual(false);
expect(args.auth).toEqual(undefined); expect(args.auth).toEqual(undefined);
expect(args.gitClient).toEqual(undefined);
expect(args.gitUser).toEqual(undefined); expect(args.gitUser).toEqual(undefined);
expect(args.gitEmail).toEqual(undefined); expect(args.gitEmail).toEqual(undefined);
expect(args.folder).toEqual(undefined); expect(args.folder).toEqual(undefined);
@ -148,6 +152,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(false); expect(args.dryRun).toEqual(false);
expect(args.auth).toEqual(undefined); expect(args.auth).toEqual(undefined);
expect(args.gitClient).toEqual(undefined);
expect(args.gitUser).toEqual(undefined); expect(args.gitUser).toEqual(undefined);
expect(args.gitEmail).toEqual(undefined); expect(args.gitEmail).toEqual(undefined);
expect(args.folder).toEqual(undefined); expect(args.folder).toEqual(undefined);
@ -185,6 +190,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(true); expect(args.dryRun).toEqual(true);
expect(args.auth).toEqual("bearer-token"); expect(args.auth).toEqual("bearer-token");
expect(args.gitClient).toEqual(undefined);
expect(args.gitUser).toEqual("Me"); expect(args.gitUser).toEqual("Me");
expect(args.gitEmail).toEqual("me@email.com"); expect(args.gitEmail).toEqual("me@email.com");
expect(args.folder).toEqual(undefined); expect(args.folder).toEqual(undefined);
@ -213,6 +219,8 @@ describe("cli args parser", () => {
"target", "target",
"--pull-request", "--pull-request",
"https://localhost/whatever/pulls/1", "https://localhost/whatever/pulls/1",
"--git-client",
"codeberg",
"--git-user", "--git-user",
"Me", "Me",
"--git-email", "--git-email",
@ -238,6 +246,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(true); expect(args.dryRun).toEqual(true);
expect(args.auth).toEqual("bearer-token"); expect(args.auth).toEqual("bearer-token");
expect(args.gitClient).toEqual("codeberg");
expect(args.gitUser).toEqual("Me"); expect(args.gitUser).toEqual("Me");
expect(args.gitEmail).toEqual("me@email.com"); expect(args.gitEmail).toEqual("me@email.com");
expect(args.folder).toEqual(undefined); expect(args.folder).toEqual(undefined);
@ -266,6 +275,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(true); expect(args.dryRun).toEqual(true);
expect(args.auth).toEqual("your-git-service-auth-token"); expect(args.auth).toEqual("your-git-service-auth-token");
expect(args.gitClient).toEqual("codeberg");
expect(args.gitUser).toEqual("YourGitUser"); expect(args.gitUser).toEqual("YourGitUser");
expect(args.gitEmail).toEqual("your-email@example.com"); expect(args.gitEmail).toEqual("your-email@example.com");
expect(args.folder).toEqual("/path/to/local/folder"); expect(args.folder).toEqual("/path/to/local/folder");
@ -296,6 +306,8 @@ describe("cli args parser", () => {
"target", "target",
"--pull-request", "--pull-request",
"https://localhost/whatever/pulls/1", "https://localhost/whatever/pulls/1",
"--git-client",
"github",
"--git-user", "--git-user",
"Me", "Me",
"--git-email", "--git-email",
@ -321,6 +333,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(true); expect(args.dryRun).toEqual(true);
expect(args.auth).toEqual("your-git-service-auth-token"); expect(args.auth).toEqual("your-git-service-auth-token");
expect(args.gitClient).toEqual("codeberg");
expect(args.gitUser).toEqual("YourGitUser"); expect(args.gitUser).toEqual("YourGitUser");
expect(args.gitEmail).toEqual("your-email@example.com"); expect(args.gitEmail).toEqual("your-email@example.com");
expect(args.folder).toEqual("/path/to/local/folder"); expect(args.folder).toEqual("/path/to/local/folder");
@ -352,6 +365,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(false); expect(args.dryRun).toEqual(false);
expect(args.auth).toEqual(undefined); expect(args.auth).toEqual(undefined);
expect(args.gitClient).toEqual(undefined);
expect(args.gitUser).toEqual(undefined); expect(args.gitUser).toEqual(undefined);
expect(args.gitEmail).toEqual(undefined); expect(args.gitEmail).toEqual(undefined);
expect(args.folder).toEqual(undefined); expect(args.folder).toEqual(undefined);
@ -384,6 +398,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(false); expect(args.dryRun).toEqual(false);
expect(args.auth).toEqual(undefined); expect(args.auth).toEqual(undefined);
expect(args.gitClient).toEqual(undefined);
expect(args.gitUser).toEqual(undefined); expect(args.gitUser).toEqual(undefined);
expect(args.gitEmail).toEqual(undefined); expect(args.gitEmail).toEqual(undefined);
expect(args.folder).toEqual(undefined); expect(args.folder).toEqual(undefined);
@ -416,6 +431,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(false); expect(args.dryRun).toEqual(false);
expect(args.auth).toEqual(undefined); expect(args.auth).toEqual(undefined);
expect(args.gitClient).toEqual(undefined);
expect(args.gitUser).toEqual(undefined); expect(args.gitUser).toEqual(undefined);
expect(args.gitEmail).toEqual(undefined); expect(args.gitEmail).toEqual(undefined);
expect(args.folder).toEqual(undefined); expect(args.folder).toEqual(undefined);
@ -445,6 +461,7 @@ describe("cli args parser", () => {
const args: Args = parser.parse(); const args: Args = parser.parse();
expect(args.dryRun).toEqual(false); expect(args.dryRun).toEqual(false);
expect(args.auth).toEqual(undefined); expect(args.auth).toEqual(undefined);
expect(args.gitClient).toEqual(undefined);
expect(args.gitUser).toEqual(undefined); expect(args.gitUser).toEqual(undefined);
expect(args.gitEmail).toEqual(undefined); expect(args.gitEmail).toEqual(undefined);
expect(args.folder).toEqual(undefined); expect(args.folder).toEqual(undefined);

View file

@ -768,4 +768,23 @@ describe("gha runner", () => {
}); });
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(3); expect(GitHubClient.prototype.createPullRequest).toReturnTimes(3);
}); });
test("explicitly set git client", async () => {
spyGetInput({
"target-branch": "target",
"pull-request": "https://api.github.com/repos/owner/reponame/pulls/2368",
"git-client": "codeberg",
});
await runner.execute();
const cwd = process.cwd() + "/bp";
expect(GitClientFactory.getOrCreate).toBeCalledTimes(1);
expect(GitClientFactory.getOrCreate).toBeCalledWith(GitClientType.CODEBERG, undefined, "https://api.github.com");
expect(GitCLIService.prototype.clone).toBeCalledTimes(1);
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "target");
});
}); });