mirror of
https://github.com/kiegroup/git-backporting.git
synced 2025-04-24 20:32:14 +00:00
project setup
This commit is contained in:
commit
05d156a5b0
39 changed files with 14823 additions and 0 deletions
3
.eslintignore
Normal file
3
.eslintignore
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
node_modules
|
||||||
|
build
|
||||||
|
dist
|
47
.eslintrc
Normal file
47
.eslintrc
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"root": true,
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"plugins": [
|
||||||
|
"@typescript-eslint"
|
||||||
|
],
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/eslint-recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"quotes": [
|
||||||
|
"error",
|
||||||
|
"double"
|
||||||
|
],
|
||||||
|
"semi": "off",
|
||||||
|
"@typescript-eslint/semi": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-explicit-any": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"fixToUnknown": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"curly": "error",
|
||||||
|
"no-empty": "error",
|
||||||
|
"no-console": "error",
|
||||||
|
"no-alert": "error",
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "off",
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"varsIgnorePattern": "^_",
|
||||||
|
"argsIgnorePattern": "^_"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-fallthrough": "off",
|
||||||
|
"arrow-parens": [
|
||||||
|
"error",
|
||||||
|
"as-needed"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
.env
|
||||||
|
node_modules/
|
||||||
|
*.code-workspace
|
||||||
|
locally_execution/**/*
|
||||||
|
test/**/_temp/**/*
|
||||||
|
yarn.lock
|
||||||
|
coverage/
|
||||||
|
test-report.xml
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
dist/
|
4
.husky/pre-commit
Executable file
4
.husky/pre-commit
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
. "$(dirname -- "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
npm run lint && npm run build && git add build
|
4
.husky/pre-push
Executable file
4
.husky/pre-push
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
. "$(dirname -- "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
npm run lint && npm run test
|
7
CHANGELOG.md
Normal file
7
CHANGELOG.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
# V1.0
|
||||||
|
|
||||||
|
[Link](https://github.com/lampajr/backporting/releases/tag/0.0.1)
|
||||||
|
|
||||||
|
TODO
|
0
README.md
Normal file
0
README.md
Normal file
102
build/src/service/git/git-cli.js
Normal file
102
build/src/service/git/git-cli.js
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const logger_service_factory_1 = __importDefault(require("../../service/logger/logger-service-factory"));
|
||||||
|
const simple_git_1 = __importDefault(require("simple-git"));
|
||||||
|
const fs_1 = __importDefault(require("fs"));
|
||||||
|
/**
|
||||||
|
* Command line git commands executor service
|
||||||
|
*/
|
||||||
|
class GitCLIService {
|
||||||
|
constructor() {
|
||||||
|
this.logger = logger_service_factory_1.default.getLogger();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return a pre-configured SimpleGit instance able to execute commands from current
|
||||||
|
* directory or the provided one
|
||||||
|
* @param cwd [optional] current working directory
|
||||||
|
* @returns {SimpleGit}
|
||||||
|
*/
|
||||||
|
git(cwd) {
|
||||||
|
const gitConfig = { ...(cwd ? { baseDir: cwd } : {}) };
|
||||||
|
return (0, simple_git_1.default)(gitConfig).addConfig("user.name", "Github").addConfig("user.email", "noreply@github.com");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return the git version
|
||||||
|
* @returns {Promise<string | undefined>}
|
||||||
|
*/
|
||||||
|
async version() {
|
||||||
|
const rawOutput = await this.git().raw("version");
|
||||||
|
const match = rawOutput.match(/(\d+\.\d+(\.\d+)?)/);
|
||||||
|
return match ? match[1] : undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Clone a git repository
|
||||||
|
* @param from url or path from which the repository should be cloned from
|
||||||
|
* @param to location at which the repository should be cloned at
|
||||||
|
* @param branch branch which should be cloned
|
||||||
|
*/
|
||||||
|
async clone(from, to, branch) {
|
||||||
|
this.logger.info(`Cloning repository ${from}..`);
|
||||||
|
if (!fs_1.default.existsSync(to)) {
|
||||||
|
await this.git().clone(from, to, ["--quiet", "--shallow-submodules", "--no-tags", "--branch", branch]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.logger.warn(`Folder ${to} already exist. Won't clone`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create a new branch starting from the current one and checkout in it
|
||||||
|
* @param cwd repository in which createBranch should be performed
|
||||||
|
* @param newBranch new branch name
|
||||||
|
*/
|
||||||
|
async createLocalBranch(cwd, newBranch) {
|
||||||
|
this.logger.info(`Creating branch ${newBranch}..`);
|
||||||
|
await this.git(cwd).checkoutLocalBranch(newBranch);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add a new remote to the current repository
|
||||||
|
* @param cwd repository in which addRemote should be performed
|
||||||
|
* @param remote remote git link
|
||||||
|
* @param remoteName [optional] name of the remote, by default 'fork' is used
|
||||||
|
*/
|
||||||
|
async addRemote(cwd, remote, remoteName = "fork") {
|
||||||
|
this.logger.info(`Adding new remote ${remote}..`);
|
||||||
|
await this.git(cwd).addRemote(remoteName, remote);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Git fetch from a particular branch
|
||||||
|
* @param cwd repository in which fetch should be performed
|
||||||
|
* @param branch fetch from the given branch
|
||||||
|
* @param remote [optional] the remote to fetch, by default origin
|
||||||
|
*/
|
||||||
|
async fetch(cwd, branch, remote = "origin") {
|
||||||
|
await this.git(cwd).fetch(remote, branch, ["--quiet"]);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get cherry-pick a specific sha
|
||||||
|
* @param cwd repository in which the sha should be cherry picked to
|
||||||
|
* @param sha commit sha
|
||||||
|
*/
|
||||||
|
async cherryPick(cwd, sha) {
|
||||||
|
this.logger.info(`Cherry picking ${sha}..`);
|
||||||
|
await this.git(cwd).raw(["cherry-pick", "--strategy=recursive", "-X", "theirs", sha]);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Push a branch to a remote
|
||||||
|
* @param cwd repository in which the push should be performed
|
||||||
|
* @param branch branch to be pushed
|
||||||
|
* @param remote [optional] remote to which the branch should be pushed to, by default 'origin'
|
||||||
|
*/
|
||||||
|
async push(cwd, branch, remote = "origin", force = false) {
|
||||||
|
this.logger.info(`Pushing ${branch} to ${remote}..`);
|
||||||
|
const options = ["--quiet"];
|
||||||
|
if (force) {
|
||||||
|
options.push("--force-with-lease");
|
||||||
|
}
|
||||||
|
await this.git(cwd).push(remote, branch, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = GitCLIService;
|
36
build/src/service/git/git-service-factory.js
Normal file
36
build/src/service/git/git-service-factory.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const git_types_1 = require("../../service/git/git.types");
|
||||||
|
const github_service_1 = __importDefault(require("../../service/git/github/github-service"));
|
||||||
|
/**
|
||||||
|
* Singleton git service factory class
|
||||||
|
*/
|
||||||
|
class GitServiceFactory {
|
||||||
|
static getService() {
|
||||||
|
if (!GitServiceFactory.instance) {
|
||||||
|
throw new Error("You must call `init` method first!");
|
||||||
|
}
|
||||||
|
return GitServiceFactory.instance;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Initialize the singleton git management service
|
||||||
|
* @param type git management service type
|
||||||
|
* @param auth authentication, like github token
|
||||||
|
*/
|
||||||
|
static init(type, auth) {
|
||||||
|
if (GitServiceFactory.instance) {
|
||||||
|
throw new Error("Git service already initialized!");
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case git_types_1.GitServiceType.GITHUB:
|
||||||
|
GitServiceFactory.instance = new github_service_1.default(auth);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Invalid git service type received: ${type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = GitServiceFactory;
|
2
build/src/service/git/git-service.js
Normal file
2
build/src/service/git/git-service.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
7
build/src/service/git/git.types.js
Normal file
7
build/src/service/git/git.types.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.GitServiceType = void 0;
|
||||||
|
var GitServiceType;
|
||||||
|
(function (GitServiceType) {
|
||||||
|
GitServiceType["GITHUB"] = "github";
|
||||||
|
})(GitServiceType = exports.GitServiceType || (exports.GitServiceType = {}));
|
18
build/src/service/git/github/github-mapper.js
Normal file
18
build/src/service/git/github/github-mapper.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
class GitHubMapper {
|
||||||
|
mapPullRequest(pr) {
|
||||||
|
return {
|
||||||
|
url: pr.url,
|
||||||
|
title: pr.title,
|
||||||
|
body: pr.body,
|
||||||
|
patchUrl: pr.patch_url,
|
||||||
|
state: pr.state,
|
||||||
|
reviewers: pr.requested_reviewers.filter(r => "login" in r).map((r => r?.login)),
|
||||||
|
sourceRepo: pr.head.repo.full_name,
|
||||||
|
targetRepo: pr.base.repo.full_name,
|
||||||
|
commits: [pr.merge_commit_sha]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = GitHubMapper;
|
30
build/src/service/git/github/github-service.js
Normal file
30
build/src/service/git/github/github-service.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const github_mapper_1 = __importDefault(require("../../../service/git/github/github-mapper"));
|
||||||
|
const octokit_factory_1 = __importDefault(require("../../../service/git/github/octokit-factory"));
|
||||||
|
class GitHubService {
|
||||||
|
constructor(token) {
|
||||||
|
this.octokit = octokit_factory_1.default.getOctokit(token);
|
||||||
|
this.mapper = new github_mapper_1.default();
|
||||||
|
}
|
||||||
|
// READ
|
||||||
|
async getPullRequest(owner, repo, prNumber) {
|
||||||
|
const { data } = await this.octokit.rest.pulls.get({
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
pull_number: prNumber
|
||||||
|
});
|
||||||
|
return this.mapper.mapPullRequest(data);
|
||||||
|
}
|
||||||
|
// WRITE
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
createPullRequest(owner, repo, head, base, title, body, reviewers) {
|
||||||
|
// throw new Error("Method not implemented.");
|
||||||
|
// TODO implement
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = GitHubService;
|
24
build/src/service/git/github/octokit-factory.js
Normal file
24
build/src/service/git/github/octokit-factory.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const logger_service_factory_1 = __importDefault(require("../../../service/logger/logger-service-factory"));
|
||||||
|
const rest_1 = require("@octokit/rest");
|
||||||
|
/**
|
||||||
|
* Singleton factory class for {Octokit} instance
|
||||||
|
*/
|
||||||
|
class OctokitFactory {
|
||||||
|
static getOctokit(token) {
|
||||||
|
if (!OctokitFactory.octokit) {
|
||||||
|
OctokitFactory.logger.info("Creating octokit instance..");
|
||||||
|
OctokitFactory.octokit = new rest_1.Octokit({
|
||||||
|
auth: token,
|
||||||
|
userAgent: "lampajr/backporting"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return OctokitFactory.octokit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = OctokitFactory;
|
||||||
|
OctokitFactory.logger = logger_service_factory_1.default.getLogger();
|
27
build/src/service/logger/console-logger-service.js
Normal file
27
build/src/service/logger/console-logger-service.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const logger_1 = __importDefault(require("../../service/logger/logger"));
|
||||||
|
class ConsoleLoggerService {
|
||||||
|
constructor() {
|
||||||
|
this.logger = new logger_1.default();
|
||||||
|
}
|
||||||
|
trace(message) {
|
||||||
|
this.logger.log("[TRACE]", message);
|
||||||
|
}
|
||||||
|
debug(message) {
|
||||||
|
this.logger.log("[DEBUG]", message);
|
||||||
|
}
|
||||||
|
info(message) {
|
||||||
|
this.logger.log("[INFO]", message);
|
||||||
|
}
|
||||||
|
warn(message) {
|
||||||
|
this.logger.log("[WARN]", message);
|
||||||
|
}
|
||||||
|
error(message) {
|
||||||
|
this.logger.log("[ERROR]", message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = ConsoleLoggerService;
|
18
build/src/service/logger/logger-service-factory.js
Normal file
18
build/src/service/logger/logger-service-factory.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const console_logger_service_1 = __importDefault(require("../../service/logger/console-logger-service"));
|
||||||
|
/**
|
||||||
|
* Singleton factory class
|
||||||
|
*/
|
||||||
|
class LoggerServiceFactory {
|
||||||
|
static getLogger() {
|
||||||
|
if (!LoggerServiceFactory.instance) {
|
||||||
|
LoggerServiceFactory.instance = new console_logger_service_1.default();
|
||||||
|
}
|
||||||
|
return LoggerServiceFactory.instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = LoggerServiceFactory;
|
2
build/src/service/logger/logger-service.js
Normal file
2
build/src/service/logger/logger-service.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
15
build/src/service/logger/logger.js
Normal file
15
build/src/service/logger/logger.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
/**
|
||||||
|
* Common logger class based on the console.log functionality
|
||||||
|
*/
|
||||||
|
class Logger {
|
||||||
|
log(prefix, ...str) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log.apply(console, [prefix, ...str]);
|
||||||
|
}
|
||||||
|
emptyLine() {
|
||||||
|
this.log("", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = Logger;
|
29
build/test/service/git/github/github-service.test.js
Normal file
29
build/test/service/git/github/github-service.test.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const git_service_factory_1 = __importDefault(require("../../../../src/service/git/git-service-factory"));
|
||||||
|
const git_types_1 = require("../../../../src/service/git/git.types");
|
||||||
|
const moctokit_data_1 = require("../../../support/moctokit/moctokit-data");
|
||||||
|
const moctokit_support_1 = require("../../../support/moctokit/moctokit-support");
|
||||||
|
describe("github service", () => {
|
||||||
|
let gitService;
|
||||||
|
beforeAll(() => {
|
||||||
|
// init git service
|
||||||
|
git_service_factory_1.default.init(git_types_1.GitServiceType.GITHUB, "whatever");
|
||||||
|
});
|
||||||
|
beforeEach(() => {
|
||||||
|
// mock github api calls
|
||||||
|
(0, moctokit_support_1.setupMoctokit)();
|
||||||
|
gitService = git_service_factory_1.default.getService();
|
||||||
|
});
|
||||||
|
test("get pull request: success", async () => {
|
||||||
|
const res = await gitService.getPullRequest(moctokit_data_1.targetOwner, moctokit_data_1.repo, moctokit_data_1.pullRequestNumber);
|
||||||
|
expect(res.sourceRepo).toBe("fork/reponame");
|
||||||
|
expect(res.targetRepo).toBe("owner/reponame");
|
||||||
|
expect(res.title).toBe("PR Title");
|
||||||
|
expect(res.commits.length).toBe(1);
|
||||||
|
expect(res.commits).toEqual(["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"]);
|
||||||
|
});
|
||||||
|
});
|
445
build/test/support/moctokit/moctokit-data.js
Normal file
445
build/test/support/moctokit/moctokit-data.js
Normal file
|
@ -0,0 +1,445 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.validPR = exports.commitRef = exports.invalidPullRequestNumber = exports.pullRequestNumber = exports.repo = exports.sourceOwner = exports.targetOwner = void 0;
|
||||||
|
exports.targetOwner = "owner";
|
||||||
|
exports.sourceOwner = "fork";
|
||||||
|
exports.repo = "reponame";
|
||||||
|
exports.pullRequestNumber = 2368;
|
||||||
|
exports.invalidPullRequestNumber = 1;
|
||||||
|
exports.commitRef = "91748965051fae1330ad58d15cf694e103267c87";
|
||||||
|
exports.validPR = {
|
||||||
|
"url": "https://api.github.com/repos/owner/reponame/pulls/2368",
|
||||||
|
"id": 1137188271,
|
||||||
|
"node_id": "PR_kwDOABTq6s5DyB2v",
|
||||||
|
"html_url": "https://github.com/owner/reponame/pull/2368",
|
||||||
|
"diff_url": "https://github.com/owner/reponame/pull/2368.diff",
|
||||||
|
"patch_url": "https://github.com/owner/reponame/pull/2368.patch",
|
||||||
|
"issue_url": "https://api.github.com/repos/owner/reponame/issues/2368",
|
||||||
|
"number": 2368,
|
||||||
|
"state": "closed",
|
||||||
|
"locked": false,
|
||||||
|
"title": "PR Title",
|
||||||
|
"user": {
|
||||||
|
"login": "kie-ci",
|
||||||
|
"id": 11995863,
|
||||||
|
"node_id": "MDQ6VXNlcjExOTk1ODYz",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/11995863?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/kie-ci",
|
||||||
|
"html_url": "https://github.com/kie-ci",
|
||||||
|
"followers_url": "https://api.github.com/users/kie-ci/followers",
|
||||||
|
"following_url": "https://api.github.com/users/kie-ci/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/kie-ci/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/kie-ci/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/kie-ci/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/kie-ci/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/kie-ci/repos",
|
||||||
|
"events_url": "https://api.github.com/users/kie-ci/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/kie-ci/received_events",
|
||||||
|
"type": "User",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"body": "Please review and merge",
|
||||||
|
"created_at": "2022-11-28T08:43:09Z",
|
||||||
|
"updated_at": "2022-11-28T10:11:53Z",
|
||||||
|
"closed_at": "2022-11-28T10:11:52Z",
|
||||||
|
"merged_at": "2022-11-28T10:11:52Z",
|
||||||
|
"merge_commit_sha": "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc",
|
||||||
|
"assignee": null,
|
||||||
|
"assignees": [],
|
||||||
|
"requested_reviewers": [
|
||||||
|
{
|
||||||
|
"login": "ghuser",
|
||||||
|
"id": 1422582,
|
||||||
|
"node_id": "MDQ6VXNlcjE0MjI1ODI=",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1422582?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/ghuser",
|
||||||
|
"html_url": "https://github.com/ghuser",
|
||||||
|
"followers_url": "https://api.github.com/users/ghuser/followers",
|
||||||
|
"following_url": "https://api.github.com/users/ghuser/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/ghuser/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/ghuser/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/ghuser/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/ghuser/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/ghuser/repos",
|
||||||
|
"events_url": "https://api.github.com/users/ghuser/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/ghuser/received_events",
|
||||||
|
"type": "User",
|
||||||
|
"site_admin": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requested_teams": [],
|
||||||
|
"labels": [],
|
||||||
|
"milestone": null,
|
||||||
|
"draft": false,
|
||||||
|
"commits_url": "https://api.github.com/repos/owner/reponame/pulls/2368/commits",
|
||||||
|
"review_comments_url": "https://api.github.com/repos/owner/reponame/pulls/2368/comments",
|
||||||
|
"review_comment_url": "https://api.github.com/repos/owner/reponame/pulls/comments{/number}",
|
||||||
|
"comments_url": "https://api.github.com/repos/owner/reponame/issues/2368/comments",
|
||||||
|
"statuses_url": "https://api.github.com/repos/owner/reponame/statuses/91748965051fae1330ad58d15cf694e103267c87",
|
||||||
|
"head": {
|
||||||
|
"label": "kiegroup:bump-8.31.x-drools-8.31.0.Final",
|
||||||
|
"ref": "bump-8.31.x-drools-8.31.0.Final",
|
||||||
|
"sha": "91748965051fae1330ad58d15cf694e103267c87",
|
||||||
|
"user": {
|
||||||
|
"login": "kiegroup",
|
||||||
|
"id": 517980,
|
||||||
|
"node_id": "MDEyOk9yZ2FuaXphdGlvbjUxNzk4MA==",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/517980?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/kiegroup",
|
||||||
|
"html_url": "https://github.com/kiegroup",
|
||||||
|
"followers_url": "https://api.github.com/users/kiegroup/followers",
|
||||||
|
"following_url": "https://api.github.com/users/kiegroup/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/kiegroup/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/kiegroup/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/kiegroup/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/kiegroup/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/kiegroup/repos",
|
||||||
|
"events_url": "https://api.github.com/users/kiegroup/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/kiegroup/received_events",
|
||||||
|
"type": "Organization",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"repo": {
|
||||||
|
"id": 1370858,
|
||||||
|
"node_id": "MDEwOlJlcG9zaXRvcnkxMzcwODU4",
|
||||||
|
"name": "optaplanner",
|
||||||
|
"full_name": "fork/reponame",
|
||||||
|
"private": false,
|
||||||
|
"owner": {
|
||||||
|
"login": "kiegroup",
|
||||||
|
"id": 517980,
|
||||||
|
"node_id": "MDEyOk9yZ2FuaXphdGlvbjUxNzk4MA==",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/517980?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/kiegroup",
|
||||||
|
"html_url": "https://github.com/kiegroup",
|
||||||
|
"followers_url": "https://api.github.com/users/kiegroup/followers",
|
||||||
|
"following_url": "https://api.github.com/users/kiegroup/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/kiegroup/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/kiegroup/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/kiegroup/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/kiegroup/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/kiegroup/repos",
|
||||||
|
"events_url": "https://api.github.com/users/kiegroup/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/kiegroup/received_events",
|
||||||
|
"type": "Organization",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"html_url": "https://github.com/fork/reponame",
|
||||||
|
"description": "AI constraint solver in Java to optimize the vehicle routing problem, employee rostering, task assignment, maintenance scheduling, conference scheduling and other planning problems.",
|
||||||
|
"fork": false,
|
||||||
|
"url": "https://api.github.com/repos/fork/reponame",
|
||||||
|
"forks_url": "https://api.github.com/repos/fork/reponame/forks",
|
||||||
|
"keys_url": "https://api.github.com/repos/fork/reponame/keys{/key_id}",
|
||||||
|
"collaborators_url": "https://api.github.com/repos/fork/reponame/collaborators{/collaborator}",
|
||||||
|
"teams_url": "https://api.github.com/repos/fork/reponame/teams",
|
||||||
|
"hooks_url": "https://api.github.com/repos/fork/reponame/hooks",
|
||||||
|
"issue_events_url": "https://api.github.com/repos/fork/reponame/issues/events{/number}",
|
||||||
|
"events_url": "https://api.github.com/repos/fork/reponame/events",
|
||||||
|
"assignees_url": "https://api.github.com/repos/fork/reponame/assignees{/user}",
|
||||||
|
"branches_url": "https://api.github.com/repos/fork/reponame/branches{/branch}",
|
||||||
|
"tags_url": "https://api.github.com/repos/fork/reponame/tags",
|
||||||
|
"blobs_url": "https://api.github.com/repos/fork/reponame/git/blobs{/sha}",
|
||||||
|
"git_tags_url": "https://api.github.com/repos/fork/reponame/git/tags{/sha}",
|
||||||
|
"git_refs_url": "https://api.github.com/repos/fork/reponame/git/refs{/sha}",
|
||||||
|
"trees_url": "https://api.github.com/repos/fork/reponame/git/trees{/sha}",
|
||||||
|
"statuses_url": "https://api.github.com/repos/fork/reponame/statuses/{sha}",
|
||||||
|
"languages_url": "https://api.github.com/repos/fork/reponame/languages",
|
||||||
|
"stargazers_url": "https://api.github.com/repos/fork/reponame/stargazers",
|
||||||
|
"contributors_url": "https://api.github.com/repos/fork/reponame/contributors",
|
||||||
|
"subscribers_url": "https://api.github.com/repos/fork/reponame/subscribers",
|
||||||
|
"subscription_url": "https://api.github.com/repos/fork/reponame/subscription",
|
||||||
|
"commits_url": "https://api.github.com/repos/fork/reponame/commits{/sha}",
|
||||||
|
"git_commits_url": "https://api.github.com/repos/fork/reponame/git/commits{/sha}",
|
||||||
|
"comments_url": "https://api.github.com/repos/fork/reponame/comments{/number}",
|
||||||
|
"issue_comment_url": "https://api.github.com/repos/fork/reponame/issues/comments{/number}",
|
||||||
|
"contents_url": "https://api.github.com/repos/fork/reponame/contents/{+path}",
|
||||||
|
"compare_url": "https://api.github.com/repos/fork/reponame/compare/{base}...{head}",
|
||||||
|
"merges_url": "https://api.github.com/repos/fork/reponame/merges",
|
||||||
|
"archive_url": "https://api.github.com/repos/fork/reponame/{archive_format}{/ref}",
|
||||||
|
"downloads_url": "https://api.github.com/repos/fork/reponame/downloads",
|
||||||
|
"issues_url": "https://api.github.com/repos/fork/reponame/issues{/number}",
|
||||||
|
"pulls_url": "https://api.github.com/repos/fork/reponame/pulls{/number}",
|
||||||
|
"milestones_url": "https://api.github.com/repos/fork/reponame/milestones{/number}",
|
||||||
|
"notifications_url": "https://api.github.com/repos/fork/reponame/notifications{?since,all,participating}",
|
||||||
|
"labels_url": "https://api.github.com/repos/fork/reponame/labels{/name}",
|
||||||
|
"releases_url": "https://api.github.com/repos/fork/reponame/releases{/id}",
|
||||||
|
"deployments_url": "https://api.github.com/repos/fork/reponame/deployments",
|
||||||
|
"created_at": "2011-02-15T19:38:23Z",
|
||||||
|
"updated_at": "2022-11-28T05:01:47Z",
|
||||||
|
"pushed_at": "2022-11-28T10:50:51Z",
|
||||||
|
"git_url": "git://github.com/fork/reponame.git",
|
||||||
|
"ssh_url": "git@github.com:fork/reponame.git",
|
||||||
|
"clone_url": "https://github.com/fork/reponame.git",
|
||||||
|
"svn_url": "https://github.com/fork/reponame",
|
||||||
|
"homepage": "https://www.optaplanner.org",
|
||||||
|
"size": 238339,
|
||||||
|
"stargazers_count": 2811,
|
||||||
|
"watchers_count": 2811,
|
||||||
|
"language": "Java",
|
||||||
|
"has_issues": false,
|
||||||
|
"has_projects": false,
|
||||||
|
"has_downloads": true,
|
||||||
|
"has_wiki": false,
|
||||||
|
"has_pages": false,
|
||||||
|
"has_discussions": false,
|
||||||
|
"forks_count": 878,
|
||||||
|
"mirror_url": null,
|
||||||
|
"archived": false,
|
||||||
|
"disabled": false,
|
||||||
|
"open_issues_count": 30,
|
||||||
|
"license": {
|
||||||
|
"key": "apache-2.0",
|
||||||
|
"name": "Apache License 2.0",
|
||||||
|
"spdx_id": "Apache-2.0",
|
||||||
|
"url": "https://api.github.com/licenses/apache-2.0",
|
||||||
|
"node_id": "MDc6TGljZW5zZTI="
|
||||||
|
},
|
||||||
|
"allow_forking": true,
|
||||||
|
"is_template": false,
|
||||||
|
"web_commit_signoff_required": false,
|
||||||
|
"topics": [
|
||||||
|
"artificial-intelligence",
|
||||||
|
"branch-and-bound",
|
||||||
|
"constraint-programming",
|
||||||
|
"constraint-satisfaction-problem",
|
||||||
|
"constraint-solver",
|
||||||
|
"constraints",
|
||||||
|
"employee-rostering",
|
||||||
|
"java",
|
||||||
|
"local-search",
|
||||||
|
"mathematical-optimization",
|
||||||
|
"metaheuristics",
|
||||||
|
"optimization",
|
||||||
|
"rostering",
|
||||||
|
"scheduling",
|
||||||
|
"simulated-annealing",
|
||||||
|
"solver",
|
||||||
|
"tabu-search",
|
||||||
|
"traveling-salesman",
|
||||||
|
"traveling-salesman-problem",
|
||||||
|
"vehicle-routing-problem"
|
||||||
|
],
|
||||||
|
"visibility": "public",
|
||||||
|
"forks": 878,
|
||||||
|
"open_issues": 30,
|
||||||
|
"watchers": 2811,
|
||||||
|
"default_branch": "main"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"base": {
|
||||||
|
"label": "kiegroup:8.31.x",
|
||||||
|
"ref": "8.31.x",
|
||||||
|
"sha": "8cfc286765cb01c84a1d62c65519fa8032bfecbd",
|
||||||
|
"user": {
|
||||||
|
"login": "kiegroup",
|
||||||
|
"id": 517980,
|
||||||
|
"node_id": "MDEyOk9yZ2FuaXphdGlvbjUxNzk4MA==",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/517980?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/kiegroup",
|
||||||
|
"html_url": "https://github.com/kiegroup",
|
||||||
|
"followers_url": "https://api.github.com/users/kiegroup/followers",
|
||||||
|
"following_url": "https://api.github.com/users/kiegroup/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/kiegroup/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/kiegroup/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/kiegroup/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/kiegroup/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/kiegroup/repos",
|
||||||
|
"events_url": "https://api.github.com/users/kiegroup/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/kiegroup/received_events",
|
||||||
|
"type": "Organization",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"repo": {
|
||||||
|
"id": 1370858,
|
||||||
|
"node_id": "MDEwOlJlcG9zaXRvcnkxMzcwODU4",
|
||||||
|
"name": "optaplanner",
|
||||||
|
"full_name": "owner/reponame",
|
||||||
|
"private": false,
|
||||||
|
"owner": {
|
||||||
|
"login": "kiegroup",
|
||||||
|
"id": 517980,
|
||||||
|
"node_id": "MDEyOk9yZ2FuaXphdGlvbjUxNzk4MA==",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/517980?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/kiegroup",
|
||||||
|
"html_url": "https://github.com/kiegroup",
|
||||||
|
"followers_url": "https://api.github.com/users/kiegroup/followers",
|
||||||
|
"following_url": "https://api.github.com/users/kiegroup/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/kiegroup/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/kiegroup/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/kiegroup/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/kiegroup/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/kiegroup/repos",
|
||||||
|
"events_url": "https://api.github.com/users/kiegroup/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/kiegroup/received_events",
|
||||||
|
"type": "Organization",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"html_url": "https://github.com/owner/reponame",
|
||||||
|
"description": "AI constraint solver in Java to optimize the vehicle routing problem, employee rostering, task assignment, maintenance scheduling, conference scheduling and other planning problems.",
|
||||||
|
"fork": false,
|
||||||
|
"url": "https://api.github.com/repos/owner/reponame",
|
||||||
|
"forks_url": "https://api.github.com/repos/owner/reponame/forks",
|
||||||
|
"keys_url": "https://api.github.com/repos/owner/reponame/keys{/key_id}",
|
||||||
|
"collaborators_url": "https://api.github.com/repos/owner/reponame/collaborators{/collaborator}",
|
||||||
|
"teams_url": "https://api.github.com/repos/owner/reponame/teams",
|
||||||
|
"hooks_url": "https://api.github.com/repos/owner/reponame/hooks",
|
||||||
|
"issue_events_url": "https://api.github.com/repos/owner/reponame/issues/events{/number}",
|
||||||
|
"events_url": "https://api.github.com/repos/owner/reponame/events",
|
||||||
|
"assignees_url": "https://api.github.com/repos/owner/reponame/assignees{/user}",
|
||||||
|
"branches_url": "https://api.github.com/repos/owner/reponame/branches{/branch}",
|
||||||
|
"tags_url": "https://api.github.com/repos/owner/reponame/tags",
|
||||||
|
"blobs_url": "https://api.github.com/repos/owner/reponame/git/blobs{/sha}",
|
||||||
|
"git_tags_url": "https://api.github.com/repos/owner/reponame/git/tags{/sha}",
|
||||||
|
"git_refs_url": "https://api.github.com/repos/owner/reponame/git/refs{/sha}",
|
||||||
|
"trees_url": "https://api.github.com/repos/owner/reponame/git/trees{/sha}",
|
||||||
|
"statuses_url": "https://api.github.com/repos/owner/reponame/statuses/{sha}",
|
||||||
|
"languages_url": "https://api.github.com/repos/owner/reponame/languages",
|
||||||
|
"stargazers_url": "https://api.github.com/repos/owner/reponame/stargazers",
|
||||||
|
"contributors_url": "https://api.github.com/repos/owner/reponame/contributors",
|
||||||
|
"subscribers_url": "https://api.github.com/repos/owner/reponame/subscribers",
|
||||||
|
"subscription_url": "https://api.github.com/repos/owner/reponame/subscription",
|
||||||
|
"commits_url": "https://api.github.com/repos/owner/reponame/commits{/sha}",
|
||||||
|
"git_commits_url": "https://api.github.com/repos/owner/reponame/git/commits{/sha}",
|
||||||
|
"comments_url": "https://api.github.com/repos/owner/reponame/comments{/number}",
|
||||||
|
"issue_comment_url": "https://api.github.com/repos/owner/reponame/issues/comments{/number}",
|
||||||
|
"contents_url": "https://api.github.com/repos/owner/reponame/contents/{+path}",
|
||||||
|
"compare_url": "https://api.github.com/repos/owner/reponame/compare/{base}...{head}",
|
||||||
|
"merges_url": "https://api.github.com/repos/owner/reponame/merges",
|
||||||
|
"archive_url": "https://api.github.com/repos/owner/reponame/{archive_format}{/ref}",
|
||||||
|
"downloads_url": "https://api.github.com/repos/owner/reponame/downloads",
|
||||||
|
"issues_url": "https://api.github.com/repos/owner/reponame/issues{/number}",
|
||||||
|
"pulls_url": "https://api.github.com/repos/owner/reponame/pulls{/number}",
|
||||||
|
"milestones_url": "https://api.github.com/repos/owner/reponame/milestones{/number}",
|
||||||
|
"notifications_url": "https://api.github.com/repos/owner/reponame/notifications{?since,all,participating}",
|
||||||
|
"labels_url": "https://api.github.com/repos/owner/reponame/labels{/name}",
|
||||||
|
"releases_url": "https://api.github.com/repos/owner/reponame/releases{/id}",
|
||||||
|
"deployments_url": "https://api.github.com/repos/owner/reponame/deployments",
|
||||||
|
"created_at": "2011-02-15T19:38:23Z",
|
||||||
|
"updated_at": "2022-11-28T05:01:47Z",
|
||||||
|
"pushed_at": "2022-11-28T10:50:51Z",
|
||||||
|
"git_url": "git://github.com/owner/reponame.git",
|
||||||
|
"ssh_url": "git@github.com:owner/reponame.git",
|
||||||
|
"clone_url": "https://github.com/owner/reponame.git",
|
||||||
|
"svn_url": "https://github.com/owner/reponame",
|
||||||
|
"homepage": "https://www.optaplanner.org",
|
||||||
|
"size": 238339,
|
||||||
|
"stargazers_count": 2811,
|
||||||
|
"watchers_count": 2811,
|
||||||
|
"language": "Java",
|
||||||
|
"has_issues": false,
|
||||||
|
"has_projects": false,
|
||||||
|
"has_downloads": true,
|
||||||
|
"has_wiki": false,
|
||||||
|
"has_pages": false,
|
||||||
|
"has_discussions": false,
|
||||||
|
"forks_count": 878,
|
||||||
|
"mirror_url": null,
|
||||||
|
"archived": false,
|
||||||
|
"disabled": false,
|
||||||
|
"open_issues_count": 30,
|
||||||
|
"license": {
|
||||||
|
"key": "apache-2.0",
|
||||||
|
"name": "Apache License 2.0",
|
||||||
|
"spdx_id": "Apache-2.0",
|
||||||
|
"url": "https://api.github.com/licenses/apache-2.0",
|
||||||
|
"node_id": "MDc6TGljZW5zZTI="
|
||||||
|
},
|
||||||
|
"allow_forking": true,
|
||||||
|
"is_template": false,
|
||||||
|
"web_commit_signoff_required": false,
|
||||||
|
"topics": [
|
||||||
|
"artificial-intelligence",
|
||||||
|
"branch-and-bound",
|
||||||
|
"constraint-programming",
|
||||||
|
"constraint-satisfaction-problem",
|
||||||
|
"constraint-solver",
|
||||||
|
"constraints",
|
||||||
|
"employee-rostering",
|
||||||
|
"java",
|
||||||
|
"local-search",
|
||||||
|
"mathematical-optimization",
|
||||||
|
"metaheuristics",
|
||||||
|
"optimization",
|
||||||
|
"rostering",
|
||||||
|
"scheduling",
|
||||||
|
"simulated-annealing",
|
||||||
|
"solver",
|
||||||
|
"tabu-search",
|
||||||
|
"traveling-salesman",
|
||||||
|
"traveling-salesman-problem",
|
||||||
|
"vehicle-routing-problem"
|
||||||
|
],
|
||||||
|
"visibility": "public",
|
||||||
|
"forks": 878,
|
||||||
|
"open_issues": 30,
|
||||||
|
"watchers": 2811,
|
||||||
|
"default_branch": "main"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"_links": {
|
||||||
|
"self": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/pulls/2368"
|
||||||
|
},
|
||||||
|
"html": {
|
||||||
|
"href": "https://github.com/owner/reponame/pull/2368"
|
||||||
|
},
|
||||||
|
"issue": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/issues/2368"
|
||||||
|
},
|
||||||
|
"comments": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/issues/2368/comments"
|
||||||
|
},
|
||||||
|
"review_comments": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/pulls/2368/comments"
|
||||||
|
},
|
||||||
|
"review_comment": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/pulls/comments{/number}"
|
||||||
|
},
|
||||||
|
"commits": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/pulls/2368/commits"
|
||||||
|
},
|
||||||
|
"statuses": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/statuses/91748965051fae1330ad58d15cf694e103267c87"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"author_association": "CONTRIBUTOR",
|
||||||
|
"auto_merge": null,
|
||||||
|
"active_lock_reason": null,
|
||||||
|
"merged": true,
|
||||||
|
"mergeable": null,
|
||||||
|
"rebaseable": null,
|
||||||
|
"mergeable_state": "unknown",
|
||||||
|
"merged_by": {
|
||||||
|
"login": "radtriste",
|
||||||
|
"id": 17157711,
|
||||||
|
"node_id": "MDQ6VXNlcjE3MTU3NzEx",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/17157711?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/radtriste",
|
||||||
|
"html_url": "https://github.com/radtriste",
|
||||||
|
"followers_url": "https://api.github.com/users/radtriste/followers",
|
||||||
|
"following_url": "https://api.github.com/users/radtriste/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/radtriste/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/radtriste/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/radtriste/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/radtriste/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/radtriste/repos",
|
||||||
|
"events_url": "https://api.github.com/users/radtriste/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/radtriste/received_events",
|
||||||
|
"type": "User",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"comments": 0,
|
||||||
|
"review_comments": 0,
|
||||||
|
"maintainer_can_modify": false,
|
||||||
|
"commits": 2,
|
||||||
|
"additions": 2,
|
||||||
|
"deletions": 2,
|
||||||
|
"changed_files": 2
|
||||||
|
};
|
47
build/test/support/moctokit/moctokit-support.js
Normal file
47
build/test/support/moctokit/moctokit-support.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.setupMoctokit = void 0;
|
||||||
|
const logger_service_factory_1 = __importDefault(require("../../../src/service/logger/logger-service-factory"));
|
||||||
|
const mock_github_1 = require("@kie/mock-github");
|
||||||
|
const moctokit_data_1 = require("./moctokit-data");
|
||||||
|
const logger = logger_service_factory_1.default.getLogger();
|
||||||
|
const setupMoctokit = () => {
|
||||||
|
logger.debug("Setting up moctokit..");
|
||||||
|
const mock = new mock_github_1.Moctokit();
|
||||||
|
// setup the mock requests here
|
||||||
|
// valid requests
|
||||||
|
mock.rest.pulls
|
||||||
|
.get({
|
||||||
|
owner: moctokit_data_1.targetOwner,
|
||||||
|
repo: moctokit_data_1.repo,
|
||||||
|
pull_number: moctokit_data_1.pullRequestNumber
|
||||||
|
})
|
||||||
|
.reply({
|
||||||
|
status: 200,
|
||||||
|
data: moctokit_data_1.validPR
|
||||||
|
});
|
||||||
|
mock.rest.pulls
|
||||||
|
.create()
|
||||||
|
.reply({
|
||||||
|
status: 201,
|
||||||
|
data: moctokit_data_1.validPR
|
||||||
|
});
|
||||||
|
// invalid requests
|
||||||
|
mock.rest.pulls
|
||||||
|
.get({
|
||||||
|
owner: moctokit_data_1.targetOwner,
|
||||||
|
repo: moctokit_data_1.repo,
|
||||||
|
pull_number: moctokit_data_1.invalidPullRequestNumber
|
||||||
|
})
|
||||||
|
.reply({
|
||||||
|
status: 404,
|
||||||
|
data: {
|
||||||
|
message: "Not found"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return mock;
|
||||||
|
};
|
||||||
|
exports.setupMoctokit = setupMoctokit;
|
16
jest.config.ts
Normal file
16
jest.config.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import type { Config } from "@jest/types";
|
||||||
|
// Sync object
|
||||||
|
const jestConfig: Config.InitialOptions = {
|
||||||
|
verbose: true,
|
||||||
|
transform: {
|
||||||
|
"^.+\\.tsx?$": "ts-jest",
|
||||||
|
},
|
||||||
|
moduleNameMapper: {
|
||||||
|
"^@gb/(.*)$": "<rootDir>/src/$1",
|
||||||
|
},
|
||||||
|
clearMocks: true,
|
||||||
|
resetMocks: true,
|
||||||
|
modulePathIgnorePatterns: ["<rootDir>/dist/"],
|
||||||
|
coveragePathIgnorePatterns: ["<rootDir>/node_modules/", "<rootDir>/test/", "<rootDir>/build/", "<rootDir>/dist/"]
|
||||||
|
};
|
||||||
|
export default jestConfig;
|
12841
package-lock.json
generated
Normal file
12841
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
70
package.json
Normal file
70
package.json
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
"name": "@lampajr/backporting",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Tool to execute automatic git backporting.",
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"private": false,
|
||||||
|
"main": "./build/src/bin/main.js",
|
||||||
|
"bin": {
|
||||||
|
"backporting": "./build/src/bin/main.js"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"build/"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"prepare": "husky install",
|
||||||
|
"clean": "rm -rf ./build",
|
||||||
|
"compile": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
|
||||||
|
"build": "npm run clean && npm run compile",
|
||||||
|
"package": "ncc build --source-map --license licenses.txt",
|
||||||
|
"test": "jest",
|
||||||
|
"test:report": "npm test -- --coverage --testResultsProcessor=jest-sonar-reporter",
|
||||||
|
"lint": "eslint . --ext .ts",
|
||||||
|
"lint:fix": "npm run lint -- --fix",
|
||||||
|
"ts-node": "ts-node"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/lampajr/backporting.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"backporting",
|
||||||
|
"pull-requests",
|
||||||
|
"github-action",
|
||||||
|
"cherry-pick"
|
||||||
|
],
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/lampajr/backporting/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/lampajr/backporting#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"@kie/mock-github": "^0.1.1",
|
||||||
|
"@types/fs-extra": "^9.0.13",
|
||||||
|
"@types/jest": "^28.1.8",
|
||||||
|
"@types/node": "^17.0.41",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.45.1",
|
||||||
|
"@typescript-eslint/parser": "^5.45.1",
|
||||||
|
"eslint": "^8.29.0",
|
||||||
|
"husky": "^8.0.2",
|
||||||
|
"jest": "^29.3.1",
|
||||||
|
"jest-sonar-reporter": "^2.0.0",
|
||||||
|
"ts-jest": "^29.0.3",
|
||||||
|
"ts-node": "^10.8.1",
|
||||||
|
"tsc-alias": "^1.7.1",
|
||||||
|
"tsconfig-paths": "^4.1.0",
|
||||||
|
"typescript": "^4.9.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/artifact": "^1.1.0",
|
||||||
|
"@actions/core": "^1.8.2",
|
||||||
|
"@actions/exec": "^1.1.1",
|
||||||
|
"@actions/glob": "^0.3.0",
|
||||||
|
"@octokit/rest": "^19.0.5",
|
||||||
|
"@octokit/types": "^8.0.0",
|
||||||
|
"@octokit/webhooks-types": "^6.7.0",
|
||||||
|
"commander": "^9.3.0",
|
||||||
|
"fs-extra": "^10.1.0",
|
||||||
|
"simple-git": "^3.15.1"
|
||||||
|
}
|
||||||
|
}
|
110
src/service/git/git-cli.ts
Normal file
110
src/service/git/git-cli.ts
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
import LoggerService from "@gb/service/logger/logger-service";
|
||||||
|
import LoggerServiceFactory from "@gb/service/logger/logger-service-factory";
|
||||||
|
import simpleGit, { SimpleGit } from "simple-git";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command line git commands executor service
|
||||||
|
*/
|
||||||
|
export default class GitCLIService {
|
||||||
|
|
||||||
|
private readonly logger: LoggerService;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.logger = LoggerServiceFactory.getLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a pre-configured SimpleGit instance able to execute commands from current
|
||||||
|
* directory or the provided one
|
||||||
|
* @param cwd [optional] current working directory
|
||||||
|
* @returns {SimpleGit}
|
||||||
|
*/
|
||||||
|
private git(cwd?: string): SimpleGit {
|
||||||
|
const gitConfig = { ...(cwd ? { baseDir: cwd } : {})};
|
||||||
|
return simpleGit(gitConfig).addConfig("user.name", "Github").addConfig("user.email", "noreply@github.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the git version
|
||||||
|
* @returns {Promise<string | undefined>}
|
||||||
|
*/
|
||||||
|
async version(): Promise<string | undefined> {
|
||||||
|
const rawOutput = await this.git().raw("version");
|
||||||
|
const match = rawOutput.match(/(\d+\.\d+(\.\d+)?)/);
|
||||||
|
return match ? match[1] : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone a git repository
|
||||||
|
* @param from url or path from which the repository should be cloned from
|
||||||
|
* @param to location at which the repository should be cloned at
|
||||||
|
* @param branch branch which should be cloned
|
||||||
|
*/
|
||||||
|
async clone(from: string, to: string, branch: string): Promise<void> {
|
||||||
|
this.logger.info(`Cloning repository ${from}..`);
|
||||||
|
if (!fs.existsSync(to)) {
|
||||||
|
await this.git().clone(from, to, ["--quiet", "--shallow-submodules", "--no-tags", "--branch", branch]);
|
||||||
|
} else {
|
||||||
|
this.logger.warn(`Folder ${to} already exist. Won't clone`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new branch starting from the current one and checkout in it
|
||||||
|
* @param cwd repository in which createBranch should be performed
|
||||||
|
* @param newBranch new branch name
|
||||||
|
*/
|
||||||
|
async createLocalBranch(cwd: string, newBranch: string): Promise<void> {
|
||||||
|
this.logger.info(`Creating branch ${newBranch}..`);
|
||||||
|
await this.git(cwd).checkoutLocalBranch(newBranch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new remote to the current repository
|
||||||
|
* @param cwd repository in which addRemote should be performed
|
||||||
|
* @param remote remote git link
|
||||||
|
* @param remoteName [optional] name of the remote, by default 'fork' is used
|
||||||
|
*/
|
||||||
|
async addRemote(cwd: string, remote: string, remoteName = "fork"): Promise<void> {
|
||||||
|
this.logger.info(`Adding new remote ${remote}..`);
|
||||||
|
await this.git(cwd).addRemote(remoteName, remote);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Git fetch from a particular branch
|
||||||
|
* @param cwd repository in which fetch should be performed
|
||||||
|
* @param branch fetch from the given branch
|
||||||
|
* @param remote [optional] the remote to fetch, by default origin
|
||||||
|
*/
|
||||||
|
async fetch(cwd: string, branch: string, remote = "origin"): Promise<void> {
|
||||||
|
await this.git(cwd).fetch(remote, branch, ["--quiet"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cherry-pick a specific sha
|
||||||
|
* @param cwd repository in which the sha should be cherry picked to
|
||||||
|
* @param sha commit sha
|
||||||
|
*/
|
||||||
|
async cherryPick(cwd: string, sha: string): Promise<void> {
|
||||||
|
this.logger.info(`Cherry picking ${sha}..`);
|
||||||
|
await this.git(cwd).raw(["cherry-pick", "--strategy=recursive", "-X", "theirs", sha]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push a branch to a remote
|
||||||
|
* @param cwd repository in which the push should be performed
|
||||||
|
* @param branch branch to be pushed
|
||||||
|
* @param remote [optional] remote to which the branch should be pushed to, by default 'origin'
|
||||||
|
*/
|
||||||
|
async push(cwd: string, branch: string, remote = "origin", force = false): Promise<void> {
|
||||||
|
this.logger.info(`Pushing ${branch} to ${remote}..`);
|
||||||
|
|
||||||
|
const options = ["--quiet"];
|
||||||
|
if (force) {
|
||||||
|
options.push("--force-with-lease");
|
||||||
|
}
|
||||||
|
await this.git(cwd).push(remote, branch, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
39
src/service/git/git-service-factory.ts
Normal file
39
src/service/git/git-service-factory.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import GitService from "@gb/service/git/git-service";
|
||||||
|
import { GitServiceType } from "@gb/service/git/git.types";
|
||||||
|
import GitHubService from "@gb/service/git/github/github-service";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton git service factory class
|
||||||
|
*/
|
||||||
|
export default class GitServiceFactory {
|
||||||
|
|
||||||
|
private static instance?: GitService;
|
||||||
|
|
||||||
|
public static getService(): GitService {
|
||||||
|
if (!GitServiceFactory.instance) {
|
||||||
|
throw new Error("You must call `init` method first!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return GitServiceFactory.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the singleton git management service
|
||||||
|
* @param type git management service type
|
||||||
|
* @param auth authentication, like github token
|
||||||
|
*/
|
||||||
|
public static init(type: GitServiceType, auth: string): void {
|
||||||
|
|
||||||
|
if (GitServiceFactory.instance) {
|
||||||
|
throw new Error("Git service already initialized!");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case GitServiceType.GITHUB:
|
||||||
|
GitServiceFactory.instance = new GitHubService(auth);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Invalid git service type received: ${type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
src/service/git/git-service.ts
Normal file
33
src/service/git/git-service.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { GitPullRequest } from "@gb/service/git/git.types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Git management service interface, which provides a common API for interacting
|
||||||
|
* with several git management services like GitHub, Gitlab or Bitbucket.
|
||||||
|
*/
|
||||||
|
export default interface GitService {
|
||||||
|
|
||||||
|
// READ
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a pull request object from the underneath git service
|
||||||
|
* @param owner repository's owner
|
||||||
|
* @param repo repository's name
|
||||||
|
* @param prNumber pull request number
|
||||||
|
* @returns {Promise<PullRequest>}
|
||||||
|
*/
|
||||||
|
getPullRequest(owner: string, repo: string, prNumber: number): Promise<GitPullRequest>;
|
||||||
|
|
||||||
|
// WRITE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new pull request on the underneath git service
|
||||||
|
* @param owner repository's owner
|
||||||
|
* @param repo repository's name
|
||||||
|
* @param head name of the source branch
|
||||||
|
* @param base name of the target branch
|
||||||
|
* @param title pr title
|
||||||
|
* @param body pr body
|
||||||
|
* @param reviewers pr list of reviewers
|
||||||
|
*/
|
||||||
|
createPullRequest(owner: string, repo: string, head: string, base: string, title: string, body: string, reviewers: string[]): Promise<void>;
|
||||||
|
}
|
15
src/service/git/git.types.ts
Normal file
15
src/service/git/git.types.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
export interface GitPullRequest {
|
||||||
|
url: string,
|
||||||
|
patchUrl: string,
|
||||||
|
state: string,
|
||||||
|
title: string,
|
||||||
|
body: string,
|
||||||
|
reviewers: string[],
|
||||||
|
targetRepo: string,
|
||||||
|
sourceRepo: string,
|
||||||
|
commits: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum GitServiceType {
|
||||||
|
GITHUB = "github"
|
||||||
|
}
|
19
src/service/git/github/github-mapper.ts
Normal file
19
src/service/git/github/github-mapper.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { GitPullRequest } from "@gb/service/git/git.types";
|
||||||
|
import { PullRequest, User } from "@octokit/webhooks-types";
|
||||||
|
|
||||||
|
export default class GitHubMapper {
|
||||||
|
|
||||||
|
mapPullRequest(pr: PullRequest): GitPullRequest {
|
||||||
|
return {
|
||||||
|
url: pr.url,
|
||||||
|
title: pr.title,
|
||||||
|
body: pr.body,
|
||||||
|
patchUrl: pr.patch_url,
|
||||||
|
state: pr.state,
|
||||||
|
reviewers: pr.requested_reviewers.filter(r => "login" in r).map((r => (r as User)?.login)),
|
||||||
|
sourceRepo: pr.head.repo.full_name,
|
||||||
|
targetRepo: pr.base.repo.full_name,
|
||||||
|
commits: [pr.merge_commit_sha]
|
||||||
|
} as GitPullRequest;
|
||||||
|
}
|
||||||
|
}
|
38
src/service/git/github/github-service.ts
Normal file
38
src/service/git/github/github-service.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import GitService from "@gb/service/git/git-service";
|
||||||
|
import { GitPullRequest } from "@gb/service/git/git.types";
|
||||||
|
import GitHubMapper from "@gb/service/git/github/github-mapper";
|
||||||
|
import OctokitFactory from "@gb/service/git/github/octokit-factory";
|
||||||
|
import { Octokit } from "@octokit/rest";
|
||||||
|
import { PullRequest } from "@octokit/webhooks-types";
|
||||||
|
|
||||||
|
export default class GitHubService implements GitService {
|
||||||
|
|
||||||
|
private octokit: Octokit;
|
||||||
|
private mapper: GitHubMapper;
|
||||||
|
|
||||||
|
constructor(token: string) {
|
||||||
|
this.octokit = OctokitFactory.getOctokit(token);
|
||||||
|
this.mapper = new GitHubMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
// READ
|
||||||
|
|
||||||
|
async getPullRequest(owner: string, repo: string, prNumber: number): Promise<GitPullRequest> {
|
||||||
|
const { data } = await this.octokit.rest.pulls.get({
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
pull_number: prNumber
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.mapper.mapPullRequest(data as PullRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WRITE
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
createPullRequest(owner: string, repo: string, head: string, base: string, title: string, body: string, reviewers: string[]): Promise<void> {
|
||||||
|
// throw new Error("Method not implemented.");
|
||||||
|
// TODO implement
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
24
src/service/git/github/octokit-factory.ts
Normal file
24
src/service/git/github/octokit-factory.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import LoggerService from "@gb/service/logger/logger-service";
|
||||||
|
import LoggerServiceFactory from "@gb/service/logger/logger-service-factory";
|
||||||
|
import { Octokit } from "@octokit/rest";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton factory class for {Octokit} instance
|
||||||
|
*/
|
||||||
|
export default class OctokitFactory {
|
||||||
|
|
||||||
|
private static logger: LoggerService = LoggerServiceFactory.getLogger();
|
||||||
|
private static octokit?: Octokit;
|
||||||
|
|
||||||
|
public static getOctokit(token: string): Octokit {
|
||||||
|
if (!OctokitFactory.octokit) {
|
||||||
|
OctokitFactory.logger.info("Creating octokit instance..");
|
||||||
|
OctokitFactory.octokit = new Octokit({
|
||||||
|
auth: token,
|
||||||
|
userAgent: "lampajr/backporting"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return OctokitFactory.octokit;
|
||||||
|
}
|
||||||
|
}
|
32
src/service/logger/console-logger-service.ts
Normal file
32
src/service/logger/console-logger-service.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import Logger from "@gb/service/logger/logger";
|
||||||
|
import LoggerService from "@gb/service/logger/logger-service";
|
||||||
|
|
||||||
|
export default class ConsoleLoggerService implements LoggerService {
|
||||||
|
|
||||||
|
private readonly logger;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.logger = new Logger();
|
||||||
|
}
|
||||||
|
|
||||||
|
trace(message: string): void {
|
||||||
|
this.logger.log("[TRACE]", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(message: string): void {
|
||||||
|
this.logger.log("[DEBUG]", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
info(message: string): void {
|
||||||
|
this.logger.log("[INFO]", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
warn(message: string): void {
|
||||||
|
this.logger.log("[WARN]", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
error(message: string): void {
|
||||||
|
this.logger.log("[ERROR]", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
18
src/service/logger/logger-service-factory.ts
Normal file
18
src/service/logger/logger-service-factory.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import ConsoleLoggerService from "@gb/service/logger/console-logger-service";
|
||||||
|
import LoggerService from "@gb/service/logger/logger-service";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton factory class
|
||||||
|
*/
|
||||||
|
export default class LoggerServiceFactory {
|
||||||
|
|
||||||
|
private static instance?: LoggerService;
|
||||||
|
|
||||||
|
public static getLogger(): LoggerService {
|
||||||
|
if (!LoggerServiceFactory.instance) {
|
||||||
|
LoggerServiceFactory.instance = new ConsoleLoggerService();
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoggerServiceFactory.instance;
|
||||||
|
}
|
||||||
|
}
|
15
src/service/logger/logger-service.ts
Normal file
15
src/service/logger/logger-service.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/**
|
||||||
|
* Logger service interface providing the most commong logging functionalities
|
||||||
|
*/
|
||||||
|
export default interface LoggerService {
|
||||||
|
|
||||||
|
trace(message: string): void;
|
||||||
|
|
||||||
|
debug(message: string): void;
|
||||||
|
|
||||||
|
info(message: string): void;
|
||||||
|
|
||||||
|
warn(message: string): void;
|
||||||
|
|
||||||
|
error(message: string): void;
|
||||||
|
}
|
15
src/service/logger/logger.ts
Normal file
15
src/service/logger/logger.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common logger class based on the console.log functionality
|
||||||
|
*/
|
||||||
|
export default class Logger {
|
||||||
|
|
||||||
|
log(prefix: string, ...str: string[]) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log.apply(console, [prefix, ...str]);
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyLine() {
|
||||||
|
this.log("", "");
|
||||||
|
}
|
||||||
|
}
|
32
test/service/git/github/github-service.test.ts
Normal file
32
test/service/git/github/github-service.test.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import GitServiceFactory from "@gb/service/git/git-service-factory";
|
||||||
|
import { GitPullRequest, GitServiceType } from "@gb/service/git/git.types";
|
||||||
|
import GitHubService from "@gb/service/git/github/github-service";
|
||||||
|
import { pullRequestNumber, repo, targetOwner } from "../../../support/moctokit/moctokit-data";
|
||||||
|
import { setupMoctokit } from "../../../support/moctokit/moctokit-support";
|
||||||
|
|
||||||
|
describe("github service", () => {
|
||||||
|
|
||||||
|
let gitService: GitHubService;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
// init git service
|
||||||
|
GitServiceFactory.init(GitServiceType.GITHUB, "whatever");
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// mock github api calls
|
||||||
|
setupMoctokit();
|
||||||
|
|
||||||
|
gitService = GitServiceFactory.getService() as GitHubService;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("get pull request: success", async () => {
|
||||||
|
const res: GitPullRequest = await gitService.getPullRequest(targetOwner, repo, pullRequestNumber);
|
||||||
|
expect(res.sourceRepo).toBe("fork/reponame");
|
||||||
|
expect(res.targetRepo).toBe("owner/reponame");
|
||||||
|
expect(res.title).toBe("PR Title");
|
||||||
|
expect(res.commits.length).toBe(1);
|
||||||
|
expect(res.commits).toEqual(["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
449
test/support/moctokit/moctokit-data.ts
Normal file
449
test/support/moctokit/moctokit-data.ts
Normal file
|
@ -0,0 +1,449 @@
|
||||||
|
export const targetOwner = "owner";
|
||||||
|
export const sourceOwner = "fork";
|
||||||
|
export const repo = "reponame";
|
||||||
|
export const pullRequestNumber = 2368;
|
||||||
|
export const invalidPullRequestNumber = 1;
|
||||||
|
export const commitRef = "91748965051fae1330ad58d15cf694e103267c87";
|
||||||
|
|
||||||
|
export const validPR = {
|
||||||
|
"url": "https://api.github.com/repos/owner/reponame/pulls/2368",
|
||||||
|
"id": 1137188271,
|
||||||
|
"node_id": "PR_kwDOABTq6s5DyB2v",
|
||||||
|
"html_url": "https://github.com/owner/reponame/pull/2368",
|
||||||
|
"diff_url": "https://github.com/owner/reponame/pull/2368.diff",
|
||||||
|
"patch_url": "https://github.com/owner/reponame/pull/2368.patch",
|
||||||
|
"issue_url": "https://api.github.com/repos/owner/reponame/issues/2368",
|
||||||
|
"number": 2368,
|
||||||
|
"state": "closed",
|
||||||
|
"locked": false,
|
||||||
|
"title": "PR Title",
|
||||||
|
"user": {
|
||||||
|
"login": "kie-ci",
|
||||||
|
"id": 11995863,
|
||||||
|
"node_id": "MDQ6VXNlcjExOTk1ODYz",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/11995863?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/kie-ci",
|
||||||
|
"html_url": "https://github.com/kie-ci",
|
||||||
|
"followers_url": "https://api.github.com/users/kie-ci/followers",
|
||||||
|
"following_url": "https://api.github.com/users/kie-ci/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/kie-ci/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/kie-ci/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/kie-ci/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/kie-ci/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/kie-ci/repos",
|
||||||
|
"events_url": "https://api.github.com/users/kie-ci/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/kie-ci/received_events",
|
||||||
|
"type": "User",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"body": "Please review and merge",
|
||||||
|
"created_at": "2022-11-28T08:43:09Z",
|
||||||
|
"updated_at": "2022-11-28T10:11:53Z",
|
||||||
|
"closed_at": "2022-11-28T10:11:52Z",
|
||||||
|
"merged_at": "2022-11-28T10:11:52Z",
|
||||||
|
"merge_commit_sha": "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc",
|
||||||
|
"assignee": null,
|
||||||
|
"assignees": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"requested_reviewers": [
|
||||||
|
{
|
||||||
|
"login": "ghuser",
|
||||||
|
"id": 1422582,
|
||||||
|
"node_id": "MDQ6VXNlcjE0MjI1ODI=",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1422582?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/ghuser",
|
||||||
|
"html_url": "https://github.com/ghuser",
|
||||||
|
"followers_url": "https://api.github.com/users/ghuser/followers",
|
||||||
|
"following_url": "https://api.github.com/users/ghuser/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/ghuser/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/ghuser/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/ghuser/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/ghuser/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/ghuser/repos",
|
||||||
|
"events_url": "https://api.github.com/users/ghuser/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/ghuser/received_events",
|
||||||
|
"type": "User",
|
||||||
|
"site_admin": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requested_teams": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"labels": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"milestone": null,
|
||||||
|
"draft": false,
|
||||||
|
"commits_url": "https://api.github.com/repos/owner/reponame/pulls/2368/commits",
|
||||||
|
"review_comments_url": "https://api.github.com/repos/owner/reponame/pulls/2368/comments",
|
||||||
|
"review_comment_url": "https://api.github.com/repos/owner/reponame/pulls/comments{/number}",
|
||||||
|
"comments_url": "https://api.github.com/repos/owner/reponame/issues/2368/comments",
|
||||||
|
"statuses_url": "https://api.github.com/repos/owner/reponame/statuses/91748965051fae1330ad58d15cf694e103267c87",
|
||||||
|
"head": {
|
||||||
|
"label": "kiegroup:bump-8.31.x-drools-8.31.0.Final",
|
||||||
|
"ref": "bump-8.31.x-drools-8.31.0.Final",
|
||||||
|
"sha": "91748965051fae1330ad58d15cf694e103267c87",
|
||||||
|
"user": {
|
||||||
|
"login": "kiegroup",
|
||||||
|
"id": 517980,
|
||||||
|
"node_id": "MDEyOk9yZ2FuaXphdGlvbjUxNzk4MA==",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/517980?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/kiegroup",
|
||||||
|
"html_url": "https://github.com/kiegroup",
|
||||||
|
"followers_url": "https://api.github.com/users/kiegroup/followers",
|
||||||
|
"following_url": "https://api.github.com/users/kiegroup/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/kiegroup/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/kiegroup/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/kiegroup/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/kiegroup/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/kiegroup/repos",
|
||||||
|
"events_url": "https://api.github.com/users/kiegroup/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/kiegroup/received_events",
|
||||||
|
"type": "Organization",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"repo": {
|
||||||
|
"id": 1370858,
|
||||||
|
"node_id": "MDEwOlJlcG9zaXRvcnkxMzcwODU4",
|
||||||
|
"name": "optaplanner",
|
||||||
|
"full_name": "fork/reponame",
|
||||||
|
"private": false,
|
||||||
|
"owner": {
|
||||||
|
"login": "kiegroup",
|
||||||
|
"id": 517980,
|
||||||
|
"node_id": "MDEyOk9yZ2FuaXphdGlvbjUxNzk4MA==",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/517980?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/kiegroup",
|
||||||
|
"html_url": "https://github.com/kiegroup",
|
||||||
|
"followers_url": "https://api.github.com/users/kiegroup/followers",
|
||||||
|
"following_url": "https://api.github.com/users/kiegroup/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/kiegroup/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/kiegroup/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/kiegroup/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/kiegroup/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/kiegroup/repos",
|
||||||
|
"events_url": "https://api.github.com/users/kiegroup/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/kiegroup/received_events",
|
||||||
|
"type": "Organization",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"html_url": "https://github.com/fork/reponame",
|
||||||
|
"description": "AI constraint solver in Java to optimize the vehicle routing problem, employee rostering, task assignment, maintenance scheduling, conference scheduling and other planning problems.",
|
||||||
|
"fork": false,
|
||||||
|
"url": "https://api.github.com/repos/fork/reponame",
|
||||||
|
"forks_url": "https://api.github.com/repos/fork/reponame/forks",
|
||||||
|
"keys_url": "https://api.github.com/repos/fork/reponame/keys{/key_id}",
|
||||||
|
"collaborators_url": "https://api.github.com/repos/fork/reponame/collaborators{/collaborator}",
|
||||||
|
"teams_url": "https://api.github.com/repos/fork/reponame/teams",
|
||||||
|
"hooks_url": "https://api.github.com/repos/fork/reponame/hooks",
|
||||||
|
"issue_events_url": "https://api.github.com/repos/fork/reponame/issues/events{/number}",
|
||||||
|
"events_url": "https://api.github.com/repos/fork/reponame/events",
|
||||||
|
"assignees_url": "https://api.github.com/repos/fork/reponame/assignees{/user}",
|
||||||
|
"branches_url": "https://api.github.com/repos/fork/reponame/branches{/branch}",
|
||||||
|
"tags_url": "https://api.github.com/repos/fork/reponame/tags",
|
||||||
|
"blobs_url": "https://api.github.com/repos/fork/reponame/git/blobs{/sha}",
|
||||||
|
"git_tags_url": "https://api.github.com/repos/fork/reponame/git/tags{/sha}",
|
||||||
|
"git_refs_url": "https://api.github.com/repos/fork/reponame/git/refs{/sha}",
|
||||||
|
"trees_url": "https://api.github.com/repos/fork/reponame/git/trees{/sha}",
|
||||||
|
"statuses_url": "https://api.github.com/repos/fork/reponame/statuses/{sha}",
|
||||||
|
"languages_url": "https://api.github.com/repos/fork/reponame/languages",
|
||||||
|
"stargazers_url": "https://api.github.com/repos/fork/reponame/stargazers",
|
||||||
|
"contributors_url": "https://api.github.com/repos/fork/reponame/contributors",
|
||||||
|
"subscribers_url": "https://api.github.com/repos/fork/reponame/subscribers",
|
||||||
|
"subscription_url": "https://api.github.com/repos/fork/reponame/subscription",
|
||||||
|
"commits_url": "https://api.github.com/repos/fork/reponame/commits{/sha}",
|
||||||
|
"git_commits_url": "https://api.github.com/repos/fork/reponame/git/commits{/sha}",
|
||||||
|
"comments_url": "https://api.github.com/repos/fork/reponame/comments{/number}",
|
||||||
|
"issue_comment_url": "https://api.github.com/repos/fork/reponame/issues/comments{/number}",
|
||||||
|
"contents_url": "https://api.github.com/repos/fork/reponame/contents/{+path}",
|
||||||
|
"compare_url": "https://api.github.com/repos/fork/reponame/compare/{base}...{head}",
|
||||||
|
"merges_url": "https://api.github.com/repos/fork/reponame/merges",
|
||||||
|
"archive_url": "https://api.github.com/repos/fork/reponame/{archive_format}{/ref}",
|
||||||
|
"downloads_url": "https://api.github.com/repos/fork/reponame/downloads",
|
||||||
|
"issues_url": "https://api.github.com/repos/fork/reponame/issues{/number}",
|
||||||
|
"pulls_url": "https://api.github.com/repos/fork/reponame/pulls{/number}",
|
||||||
|
"milestones_url": "https://api.github.com/repos/fork/reponame/milestones{/number}",
|
||||||
|
"notifications_url": "https://api.github.com/repos/fork/reponame/notifications{?since,all,participating}",
|
||||||
|
"labels_url": "https://api.github.com/repos/fork/reponame/labels{/name}",
|
||||||
|
"releases_url": "https://api.github.com/repos/fork/reponame/releases{/id}",
|
||||||
|
"deployments_url": "https://api.github.com/repos/fork/reponame/deployments",
|
||||||
|
"created_at": "2011-02-15T19:38:23Z",
|
||||||
|
"updated_at": "2022-11-28T05:01:47Z",
|
||||||
|
"pushed_at": "2022-11-28T10:50:51Z",
|
||||||
|
"git_url": "git://github.com/fork/reponame.git",
|
||||||
|
"ssh_url": "git@github.com:fork/reponame.git",
|
||||||
|
"clone_url": "https://github.com/fork/reponame.git",
|
||||||
|
"svn_url": "https://github.com/fork/reponame",
|
||||||
|
"homepage": "https://www.optaplanner.org",
|
||||||
|
"size": 238339,
|
||||||
|
"stargazers_count": 2811,
|
||||||
|
"watchers_count": 2811,
|
||||||
|
"language": "Java",
|
||||||
|
"has_issues": false,
|
||||||
|
"has_projects": false,
|
||||||
|
"has_downloads": true,
|
||||||
|
"has_wiki": false,
|
||||||
|
"has_pages": false,
|
||||||
|
"has_discussions": false,
|
||||||
|
"forks_count": 878,
|
||||||
|
"mirror_url": null,
|
||||||
|
"archived": false,
|
||||||
|
"disabled": false,
|
||||||
|
"open_issues_count": 30,
|
||||||
|
"license": {
|
||||||
|
"key": "apache-2.0",
|
||||||
|
"name": "Apache License 2.0",
|
||||||
|
"spdx_id": "Apache-2.0",
|
||||||
|
"url": "https://api.github.com/licenses/apache-2.0",
|
||||||
|
"node_id": "MDc6TGljZW5zZTI="
|
||||||
|
},
|
||||||
|
"allow_forking": true,
|
||||||
|
"is_template": false,
|
||||||
|
"web_commit_signoff_required": false,
|
||||||
|
"topics": [
|
||||||
|
"artificial-intelligence",
|
||||||
|
"branch-and-bound",
|
||||||
|
"constraint-programming",
|
||||||
|
"constraint-satisfaction-problem",
|
||||||
|
"constraint-solver",
|
||||||
|
"constraints",
|
||||||
|
"employee-rostering",
|
||||||
|
"java",
|
||||||
|
"local-search",
|
||||||
|
"mathematical-optimization",
|
||||||
|
"metaheuristics",
|
||||||
|
"optimization",
|
||||||
|
"rostering",
|
||||||
|
"scheduling",
|
||||||
|
"simulated-annealing",
|
||||||
|
"solver",
|
||||||
|
"tabu-search",
|
||||||
|
"traveling-salesman",
|
||||||
|
"traveling-salesman-problem",
|
||||||
|
"vehicle-routing-problem"
|
||||||
|
],
|
||||||
|
"visibility": "public",
|
||||||
|
"forks": 878,
|
||||||
|
"open_issues": 30,
|
||||||
|
"watchers": 2811,
|
||||||
|
"default_branch": "main"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"base": {
|
||||||
|
"label": "kiegroup:8.31.x",
|
||||||
|
"ref": "8.31.x",
|
||||||
|
"sha": "8cfc286765cb01c84a1d62c65519fa8032bfecbd",
|
||||||
|
"user": {
|
||||||
|
"login": "kiegroup",
|
||||||
|
"id": 517980,
|
||||||
|
"node_id": "MDEyOk9yZ2FuaXphdGlvbjUxNzk4MA==",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/517980?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/kiegroup",
|
||||||
|
"html_url": "https://github.com/kiegroup",
|
||||||
|
"followers_url": "https://api.github.com/users/kiegroup/followers",
|
||||||
|
"following_url": "https://api.github.com/users/kiegroup/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/kiegroup/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/kiegroup/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/kiegroup/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/kiegroup/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/kiegroup/repos",
|
||||||
|
"events_url": "https://api.github.com/users/kiegroup/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/kiegroup/received_events",
|
||||||
|
"type": "Organization",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"repo": {
|
||||||
|
"id": 1370858,
|
||||||
|
"node_id": "MDEwOlJlcG9zaXRvcnkxMzcwODU4",
|
||||||
|
"name": "optaplanner",
|
||||||
|
"full_name": "owner/reponame",
|
||||||
|
"private": false,
|
||||||
|
"owner": {
|
||||||
|
"login": "kiegroup",
|
||||||
|
"id": 517980,
|
||||||
|
"node_id": "MDEyOk9yZ2FuaXphdGlvbjUxNzk4MA==",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/517980?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/kiegroup",
|
||||||
|
"html_url": "https://github.com/kiegroup",
|
||||||
|
"followers_url": "https://api.github.com/users/kiegroup/followers",
|
||||||
|
"following_url": "https://api.github.com/users/kiegroup/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/kiegroup/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/kiegroup/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/kiegroup/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/kiegroup/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/kiegroup/repos",
|
||||||
|
"events_url": "https://api.github.com/users/kiegroup/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/kiegroup/received_events",
|
||||||
|
"type": "Organization",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"html_url": "https://github.com/owner/reponame",
|
||||||
|
"description": "AI constraint solver in Java to optimize the vehicle routing problem, employee rostering, task assignment, maintenance scheduling, conference scheduling and other planning problems.",
|
||||||
|
"fork": false,
|
||||||
|
"url": "https://api.github.com/repos/owner/reponame",
|
||||||
|
"forks_url": "https://api.github.com/repos/owner/reponame/forks",
|
||||||
|
"keys_url": "https://api.github.com/repos/owner/reponame/keys{/key_id}",
|
||||||
|
"collaborators_url": "https://api.github.com/repos/owner/reponame/collaborators{/collaborator}",
|
||||||
|
"teams_url": "https://api.github.com/repos/owner/reponame/teams",
|
||||||
|
"hooks_url": "https://api.github.com/repos/owner/reponame/hooks",
|
||||||
|
"issue_events_url": "https://api.github.com/repos/owner/reponame/issues/events{/number}",
|
||||||
|
"events_url": "https://api.github.com/repos/owner/reponame/events",
|
||||||
|
"assignees_url": "https://api.github.com/repos/owner/reponame/assignees{/user}",
|
||||||
|
"branches_url": "https://api.github.com/repos/owner/reponame/branches{/branch}",
|
||||||
|
"tags_url": "https://api.github.com/repos/owner/reponame/tags",
|
||||||
|
"blobs_url": "https://api.github.com/repos/owner/reponame/git/blobs{/sha}",
|
||||||
|
"git_tags_url": "https://api.github.com/repos/owner/reponame/git/tags{/sha}",
|
||||||
|
"git_refs_url": "https://api.github.com/repos/owner/reponame/git/refs{/sha}",
|
||||||
|
"trees_url": "https://api.github.com/repos/owner/reponame/git/trees{/sha}",
|
||||||
|
"statuses_url": "https://api.github.com/repos/owner/reponame/statuses/{sha}",
|
||||||
|
"languages_url": "https://api.github.com/repos/owner/reponame/languages",
|
||||||
|
"stargazers_url": "https://api.github.com/repos/owner/reponame/stargazers",
|
||||||
|
"contributors_url": "https://api.github.com/repos/owner/reponame/contributors",
|
||||||
|
"subscribers_url": "https://api.github.com/repos/owner/reponame/subscribers",
|
||||||
|
"subscription_url": "https://api.github.com/repos/owner/reponame/subscription",
|
||||||
|
"commits_url": "https://api.github.com/repos/owner/reponame/commits{/sha}",
|
||||||
|
"git_commits_url": "https://api.github.com/repos/owner/reponame/git/commits{/sha}",
|
||||||
|
"comments_url": "https://api.github.com/repos/owner/reponame/comments{/number}",
|
||||||
|
"issue_comment_url": "https://api.github.com/repos/owner/reponame/issues/comments{/number}",
|
||||||
|
"contents_url": "https://api.github.com/repos/owner/reponame/contents/{+path}",
|
||||||
|
"compare_url": "https://api.github.com/repos/owner/reponame/compare/{base}...{head}",
|
||||||
|
"merges_url": "https://api.github.com/repos/owner/reponame/merges",
|
||||||
|
"archive_url": "https://api.github.com/repos/owner/reponame/{archive_format}{/ref}",
|
||||||
|
"downloads_url": "https://api.github.com/repos/owner/reponame/downloads",
|
||||||
|
"issues_url": "https://api.github.com/repos/owner/reponame/issues{/number}",
|
||||||
|
"pulls_url": "https://api.github.com/repos/owner/reponame/pulls{/number}",
|
||||||
|
"milestones_url": "https://api.github.com/repos/owner/reponame/milestones{/number}",
|
||||||
|
"notifications_url": "https://api.github.com/repos/owner/reponame/notifications{?since,all,participating}",
|
||||||
|
"labels_url": "https://api.github.com/repos/owner/reponame/labels{/name}",
|
||||||
|
"releases_url": "https://api.github.com/repos/owner/reponame/releases{/id}",
|
||||||
|
"deployments_url": "https://api.github.com/repos/owner/reponame/deployments",
|
||||||
|
"created_at": "2011-02-15T19:38:23Z",
|
||||||
|
"updated_at": "2022-11-28T05:01:47Z",
|
||||||
|
"pushed_at": "2022-11-28T10:50:51Z",
|
||||||
|
"git_url": "git://github.com/owner/reponame.git",
|
||||||
|
"ssh_url": "git@github.com:owner/reponame.git",
|
||||||
|
"clone_url": "https://github.com/owner/reponame.git",
|
||||||
|
"svn_url": "https://github.com/owner/reponame",
|
||||||
|
"homepage": "https://www.optaplanner.org",
|
||||||
|
"size": 238339,
|
||||||
|
"stargazers_count": 2811,
|
||||||
|
"watchers_count": 2811,
|
||||||
|
"language": "Java",
|
||||||
|
"has_issues": false,
|
||||||
|
"has_projects": false,
|
||||||
|
"has_downloads": true,
|
||||||
|
"has_wiki": false,
|
||||||
|
"has_pages": false,
|
||||||
|
"has_discussions": false,
|
||||||
|
"forks_count": 878,
|
||||||
|
"mirror_url": null,
|
||||||
|
"archived": false,
|
||||||
|
"disabled": false,
|
||||||
|
"open_issues_count": 30,
|
||||||
|
"license": {
|
||||||
|
"key": "apache-2.0",
|
||||||
|
"name": "Apache License 2.0",
|
||||||
|
"spdx_id": "Apache-2.0",
|
||||||
|
"url": "https://api.github.com/licenses/apache-2.0",
|
||||||
|
"node_id": "MDc6TGljZW5zZTI="
|
||||||
|
},
|
||||||
|
"allow_forking": true,
|
||||||
|
"is_template": false,
|
||||||
|
"web_commit_signoff_required": false,
|
||||||
|
"topics": [
|
||||||
|
"artificial-intelligence",
|
||||||
|
"branch-and-bound",
|
||||||
|
"constraint-programming",
|
||||||
|
"constraint-satisfaction-problem",
|
||||||
|
"constraint-solver",
|
||||||
|
"constraints",
|
||||||
|
"employee-rostering",
|
||||||
|
"java",
|
||||||
|
"local-search",
|
||||||
|
"mathematical-optimization",
|
||||||
|
"metaheuristics",
|
||||||
|
"optimization",
|
||||||
|
"rostering",
|
||||||
|
"scheduling",
|
||||||
|
"simulated-annealing",
|
||||||
|
"solver",
|
||||||
|
"tabu-search",
|
||||||
|
"traveling-salesman",
|
||||||
|
"traveling-salesman-problem",
|
||||||
|
"vehicle-routing-problem"
|
||||||
|
],
|
||||||
|
"visibility": "public",
|
||||||
|
"forks": 878,
|
||||||
|
"open_issues": 30,
|
||||||
|
"watchers": 2811,
|
||||||
|
"default_branch": "main"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"_links": {
|
||||||
|
"self": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/pulls/2368"
|
||||||
|
},
|
||||||
|
"html": {
|
||||||
|
"href": "https://github.com/owner/reponame/pull/2368"
|
||||||
|
},
|
||||||
|
"issue": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/issues/2368"
|
||||||
|
},
|
||||||
|
"comments": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/issues/2368/comments"
|
||||||
|
},
|
||||||
|
"review_comments": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/pulls/2368/comments"
|
||||||
|
},
|
||||||
|
"review_comment": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/pulls/comments{/number}"
|
||||||
|
},
|
||||||
|
"commits": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/pulls/2368/commits"
|
||||||
|
},
|
||||||
|
"statuses": {
|
||||||
|
"href": "https://api.github.com/repos/owner/reponame/statuses/91748965051fae1330ad58d15cf694e103267c87"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"author_association": "CONTRIBUTOR",
|
||||||
|
"auto_merge": null,
|
||||||
|
"active_lock_reason": null,
|
||||||
|
"merged": true,
|
||||||
|
"mergeable": null,
|
||||||
|
"rebaseable": null,
|
||||||
|
"mergeable_state": "unknown",
|
||||||
|
"merged_by": {
|
||||||
|
"login": "radtriste",
|
||||||
|
"id": 17157711,
|
||||||
|
"node_id": "MDQ6VXNlcjE3MTU3NzEx",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/17157711?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/radtriste",
|
||||||
|
"html_url": "https://github.com/radtriste",
|
||||||
|
"followers_url": "https://api.github.com/users/radtriste/followers",
|
||||||
|
"following_url": "https://api.github.com/users/radtriste/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/radtriste/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/radtriste/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/radtriste/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/radtriste/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/radtriste/repos",
|
||||||
|
"events_url": "https://api.github.com/users/radtriste/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/radtriste/received_events",
|
||||||
|
"type": "User",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"comments": 0,
|
||||||
|
"review_comments": 0,
|
||||||
|
"maintainer_can_modify": false,
|
||||||
|
"commits": 2,
|
||||||
|
"additions": 2,
|
||||||
|
"deletions": 2,
|
||||||
|
"changed_files": 2
|
||||||
|
};
|
49
test/support/moctokit/moctokit-support.ts
Normal file
49
test/support/moctokit/moctokit-support.ts
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import LoggerServiceFactory from "@gb/service/logger/logger-service-factory";
|
||||||
|
import { Moctokit } from "@kie/mock-github";
|
||||||
|
import { targetOwner, repo, pullRequestNumber, validPR, invalidPullRequestNumber } from "./moctokit-data";
|
||||||
|
|
||||||
|
const logger = LoggerServiceFactory.getLogger();
|
||||||
|
|
||||||
|
export const setupMoctokit = (): Moctokit => {
|
||||||
|
logger.debug("Setting up moctokit..");
|
||||||
|
|
||||||
|
const mock = new Moctokit();
|
||||||
|
|
||||||
|
// setup the mock requests here
|
||||||
|
|
||||||
|
// valid requests
|
||||||
|
mock.rest.pulls
|
||||||
|
.get({
|
||||||
|
owner: targetOwner,
|
||||||
|
repo: repo,
|
||||||
|
pull_number: pullRequestNumber
|
||||||
|
})
|
||||||
|
.reply({
|
||||||
|
status: 200,
|
||||||
|
data: validPR
|
||||||
|
});
|
||||||
|
|
||||||
|
mock.rest.pulls
|
||||||
|
.create()
|
||||||
|
.reply({
|
||||||
|
status: 201,
|
||||||
|
data: validPR
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// invalid requests
|
||||||
|
mock.rest.pulls
|
||||||
|
.get({
|
||||||
|
owner: targetOwner,
|
||||||
|
repo: repo,
|
||||||
|
pull_number: invalidPullRequestNumber
|
||||||
|
})
|
||||||
|
.reply({
|
||||||
|
status: 404,
|
||||||
|
data: {
|
||||||
|
message: "Not found"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return mock;
|
||||||
|
};
|
130
tsconfig.json
Normal file
130
tsconfig.json
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||||
|
|
||||||
|
/* Projects */
|
||||||
|
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||||
|
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||||
|
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||||
|
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||||
|
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||||
|
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||||
|
|
||||||
|
/* Language and Environment */
|
||||||
|
"target": "ES2020",
|
||||||
|
/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||||
|
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||||
|
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||||
|
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||||
|
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||||
|
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||||
|
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||||
|
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||||
|
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||||
|
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||||
|
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||||
|
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||||
|
|
||||||
|
/* Modules */
|
||||||
|
"module": "commonjs",
|
||||||
|
/* Specify what module code is generated. */
|
||||||
|
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||||
|
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||||
|
"baseUrl": "./",
|
||||||
|
/* Specify the base directory to resolve non-relative module names. */
|
||||||
|
"paths": {
|
||||||
|
"@gb/*": [
|
||||||
|
"./src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
/* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||||
|
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||||
|
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||||
|
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||||
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||||
|
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||||
|
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||||
|
|
||||||
|
/* JavaScript Support */
|
||||||
|
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||||
|
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||||
|
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||||
|
|
||||||
|
/* Emit */
|
||||||
|
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||||
|
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||||
|
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||||
|
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||||
|
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||||
|
"outDir": "./build",
|
||||||
|
/* Specify an output folder for all emitted files. */
|
||||||
|
// "removeComments": true, /* Disable emitting comments. */
|
||||||
|
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||||
|
"importHelpers": false,
|
||||||
|
/* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||||
|
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||||
|
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||||
|
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||||
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
|
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||||
|
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||||
|
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||||
|
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||||
|
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||||
|
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||||
|
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||||
|
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||||
|
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||||
|
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||||
|
|
||||||
|
/* Interop Constraints */
|
||||||
|
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||||
|
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||||
|
"esModuleInterop": true,
|
||||||
|
/* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||||
|
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
/* Ensure that casing is correct in imports. */
|
||||||
|
|
||||||
|
/* Type Checking */
|
||||||
|
"strict": true,
|
||||||
|
/* Enable all strict type-checking options. */
|
||||||
|
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||||
|
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||||
|
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||||
|
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||||
|
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||||
|
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||||
|
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||||
|
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||||
|
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||||
|
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||||
|
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||||
|
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||||
|
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||||
|
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||||
|
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||||
|
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||||
|
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||||
|
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||||
|
|
||||||
|
/* Completeness */
|
||||||
|
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||||
|
"skipLibCheck": true
|
||||||
|
/* Skip type checking all .d.ts files. */
|
||||||
|
},
|
||||||
|
"ts-node": {
|
||||||
|
// Do not forget to `npm install --save-dev tsconfig-paths`
|
||||||
|
"require": ["tsconfig-paths/register"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src",
|
||||||
|
"test"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"build",
|
||||||
|
"dist"
|
||||||
|
]
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue