From 5f12c50c451e799fb6300483c377f0e741958500 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Sat, 23 Mar 2024 15:38:46 +0100 Subject: [PATCH] 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. --- README.md | 1 + action.yml | 3 +++ dist/cli/index.js | 11 ++++++++++- dist/gha/index.js | 10 +++++++++- src/service/args/args-parser.ts | 1 + src/service/args/args.types.ts | 1 + src/service/args/cli/cli-args-parser.ts | 2 ++ src/service/args/gha/gha-args-parser.ts | 1 + src/service/runner/runner.ts | 7 ++++++- test/service/args/cli/cli-args-parser.test.ts | 17 +++++++++++++++++ test/service/runner/gha-github-runner.test.ts | 19 +++++++++++++++++++ 11 files changed, 70 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 800b67f..b820807 100644 --- a/README.md +++ b/README.md @@ -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 | | | 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 | +| Git Client | --git-client | N | Git client type , if not set it is infered from pull-request | Git User | -gu, --git-user | N | Local git user name | "GitHub" | | Git Email | -ge, --git-email | N | Local git user email | "noreply@github.com" | | Title | --title | N | Backporting pull request title | "{original-pr-title}" | diff --git a/action.yml b/action.yml index 04c4626..d7b5281 100644 --- a/action.yml +++ b/action.yml @@ -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" default: ${{ github.token }} required: false + git-client: + description: "Git client type , if not set it is infered from pull-request" + required: false git-user: description: "Local git user name" default: "GitHub" diff --git a/dist/cli/index.js b/dist/cli/index.js index 9d3a9d1..a3f1819 100755 --- a/dist/cli/index.js +++ b/dist/cli/index.js @@ -49,6 +49,7 @@ class ArgsParser { dryRun: this.getOrDefault(args.dryRun, false), auth: this.getOrDefault(args.auth), folder: this.getOrDefault(args.folder), + gitClient: this.getOrDefault(args.gitClient), gitUser: this.getOrDefault(args.gitUser), gitEmail: this.getOrDefault(args.gitEmail), title: this.getOrDefault(args.title), @@ -183,6 +184,7 @@ class CLIArgsParser extends args_parser_1.default { .option("-pr, --pull-request ", "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 ", "git authentication string, if not provided fallback by looking for existing env variables like GITHUB_TOKEN") + .option("--git-client ", "git client type, if not set it is infered from --pull-request") .option("-gu, --git-user ", "local git user name, default is 'GitHub'") .option("-ge, --git-email ", "local git user email, default is 'noreply@github.com'") .option("-f, --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, targetBranch: opts.targetBranch, folder: opts.folder, + gitClient: opts.gitClient, gitUser: opts.gitUser, gitEmail: opts.gitEmail, title: opts.title, @@ -1343,7 +1346,13 @@ class Runner { this.logger.warn("Dry run enabled"); } // 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 const apiUrl = (0, git_util_1.inferGitApiUrl)(args.pullRequest, gitClientType === git_types_1.GitClientType.CODEBERG ? "v1" : undefined); const token = this.fetchToken(args, gitClientType); diff --git a/dist/gha/index.js b/dist/gha/index.js index 529a401..21cc4e7 100755 --- a/dist/gha/index.js +++ b/dist/gha/index.js @@ -49,6 +49,7 @@ class ArgsParser { dryRun: this.getOrDefault(args.dryRun, false), auth: this.getOrDefault(args.auth), folder: this.getOrDefault(args.folder), + gitClient: this.getOrDefault(args.gitClient), gitUser: this.getOrDefault(args.gitUser), gitEmail: this.getOrDefault(args.gitEmail), title: this.getOrDefault(args.title), @@ -187,6 +188,7 @@ class GHAArgsParser extends args_parser_1.default { pullRequest: (0, core_1.getInput)("pull-request"), targetBranch: (0, core_1.getInput)("target-branch"), 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")), gitEmail: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("git-email")), title: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("title")), @@ -1313,7 +1315,13 @@ class Runner { this.logger.warn("Dry run enabled"); } // 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 const apiUrl = (0, git_util_1.inferGitApiUrl)(args.pullRequest, gitClientType === git_types_1.GitClientType.CODEBERG ? "v1" : undefined); const token = this.fetchToken(args, gitClientType); diff --git a/src/service/args/args-parser.ts b/src/service/args/args-parser.ts index 1c8cb51..bc71810 100644 --- a/src/service/args/args-parser.ts +++ b/src/service/args/args-parser.ts @@ -27,6 +27,7 @@ export default abstract class ArgsParser { dryRun: this.getOrDefault(args.dryRun, false), auth: this.getOrDefault(args.auth), folder: this.getOrDefault(args.folder), + gitClient: this.getOrDefault(args.gitClient), gitUser: this.getOrDefault(args.gitUser), gitEmail: this.getOrDefault(args.gitEmail), title: this.getOrDefault(args.title), diff --git a/src/service/args/args.types.ts b/src/service/args/args.types.ts index 1a38562..2e34064 100644 --- a/src/service/args/args.types.ts +++ b/src/service/args/args.types.ts @@ -8,6 +8,7 @@ export interface Args { dryRun?: boolean, // if enabled do not push anything remotely auth?: string, // git service auth, like github token folder?: string, // local folder where the repositories should be cloned + gitClient?: string, // git client gitUser?: string, // local git user, default 'GitHub' gitEmail?: string, // local git email, default 'noreply@github.com' title?: string, // backport pr title, default original pr title prefixed by target branch diff --git a/src/service/args/cli/cli-args-parser.ts b/src/service/args/cli/cli-args-parser.ts index c8ebc92..f96cb55 100644 --- a/src/service/args/cli/cli-args-parser.ts +++ b/src/service/args/cli/cli-args-parser.ts @@ -14,6 +14,7 @@ export default class CLIArgsParser extends ArgsParser { .option("-pr, --pull-request ", "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 ", "git authentication string, if not provided fallback by looking for existing env variables like GITHUB_TOKEN") + .option("--git-client ", "git client type, if not set it is infered from --pull-request") .option("-gu, --git-user ", "local git user name, default is 'GitHub'") .option("-ge, --git-email ", "local git user email, default is 'noreply@github.com'") .option("-f, --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, targetBranch: opts.targetBranch, folder: opts.folder, + gitClient: opts.gitClient, gitUser: opts.gitUser, gitEmail: opts.gitEmail, title: opts.title, diff --git a/src/service/args/gha/gha-args-parser.ts b/src/service/args/gha/gha-args-parser.ts index 29580ab..9d0b04e 100644 --- a/src/service/args/gha/gha-args-parser.ts +++ b/src/service/args/gha/gha-args-parser.ts @@ -18,6 +18,7 @@ export default class GHAArgsParser extends ArgsParser { pullRequest: getInput("pull-request"), targetBranch: getInput("target-branch"), folder: getOrUndefined(getInput("folder")), + gitClient: getOrUndefined(getInput("git-client")), gitUser: getOrUndefined(getInput("git-user")), gitEmail: getOrUndefined(getInput("git-email")), title: getOrUndefined(getInput("title")), diff --git a/src/service/runner/runner.ts b/src/service/runner/runner.ts index 1e48193..e7db1b9 100644 --- a/src/service/runner/runner.ts +++ b/src/service/runner/runner.ts @@ -60,7 +60,12 @@ export default class Runner { } // 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 const apiUrl = inferGitApiUrl(args.pullRequest, gitClientType === GitClientType.CODEBERG ? "v1" : undefined); const token = this.fetchToken(args, gitClientType); diff --git a/test/service/args/cli/cli-args-parser.test.ts b/test/service/args/cli/cli-args-parser.test.ts index bf82586..c8b462d 100644 --- a/test/service/args/cli/cli-args-parser.test.ts +++ b/test/service/args/cli/cli-args-parser.test.ts @@ -15,6 +15,7 @@ const RANDOM_CONFIG_FILE_CONTENT = { "targetBranch": "target-branch-name", "pullRequest": "https://github.com/user/repo/pull/123", "folder": "/path/to/local/folder", + "gitClient": "codeberg", "gitUser": "YourGitUser", "gitEmail": "your-email@example.com", "title": "Backport: Original PR Title", @@ -62,6 +63,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(false); expect(args.auth).toEqual(undefined); + expect(args.gitClient).toEqual(undefined); expect(args.gitUser).toEqual(undefined); expect(args.gitEmail).toEqual(undefined); expect(args.folder).toEqual(undefined); @@ -90,6 +92,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(false); expect(args.auth).toEqual(undefined); + expect(args.gitClient).toEqual(undefined); expect(args.gitUser).toEqual(undefined); expect(args.gitEmail).toEqual(undefined); expect(args.folder).toEqual(undefined); @@ -120,6 +123,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(false); expect(args.auth).toEqual(undefined); + expect(args.gitClient).toEqual(undefined); expect(args.gitUser).toEqual(undefined); expect(args.gitEmail).toEqual(undefined); expect(args.folder).toEqual(undefined); @@ -148,6 +152,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(false); expect(args.auth).toEqual(undefined); + expect(args.gitClient).toEqual(undefined); expect(args.gitUser).toEqual(undefined); expect(args.gitEmail).toEqual(undefined); expect(args.folder).toEqual(undefined); @@ -185,6 +190,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(true); expect(args.auth).toEqual("bearer-token"); + expect(args.gitClient).toEqual(undefined); expect(args.gitUser).toEqual("Me"); expect(args.gitEmail).toEqual("me@email.com"); expect(args.folder).toEqual(undefined); @@ -213,6 +219,8 @@ describe("cli args parser", () => { "target", "--pull-request", "https://localhost/whatever/pulls/1", + "--git-client", + "codeberg", "--git-user", "Me", "--git-email", @@ -238,6 +246,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(true); expect(args.auth).toEqual("bearer-token"); + expect(args.gitClient).toEqual("codeberg"); expect(args.gitUser).toEqual("Me"); expect(args.gitEmail).toEqual("me@email.com"); expect(args.folder).toEqual(undefined); @@ -266,6 +275,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(true); expect(args.auth).toEqual("your-git-service-auth-token"); + expect(args.gitClient).toEqual("codeberg"); expect(args.gitUser).toEqual("YourGitUser"); expect(args.gitEmail).toEqual("your-email@example.com"); expect(args.folder).toEqual("/path/to/local/folder"); @@ -296,6 +306,8 @@ describe("cli args parser", () => { "target", "--pull-request", "https://localhost/whatever/pulls/1", + "--git-client", + "github", "--git-user", "Me", "--git-email", @@ -321,6 +333,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(true); expect(args.auth).toEqual("your-git-service-auth-token"); + expect(args.gitClient).toEqual("codeberg"); expect(args.gitUser).toEqual("YourGitUser"); expect(args.gitEmail).toEqual("your-email@example.com"); expect(args.folder).toEqual("/path/to/local/folder"); @@ -352,6 +365,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(false); expect(args.auth).toEqual(undefined); + expect(args.gitClient).toEqual(undefined); expect(args.gitUser).toEqual(undefined); expect(args.gitEmail).toEqual(undefined); expect(args.folder).toEqual(undefined); @@ -384,6 +398,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(false); expect(args.auth).toEqual(undefined); + expect(args.gitClient).toEqual(undefined); expect(args.gitUser).toEqual(undefined); expect(args.gitEmail).toEqual(undefined); expect(args.folder).toEqual(undefined); @@ -416,6 +431,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(false); expect(args.auth).toEqual(undefined); + expect(args.gitClient).toEqual(undefined); expect(args.gitUser).toEqual(undefined); expect(args.gitEmail).toEqual(undefined); expect(args.folder).toEqual(undefined); @@ -445,6 +461,7 @@ describe("cli args parser", () => { const args: Args = parser.parse(); expect(args.dryRun).toEqual(false); expect(args.auth).toEqual(undefined); + expect(args.gitClient).toEqual(undefined); expect(args.gitUser).toEqual(undefined); expect(args.gitEmail).toEqual(undefined); expect(args.folder).toEqual(undefined); diff --git a/test/service/runner/gha-github-runner.test.ts b/test/service/runner/gha-github-runner.test.ts index 7976a9d..dfdf902 100644 --- a/test/service/runner/gha-github-runner.test.ts +++ b/test/service/runner/gha-github-runner.test.ts @@ -768,4 +768,23 @@ describe("gha runner", () => { }); 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"); + }); + }); \ No newline at end of file