com.release_notes_for_bitbucket.release_helper.ReleaseHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bitbucket-release-manager Show documentation
Show all versions of bitbucket-release-manager Show documentation
This tool collects all issues that were fixed in some/the latest release and assigns them a corresponding milestone. In effect this milestone is basis for your release notes. This is the command line tool - a maven plugin is available too.
The newest version!
package com.release_notes_for_bitbucket.release_helper;
import com.release_notes_for_bitbucket.fetcher.ChangesetFetcher;
import com.release_notes_for_bitbucket.fetcher.IssueFetcher;
import com.release_notes_for_bitbucket.model.Changeset;
import com.release_notes_for_bitbucket.model.Issue;
import com.release_notes_for_bitbucket.model.Milestone;
import com.release_notes_for_bitbucket.version_tree.Commit;
import com.release_notes_for_bitbucket.version_tree.CommitTree;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ReleaseHelper {
private final CommitTree commitTree;
private final ChangesetFetcher changesetFetcher;
private final IssueFetcher issueFetcher;
public ReleaseHelper(String user, String password, String repoOwner, String repoName) {
issueFetcher = new IssueFetcher(user, password, repoOwner, repoName);
changesetFetcher = new ChangesetFetcher(user, password, repoOwner, repoName);
commitTree = new CommitTree(changesetFetcher);
}
/**
* For testing only!
* @param commitTree
* @param changesetFetcher
* @param issueFetcher
*/
ReleaseHelper(CommitTree commitTree, ChangesetFetcher changesetFetcher, IssueFetcher issueFetcher) {
this.commitTree = commitTree;
this.changesetFetcher = changesetFetcher;
this.issueFetcher = issueFetcher;
}
/**
* Fetches changeset for release
*
* @param version get most current release if null
* @return
* @throws IOException
*/
public Changeset getReleaseCommit(String version) throws IOException {
for (int i = 0; i < changesetFetcher.getTotal(); i++) {
if (i >= changesetFetcher.getAllFetchedChangesets().size()) {
changesetFetcher.fetchMore(50);
}
Commit commit = new Commit(changesetFetcher.getAllFetchedChangesets().get(i));
if (commit.getRelease() != null) {
if (version == null) {
return commit.getChangeset();
} else {
if (version.equals(commit.getRelease())) {
return commit.getChangeset();
}
}
}
}
return null;
}
/**
* Commits that are (also) part of a newer release are returned as well!
*
* @param releaseCommit
* @return all Commits that are part of the given release, but not part of any other release (does not include given release)
*/
public Set getCommitsNotInSomeOtherRelease(Changeset releaseCommit) {
Commit release = commitTree.getForChangeset(releaseCommit);
Deque candidates = new ArrayDeque<>();
candidates.addAll(commitTree.getPredecessors(release));
Set result = new HashSet<>();
Set checkedCandidates = new HashSet<>();
while (!candidates.isEmpty()) {
Commit candidate = candidates.poll();
boolean candidateOk = true;
if (!release.equals(candidate) && candidate.getRelease() == null) {
//check all successors (oder than 'release') for beeing release:
for (Commit successor : commitTree.getRecursiveSuccessors(candidate)) {
if (successor.getDate().after(release.getDate())) {
continue;
}
if (!release.equals(successor) && successor.getRelease() != null) {
candidateOk = false;
}
}
if (candidateOk) {
result.add(candidate);
for (Commit predecessor : candidate.getPredecessors()) {
if (!candidates.contains(predecessor) && !checkedCandidates.contains(predecessor)) {
candidates.addLast(predecessor);
}
}
}
checkedCandidates.add(candidate);
}
}
return result;
}
public Set getResolvedIssues(Set commits) {
Set result = new HashSet<>();
for (Commit commit : commits) {
//See https://confluence.atlassian.com/display/BITBUCKET/Resolve+issues+automatically+when+users+push+code
Pattern fixedIssuePattern = Pattern.compile("(?:close|closes|closed|closing|fix|fixed|fixes|fixing|resolve|resolves|resolved|resolving) (?:bug |issue |ticket )?#(\\d+)", Pattern.CASE_INSENSITIVE);
Matcher matcher = fixedIssuePattern.matcher(commit.getChangeset().getMessage());
System.out.println("Checking: " + commit.getId() + " - " + commit.getChangeset().getMessage().trim());
while (matcher.find()) {
result.add(Integer.parseInt(matcher.group(1)));
}
}
return result;
}
public Set getFixedIssues(Set markedAsResolvedIssues) throws IOException {
Set fixedIssues = new HashSet<>();
for (Integer issueId : markedAsResolvedIssues) {
Issue issue = issueFetcher.fetchIssue(issueId);
if ("resolved".equals(issue.getStatus())) {
fixedIssues.add(issue);
}
}
return fixedIssues;
}
public void setMilestoneForIssues(Milestone milestone, Set fixedIssues) throws IOException {
// for all theses issues, set milestone (if already some other milestone is set -> warning (overwrite via conf.?)
for (Issue issue : fixedIssues) {
if(milestone.getName().equals(issue.getMetadata().getMilestone())) {
continue; // don't reset to exising version
}
if (issue.getMetadata().getMilestone() != null) {
System.out.println("Warning: overwriting milestone (" + issue.getMetadata().getMilestone() + ") for issue: #" + issue.getLocalId());
}
issueFetcher.setMilestone(issue.getLocalId(), milestone.getName());
}
}
}