Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.hp.octane.integrations.services.pullrequestsandbranches.gitlab.GitlabServerFetchHandler Maven / Gradle / Ivy
/**
* Copyright 2017-2023 Open Text
*
* The only warranties for products and services of Open Text and
* its affiliates and licensors (“Open Text”) are as may be set forth
* in the express warranty statements accompanying such products and services.
* Nothing herein should be construed as constituting an additional warranty.
* Open Text shall not be liable for technical or editorial errors or
* omissions contained herein. The information contained herein is subject
* to change without notice.
*
* Except as specifically indicated otherwise, this document contains
* confidential information and a valid license is required for possession,
* use or copying. If this work is provided to the U.S. Government,
* consistent with FAR 12.211 and 12.212, Commercial Computer Software,
* Computer Software Documentation, and Technical Data for Commercial Items are
* licensed to the U.S. Government under vendor's standard commercial license.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hp.octane.integrations.services.pullrequestsandbranches.gitlab;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.hp.octane.integrations.dto.DTOFactory;
import com.hp.octane.integrations.dto.connectivity.OctaneResponse;
import com.hp.octane.integrations.dto.scm.Branch;
import com.hp.octane.integrations.dto.scm.PullRequest;
import com.hp.octane.integrations.dto.scm.SCMRepository;
import com.hp.octane.integrations.dto.scm.SCMRepositoryLinks;
import com.hp.octane.integrations.dto.scm.SCMType;
import com.hp.octane.integrations.services.pullrequestsandbranches.factory.BranchFetchParameters;
import com.hp.octane.integrations.services.pullrequestsandbranches.factory.CommitUserIdPicker;
import com.hp.octane.integrations.services.pullrequestsandbranches.factory.FetchHandler;
import com.hp.octane.integrations.services.pullrequestsandbranches.factory.FetchUtils;
import com.hp.octane.integrations.services.pullrequestsandbranches.factory.PullRequestFetchParameters;
import com.hp.octane.integrations.services.pullrequestsandbranches.factory.RepoTemplates;
import com.hp.octane.integrations.services.pullrequestsandbranches.gitlab.pojo.Repository;
import com.hp.octane.integrations.services.pullrequestsandbranches.rest.authentication.AuthenticationStrategy;
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.models.AbstractUser;
import org.gitlab4j.api.models.Commit;
import org.gitlab4j.api.models.MergeRequest;
import org.gitlab4j.api.models.Project;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class GitlabServerFetchHandler extends FetchHandler {
protected static final DTOFactory dtoFactory = DTOFactory.getInstance();
private final String secret;
private GitLabApi gitLabApi;
private Project gitLabProject;
public GitlabServerFetchHandler(AuthenticationStrategy authenticationStrategy, String token) {
super(authenticationStrategy);
this.secret = token;
}
private void initGitlab(String baseUrl) {
if (baseUrl.endsWith(".git")) {
baseUrl = baseUrl.substring(0, baseUrl.length() - 4);
}
String[] split = baseUrl.split("//");
String path = split[1];
int i = path.indexOf('/');
StringBuffer urlSB = new StringBuffer();
urlSB.append(split[0]).append("//").append(path, 0, i);
StringBuffer pathSB = new StringBuffer();
pathSB.append(path, i + 1, path.length());
String GLURL = urlSB.toString();
this.gitLabApi = new GitLabApi(GitLabApi.ApiVersion.V4, GLURL, this.secret);
try {
this.gitLabProject = gitLabApi.getProjectApi().getProject(pathSB.toString());
} catch (GitLabApiException e) {
throw new RuntimeException(e);
}
}
@Override
public List fetchPullRequests(PullRequestFetchParameters parameters, CommitUserIdPicker commitUserIdPicker,
Consumer logger) {
List result = new ArrayList<>();
List mergeRequests;
initGitlab(parameters.getRepoUrl());
try {
mergeRequests = this.gitLabApi.getMergeRequestApi()
.getMergeRequests(this.gitLabProject.getId(), parameters.getPageSize()).all()
.stream()
.filter(mr -> mr.getUpdatedAt().getTime() > parameters.getMinUpdateTime())
.sorted(
Comparator.comparing(MergeRequest::getUpdatedAt)).collect(
Collectors.toList());
//remove exceeding items
while (mergeRequests.size() > parameters.getMaxPRsToFetch()) {
mergeRequests.remove(0);
}
List sourcePatterns = FetchUtils.buildPatterns(parameters.getSourceBranchFilter());
List targetPatterns = FetchUtils.buildPatterns(parameters.getTargetBranchFilter());
List filteredMergeRequests = mergeRequests.stream()
.filter(mr -> FetchUtils.isBranchMatch(sourcePatterns, mr.getSourceBranch()) &&
FetchUtils.isBranchMatch(targetPatterns, mr.getTargetBranch())).collect(Collectors.toList());
logger.accept(String.format("Received %d merge-requests, while %d are matching source/target filters", mergeRequests.size(),
filteredMergeRequests.size()));
printMergeRequestTitles(logger, mergeRequests, "Received merge-requests:");
printMergeRequestTitles(logger, filteredMergeRequests, "Matching merge-requests:");
if (!filteredMergeRequests.isEmpty()) {
Set usersWithoutMails =
filteredMergeRequests.stream().map(MergeRequest::getAuthor).filter(au -> au.getEmail() == null)
.map(AbstractUser::getUsername).collect(Collectors.toSet());
if (!usersWithoutMails.isEmpty()) {
logger.accept("Note : Some users doesn't have defined public email in their profile. For such users, SCM user will contain their Username: " +
usersWithoutMails);
}
logger.accept("Fetching commits ...");
int counter = 0;
for (MergeRequest mergeRequest : filteredMergeRequests) {
List commits =
gitLabApi.getMergeRequestApi().getCommits(this.gitLabProject.getId(), mergeRequest.getIid());
List dtoCommits = new ArrayList<>();
commits.forEach(commit -> {
com.hp.octane.integrations.dto.scm.SCMCommit dtoCommit = dtoFactory.newDTO(com.hp.octane.integrations.dto.scm.SCMCommit.class)
.setRevId(commit.getId())
.setComment(commit.getMessage())
.setUser(getUserName(commit.getCommitterEmail(), commit.getCommitterName()))
.setUserEmail(commit.getCommitterEmail())
.setTime(commit.getTimestamp() != null ? commit.getTimestamp().getTime() : new Date().getTime())
.setParentRevId(Objects.isNull(commit.getParentIds())
? null
: (commit.getParentIds().isEmpty() ? null : commit.getParentIds().get(0)));
dtoCommits.add(dtoCommit);
});
SCMRepository sourceRepository = buildScmRepository(parameters.getRepoUrl(),mergeRequest.getSourceBranch());
SCMRepository targetRepository = buildScmRepository(parameters.getRepoUrl(),mergeRequest.getTargetBranch());
String userId = getUserName(commitUserIdPicker, mergeRequest.getAuthor().getEmail(), mergeRequest.getAuthor().getName());
com.hp.octane.integrations.dto.scm.PullRequest dtoPullRequest = dtoFactory.newDTO(com.hp.octane.integrations.dto.scm.PullRequest.class)
.setId(Long.toString(mergeRequest.getIid()))
.setTitle(mergeRequest.getTitle())
.setDescription(mergeRequest.getDescription())
.setState(mergeRequest.getState())
.setCreatedTime(
Objects.isNull(mergeRequest.getCreatedAt()) ? null : mergeRequest.getCreatedAt().getTime())
.setUpdatedTime(
Objects.isNull(mergeRequest.getUpdatedAt()) ? null : mergeRequest.getUpdatedAt().getTime())
.setMergedTime(
Objects.isNull(mergeRequest.getMergedAt()) ? null : mergeRequest.getMergedAt().getTime())
.setIsMerged(Objects.nonNull(mergeRequest.getMergedAt()))
.setAuthorName(userId)
.setAuthorEmail(Objects.isNull(mergeRequest.getAuthor()) ? null : mergeRequest.getAuthor().getEmail())
.setClosedTime(Objects.isNull(mergeRequest.getClosedAt()) ? null : mergeRequest.getClosedAt().getTime())
.setSelfUrl(mergeRequest.getWebUrl())
.setSourceRepository(sourceRepository)
.setTargetRepository(targetRepository)
.setCommits(dtoCommits);
result.add(dtoPullRequest);
if (counter > 0 && counter % 25 == 0) {
logger.accept("Fetching commits " + counter * 100 / filteredMergeRequests.size() + "%");
}
counter++;
}
}
else {
logger.accept("No new/updated PR is found.");
}
return result;
} catch (GitLabApiException e) {
throw new RuntimeException(e);
}
}
private void printMergeRequestTitles(Consumer logConsumer, List mergeRequests, String textToPrint) {
if (mergeRequests.isEmpty()) {
return;
}
logConsumer.accept(textToPrint);
for (MergeRequest mr : mergeRequests) {
String prTitle = (null == mr.getTitle()) ? "" : mr.getTitle();
logConsumer.accept(prTitle);
}
}
@Override
public List fetchBranches(BranchFetchParameters parameters, Map sha2DateMapCache,
Consumer logger) throws IOException {
initGitlab(parameters.getRepoUrl());
List branches;
try {
branches = gitLabApi.getRepositoryApi().getBranches(this.gitLabProject.getId(), parameters.getPageSize()).all();
} catch (GitLabApiException e) {
throw new RuntimeException(e);
}
List filterPatterns = FetchUtils.buildPatterns(parameters.getFilter());
List filteredBranches = branches.stream().filter(br -> FetchUtils.isBranchMatch(filterPatterns, br.getName()))
.map(this::convertToDTOBranch).collect(Collectors.toList());
long outdatedTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(parameters.getActiveBranchDays());
int fetched = 0;
int outdated = 0;
for (com.hp.octane.integrations.dto.scm.Branch branch : filteredBranches) {
if (sha2DateMapCache != null && sha2DateMapCache.containsKey(branch.getLastCommitSHA())) {
branch.setLastCommitTime(sha2DateMapCache.get(branch.getLastCommitSHA()));
if (branch.getLastCommitTime() < outdatedTime) {
outdated++;
continue;
}
}
if (fetched < parameters.getMaxBranchesToFill()) {
branch.setPartial(false);
fetched++;
}
}
logger.accept(String.format("Found %d branches in GitLab, while %d are matching filters", branches.size(),
filteredBranches.size()));
if (!filteredBranches.isEmpty()) {
logger.accept("Fetching branches is done");
} else {
logger.accept("No new/updated branch is found.");
}
logger.accept(String.format("Fetching branches is done, fetched %s, skipped as outdated %s", fetched, outdated));
return filteredBranches;
}
private com.hp.octane.integrations.dto.scm.Branch convertToDTOBranch(
org.gitlab4j.api.models.Branch branch) {
return DTOFactory.getInstance().newDTO(com.hp.octane.integrations.dto.scm.Branch.class)
.setName(branch.getName())
.setLastCommitUrl(branch.getCommit().getUrl())
.setLastCommitSHA(branch.getCommit().getId())
.setLastCommitTime(branch.getCommit().getCommittedDate().getTime())
.setLastCommiterName(branch.getCommit().getCommitterName())
.setLastCommiterEmail(branch.getCommit().getCommitterEmail())
.setIsMerged(branch.getMerged())
.setPartial(true);
}
@Override
public String getRepoApiPath(String repoHttpCloneUrl) {
//https://hmf.gitlab.otxlab.net/adm-sdp/something/somethingElse => https://hmf.gitlab.otxlab.net/api/v4/projects/adm-sdp/something%2FsomethingElse
try {
if (repoHttpCloneUrl.endsWith(".git")) {
repoHttpCloneUrl = repoHttpCloneUrl.substring(0, repoHttpCloneUrl.length() - 4);
}
if (repoHttpCloneUrl.contains("//")) {
List list = Arrays.asList(repoHttpCloneUrl.split("//"));
String rest = list.get(1);
int i = rest.indexOf('/');
String encoded = rest.substring(i + 1).replace("/", "%2F");
StringBuffer sb = new StringBuffer();
sb.append(list.get(0)).append("//").append(rest, 0, i).append("/api/v4/projects/").append(encoded);
return sb.toString();
} else {
throw new Exception();
}
} catch (Exception e) {
throw new IllegalArgumentException("Unexpected format for gitlab server repository URL : " + repoHttpCloneUrl);
}
}
@Override
protected String parseRequestError(OctaneResponse response) {
return JsonConverter.getErrorMessage(response.getBody());
}
@Override
public SCMRepositoryLinks parseSCMRepositoryLinks(String responseBody) throws JsonProcessingException {
Repository repo = JsonConverter.convert(responseBody, Repository.class);
SCMRepositoryLinks links = dtoFactory.newDTO(SCMRepositoryLinks.class).setHttpUrl(repo.getHttp_url_to_repo()).setSshUrl(repo.getSsh_url_to_repo());
return links;
}
@Override
public RepoTemplates buildRepoTemplates(String repoApiBaseUrl) {
String selfUrl = repoApiBaseUrl.substring(0, repoApiBaseUrl.length() - 4);//remove .git at the end
RepoTemplates repoTemplates = new RepoTemplates();
repoTemplates.setDiffTemplate(selfUrl + "/commit/{revision}#{filePath}");
repoTemplates.setSourceViewTemplate(selfUrl + "/blob/{revision}/{filePath}");
repoTemplates.setBranchFileTemplate(selfUrl + "/tree/{branchName}/{filePath}");
return repoTemplates;
}
private SCMRepository buildScmRepository(String repoUrl, String branch) {
return dtoFactory.newDTO(SCMRepository.class)
.setUrl(repoUrl)
.setBranch(branch)
.setType(SCMType.GIT);
}
}