@Override public boolean matches(Issue issue) { DefaultIssue defaultIssue = (DefaultIssue) issue; Optional<String> lastPreviousStatus = defaultIssue.changes().stream() // exclude current change (if any) .filter(change -> change != defaultIssue.currentChange()) .filter(change -> change.creationDate() != null) .sorted(Comparator.comparing(FieldDiffs::creationDate).reversed()) .map(change -> change.get("status")) .filter(Objects::nonNull) .findFirst() .map(t -> (String) t.oldValue()); return lastPreviousStatus.filter(this.expectedPreviousStatus::equals).isPresent(); } }
@Override public void execute(Context context) { DefaultIssue defaultIssue = (DefaultIssue) context.issue(); String previousResolution = defaultIssue.changes().stream() // exclude current change (if any) .filter(change -> change != defaultIssue.currentChange()) .filter(change -> change.creationDate() != null) .sorted(Comparator.comparing(FieldDiffs::creationDate).reversed()) .map(this::parse) .filter(Objects::nonNull) .filter(StatusAndResolutionDiffs::hasResolution) .findFirst() .map(t -> t.newStatusClosed ? t.oldResolution : t.newResolution) .orElse(null); context.setResolution(previousResolution); }
private static void copyChangesOfIssueFromOtherBranch(DefaultIssue raw, DefaultIssue base) { base.defaultIssueComments().forEach(c -> raw.addComment(copyComment(raw.key(), c))); base.changes().forEach(c -> copyFieldDiffOfIssueFromOtherBranch(raw.key(), c).ifPresent(raw::addChange)); }
@Test public void adding_null_change_has_no_effect() { DefaultIssue issue = new DefaultIssue(); issue.addChange(null); assertThat(issue.changes()).hasSize(0); } }
@Test public void all_changes_contain_current_change() { IssueChangeContext issueChangeContext = mock(IssueChangeContext.class); DefaultIssue issue = new DefaultIssue().setKey("AAA").setFieldChange(issueChangeContext, "actionPlan", "1.0", "1.1"); assertThat(issue.changes()).hasSize(1); }
@Test public void setIssueMoved_has_no_effect_if_component_uuid_is_not_changed() { String componentUuid = "a"; issue.setComponentUuid(componentUuid); underTest.setIssueMoved(issue, componentUuid, context); assertThat(issue.changes()).isEmpty(); assertThat(issue.componentUuid()).isEqualTo(componentUuid); assertThat(issue.isChanged()).isFalse(); assertThat(issue.updateDate()).isNull(); assertThat(issue.mustSendNotifications()).isFalse(); }
@Test public void setIssueMoved_changes_componentUuid_adds_a_change() { String oldComponentUuid = "a"; String newComponentUuid = "b"; issue.setComponentUuid(oldComponentUuid); underTest.setIssueMoved(issue, newComponentUuid, context); assertThat(issue.changes()).hasSize(1); FieldDiffs fieldDiffs = issue.changes().get(0); assertThat(fieldDiffs.creationDate()).isEqualTo(context.date()); assertThat(fieldDiffs.diffs()).hasSize(1); Map.Entry<String, FieldDiffs.Diff> entry = fieldDiffs.diffs().entrySet().iterator().next(); assertThat(entry.getKey()).isEqualTo("file"); assertThat(entry.getValue().oldValue()).isEqualTo(oldComponentUuid); assertThat(entry.getValue().newValue()).isEqualTo(newComponentUuid); assertThat(issue.componentUuid()).isEqualTo(newComponentUuid); assertThat(issue.isChanged()).isTrue(); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(context.date(), Calendar.SECOND)); } }
.extracting(DefaultIssueComment::issueKey, DefaultIssueComment::createdAt, DefaultIssueComment::userUuid, DefaultIssueComment::markdownText) .containsOnly(tuple("raw", commentDate, "user_uuid", "A comment")); assertThat(raw.changes()).hasSize(2); assertThat(raw.changes().get(0).creationDate()).isEqualTo(diffDate); assertThat(raw.changes().get(0).userUuid()).isEqualTo("user_uuid"); assertThat(raw.changes().get(0).issueKey()).isEqualTo("raw"); assertThat(raw.changes().get(0).diffs()).containsOnlyKeys("severity"); assertThat(raw.changes().get(1).userUuid()).isEqualTo("default_user_uuid"); assertThat(raw.changes().get(1).diffs()).containsOnlyKeys(IssueFieldsSetter.FROM_SHORT_BRANCH); assertThat(raw.changes().get(1).get(IssueFieldsSetter.FROM_SHORT_BRANCH).oldValue()).isEqualTo("feature/foo"); assertThat(raw.changes().get(1).get(IssueFieldsSetter.FROM_SHORT_BRANCH).newValue()).isEqualTo("master");
@Test public void lazy_load_changes() { UserDto user1 = db.users().insertUser(); IssueDto issue1 = db.issues() .insertIssue(IssueTesting.newIssue(rule, branch1Dto, fileOnBranch1Dto).setKee("issue1").setStatus(Issue.STATUS_REOPENED).setLine(1).setChecksum("checksum")); db.issues().insertComment(issue1, user1, "A comment 1"); db.issues().insertFieldDiffs(issue1, FieldDiffs.parse("severity=BLOCKER|INFO,assignee=toto|titi").setCreationDate(new Date())); UserDto user2 = db.users().insertUser(); IssueDto issue2 = db.issues() .insertIssue(IssueTesting.newIssue(rule, branch2Dto, fileOnBranch2Dto).setKee("issue2").setStatus(Issue.STATUS_CONFIRMED).setLine(1).setChecksum("checksum")); db.issues().insertComment(issue2, user2, "A comment 2"); db.issues().insertFieldDiffs(issue2, FieldDiffs.parse("severity=BLOCKER|MINOR,assignee=foo|bar").setCreationDate(new Date())); DefaultIssue newIssue = createIssue("newIssue", rule.getKey(), Issue.STATUS_OPEN, null, new Date()); copier.tryMerge(FILE_1, Collections.singleton(newIssue)); ArgumentCaptor<DefaultIssue> issueToMerge = ArgumentCaptor.forClass(DefaultIssue.class); verify(issueLifecycle).mergeConfirmedOrResolvedFromShortLivingBranch(eq(newIssue), issueToMerge.capture(), eq("myBranch2")); assertThat(issueToMerge.getValue().key()).isEqualTo("issue2"); assertThat(issueToMerge.getValue().defaultIssueComments()).isNotEmpty(); assertThat(issueToMerge.getValue().changes()).isNotEmpty(); }
public void insertChanges(IssueChangeMapper mapper, DefaultIssue issue) { for (DefaultIssueComment comment : issue.defaultIssueComments()) { if (comment.isNew()) { IssueChangeDto changeDto = IssueChangeDto.of(comment); mapper.insert(changeDto); } } FieldDiffs diffs = issue.currentChange(); if (issue.isCopied()) { for (FieldDiffs d : issue.changes()) { IssueChangeDto changeDto = IssueChangeDto.of(issue.key(), d); mapper.insert(changeDto); } } else if (!issue.isNew() && diffs != null) { IssueChangeDto changeDto = IssueChangeDto.of(issue.key(), diffs); mapper.insert(changeDto); } } }
assertThat(raw.isOnDisabledRule()).isTrue(); assertThat(raw.selectedAt()).isEqualTo(1000L); assertThat(raw.changes().get(0).get(IssueFieldsSetter.FROM_LONG_BRANCH).oldValue()).isEqualTo("master"); assertThat(raw.changes().get(0).get(IssueFieldsSetter.FROM_LONG_BRANCH).newValue()).isEqualTo("release-2.x");
assertThat(raw.selectedAt()).isEqualTo(1000L); assertThat(raw.isChanged()).isFalse(); assertThat(raw.changes()).hasSize(2); assertThat(raw.changes().get(0).diffs()) .containsOnly(entry("foo", new FieldDiffs.Diff("bar", "donut"))); assertThat(raw.changes().get(1).diffs()) .containsOnly(entry("file", new FieldDiffs.Diff("A", "B")));
@Test public void loadLatestDiffChangesForReopeningOfClosedIssues_adds_2_diff_changes_if_most_recent_status_and_resolution_are_not_the_same_diff() { ComponentDto project = dbTester.components().insertPublicProject(); ComponentDto file = dbTester.components().insertComponent(ComponentTesting.newFileDto(project)); RuleDefinitionDto rule = dbTester.rules().insert(); IssueDto issue = dbTester.issues().insert(rule, project, file); dbTester.issues().insertChange(issue, t -> t.setChangeData(randomDiffWith("status", "valStatus1")).setIssueChangeCreationDate(5)); dbTester.issues().insertChange(issue, t -> t.setChangeData(randomDiffWith("status", "valStatus2", "resolution", "valRes2")).setIssueChangeCreationDate(19)); dbTester.issues().insertChange(issue, t -> t.setChangeData(randomDiffWith("status", "valStatus3")).setIssueChangeCreationDate(20)); dbTester.issues().insertChange(issue, t -> t.setChangeData(randomDiffWith("resolution", "valRes4")).setIssueChangeCreationDate(13)); ComponentIssuesLoader underTest = new ComponentIssuesLoader(dbClient, null /* not used in method */, null /* not used in method */, newConfiguration("0"), null /* not used by method */); DefaultIssue defaultIssue = new DefaultIssue().setKey(issue.getKey()); underTest.loadLatestDiffChangesForReopeningOfClosedIssues(ImmutableList.of(defaultIssue)); assertThat(defaultIssue.changes()) .hasSize(2); assertThat(defaultIssue.changes()) .extracting(t -> t.get("status")) .filteredOn(t -> hasValue(t, "valStatus3")) .hasSize(1); assertThat(defaultIssue.changes()) .extracting(t -> t.get("resolution")) .filteredOn(t -> hasValue(t, "valRes2")) .hasSize(1); }
@Test @UseDataProvider("statusOrResolutionFieldName") public void loadLatestDiffChangesForReopeningOfClosedIssues_add_diff_change_with_most_recent_status_or_resolution(String statusOrResolutionFieldName) { ComponentDto project = dbTester.components().insertPublicProject(); ComponentDto file = dbTester.components().insertComponent(ComponentTesting.newFileDto(project)); RuleDefinitionDto rule = dbTester.rules().insert(); IssueDto issue = dbTester.issues().insert(rule, project, file); dbTester.issues().insertChange(issue, t -> t.setChangeData(randomDiffWith(statusOrResolutionFieldName, "val1")).setIssueChangeCreationDate(5)); dbTester.issues().insertChange(issue, t -> t.setChangeData(randomDiffWith(statusOrResolutionFieldName, "val2")).setIssueChangeCreationDate(20)); dbTester.issues().insertChange(issue, t -> t.setChangeData(randomDiffWith(statusOrResolutionFieldName, "val3")).setIssueChangeCreationDate(13)); ComponentIssuesLoader underTest = new ComponentIssuesLoader(dbClient, null /* not used in method */, null /* not used in method */, newConfiguration("0"), null /* not used by method */); DefaultIssue defaultIssue = new DefaultIssue().setKey(issue.getKey()); underTest.loadLatestDiffChangesForReopeningOfClosedIssues(ImmutableList.of(defaultIssue)); assertThat(defaultIssue.changes()) .hasSize(1); assertThat(defaultIssue.changes()) .extracting(t -> t.get(statusOrResolutionFieldName)) .filteredOn(t -> hasValue(t, "val2")) .hasSize(1); }
@Test public void loadLatestDiffChangesForReopeningOfClosedIssues_add_single_diff_change_when_most_recent_status_and_resolution_is_the_same_diff() { ComponentDto project = dbTester.components().insertPublicProject(); ComponentDto file = dbTester.components().insertComponent(ComponentTesting.newFileDto(project)); RuleDefinitionDto rule = dbTester.rules().insert(); IssueDto issue = dbTester.issues().insert(rule, project, file); dbTester.issues().insertChange(issue, t -> t.setChangeData(randomDiffWith("status", "valStatus1")).setIssueChangeCreationDate(5)); dbTester.issues().insertChange(issue, t -> t.setChangeData(randomDiffWith("status", "valStatus2")).setIssueChangeCreationDate(19)); dbTester.issues().insertChange(issue, t -> t.setChangeData(randomDiffWith("status", "valStatus3", "resolution", "valRes3")).setIssueChangeCreationDate(20)); dbTester.issues().insertChange(issue, t -> t.setChangeData(randomDiffWith("resolution", "valRes4")).setIssueChangeCreationDate(13)); ComponentIssuesLoader underTest = new ComponentIssuesLoader(dbClient, null /* not used in method */, null /* not used in method */, newConfiguration("0"), null /* not used by method */); DefaultIssue defaultIssue = new DefaultIssue().setKey(issue.getKey()); underTest.loadLatestDiffChangesForReopeningOfClosedIssues(ImmutableList.of(defaultIssue)); assertThat(defaultIssue.changes()) .hasSize(1); assertThat(defaultIssue.changes()) .extracting(t -> t.get("status")) .filteredOn(t -> hasValue(t, "valStatus3")) .hasSize(1); assertThat(defaultIssue.changes()) .extracting(t -> t.get("resolution")) .filteredOn(t -> hasValue(t, "valRes3")) .hasSize(1); }
base.changes().forEach(raw::addChange); if (raw.isFromHotspot() != base.isFromHotspot()) {
private static void copyChanges(DefaultIssue raw, DefaultIssue base) { base.defaultIssueComments().forEach(c -> raw.addComment(copy(raw.key(), c))); base.changes().forEach(c -> copy(raw.key(), c).ifPresent(raw::addChange)); }
public static void insertChanges(IssueChangeMapper mapper, DefaultIssue issue) { for (DefaultIssueComment comment : issue.defaultIssueComments()) { if (comment.isNew()) { IssueChangeDto changeDto = IssueChangeDto.of(comment); mapper.insert(changeDto); } } FieldDiffs diffs = issue.currentChange(); if (issue.isCopied()) { for (FieldDiffs d : issue.changes()) { IssueChangeDto changeDto = IssueChangeDto.of(issue.key(), d); mapper.insert(changeDto); } } else if (!issue.isNew() && diffs != null) { IssueChangeDto changeDto = IssueChangeDto.of(issue.key(), diffs); mapper.insert(changeDto); } }