From 653d6d79485f68af586c4784fa02e0880f8bc6d8 Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Tue, 14 May 2024 16:03:35 -0700 Subject: [PATCH] Support Antora versions for project documentation links Closes gh-19 --- .../contentful/ProjectDocumentation.java | 10 +++++- .../projectapi/web/release/NewRelease.java | 9 ++++- .../web/release/ReleasesController.java | 2 +- .../contentful/ContentfulOperationsTests.java | 5 +-- .../contentful/ContentfulServiceTests.java | 4 +-- .../ProjectDocumentationJsonTests.java | 4 ++- .../LegacyReleasesControllerTests.java | 4 +-- .../web/release/ReleasesControllerTests.java | 35 +++++++++++++++++-- .../web/release/add-with-antora.json | 6 ++++ 9 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 src/test/resources/io/spring/projectapi/web/release/add-with-antora.json diff --git a/src/main/java/io/spring/projectapi/contentful/ProjectDocumentation.java b/src/main/java/io/spring/projectapi/contentful/ProjectDocumentation.java index d288995..2083249 100644 --- a/src/main/java/io/spring/projectapi/contentful/ProjectDocumentation.java +++ b/src/main/java/io/spring/projectapi/contentful/ProjectDocumentation.java @@ -30,6 +30,8 @@ public class ProjectDocumentation implements Comparable { private final String version; + private final boolean antora; + private final String api; private final String ref; @@ -39,8 +41,10 @@ public class ProjectDocumentation implements Comparable { private final boolean current; @JsonCreator(mode = Mode.PROPERTIES) - public ProjectDocumentation(String version, String api, String ref, Status status, boolean current) { + public ProjectDocumentation(String version, boolean antora, String api, String ref, Status status, + boolean current) { this.version = version; + this.antora = antora; this.api = api; this.ref = ref; this.status = status; @@ -76,6 +80,10 @@ public int compareTo(ProjectDocumentation other) { return -this.version.compareTo(other.version); } + public boolean isAntora() { + return this.antora; + } + /** * Project documentation status. */ diff --git a/src/main/java/io/spring/projectapi/web/release/NewRelease.java b/src/main/java/io/spring/projectapi/web/release/NewRelease.java index a3ae137..f67693a 100644 --- a/src/main/java/io/spring/projectapi/web/release/NewRelease.java +++ b/src/main/java/io/spring/projectapi/web/release/NewRelease.java @@ -36,11 +36,14 @@ public class NewRelease { @URL private final String apiDocUrl; + private final boolean isAntora; + @JsonCreator - public NewRelease(String version, String referenceDocUrl, String apiDocUrl) { + public NewRelease(String version, String referenceDocUrl, String apiDocUrl, boolean isAntora) { this.version = version; this.referenceDocUrl = referenceDocUrl; this.apiDocUrl = apiDocUrl; + this.isAntora = isAntora; } public String getVersion() { @@ -55,4 +58,8 @@ public String getApiDocUrl() { return this.apiDocUrl; } + public boolean isAntora() { + return this.isAntora; + } + } diff --git a/src/main/java/io/spring/projectapi/web/release/ReleasesController.java b/src/main/java/io/spring/projectapi/web/release/ReleasesController.java index c406b58..40c5b05 100644 --- a/src/main/java/io/spring/projectapi/web/release/ReleasesController.java +++ b/src/main/java/io/spring/projectapi/web/release/ReleasesController.java @@ -110,7 +110,7 @@ public ResponseEntity add(@PathVariable String id, @RequestBody NewRelea return ResponseEntity.badRequest().body(message); } Release.Status status = Release.Status.fromVersion(version); - ProjectDocumentation projectDocumentation = new ProjectDocumentation(release.getVersion(), + ProjectDocumentation projectDocumentation = new ProjectDocumentation(release.getVersion(), release.isAntora(), release.getApiDocUrl(), release.getReferenceDocUrl(), ProjectDocumentation.Status.valueOf(status.name()), false); this.contentfulService.addProjectDocumentation(id, projectDocumentation); diff --git a/src/test/java/io/spring/projectapi/contentful/ContentfulOperationsTests.java b/src/test/java/io/spring/projectapi/contentful/ContentfulOperationsTests.java index 1c568f2..094f1cc 100644 --- a/src/test/java/io/spring/projectapi/contentful/ContentfulOperationsTests.java +++ b/src/test/java/io/spring/projectapi/contentful/ContentfulOperationsTests.java @@ -80,6 +80,7 @@ void addProjectDocumentation() { assertThat(updatedEntry.size()).isEqualTo(2); assertThat(updatedEntry).extracting((map) -> map.get("version")).containsExactly("1.0", "2.0"); assertThat(updatedEntry).extracting((map) -> map.get("current")).containsExactly(false, true); + assertThat(updatedEntry).extracting((map) -> map.get("antora")).containsExactly(false, true); } @Test @@ -287,7 +288,7 @@ private Consumer>> addRelease() { private static Map getRelease(boolean current) { return Map.of("version", "1.0", "api", "http://api.com", "ref", "http://ref.com", "status", - "GENERAL_AVAILABILITY", "repository", "RELEASE", "current", current); + "GENERAL_AVAILABILITY", "repository", "RELEASE", "current", current, "antora", false); } @SuppressWarnings("unchecked") @@ -300,7 +301,7 @@ private void setupNonExistentProject() { } private ProjectDocumentation getDocumentation(String version, Status status) { - return new ProjectDocumentation(version, "http://api.com", "http://ref.com", status, false); + return new ProjectDocumentation(version, true, "http://api.com", "http://ref.com", status, false); } } diff --git a/src/test/java/io/spring/projectapi/contentful/ContentfulServiceTests.java b/src/test/java/io/spring/projectapi/contentful/ContentfulServiceTests.java index 4e2c4b8..cbf0fe0 100644 --- a/src/test/java/io/spring/projectapi/contentful/ContentfulServiceTests.java +++ b/src/test/java/io/spring/projectapi/contentful/ContentfulServiceTests.java @@ -43,8 +43,8 @@ class ContentfulServiceTests { private static final Project PROJECT = new Project("Test Project", "test-project", "github", Status.ACTIVE); - private static final ProjectDocumentation PROJECT_DOCUMENTATION = new ProjectDocumentation("2.0", "http://api.com", - "http://ref.com", ProjectDocumentation.Status.GENERAL_AVAILABILITY, false); + private static final ProjectDocumentation PROJECT_DOCUMENTATION = new ProjectDocumentation("2.0", false, + "http://api.com", "http://ref.com", ProjectDocumentation.Status.GENERAL_AVAILABILITY, false); private static final ProjectSupport PROJECT_SUPPORT = new ProjectSupport("2.2.x", LocalDate.parse("2020-02-01"), LocalDate.parse("2020-02-02"), LocalDate.parse("2020-02-03"), LocalDate.parse("2020-02-04"), diff --git a/src/test/java/io/spring/projectapi/contentful/ProjectDocumentationJsonTests.java b/src/test/java/io/spring/projectapi/contentful/ProjectDocumentationJsonTests.java index 51c31d1..d24b3ca 100644 --- a/src/test/java/io/spring/projectapi/contentful/ProjectDocumentationJsonTests.java +++ b/src/test/java/io/spring/projectapi/contentful/ProjectDocumentationJsonTests.java @@ -48,7 +48,7 @@ class ProjectDocumentationJsonTests { @Test void convertValueToMapReturnsMap() { - ProjectDocumentation documentation = new ProjectDocumentation("ver", "api", "ref", + ProjectDocumentation documentation = new ProjectDocumentation("ver", false, "api", "ref", ProjectDocumentation.Status.PRERELEASE, true); Map converted = this.objectMapper.convertValue(documentation, Map.class); Map expected = new HashMap<>(); @@ -57,6 +57,7 @@ void convertValueToMapReturnsMap() { expected.put("ref", documentation.getRef()); expected.put("status", documentation.getStatus().name()); expected.put("current", documentation.isCurrent()); + expected.put("antora", documentation.isAntora()); assertThat(converted).isEqualTo(expected); } @@ -69,6 +70,7 @@ void readObjectReadsJson() throws Exception { .isEqualTo("https://docs.spring.io/spring-boot/docs/{version}/reference/html/"); assertThat(projectDocumentation.getStatus()).isEqualTo(Status.SNAPSHOT); assertThat(projectDocumentation.isCurrent()).isEqualTo(true); + assertThat(projectDocumentation.isAntora()).isEqualTo(false); } } diff --git a/src/test/java/io/spring/projectapi/web/release/LegacyReleasesControllerTests.java b/src/test/java/io/spring/projectapi/web/release/LegacyReleasesControllerTests.java index 12f2460..ba002af 100644 --- a/src/test/java/io/spring/projectapi/web/release/LegacyReleasesControllerTests.java +++ b/src/test/java/io/spring/projectapi/web/release/LegacyReleasesControllerTests.java @@ -73,10 +73,10 @@ private List getProjectDocumentations() { List result = new ArrayList<>(); String docsRoot; docsRoot = "https://docs.spring.io/spring-boot/docs/2.3.0/"; - result.add(new ProjectDocumentation("2.3.0", docsRoot + "api/", docsRoot + "reference/html/", + result.add(new ProjectDocumentation("2.3.0", false, docsRoot + "api/", docsRoot + "reference/html/", Status.GENERAL_AVAILABILITY, true)); docsRoot = "https://docs.spring.io/spring-boot/docs/2.3.1-SNAPSHOT/"; - result.add(new ProjectDocumentation("2.3.1-SNAPSHOT", docsRoot + "api/", docsRoot + "reference/html/", + result.add(new ProjectDocumentation("2.3.1-SNAPSHOT", false, docsRoot + "api/", docsRoot + "reference/html/", Status.SNAPSHOT, false)); return result; } diff --git a/src/test/java/io/spring/projectapi/web/release/ReleasesControllerTests.java b/src/test/java/io/spring/projectapi/web/release/ReleasesControllerTests.java index 3586379..2db08aa 100644 --- a/src/test/java/io/spring/projectapi/web/release/ReleasesControllerTests.java +++ b/src/test/java/io/spring/projectapi/web/release/ReleasesControllerTests.java @@ -161,9 +161,37 @@ void addAddsRelease() throws Exception { .contentType(MediaType.APPLICATION_JSON) .content(from("add.json"))) .andExpect(status().isCreated()) + .andExpect(header().string("Location", expectedLocation)); + ArgumentCaptor captor = ArgumentCaptor.forClass(ProjectDocumentation.class); + verify(this.contentfulService).addProjectDocumentation(eq("spring-boot"), captor.capture()); + ProjectDocumentation added = captor.getValue(); + assertThat(added.getVersion()).isEqualTo("2.8.0"); + assertThat(added.getApi()).isEqualTo("https://docs.spring.io/spring-boot/docs/{version}/api/"); + assertThat(added.getRef()).isEqualTo("https://docs.spring.io/spring-boot/docs/{version}/reference/html/"); + assertThat(added.getStatus()).isEqualTo(ProjectDocumentation.Status.GENERAL_AVAILABILITY); + assertThat(added.isCurrent()).isFalse(); + assertThat(added.isAntora()).isFalse(); + } + + @Test + @WithMockUser(roles = "ADMIN") + void addWithAntoraVersionAddsRelease() throws Exception { + given(this.contentfulService.getProjectDocumentations("spring-boot")).willReturn(getProjectDocumentations()); + String expectedLocation = "https://api.spring.io/projects/spring-boot/releases/2.8.0"; + ConstrainedFields fields = ConstrainedFields.constraintsOn(NewRelease.class); + this.mvc + .perform(post("/projects/spring-boot/releases").accept(MediaTypes.HAL_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(from("add-with-antora.json"))) + .andExpect(status().isCreated()) .andExpect(header().string("Location", expectedLocation)) .andDo(document("create-release", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), - requestFields(fields.withPath("version").description("The Release version"), + requestFields(fields.withPath("version").description("The Release version"), fields + .withPath("isAntora") + .type(JsonFieldType.BOOLEAN) + .optional() + .description( + "Indicates if the documentation for this release is on Antora. Defaults to false if not specified."), fields.withPath("referenceDocUrl") .description( "URL of the reference documentation, {version} template variable is supported"), @@ -178,6 +206,7 @@ void addAddsRelease() throws Exception { assertThat(added.getRef()).isEqualTo("https://docs.spring.io/spring-boot/docs/{version}/reference/html/"); assertThat(added.getStatus()).isEqualTo(ProjectDocumentation.Status.GENERAL_AVAILABILITY); assertThat(added.isCurrent()).isFalse(); + assertThat(added.isAntora()).isTrue(); } @Test @@ -248,10 +277,10 @@ private List getProjectDocumentations() { List result = new ArrayList<>(); String docsRoot; docsRoot = "https://docs.spring.io/spring-boot/docs/2.3.0/"; - result.add(new ProjectDocumentation("2.3.0", docsRoot + "api/", docsRoot + "reference/html/", + result.add(new ProjectDocumentation("2.3.0", false, docsRoot + "api/", docsRoot + "reference/html/", Status.GENERAL_AVAILABILITY, true)); docsRoot = "https://docs.spring.io/spring-boot/docs/2.3.1-SNAPSHOT/"; - result.add(new ProjectDocumentation("2.3.1-SNAPSHOT", docsRoot + "api/", docsRoot + "reference/html/", + result.add(new ProjectDocumentation("2.3.1-SNAPSHOT", false, docsRoot + "api/", docsRoot + "reference/html/", Status.SNAPSHOT, false)); return result; } diff --git a/src/test/resources/io/spring/projectapi/web/release/add-with-antora.json b/src/test/resources/io/spring/projectapi/web/release/add-with-antora.json new file mode 100644 index 0000000..dbdf136 --- /dev/null +++ b/src/test/resources/io/spring/projectapi/web/release/add-with-antora.json @@ -0,0 +1,6 @@ +{ + "version": "2.8.0", + "isAntora": true, + "apiDocUrl": "https://docs.spring.io/spring-boot/docs/{version}/api/", + "referenceDocUrl": "https://docs.spring.io/spring-boot/docs/{version}/reference/html/" +} \ No newline at end of file