feat: auto-detect the value of the no-squash option (#118)

The auto-no-squash option is added to:

* backport all the commits when the pull/merge request has been merged
* backport the squashed commit otherwise

It is equivalent to dynamically adjust the value of the no-squash
option, depending on the context.

The no-squash option is kept for backward compatibility for a single
use case: backporting the merged commit instead of backporting the
commits of the pull/merge request request.

Detecting if a pull/merge request was squashed or not depends on the
underlying forge:

* Forgejo / GitHub: use the API to count the number of parents
* GitLab: if the squash_commit_sha is set, the merge request was
  squashed

If the pull/merge request is open, always backport all the commits it
contains.

Fixes: https://github.com/kiegroup/git-backporting/issues/113

Co-authored-by: Andrea Lamparelli <a.lamparelli95@gmail.com>
This commit is contained in:
Earl Warren 2024-04-08 18:51:13 +02:00 committed by GitHub
parent fc5dba6703
commit 6042bcc40b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 324 additions and 54 deletions

View file

@ -1,4 +1,5 @@
import GitClient from "@bp/service/git/git-client";
import { inferSquash } from "@bp/service/git/git-util";
import { BackportPullRequest, GitClientType, GitPullRequest } from "@bp/service/git/git.types";
import GitHubMapper from "@bp/service/git/github/github-mapper";
import OctokitFactory from "@bp/service/git/github/octokit-factory";
@ -37,7 +38,7 @@ export default class GitHubClient implements GitClient {
return "noreply@github.com";
}
async getPullRequest(owner: string, repo: string, prNumber: number, squash = true): Promise<GitPullRequest> {
async getPullRequest(owner: string, repo: string, prNumber: number, squash: boolean | undefined): Promise<GitPullRequest> {
this.logger.debug(`Fetching pull request ${owner}/${repo}/${prNumber}`);
const { data } = await this.octokit.rest.pulls.get({
owner: owner,
@ -45,6 +46,22 @@ export default class GitHubClient implements GitClient {
pull_number: prNumber,
});
if (squash === undefined) {
let commit_sha: string | undefined = undefined;
const open: boolean = data.state == "open";
if (!open) {
const commit = await this.octokit.rest.git.getCommit({
owner: owner,
repo: repo,
commit_sha: (data.merge_commit_sha as string),
});
if (commit.data.parents.length === 1) {
commit_sha = (data.merge_commit_sha as string);
}
}
squash = inferSquash(open, commit_sha);
}
const commits: string[] = [];
if (!squash) {
// fetch all commits
@ -64,7 +81,7 @@ export default class GitHubClient implements GitClient {
return this.mapper.mapPullRequest(data as PullRequest, commits);
}
async getPullRequestFromUrl(prUrl: string, squash = true): Promise<GitPullRequest> {
async getPullRequestFromUrl(prUrl: string, squash: boolean | undefined): Promise<GitPullRequest> {
const { owner, project, id } = this.extractPullRequestData(prUrl);
return this.getPullRequest(owner, project, id, squash);
}