mirror of
https://code.forgejo.org/actions/git-backporting
synced 2025-03-14 22:27:02 +01:00
feat: integrate with codeberg (#80)
This commit is contained in:
parent
eecbff34b7
commit
9f0fbc0b2f
11 changed files with 72 additions and 25 deletions
|
@ -31,7 +31,7 @@ Table of content
|
|||
|
||||
## Who is this tool for?
|
||||
|
||||
`git-backporting` is a tool that provides capabilities to *backport* pull requests (on *GitHub*) and merge requests (on *GitLab*) in an automated way.
|
||||
`git-backporting` is a fully configurable tool that provides capabilities to *backport* pull requests (on *GitHub*) and merge requests (on *GitLab*) in an automated way.
|
||||
|
||||
> *What is backporting?* - backporting is an action aiming to move a change (usually a commit) from a branch (usually the main one) to another one, which is generally referring to a still maintained release branch. Keeping it simple: it is about to move a specific change or a set of them from one branch to another.
|
||||
|
||||
|
@ -139,6 +139,8 @@ Right now **Git Backporting** supports the following git management services:
|
|||
|
||||
* ***GITLAB***: This has been introduced since version `3.0.0`, it works for both public and private *GitLab* servers. The interaction with this service is performed using plain [*axios*](https://axios-http.com) requests. The *gitlab* api version that is used to make requests is `v4`, at the moment there is no possibility to override it.
|
||||
|
||||
* ***CODEBERG***: Introduced since version `4.4.0`, it works for public [codeberg.org](https://codeberg.org/) platform. Thanks to the api compatibility with GitHub, the interaction with this service is performed using using [*octokit*](https://octokit.github.io/rest.js) client library.
|
||||
|
||||
> **NOTE**: by default, all gitlab requests are performed setting `rejectUnauthorized=false`, planning to make this configurable too.
|
||||
|
||||
## GitHub action
|
||||
|
|
22
dist/cli/index.js
vendored
22
dist/cli/index.js
vendored
|
@ -566,6 +566,9 @@ class GitClientFactory {
|
|||
case git_types_1.GitClientType.GITLAB:
|
||||
GitClientFactory.instance = new gitlab_client_1.default(authToken, apiUrl);
|
||||
break;
|
||||
case git_types_1.GitClientType.CODEBERG:
|
||||
GitClientFactory.instance = new github_client_1.default(authToken, apiUrl);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Invalid git service type received: ${type}`);
|
||||
}
|
||||
|
@ -607,6 +610,9 @@ const inferGitClient = (prUrl) => {
|
|||
else if (stdPrUrl.includes(git_types_1.GitClientType.GITLAB.toString())) {
|
||||
return git_types_1.GitClientType.GITLAB;
|
||||
}
|
||||
else if (stdPrUrl.includes(git_types_1.GitClientType.CODEBERG.toString())) {
|
||||
return git_types_1.GitClientType.CODEBERG;
|
||||
}
|
||||
throw new Error(`Remote git service not recognized from pr url: ${prUrl}`);
|
||||
};
|
||||
exports.inferGitClient = inferGitClient;
|
||||
|
@ -640,6 +646,7 @@ var GitClientType;
|
|||
(function (GitClientType) {
|
||||
GitClientType["GITHUB"] = "github";
|
||||
GitClientType["GITLAB"] = "gitlab";
|
||||
GitClientType["CODEBERG"] = "codeberg";
|
||||
})(GitClientType = exports.GitClientType || (exports.GitClientType = {}));
|
||||
var GitRepoState;
|
||||
(function (GitRepoState) {
|
||||
|
@ -661,6 +668,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
const git_types_1 = __nccwpck_require__(750);
|
||||
const github_mapper_1 = __importDefault(__nccwpck_require__(5764));
|
||||
const octokit_factory_1 = __importDefault(__nccwpck_require__(4257));
|
||||
const logger_service_factory_1 = __importDefault(__nccwpck_require__(8936));
|
||||
|
@ -673,7 +681,7 @@ class GitHubClient {
|
|||
}
|
||||
// READ
|
||||
getDefaultGitUser() {
|
||||
return "GitHub";
|
||||
return this.apiUrl.includes(git_types_1.GitClientType.CODEBERG.toString()) ? "Codeberg" : "GitHub";
|
||||
}
|
||||
getDefaultGitEmail() {
|
||||
return "noreply@github.com";
|
||||
|
@ -806,9 +814,9 @@ class GitHubMapper {
|
|||
state: this.mapGitState(pr.state),
|
||||
merged: pr.merged ?? false,
|
||||
mergedBy: pr.merged_by?.login,
|
||||
reviewers: pr.requested_reviewers.filter(r => "login" in r).map((r => r?.login)),
|
||||
assignees: pr.assignees.filter(r => "login" in r).map(r => r.login),
|
||||
labels: pr.labels.map(l => l.name),
|
||||
reviewers: pr.requested_reviewers?.filter(r => "login" in r).map((r => r?.login)) ?? [],
|
||||
assignees: pr.assignees?.filter(r => "login" in r).map(r => r.login) ?? [],
|
||||
labels: pr.labels?.map(l => l.name) ?? [],
|
||||
sourceRepo: await this.mapSourceRepo(pr),
|
||||
targetRepo: await this.mapTargetRepo(pr),
|
||||
nCommits: pr.commits,
|
||||
|
@ -1260,8 +1268,8 @@ class Runner {
|
|||
}
|
||||
// 2. init git service
|
||||
const gitClientType = (0, git_util_1.inferGitClient)(args.pullRequest);
|
||||
// right now the apiVersion is set to v4
|
||||
const apiUrl = (0, git_util_1.inferGitApiUrl)(args.pullRequest);
|
||||
// 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 gitApi = git_client_factory_1.default.getOrCreate(gitClientType, args.auth, apiUrl);
|
||||
// 3. parse configs
|
||||
this.logger.debug("Parsing configs..");
|
||||
|
@ -1302,7 +1310,7 @@ class Runner {
|
|||
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
||||
configs.originalPullRequest.state === "open") {
|
||||
this.logger.debug("Fetching pull request remote..");
|
||||
const prefix = git.gitClientType === git_types_1.GitClientType.GITHUB ? "pull" : "merge-requests"; // default is for gitlab
|
||||
const prefix = git.gitClientType === git_types_1.GitClientType.GITLAB ? "merge-requests" : "pull"; // default is for gitlab
|
||||
await git.gitCli.fetch(configs.folder, `${prefix}/${configs.originalPullRequest.number}/head:pr/${configs.originalPullRequest.number}`);
|
||||
}
|
||||
// 7. apply all changes to the new branch
|
||||
|
|
22
dist/gha/index.js
vendored
22
dist/gha/index.js
vendored
|
@ -536,6 +536,9 @@ class GitClientFactory {
|
|||
case git_types_1.GitClientType.GITLAB:
|
||||
GitClientFactory.instance = new gitlab_client_1.default(authToken, apiUrl);
|
||||
break;
|
||||
case git_types_1.GitClientType.CODEBERG:
|
||||
GitClientFactory.instance = new github_client_1.default(authToken, apiUrl);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Invalid git service type received: ${type}`);
|
||||
}
|
||||
|
@ -577,6 +580,9 @@ const inferGitClient = (prUrl) => {
|
|||
else if (stdPrUrl.includes(git_types_1.GitClientType.GITLAB.toString())) {
|
||||
return git_types_1.GitClientType.GITLAB;
|
||||
}
|
||||
else if (stdPrUrl.includes(git_types_1.GitClientType.CODEBERG.toString())) {
|
||||
return git_types_1.GitClientType.CODEBERG;
|
||||
}
|
||||
throw new Error(`Remote git service not recognized from pr url: ${prUrl}`);
|
||||
};
|
||||
exports.inferGitClient = inferGitClient;
|
||||
|
@ -610,6 +616,7 @@ var GitClientType;
|
|||
(function (GitClientType) {
|
||||
GitClientType["GITHUB"] = "github";
|
||||
GitClientType["GITLAB"] = "gitlab";
|
||||
GitClientType["CODEBERG"] = "codeberg";
|
||||
})(GitClientType = exports.GitClientType || (exports.GitClientType = {}));
|
||||
var GitRepoState;
|
||||
(function (GitRepoState) {
|
||||
|
@ -631,6 +638,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
const git_types_1 = __nccwpck_require__(750);
|
||||
const github_mapper_1 = __importDefault(__nccwpck_require__(5764));
|
||||
const octokit_factory_1 = __importDefault(__nccwpck_require__(4257));
|
||||
const logger_service_factory_1 = __importDefault(__nccwpck_require__(8936));
|
||||
|
@ -643,7 +651,7 @@ class GitHubClient {
|
|||
}
|
||||
// READ
|
||||
getDefaultGitUser() {
|
||||
return "GitHub";
|
||||
return this.apiUrl.includes(git_types_1.GitClientType.CODEBERG.toString()) ? "Codeberg" : "GitHub";
|
||||
}
|
||||
getDefaultGitEmail() {
|
||||
return "noreply@github.com";
|
||||
|
@ -776,9 +784,9 @@ class GitHubMapper {
|
|||
state: this.mapGitState(pr.state),
|
||||
merged: pr.merged ?? false,
|
||||
mergedBy: pr.merged_by?.login,
|
||||
reviewers: pr.requested_reviewers.filter(r => "login" in r).map((r => r?.login)),
|
||||
assignees: pr.assignees.filter(r => "login" in r).map(r => r.login),
|
||||
labels: pr.labels.map(l => l.name),
|
||||
reviewers: pr.requested_reviewers?.filter(r => "login" in r).map((r => r?.login)) ?? [],
|
||||
assignees: pr.assignees?.filter(r => "login" in r).map(r => r.login) ?? [],
|
||||
labels: pr.labels?.map(l => l.name) ?? [],
|
||||
sourceRepo: await this.mapSourceRepo(pr),
|
||||
targetRepo: await this.mapTargetRepo(pr),
|
||||
nCommits: pr.commits,
|
||||
|
@ -1230,8 +1238,8 @@ class Runner {
|
|||
}
|
||||
// 2. init git service
|
||||
const gitClientType = (0, git_util_1.inferGitClient)(args.pullRequest);
|
||||
// right now the apiVersion is set to v4
|
||||
const apiUrl = (0, git_util_1.inferGitApiUrl)(args.pullRequest);
|
||||
// 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 gitApi = git_client_factory_1.default.getOrCreate(gitClientType, args.auth, apiUrl);
|
||||
// 3. parse configs
|
||||
this.logger.debug("Parsing configs..");
|
||||
|
@ -1272,7 +1280,7 @@ class Runner {
|
|||
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
||||
configs.originalPullRequest.state === "open") {
|
||||
this.logger.debug("Fetching pull request remote..");
|
||||
const prefix = git.gitClientType === git_types_1.GitClientType.GITHUB ? "pull" : "merge-requests"; // default is for gitlab
|
||||
const prefix = git.gitClientType === git_types_1.GitClientType.GITLAB ? "merge-requests" : "pull"; // default is for gitlab
|
||||
await git.gitCli.fetch(configs.folder, `${prefix}/${configs.originalPullRequest.number}/head:pr/${configs.originalPullRequest.number}`);
|
||||
}
|
||||
// 7. apply all changes to the new branch
|
||||
|
|
|
@ -43,6 +43,9 @@ export default class GitClientFactory {
|
|||
case GitClientType.GITLAB:
|
||||
GitClientFactory.instance = new GitLabClient(authToken, apiUrl);
|
||||
break;
|
||||
case GitClientType.CODEBERG:
|
||||
GitClientFactory.instance = new GitHubService(authToken, apiUrl);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Invalid git service type received: ${type}`);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ export const inferGitClient = (prUrl: string): GitClientType => {
|
|||
return GitClientType.GITHUB;
|
||||
} else if (stdPrUrl.includes(GitClientType.GITLAB.toString())) {
|
||||
return GitClientType.GITLAB;
|
||||
} else if (stdPrUrl.includes(GitClientType.CODEBERG.toString())) {
|
||||
return GitClientType.CODEBERG;
|
||||
}
|
||||
|
||||
throw new Error(`Remote git service not recognized from pr url: ${prUrl}`);
|
||||
|
|
|
@ -41,6 +41,7 @@ export interface BackportPullRequest {
|
|||
export enum GitClientType {
|
||||
GITHUB = "github",
|
||||
GITLAB = "gitlab",
|
||||
CODEBERG = "codeberg",
|
||||
}
|
||||
|
||||
export enum GitRepoState {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import GitClient from "@bp/service/git/git-client";
|
||||
import { BackportPullRequest, GitPullRequest } from "@bp/service/git/git.types";
|
||||
import { BackportPullRequest, GitClientType, GitPullRequest } from "@bp/service/git/git.types";
|
||||
import GitHubMapper from "@bp/service/git/github/github-mapper";
|
||||
import OctokitFactory from "@bp/service/git/github/octokit-factory";
|
||||
import LoggerService from "@bp/service/logger/logger-service";
|
||||
|
@ -24,7 +24,7 @@ export default class GitHubClient implements GitClient {
|
|||
// READ
|
||||
|
||||
getDefaultGitUser(): string {
|
||||
return "GitHub";
|
||||
return this.apiUrl.includes(GitClientType.CODEBERG.toString()) ? "Codeberg" : "GitHub";
|
||||
}
|
||||
|
||||
getDefaultGitEmail(): string {
|
||||
|
|
|
@ -24,9 +24,9 @@ export default class GitHubMapper implements GitResponseMapper<PullRequest, "ope
|
|||
state: this.mapGitState(pr.state), // TODO fix using custom mapper
|
||||
merged: pr.merged ?? false,
|
||||
mergedBy: pr.merged_by?.login,
|
||||
reviewers: pr.requested_reviewers.filter(r => "login" in r).map((r => (r as User)?.login)),
|
||||
assignees: pr.assignees.filter(r => "login" in r).map(r => r.login),
|
||||
labels: pr.labels.map(l => l.name),
|
||||
reviewers: pr.requested_reviewers?.filter(r => "login" in r).map((r => (r as User)?.login)) ?? [],
|
||||
assignees: pr.assignees?.filter(r => "login" in r).map(r => r.login) ?? [],
|
||||
labels: pr.labels?.map(l => l.name) ?? [],
|
||||
sourceRepo: await this.mapSourceRepo(pr),
|
||||
targetRepo: await this.mapTargetRepo(pr),
|
||||
nCommits: pr.commits,
|
||||
|
|
|
@ -61,8 +61,8 @@ export default class Runner {
|
|||
|
||||
// 2. init git service
|
||||
const gitClientType: GitClientType = inferGitClient(args.pullRequest);
|
||||
// right now the apiVersion is set to v4
|
||||
const apiUrl = inferGitApiUrl(args.pullRequest);
|
||||
// the api version is ignored in case of github
|
||||
const apiUrl = inferGitApiUrl(args.pullRequest, gitClientType === GitClientType.CODEBERG ? "v1" : undefined);
|
||||
const gitApi: GitClient = GitClientFactory.getOrCreate(gitClientType, args.auth, apiUrl);
|
||||
|
||||
// 3. parse configs
|
||||
|
@ -112,7 +112,7 @@ export default class Runner {
|
|||
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
||||
configs.originalPullRequest.state === "open") {
|
||||
this.logger.debug("Fetching pull request remote..");
|
||||
const prefix = git.gitClientType === GitClientType.GITHUB ? "pull" : "merge-requests"; // default is for gitlab
|
||||
const prefix = git.gitClientType === GitClientType.GITLAB ? "merge-requests" : "pull" ; // default is for gitlab
|
||||
await git.gitCli.fetch(configs.folder, `${prefix}/${configs.originalPullRequest.number}/head:pr/${configs.originalPullRequest.number}`);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,11 @@ describe("git client factory test", () => {
|
|||
expect(client).toBeInstanceOf(GitLabClient);
|
||||
});
|
||||
|
||||
test("correctly create codeberg client", () => {
|
||||
const client = GitClientFactory.getOrCreate(GitClientType.CODEBERG, "auth", "apiurl");
|
||||
expect(client).toBeInstanceOf(GitHubClient);
|
||||
});
|
||||
|
||||
test("check get service github", () => {
|
||||
const create = GitClientFactory.getOrCreate(GitClientType.GITHUB, "auth", "apiurl");
|
||||
const get = GitClientFactory.getClient();
|
||||
|
@ -31,4 +36,10 @@ describe("git client factory test", () => {
|
|||
const get = GitClientFactory.getClient();
|
||||
expect(create).toStrictEqual(get);
|
||||
});
|
||||
|
||||
test("check get service codeberg", () => {
|
||||
const create = GitClientFactory.getOrCreate(GitClientType.CODEBERG, "auth", "apiurl");
|
||||
const get = GitClientFactory.getClient();
|
||||
expect(create).toStrictEqual(get);
|
||||
});
|
||||
});
|
|
@ -23,6 +23,18 @@ describe("check git utilities", () => {
|
|||
expect(inferGitApiUrl("http://github.acme-inc.com/superuser/backporting-example/pull/4", "v3")).toStrictEqual("http://github.acme-inc.com/api/v3");
|
||||
});
|
||||
|
||||
test("check infer github api from github api url", ()=> {
|
||||
expect(inferGitApiUrl("https://api.github.com/repos/owner/repo/pulls/1")).toStrictEqual("https://api.github.com");
|
||||
});
|
||||
|
||||
test("check infer codeberg api", ()=> {
|
||||
expect(inferGitApiUrl("https://codeberg.org/lampajr/backporting-example/pulls/1", "v1")).toStrictEqual("https://codeberg.org/api/v1");
|
||||
});
|
||||
|
||||
test("check infer codeberg api", ()=> {
|
||||
expect(inferGitApiUrl("https://codeberg.org/lampajr/backporting-example/pulls/1", undefined)).toStrictEqual("https://codeberg.org/api/v4");
|
||||
});
|
||||
|
||||
test("check infer github client", ()=> {
|
||||
expect(inferGitClient("https://github.com/superuser/backporting-example/pull/4")).toStrictEqual(GitClientType.GITHUB);
|
||||
});
|
||||
|
@ -39,7 +51,7 @@ describe("check git utilities", () => {
|
|||
expect(inferGitClient("https://api.github.com/repos/owner/repo/pulls/1")).toStrictEqual(GitClientType.GITHUB);
|
||||
});
|
||||
|
||||
test("check infer github api from github api url", ()=> {
|
||||
expect(inferGitApiUrl("https://api.github.com/repos/owner/repo/pulls/1")).toStrictEqual("https://api.github.com");
|
||||
test("check infer codeberg client", ()=> {
|
||||
expect(inferGitClient("https://codeberg.org/lampajr/backporting-example/pulls/1")).toStrictEqual(GitClientType.CODEBERG);
|
||||
});
|
||||
});
|
Loading…
Add table
Reference in a new issue