Skip to content

Commit 87ede2f

Browse files
committed
Tests for release note generation via bundles
1 parent 99043b5 commit 87ede2f

File tree

9 files changed

+331
-430
lines changed

9 files changed

+331
-430
lines changed

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/ChangelogBundle.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,13 @@ public static ChangelogBundle parse(File file) {
4040
throw new UncheckedIOException(e);
4141
}
4242
}
43+
44+
public static ChangelogBundle copy(ChangelogBundle bundle) {
45+
List<ChangelogEntry> changelogs = bundle.changelogs().stream().toList();
46+
return new ChangelogBundle(bundle.version(), bundle.released(), bundle.generated(), changelogs);
47+
}
48+
49+
public ChangelogBundle withChangelogs(List<ChangelogEntry> changelogs) {
50+
return new ChangelogBundle(version, released, generated, changelogs);
51+
}
4352
}

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/GenerateReleaseNotesTask.java

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.gradle.process.ExecOperations;
3232

3333
import java.io.IOException;
34+
import java.util.ArrayList;
3435
import java.util.Comparator;
3536
import java.util.HashSet;
3637
import java.util.List;
@@ -93,60 +94,42 @@ public void executeTask() throws IOException {
9394

9495
LOGGER.info("Finding changelog bundles...");
9596

96-
List<ChangelogBundle> bundles = this.changelogBundleDirectory.getAsFileTree()
97+
List<ChangelogBundle> allBundles = this.changelogBundleDirectory.getAsFileTree()
9798
.getFiles()
9899
.stream()
99100
.map(ChangelogBundle::parse)
100-
.sorted(Comparator.comparing(ChangelogBundle::released).reversed().thenComparing(ChangelogBundle::generated).reversed())
101101
.toList();
102102

103-
// Ensure that each changelog/PR only shows up once, in its earliest release
104-
var uniquePrs = new HashSet<Integer>();
105-
for (int i = bundles.size() - 1; i >= 0; i--) {
106-
var bundle = bundles.get(i);
107-
if (!bundle.released()) {
108-
bundle.changelogs().removeAll(bundle.changelogs().stream().filter(c -> uniquePrs.contains(c.getPr())).toList());
109-
}
110-
uniquePrs.addAll(bundle.changelogs().stream().map(ChangelogEntry::getPr).toList());
111-
}
103+
var bundles = getSortedBundlesWithUniqueChangelogs(allBundles);
112104

113105
LOGGER.info("Generating release notes...");
114106
ReleaseNotesGenerator.update(this.releaseNotesTemplate.get().getAsFile(), this.releaseNotesFile.get().getAsFile(), bundles);
115107
ReleaseNotesGenerator.update(this.breakingChangesTemplate.get().getAsFile(), this.breakingChangesFile.get().getAsFile(), bundles);
116108
ReleaseNotesGenerator.update(this.deprecationsTemplate.get().getAsFile(), this.deprecationsFile.get().getAsFile(), bundles);
117109
}
118110

119-
/**
120-
* Find all tags in the major series for the supplied version
121-
* @param gitWrapper used to call `git`
122-
* @param currentVersion the version to base the query upon
123-
* @return all versions in the series
124-
*/
125111
@VisibleForTesting
126-
static Set<QualifiedVersion> getVersions(GitWrapper gitWrapper, String currentVersion) {
127-
QualifiedVersion qualifiedVersion = QualifiedVersion.of(currentVersion);
128-
final String pattern = "v" + qualifiedVersion.major() + ".*";
129-
// We may be generating notes for a minor version prior to the latest minor, so we need to filter out versions that are too new.
130-
Set<QualifiedVersion> versions = Stream.concat(
131-
gitWrapper.listVersions(pattern).filter(v -> v.isBefore(qualifiedVersion)),
132-
Stream.of(qualifiedVersion)
133-
).collect(toSet());
134-
135-
// If this is a new minor ensure we include the previous minor, which may not have been released
136-
if (qualifiedVersion.minor() > 0 && qualifiedVersion.revision() == 0) {
137-
QualifiedVersion previousMinor = new QualifiedVersion(qualifiedVersion.major(), qualifiedVersion.minor() - 1, 0, null);
138-
versions.add(previousMinor);
139-
}
112+
static List<ChangelogBundle> getSortedBundlesWithUniqueChangelogs(List<ChangelogBundle> bundles) {
113+
List<ChangelogBundle> sorted = bundles.stream()
114+
// .map(ChangelogBundle::copy)
115+
.sorted(Comparator.comparing(ChangelogBundle::released).reversed().thenComparing(ChangelogBundle::generated))
116+
.toList();
140117

141-
return versions;
142-
}
118+
// Ensure that each changelog/PR only shows up once, in its earliest release
119+
var uniquePrs = new HashSet<Integer>();
120+
List<ChangelogBundle> modifiedBundles = new ArrayList<>();
121+
for (int i = sorted.size() - 1; i >= 0; i--) {
122+
var bundle = sorted.get(i);
123+
if (bundle.released() == false) {
124+
List<ChangelogEntry> entries = bundle.changelogs().stream().filter(c -> false == uniquePrs.contains(c.getPr())).toList();
125+
modifiedBundles.add(bundle.withChangelogs(entries));
126+
} else {
127+
modifiedBundles.add(bundle);
128+
}
129+
uniquePrs.addAll(bundle.changelogs().stream().map(ChangelogEntry::getPr).toList());
130+
}
143131

144-
/**
145-
* Convert set of QualifiedVersion to MinorVersion by deleting all but the major and minor components.
146-
*/
147-
@VisibleForTesting
148-
static Set<MinorVersion> getMinorVersions(Set<QualifiedVersion> versions) {
149-
return versions.stream().map(MinorVersion::of).collect(toSet());
132+
return modifiedBundles;
150133
}
151134

152135
/**

build-tools-internal/src/test/java/org/elasticsearch/gradle/internal/release/GenerateReleaseNotesTaskTest.java

Lines changed: 0 additions & 272 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,12 @@
99

1010
package org.elasticsearch.gradle.internal.release;
1111

12-
import org.junit.Before;
1312
import org.junit.Test;
1413

15-
import java.io.File;
16-
import java.util.Map;
17-
import java.util.Set;
18-
import java.util.stream.Stream;
19-
2014
import static org.hamcrest.MatcherAssert.assertThat;
21-
import static org.hamcrest.Matchers.aMapWithSize;
22-
import static org.hamcrest.Matchers.allOf;
23-
import static org.hamcrest.Matchers.containsInAnyOrder;
24-
import static org.hamcrest.Matchers.equalTo;
25-
import static org.hamcrest.Matchers.hasEntry;
26-
import static org.hamcrest.Matchers.hasItem;
27-
import static org.hamcrest.Matchers.hasKey;
2815
import static org.hamcrest.Matchers.is;
29-
import static org.mockito.Matchers.anyString;
30-
import static org.mockito.Matchers.eq;
31-
import static org.mockito.Mockito.mock;
32-
import static org.mockito.Mockito.verify;
33-
import static org.mockito.Mockito.verifyNoMoreInteractions;
34-
import static org.mockito.Mockito.when;
3516

3617
public class GenerateReleaseNotesTaskTest {
37-
private GitWrapper gitWrapper;
38-
39-
@Before
40-
public void setup() {
41-
this.gitWrapper = mock(GitWrapper.class);
42-
}
43-
4418
/**
4519
* Check that the task does not update git tags if the current version is a snapshot of the first patch release.
4620
*/
@@ -88,250 +62,4 @@ public void needsGitTags_withFirsAlphaRelease_returnsFalse() {
8862
public void needsGitTags_withLaterAlphaRelease_returnsFalse() {
8963
assertThat(GenerateReleaseNotesTask.needsGitTags("8.0.0-alpha2"), is(true));
9064
}
91-
92-
/**
93-
* Check that partitioning changelog files when the current version is a snapshot returns a map with a single entry.
94-
*/
95-
@Test
96-
public void partitionFiles_withSnapshot_returnsSingleMapping() {
97-
// when:
98-
Map<QualifiedVersion, Set<File>> partitionedFiles = GenerateReleaseNotesTask.partitionFilesByVersion(
99-
gitWrapper,
100-
"8.0.0-SNAPSHOT",
101-
Set.of(new File("docs/changelog/1234.yaml"))
102-
);
103-
104-
// then:
105-
assertThat(partitionedFiles, aMapWithSize(1));
106-
assertThat(
107-
partitionedFiles,
108-
hasEntry(equalTo(QualifiedVersion.of("8.0.0-SNAPSHOT")), hasItem(new File("docs/changelog/1234.yaml")))
109-
);
110-
verifyNoMoreInteractions(gitWrapper);
111-
}
112-
113-
/**
114-
* Check that partitioning changelog files when the current version is the first release
115-
* in a minor series returns a map with a single entry.
116-
*/
117-
@Test
118-
public void partitionFiles_withFirstRevision_returnsSingleMapping() {
119-
// when:
120-
Map<QualifiedVersion, Set<File>> partitionedFiles = GenerateReleaseNotesTask.partitionFilesByVersion(
121-
gitWrapper,
122-
"8.5.0",
123-
Set.of(new File("docs/changelog/1234.yaml"))
124-
);
125-
126-
// then:
127-
assertThat(partitionedFiles, aMapWithSize(1));
128-
assertThat(partitionedFiles, hasEntry(equalTo(QualifiedVersion.of("8.5.0")), hasItem(new File("docs/changelog/1234.yaml"))));
129-
verifyNoMoreInteractions(gitWrapper);
130-
}
131-
132-
/**
133-
* Check that partitioning changelog files when the current version is the first alpha prerelease returns a map with a single entry.
134-
*/
135-
@Test
136-
public void partitionFiles_withFirstAlpha_returnsSingleMapping() {
137-
// when:
138-
Map<QualifiedVersion, Set<File>> partitionedFiles = GenerateReleaseNotesTask.partitionFilesByVersion(
139-
gitWrapper,
140-
"8.0.0-alpha1",
141-
Set.of(new File("docs/changelog/1234.yaml"))
142-
);
143-
144-
// then:
145-
assertThat(partitionedFiles, aMapWithSize(1));
146-
assertThat(partitionedFiles, hasEntry(equalTo(QualifiedVersion.of("8.0.0-alpha1")), hasItem(new File("docs/changelog/1234.yaml"))));
147-
verifyNoMoreInteractions(gitWrapper);
148-
}
149-
150-
/**
151-
* Check that when deriving a lit of versions from git tags, the current unreleased version is included.
152-
*/
153-
@Test
154-
public void getVersions_includesCurrentAndPreviousVersion() {
155-
// given:
156-
when(gitWrapper.listVersions(anyString())).thenReturn(
157-
Stream.of("8.0.0-alpha1", "8.0.0-alpha2", "8.0.0-beta1", "8.0.0-beta2", "8.0.0-beta3", "8.0.0-rc1", "8.0.0", "8.0.1", "8.1.0")
158-
.map(QualifiedVersion::of)
159-
);
160-
161-
// when:
162-
Set<QualifiedVersion> versions = GenerateReleaseNotesTask.getVersions(gitWrapper, "8.3.0-SNAPSHOT");
163-
164-
// then:
165-
assertThat(
166-
versions,
167-
containsInAnyOrder(
168-
Stream.of(
169-
"8.0.0-alpha1",
170-
"8.0.0-alpha2",
171-
"8.0.0-beta1",
172-
"8.0.0-beta2",
173-
"8.0.0-beta3",
174-
"8.0.0-rc1",
175-
"8.0.0",
176-
"8.0.1",
177-
"8.1.0",
178-
"8.2.0",
179-
"8.3.0-SNAPSHOT"
180-
).map(QualifiedVersion::of).toArray(QualifiedVersion[]::new)
181-
)
182-
);
183-
}
184-
185-
/**
186-
* Check that when deriving a list of major.minor versions from git tags, the current unreleased version is included,
187-
* but any higher version numbers are not.
188-
*/
189-
@Test
190-
public void getMinorVersions_includesCurrentButNotFutureVersions() {
191-
// given:
192-
when(gitWrapper.listVersions(anyString())).thenReturn(
193-
Stream.of("8.0.0-alpha1", "8.0.0-alpha2", "8.0.0", "8.0.1", "8.1.0", "8.2.0", "8.2.1", "8.3.0", "8.3.1", "8.4.0")
194-
.map(QualifiedVersion::of)
195-
);
196-
197-
// when:
198-
Set<QualifiedVersion> versions = GenerateReleaseNotesTask.getVersions(gitWrapper, "8.3.0-SNAPSHOT");
199-
Set<MinorVersion> minorVersions = GenerateReleaseNotesTask.getMinorVersions(versions);
200-
201-
// then:
202-
assertThat(
203-
minorVersions,
204-
containsInAnyOrder(new MinorVersion(8, 0), new MinorVersion(8, 1), new MinorVersion(8, 2), new MinorVersion(8, 3))
205-
);
206-
}
207-
208-
/**
209-
* Check that the task partitions the list of files correctly by version for a prerelease.
210-
*/
211-
@Test
212-
public void partitionFiles_withPrerelease_correctlyGroupsByPrereleaseVersion() {
213-
// given:
214-
when(gitWrapper.listVersions(anyString())).thenReturn(
215-
Stream.of("8.0.0-alpha1", "8.0.0-alpha2", "8.0.0-beta1", "8.0.0-beta2", "8.0.0-beta3", "8.0.0-rc1", "8.0.0")
216-
.map(QualifiedVersion::of)
217-
);
218-
when(gitWrapper.listFiles(eq("v8.0.0-alpha1"), anyString())).thenReturn(
219-
Stream.of("docs/changelog/1_1234.yaml", "docs/changelog/1_5678.yaml")
220-
);
221-
when(gitWrapper.listFiles(eq("v8.0.0-alpha2"), anyString())).thenReturn(
222-
Stream.of("docs/changelog/2_1234.yaml", "docs/changelog/2_5678.yaml")
223-
);
224-
225-
Set<File> allFiles = Set.of(
226-
new File("docs/changelog/1_1234.yaml"),
227-
new File("docs/changelog/1_5678.yaml"),
228-
new File("docs/changelog/2_1234.yaml"),
229-
new File("docs/changelog/2_5678.yaml"),
230-
new File("docs/changelog/3_1234.yaml"),
231-
new File("docs/changelog/3_5678.yaml")
232-
);
233-
234-
// when:
235-
Map<QualifiedVersion, Set<File>> partitionedFiles = GenerateReleaseNotesTask.partitionFilesByVersion(
236-
gitWrapper,
237-
"8.0.0-beta1",
238-
allFiles
239-
);
240-
241-
// then:
242-
verify(gitWrapper).listVersions("v8.0*");
243-
verify(gitWrapper).listFiles("v8.0.0-alpha1", "docs/changelog");
244-
verify(gitWrapper).listFiles("v8.0.0-alpha2", "docs/changelog");
245-
246-
assertThat(
247-
partitionedFiles,
248-
allOf(
249-
aMapWithSize(3),
250-
hasKey(QualifiedVersion.of("8.0.0-alpha1")),
251-
hasKey(QualifiedVersion.of("8.0.0-alpha2")),
252-
hasKey(QualifiedVersion.of("8.0.0-beta1"))
253-
)
254-
);
255-
256-
assertThat(
257-
partitionedFiles,
258-
allOf(
259-
hasEntry(
260-
equalTo(QualifiedVersion.of("8.0.0-alpha1")),
261-
containsInAnyOrder(new File("docs/changelog/1_1234.yaml"), new File("docs/changelog/1_5678.yaml"))
262-
),
263-
hasEntry(
264-
equalTo(QualifiedVersion.of("8.0.0-alpha2")),
265-
containsInAnyOrder(new File("docs/changelog/2_1234.yaml"), new File("docs/changelog/2_5678.yaml"))
266-
),
267-
hasEntry(
268-
equalTo(QualifiedVersion.of("8.0.0-beta1")),
269-
containsInAnyOrder(new File("docs/changelog/3_1234.yaml"), new File("docs/changelog/3_5678.yaml"))
270-
)
271-
)
272-
);
273-
}
274-
275-
/**
276-
* Check that the task partitions the list of files correctly by version for a patch release.
277-
*/
278-
@Test
279-
public void partitionFiles_withPatchRelease_correctlyGroupsByPatchVersion() {
280-
// given:
281-
when(gitWrapper.listVersions(anyString())).thenReturn(
282-
Stream.of("8.0.0-alpha1", "8.0.0-alpha2", "8.0.0-beta1", "8.0.0-rc1", "8.0.0", "8.0.1", "8.0.2", "8.1.0")
283-
.map(QualifiedVersion::of)
284-
);
285-
when(gitWrapper.listFiles(eq("v8.0.0"), anyString())).thenReturn(
286-
Stream.of("docs/changelog/1_1234.yaml", "docs/changelog/1_5678.yaml")
287-
);
288-
when(gitWrapper.listFiles(eq("v8.0.1"), anyString())).thenReturn(
289-
Stream.of("docs/changelog/2_1234.yaml", "docs/changelog/2_5678.yaml")
290-
);
291-
292-
Set<File> allFiles = Set.of(
293-
new File("docs/changelog/1_1234.yaml"),
294-
new File("docs/changelog/1_5678.yaml"),
295-
new File("docs/changelog/2_1234.yaml"),
296-
new File("docs/changelog/2_5678.yaml"),
297-
new File("docs/changelog/3_1234.yaml"),
298-
new File("docs/changelog/3_5678.yaml")
299-
);
300-
301-
// when:
302-
Map<QualifiedVersion, Set<File>> partitionedFiles = GenerateReleaseNotesTask.partitionFilesByVersion(gitWrapper, "8.0.2", allFiles);
303-
304-
// then:
305-
verify(gitWrapper).listVersions("v8.0*");
306-
verify(gitWrapper).listFiles("v8.0.0", "docs/changelog");
307-
verify(gitWrapper).listFiles("v8.0.1", "docs/changelog");
308-
309-
assertThat(
310-
partitionedFiles,
311-
allOf(
312-
aMapWithSize(3),
313-
hasKey(QualifiedVersion.of("8.0.0")),
314-
hasKey(QualifiedVersion.of("8.0.1")),
315-
hasKey(QualifiedVersion.of("8.0.2"))
316-
)
317-
);
318-
319-
assertThat(
320-
partitionedFiles,
321-
allOf(
322-
hasEntry(
323-
equalTo(QualifiedVersion.of("8.0.0")),
324-
containsInAnyOrder(new File("docs/changelog/1_1234.yaml"), new File("docs/changelog/1_5678.yaml"))
325-
),
326-
hasEntry(
327-
equalTo(QualifiedVersion.of("8.0.1")),
328-
containsInAnyOrder(new File("docs/changelog/2_1234.yaml"), new File("docs/changelog/2_5678.yaml"))
329-
),
330-
hasEntry(
331-
equalTo(QualifiedVersion.of("8.0.2")),
332-
containsInAnyOrder(new File("docs/changelog/3_1234.yaml"), new File("docs/changelog/3_5678.yaml"))
333-
)
334-
)
335-
);
336-
}
33765
}

0 commit comments

Comments
 (0)