diff --git a/docs/src/main/asciidoc/spring-cloud-release-tools.adoc b/docs/src/main/asciidoc/spring-cloud-release-tools.adoc index f9d8b212..bf2092c2 100644 --- a/docs/src/main/asciidoc/spring-cloud-release-tools.adoc +++ b/docs/src/main/asciidoc/spring-cloud-release-tools.adoc @@ -30,6 +30,10 @@ why this tool makes it easy to automate the release / dependency update process - Generates a blog template under `target/blog.md` (ONLY FOR NON-SNAPSHOT VERSIONS) - Generates a tweet template under `target/tweet.txt` (ONLY FOR NON-SNAPSHOT VERSIONS) - Generates a release notes template under `target/notes.md` (ONLY FOR NON-SNAPSHOT VERSIONS) +- Updates project information in Sagan (http://spring.io) (ONLY FOR SNAPSHOT / RELEASE VERSIONS) + +IMPORTANT: Starting with version that does Sagan integration, you MUST pass the OAuth token, +otherwise the application will fail to start === What should I do first? diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/Releaser.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/Releaser.java index 53f8156f..f8b4d7b2 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/Releaser.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/Releaser.java @@ -143,7 +143,8 @@ public class Releaser { public void updateSagan(File project, ProjectVersion releaseVersion) { String currentBranch = this.projectGitHandler.currentBranch(project); - this.saganUpdater.updateSagan(currentBranch, releaseVersion); + ProjectVersion originalVersion = new ProjectVersion(project); + this.saganUpdater.updateSagan(currentBranch, originalVersion, releaseVersion); log.info("\nSuccessfully updated Sagan for branch [{}]", currentBranch); } } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/ReleaserProperties.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/ReleaserProperties.java index 3624b1c5..a5364a30 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/ReleaserProperties.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/ReleaserProperties.java @@ -287,7 +287,7 @@ public class ReleaserProperties { /** * URL to the Sagan API */ - private String baseUrl; + private String baseUrl = "http://spring.io"; public String getBaseUrl() { return this.baseUrl; diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectVersion.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectVersion.java index e0d33ae0..eac58003 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectVersion.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/pom/ProjectVersion.java @@ -15,7 +15,6 @@ public class ProjectVersion { public final String projectName; public final String version; - private final PomReader pomReader = new PomReader(); private final Model model; public ProjectVersion(String projectName, String version) { @@ -25,7 +24,8 @@ public class ProjectVersion { } public ProjectVersion(File project) { - Model model = this.pomReader.readPom(project); + PomReader pomReader = new PomReader(); + Model model = pomReader.readPom(project); this.projectName = nameWithoutParent(model.getArtifactId()); this.version = model.getVersion(); this.model = model; diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Project.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Project.java index 86e7fd0b..0cf2652a 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Project.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Project.java @@ -16,4 +16,12 @@ public class Project { public List projectReleases = new ArrayList<>(); public List stackOverflowTagList = new ArrayList<>(); public boolean aggregator; + + @Override public String toString() { + return "Project{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", repoUrl='" + + repoUrl + '\'' + ", siteUrl='" + siteUrl + '\'' + ", category='" + + category + '\'' + ", stackOverflowTags='" + stackOverflowTags + '\'' + + ", projectReleases=" + projectReleases + ", stackOverflowTagList=" + + stackOverflowTagList + ", aggregator=" + aggregator + '}'; + } } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Release.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Release.java index 01bc90e4..655298ec 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Release.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Release.java @@ -16,4 +16,14 @@ public class Release { public boolean preRelease; public String versionDisplayName = ""; public boolean snapshot; + + @Override public String toString() { + return "Release{" + "releaseStatus='" + releaseStatus + '\'' + ", refDocUrl='" + + refDocUrl + '\'' + ", apiDocUrl='" + apiDocUrl + '\'' + ", groupId='" + + groupId + '\'' + ", artifactId='" + artifactId + '\'' + ", repository=" + + repository + ", version='" + version + '\'' + ", current=" + current + + ", generalAvailability=" + generalAvailability + ", preRelease=" + + preRelease + ", versionDisplayName='" + versionDisplayName + '\'' + + ", snapshot=" + snapshot + '}'; + } } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/ReleaseUpdate.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/ReleaseUpdate.java index b9b0feea..2a3cce57 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/ReleaseUpdate.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/ReleaseUpdate.java @@ -10,11 +10,12 @@ public class ReleaseUpdate { public String releaseStatus = ""; public String refDocUrl = ""; public String apiDocUrl = ""; + public Repository repository; @Override public String toString() { return "ReleaseUpdate{" + "groupId='" + groupId + '\'' + ", artifactId='" + artifactId + '\'' + ", version='" + version + '\'' + ", releaseStatus='" + releaseStatus + '\'' + ", refDocUrl='" + refDocUrl + '\'' - + ", apiDocUrl='" + apiDocUrl + '\'' + '}'; + + ", apiDocUrl='" + apiDocUrl + '\'' + ", repository=" + repository + '}'; } } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Repository.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Repository.java index b2122d63..cd1b6fd7 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Repository.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/Repository.java @@ -8,4 +8,9 @@ public class Repository { public String name; public String url; public boolean snapshotsEnabled; + + @Override public String toString() { + return "Repository{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", url='" + + url + '\'' + ", snapshotsEnabled=" + snapshotsEnabled + '}'; + } } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/RestTemplateSaganClient.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/RestTemplateSaganClient.java index b7b3be85..6b536c0f 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/RestTemplateSaganClient.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/RestTemplateSaganClient.java @@ -2,10 +2,12 @@ package org.springframework.cloud.release.internal.sagan; import java.net.URI; +import org.slf4j.LoggerFactory; import org.springframework.cloud.release.internal.ReleaserProperties; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; /** @@ -13,6 +15,8 @@ import org.springframework.web.client.RestTemplate; */ class RestTemplateSaganClient implements SaganClient { + private static final org.slf4j.Logger log = LoggerFactory.getLogger(RestTemplateSaganClient.class); + private final RestTemplate restTemplate; private final String baseUrl; @@ -32,9 +36,13 @@ class RestTemplateSaganClient implements SaganClient { @Override public Release createOrUpdateRelease(String projectName, ReleaseUpdate releaseUpdate) { RequestEntity request = RequestEntity - .post(URI.create(this.baseUrl +"/project_metadata/" + projectName + "/releases")) + .put(URI.create(this.baseUrl +"/project_metadata/" + projectName + "/releases")) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) .body(releaseUpdate); - return this.restTemplate.exchange(request, Release.class).getBody(); + ResponseEntity entity = this.restTemplate + .exchange(request, Release.class); + Release release = entity.getBody(); + log.info("Response from Sagan\n\n[{}] \n with body [{}]", entity, release); + return release; } } diff --git a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/SaganUpdater.java b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/SaganUpdater.java index f3290c02..a19ac18e 100644 --- a/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/SaganUpdater.java +++ b/spring-cloud-release-tools-core/src/main/java/org/springframework/cloud/release/internal/sagan/SaganUpdater.java @@ -17,16 +17,17 @@ public class SaganUpdater { this.saganClient = saganClient; } - public void updateSagan(String branch, ProjectVersion version) { + public void updateSagan(String branch, ProjectVersion originalVersion, ProjectVersion version) { if (version.isMilestone() || version.isRc()) { log.info("Won't update Sagan about milestones / rc"); return; } ReleaseUpdate update = new ReleaseUpdate(); - update.groupId = version.groupId(); + update.groupId = originalVersion.groupId(); update.artifactId = version.projectName; update.version = version.version; - update.apiDocUrl = "http://github.com/spring-cloud/" + version.projectName; + update.releaseStatus = version.isSnapshot() ? "SNAPSHOT" : "GENERAL_AVAILABILITY"; + update.apiDocUrl = referenceUrl(branch, version); update.refDocUrl = referenceUrl(branch, version); log.info("Updating Sagan with \n\n{}", update); this.saganClient.createOrUpdateRelease(version.projectName, update); diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/RestTemplateSaganClientTests.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/RestTemplateSaganClientTests.java index dad1ad6d..43f19df3 100644 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/RestTemplateSaganClientTests.java +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/RestTemplateSaganClientTests.java @@ -91,11 +91,15 @@ public class RestTemplateSaganClientTests { ReleaseUpdate releaseUpdate = new ReleaseUpdate(); releaseUpdate.groupId = "org.springframework"; releaseUpdate.artifactId = "spring-context"; - releaseUpdate.version = "1.2.3.RELEASE"; - releaseUpdate.releaseStatus = "GENERAL_AVAILABILITY"; + releaseUpdate.version = "1.2.8.RELEASE"; + releaseUpdate.releaseStatus = "PRERELEASE"; releaseUpdate.refDocUrl = "http://docs.spring.io/spring/docs/{version}/spring-framework-reference/"; releaseUpdate.apiDocUrl = "http://docs.spring.io/spring/docs/{version}/javadoc-api/"; + + \n \"repository\" : {\n \"id\" : \"spring-milestones\",\n \"name\" : \"Spring Milestones\",\n \"url\" : \"https://repo.spring.io/libs-milestone\",\n \"snapshotsEnabled\" : false\n }\n}, {\n \"groupId\" : \"org.springframework\",\n \"artifactId\" : \"spring-context\",\n \"version\" : \"5.0.0.BUILD-SNAPSHOT\",\n \"releaseStatus\" : \"SNAPSHOT\",\n \"refDocUrl\" : \"http://docs.spring.io/spring/docs/{version}/spring-framework-reference/\",\n \"apiDocUrl\" : \"http://docs.spring.io/spring/docs/{version}/javadoc-api/\",\n \"repository\" : {\n \"id\" : \"spring-snapshots\",\n \"name\" : \"Spring Snapshots\",\n \"url\" : \"https://repo.spring.io/libs-snapshot\",\n \"snapshotsEnabled\" : true\n }\n}, {\n \"groupId\" : \"org.springframework\",\n \"artifactId\" : \"spring-context\",\n \"version\" : \"4.3.12.BUILD-SNAPSHOT\",\n \"releaseStatus\" : \"SNAPSHOT\",\n \"refDocUrl\" : \"http://docs.spring.io/spring/docs/{version}/spring-framework-reference/htmlsingle/\",\n \"apiDocUrl\" : \"http://docs.spring.io/spring/docs/{version}/javadoc-api/\",\n \"repository\" : {\n \"id\" : \"spring-snapshots\",\n \"name\" : \"Spring Snapshots\",\n \"url\" : \"https://repo.spring.io/libs-snapshot\",\n \"snapshotsEnabled\" : true\n }\n}, {\n \"groupId\" : \"org.springframework\",\n \"artifactId\" : \"spring-context\",\n \"version\" : \"4.3.11.RELEASE\",\n \"releaseStatus\" : \"GENERAL_AVAILABILITY\",\n \"current\" : true,\n \"refDocUrl\" : \"http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/\",\n \"apiDocUrl\" : \"http://docs.spring.io/spring/docs/current/javadoc-api/\"\n}, {\n \"groupId\" : \"org.springframework\",\n \"artifactId\" : \"spring-context\",\n \"version\" : \"4.2.9.RELEASE\",\n \"releaseStatus\" : \"GENERAL_AVAILABILITY\",\n \"refDocUrl\" : \"http://docs.spring.io/spring/docs/{version}/spring-framework-reference/htmlsingle/\",\n \"apiDocUrl\" : \"http://docs.spring.io/spring/docs/{version}/javadoc-api/\"\n}, {\n \"groupId\" : \"org.springframework\",\n \"artifactId\" : \"spring-context\",\n \"version\" : \"3.2.18.RELEASE\",\n \"releaseStatus\" : \"GENERAL_AVAILABILITY\",\n \"refDocUrl\" : \"http://docs.spring.io/spring/docs/{version}/spring-framework-reference/htmlsingle/\",\n \"apiDocUrl\" : \"http://docs.spring.io/spring/docs/{version}/javadoc-api/\"\n} ]" + + Release release = this.client.createOrUpdateRelease("spring-framework", releaseUpdate); then(release.releaseStatus).isEqualTo("GENERAL_AVAILABILITY"); diff --git a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java index 8eaa8e26..05189d11 100644 --- a/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java +++ b/spring-cloud-release-tools-core/src/test/java/org/springframework/cloud/release/internal/sagan/SaganUpdaterTest.java @@ -20,39 +20,43 @@ public class SaganUpdaterTest { @InjectMocks SaganUpdater saganUpdater; @Test public void should_not_update_sagan_for_milestone_or_rc() throws Exception { - this.saganUpdater.updateSagan("master", new ProjectVersion("foo", "1.0.0.M1")); + this.saganUpdater.updateSagan("master", version("1.0.0.M1"), version("1.0.0.M1")); BDDMockito.then(this.saganClient).should(BDDMockito.never()) .createOrUpdateRelease(BDDMockito.anyString(), BDDMockito.any(ReleaseUpdate.class)); - this.saganUpdater.updateSagan("master", new ProjectVersion("foo", "1.0.0.RC1")); + this.saganUpdater.updateSagan("master", version("1.0.0.RC1"), version("1.0.0.RC1")); BDDMockito.then(this.saganClient).should(BDDMockito.never()) .createOrUpdateRelease(BDDMockito.anyString(), BDDMockito.any(ReleaseUpdate.class)); } - @Test public void should_update_sagan_from_master() throws Exception { - ProjectVersion projectVersion = new ProjectVersion("foo", "1.0.0.BUILD-SNAPSHOT"); + private ProjectVersion version(String version) { + return new ProjectVersion("foo", version); + } - this.saganUpdater.updateSagan("master", projectVersion); + @Test public void should_update_sagan_from_master() throws Exception { + ProjectVersion projectVersion = version("1.0.0.BUILD-SNAPSHOT"); + + this.saganUpdater.updateSagan("master", projectVersion, projectVersion); BDDMockito.then(this.saganClient).should().createOrUpdateRelease(BDDMockito.eq("foo"), BDDMockito.argThat(withReleaseUpdate("1.0.0.BUILD-SNAPSHOT", "http://cloud.spring.io/foo/foo.html"))); } @Test public void should_update_sagan_from_release_version() throws Exception { - ProjectVersion projectVersion = new ProjectVersion("foo", "1.0.0.RELEASE"); + ProjectVersion projectVersion = version("1.0.0.RELEASE"); - this.saganUpdater.updateSagan("master", projectVersion); + this.saganUpdater.updateSagan("master", projectVersion, projectVersion); BDDMockito.then(this.saganClient).should().createOrUpdateRelease(BDDMockito.eq("foo"), BDDMockito.argThat(withReleaseUpdate("1.0.0.RELEASE", "http://cloud.spring.io/spring-cloud-static/foo/{version}/"))); } @Test public void should_update_sagan_from_non_master() throws Exception { - ProjectVersion projectVersion = new ProjectVersion("foo", "1.1.0.BUILD-SNAPSHOT"); + ProjectVersion projectVersion = version("1.1.0.BUILD-SNAPSHOT"); - this.saganUpdater.updateSagan("1.1.x", projectVersion); + this.saganUpdater.updateSagan("1.1.x", projectVersion, projectVersion); BDDMockito.then(this.saganClient).should().createOrUpdateRelease(BDDMockito.eq("foo"), BDDMockito.argThat(withReleaseUpdate("1.1.0.BUILD-SNAPSHOT", "http://cloud.spring.io/foo/1.1.x/"))); @@ -63,7 +67,7 @@ public class SaganUpdaterTest { @Override protected boolean matchesSafely(ReleaseUpdate item) { return "foo".equals(item.artifactId) && version.equals(item.version) && - "http://github.com/spring-cloud/foo".equals(item.apiDocUrl) && + refDocUrl.equals(item.apiDocUrl) && refDocUrl.equals(item.refDocUrl); } diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/sagan/SaganConfiguration.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/sagan/SaganConfiguration.java index a7372b83..ac86ccc0 100644 --- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/sagan/SaganConfiguration.java +++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/sagan/SaganConfiguration.java @@ -4,6 +4,7 @@ import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.cloud.release.internal.ReleaserProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.util.Assert; import org.springframework.web.client.RestTemplate; /** @@ -19,6 +20,7 @@ class SaganConfiguration { } private RestTemplate restTemplate(ReleaserProperties properties) { + Assert.hasText(properties.getGit().getOauthToken(), "In order to connect to Sagan you need to pass the Github OAuth token"); return new RestTemplateBuilder() .basicAuthorization(properties.getGit().getOauthToken(), "") .build(); diff --git a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java index c890ed5b..c28b96ed 100644 --- a/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java +++ b/spring-cloud-release-tools-spring/src/main/java/org/springframework/cloud/release/internal/spring/Tasks.java @@ -52,8 +52,8 @@ class Tasks { args.releaser.createTweet(args.versionFromScRelease); args.releaser.createReleaseNotes(args.versionFromScRelease, args.projects); }); - static Task UPDATING_SAGAN = task("updatingSagan", "g", - "UPDATING SAGAN", + static Task UPDATE_SAGAN = task("updateSagan", "g", + "UPDATE SAGAN", "Updating Sagan with release info", args -> { args.releaser.updateSagan(args.project, args.versionFromScRelease); @@ -69,7 +69,7 @@ class Tasks { Tasks.PUSH, Tasks.CLOSE_MILESTONE, Tasks.CREATE_TEMPLATES, - Tasks.UPDATING_SAGAN + Tasks.UPDATE_SAGAN ).collect(Collectors.toList()); static Task RELEASE = Tasks.task("release", "r", diff --git a/spring-cloud-release-tools-spring/src/main/resources/application.yml b/spring-cloud-release-tools-spring/src/main/resources/application.yml new file mode 100644 index 00000000..d18f0f6d --- /dev/null +++ b/spring-cloud-release-tools-spring/src/main/resources/application.yml @@ -0,0 +1 @@ +spring.main.web-environment: false \ No newline at end of file