use of net.nemerosa.ontrack.extension.issues.model.Issue in project ontrack by nemerosa.
the class GitLabIssueServiceExtensionTest method no_link_for_all_issues.
@Test
public void no_link_for_all_issues() {
Issue issue = mock(Issue.class);
String link = extension.getLinkForAllIssues(configuration, Collections.singletonList(issue));
assertNull(link);
}
use of net.nemerosa.ontrack.extension.issues.model.Issue in project ontrack by nemerosa.
the class JIRAServiceExtension method followLinks.
/**
* Given an issue seed, and a list of link names, follows the given links recursively and
* puts the associated issues into the {@code collectedIssues} map.
*
* @param configuration JIRA configuration to use to load the issues
* @param seed Issue to start from.
* @param linkNames Links to follow
* @param collectedIssues Collected issues, indexed by their key
*/
public void followLinks(JIRAConfiguration configuration, JIRAIssue seed, Set<String> linkNames, Map<String, JIRAIssue> collectedIssues) {
try (Transaction tx = transactionService.start()) {
JIRASession session = getJIRASession(tx, configuration);
// Gets the client from the current session
JIRAClient client = session.getClient();
// Puts the seed into the list
collectedIssues.put(seed.getKey(), seed);
// Gets the linked issue keys
seed.getLinks().stream().filter(linkedIssue -> linkNames.contains(linkedIssue.getLinkName())).filter(linkedIssue -> !collectedIssues.containsKey(linkedIssue.getKey())).map(linkedIssue -> client.getIssue(linkedIssue.getKey(), configuration)).forEach(linkedIssue -> followLinks(configuration, linkedIssue, linkNames, collectedIssues));
}
}
use of net.nemerosa.ontrack.extension.issues.model.Issue in project ontrack by nemerosa.
the class SVNInfoServiceImpl method getIssueInfo.
@Override
public OntrackSVNIssueInfo getIssueInfo(String configurationName, String issueKey) {
// Repository
SVNRepository repository = svnService.getRepository(configurationName);
// Issue service
ConfiguredIssueService configuredIssueService = repository.getConfiguredIssueService();
if (configuredIssueService == null) {
// No issue service configured
return OntrackSVNIssueInfo.empty(repository.getConfiguration());
}
// Gets the details about the issue
Issue issue = configuredIssueService.getIssue(issueKey);
// For each configured branch
Map<String, BranchRevision> branchRevisions = new HashMap<>();
svnService.forEachConfiguredBranch(config -> Objects.equals(configurationName, config.getConfiguration().getName()), (branch, branchConfig) -> {
String branchPath = branchConfig.getCuredBranchPath();
// List of linked issues
Collection<String> linkedIssues = configuredIssueService.getLinkedIssues(branch.getProject(), issue).stream().map(Issue::getKey).collect(Collectors.toList());
// Gets the last raw revision on this branch
issueRevisionDao.findLastRevisionByIssuesAndBranch(repository.getId(), linkedIssues, branchPath).ifPresent(revision -> branchRevisions.put(branchPath, new BranchRevision(branchPath, revision, false)));
});
// Until all revisions are complete in respect of their merges...
while (!BranchRevision.areComplete(branchRevisions.values())) {
// Gets the incomplete revisions
Collection<BranchRevision> incompleteRevisions = branchRevisions.values().stream().filter(br -> !br.isComplete()).collect(Collectors.toList());
// For each of them, gets the list of revisions it was merged to
incompleteRevisions.forEach(br -> {
List<Long> merges = revisionDao.getMergesForRevision(repository.getId(), br.getRevision());
// Marks the current revision as complete
branchRevisions.put(br.getPath(), br.complete());
// Gets the revision info for each merged revision
List<TRevision> revisions = merges.stream().map(r -> revisionDao.get(repository.getId(), r)).collect(Collectors.toList());
// For each revision path, compares with current stored revision
revisions.forEach(t -> {
String branch = t.getBranch();
// Existing branch revision?
BranchRevision existingBranchRevision = branchRevisions.get(branch);
if (existingBranchRevision == null || t.getRevision() > existingBranchRevision.getRevision()) {
branchRevisions.put(branch, new BranchRevision(branch, t.getRevision(), true));
}
});
});
}
// We now have the last revision for this issue on each branch...
List<OntrackSVNIssueRevisionInfo> issueRevisionInfos = new ArrayList<>();
branchRevisions.values().forEach(br -> {
// Loads the revision info
SVNRevisionInfo basicInfo = svnService.getRevisionInfo(repository, br.getRevision());
SVNChangeLogRevision changeLogRevision = svnService.createChangeLogRevision(repository, basicInfo);
// Info to collect
OntrackSVNIssueRevisionInfo issueRevisionInfo = OntrackSVNIssueRevisionInfo.of(changeLogRevision);
// Gets the branch from the branch path
AtomicReference<Branch> rBranch = new AtomicReference<>();
svnService.forEachConfiguredBranch(config -> Objects.equals(configurationName, config.getConfiguration().getName()), (candidate, branchConfig) -> {
String branchPath = branchConfig.getCuredBranchPath();
if (Objects.equals(br.getPath(), branchPath)) {
rBranch.set(candidate);
}
});
Branch branch = rBranch.get();
if (branch != null) {
// Collects branch info
SCMIssueCommitBranchInfo branchInfo = SCMIssueCommitBranchInfo.of(branch);
// Gets the first copy event on this path after this revision
SVNLocation firstCopy = svnService.getFirstCopyAfter(repository, basicInfo.toLocation());
// Identifies a possible build given the path/revision and the first copy
Optional<Build> buildAfterCommit = lookupBuild(basicInfo.toLocation(), firstCopy, branch);
branchInfo = scmService.getBranchInfo(buildAfterCommit, branchInfo);
// OK
issueRevisionInfo.add(branchInfo);
}
// OK
issueRevisionInfos.add(issueRevisionInfo);
});
// Gets the list of revisions & their basic info (order from latest to oldest)
List<SVNChangeLogRevision> revisions = svnService.getRevisionsForIssueKey(repository, issueKey).stream().map(revision -> svnService.createChangeLogRevision(repository, svnService.getRevisionInfo(repository, revision))).collect(Collectors.toList());
// OK
return new OntrackSVNIssueInfo(repository.getConfiguration(), repository.getConfiguredIssueService().getIssueServiceConfigurationRepresentation(), issue, issueRevisionInfos, revisions);
}
use of net.nemerosa.ontrack.extension.issues.model.Issue in project ontrack by nemerosa.
the class SVNController method changeLog.
/**
* Change log export
*/
@RequestMapping(value = "changelog/export", method = RequestMethod.GET)
public ResponseEntity<String> changeLog(IssueChangeLogExportRequest request) {
// Gets the change log
SVNChangeLog changeLog = changeLogService.changeLog(request);
// Gets the issue service
ConfiguredIssueService configuredIssueService = changeLog.getRepository().getConfiguredIssueService();
if (configuredIssueService == null) {
return new ResponseEntity<>("The branch is not configured for issues", HttpStatus.NO_CONTENT);
}
// Gets the issue change log
SVNChangeLogIssues changeLogIssues = changeLogService.getChangeLogIssues(changeLog);
// List of issues
List<Issue> issues = changeLogIssues.getList().stream().map(SCMChangeLogIssue::getIssue).collect(Collectors.toList());
// Exports the change log using the given format
ExportedIssues exportedChangeLogIssues = configuredIssueService.getIssueServiceExtension().exportIssues(configuredIssueService.getIssueServiceConfiguration(), issues, request);
// Content type
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("Content-Type", exportedChangeLogIssues.getFormat());
// Body and headers
return new ResponseEntity<>(exportedChangeLogIssues.getContent(), responseHeaders, HttpStatus.OK);
}
use of net.nemerosa.ontrack.extension.issues.model.Issue in project ontrack by nemerosa.
the class IssueServiceUtils method groupIssues.
public static Map<String, List<Issue>> groupIssues(IssueServiceConfiguration issueServiceConfiguration, List<? extends Issue> issues, IssueChangeLogExportRequest request, BiFunction<IssueServiceConfiguration, Issue, Set<String>> issueTypesFn) {
// Excluded issues
Set<String> excludedTypes = request.getExcludedTypes();
// Gets the grouping specification
Map<String, Set<String>> groupingSpecification = request.getGroupingSpecification();
// Map of issues, ordered by group
Map<String, List<Issue>> groupedIssues = new LinkedHashMap<>();
// Pre-enter the empty group list, in order to guarantee the ordering
for (String groupName : groupingSpecification.keySet()) {
groupedIssues.put(groupName, new ArrayList<>());
}
// For all issues
for (Issue issue : issues) {
// Issue type(s)
Set<String> issueTypes = issueTypesFn.apply(issueServiceConfiguration, issue);
// Excluded issue?
if (Collections.disjoint(excludedTypes, issueTypes)) {
// Issue is not excluded
// Gets the groups this issue belongs to
Set<String> issueGroups = getIssueGroups(issueTypes, groupingSpecification);
// Target group
String targetGroup;
if (issueGroups.size() > 1) {
throw new IssueExportMoreThanOneGroupException(issue.getKey(), issueGroups);
} else if (issueGroups.isEmpty()) {
if (groupingSpecification.isEmpty()) {
targetGroup = IssueExportService.NO_GROUP;
} else {
targetGroup = request.getAltGroup();
}
} else {
targetGroup = Iterables.get(issueGroups, 0);
}
// Grouping
List<Issue> issueList = groupedIssues.get(targetGroup);
if (issueList == null) {
issueList = new ArrayList<>();
groupedIssues.put(targetGroup, issueList);
}
issueList.add(issue);
}
}
// Prunes empty groups
Iterator<Map.Entry<String, List<Issue>>> iterator = groupedIssues.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, List<Issue>> entry = iterator.next();
if (entry.getValue().isEmpty()) {
iterator.remove();
}
}
// OK
return groupedIssues;
}
Aggregations