use of com.hp.octane.integrations.services.pullrequestsandbranches.github.GithubV3FetchHandler in project octane-ci-java-sdk by MicroFocus.
the class PullRequestAndBranchServiceImpl method syncBranchesToOctane.
@Override
public BranchSyncResult syncBranchesToOctane(FetchHandler fetcherHandler, BranchFetchParameters fp, Long workspaceId, CommitUserIdPicker idPicker, Consumer<String> logConsumer) throws IOException {
// update ssh url
String baseUrl = fetcherHandler.getRepoApiPath(fp.getRepoUrl());
logConsumer.accept(fetcherHandler.getClass().getSimpleName() + " handler, Base url : " + baseUrl);
SCMRepositoryLinks links = fetcherHandler.pingRepository(baseUrl, logConsumer);
fp.setRepoUrlSsh(links.getSshUrl());
if (fp.isUseSSHFormat()) {
logConsumer.accept("Repo ssh format url : " + fp.getRepoUrlSsh());
}
String repoUrlForOctane = fp.isUseSSHFormat() ? fp.getRepoUrlSsh() : fp.getRepoUrl();
// LOAD FROM CACHE
boolean supportCaching = fetcherHandler instanceof GithubV3FetchHandler;
Map<String, Long> sha2DateMapCache = null;
if (supportCaching) {
sha2DateMapCache = loadBranchCommitsFromCache(repoUrlForOctane, logConsumer);
}
// FETCH FROM CI SERVER
List<Branch> ciServerBranches = fetcherHandler.fetchBranches(fp, sha2DateMapCache, logConsumer);
Map<String, Branch> ciServerBranchMap = ciServerBranches.stream().collect(Collectors.toMap(Branch::getName, Function.identity()));
// SAVE TO CACHE
if (supportCaching) {
saveBranchCommitsToCache(repoUrlForOctane, logConsumer, sha2DateMapCache, ciServerBranches);
}
// GET BRANCHES FROM OCTANE
String repoShortName = FetchUtils.getRepoShortName(fp.getRepoUrl());
List<Entity> roots = getRepositoryRoots(repoUrlForOctane, workspaceId);
List<Entity> octaneBranches = null;
String rootId;
if (roots != null && !roots.isEmpty()) {
rootId = roots.get(0).getId();
octaneBranches = getRepositoryBranches(rootId, workspaceId, false);
logConsumer.accept("Found repository root with id " + rootId);
} else {
Entity createdRoot = createRepositoryRoot(repoUrlForOctane, repoShortName, workspaceId);
rootId = createdRoot.getId();
logConsumer.accept("Repository root is created with id " + rootId);
}
if (octaneBranches == null) {
octaneBranches = Collections.emptyList();
}
List<Pattern> filterPatterns = FetchUtils.buildPatterns(fp.getFilter());
Map<String, List<Entity>> octaneBranchMap = octaneBranches.stream().filter(br -> FetchUtils.isBranchMatch(filterPatterns, br.getName())).collect(groupingBy(b -> b.getName()));
logConsumer.accept("Found " + octaneBranches.size() + " branches in ALM Octane related to defined filter.");
// GENERATE UPDATES
String finalRootId = rootId;
BranchSyncResult result = new BranchSyncResult();
// DELETED
octaneBranchMap.entrySet().stream().filter(entry -> !ciServerBranchMap.containsKey(entry.getKey())).map(e -> e.getValue()).flatMap(Collection::stream).map(e -> dtoFactory.newDTO(Branch.class).setOctaneId(e.getId()).setName(e.getName())).forEach(b -> result.getDeleted().add(b));
// NEW AND UPDATES
ciServerBranches.forEach(ciBranch -> {
if (ciBranch.isPartial()) {
// SKIP if branch is partial (it can happen because of rate limitations or because branch is merged to master or not active for long time)
return;
}
List<Entity> octaneBranchList = octaneBranchMap.get(ciBranch.getName());
if (octaneBranchList == null) {
// not exist in octane, check if to add
long diff = System.currentTimeMillis() - ciBranch.getLastCommitTime();
long diffDays = TimeUnit.MILLISECONDS.toDays(diff);
if (diffDays < fp.getActiveBranchDays()) {
result.getCreated().add(ciBranch);
}
} else {
// check for update
octaneBranchList.forEach(octaneBranch -> {
if (!ciBranch.getLastCommitSHA().equals(octaneBranch.getField(EntityConstants.ScmRepository.LAST_COMMIT_SHA_FIELD)) || !ciBranch.getIsMerged().equals(octaneBranch.getField(EntityConstants.ScmRepository.IS_MERGED_FIELD))) {
ciBranch.setOctaneId(octaneBranch.getId());
result.getUpdated().add(ciBranch);
}
});
}
});
// SEND TO OCTANE
if (!result.getDeleted().isEmpty()) {
List<Entity> toDelete = result.getDeleted().stream().map(b -> buildOctaneBranchForUpdateAsDeleted(b)).collect(Collectors.toList());
entitiesService.updateEntities(workspaceId, EntityConstants.ScmRepository.COLLECTION_NAME, toDelete);
logConsumer.accept("Deleted branches : " + toDelete.size());
}
if (!result.getUpdated().isEmpty()) {
List<Entity> toUpdate = result.getUpdated().stream().map(b -> buildOctaneBranchForUpdate(b, idPicker)).collect(Collectors.toList());
entitiesService.updateEntities(workspaceId, EntityConstants.ScmRepository.COLLECTION_NAME, toUpdate);
logConsumer.accept("Updated branches : " + toUpdate.size());
}
if (!result.getCreated().isEmpty()) {
List<Entity> toCreate = result.getCreated().stream().map(b -> buildOctaneBranchForCreate(finalRootId, b, idPicker)).collect(Collectors.toList());
try {
entitiesService.postEntities(workspaceId, EntityConstants.ScmRepository.COLLECTION_NAME, toCreate);
logConsumer.accept("New branches : " + toCreate.size());
} catch (OctaneBulkException bulkException) {
logConsumer.accept(String.format("New branches created: %s, failed to create %s branches", (toCreate.size() - bulkException.getData().getErrors().size()), bulkException.getData().getErrors().size()));
// handling previously deleted branches. (new branches were created with the name that already exist in Octane but set as deleted)
boolean hasDuplicatedException = bulkException.getData().getErrors().stream().filter(ex -> EntityConstants.Errors.DUPLICATE_ERROR_CODE.equals(ex.getErrorCode())).findAny().isPresent();
Map<String, Entity> deletedBranchesInOctane = !hasDuplicatedException ? Collections.emptyMap() : getRepositoryBranches(rootId, workspaceId, true).stream().collect(Collectors.toMap(e -> e.getStringValue(EntityConstants.ScmRepository.NAME_FIELD), Function.identity()));
// try to update duplicates
List<Entity> deletedBranchesToUpdate = new ArrayList<>();
bulkException.getData().getErrors().forEach(ex -> {
// if post was done with only one entity - index will be null
int index = ex.getIndex() == null ? 0 : ex.getIndex();
Branch branch = result.getCreated().get(index);
if (EntityConstants.Errors.DUPLICATE_ERROR_CODE.equals(ex.getErrorCode())) {
Entity octaneEntity = deletedBranchesInOctane.get(branch.getName());
if (octaneEntity != null) {
branch.setOctaneId(octaneEntity.getId());
deletedBranchesToUpdate.add(buildOctaneBranchForUpdate(branch, idPicker).setField(EntityConstants.ScmRepository.IS_DELETED_FIELD, false));
} else {
logConsumer.accept("Failed to create/update branch : " + branch.getName());
}
} else {
logConsumer.accept(String.format("Failed to create branch %s : %s ", branch.getName(), ex.getDescriptionTranslated()));
}
});
if (!deletedBranchesToUpdate.isEmpty()) {
entitiesService.updateEntities(workspaceId, EntityConstants.ScmRepository.COLLECTION_NAME, deletedBranchesToUpdate);
logConsumer.accept("New branches that appear as deleted in ALM OCtane : " + deletedBranchesToUpdate.size());
}
}
}
if (result.getDeleted().isEmpty() && result.getUpdated().isEmpty() && result.getCreated().isEmpty()) {
logConsumer.accept("No changes are found.");
}
return result;
}
Aggregations