Skip to content

Commit

Permalink
Create gaps in release train and prevent 422 error
Browse files Browse the repository at this point in the history
Closes gh-32
  • Loading branch information
sjohnr committed Apr 16, 2024
1 parent d730661 commit bb39599
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 80 deletions.
28 changes: 20 additions & 8 deletions core/src/main/java/io/spring/release/SpringReleases.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.github.api.GitHubApi;
import com.github.api.Milestone;
Expand Down Expand Up @@ -323,13 +324,19 @@ public void scheduleReleaseIfNotExists(String owner, String repo, String version

var baseVersion = "%s.%s.%s".formatted(major, minor, patch);
var repository = new Repository(owner, repo);
if (this.gitHubApi.getMilestone(repository, baseVersion) != null) {
// @formatter:off
var existingMilestones = this.gitHubApi.getMilestones(repository).stream()
.map(Milestone::title)
.collect(Collectors.toSet());
// @formatter:on
if (existingMilestones.contains(baseVersion)) {
return;
}

var startDate = LocalDate.now();
// @formatter:off
var releaseTrainSpec = SpringReleaseTrainSpec.builder()
.nextTrain()
.nextTrain(startDate)
.version(baseVersion)
.weekOfMonth(weekOfMonth)
.dayOfWeek(dayOfWeek)
Expand All @@ -343,22 +350,27 @@ public void scheduleReleaseIfNotExists(String owner, String repo, String version
// train which can be manually updated to match the desired schedule.
if (baseVersion.endsWith(".0")) {
// Create M1, M2, M3, RC1 and GA milestones for release train
releaseTrain.getTrainDates().forEach((milestoneTitle, dueOn) -> {
releaseTrain.getTrainDates().forEach((milestoneTitle, releaseDate) -> {
// Skip existing versions and create only the gaps
if (existingMilestones.contains(milestoneTitle)) {
return;
}

// Note: GitHub seems to store full date/time as UTC then displays
// as a date (no time) in your timezone, which means the date will
// not always be the same date as we intend.
// For example, midnight UTC is actually 8pm CDT (the previous day).
// We use 12pm/noon UTC to be as far from anybody's midnight as we can.
var milestone = new Milestone(milestoneTitle, null,
dueOn.atTime(LocalTime.NOON).toInstant(ZoneOffset.UTC));
var dueOn = releaseDate.atTime(LocalTime.NOON).toInstant(ZoneOffset.UTC);
var milestone = new Milestone(milestoneTitle, null, dueOn);
this.gitHubApi.createMilestone(repository, milestone);
});
}
else {
// Create GA milestone for patch release on the next even month
var startDate = LocalDate.now();
var dueOn = releaseTrain.getNextReleaseDate(startDate);
var milestone = new Milestone(baseVersion, null, dueOn.atTime(LocalTime.NOON).toInstant(ZoneOffset.UTC));
var nextReleaseDate = releaseTrain.getNextReleaseDate(startDate);
var dueOn = nextReleaseDate.atTime(LocalTime.NOON).toInstant(ZoneOffset.UTC);
var milestone = new Milestone(baseVersion, null, dueOn);
this.gitHubApi.createMilestone(repository, milestone);
}
}
Expand Down
126 changes: 54 additions & 72 deletions core/src/test/java/io/spring/release/SpringReleasesTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -463,90 +463,89 @@ public void scheduleReleaseIfNotExistsWhenMinorVersionThenReleaseTrainCreated()
var version = "6.2.0";
this.springReleases.scheduleReleaseIfNotExists(OWNER, REPO, version, WEEK_OF_MONTH, DAY_OF_WEEK);

var repositoryCaptor = forClass(Repository.class);
var repository = new Repository(OWNER, REPO);
var milestoneCaptor = forClass(Milestone.class);
verify(this.gitHubApi).getMilestone(repositoryCaptor.capture(), eq(version));
verify(this.gitHubApi, times(5)).createMilestone(repositoryCaptor.capture(), milestoneCaptor.capture());
verify(this.gitHubApi).getMilestones(repository);
verify(this.gitHubApi, times(5)).createMilestone(eq(repository), milestoneCaptor.capture());
verifyNoMoreInteractions(this.gitHubApi);

var repository = repositoryCaptor.getValue();
assertThat(repository.owner()).isEqualTo(OWNER);
assertThat(repository.name()).isEqualTo(REPO);

var milestones = milestoneCaptor.getAllValues();
assertThat(milestones.stream().map(Milestone::title).toList()).containsExactly("6.2.0-M1", "6.2.0-M2",
"6.2.0-M3", "6.2.0-RC1", "6.2.0");
var milestonesCreated = milestoneCaptor.getAllValues().stream().map(Milestone::title).toList();
assertThat(milestonesCreated).containsExactly("6.2.0-M1", "6.2.0-M2", "6.2.0-M3", "6.2.0-RC1", "6.2.0");
}

@Test
public void scheduleReleaseIfNotExistsWhenMinorVersionIsSnapshotThenReleaseTrainCreated() {
var version = "6.2.0-SNAPSHOT";
this.springReleases.scheduleReleaseIfNotExists(OWNER, REPO, version, WEEK_OF_MONTH, DAY_OF_WEEK);

var repositoryCaptor = forClass(Repository.class);
var repository = new Repository(OWNER, REPO);
var milestoneCaptor = forClass(Milestone.class);
verify(this.gitHubApi).getMilestone(repositoryCaptor.capture(), eq("6.2.0"));
verify(this.gitHubApi, times(5)).createMilestone(repositoryCaptor.capture(), milestoneCaptor.capture());
verify(this.gitHubApi).getMilestones(repository);
verify(this.gitHubApi, times(5)).createMilestone(eq(repository), milestoneCaptor.capture());
verifyNoMoreInteractions(this.gitHubApi);

var repository = repositoryCaptor.getValue();
assertThat(repository.owner()).isEqualTo(OWNER);
assertThat(repository.name()).isEqualTo(REPO);

var milestones = milestoneCaptor.getAllValues();
assertThat(milestones.stream().map(Milestone::title).toList()).containsExactly("6.2.0-M1", "6.2.0-M2",
"6.2.0-M3", "6.2.0-RC1", "6.2.0");
var milestonesCreated = milestoneCaptor.getAllValues().stream().map(Milestone::title).toList();
assertThat(milestonesCreated).containsExactly("6.2.0-M1", "6.2.0-M2", "6.2.0-M3", "6.2.0-RC1", "6.2.0");
}

@Test
public void scheduleReleaseIfNotExistsWhenMinorVersionExistsThenNotCreated() {
var version = "6.2.0";
var milestone = new Milestone(version, 1L, null);
when(this.gitHubApi.getMilestone(any(Repository.class), anyString())).thenReturn(milestone);
var repository = new Repository(OWNER, REPO);
when(this.gitHubApi.getMilestones(repository)).thenReturn(List.of(milestone));
this.springReleases.scheduleReleaseIfNotExists(OWNER, REPO, version, WEEK_OF_MONTH, DAY_OF_WEEK);

verify(this.gitHubApi).getMilestones(repository);
verifyNoMoreInteractions(this.gitHubApi);
}

@Test
public void scheduleReleaseIfNotExistsWhenMinorVersionAndGaVersionMissingFromReleaseTrainThenCreated() {
var version = "6.2.0";
var repository = new Repository(OWNER, REPO);
// @formatter:off
var existingMilestones = List.of(
new Milestone("6.2.0-M1", null, null),
new Milestone("6.2.0-M2", null, null),
new Milestone("6.2.0-M3", null, null),
new Milestone("6.2.0-RC1", null, null));
// @formatter:on
when(this.gitHubApi.getMilestones(repository)).thenReturn(existingMilestones);
this.springReleases.scheduleReleaseIfNotExists(OWNER, REPO, version, WEEK_OF_MONTH, DAY_OF_WEEK);

var repositoryCaptor = forClass(Repository.class);
verify(this.gitHubApi).getMilestone(repositoryCaptor.capture(), eq(version));
var milestoneCaptor = forClass(Milestone.class);
verify(this.gitHubApi).getMilestones(repository);
verify(this.gitHubApi).createMilestone(eq(repository), milestoneCaptor.capture());
verifyNoMoreInteractions(this.gitHubApi);

var repository = repositoryCaptor.getValue();
assertThat(repository.owner()).isEqualTo(OWNER);
assertThat(repository.name()).isEqualTo(REPO);
var milestone = milestoneCaptor.getValue();
assertThat(milestone.title()).isEqualTo(version);
}

@Test
public void scheduleReleaseIfNotExistsWhenMinorVersionIsSnapshotAndExistsThenNotCreated() {
var version = "6.2.0-SNAPSHOT";
var baseVersion = "6.2.0";
var milestone = new Milestone(baseVersion, 1L, null);
when(this.gitHubApi.getMilestone(any(Repository.class), anyString())).thenReturn(milestone);
var milestone = new Milestone("6.2.0", 1L, null);
var repository = new Repository(OWNER, REPO);
when(this.gitHubApi.getMilestones(repository)).thenReturn(List.of(milestone));
this.springReleases.scheduleReleaseIfNotExists(OWNER, REPO, version, WEEK_OF_MONTH, DAY_OF_WEEK);

var repositoryCaptor = forClass(Repository.class);
verify(this.gitHubApi).getMilestone(repositoryCaptor.capture(), eq(baseVersion));
verify(this.gitHubApi).getMilestones(repository);
verifyNoMoreInteractions(this.gitHubApi);

var repository = repositoryCaptor.getValue();
assertThat(repository.owner()).isEqualTo(OWNER);
assertThat(repository.name()).isEqualTo(REPO);
}

@Test
public void scheduleReleaseIfNotExistsWhenPatchVersionThenPatchReleaseCreated() {
var version = "6.2.1";
this.springReleases.scheduleReleaseIfNotExists(OWNER, REPO, version, WEEK_OF_MONTH, DAY_OF_WEEK);

var repositoryCaptor = forClass(Repository.class);
var repository = new Repository(OWNER, REPO);
var milestoneCaptor = forClass(Milestone.class);
verify(this.gitHubApi).getMilestone(repositoryCaptor.capture(), eq(version));
verify(this.gitHubApi).createMilestone(repositoryCaptor.capture(), milestoneCaptor.capture());
verify(this.gitHubApi).getMilestones(repository);
verify(this.gitHubApi).createMilestone(eq(repository), milestoneCaptor.capture());
verifyNoMoreInteractions(this.gitHubApi);

var repository = repositoryCaptor.getValue();
assertThat(repository.owner()).isEqualTo(OWNER);
assertThat(repository.name()).isEqualTo(REPO);

var milestone = milestoneCaptor.getValue();
assertThat(milestone.title()).isEqualTo("6.2.1");
}
Expand All @@ -556,16 +555,12 @@ public void scheduleReleaseIfNotExistsWhenPatchVersionIsSnapshotThenPatchRelease
var version = "6.2.1-SNAPSHOT";
this.springReleases.scheduleReleaseIfNotExists(OWNER, REPO, version, WEEK_OF_MONTH, DAY_OF_WEEK);

var repositoryCaptor = forClass(Repository.class);
var repository = new Repository(OWNER, REPO);
var milestoneCaptor = forClass(Milestone.class);
verify(this.gitHubApi).getMilestone(repositoryCaptor.capture(), eq("6.2.1"));
verify(this.gitHubApi).createMilestone(repositoryCaptor.capture(), milestoneCaptor.capture());
verify(this.gitHubApi).getMilestones(repository);
verify(this.gitHubApi).createMilestone(eq(repository), milestoneCaptor.capture());
verifyNoMoreInteractions(this.gitHubApi);

var repository = repositoryCaptor.getValue();
assertThat(repository.owner()).isEqualTo(OWNER);
assertThat(repository.name()).isEqualTo(REPO);

var milestone = milestoneCaptor.getValue();
assertThat(milestone.title()).isEqualTo("6.2.1");
}
Expand All @@ -574,34 +569,24 @@ public void scheduleReleaseIfNotExistsWhenPatchVersionIsSnapshotThenPatchRelease
public void scheduleReleaseIfNotExistsWhenPatchVersionExistsThenNotCreated() {
var version = "6.2.1";
var milestone = new Milestone(version, 1L, null);
when(this.gitHubApi.getMilestone(any(Repository.class), anyString())).thenReturn(milestone);

var repository = new Repository(OWNER, REPO);
when(this.gitHubApi.getMilestones(repository)).thenReturn(List.of(milestone));
this.springReleases.scheduleReleaseIfNotExists(OWNER, REPO, version, WEEK_OF_MONTH, DAY_OF_WEEK);

var repositoryCaptor = forClass(Repository.class);
verify(this.gitHubApi).getMilestone(repositoryCaptor.capture(), eq(version));
verify(this.gitHubApi).getMilestones(repository);
verifyNoMoreInteractions(this.gitHubApi);

var repository = repositoryCaptor.getValue();
assertThat(repository.owner()).isEqualTo(OWNER);
assertThat(repository.name()).isEqualTo(REPO);
}

@Test
public void scheduleReleaseIfNotExistsWhenPatchVersionIsSnapshotAndExistsThenNotCreated() {
var version = "6.2.1-SNAPSHOT";
var baseVersion = "6.2.1";
var milestone = new Milestone(baseVersion, 1L, null);
when(this.gitHubApi.getMilestone(any(Repository.class), anyString())).thenReturn(milestone);
var milestone = new Milestone("6.2.1", 1L, null);
var repository = new Repository(OWNER, REPO);
when(this.gitHubApi.getMilestones(repository)).thenReturn(List.of(milestone));
this.springReleases.scheduleReleaseIfNotExists(OWNER, REPO, version, WEEK_OF_MONTH, DAY_OF_WEEK);

var repositoryCaptor = forClass(Repository.class);
verify(this.gitHubApi).getMilestone(repositoryCaptor.capture(), eq(baseVersion));
verify(this.gitHubApi).getMilestones(repository);
verifyNoMoreInteractions(this.gitHubApi);

var repository = repositoryCaptor.getValue();
assertThat(repository.owner()).isEqualTo(OWNER);
assertThat(repository.name()).isEqualTo(REPO);
}

// gh-31
Expand All @@ -610,14 +595,11 @@ public void scheduleReleaseIfNotExistsWhenCreatedThenDueOnCorrectDate() {
var version = "6.1.9";
this.springReleases.scheduleReleaseIfNotExists(OWNER, REPO, version, WEEK_OF_MONTH, DAY_OF_WEEK);

var repositoryCaptor = forClass(Repository.class);
var repository = new Repository(OWNER, REPO);
var milestoneCaptor = forClass(Milestone.class);
verify(this.gitHubApi).getMilestone(repositoryCaptor.capture(), eq(version));

var repository = repositoryCaptor.getValue();
assertThat(repository.owner()).isEqualTo(OWNER);
assertThat(repository.name()).isEqualTo(REPO);
verify(this.gitHubApi).getMilestones(repository);
verify(this.gitHubApi).createMilestone(eq(repository), milestoneCaptor.capture());
verifyNoMoreInteractions(this.gitHubApi);

var releaseTrainSpec = SpringReleaseTrainSpec.builder()
.nextTrain()
Expand Down

0 comments on commit bb39599

Please sign in to comment.