From 6aeaca7f6b4839715ec71b34e95eff7a27f12df5 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Mon, 8 Jan 2018 17:16:09 +0100 Subject: [PATCH 01/86] First draft create GithubConfig --- .../retest/rebazer/config/GithubConfig.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/org/retest/rebazer/config/GithubConfig.java diff --git a/src/main/java/org/retest/rebazer/config/GithubConfig.java b/src/main/java/org/retest/rebazer/config/GithubConfig.java new file mode 100644 index 0000000..e1bf996 --- /dev/null +++ b/src/main/java/org/retest/rebazer/config/GithubConfig.java @@ -0,0 +1,21 @@ +package org.retest.rebazer.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class GithubConfig { + + private final static String baseUrl = "https://api.github.com/"; + + @Autowired + private RebazerConfig config; + + @Bean + public RestTemplate githubTemplate( final RestTemplateBuilder builder ) { + return builder.basicAuthorization( config.getUser(), config.getPass() ).rootUri( baseUrl ).build(); + } +} From 02cc88064e2189e9bc2fa220a5e579c9311b1549 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Mon, 8 Jan 2018 17:16:51 +0100 Subject: [PATCH 02/86] Change repoUrl to support github --- src/main/java/org/retest/rebazer/service/RebaseService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 01efffb..446f69c 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -42,7 +42,8 @@ public RebaseService( final RebazerConfig config ) { config.getRepos().forEach( repo -> { final File repoFolder = new File( config.getWorkspace(), repo.getName() ); Git localRepo = null; - final String repoUrl = "https://bitbucket.org/" + config.getTeam() + "/" + repo.getName() + ".git"; + // final String repoUrl = "https://bitbucket.org/" + config.getTeam() + "/" + repo.getName() + ".git"; + final String repoUrl = "https://github.com/" + config.getTeam() + "/" + repo.getName() + ".git"; repo.setUrl( repoUrl ); repo.setCredentials( credentials ); From 028476e254be89e0abfb56c5f490499be25dc90d Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Mon, 8 Jan 2018 17:17:49 +0100 Subject: [PATCH 03/86] Add GithubService to handle PR conditions --- .../retest/rebazer/service/GithubService.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/main/java/org/retest/rebazer/service/GithubService.java diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java new file mode 100644 index 0000000..25d5138 --- /dev/null +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -0,0 +1,56 @@ +package org.retest.rebazer.service; + +import java.util.List; + +import org.retest.rebazer.config.RebazerConfig; +import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.domain.PullRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) +public class GithubService { + + private RestTemplate githubTemplate; + + private RebazerConfig config; + + @Scheduled( fixedDelay = 60 * 1000 ) + public void pollGithub() { + for ( final Repository repo : config.getRepos() ) { + log.info( "Processing {}.", repo ); + for ( final PullRequest pr : getAllPullRequests( repo ) ) { + handlePR( repo, pr ); + } + } + } + + private void handlePR( final Repository repo, final PullRequest pullRequest ) {} + + private List getAllPullRequests( final Repository repo ) { + final String urlPath = "/repos/" + config.getTeam() + "/" + repo.getName() + "/pulls"; + final DocumentContext jp = jsonPathForPath( urlPath ); + return parsePullRequestsJson( repo, urlPath, jp ); + } + + private static List parsePullRequestsJson( final Repository repo, final String urlPath, + final DocumentContext jp ) { + return null; + } + + private DocumentContext jsonPathForPath( final String urlPath ) { + final String json = githubTemplate.getForObject( urlPath, String.class ); + return JsonPath.parse( json ); + } + +} From 049ccd4279b7d942c40aafcee2522ef423aa1370 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Mon, 8 Jan 2018 17:20:09 +0100 Subject: [PATCH 04/86] Edit method to parse PullRequests as ArrayList --- .../retest/rebazer/service/GithubService.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 25d5138..dfb2212 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -1,5 +1,6 @@ package org.retest.rebazer.service; +import java.util.ArrayList; import java.util.List; import org.retest.rebazer.config.RebazerConfig; @@ -45,7 +46,24 @@ private List getAllPullRequests( final Repository repo ) { private static List parsePullRequestsJson( final Repository repo, final String urlPath, final DocumentContext jp ) { - return null; + final List pullRequestAmount = jp.read( "$..number" ); + final int numPullRequests = pullRequestAmount.size(); + final List results = new ArrayList<>( numPullRequests ); + for ( int i = 0; i < numPullRequests; i++ ) { + final int id = pullRequestAmount.get( i ); + final String source = jp.read( "$.[" + i + "].head.ref" ); + final String destination = jp.read( "$.[" + i + "].base.ref" ); + final String lastUpdate = jp.read( "$.[" + i + "].updated_at" ); + results.add( PullRequest.builder() // + .id( id ) // + .repo( repo.getName() ) // + .source( source ) // + .destination( destination ) // + .url( urlPath + "/" + id ) // + .lastUpdate( lastUpdate ) // + .build() ); // + } + return results; } private DocumentContext jsonPathForPath( final String urlPath ) { From d1de03b6913ef4a054181ca619bd432c8cb18b9f Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Mon, 8 Jan 2018 17:22:13 +0100 Subject: [PATCH 05/86] Add condition to handle approved PullRequests *parse json to search for the correct state --- .../retest/rebazer/service/GithubService.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index dfb2212..0eac14b 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -36,7 +36,25 @@ public void pollGithub() { } } - private void handlePR( final Repository repo, final PullRequest pullRequest ) {} + private void handlePR( final Repository repo, final PullRequest pullRequest ) { + if ( !isApproved( pullRequest ) ) { + log.info( "Waiting for approval of {}.", pullRequest ); + } + } + + private boolean isApproved( final PullRequest pullRequest ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/reviews" ); + final List states = jp.read( "$..state" ); + boolean approved = false; + for ( final String state : states ) { + if ( state.equals( "APPROVED" ) ) { + approved = true; + } else { + approved = false; + } + } + return approved; + } private List getAllPullRequests( final Repository repo ) { final String urlPath = "/repos/" + config.getTeam() + "/" + repo.getName() + "/pulls"; From 00f799a8a608b85177015c93bf9c5fc79c4b77f1 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Mon, 8 Jan 2018 17:28:33 +0100 Subject: [PATCH 06/86] Add methods to check if rebaseNeeded(PullRequest) --- .../retest/rebazer/service/GithubService.java | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 0eac14b..efd90f1 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -37,7 +37,9 @@ public void pollGithub() { } private void handlePR( final Repository repo, final PullRequest pullRequest ) { - if ( !isApproved( pullRequest ) ) { + if ( rebaseNeeded( pullRequest ) ) { + //TODO call method to rebase(pullRequest) + } else if ( !isApproved( pullRequest ) ) { log.info( "Waiting for approval of {}.", pullRequest ); } } @@ -56,6 +58,33 @@ private boolean isApproved( final PullRequest pullRequest ) { return approved; } + private boolean rebaseNeeded( final PullRequest pullRequest ) { + return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest ) ); + } + + private String getHeadOfBranch( final PullRequest pullRequest ) { + final String url = "/repos/" + config.getTeam() + "/" + pullRequest.getRepo() + "/"; + return jsonPathForPath( url + "git/refs/heads/" + pullRequest.getDestination() ).read( "$.object.sha" ); + } + + private String getLastCommonCommitId( final PullRequest pullRequest ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); + + final List commitIds = jp.read( "$..sha" ); + final List parentIds = jp.read( "$..parents..sha" ); + + // return parentIds.stream().filter( parent -> !commitIds.contains( parent ) ).findFirst() + // .orElseThrow( IllegalStateException::new ); + for ( final String parent : parentIds ) { + if ( commitIds.contains( parent ) ) { + return parent; + } else { + throw new IllegalStateException(); + } + } + return null; + } + private List getAllPullRequests( final Repository repo ) { final String urlPath = "/repos/" + config.getTeam() + "/" + repo.getName() + "/pulls"; final DocumentContext jp = jsonPathForPath( urlPath ); From 1cc50bfd046a29494a5a2f75ee724efee8bba9e4 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Mon, 8 Jan 2018 17:38:40 +0100 Subject: [PATCH 07/86] Call method to rebase a repo --- .../java/org/retest/rebazer/service/GithubService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index efd90f1..eab4bae 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -25,6 +25,7 @@ public class GithubService { private RestTemplate githubTemplate; private RebazerConfig config; + private final RebaseService rebaseService; @Scheduled( fixedDelay = 60 * 1000 ) public void pollGithub() { @@ -38,7 +39,7 @@ public void pollGithub() { private void handlePR( final Repository repo, final PullRequest pullRequest ) { if ( rebaseNeeded( pullRequest ) ) { - //TODO call method to rebase(pullRequest) + rebase( repo, pullRequest ); } else if ( !isApproved( pullRequest ) ) { log.info( "Waiting for approval of {}.", pullRequest ); } @@ -118,4 +119,9 @@ private DocumentContext jsonPathForPath( final String urlPath ) { return JsonPath.parse( json ); } + private void rebase( final Repository repo, final PullRequest pullRequest ) { + rebaseService.rebase( repo, pullRequest ); + //TODO method to addComment( pullRequest ) if a mergeConflict happens; + } + } From de555658b21d79bd0d81884a5170edabd553288f Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Tue, 9 Jan 2018 07:53:59 +0100 Subject: [PATCH 08/86] Add method to merge(PullRequest) into destination --- .../retest/rebazer/service/GithubService.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index eab4bae..08402c6 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -1,7 +1,9 @@ package org.retest.rebazer.service; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.Repository; @@ -38,10 +40,14 @@ public void pollGithub() { } private void handlePR( final Repository repo, final PullRequest pullRequest ) { + log.debug( "Processing {}.", pullRequest ); + if ( rebaseNeeded( pullRequest ) ) { rebase( repo, pullRequest ); } else if ( !isApproved( pullRequest ) ) { log.info( "Waiting for approval of {}.", pullRequest ); + } else { + merge( pullRequest ); } } @@ -86,6 +92,17 @@ private String getLastCommonCommitId( final PullRequest pullRequest ) { return null; } + private void merge( final PullRequest pullRequest ) { + log.warn( "Merging pull request {}", pullRequest ); + final String message = String.format( "Merged in %s (pull request #%d) by ReBaZer", pullRequest.getSource(), + pullRequest.getId() ); + final Map request = new HashMap<>(); + request.put( "commit_title", message ); + request.put( "merge_method", "merge" ); + + githubTemplate.put( pullRequest.getUrl() + "/merge", request, Object.class ); + } + private List getAllPullRequests( final Repository repo ) { final String urlPath = "/repos/" + config.getTeam() + "/" + repo.getName() + "/pulls"; final DocumentContext jp = jsonPathForPath( urlPath ); From 84ae05725d0096022d775942754b8264a7bd225b Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Tue, 9 Jan 2018 08:05:21 +0100 Subject: [PATCH 09/86] Add comment if a merge conflict happens --- .../org/retest/rebazer/service/GithubService.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 08402c6..13f16e8 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -137,8 +137,15 @@ private DocumentContext jsonPathForPath( final String urlPath ) { } private void rebase( final Repository repo, final PullRequest pullRequest ) { - rebaseService.rebase( repo, pullRequest ); - //TODO method to addComment( pullRequest ) if a mergeConflict happens; + if ( !rebaseService.rebase( repo, pullRequest ) ) { + addComment( pullRequest ); + } + } + + private void addComment( final PullRequest pullRequest ) { + final Map request = new HashMap<>(); + request.put( "body", "This pull request needs some manual love ..." ); + githubTemplate.put( pullRequest.getUrl() + "/comments", request, String.class ); } } From 1ff00c8e996b4b212c5170206d4d00d8ffec24f7 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Tue, 9 Jan 2018 10:06:10 +0100 Subject: [PATCH 10/86] Add GithubServiceTest and change visibilty of methods *to test rebaseNeeded(PullRequest) *to test isApproved(PullRequest) *to test getAllPullRequests(Repository) *add json to test GithubService methods *make objects immutable --- .../retest/rebazer/service/GithubService.java | 14 +-- .../rebazer/service/GithubServiceTest.java | 105 ++++++++++++++++++ .../service/githubservicetest/response.json | 12 ++ 3 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 src/test/java/org/retest/rebazer/service/GithubServiceTest.java create mode 100644 src/test/resources/org/retest/rebazer/service/githubservicetest/response.json diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 13f16e8..6a8b9c5 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -24,9 +24,9 @@ @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class GithubService { - private RestTemplate githubTemplate; + private final RestTemplate githubTemplate; - private RebazerConfig config; + private final RebazerConfig config; private final RebaseService rebaseService; @Scheduled( fixedDelay = 60 * 1000 ) @@ -51,7 +51,7 @@ private void handlePR( final Repository repo, final PullRequest pullRequest ) { } } - private boolean isApproved( final PullRequest pullRequest ) { + boolean isApproved( final PullRequest pullRequest ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/reviews" ); final List states = jp.read( "$..state" ); boolean approved = false; @@ -65,16 +65,16 @@ private boolean isApproved( final PullRequest pullRequest ) { return approved; } - private boolean rebaseNeeded( final PullRequest pullRequest ) { + boolean rebaseNeeded( final PullRequest pullRequest ) { return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest ) ); } - private String getHeadOfBranch( final PullRequest pullRequest ) { + String getHeadOfBranch( final PullRequest pullRequest ) { final String url = "/repos/" + config.getTeam() + "/" + pullRequest.getRepo() + "/"; return jsonPathForPath( url + "git/refs/heads/" + pullRequest.getDestination() ).read( "$.object.sha" ); } - private String getLastCommonCommitId( final PullRequest pullRequest ) { + String getLastCommonCommitId( final PullRequest pullRequest ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); final List commitIds = jp.read( "$..sha" ); @@ -103,7 +103,7 @@ private void merge( final PullRequest pullRequest ) { githubTemplate.put( pullRequest.getUrl() + "/merge", request, Object.class ); } - private List getAllPullRequests( final Repository repo ) { + List getAllPullRequests( final Repository repo ) { final String urlPath = "/repos/" + config.getTeam() + "/" + repo.getName() + "/pulls"; final DocumentContext jp = jsonPathForPath( urlPath ); return parsePullRequestsJson( repo, urlPath, jp ); diff --git a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java new file mode 100644 index 0000000..15f1063 --- /dev/null +++ b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java @@ -0,0 +1,105 @@ +package org.retest.rebazer.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.retest.rebazer.config.RebazerConfig; +import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.domain.PullRequest; +import org.springframework.web.client.RestTemplate; + +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; + +public class GithubServiceTest { + + RestTemplate githubTemplate; + RebazerConfig config; + + GithubService cut; + + @Before + public void setUp() { + githubTemplate = mock( RestTemplate.class ); + config = mock( RebazerConfig.class ); + final RebaseService rebaseService = mock( RebaseService.class ); + + cut = new GithubService( githubTemplate, config, rebaseService ); + } + + @Test + public void rebaseNeeded_should_return_false_if_headOfBranch_is_equal_to_lastCommonCommitId() { + final PullRequest pullRequest = mock( PullRequest.class ); + final GithubService cut = mock( GithubService.class ); + final String head = "12325345923759135"; + when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); + when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( head ); + when( cut.rebaseNeeded( pullRequest ) ).thenCallRealMethod(); + + assertThat( cut.rebaseNeeded( pullRequest ) ).isFalse(); + } + + @Test + public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCommonCommitId() { + final PullRequest pullRequest = mock( PullRequest.class ); + final GithubService cut = mock( GithubService.class ); + final String head = "12325345923759135"; + final String lcci = "21342343253253452"; + when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); + when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( lcci ); + when( cut.rebaseNeeded( pullRequest ) ).thenCallRealMethod(); + + assertThat( cut.rebaseNeeded( pullRequest ) ).isTrue(); + } + + @Test + public void isApproved_should_return_false_if_approved_is_false() { + final PullRequest pullRequest = mock( PullRequest.class ); + final String json = "{participants: [{\"state\": \"CHANGES_REQUESTED\"}]}\""; + when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + + assertThat( cut.isApproved( pullRequest ) ).isFalse(); + } + + @Test + public void isApproved_should_return_ture_if_approved_is_true() { + final PullRequest pullRequest = mock( PullRequest.class ); + final String json = "{participants: [{\"state\": \"APPROVED\"}]}\""; + when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + + assertThat( cut.isApproved( pullRequest ) ).isTrue(); + } + + @Test + public void getAllPullRequests_should_return_all_pull_requests_as_list() throws IOException { + final Repository repo = mock( Repository.class ); + final String json = new String( Files.readAllBytes( + Paths.get( "src/test/resources/org/retest/rebazer/service/githubservicetest/response.json" ) ) ); + final DocumentContext documentContext = JsonPath.parse( json ); + when( config.getTeam() ).thenReturn( "test_team" ); + when( repo.getName() ).thenReturn( "test_repo_name" ); + when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + + final int expectedId = (int) documentContext.read( "$.[0].number" ); + final String expectedUrl = "/repos/" + config.getTeam() + "/" + repo.getName() + "/pulls/" + expectedId; + final List expected = Arrays.asList( PullRequest.builder().id( expectedId ).repo( repo.getName() ) + .source( documentContext.read( "$.[0].head.ref" ) ) + .destination( documentContext.read( "$.[0].base.ref" ) ).url( expectedUrl ) + .lastUpdate( documentContext.read( "$.[0].updated_at" ) ).build() ); + final List actual = cut.getAllPullRequests( repo ); + + assertThat( actual ).isEqualTo( expected ); + } + +} diff --git a/src/test/resources/org/retest/rebazer/service/githubservicetest/response.json b/src/test/resources/org/retest/rebazer/service/githubservicetest/response.json new file mode 100644 index 0000000..24f5307 --- /dev/null +++ b/src/test/resources/org/retest/rebazer/service/githubservicetest/response.json @@ -0,0 +1,12 @@ +[ + { + "number": 2, + "head": { + "ref": "test/source-branch" + }, + "base": { + "ref": "master" + }, + "updated_at": "yyyy-MM-ddThh:mm:ss.SSSZZ" + } +] \ No newline at end of file From 9f937286a695905b3022433cb1c95b8270a57355 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Tue, 9 Jan 2018 12:29:03 +0100 Subject: [PATCH 11/86] Add greenBuildExists(PullRequest) and add test *to check if there are successful builds for the PullRequest --- .../retest/rebazer/service/GithubService.java | 11 ++++++++- .../rebazer/service/GithubServiceTest.java | 24 ++++++++++++++++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 6a8b9c5..dbcafc2 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -42,7 +42,9 @@ public void pollGithub() { private void handlePR( final Repository repo, final PullRequest pullRequest ) { log.debug( "Processing {}.", pullRequest ); - if ( rebaseNeeded( pullRequest ) ) { + if ( !greenBuildExists( pullRequest ) ) { + log.info( "Waiting for green build of {}.", pullRequest ); + } else if ( rebaseNeeded( pullRequest ) ) { rebase( repo, pullRequest ); } else if ( !isApproved( pullRequest ) ) { log.info( "Waiting for approval of {}.", pullRequest ); @@ -103,6 +105,13 @@ private void merge( final PullRequest pullRequest ) { githubTemplate.put( pullRequest.getUrl() + "/merge", request, Object.class ); } + boolean greenBuildExists( final PullRequest pullRequest ) { + final String urlPath = "/repos/" + config.getTeam() + "/" + pullRequest.getRepo() + "/commits/" + + pullRequest.getSource() + "/status"; + final DocumentContext jp = jsonPathForPath( urlPath ); + return jp.> read( "$.statuses[*].state" ).stream().anyMatch( s -> s.equals( "success" ) ); + } + List getAllPullRequests( final Repository repo ) { final String urlPath = "/repos/" + config.getTeam() + "/" + repo.getName() + "/pulls"; final DocumentContext jp = jsonPathForPath( urlPath ); diff --git a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java index 15f1063..b5d92f0 100644 --- a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java @@ -66,21 +66,39 @@ public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCo @Test public void isApproved_should_return_false_if_approved_is_false() { final PullRequest pullRequest = mock( PullRequest.class ); - final String json = "{participants: [{\"state\": \"CHANGES_REQUESTED\"}]}\""; + final String json = "{review: [{\"state\": \"CHANGES_REQUESTED\"}]}\""; when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.isApproved( pullRequest ) ).isFalse(); } @Test - public void isApproved_should_return_ture_if_approved_is_true() { + public void isApproved_should_return_true_if_approved_is_true() { final PullRequest pullRequest = mock( PullRequest.class ); - final String json = "{participants: [{\"state\": \"APPROVED\"}]}\""; + final String json = "{review: [{\"state\": \"APPROVED\"}]}\""; when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.isApproved( pullRequest ) ).isTrue(); } + @Test + public void greenBuildExists_should_return_false_if_state_is_failed() { + final PullRequest pullRequest = mock( PullRequest.class ); + final String json = "{statuses: [{\"state\": \"failure_or_error\"}]}"; + when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + + assertThat( cut.greenBuildExists( pullRequest ) ).isFalse(); + } + + @Test + public void greenBuildExists_should_return_true_if_state_is_successful() { + final PullRequest pullRequest = mock( PullRequest.class ); + final String json = "{statuses: [{\"state\": \"success\"}]}"; + when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + + assertThat( cut.greenBuildExists( pullRequest ) ).isTrue(); + } + @Test public void getAllPullRequests_should_return_all_pull_requests_as_list() throws IOException { final Repository repo = mock( Repository.class ); From bc1481e0297b908242a8f43fa76e16de4b4c083e Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Tue, 16 Jan 2018 11:23:02 +0100 Subject: [PATCH 12/86] Edit addComment and add pullRequestLastUpdateStore --- .../retest/rebazer/service/GithubService.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index dbcafc2..58031e2 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -28,9 +28,11 @@ public class GithubService { private final RebazerConfig config; private final RebaseService rebaseService; + private final PullRequestLastUpdateStore pullRequestLastUpdateStore; @Scheduled( fixedDelay = 60 * 1000 ) public void pollGithub() { + //TODO add condition to seperate the service and extract the handling into an extra class for ( final Repository repo : config.getRepos() ) { log.info( "Processing {}.", repo ); for ( final PullRequest pr : getAllPullRequests( repo ) ) { @@ -42,17 +44,30 @@ public void pollGithub() { private void handlePR( final Repository repo, final PullRequest pullRequest ) { log.debug( "Processing {}.", pullRequest ); - if ( !greenBuildExists( pullRequest ) ) { + if ( pullRequestLastUpdateStore.isHandled( repo, pullRequest ) ) { + log.info( "{} is unchanged since last run (last change: {}).", pullRequest, + pullRequestLastUpdateStore.getLastDate( repo, pullRequest ) ); + + } else if ( !greenBuildExists( pullRequest ) ) { log.info( "Waiting for green build of {}.", pullRequest ); + pullRequestLastUpdateStore.setHandled( repo, pullRequest ); + } else if ( rebaseNeeded( pullRequest ) ) { rebase( repo, pullRequest ); + pullRequestLastUpdateStore.setHandled( repo, pullRequest ); + } else if ( !isApproved( pullRequest ) ) { log.info( "Waiting for approval of {}.", pullRequest ); + pullRequestLastUpdateStore.setHandled( repo, pullRequest ); + } else { + log.info( "Merging pull request " + pullRequest ); merge( pullRequest ); + pullRequestLastUpdateStore.resetAllInThisRepo( repo ); } } + //TODO change visibilty of redundant service methods to public and extract an interface boolean isApproved( final PullRequest pullRequest ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/reviews" ); final List states = jp.read( "$..state" ); @@ -154,7 +169,8 @@ private void rebase( final Repository repo, final PullRequest pullRequest ) { private void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "body", "This pull request needs some manual love ..." ); - githubTemplate.put( pullRequest.getUrl() + "/comments", request, String.class ); + githubTemplate.postForObject( "/repos/" + config.getTeam() + "/" + pullRequest.getRepo() + "/issues/" + + pullRequest.getId() + "/comments", request, String.class ); } } From 67f40253577beb1b854ff266741efa7d09589fec Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Wed, 24 Jan 2018 11:05:51 +0100 Subject: [PATCH 13/86] Add getLatestUpdate and test after rebase --- .../retest/rebazer/service/GithubService.java | 16 +++++++++++++++- .../rebazer/service/GithubServiceTest.java | 13 ++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 58031e2..ceaba7b 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -54,7 +54,8 @@ private void handlePR( final Repository repo, final PullRequest pullRequest ) { } else if ( rebaseNeeded( pullRequest ) ) { rebase( repo, pullRequest ); - pullRequestLastUpdateStore.setHandled( repo, pullRequest ); + // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called + pullRequestLastUpdateStore.setHandled( repo, getLatestUpdate( pullRequest ) ); } else if ( !isApproved( pullRequest ) ) { log.info( "Waiting for approval of {}.", pullRequest ); @@ -67,6 +68,19 @@ private void handlePR( final Repository repo, final PullRequest pullRequest ) { } } + PullRequest getLatestUpdate( final PullRequest pullRequest ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); + final PullRequest updatedPullRequest = PullRequest.builder() // + .id( pullRequest.getId() ) // + .repo( pullRequest.getRepo() ) // + .source( pullRequest.getSource() ) // + .destination( pullRequest.getDestination() ) // + .url( pullRequest.getUrl() ) // + .lastUpdate( jp.read( "$.updated_at" ) ) // + .build(); + return updatedPullRequest; + } + //TODO change visibilty of redundant service methods to public and extract an interface boolean isApproved( final PullRequest pullRequest ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/reviews" ); diff --git a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java index b5d92f0..4e16698 100644 --- a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java @@ -24,6 +24,7 @@ public class GithubServiceTest { + PullRequestLastUpdateStore pullRequestUpdateStates; RestTemplate githubTemplate; RebazerConfig config; @@ -34,8 +35,9 @@ public void setUp() { githubTemplate = mock( RestTemplate.class ); config = mock( RebazerConfig.class ); final RebaseService rebaseService = mock( RebaseService.class ); + pullRequestUpdateStates = mock( PullRequestLastUpdateStore.class ); - cut = new GithubService( githubTemplate, config, rebaseService ); + cut = new GithubService( githubTemplate, config, rebaseService, null ); } @Test @@ -120,4 +122,13 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws assertThat( actual ).isEqualTo( expected ); } + @Test + public void getLatestUpdate_should_return_updated_PullRequest() { + final PullRequest pullRequest = mock( PullRequest.class ); + final String json = "{\"updated_at\": \"someTimestamp\"}"; + when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + + assertThat( cut.getLatestUpdate( pullRequest ).getLastUpdate() ).isEqualTo( "someTimestamp" ); + } + } From e1ebae1da423e310d500eb7cf98ae11fd836fdc4 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Wed, 24 Jan 2018 11:13:02 +0100 Subject: [PATCH 14/86] Adapt yml.example for multiple services --- src/main/resources/application.yml.example | 31 ++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/main/resources/application.yml.example b/src/main/resources/application.yml.example index eb764e5..ac1cf4e 100644 --- a/src/main/resources/application.yml.example +++ b/src/main/resources/application.yml.example @@ -3,13 +3,28 @@ spring: web-environment: false rebazer: - team: your_company - user: service_user - pass: dont_use_this_pass_at_home workspace: ./rebazer-workspace garbageCollectionCountdown: 20 - repos: - - name: the_repo_name - branch: master - - name: the_other_repo_name - branch: master + pollInterval: 10000 + services: + - type: bitbucket + url: https://bitbucket.org/ + team: + name: your_company + user: service_user + pass: dont_use_this_pass_at_home + repos: + - name: blub + branch: blub + - name: bla + branch: bla + + - type: github + url: https://github.com/ + team: + name: your_company + user: service_user + pass: dont_use_this_pass_at_home + repos: + - name: foo + branch: foo From 5445e1347350b17cfd294f457a27b83c14a277a7 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Wed, 24 Jan 2018 11:20:36 +0100 Subject: [PATCH 15/86] Extend RebazerConfig to match yaml *add empty interface Provider --- .../retest/rebazer/config/RebazerConfig.java | 24 +++++++++++++++---- .../org/retest/rebazer/service/Provider.java | 5 ++++ 2 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/retest/rebazer/service/Provider.java diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 580230d..2f3fa83 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -4,6 +4,7 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.transport.CredentialsProvider; +import org.retest.rebazer.service.Provider; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -13,12 +14,10 @@ @Configuration @ConfigurationProperties( "rebazer" ) public class RebazerConfig { - private String team; - private String user; - private String pass; + private List services; private String workspace = "./rebazer-workspace"; - private List repos; private int garbageCollectionCountdown = 20; + private int pollInterval; @Data public static class Repository { @@ -33,4 +32,21 @@ public String toString() { return "Repo " + name + " (" + url + ")"; } } + + @Data + public static class Team { + private String id; + private String name; + private String user; + private String pass; + private List repos; + } + + @Data + public static class Services { + private String type; + private String url; + private Team team; + private Provider provider; + } } diff --git a/src/main/java/org/retest/rebazer/service/Provider.java b/src/main/java/org/retest/rebazer/service/Provider.java new file mode 100644 index 0000000..ca8a287 --- /dev/null +++ b/src/main/java/org/retest/rebazer/service/Provider.java @@ -0,0 +1,5 @@ +package org.retest.rebazer.service; + +public interface Provider { + +} From f048322686824defebaeb7a92f350a574ad18c30 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Wed, 24 Jan 2018 11:43:05 +0100 Subject: [PATCH 16/86] Extract polling and edit interface *make methods public to use interface *add methods to Provider *implement services *create class for polling *adapt polling to get config Objects --- .../rebazer/service/BitbucketService.java | 73 ++++++------------ .../retest/rebazer/service/GithubService.java | 75 ++++++------------- .../rebazer/service/HandleServices.java | 75 +++++++++++++++++++ .../org/retest/rebazer/service/Provider.java | 25 +++++++ .../rebazer/service/BitbucketServiceTest.java | 1 + 5 files changed, 143 insertions(+), 106 deletions(-) create mode 100644 src/main/java/org/retest/rebazer/service/HandleServices.java diff --git a/src/main/java/org/retest/rebazer/service/BitbucketService.java b/src/main/java/org/retest/rebazer/service/BitbucketService.java index 80120f0..a208c2e 100644 --- a/src/main/java/org/retest/rebazer/service/BitbucketService.java +++ b/src/main/java/org/retest/rebazer/service/BitbucketService.java @@ -9,7 +9,6 @@ import org.retest.rebazer.config.RebazerConfig.Repository; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @@ -17,58 +16,19 @@ import com.jayway.jsonpath.JsonPath; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Service @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) -public class BitbucketService { +public class BitbucketService implements Provider { private final RestTemplate bitbucketTemplate; private final RestTemplate bitbucketLegacyTemplate; private final RebazerConfig config; private final RebaseService rebaseService; - private final PullRequestLastUpdateStore pullRequestLastUpdateStore; - - @Scheduled( fixedDelay = 60 * 1000 ) - public void pollBitbucket() { - for ( final Repository repo : config.getRepos() ) { - log.debug( "Processing {}.", repo ); - for ( final PullRequest pr : getAllPullRequests( repo ) ) { - handlePR( repo, pr ); - } - } - } - - private void handlePR( final Repository repo, final PullRequest pullRequest ) { - log.debug( "Processing {}.", pullRequest ); - - if ( pullRequestLastUpdateStore.isHandled( repo, pullRequest ) ) { - log.info( "{} is unchanged since last run (last change: {}).", pullRequest, - pullRequestLastUpdateStore.getLastDate( repo, pullRequest ) ); - - } else if ( !greenBuildExists( pullRequest ) ) { - log.info( "Waiting for green build of {}.", pullRequest ); - pullRequestLastUpdateStore.setHandled( repo, pullRequest ); - - } else if ( rebaseNeeded( pullRequest ) ) { - rebase( repo, pullRequest ); - // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called - pullRequestLastUpdateStore.setHandled( repo, getLatestUpdate( pullRequest ) ); - - } else if ( !isApproved( pullRequest ) ) { - log.info( "Waiting for approval of {}.", pullRequest ); - pullRequestLastUpdateStore.setHandled( repo, pullRequest ); - - } else { - log.info( "Merging pull request " + pullRequest ); - merge( pullRequest ); - pullRequestLastUpdateStore.resetAllInThisRepo( repo ); - } - } - PullRequest getLatestUpdate( final PullRequest pullRequest ) { + @Override + public PullRequest getLatestUpdate( final PullRequest pullRequest ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); final PullRequest updatedPullRequest = PullRequest.builder() // .id( pullRequest.getId() ) // @@ -81,21 +41,25 @@ PullRequest getLatestUpdate( final PullRequest pullRequest ) { return updatedPullRequest; } - boolean isApproved( final PullRequest pullRequest ) { + @Override + public boolean isApproved( final PullRequest pullRequest ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); return jp.> read( "$.participants[*].approved" ).stream().anyMatch( approved -> approved ); } - boolean rebaseNeeded( final PullRequest pullRequest ) { + @Override + public boolean rebaseNeeded( final PullRequest pullRequest ) { return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest ) ); } - String getHeadOfBranch( final PullRequest pullRequest ) { + @Override + public String getHeadOfBranch( final PullRequest pullRequest ) { final String url = "/repositories/" + config.getTeam() + "/" + pullRequest.getRepo() + "/"; return jsonPathForPath( url + "refs/branches/" + pullRequest.getDestination() ).read( "$.target.hash" ); } - String getLastCommonCommitId( final PullRequest pullRequest ) { + @Override + public String getLastCommonCommitId( final PullRequest pullRequest ) { DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); final int pageLength = jp.read( "$.pagelen" ); @@ -113,7 +77,8 @@ String getLastCommonCommitId( final PullRequest pullRequest ) { .orElseThrow( IllegalStateException::new ); } - private void merge( final PullRequest pullRequest ) { + @Override + public void merge( final PullRequest pullRequest ) { final String message = String.format( "Merged in %s (pull request #%d) by ReBaZer", pullRequest.getSource(), pullRequest.getId() ); // TODO add approver to message? @@ -125,12 +90,14 @@ private void merge( final PullRequest pullRequest ) { bitbucketTemplate.postForObject( pullRequest.getUrl() + "/merge", request, Object.class ); } - boolean greenBuildExists( final PullRequest pullRequest ) { + @Override + public boolean greenBuildExists( final PullRequest pullRequest ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/statuses" ); return jp.> read( "$.values[*].state" ).stream().anyMatch( s -> s.equals( "SUCCESSFUL" ) ); } - List getAllPullRequests( final Repository repo ) { + @Override + public List getAllPullRequests( final Repository repo ) { final String urlPath = "/repositories/" + config.getTeam() + "/" + repo.getName() + "/pullrequests"; final DocumentContext jp = jsonPathForPath( urlPath ); return parsePullRequestsJson( repo, urlPath, jp ); @@ -162,13 +129,15 @@ DocumentContext jsonPathForPath( final String urlPath ) { return JsonPath.parse( json ); } - private void rebase( final Repository repo, final PullRequest pullRequest ) { + @Override + public void rebase( final Repository repo, final PullRequest pullRequest ) { if ( !rebaseService.rebase( repo, pullRequest ) ) { addComment( pullRequest ); } } - private void addComment( final PullRequest pullRequest ) { + @Override + public void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "content", "This pull request needs some manual love ..." ); bitbucketLegacyTemplate.postForObject( pullRequest.getUrl() + "/comments", request, String.class ); diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index ceaba7b..1b442e4 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -9,7 +9,6 @@ import org.retest.rebazer.config.RebazerConfig.Repository; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @@ -17,58 +16,18 @@ import com.jayway.jsonpath.JsonPath; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Service @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) -public class GithubService { +public class GithubService implements Provider { private final RestTemplate githubTemplate; private final RebazerConfig config; private final RebaseService rebaseService; - private final PullRequestLastUpdateStore pullRequestLastUpdateStore; - - @Scheduled( fixedDelay = 60 * 1000 ) - public void pollGithub() { - //TODO add condition to seperate the service and extract the handling into an extra class - for ( final Repository repo : config.getRepos() ) { - log.info( "Processing {}.", repo ); - for ( final PullRequest pr : getAllPullRequests( repo ) ) { - handlePR( repo, pr ); - } - } - } - - private void handlePR( final Repository repo, final PullRequest pullRequest ) { - log.debug( "Processing {}.", pullRequest ); - - if ( pullRequestLastUpdateStore.isHandled( repo, pullRequest ) ) { - log.info( "{} is unchanged since last run (last change: {}).", pullRequest, - pullRequestLastUpdateStore.getLastDate( repo, pullRequest ) ); - - } else if ( !greenBuildExists( pullRequest ) ) { - log.info( "Waiting for green build of {}.", pullRequest ); - pullRequestLastUpdateStore.setHandled( repo, pullRequest ); - - } else if ( rebaseNeeded( pullRequest ) ) { - rebase( repo, pullRequest ); - // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called - pullRequestLastUpdateStore.setHandled( repo, getLatestUpdate( pullRequest ) ); - - } else if ( !isApproved( pullRequest ) ) { - log.info( "Waiting for approval of {}.", pullRequest ); - pullRequestLastUpdateStore.setHandled( repo, pullRequest ); - - } else { - log.info( "Merging pull request " + pullRequest ); - merge( pullRequest ); - pullRequestLastUpdateStore.resetAllInThisRepo( repo ); - } - } - PullRequest getLatestUpdate( final PullRequest pullRequest ) { + @Override + public PullRequest getLatestUpdate( final PullRequest pullRequest ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); final PullRequest updatedPullRequest = PullRequest.builder() // .id( pullRequest.getId() ) // @@ -81,8 +40,8 @@ PullRequest getLatestUpdate( final PullRequest pullRequest ) { return updatedPullRequest; } - //TODO change visibilty of redundant service methods to public and extract an interface - boolean isApproved( final PullRequest pullRequest ) { + @Override + public boolean isApproved( final PullRequest pullRequest ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/reviews" ); final List states = jp.read( "$..state" ); boolean approved = false; @@ -96,16 +55,19 @@ boolean isApproved( final PullRequest pullRequest ) { return approved; } - boolean rebaseNeeded( final PullRequest pullRequest ) { + @Override + public boolean rebaseNeeded( final PullRequest pullRequest ) { return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest ) ); } - String getHeadOfBranch( final PullRequest pullRequest ) { + @Override + public String getHeadOfBranch( final PullRequest pullRequest ) { final String url = "/repos/" + config.getTeam() + "/" + pullRequest.getRepo() + "/"; return jsonPathForPath( url + "git/refs/heads/" + pullRequest.getDestination() ).read( "$.object.sha" ); } - String getLastCommonCommitId( final PullRequest pullRequest ) { + @Override + public String getLastCommonCommitId( final PullRequest pullRequest ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); final List commitIds = jp.read( "$..sha" ); @@ -123,7 +85,8 @@ String getLastCommonCommitId( final PullRequest pullRequest ) { return null; } - private void merge( final PullRequest pullRequest ) { + @Override + public void merge( final PullRequest pullRequest ) { log.warn( "Merging pull request {}", pullRequest ); final String message = String.format( "Merged in %s (pull request #%d) by ReBaZer", pullRequest.getSource(), pullRequest.getId() ); @@ -134,14 +97,16 @@ private void merge( final PullRequest pullRequest ) { githubTemplate.put( pullRequest.getUrl() + "/merge", request, Object.class ); } - boolean greenBuildExists( final PullRequest pullRequest ) { + @Override + public boolean greenBuildExists( final PullRequest pullRequest ) { final String urlPath = "/repos/" + config.getTeam() + "/" + pullRequest.getRepo() + "/commits/" + pullRequest.getSource() + "/status"; final DocumentContext jp = jsonPathForPath( urlPath ); return jp.> read( "$.statuses[*].state" ).stream().anyMatch( s -> s.equals( "success" ) ); } - List getAllPullRequests( final Repository repo ) { + @Override + public List getAllPullRequests( final Repository repo ) { final String urlPath = "/repos/" + config.getTeam() + "/" + repo.getName() + "/pulls"; final DocumentContext jp = jsonPathForPath( urlPath ); return parsePullRequestsJson( repo, urlPath, jp ); @@ -174,13 +139,15 @@ private DocumentContext jsonPathForPath( final String urlPath ) { return JsonPath.parse( json ); } - private void rebase( final Repository repo, final PullRequest pullRequest ) { + @Override + public void rebase( final Repository repo, final PullRequest pullRequest ) { if ( !rebaseService.rebase( repo, pullRequest ) ) { addComment( pullRequest ); } } - private void addComment( final PullRequest pullRequest ) { + @Override + public void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "body", "This pull request needs some manual love ..." ); githubTemplate.postForObject( "/repos/" + config.getTeam() + "/" + pullRequest.getRepo() + "/issues/" diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java new file mode 100644 index 0000000..5f62bc4 --- /dev/null +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -0,0 +1,75 @@ +package org.retest.rebazer.service; + +import org.retest.rebazer.config.RebazerConfig; +import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.Services; +import org.retest.rebazer.config.RebazerConfig.Team; +import org.retest.rebazer.domain.PullRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) +public class HandleServices { + + private final RebazerConfig config; + private final PullRequestLastUpdateStore pullRequestLastUpdateStore; + + @Qualifier( "bitbucketService" ) + private final Provider bitbucketService; + + @Qualifier( "githubService" ) + private final Provider githubService; + + @Scheduled( fixedDelay = 60 * 1000 ) + public void pollBitbucket() { + for ( final Services service : config.getServices() ) { + if ( "bitbucket".equals( service.getType() ) ) { + service.setProvider( bitbucketService ); + final Team team = service.getTeam(); + for ( final Repository repo : team.getRepos() ) { + log.debug( "Processing {}.", repo ); + for ( final PullRequest pr : bitbucketService.getAllPullRequests( repo ) ) { + System.out.println( pr ); + // handlePR( bitbucketService, repo, pr ); + } + } + } + } + + } + + private void handlePR( final Provider provider, final Repository repo, final PullRequest pullRequest ) { + log.debug( "Processing {}.", pullRequest ); + + if ( pullRequestLastUpdateStore.isHandled( repo, pullRequest ) ) { + log.info( "{} is unchanged since last run (last change: {}).", pullRequest, + pullRequestLastUpdateStore.getLastDate( repo, pullRequest ) ); + + } else if ( !provider.greenBuildExists( pullRequest ) ) { + log.info( "Waiting for green build of {}.", pullRequest ); + pullRequestLastUpdateStore.setHandled( repo, pullRequest ); + + } else if ( provider.rebaseNeeded( pullRequest ) ) { + provider.rebase( repo, pullRequest ); + // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called + pullRequestLastUpdateStore.setHandled( repo, provider.getLatestUpdate( pullRequest ) ); + + } else if ( !provider.isApproved( pullRequest ) ) { + log.info( "Waiting for approval of {}.", pullRequest ); + pullRequestLastUpdateStore.setHandled( repo, pullRequest ); + + } else { + log.info( "Merging pull request " + pullRequest ); + provider.merge( pullRequest ); + pullRequestLastUpdateStore.resetAllInThisRepo( repo ); + } + } + +} diff --git a/src/main/java/org/retest/rebazer/service/Provider.java b/src/main/java/org/retest/rebazer/service/Provider.java index ca8a287..d5d9474 100644 --- a/src/main/java/org/retest/rebazer/service/Provider.java +++ b/src/main/java/org/retest/rebazer/service/Provider.java @@ -1,5 +1,30 @@ package org.retest.rebazer.service; +import java.util.List; + +import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.domain.PullRequest; + public interface Provider { + PullRequest getLatestUpdate( PullRequest pullRequest ); + + boolean isApproved( PullRequest pullRequest ); + + boolean rebaseNeeded( PullRequest pullRequest ); + + String getHeadOfBranch( PullRequest pullRequest ); + + String getLastCommonCommitId( PullRequest pullRequest ); + + void merge( PullRequest pullRequest ); + + boolean greenBuildExists( PullRequest pullRequest ); + + List getAllPullRequests( Repository repo ); + + void rebase( Repository repo, PullRequest pullRequest ); + + void addComment( PullRequest pullRequest ); + } diff --git a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java index 036d4ee..86deb49 100644 --- a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java @@ -122,6 +122,7 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws @Test public void getLatestUpdate_should_return_updated_PullRequest() { + final PullRequest pullRequest = mock( PullRequest.class ); final String json = "{\"updated_on\": \"someTimestamp\"}"; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); From 4df9276e2f7a9cd654a01426a832d559230b6d74 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Wed, 24 Jan 2018 11:46:49 +0100 Subject: [PATCH 17/86] Change repoUrl to get it from RebazerConfig --- .../retest/rebazer/service/RebaseService.java | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 446f69c..2659e52 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -16,6 +16,8 @@ import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.Services; +import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -35,35 +37,34 @@ public class RebaseService { public RebaseService( final RebazerConfig config ) { this.config = config; currentGcCountdown = config.getGarbageCollectionCountdown(); - - final CredentialsProvider credentials = - new UsernamePasswordCredentialsProvider( config.getUser(), config.getPass() ); - - config.getRepos().forEach( repo -> { - final File repoFolder = new File( config.getWorkspace(), repo.getName() ); - Git localRepo = null; - // final String repoUrl = "https://bitbucket.org/" + config.getTeam() + "/" + repo.getName() + ".git"; - final String repoUrl = "https://github.com/" + config.getTeam() + "/" + repo.getName() + ".git"; - repo.setUrl( repoUrl ); - repo.setCredentials( credentials ); - - if ( repoFolder.exists() ) { - localRepo = tryToOpenExistingRepoAndCheckRemote( repoFolder, repoUrl ); - if ( localRepo == null ) { - try { - FileUtils.deleteDirectory( repoFolder ); - } catch ( final IOException e ) { - throw new RuntimeException( e ); + for ( final Services services : config.getServices() ) { + final Team team = services.getTeam(); + final CredentialsProvider credentials = + new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); + team.getRepos().forEach( repo -> { + final File repoFolder = new File( config.getWorkspace(), repo.getName() ); + Git localRepo = null; + final String repoUrl = services.getUrl() + team.getName() + "/" + repo.getName() + ".git"; + repo.setUrl( repoUrl ); + repo.setCredentials( credentials ); + + if ( repoFolder.exists() ) { + localRepo = tryToOpenExistingRepoAndCheckRemote( repoFolder, repoUrl ); + if ( localRepo == null ) { + try { + FileUtils.deleteDirectory( repoFolder ); + } catch ( final IOException e ) { + throw new RuntimeException( e ); + } } } - } - if ( localRepo == null ) { - localRepo = cloneNewRepo( repoFolder, repoUrl, credentials ); - } - repo.setGit( localRepo ); - cleanUp( repo ); - } ); - + if ( localRepo == null ) { + localRepo = cloneNewRepo( repoFolder, repoUrl, credentials ); + } + repo.setGit( localRepo ); + cleanUp( repo ); + } ); + } } private static Git tryToOpenExistingRepoAndCheckRemote( final File repoFolder, final String expectedRepoUrl ) { From 609e62630f8eaf07103057ad1d1e1124d8494406 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Wed, 24 Jan 2018 12:26:32 +0100 Subject: [PATCH 18/86] Add Team to Provider methods *to match yaml configuration --- .../rebazer/service/BitbucketService.java | 23 +++++++-------- .../retest/rebazer/service/GithubService.java | 29 ++++++++++--------- .../rebazer/service/HandleServices.java | 13 +++++---- .../org/retest/rebazer/service/Provider.java | 13 +++++---- 4 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/BitbucketService.java b/src/main/java/org/retest/rebazer/service/BitbucketService.java index a208c2e..83086d1 100644 --- a/src/main/java/org/retest/rebazer/service/BitbucketService.java +++ b/src/main/java/org/retest/rebazer/service/BitbucketService.java @@ -5,8 +5,8 @@ import java.util.List; import java.util.Map; -import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -24,7 +24,6 @@ public class BitbucketService implements Provider { private final RestTemplate bitbucketTemplate; private final RestTemplate bitbucketLegacyTemplate; - private final RebazerConfig config; private final RebaseService rebaseService; @Override @@ -48,13 +47,13 @@ public boolean isApproved( final PullRequest pullRequest ) { } @Override - public boolean rebaseNeeded( final PullRequest pullRequest ) { - return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest ) ); + public boolean rebaseNeeded( final PullRequest pullRequest, final Team team ) { + return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest, team ) ); } @Override - public String getHeadOfBranch( final PullRequest pullRequest ) { - final String url = "/repositories/" + config.getTeam() + "/" + pullRequest.getRepo() + "/"; + public String getHeadOfBranch( final PullRequest pullRequest, final Team team ) { + final String url = "/repositories/" + team.getName() + "/" + pullRequest.getRepo() + "/"; return jsonPathForPath( url + "refs/branches/" + pullRequest.getDestination() ).read( "$.target.hash" ); } @@ -91,14 +90,14 @@ public void merge( final PullRequest pullRequest ) { } @Override - public boolean greenBuildExists( final PullRequest pullRequest ) { + public boolean greenBuildExists( final PullRequest pullRequest, final Team team ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/statuses" ); return jp.> read( "$.values[*].state" ).stream().anyMatch( s -> s.equals( "SUCCESSFUL" ) ); } @Override - public List getAllPullRequests( final Repository repo ) { - final String urlPath = "/repositories/" + config.getTeam() + "/" + repo.getName() + "/pullrequests"; + public List getAllPullRequests( final Repository repo, final Team team ) { + final String urlPath = "/repositories/" + team.getName() + "/" + repo.getName() + "/pullrequests"; final DocumentContext jp = jsonPathForPath( urlPath ); return parsePullRequestsJson( repo, urlPath, jp ); } @@ -130,14 +129,14 @@ DocumentContext jsonPathForPath( final String urlPath ) { } @Override - public void rebase( final Repository repo, final PullRequest pullRequest ) { + public void rebase( final Repository repo, final PullRequest pullRequest, final Team team ) { if ( !rebaseService.rebase( repo, pullRequest ) ) { - addComment( pullRequest ); + addComment( pullRequest, team ); } } @Override - public void addComment( final PullRequest pullRequest ) { + public void addComment( final PullRequest pullRequest, final Team team ) { final Map request = new HashMap<>(); request.put( "content", "This pull request needs some manual love ..." ); bitbucketLegacyTemplate.postForObject( pullRequest.getUrl() + "/comments", request, String.class ); diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 1b442e4..a52b7ec 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -5,8 +5,8 @@ import java.util.List; import java.util.Map; -import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -16,14 +16,15 @@ import com.jayway.jsonpath.JsonPath; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Service @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class GithubService implements Provider { private final RestTemplate githubTemplate; - private final RebazerConfig config; private final RebaseService rebaseService; @Override @@ -56,13 +57,13 @@ public boolean isApproved( final PullRequest pullRequest ) { } @Override - public boolean rebaseNeeded( final PullRequest pullRequest ) { - return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest ) ); + public boolean rebaseNeeded( final PullRequest pullRequest, final Team team ) { + return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest, team ) ); } @Override - public String getHeadOfBranch( final PullRequest pullRequest ) { - final String url = "/repos/" + config.getTeam() + "/" + pullRequest.getRepo() + "/"; + public String getHeadOfBranch( final PullRequest pullRequest, final Team team ) { + final String url = "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/"; return jsonPathForPath( url + "git/refs/heads/" + pullRequest.getDestination() ).read( "$.object.sha" ); } @@ -98,16 +99,16 @@ public void merge( final PullRequest pullRequest ) { } @Override - public boolean greenBuildExists( final PullRequest pullRequest ) { - final String urlPath = "/repos/" + config.getTeam() + "/" + pullRequest.getRepo() + "/commits/" + public boolean greenBuildExists( final PullRequest pullRequest, final Team team ) { + final String urlPath = "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/commits/" + pullRequest.getSource() + "/status"; final DocumentContext jp = jsonPathForPath( urlPath ); return jp.> read( "$.statuses[*].state" ).stream().anyMatch( s -> s.equals( "success" ) ); } @Override - public List getAllPullRequests( final Repository repo ) { - final String urlPath = "/repos/" + config.getTeam() + "/" + repo.getName() + "/pulls"; + public List getAllPullRequests( final Repository repo, final Team team ) { + final String urlPath = "/repos/" + team.getName() + "/" + repo.getName() + "/pulls"; final DocumentContext jp = jsonPathForPath( urlPath ); return parsePullRequestsJson( repo, urlPath, jp ); } @@ -140,17 +141,17 @@ private DocumentContext jsonPathForPath( final String urlPath ) { } @Override - public void rebase( final Repository repo, final PullRequest pullRequest ) { + public void rebase( final Repository repo, final PullRequest pullRequest, final Team team ) { if ( !rebaseService.rebase( repo, pullRequest ) ) { - addComment( pullRequest ); + addComment( pullRequest, team ); } } @Override - public void addComment( final PullRequest pullRequest ) { + public void addComment( final PullRequest pullRequest, final Team team ) { final Map request = new HashMap<>(); request.put( "body", "This pull request needs some manual love ..." ); - githubTemplate.postForObject( "/repos/" + config.getTeam() + "/" + pullRequest.getRepo() + "/issues/" + githubTemplate.postForObject( "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/issues/" + pullRequest.getId() + "/comments", request, String.class ); } diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index 5f62bc4..faa93b3 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -35,9 +35,9 @@ public void pollBitbucket() { final Team team = service.getTeam(); for ( final Repository repo : team.getRepos() ) { log.debug( "Processing {}.", repo ); - for ( final PullRequest pr : bitbucketService.getAllPullRequests( repo ) ) { + for ( final PullRequest pr : bitbucketService.getAllPullRequests( repo, team ) ) { System.out.println( pr ); - // handlePR( bitbucketService, repo, pr ); + handlePR( bitbucketService, repo, pr, team ); } } } @@ -45,19 +45,20 @@ public void pollBitbucket() { } - private void handlePR( final Provider provider, final Repository repo, final PullRequest pullRequest ) { + private void handlePR( final Provider provider, final Repository repo, final PullRequest pullRequest, + final Team team ) { log.debug( "Processing {}.", pullRequest ); if ( pullRequestLastUpdateStore.isHandled( repo, pullRequest ) ) { log.info( "{} is unchanged since last run (last change: {}).", pullRequest, pullRequestLastUpdateStore.getLastDate( repo, pullRequest ) ); - } else if ( !provider.greenBuildExists( pullRequest ) ) { + } else if ( !provider.greenBuildExists( pullRequest, team ) ) { log.info( "Waiting for green build of {}.", pullRequest ); pullRequestLastUpdateStore.setHandled( repo, pullRequest ); - } else if ( provider.rebaseNeeded( pullRequest ) ) { - provider.rebase( repo, pullRequest ); + } else if ( provider.rebaseNeeded( pullRequest, team ) ) { + provider.rebase( repo, pullRequest, team ); // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called pullRequestLastUpdateStore.setHandled( repo, provider.getLatestUpdate( pullRequest ) ); diff --git a/src/main/java/org/retest/rebazer/service/Provider.java b/src/main/java/org/retest/rebazer/service/Provider.java index d5d9474..7521b85 100644 --- a/src/main/java/org/retest/rebazer/service/Provider.java +++ b/src/main/java/org/retest/rebazer/service/Provider.java @@ -3,6 +3,7 @@ import java.util.List; import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; public interface Provider { @@ -11,20 +12,20 @@ public interface Provider { boolean isApproved( PullRequest pullRequest ); - boolean rebaseNeeded( PullRequest pullRequest ); + boolean rebaseNeeded( PullRequest pullRequest, Team team ); - String getHeadOfBranch( PullRequest pullRequest ); + String getHeadOfBranch( PullRequest pullRequest, Team team ); String getLastCommonCommitId( PullRequest pullRequest ); void merge( PullRequest pullRequest ); - boolean greenBuildExists( PullRequest pullRequest ); + boolean greenBuildExists( PullRequest pullRequest, Team team ); - List getAllPullRequests( Repository repo ); + List getAllPullRequests( Repository repo, Team team ); - void rebase( Repository repo, PullRequest pullRequest ); + void rebase( Repository repo, PullRequest pullRequest, Team team ); - void addComment( PullRequest pullRequest ); + void addComment( PullRequest pullRequest, Team team ); } From 5510b65d08859a51d4b6e543a2d391f39db6dc18 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Wed, 24 Jan 2018 12:28:55 +0100 Subject: [PATCH 19/86] Change templates to support multiple user --- .../retest/rebazer/config/BitbucketConfig.java | 15 +++++---------- .../org/retest/rebazer/config/GithubConfig.java | 11 +++-------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/BitbucketConfig.java b/src/main/java/org/retest/rebazer/config/BitbucketConfig.java index 68efc65..5d1e3f3 100644 --- a/src/main/java/org/retest/rebazer/config/BitbucketConfig.java +++ b/src/main/java/org/retest/rebazer/config/BitbucketConfig.java @@ -1,28 +1,23 @@ package org.retest.rebazer.config; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; -@Configuration public class BitbucketConfig { private final static String baseUrlV1 = "https://api.bitbucket.org/1.0"; private final static String baseUrlV2 = "https://api.bitbucket.org/2.0"; - @Autowired - private RebazerConfig config; - @Bean - public RestTemplate bitbucketLegacyTemplate( final RestTemplateBuilder builder ) { - return builder.basicAuthorization( config.getUser(), config.getPass() ).rootUri( baseUrlV1 ).build(); + public RestTemplate bitbucketLegacyTemplate( final RestTemplateBuilder builder, final String user, + final String pass ) { + return builder.basicAuthorization( user, pass ).rootUri( baseUrlV1 ).build(); } @Bean - public RestTemplate bitbucketTemplate( final RestTemplateBuilder builder ) { - return builder.basicAuthorization( config.getUser(), config.getPass() ).rootUri( baseUrlV2 ).build(); + public RestTemplate bitbucketTemplate( final RestTemplateBuilder builder, final String user, final String pass ) { + return builder.basicAuthorization( user, pass ).rootUri( baseUrlV2 ).build(); } } diff --git a/src/main/java/org/retest/rebazer/config/GithubConfig.java b/src/main/java/org/retest/rebazer/config/GithubConfig.java index e1bf996..06d5967 100644 --- a/src/main/java/org/retest/rebazer/config/GithubConfig.java +++ b/src/main/java/org/retest/rebazer/config/GithubConfig.java @@ -1,21 +1,16 @@ package org.retest.rebazer.config; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; -@Configuration public class GithubConfig { private final static String baseUrl = "https://api.github.com/"; - @Autowired - private RebazerConfig config; - @Bean - public RestTemplate githubTemplate( final RestTemplateBuilder builder ) { - return builder.basicAuthorization( config.getUser(), config.getPass() ).rootUri( baseUrl ).build(); + public RestTemplate githubTemplate( final RestTemplateBuilder builder, final String user, final String pass ) { + return builder.basicAuthorization( user, pass ).rootUri( baseUrl ).build(); } + } From d7bd76ccc3eb34987c82de538db6b85bcf8fcb02 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Wed, 24 Jan 2018 12:43:01 +0100 Subject: [PATCH 20/86] Add restTemplates to support multiple teams *edit methods to get the right RestTemplate --- .../rebazer/service/BitbucketService.java | 55 +++++++-------- .../retest/rebazer/service/GithubService.java | 50 +++++++------- .../rebazer/service/HandleServices.java | 67 ++++++++++++++----- .../org/retest/rebazer/service/Provider.java | 21 +++--- 4 files changed, 113 insertions(+), 80 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/BitbucketService.java b/src/main/java/org/retest/rebazer/service/BitbucketService.java index 83086d1..98dba4e 100644 --- a/src/main/java/org/retest/rebazer/service/BitbucketService.java +++ b/src/main/java/org/retest/rebazer/service/BitbucketService.java @@ -21,14 +21,11 @@ @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class BitbucketService implements Provider { - private final RestTemplate bitbucketTemplate; - private final RestTemplate bitbucketLegacyTemplate; - private final RebaseService rebaseService; @Override - public PullRequest getLatestUpdate( final PullRequest pullRequest ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); + public PullRequest getLatestUpdate( final PullRequest pullRequest, final RestTemplate template ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl(), template ); final PullRequest updatedPullRequest = PullRequest.builder() // .id( pullRequest.getId() ) // .repo( pullRequest.getRepo() ) // @@ -41,32 +38,34 @@ public PullRequest getLatestUpdate( final PullRequest pullRequest ) { } @Override - public boolean isApproved( final PullRequest pullRequest ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); + public boolean isApproved( final PullRequest pullRequest, final RestTemplate template ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl(), template ); return jp.> read( "$.participants[*].approved" ).stream().anyMatch( approved -> approved ); } @Override - public boolean rebaseNeeded( final PullRequest pullRequest, final Team team ) { - return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest, team ) ); + public boolean rebaseNeeded( final PullRequest pullRequest, final Team team, final RestTemplate template ) { + return !getLastCommonCommitId( pullRequest, template ).equals( getHeadOfBranch( pullRequest, team, template ) ); } @Override - public String getHeadOfBranch( final PullRequest pullRequest, final Team team ) { + public String getHeadOfBranch( final PullRequest pullRequest, final Team team, + final RestTemplate bitbucketTemplate ) { final String url = "/repositories/" + team.getName() + "/" + pullRequest.getRepo() + "/"; - return jsonPathForPath( url + "refs/branches/" + pullRequest.getDestination() ).read( "$.target.hash" ); + return jsonPathForPath( url + "refs/branches/" + pullRequest.getDestination(), bitbucketTemplate ) + .read( "$.target.hash" ); } @Override - public String getLastCommonCommitId( final PullRequest pullRequest ) { - DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); + public String getLastCommonCommitId( final PullRequest pullRequest, final RestTemplate bitbucketTemplate ) { + DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits", bitbucketTemplate ); final int pageLength = jp.read( "$.pagelen" ); final int size = jp.read( "$.size" ); final int lastPage = (pageLength + size - 1) / pageLength; if ( lastPage > 1 ) { - jp = jsonPathForPath( pullRequest.getUrl() + "/commits?page=" + lastPage ); + jp = jsonPathForPath( pullRequest.getUrl() + "/commits?page=" + lastPage, bitbucketTemplate ); } final List commitIds = jp.read( "$.values[*].hash" ); @@ -77,7 +76,7 @@ public String getLastCommonCommitId( final PullRequest pullRequest ) { } @Override - public void merge( final PullRequest pullRequest ) { + public void merge( final PullRequest pullRequest, final RestTemplate template ) { final String message = String.format( "Merged in %s (pull request #%d) by ReBaZer", pullRequest.getSource(), pullRequest.getId() ); // TODO add approver to message? @@ -86,23 +85,23 @@ public void merge( final PullRequest pullRequest ) { request.put( "message", message ); request.put( "merge_strategy", "merge_commit" ); - bitbucketTemplate.postForObject( pullRequest.getUrl() + "/merge", request, Object.class ); + template.postForObject( pullRequest.getUrl() + "/merge", request, Object.class ); } @Override - public boolean greenBuildExists( final PullRequest pullRequest, final Team team ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/statuses" ); + public boolean greenBuildExists( final PullRequest pullRequest, final Team team, final RestTemplate template ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/statuses", template ); return jp.> read( "$.values[*].state" ).stream().anyMatch( s -> s.equals( "SUCCESSFUL" ) ); } @Override - public List getAllPullRequests( final Repository repo, final Team team ) { + public List getAllPullRequests( final Repository repo, final Team team, final RestTemplate template ) { final String urlPath = "/repositories/" + team.getName() + "/" + repo.getName() + "/pullrequests"; - final DocumentContext jp = jsonPathForPath( urlPath ); + final DocumentContext jp = jsonPathForPath( urlPath, template ); return parsePullRequestsJson( repo, urlPath, jp ); } - private static List parsePullRequestsJson( final Repository repo, final String urlPath, + public static List parsePullRequestsJson( final Repository repo, final String urlPath, final DocumentContext jp ) { final int numPullRequests = (int) jp.read( "$.size" ); final List results = new ArrayList<>( numPullRequests ); @@ -123,23 +122,25 @@ private static List parsePullRequestsJson( final Repository repo, f return results; } - DocumentContext jsonPathForPath( final String urlPath ) { - final String json = bitbucketTemplate.getForObject( urlPath, String.class ); + private DocumentContext jsonPathForPath( final String urlPath, final RestTemplate template ) { + final String json = template.getForObject( urlPath, String.class ); return JsonPath.parse( json ); } @Override - public void rebase( final Repository repo, final PullRequest pullRequest, final Team team ) { + public void rebase( final Repository repo, final PullRequest pullRequest, final Team team, + final RestTemplate template ) { if ( !rebaseService.rebase( repo, pullRequest ) ) { - addComment( pullRequest, team ); + addComment( pullRequest, team, template ); } } @Override - public void addComment( final PullRequest pullRequest, final Team team ) { + public void addComment( final PullRequest pullRequest, final Team team, final RestTemplate template ) { final Map request = new HashMap<>(); request.put( "content", "This pull request needs some manual love ..." ); - bitbucketLegacyTemplate.postForObject( pullRequest.getUrl() + "/comments", request, String.class ); + + template.postForObject( pullRequest.getUrl() + "/comments", request, String.class ); } } diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index a52b7ec..4583873 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -23,13 +23,11 @@ @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class GithubService implements Provider { - private final RestTemplate githubTemplate; - private final RebaseService rebaseService; @Override - public PullRequest getLatestUpdate( final PullRequest pullRequest ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); + public PullRequest getLatestUpdate( final PullRequest pullRequest, final RestTemplate template ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl(), template ); final PullRequest updatedPullRequest = PullRequest.builder() // .id( pullRequest.getId() ) // .repo( pullRequest.getRepo() ) // @@ -42,8 +40,8 @@ public PullRequest getLatestUpdate( final PullRequest pullRequest ) { } @Override - public boolean isApproved( final PullRequest pullRequest ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/reviews" ); + public boolean isApproved( final PullRequest pullRequest, final RestTemplate template ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/reviews", template ); final List states = jp.read( "$..state" ); boolean approved = false; for ( final String state : states ) { @@ -57,19 +55,20 @@ public boolean isApproved( final PullRequest pullRequest ) { } @Override - public boolean rebaseNeeded( final PullRequest pullRequest, final Team team ) { - return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest, team ) ); + public boolean rebaseNeeded( final PullRequest pullRequest, final Team team, final RestTemplate template ) { + return !getLastCommonCommitId( pullRequest, template ).equals( getHeadOfBranch( pullRequest, team, template ) ); } @Override - public String getHeadOfBranch( final PullRequest pullRequest, final Team team ) { + public String getHeadOfBranch( final PullRequest pullRequest, final Team team, final RestTemplate template ) { final String url = "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/"; - return jsonPathForPath( url + "git/refs/heads/" + pullRequest.getDestination() ).read( "$.object.sha" ); + return jsonPathForPath( url + "git/refs/heads/" + pullRequest.getDestination(), template ) + .read( "$.object.sha" ); } @Override - public String getLastCommonCommitId( final PullRequest pullRequest ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); + public String getLastCommonCommitId( final PullRequest pullRequest, final RestTemplate template ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits", template ); final List commitIds = jp.read( "$..sha" ); final List parentIds = jp.read( "$..parents..sha" ); @@ -87,7 +86,7 @@ public String getLastCommonCommitId( final PullRequest pullRequest ) { } @Override - public void merge( final PullRequest pullRequest ) { + public void merge( final PullRequest pullRequest, final RestTemplate template ) { log.warn( "Merging pull request {}", pullRequest ); final String message = String.format( "Merged in %s (pull request #%d) by ReBaZer", pullRequest.getSource(), pullRequest.getId() ); @@ -95,25 +94,25 @@ public void merge( final PullRequest pullRequest ) { request.put( "commit_title", message ); request.put( "merge_method", "merge" ); - githubTemplate.put( pullRequest.getUrl() + "/merge", request, Object.class ); + template.put( pullRequest.getUrl() + "/merge", request, Object.class ); } @Override - public boolean greenBuildExists( final PullRequest pullRequest, final Team team ) { + public boolean greenBuildExists( final PullRequest pullRequest, final Team team, final RestTemplate template ) { final String urlPath = "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/commits/" + pullRequest.getSource() + "/status"; - final DocumentContext jp = jsonPathForPath( urlPath ); + final DocumentContext jp = jsonPathForPath( urlPath, template ); return jp.> read( "$.statuses[*].state" ).stream().anyMatch( s -> s.equals( "success" ) ); } @Override - public List getAllPullRequests( final Repository repo, final Team team ) { + public List getAllPullRequests( final Repository repo, final Team team, final RestTemplate template ) { final String urlPath = "/repos/" + team.getName() + "/" + repo.getName() + "/pulls"; - final DocumentContext jp = jsonPathForPath( urlPath ); + final DocumentContext jp = jsonPathForPath( urlPath, template ); return parsePullRequestsJson( repo, urlPath, jp ); } - private static List parsePullRequestsJson( final Repository repo, final String urlPath, + public static List parsePullRequestsJson( final Repository repo, final String urlPath, final DocumentContext jp ) { final List pullRequestAmount = jp.read( "$..number" ); final int numPullRequests = pullRequestAmount.size(); @@ -135,23 +134,24 @@ private static List parsePullRequestsJson( final Repository repo, f return results; } - private DocumentContext jsonPathForPath( final String urlPath ) { - final String json = githubTemplate.getForObject( urlPath, String.class ); + private DocumentContext jsonPathForPath( final String urlPath, final RestTemplate template ) { + final String json = template.getForObject( urlPath, String.class ); return JsonPath.parse( json ); } @Override - public void rebase( final Repository repo, final PullRequest pullRequest, final Team team ) { + public void rebase( final Repository repo, final PullRequest pullRequest, final Team team, + final RestTemplate template ) { if ( !rebaseService.rebase( repo, pullRequest ) ) { - addComment( pullRequest, team ); + addComment( pullRequest, team, template ); } } @Override - public void addComment( final PullRequest pullRequest, final Team team ) { + public void addComment( final PullRequest pullRequest, final Team team, final RestTemplate template ) { final Map request = new HashMap<>(); request.put( "body", "This pull request needs some manual love ..." ); - githubTemplate.postForObject( "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/issues/" + template.postForObject( "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/issues/" + pullRequest.getId() + "/comments", request, String.class ); } diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index faa93b3..b1ad07a 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -1,5 +1,10 @@ package org.retest.rebazer.service; +import java.util.HashMap; +import java.util.Map; + +import org.retest.rebazer.config.BitbucketConfig; +import org.retest.rebazer.config.GithubConfig; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.Repository; import org.retest.rebazer.config.RebazerConfig.Services; @@ -7,8 +12,10 @@ import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -27,50 +34,74 @@ public class HandleServices { @Qualifier( "githubService" ) private final Provider githubService; + private final BitbucketConfig bitbucketConfig = new BitbucketConfig(); + private final GithubConfig githubConfig = new GithubConfig(); + private final RestTemplateBuilder builder; + + private final Map restTemplates = new HashMap<>(); + private RestTemplate template; + @Scheduled( fixedDelay = 60 * 1000 ) public void pollBitbucket() { - for ( final Services service : config.getServices() ) { - if ( "bitbucket".equals( service.getType() ) ) { - service.setProvider( bitbucketService ); - final Team team = service.getTeam(); - for ( final Repository repo : team.getRepos() ) { - log.debug( "Processing {}.", repo ); - for ( final PullRequest pr : bitbucketService.getAllPullRequests( repo, team ) ) { - System.out.println( pr ); - handlePR( bitbucketService, repo, pr, team ); - } + for ( final Services services : config.getServices() ) { + final Team team = services.getTeam(); + if ( "bitbucket".equals( services.getType() ) ) { + services.setProvider( bitbucketService ); + restTemplates.put( team.getUser(), + bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ) ); + restTemplates.put( team.getName(), + bitbucketConfig.bitbucketTemplate( builder, team.getUser(), team.getPass() ) ); + } else if ( "github".equals( services.getType() ) ) { + services.setProvider( githubService ); + restTemplates.put( team.getName(), + githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ) ); + } + for ( final Repository repo : team.getRepos() ) { + log.debug( "Processing {}.", repo ); + for ( final PullRequest pr : services.getProvider().getAllPullRequests( repo, team, + restTemplates.get( team.getName() ) ) ) { + handlePR( services.getProvider(), repo, pr, team, restTemplates ); } } } } - private void handlePR( final Provider provider, final Repository repo, final PullRequest pullRequest, - final Team team ) { + public void handlePR( final Provider provider, final Repository repo, final PullRequest pullRequest, + final Team team, final Map restTemplates ) { log.debug( "Processing {}.", pullRequest ); + if ( provider.getClass().equals( BitbucketService.class ) ) { + template = restTemplates.get( team.getUser() ); + } else if ( provider.getClass().equals( GithubService.class ) ) { + template = restTemplates.get( team.getName() ); + } if ( pullRequestLastUpdateStore.isHandled( repo, pullRequest ) ) { log.info( "{} is unchanged since last run (last change: {}).", pullRequest, pullRequestLastUpdateStore.getLastDate( repo, pullRequest ) ); - } else if ( !provider.greenBuildExists( pullRequest, team ) ) { + } else if ( !provider.greenBuildExists( pullRequest, team, restTemplates.get( team.getName() ) ) ) { log.info( "Waiting for green build of {}.", pullRequest ); pullRequestLastUpdateStore.setHandled( repo, pullRequest ); - } else if ( provider.rebaseNeeded( pullRequest, team ) ) { - provider.rebase( repo, pullRequest, team ); + } else if ( provider.rebaseNeeded( pullRequest, team, template ) ) { + provider.rebase( repo, pullRequest, team, restTemplates.get( team.getName() ) ); // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called - pullRequestLastUpdateStore.setHandled( repo, provider.getLatestUpdate( pullRequest ) ); + pullRequestLastUpdateStore.setHandled( repo, provider.getLatestUpdate( pullRequest, template ) ); - } else if ( !provider.isApproved( pullRequest ) ) { + } else if ( !provider.isApproved( pullRequest, restTemplates.get( team.getName() ) ) ) { log.info( "Waiting for approval of {}.", pullRequest ); pullRequestLastUpdateStore.setHandled( repo, pullRequest ); } else { log.info( "Merging pull request " + pullRequest ); - provider.merge( pullRequest ); + provider.merge( pullRequest, restTemplates.get( team.getName() ) ); pullRequestLastUpdateStore.resetAllInThisRepo( repo ); } } + public int getCurrentPollInterval( final RebazerConfig config ) { + return config.getPollInterval(); + } + } diff --git a/src/main/java/org/retest/rebazer/service/Provider.java b/src/main/java/org/retest/rebazer/service/Provider.java index 7521b85..5ecdb53 100644 --- a/src/main/java/org/retest/rebazer/service/Provider.java +++ b/src/main/java/org/retest/rebazer/service/Provider.java @@ -5,27 +5,28 @@ import org.retest.rebazer.config.RebazerConfig.Repository; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; +import org.springframework.web.client.RestTemplate; public interface Provider { - PullRequest getLatestUpdate( PullRequest pullRequest ); + PullRequest getLatestUpdate( PullRequest pullRequest, RestTemplate template ); - boolean isApproved( PullRequest pullRequest ); + boolean isApproved( PullRequest pullRequest, RestTemplate template ); - boolean rebaseNeeded( PullRequest pullRequest, Team team ); + boolean rebaseNeeded( PullRequest pullRequest, Team team, RestTemplate template ); - String getHeadOfBranch( PullRequest pullRequest, Team team ); + String getHeadOfBranch( PullRequest pullRequest, Team team, RestTemplate template ); - String getLastCommonCommitId( PullRequest pullRequest ); + String getLastCommonCommitId( PullRequest pullRequest, RestTemplate template ); - void merge( PullRequest pullRequest ); + void merge( PullRequest pullRequest, RestTemplate template ); - boolean greenBuildExists( PullRequest pullRequest, Team team ); + boolean greenBuildExists( PullRequest pullRequest, Team team, RestTemplate template ); - List getAllPullRequests( Repository repo, Team team ); + List getAllPullRequests( Repository repo, Team team, RestTemplate template ); - void rebase( Repository repo, PullRequest pullRequest, Team team ); + void addComment( PullRequest pullRequest, Team team, RestTemplate template ); - void addComment( PullRequest pullRequest, Team team ); + void rebase( Repository repo, PullRequest pullRequest, Team team, RestTemplate template ); } From cb4c6bf156e41e917342eb995e428329b97c0cdf Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Wed, 24 Jan 2018 12:51:41 +0100 Subject: [PATCH 21/86] Adapt service tests for new configuration --- .../rebazer/service/BitbucketServiceTest.java | 68 +++++++++---------- .../rebazer/service/GithubServiceTest.java | 46 ++++++------- 2 files changed, 52 insertions(+), 62 deletions(-) diff --git a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java index 86deb49..dc89bdf 100644 --- a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java @@ -1,11 +1,12 @@ package org.retest.rebazer.service; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; @@ -15,6 +16,7 @@ import org.junit.Test; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.web.client.RestTemplate; @@ -24,109 +26,105 @@ public class BitbucketServiceTest { PullRequestLastUpdateStore pullRequestUpdateStates; - PullRequest pullRequest; RestTemplate bitbucketTemplate; RebazerConfig config; + Team team; - BitbucketService cut; + Provider cut; @Before public void setUp() { bitbucketTemplate = mock( RestTemplate.class ); - final RestTemplate bitbucketLegacyTemplate = mock( RestTemplate.class ); config = mock( RebazerConfig.class ); + team = mock( Team.class ); final RebaseService rebaseService = mock( RebaseService.class ); pullRequestUpdateStates = mock( PullRequestLastUpdateStore.class ); - pullRequest = PullRequest.builder().url( "" ).build(); - cut = new BitbucketService( bitbucketTemplate, bitbucketLegacyTemplate, config, rebaseService, - pullRequestUpdateStates ); + cut = new BitbucketService( rebaseService ); } @Test public void rebaseNeeded_should_return_false_if_headOfBranch_is_equal_to_lastCommonCommitId() { - final BitbucketService cut = mock( BitbucketService.class ); + final PullRequest pullRequest = mock( PullRequest.class ); + final Provider cut = mock( BitbucketService.class ); final String head = "12325345923759135"; - when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); - when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( head ); - when( cut.rebaseNeeded( pullRequest ) ).thenCallRealMethod(); + when( cut.getHeadOfBranch( pullRequest, team, bitbucketTemplate ) ).thenReturn( head ); + when( cut.getLastCommonCommitId( pullRequest, bitbucketTemplate ) ).thenReturn( head ); + when( cut.rebaseNeeded( pullRequest, team, bitbucketTemplate ) ).thenCallRealMethod(); - assertThat( cut.rebaseNeeded( pullRequest ) ).isFalse(); + assertThat( cut.rebaseNeeded( pullRequest, team, bitbucketTemplate ) ).isFalse(); } @Test public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCommonCommitId() { - final BitbucketService cut = mock( BitbucketService.class ); + final PullRequest pullRequest = mock( PullRequest.class ); + final Provider cut = mock( BitbucketService.class ); final String head = "12325345923759135"; final String lcci = "21342343253253452"; - when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); - when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( lcci ); - when( cut.rebaseNeeded( pullRequest ) ).thenCallRealMethod(); + when( cut.getHeadOfBranch( pullRequest, team, bitbucketTemplate ) ).thenReturn( head ); + when( cut.getLastCommonCommitId( pullRequest, bitbucketTemplate ) ).thenReturn( lcci ); + when( cut.rebaseNeeded( pullRequest, team, bitbucketTemplate ) ).thenCallRealMethod(); - assertThat( cut.rebaseNeeded( pullRequest ) ).isTrue(); + assertThat( cut.rebaseNeeded( pullRequest, team, bitbucketTemplate ) ).isTrue(); } @Test public void isApproved_should_return_false_if_approved_is_false() { + final PullRequest pullRequest = mock( PullRequest.class ); final String json = "{participants: [{\"approved\": false}]}\""; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.isApproved( pullRequest ) ).isFalse(); + assertThat( cut.isApproved( pullRequest, bitbucketTemplate ) ).isFalse(); } @Test public void isApproved_should_return_ture_if_approved_is_true() { + final PullRequest pullRequest = mock( PullRequest.class ); final String json = "{participants: [{\"approved\": true}]}\""; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.isApproved( pullRequest ) ).isTrue(); + assertThat( cut.isApproved( pullRequest, bitbucketTemplate ) ).isTrue(); } @Test public void greenBuildExists_should_return_false_if_state_is_failed() { + final PullRequest pullRequest = mock( PullRequest.class ); final String json = "{values: [{\"state\": FAILED}]}"; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.greenBuildExists( pullRequest ) ).isFalse(); + assertThat( cut.greenBuildExists( pullRequest, team, bitbucketTemplate ) ).isFalse(); } @Test public void greenBuildExists_should_return_true_if_state_is_successful() { + final PullRequest pullRequest = mock( PullRequest.class ); final String json = "{values: [{\"state\": SUCCESSFUL}]}"; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.greenBuildExists( pullRequest ) ).isTrue(); + assertThat( cut.greenBuildExists( pullRequest, team, bitbucketTemplate ) ).isTrue(); } @Test - public void getAllPullRequests_should_return_all_pull_requests_as_list() throws Exception { + public void getAllPullRequests_should_return_all_pull_requests_as_list() throws IOException { final Repository repo = mock( Repository.class ); final String json = new String( Files.readAllBytes( Paths.get( "src/test/resources/org/retest/rebazer/service/bitbucketservicetest/response.json" ) ) ); final DocumentContext documentContext = JsonPath.parse( json ); - when( config.getTeam() ).thenReturn( "test_team" ); + + when( team.getName() ).thenReturn( "test_team" ); when( repo.getName() ).thenReturn( "test_repo_name" ); when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); final int expectedId = (int) documentContext.read( "$.values[0].id" ); final String expectedUrl = - "/repositories/" + config.getTeam() + "/" + repo.getName() + "/pullrequests/" + expectedId; + "/repositories/" + team.getName() + "/" + repo.getName() + "/pullrequests/" + expectedId; final List expected = Arrays.asList( PullRequest.builder().id( expectedId ).repo( repo.getName() ) .source( documentContext.read( "$.values[0].source.branch.name" ) ) .destination( documentContext.read( "$.values[0].destination.branch.name" ) ).url( expectedUrl ) .lastUpdate( documentContext.read( "$.values[0].updated_on" ) ).build() ); - final List actual = cut.getAllPullRequests( repo ); + final List actual = cut.getAllPullRequests( repo, team, bitbucketTemplate ); assertThat( actual ).isEqualTo( expected ); } - @Test - public void getLatestUpdate_should_return_updated_PullRequest() { - final PullRequest pullRequest = mock( PullRequest.class ); - final String json = "{\"updated_on\": \"someTimestamp\"}"; - when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - - assertThat( cut.getLatestUpdate( pullRequest ).getLastUpdate() ).isEqualTo( "someTimestamp" ); - } - } diff --git a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java index 4e16698..db0c52e 100644 --- a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java @@ -16,6 +16,7 @@ import org.junit.Test; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.web.client.RestTemplate; @@ -24,9 +25,9 @@ public class GithubServiceTest { - PullRequestLastUpdateStore pullRequestUpdateStates; RestTemplate githubTemplate; RebazerConfig config; + Team team; GithubService cut; @@ -34,10 +35,10 @@ public class GithubServiceTest { public void setUp() { githubTemplate = mock( RestTemplate.class ); config = mock( RebazerConfig.class ); + team = mock( Team.class ); final RebaseService rebaseService = mock( RebaseService.class ); - pullRequestUpdateStates = mock( PullRequestLastUpdateStore.class ); - cut = new GithubService( githubTemplate, config, rebaseService, null ); + cut = new GithubService( rebaseService ); } @Test @@ -45,11 +46,11 @@ public void rebaseNeeded_should_return_false_if_headOfBranch_is_equal_to_lastCom final PullRequest pullRequest = mock( PullRequest.class ); final GithubService cut = mock( GithubService.class ); final String head = "12325345923759135"; - when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); - when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( head ); - when( cut.rebaseNeeded( pullRequest ) ).thenCallRealMethod(); + when( cut.getHeadOfBranch( pullRequest, team, githubTemplate ) ).thenReturn( head ); + when( cut.getLastCommonCommitId( pullRequest, githubTemplate ) ).thenReturn( head ); + when( cut.rebaseNeeded( pullRequest, team, githubTemplate ) ).thenCallRealMethod(); - assertThat( cut.rebaseNeeded( pullRequest ) ).isFalse(); + assertThat( cut.rebaseNeeded( pullRequest, team, githubTemplate ) ).isFalse(); } @Test @@ -58,11 +59,11 @@ public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCo final GithubService cut = mock( GithubService.class ); final String head = "12325345923759135"; final String lcci = "21342343253253452"; - when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); - when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( lcci ); - when( cut.rebaseNeeded( pullRequest ) ).thenCallRealMethod(); + when( cut.getHeadOfBranch( pullRequest, team, githubTemplate ) ).thenReturn( head ); + when( cut.getLastCommonCommitId( pullRequest, githubTemplate ) ).thenReturn( lcci ); + when( cut.rebaseNeeded( pullRequest, team, githubTemplate ) ).thenCallRealMethod(); - assertThat( cut.rebaseNeeded( pullRequest ) ).isTrue(); + assertThat( cut.rebaseNeeded( pullRequest, team, githubTemplate ) ).isTrue(); } @Test @@ -71,7 +72,7 @@ public void isApproved_should_return_false_if_approved_is_false() { final String json = "{review: [{\"state\": \"CHANGES_REQUESTED\"}]}\""; when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.isApproved( pullRequest ) ).isFalse(); + assertThat( cut.isApproved( pullRequest, githubTemplate ) ).isFalse(); } @Test @@ -80,7 +81,7 @@ public void isApproved_should_return_true_if_approved_is_true() { final String json = "{review: [{\"state\": \"APPROVED\"}]}\""; when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.isApproved( pullRequest ) ).isTrue(); + assertThat( cut.isApproved( pullRequest, githubTemplate ) ).isTrue(); } @Test @@ -89,7 +90,7 @@ public void greenBuildExists_should_return_false_if_state_is_failed() { final String json = "{statuses: [{\"state\": \"failure_or_error\"}]}"; when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.greenBuildExists( pullRequest ) ).isFalse(); + assertThat( cut.greenBuildExists( pullRequest, team, githubTemplate ) ).isFalse(); } @Test @@ -98,7 +99,7 @@ public void greenBuildExists_should_return_true_if_state_is_successful() { final String json = "{statuses: [{\"state\": \"success\"}]}"; when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.greenBuildExists( pullRequest ) ).isTrue(); + assertThat( cut.greenBuildExists( pullRequest, team, githubTemplate ) ).isTrue(); } @Test @@ -107,28 +108,19 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws final String json = new String( Files.readAllBytes( Paths.get( "src/test/resources/org/retest/rebazer/service/githubservicetest/response.json" ) ) ); final DocumentContext documentContext = JsonPath.parse( json ); - when( config.getTeam() ).thenReturn( "test_team" ); + when( team.getName() ).thenReturn( "test_team" ); when( repo.getName() ).thenReturn( "test_repo_name" ); when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); final int expectedId = (int) documentContext.read( "$.[0].number" ); - final String expectedUrl = "/repos/" + config.getTeam() + "/" + repo.getName() + "/pulls/" + expectedId; + final String expectedUrl = "/repos/" + team.getName() + "/" + repo.getName() + "/pulls/" + expectedId; final List expected = Arrays.asList( PullRequest.builder().id( expectedId ).repo( repo.getName() ) .source( documentContext.read( "$.[0].head.ref" ) ) .destination( documentContext.read( "$.[0].base.ref" ) ).url( expectedUrl ) .lastUpdate( documentContext.read( "$.[0].updated_at" ) ).build() ); - final List actual = cut.getAllPullRequests( repo ); + final List actual = cut.getAllPullRequests( repo, team, githubTemplate ); assertThat( actual ).isEqualTo( expected ); } - @Test - public void getLatestUpdate_should_return_updated_PullRequest() { - final PullRequest pullRequest = mock( PullRequest.class ); - final String json = "{\"updated_at\": \"someTimestamp\"}"; - when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - - assertThat( cut.getLatestUpdate( pullRequest ).getLastUpdate() ).isEqualTo( "someTimestamp" ); - } - } From b7e6f47472f68820882f55aa770be6c6321d901d Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Thu, 25 Jan 2018 07:14:28 +0100 Subject: [PATCH 22/86] Rename Services to its functionality *adapt classes which called Services --- .../retest/rebazer/config/RebazerConfig.java | 4 ++-- .../retest/rebazer/service/HandleServices.java | 18 +++++++++--------- .../retest/rebazer/service/RebaseService.java | 8 ++++---- src/main/resources/application.yml.example | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 2f3fa83..e078cc9 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -14,7 +14,7 @@ @Configuration @ConfigurationProperties( "rebazer" ) public class RebazerConfig { - private List services; + private List hosts; private String workspace = "./rebazer-workspace"; private int garbageCollectionCountdown = 20; private int pollInterval; @@ -43,7 +43,7 @@ public static class Team { } @Data - public static class Services { + public static class RepositoryHost { private String type; private String url; private Team team; diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index b1ad07a..c11ff95 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -7,7 +7,7 @@ import org.retest.rebazer.config.GithubConfig; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.Repository; -import org.retest.rebazer.config.RebazerConfig.Services; +import org.retest.rebazer.config.RebazerConfig.RepositoryHost; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; @@ -43,24 +43,24 @@ public class HandleServices { @Scheduled( fixedDelay = 60 * 1000 ) public void pollBitbucket() { - for ( final Services services : config.getServices() ) { - final Team team = services.getTeam(); - if ( "bitbucket".equals( services.getType() ) ) { - services.setProvider( bitbucketService ); + for ( final RepositoryHost hosts : config.getHosts() ) { + final Team team = hosts.getTeam(); + if ( "bitbucket".equals( hosts.getType() ) ) { + hosts.setProvider( bitbucketService ); restTemplates.put( team.getUser(), bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ) ); restTemplates.put( team.getName(), bitbucketConfig.bitbucketTemplate( builder, team.getUser(), team.getPass() ) ); - } else if ( "github".equals( services.getType() ) ) { - services.setProvider( githubService ); + } else if ( "github".equals( hosts.getType() ) ) { + hosts.setProvider( githubService ); restTemplates.put( team.getName(), githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ) ); } for ( final Repository repo : team.getRepos() ) { log.debug( "Processing {}.", repo ); - for ( final PullRequest pr : services.getProvider().getAllPullRequests( repo, team, + for ( final PullRequest pr : hosts.getProvider().getAllPullRequests( repo, team, restTemplates.get( team.getName() ) ) ) { - handlePR( services.getProvider(), repo, pr, team, restTemplates ); + handlePR( hosts.getProvider(), repo, pr, team, restTemplates ); } } } diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 2659e52..bbd02c0 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -16,7 +16,7 @@ import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.Repository; -import org.retest.rebazer.config.RebazerConfig.Services; +import org.retest.rebazer.config.RebazerConfig.RepositoryHost; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; @@ -37,14 +37,14 @@ public class RebaseService { public RebaseService( final RebazerConfig config ) { this.config = config; currentGcCountdown = config.getGarbageCollectionCountdown(); - for ( final Services services : config.getServices() ) { - final Team team = services.getTeam(); + for ( final RepositoryHost host : config.getHosts() ) { + final Team team = host.getTeam(); final CredentialsProvider credentials = new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); team.getRepos().forEach( repo -> { final File repoFolder = new File( config.getWorkspace(), repo.getName() ); Git localRepo = null; - final String repoUrl = services.getUrl() + team.getName() + "/" + repo.getName() + ".git"; + final String repoUrl = host.getUrl() + team.getName() + "/" + repo.getName() + ".git"; repo.setUrl( repoUrl ); repo.setCredentials( credentials ); diff --git a/src/main/resources/application.yml.example b/src/main/resources/application.yml.example index ac1cf4e..6a2e8ae 100644 --- a/src/main/resources/application.yml.example +++ b/src/main/resources/application.yml.example @@ -6,7 +6,7 @@ rebazer: workspace: ./rebazer-workspace garbageCollectionCountdown: 20 pollInterval: 10000 - services: + hosts: - type: bitbucket url: https://bitbucket.org/ team: From 40f9b89a2377d45950d0d0f41c33932036df36b9 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Thu, 25 Jan 2018 07:28:53 +0100 Subject: [PATCH 23/86] Add List to support different teams *edit yml.example to realize Team as list --- .../retest/rebazer/config/RebazerConfig.java | 2 +- .../rebazer/service/HandleServices.java | 35 ++++++------- .../retest/rebazer/service/RebaseService.java | 49 ++++++++++--------- src/main/resources/application.yml.example | 40 +++++++-------- 4 files changed, 64 insertions(+), 62 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index e078cc9..687d8ab 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -46,7 +46,7 @@ public static class Team { public static class RepositoryHost { private String type; private String url; - private Team team; + private List team; private Provider provider; } } diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index c11ff95..2543d65 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -44,23 +44,24 @@ public class HandleServices { @Scheduled( fixedDelay = 60 * 1000 ) public void pollBitbucket() { for ( final RepositoryHost hosts : config.getHosts() ) { - final Team team = hosts.getTeam(); - if ( "bitbucket".equals( hosts.getType() ) ) { - hosts.setProvider( bitbucketService ); - restTemplates.put( team.getUser(), - bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ) ); - restTemplates.put( team.getName(), - bitbucketConfig.bitbucketTemplate( builder, team.getUser(), team.getPass() ) ); - } else if ( "github".equals( hosts.getType() ) ) { - hosts.setProvider( githubService ); - restTemplates.put( team.getName(), - githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ) ); - } - for ( final Repository repo : team.getRepos() ) { - log.debug( "Processing {}.", repo ); - for ( final PullRequest pr : hosts.getProvider().getAllPullRequests( repo, team, - restTemplates.get( team.getName() ) ) ) { - handlePR( hosts.getProvider(), repo, pr, team, restTemplates ); + for ( final Team team : hosts.getTeam() ) { + if ( "bitbucket".equals( hosts.getType() ) ) { + hosts.setProvider( bitbucketService ); + restTemplates.put( team.getUser(), + bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ) ); + restTemplates.put( team.getName(), + bitbucketConfig.bitbucketTemplate( builder, team.getUser(), team.getPass() ) ); + } else if ( "github".equals( hosts.getType() ) ) { + hosts.setProvider( githubService ); + restTemplates.put( team.getName(), + githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ) ); + } + for ( final Repository repo : team.getRepos() ) { + log.debug( "Processing {}.", repo ); + for ( final PullRequest pr : hosts.getProvider().getAllPullRequests( repo, team, + restTemplates.get( team.getName() ) ) ) { + handlePR( hosts.getProvider(), repo, pr, team, restTemplates ); + } } } } diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index bbd02c0..ceb9608 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -38,32 +38,33 @@ public RebaseService( final RebazerConfig config ) { this.config = config; currentGcCountdown = config.getGarbageCollectionCountdown(); for ( final RepositoryHost host : config.getHosts() ) { - final Team team = host.getTeam(); - final CredentialsProvider credentials = - new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); - team.getRepos().forEach( repo -> { - final File repoFolder = new File( config.getWorkspace(), repo.getName() ); - Git localRepo = null; - final String repoUrl = host.getUrl() + team.getName() + "/" + repo.getName() + ".git"; - repo.setUrl( repoUrl ); - repo.setCredentials( credentials ); - - if ( repoFolder.exists() ) { - localRepo = tryToOpenExistingRepoAndCheckRemote( repoFolder, repoUrl ); - if ( localRepo == null ) { - try { - FileUtils.deleteDirectory( repoFolder ); - } catch ( final IOException e ) { - throw new RuntimeException( e ); + for ( final Team team : host.getTeam() ) { + final CredentialsProvider credentials = + new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); + team.getRepos().forEach( repo -> { + final File repoFolder = new File( config.getWorkspace(), repo.getName() ); + Git localRepo = null; + final String repoUrl = host.getUrl() + team.getName() + "/" + repo.getName() + ".git"; + repo.setUrl( repoUrl ); + repo.setCredentials( credentials ); + + if ( repoFolder.exists() ) { + localRepo = tryToOpenExistingRepoAndCheckRemote( repoFolder, repoUrl ); + if ( localRepo == null ) { + try { + FileUtils.deleteDirectory( repoFolder ); + } catch ( final IOException e ) { + throw new RuntimeException( e ); + } } } - } - if ( localRepo == null ) { - localRepo = cloneNewRepo( repoFolder, repoUrl, credentials ); - } - repo.setGit( localRepo ); - cleanUp( repo ); - } ); + if ( localRepo == null ) { + localRepo = cloneNewRepo( repoFolder, repoUrl, credentials ); + } + repo.setGit( localRepo ); + cleanUp( repo ); + } ); + } } } diff --git a/src/main/resources/application.yml.example b/src/main/resources/application.yml.example index 6a2e8ae..aa04327 100644 --- a/src/main/resources/application.yml.example +++ b/src/main/resources/application.yml.example @@ -7,24 +7,24 @@ rebazer: garbageCollectionCountdown: 20 pollInterval: 10000 hosts: - - type: bitbucket - url: https://bitbucket.org/ - team: - name: your_company - user: service_user - pass: dont_use_this_pass_at_home - repos: - - name: blub - branch: blub - - name: bla - branch: bla + - type: bitbucket + url: https://bitbucket.org/ + team: + - name: your_company + user: service_user + pass: dont_use_this_pass_at_home + repos: + - name: blub + branch: blub + - name: bla + branch: bla - - type: github - url: https://github.com/ - team: - name: your_company - user: service_user - pass: dont_use_this_pass_at_home - repos: - - name: foo - branch: foo + - type: github + url: https://github.com/ + team: + - name: your_company + user: service_user + pass: dont_use_this_pass_at_home + repos: + - name: foo + branch: foo From ec440145848350ed1bde64588fe705e8c926ef99 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Thu, 25 Jan 2018 08:53:08 +0100 Subject: [PATCH 24/86] Rename Repository to its funcionality --- .../retest/rebazer/config/RebazerConfig.java | 5 ++--- .../rebazer/service/BitbucketService.java | 8 ++++---- .../retest/rebazer/service/GithubService.java | 8 ++++---- .../rebazer/service/HandleServices.java | 20 +++++++++---------- .../org/retest/rebazer/service/Provider.java | 6 +++--- .../service/PullRequestLastUpdateStore.java | 12 +++++------ .../retest/rebazer/service/RebaseService.java | 6 +++--- .../rebazer/service/BitbucketServiceTest.java | 4 ++-- .../rebazer/service/GithubServiceTest.java | 4 ++-- .../PullRequestLastUpdateStoreTest.java | 6 +++--- 10 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 687d8ab..c0e6420 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -20,7 +20,7 @@ public class RebazerConfig { private int pollInterval; @Data - public static class Repository { + public static class RepositoryConfig { private String name; private String branch; private String url; @@ -35,11 +35,10 @@ public String toString() { @Data public static class Team { - private String id; private String name; private String user; private String pass; - private List repos; + private List repos; } @Data diff --git a/src/main/java/org/retest/rebazer/service/BitbucketService.java b/src/main/java/org/retest/rebazer/service/BitbucketService.java index 98dba4e..46077ad 100644 --- a/src/main/java/org/retest/rebazer/service/BitbucketService.java +++ b/src/main/java/org/retest/rebazer/service/BitbucketService.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.Map; -import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; @@ -95,13 +95,13 @@ public boolean greenBuildExists( final PullRequest pullRequest, final Team team, } @Override - public List getAllPullRequests( final Repository repo, final Team team, final RestTemplate template ) { + public List getAllPullRequests( final RepositoryConfig repo, final Team team, final RestTemplate template ) { final String urlPath = "/repositories/" + team.getName() + "/" + repo.getName() + "/pullrequests"; final DocumentContext jp = jsonPathForPath( urlPath, template ); return parsePullRequestsJson( repo, urlPath, jp ); } - public static List parsePullRequestsJson( final Repository repo, final String urlPath, + public static List parsePullRequestsJson( final RepositoryConfig repo, final String urlPath, final DocumentContext jp ) { final int numPullRequests = (int) jp.read( "$.size" ); final List results = new ArrayList<>( numPullRequests ); @@ -128,7 +128,7 @@ private DocumentContext jsonPathForPath( final String urlPath, final RestTemplat } @Override - public void rebase( final Repository repo, final PullRequest pullRequest, final Team team, + public void rebase( final RepositoryConfig repo, final PullRequest pullRequest, final Team team, final RestTemplate template ) { if ( !rebaseService.rebase( repo, pullRequest ) ) { addComment( pullRequest, team, template ); diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 4583873..19fab61 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.Map; -import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; @@ -106,13 +106,13 @@ public boolean greenBuildExists( final PullRequest pullRequest, final Team team, } @Override - public List getAllPullRequests( final Repository repo, final Team team, final RestTemplate template ) { + public List getAllPullRequests( final RepositoryConfig repo, final Team team, final RestTemplate template ) { final String urlPath = "/repos/" + team.getName() + "/" + repo.getName() + "/pulls"; final DocumentContext jp = jsonPathForPath( urlPath, template ); return parsePullRequestsJson( repo, urlPath, jp ); } - public static List parsePullRequestsJson( final Repository repo, final String urlPath, + public static List parsePullRequestsJson( final RepositoryConfig repo, final String urlPath, final DocumentContext jp ) { final List pullRequestAmount = jp.read( "$..number" ); final int numPullRequests = pullRequestAmount.size(); @@ -140,7 +140,7 @@ private DocumentContext jsonPathForPath( final String urlPath, final RestTemplat } @Override - public void rebase( final Repository repo, final PullRequest pullRequest, final Team team, + public void rebase( final RepositoryConfig repo, final PullRequest pullRequest, final Team team, final RestTemplate template ) { if ( !rebaseService.rebase( repo, pullRequest ) ) { addComment( pullRequest, team, template ); diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index 2543d65..faff119 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -6,7 +6,7 @@ import org.retest.rebazer.config.BitbucketConfig; import org.retest.rebazer.config.GithubConfig; import org.retest.rebazer.config.RebazerConfig; -import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryHost; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; @@ -56,7 +56,7 @@ public void pollBitbucket() { restTemplates.put( team.getName(), githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ) ); } - for ( final Repository repo : team.getRepos() ) { + for ( final RepositoryConfig repo : team.getRepos() ) { log.debug( "Processing {}.", repo ); for ( final PullRequest pr : hosts.getProvider().getAllPullRequests( repo, team, restTemplates.get( team.getName() ) ) ) { @@ -68,7 +68,7 @@ public void pollBitbucket() { } - public void handlePR( final Provider provider, final Repository repo, final PullRequest pullRequest, + public void handlePR( final Provider provider, final RepositoryConfig repositories, final PullRequest pullRequest, final Team team, final Map restTemplates ) { log.debug( "Processing {}.", pullRequest ); @@ -77,27 +77,27 @@ public void handlePR( final Provider provider, final Repository repo, final Pull } else if ( provider.getClass().equals( GithubService.class ) ) { template = restTemplates.get( team.getName() ); } - if ( pullRequestLastUpdateStore.isHandled( repo, pullRequest ) ) { + if ( pullRequestLastUpdateStore.isHandled( repositories, pullRequest ) ) { log.info( "{} is unchanged since last run (last change: {}).", pullRequest, - pullRequestLastUpdateStore.getLastDate( repo, pullRequest ) ); + pullRequestLastUpdateStore.getLastDate( repositories, pullRequest ) ); } else if ( !provider.greenBuildExists( pullRequest, team, restTemplates.get( team.getName() ) ) ) { log.info( "Waiting for green build of {}.", pullRequest ); - pullRequestLastUpdateStore.setHandled( repo, pullRequest ); + pullRequestLastUpdateStore.setHandled( repositories, pullRequest ); } else if ( provider.rebaseNeeded( pullRequest, team, template ) ) { - provider.rebase( repo, pullRequest, team, restTemplates.get( team.getName() ) ); + provider.rebase( repositories, pullRequest, team, restTemplates.get( team.getName() ) ); // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called - pullRequestLastUpdateStore.setHandled( repo, provider.getLatestUpdate( pullRequest, template ) ); + pullRequestLastUpdateStore.setHandled( repositories, provider.getLatestUpdate( pullRequest, template ) ); } else if ( !provider.isApproved( pullRequest, restTemplates.get( team.getName() ) ) ) { log.info( "Waiting for approval of {}.", pullRequest ); - pullRequestLastUpdateStore.setHandled( repo, pullRequest ); + pullRequestLastUpdateStore.setHandled( repositories, pullRequest ); } else { log.info( "Merging pull request " + pullRequest ); provider.merge( pullRequest, restTemplates.get( team.getName() ) ); - pullRequestLastUpdateStore.resetAllInThisRepo( repo ); + pullRequestLastUpdateStore.resetAllInThisRepo( repositories ); } } diff --git a/src/main/java/org/retest/rebazer/service/Provider.java b/src/main/java/org/retest/rebazer/service/Provider.java index 5ecdb53..46fde13 100644 --- a/src/main/java/org/retest/rebazer/service/Provider.java +++ b/src/main/java/org/retest/rebazer/service/Provider.java @@ -2,7 +2,7 @@ import java.util.List; -import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.web.client.RestTemplate; @@ -23,10 +23,10 @@ public interface Provider { boolean greenBuildExists( PullRequest pullRequest, Team team, RestTemplate template ); - List getAllPullRequests( Repository repo, Team team, RestTemplate template ); + List getAllPullRequests( RepositoryConfig repo, Team team, RestTemplate template ); void addComment( PullRequest pullRequest, Team team, RestTemplate template ); - void rebase( Repository repo, PullRequest pullRequest, Team team, RestTemplate template ); + void rebase( RepositoryConfig repo, PullRequest pullRequest, Team team, RestTemplate template ); } diff --git a/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java b/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java index c4acbd2..6eb6451 100644 --- a/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java +++ b/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java @@ -3,16 +3,16 @@ import java.util.HashMap; import java.util.Map; -import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.domain.PullRequest; import org.springframework.stereotype.Component; @Component public class PullRequestLastUpdateStore { - private final Map> pullRequestUpdateStates = new HashMap<>(); + private final Map> pullRequestUpdateStates = new HashMap<>(); - void setHandled( final Repository repo, final PullRequest pullRequest ) { + void setHandled( final RepositoryConfig repo, final PullRequest pullRequest ) { Map repoMap = pullRequestUpdateStates.get( repo ); if ( repoMap == null ) { repoMap = new HashMap<>(); @@ -21,19 +21,19 @@ void setHandled( final Repository repo, final PullRequest pullRequest ) { repoMap.put( pullRequest.getId(), pullRequest.getLastUpdate() ); } - String getLastDate( final Repository repo, final PullRequest pullRequest ) { + String getLastDate( final RepositoryConfig repo, final PullRequest pullRequest ) { final Map repoMap = pullRequestUpdateStates.get( repo ); return repoMap != null ? repoMap.get( pullRequest.getId() ) : null; } - void resetAllInThisRepo( final Repository repo ) { + void resetAllInThisRepo( final RepositoryConfig repo ) { final Map repoMap = pullRequestUpdateStates.get( repo ); if ( repoMap != null ) { repoMap.clear(); } } - boolean isHandled( final Repository repo, final PullRequest pullRequest ) { + boolean isHandled( final RepositoryConfig repo, final PullRequest pullRequest ) { return pullRequest.getLastUpdate().equals( getLastDate( repo, pullRequest ) ); } diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index ceb9608..bb0f734 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -15,7 +15,7 @@ import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.retest.rebazer.config.RebazerConfig; -import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryHost; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; @@ -98,7 +98,7 @@ private static Git cloneNewRepo( final File repoFolder, final String gitRepoUrl, } @SneakyThrows - public boolean rebase( final Repository repo, final PullRequest pullRequest ) { + public boolean rebase( final RepositoryConfig repo, final PullRequest pullRequest ) { log.info( "Rebasing {}.", pullRequest ); try { @@ -140,7 +140,7 @@ public boolean rebase( final Repository repo, final PullRequest pullRequest ) { } @SneakyThrows - private void cleanUp( final Repository repo ) { + private void cleanUp( final RepositoryConfig repo ) { final Git repository = repo.getGit(); resetAndRemoveUntrackedFiles( repository ); repository.checkout().setName( "remotes/origin/" + repo.getBranch() ).call(); diff --git a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java index dc89bdf..1f43376 100644 --- a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java @@ -15,7 +15,7 @@ import org.junit.Before; import org.junit.Test; import org.retest.rebazer.config.RebazerConfig; -import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.web.client.RestTemplate; @@ -106,7 +106,7 @@ public void greenBuildExists_should_return_true_if_state_is_successful() { @Test public void getAllPullRequests_should_return_all_pull_requests_as_list() throws IOException { - final Repository repo = mock( Repository.class ); + final RepositoryConfig repo = mock( RepositoryConfig.class ); final String json = new String( Files.readAllBytes( Paths.get( "src/test/resources/org/retest/rebazer/service/bitbucketservicetest/response.json" ) ) ); final DocumentContext documentContext = JsonPath.parse( json ); diff --git a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java index db0c52e..a45e7e2 100644 --- a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java @@ -15,7 +15,7 @@ import org.junit.Before; import org.junit.Test; import org.retest.rebazer.config.RebazerConfig; -import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.web.client.RestTemplate; @@ -104,7 +104,7 @@ public void greenBuildExists_should_return_true_if_state_is_successful() { @Test public void getAllPullRequests_should_return_all_pull_requests_as_list() throws IOException { - final Repository repo = mock( Repository.class ); + final RepositoryConfig repo = mock( RepositoryConfig.class ); final String json = new String( Files.readAllBytes( Paths.get( "src/test/resources/org/retest/rebazer/service/githubservicetest/response.json" ) ) ); final DocumentContext documentContext = JsonPath.parse( json ); diff --git a/src/test/java/org/retest/rebazer/service/PullRequestLastUpdateStoreTest.java b/src/test/java/org/retest/rebazer/service/PullRequestLastUpdateStoreTest.java index 3c5c5ff..feb1e57 100644 --- a/src/test/java/org/retest/rebazer/service/PullRequestLastUpdateStoreTest.java +++ b/src/test/java/org/retest/rebazer/service/PullRequestLastUpdateStoreTest.java @@ -6,12 +6,12 @@ import org.junit.Before; import org.junit.Test; -import org.retest.rebazer.config.RebazerConfig.Repository; +import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.domain.PullRequest; public class PullRequestLastUpdateStoreTest { - Repository repo; + RepositoryConfig repo; PullRequest pr; String lastUpdate; @@ -21,7 +21,7 @@ public class PullRequestLastUpdateStoreTest { public void setUp() { cut = new PullRequestLastUpdateStore(); - repo = mock( Repository.class ); + repo = mock( RepositoryConfig.class ); pr = mock( PullRequest.class ); when( pr.getId() ).thenReturn( 1 ); lastUpdate = "2017-11-30T10:05:28+00:00"; From 45c4dc523e06f503e740c83189c88bdfc9c02e9e Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Thu, 25 Jan 2018 12:39:05 +0100 Subject: [PATCH 25/86] Add ctor and remove obsolete methods parameter *Add ctor to Provider subclasses with parameter info from Provider methods *Create Provider subclasses with the specific RestTemplates to realize clarity *Adapt classes which called those objects --- .../rebazer/service/BitbucketService.java | 63 +++++++++++-------- .../retest/rebazer/service/GithubService.java | 58 ++++++++++------- .../rebazer/service/HandleServices.java | 63 +++++++------------ .../org/retest/rebazer/service/Provider.java | 22 +++---- .../rebazer/service/BitbucketServiceTest.java | 30 ++++----- .../rebazer/service/GithubServiceTest.java | 29 ++++----- 6 files changed, 135 insertions(+), 130 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/BitbucketService.java b/src/main/java/org/retest/rebazer/service/BitbucketService.java index 46077ad..21ec666 100644 --- a/src/main/java/org/retest/rebazer/service/BitbucketService.java +++ b/src/main/java/org/retest/rebazer/service/BitbucketService.java @@ -23,9 +23,23 @@ public class BitbucketService implements Provider { private final RebaseService rebaseService; + RestTemplate bitbucketLegacyTemplate; + RestTemplate bitbucketTemplate; + Team team; + RepositoryConfig repo; + + public BitbucketService( final RebaseService rebaseService, final Team team, final RepositoryConfig repo, + final RestTemplate bitbucketLegacyTemplate, final RestTemplate bitbucketTemplate ) { + this.rebaseService = rebaseService; + this.team = team; + this.bitbucketLegacyTemplate = bitbucketLegacyTemplate; + this.bitbucketTemplate = bitbucketTemplate; + this.repo = repo; + } + @Override - public PullRequest getLatestUpdate( final PullRequest pullRequest, final RestTemplate template ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl(), template ); + public PullRequest getLatestUpdate( final PullRequest pullRequest ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); final PullRequest updatedPullRequest = PullRequest.builder() // .id( pullRequest.getId() ) // .repo( pullRequest.getRepo() ) // @@ -38,34 +52,32 @@ public PullRequest getLatestUpdate( final PullRequest pullRequest, final RestTem } @Override - public boolean isApproved( final PullRequest pullRequest, final RestTemplate template ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl(), template ); + public boolean isApproved( final PullRequest pullRequest ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); return jp.> read( "$.participants[*].approved" ).stream().anyMatch( approved -> approved ); } @Override - public boolean rebaseNeeded( final PullRequest pullRequest, final Team team, final RestTemplate template ) { - return !getLastCommonCommitId( pullRequest, template ).equals( getHeadOfBranch( pullRequest, team, template ) ); + public boolean rebaseNeeded( final PullRequest pullRequest ) { + return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest ) ); } @Override - public String getHeadOfBranch( final PullRequest pullRequest, final Team team, - final RestTemplate bitbucketTemplate ) { + public String getHeadOfBranch( final PullRequest pullRequest ) { final String url = "/repositories/" + team.getName() + "/" + pullRequest.getRepo() + "/"; - return jsonPathForPath( url + "refs/branches/" + pullRequest.getDestination(), bitbucketTemplate ) - .read( "$.target.hash" ); + return jsonPathForPath( url + "refs/branches/" + pullRequest.getDestination() ).read( "$.target.hash" ); } @Override - public String getLastCommonCommitId( final PullRequest pullRequest, final RestTemplate bitbucketTemplate ) { - DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits", bitbucketTemplate ); + public String getLastCommonCommitId( final PullRequest pullRequest ) { + DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); final int pageLength = jp.read( "$.pagelen" ); final int size = jp.read( "$.size" ); final int lastPage = (pageLength + size - 1) / pageLength; if ( lastPage > 1 ) { - jp = jsonPathForPath( pullRequest.getUrl() + "/commits?page=" + lastPage, bitbucketTemplate ); + jp = jsonPathForPath( pullRequest.getUrl() + "/commits?page=" + lastPage ); } final List commitIds = jp.read( "$.values[*].hash" ); @@ -76,7 +88,7 @@ public String getLastCommonCommitId( final PullRequest pullRequest, final RestTe } @Override - public void merge( final PullRequest pullRequest, final RestTemplate template ) { + public void merge( final PullRequest pullRequest ) { final String message = String.format( "Merged in %s (pull request #%d) by ReBaZer", pullRequest.getSource(), pullRequest.getId() ); // TODO add approver to message? @@ -85,19 +97,19 @@ public void merge( final PullRequest pullRequest, final RestTemplate template ) request.put( "message", message ); request.put( "merge_strategy", "merge_commit" ); - template.postForObject( pullRequest.getUrl() + "/merge", request, Object.class ); + bitbucketTemplate.postForObject( pullRequest.getUrl() + "/merge", request, Object.class ); } @Override - public boolean greenBuildExists( final PullRequest pullRequest, final Team team, final RestTemplate template ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/statuses", template ); + public boolean greenBuildExists( final PullRequest pullRequest ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/statuses" ); return jp.> read( "$.values[*].state" ).stream().anyMatch( s -> s.equals( "SUCCESSFUL" ) ); } @Override - public List getAllPullRequests( final RepositoryConfig repo, final Team team, final RestTemplate template ) { + public List getAllPullRequests( final RepositoryConfig repo ) { final String urlPath = "/repositories/" + team.getName() + "/" + repo.getName() + "/pullrequests"; - final DocumentContext jp = jsonPathForPath( urlPath, template ); + final DocumentContext jp = jsonPathForPath( urlPath ); return parsePullRequestsJson( repo, urlPath, jp ); } @@ -122,25 +134,24 @@ public static List parsePullRequestsJson( final RepositoryConfig re return results; } - private DocumentContext jsonPathForPath( final String urlPath, final RestTemplate template ) { - final String json = template.getForObject( urlPath, String.class ); + private DocumentContext jsonPathForPath( final String urlPath ) { + final String json = bitbucketTemplate.getForObject( urlPath, String.class ); return JsonPath.parse( json ); } @Override - public void rebase( final RepositoryConfig repo, final PullRequest pullRequest, final Team team, - final RestTemplate template ) { + public void rebase( final RepositoryConfig repo, final PullRequest pullRequest ) { if ( !rebaseService.rebase( repo, pullRequest ) ) { - addComment( pullRequest, team, template ); + addComment( pullRequest ); } } @Override - public void addComment( final PullRequest pullRequest, final Team team, final RestTemplate template ) { + public void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "content", "This pull request needs some manual love ..." ); - template.postForObject( pullRequest.getUrl() + "/comments", request, String.class ); + bitbucketLegacyTemplate.postForObject( pullRequest.getUrl() + "/comments", request, String.class ); } } diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 19fab61..1f87d43 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -25,9 +25,21 @@ public class GithubService implements Provider { private final RebaseService rebaseService; + RestTemplate githubTemplate; + Team team; + RepositoryConfig repo; + + public GithubService( final RebaseService rebaseService, final Team team, final RepositoryConfig repo, + final RestTemplate githubTemplate ) { + this.rebaseService = rebaseService; + this.team = team; + this.githubTemplate = githubTemplate; + this.repo = repo; + } + @Override - public PullRequest getLatestUpdate( final PullRequest pullRequest, final RestTemplate template ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl(), template ); + public PullRequest getLatestUpdate( final PullRequest pullRequest ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); final PullRequest updatedPullRequest = PullRequest.builder() // .id( pullRequest.getId() ) // .repo( pullRequest.getRepo() ) // @@ -40,8 +52,8 @@ public PullRequest getLatestUpdate( final PullRequest pullRequest, final RestTem } @Override - public boolean isApproved( final PullRequest pullRequest, final RestTemplate template ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/reviews", template ); + public boolean isApproved( final PullRequest pullRequest ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/reviews" ); final List states = jp.read( "$..state" ); boolean approved = false; for ( final String state : states ) { @@ -55,20 +67,19 @@ public boolean isApproved( final PullRequest pullRequest, final RestTemplate tem } @Override - public boolean rebaseNeeded( final PullRequest pullRequest, final Team team, final RestTemplate template ) { - return !getLastCommonCommitId( pullRequest, template ).equals( getHeadOfBranch( pullRequest, team, template ) ); + public boolean rebaseNeeded( final PullRequest pullRequest ) { + return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest ) ); } @Override - public String getHeadOfBranch( final PullRequest pullRequest, final Team team, final RestTemplate template ) { + public String getHeadOfBranch( final PullRequest pullRequest ) { final String url = "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/"; - return jsonPathForPath( url + "git/refs/heads/" + pullRequest.getDestination(), template ) - .read( "$.object.sha" ); + return jsonPathForPath( url + "git/refs/heads/" + pullRequest.getDestination() ).read( "$.object.sha" ); } @Override - public String getLastCommonCommitId( final PullRequest pullRequest, final RestTemplate template ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits", template ); + public String getLastCommonCommitId( final PullRequest pullRequest ) { + final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); final List commitIds = jp.read( "$..sha" ); final List parentIds = jp.read( "$..parents..sha" ); @@ -86,7 +97,7 @@ public String getLastCommonCommitId( final PullRequest pullRequest, final RestTe } @Override - public void merge( final PullRequest pullRequest, final RestTemplate template ) { + public void merge( final PullRequest pullRequest ) { log.warn( "Merging pull request {}", pullRequest ); final String message = String.format( "Merged in %s (pull request #%d) by ReBaZer", pullRequest.getSource(), pullRequest.getId() ); @@ -94,21 +105,21 @@ public void merge( final PullRequest pullRequest, final RestTemplate template ) request.put( "commit_title", message ); request.put( "merge_method", "merge" ); - template.put( pullRequest.getUrl() + "/merge", request, Object.class ); + githubTemplate.put( pullRequest.getUrl() + "/merge", request, Object.class ); } @Override - public boolean greenBuildExists( final PullRequest pullRequest, final Team team, final RestTemplate template ) { + public boolean greenBuildExists( final PullRequest pullRequest ) { final String urlPath = "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/commits/" + pullRequest.getSource() + "/status"; - final DocumentContext jp = jsonPathForPath( urlPath, template ); + final DocumentContext jp = jsonPathForPath( urlPath ); return jp.> read( "$.statuses[*].state" ).stream().anyMatch( s -> s.equals( "success" ) ); } @Override - public List getAllPullRequests( final RepositoryConfig repo, final Team team, final RestTemplate template ) { + public List getAllPullRequests( final RepositoryConfig repo ) { final String urlPath = "/repos/" + team.getName() + "/" + repo.getName() + "/pulls"; - final DocumentContext jp = jsonPathForPath( urlPath, template ); + final DocumentContext jp = jsonPathForPath( urlPath ); return parsePullRequestsJson( repo, urlPath, jp ); } @@ -134,24 +145,23 @@ public static List parsePullRequestsJson( final RepositoryConfig re return results; } - private DocumentContext jsonPathForPath( final String urlPath, final RestTemplate template ) { - final String json = template.getForObject( urlPath, String.class ); + private DocumentContext jsonPathForPath( final String urlPath ) { + final String json = githubTemplate.getForObject( urlPath, String.class ); return JsonPath.parse( json ); } @Override - public void rebase( final RepositoryConfig repo, final PullRequest pullRequest, final Team team, - final RestTemplate template ) { + public void rebase( final RepositoryConfig repo, final PullRequest pullRequest ) { if ( !rebaseService.rebase( repo, pullRequest ) ) { - addComment( pullRequest, team, template ); + addComment( pullRequest ); } } @Override - public void addComment( final PullRequest pullRequest, final Team team, final RestTemplate template ) { + public void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "body", "This pull request needs some manual love ..." ); - template.postForObject( "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/issues/" + githubTemplate.postForObject( "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/issues/" + pullRequest.getId() + "/comments", request, String.class ); } diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index faff119..90a7641 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -1,8 +1,5 @@ package org.retest.rebazer.service; -import java.util.HashMap; -import java.util.Map; - import org.retest.rebazer.config.BitbucketConfig; import org.retest.rebazer.config.GithubConfig; import org.retest.rebazer.config.RebazerConfig; @@ -11,7 +8,6 @@ import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -25,42 +21,34 @@ @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class HandleServices { + private final RebaseService rebaseService; private final RebazerConfig config; private final PullRequestLastUpdateStore pullRequestLastUpdateStore; - @Qualifier( "bitbucketService" ) - private final Provider bitbucketService; - - @Qualifier( "githubService" ) - private final Provider githubService; - private final BitbucketConfig bitbucketConfig = new BitbucketConfig(); private final GithubConfig githubConfig = new GithubConfig(); private final RestTemplateBuilder builder; - private final Map restTemplates = new HashMap<>(); - private RestTemplate template; - @Scheduled( fixedDelay = 60 * 1000 ) public void pollBitbucket() { for ( final RepositoryHost hosts : config.getHosts() ) { for ( final Team team : hosts.getTeam() ) { - if ( "bitbucket".equals( hosts.getType() ) ) { - hosts.setProvider( bitbucketService ); - restTemplates.put( team.getUser(), - bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ) ); - restTemplates.put( team.getName(), - bitbucketConfig.bitbucketTemplate( builder, team.getUser(), team.getPass() ) ); - } else if ( "github".equals( hosts.getType() ) ) { - hosts.setProvider( githubService ); - restTemplates.put( team.getName(), - githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ) ); - } for ( final RepositoryConfig repo : team.getRepos() ) { log.debug( "Processing {}.", repo ); - for ( final PullRequest pr : hosts.getProvider().getAllPullRequests( repo, team, - restTemplates.get( team.getName() ) ) ) { - handlePR( hosts.getProvider(), repo, pr, team, restTemplates ); + if ( "bitbucket".equals( hosts.getType() ) ) { + final RestTemplate bitbucketLegacyTemplate = + bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ); + final RestTemplate bitbucketTemplate = + bitbucketConfig.bitbucketTemplate( builder, team.getUser(), team.getPass() ); + hosts.setProvider( new BitbucketService( rebaseService, team, repo, bitbucketLegacyTemplate, + bitbucketTemplate ) ); + } else if ( "github".equals( hosts.getType() ) ) { + final RestTemplate githubTemplate = + githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ); + hosts.setProvider( new GithubService( rebaseService, team, repo, githubTemplate ) ); + } + for ( final PullRequest pr : hosts.getProvider().getAllPullRequests( repo ) ) { + handlePR( hosts.getProvider(), repo, pr ); } } } @@ -68,35 +56,30 @@ public void pollBitbucket() { } - public void handlePR( final Provider provider, final RepositoryConfig repositories, final PullRequest pullRequest, - final Team team, final Map restTemplates ) { + public void handlePR( final Provider provider, final RepositoryConfig repositories, + final PullRequest pullRequest ) { log.debug( "Processing {}.", pullRequest ); - if ( provider.getClass().equals( BitbucketService.class ) ) { - template = restTemplates.get( team.getUser() ); - } else if ( provider.getClass().equals( GithubService.class ) ) { - template = restTemplates.get( team.getName() ); - } if ( pullRequestLastUpdateStore.isHandled( repositories, pullRequest ) ) { log.info( "{} is unchanged since last run (last change: {}).", pullRequest, pullRequestLastUpdateStore.getLastDate( repositories, pullRequest ) ); - } else if ( !provider.greenBuildExists( pullRequest, team, restTemplates.get( team.getName() ) ) ) { + } else if ( !provider.greenBuildExists( pullRequest ) ) { log.info( "Waiting for green build of {}.", pullRequest ); pullRequestLastUpdateStore.setHandled( repositories, pullRequest ); - } else if ( provider.rebaseNeeded( pullRequest, team, template ) ) { - provider.rebase( repositories, pullRequest, team, restTemplates.get( team.getName() ) ); + } else if ( provider.rebaseNeeded( pullRequest ) ) { + provider.rebase( repositories, pullRequest ); // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called - pullRequestLastUpdateStore.setHandled( repositories, provider.getLatestUpdate( pullRequest, template ) ); + pullRequestLastUpdateStore.setHandled( repositories, provider.getLatestUpdate( pullRequest ) ); - } else if ( !provider.isApproved( pullRequest, restTemplates.get( team.getName() ) ) ) { + } else if ( !provider.isApproved( pullRequest ) ) { log.info( "Waiting for approval of {}.", pullRequest ); pullRequestLastUpdateStore.setHandled( repositories, pullRequest ); } else { log.info( "Merging pull request " + pullRequest ); - provider.merge( pullRequest, restTemplates.get( team.getName() ) ); + provider.merge( pullRequest ); pullRequestLastUpdateStore.resetAllInThisRepo( repositories ); } } diff --git a/src/main/java/org/retest/rebazer/service/Provider.java b/src/main/java/org/retest/rebazer/service/Provider.java index 46fde13..c7da306 100644 --- a/src/main/java/org/retest/rebazer/service/Provider.java +++ b/src/main/java/org/retest/rebazer/service/Provider.java @@ -3,30 +3,28 @@ import java.util.List; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; -import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; -import org.springframework.web.client.RestTemplate; public interface Provider { - PullRequest getLatestUpdate( PullRequest pullRequest, RestTemplate template ); + PullRequest getLatestUpdate( PullRequest pullRequest ); - boolean isApproved( PullRequest pullRequest, RestTemplate template ); + boolean isApproved( PullRequest pullRequest ); - boolean rebaseNeeded( PullRequest pullRequest, Team team, RestTemplate template ); + boolean rebaseNeeded( PullRequest pullRequest ); - String getHeadOfBranch( PullRequest pullRequest, Team team, RestTemplate template ); + String getHeadOfBranch( PullRequest pullRequest ); - String getLastCommonCommitId( PullRequest pullRequest, RestTemplate template ); + String getLastCommonCommitId( PullRequest pullRequest ); - void merge( PullRequest pullRequest, RestTemplate template ); + void merge( PullRequest pullRequest ); - boolean greenBuildExists( PullRequest pullRequest, Team team, RestTemplate template ); + boolean greenBuildExists( PullRequest pullRequest ); - List getAllPullRequests( RepositoryConfig repo, Team team, RestTemplate template ); + List getAllPullRequests( RepositoryConfig repo ); - void addComment( PullRequest pullRequest, Team team, RestTemplate template ); + void addComment( PullRequest pullRequest ); - void rebase( RepositoryConfig repo, PullRequest pullRequest, Team team, RestTemplate template ); + void rebase( RepositoryConfig repo, PullRequest pullRequest ); } diff --git a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java index 1f43376..f32d5d6 100644 --- a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java @@ -37,10 +37,12 @@ public void setUp() { bitbucketTemplate = mock( RestTemplate.class ); config = mock( RebazerConfig.class ); team = mock( Team.class ); + final RepositoryConfig repo = mock( RepositoryConfig.class ); final RebaseService rebaseService = mock( RebaseService.class ); + final RestTemplate bitbucketLegacyTemplate = mock( RestTemplate.class ); pullRequestUpdateStates = mock( PullRequestLastUpdateStore.class ); - cut = new BitbucketService( rebaseService ); + cut = new BitbucketService( rebaseService, team, repo, bitbucketLegacyTemplate, bitbucketTemplate ); } @Test @@ -48,11 +50,11 @@ public void rebaseNeeded_should_return_false_if_headOfBranch_is_equal_to_lastCom final PullRequest pullRequest = mock( PullRequest.class ); final Provider cut = mock( BitbucketService.class ); final String head = "12325345923759135"; - when( cut.getHeadOfBranch( pullRequest, team, bitbucketTemplate ) ).thenReturn( head ); - when( cut.getLastCommonCommitId( pullRequest, bitbucketTemplate ) ).thenReturn( head ); - when( cut.rebaseNeeded( pullRequest, team, bitbucketTemplate ) ).thenCallRealMethod(); + when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); + when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( head ); + when( cut.rebaseNeeded( pullRequest ) ).thenCallRealMethod(); - assertThat( cut.rebaseNeeded( pullRequest, team, bitbucketTemplate ) ).isFalse(); + assertThat( cut.rebaseNeeded( pullRequest ) ).isFalse(); } @Test @@ -61,11 +63,11 @@ public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCo final Provider cut = mock( BitbucketService.class ); final String head = "12325345923759135"; final String lcci = "21342343253253452"; - when( cut.getHeadOfBranch( pullRequest, team, bitbucketTemplate ) ).thenReturn( head ); - when( cut.getLastCommonCommitId( pullRequest, bitbucketTemplate ) ).thenReturn( lcci ); - when( cut.rebaseNeeded( pullRequest, team, bitbucketTemplate ) ).thenCallRealMethod(); + when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); + when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( lcci ); + when( cut.rebaseNeeded( pullRequest ) ).thenCallRealMethod(); - assertThat( cut.rebaseNeeded( pullRequest, team, bitbucketTemplate ) ).isTrue(); + assertThat( cut.rebaseNeeded( pullRequest ) ).isTrue(); } @Test @@ -74,7 +76,7 @@ public void isApproved_should_return_false_if_approved_is_false() { final String json = "{participants: [{\"approved\": false}]}\""; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.isApproved( pullRequest, bitbucketTemplate ) ).isFalse(); + assertThat( cut.isApproved( pullRequest ) ).isFalse(); } @Test @@ -83,7 +85,7 @@ public void isApproved_should_return_ture_if_approved_is_true() { final String json = "{participants: [{\"approved\": true}]}\""; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.isApproved( pullRequest, bitbucketTemplate ) ).isTrue(); + assertThat( cut.isApproved( pullRequest ) ).isTrue(); } @Test @@ -92,7 +94,7 @@ public void greenBuildExists_should_return_false_if_state_is_failed() { final String json = "{values: [{\"state\": FAILED}]}"; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.greenBuildExists( pullRequest, team, bitbucketTemplate ) ).isFalse(); + assertThat( cut.greenBuildExists( pullRequest ) ).isFalse(); } @Test @@ -101,7 +103,7 @@ public void greenBuildExists_should_return_true_if_state_is_successful() { final String json = "{values: [{\"state\": SUCCESSFUL}]}"; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.greenBuildExists( pullRequest, team, bitbucketTemplate ) ).isTrue(); + assertThat( cut.greenBuildExists( pullRequest ) ).isTrue(); } @Test @@ -122,7 +124,7 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws .source( documentContext.read( "$.values[0].source.branch.name" ) ) .destination( documentContext.read( "$.values[0].destination.branch.name" ) ).url( expectedUrl ) .lastUpdate( documentContext.read( "$.values[0].updated_on" ) ).build() ); - final List actual = cut.getAllPullRequests( repo, team, bitbucketTemplate ); + final List actual = cut.getAllPullRequests( repo ); assertThat( actual ).isEqualTo( expected ); } diff --git a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java index a45e7e2..b6f17ab 100644 --- a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java @@ -36,9 +36,10 @@ public void setUp() { githubTemplate = mock( RestTemplate.class ); config = mock( RebazerConfig.class ); team = mock( Team.class ); + final RepositoryConfig repo = mock( RepositoryConfig.class ); final RebaseService rebaseService = mock( RebaseService.class ); - cut = new GithubService( rebaseService ); + cut = new GithubService( rebaseService, team, repo, githubTemplate ); } @Test @@ -46,11 +47,11 @@ public void rebaseNeeded_should_return_false_if_headOfBranch_is_equal_to_lastCom final PullRequest pullRequest = mock( PullRequest.class ); final GithubService cut = mock( GithubService.class ); final String head = "12325345923759135"; - when( cut.getHeadOfBranch( pullRequest, team, githubTemplate ) ).thenReturn( head ); - when( cut.getLastCommonCommitId( pullRequest, githubTemplate ) ).thenReturn( head ); - when( cut.rebaseNeeded( pullRequest, team, githubTemplate ) ).thenCallRealMethod(); + when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); + when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( head ); + when( cut.rebaseNeeded( pullRequest ) ).thenCallRealMethod(); - assertThat( cut.rebaseNeeded( pullRequest, team, githubTemplate ) ).isFalse(); + assertThat( cut.rebaseNeeded( pullRequest ) ).isFalse(); } @Test @@ -59,11 +60,11 @@ public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCo final GithubService cut = mock( GithubService.class ); final String head = "12325345923759135"; final String lcci = "21342343253253452"; - when( cut.getHeadOfBranch( pullRequest, team, githubTemplate ) ).thenReturn( head ); - when( cut.getLastCommonCommitId( pullRequest, githubTemplate ) ).thenReturn( lcci ); - when( cut.rebaseNeeded( pullRequest, team, githubTemplate ) ).thenCallRealMethod(); + when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); + when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( lcci ); + when( cut.rebaseNeeded( pullRequest ) ).thenCallRealMethod(); - assertThat( cut.rebaseNeeded( pullRequest, team, githubTemplate ) ).isTrue(); + assertThat( cut.rebaseNeeded( pullRequest ) ).isTrue(); } @Test @@ -72,7 +73,7 @@ public void isApproved_should_return_false_if_approved_is_false() { final String json = "{review: [{\"state\": \"CHANGES_REQUESTED\"}]}\""; when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.isApproved( pullRequest, githubTemplate ) ).isFalse(); + assertThat( cut.isApproved( pullRequest ) ).isFalse(); } @Test @@ -81,7 +82,7 @@ public void isApproved_should_return_true_if_approved_is_true() { final String json = "{review: [{\"state\": \"APPROVED\"}]}\""; when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.isApproved( pullRequest, githubTemplate ) ).isTrue(); + assertThat( cut.isApproved( pullRequest ) ).isTrue(); } @Test @@ -90,7 +91,7 @@ public void greenBuildExists_should_return_false_if_state_is_failed() { final String json = "{statuses: [{\"state\": \"failure_or_error\"}]}"; when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.greenBuildExists( pullRequest, team, githubTemplate ) ).isFalse(); + assertThat( cut.greenBuildExists( pullRequest ) ).isFalse(); } @Test @@ -99,7 +100,7 @@ public void greenBuildExists_should_return_true_if_state_is_successful() { final String json = "{statuses: [{\"state\": \"success\"}]}"; when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); - assertThat( cut.greenBuildExists( pullRequest, team, githubTemplate ) ).isTrue(); + assertThat( cut.greenBuildExists( pullRequest ) ).isTrue(); } @Test @@ -118,7 +119,7 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws .source( documentContext.read( "$.[0].head.ref" ) ) .destination( documentContext.read( "$.[0].base.ref" ) ).url( expectedUrl ) .lastUpdate( documentContext.read( "$.[0].updated_at" ) ).build() ); - final List actual = cut.getAllPullRequests( repo, team, githubTemplate ); + final List actual = cut.getAllPullRequests( repo ); assertThat( actual ).isEqualTo( expected ); } From 106bc787e41e74b86f130ff10218192c4db0a674 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Thu, 25 Jan 2018 13:17:21 +0100 Subject: [PATCH 26/86] Adapt RebazerConfig to improve readability --- .../retest/rebazer/config/RebazerConfig.java | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index c0e6420..3b970cb 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -14,23 +14,17 @@ @Configuration @ConfigurationProperties( "rebazer" ) public class RebazerConfig { - private List hosts; private String workspace = "./rebazer-workspace"; private int garbageCollectionCountdown = 20; private int pollInterval; + private List hosts; @Data - public static class RepositoryConfig { - private String name; - private String branch; + public static class RepositoryHost { + private String type; private String url; - private CredentialsProvider credentials; - private Git git; - - @Override - public String toString() { - return "Repo " + name + " (" + url + ")"; - } + private List team; + private Provider provider; } @Data @@ -42,10 +36,17 @@ public static class Team { } @Data - public static class RepositoryHost { - private String type; + public static class RepositoryConfig { + private String name; + private String branch; private String url; - private List team; - private Provider provider; + private CredentialsProvider credentials; + private Git git; + + @Override + public String toString() { + return "Repo " + name + " (" + url + ")"; + } } + } From e079bc4ad9620ea3301c61e947dde112ba3a4916 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Thu, 25 Jan 2018 13:20:00 +0100 Subject: [PATCH 27/86] Use for-loop to uniform loop style --- .../java/org/retest/rebazer/service/RebaseService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index bb0f734..38c34e2 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -39,9 +39,9 @@ public RebaseService( final RebazerConfig config ) { currentGcCountdown = config.getGarbageCollectionCountdown(); for ( final RepositoryHost host : config.getHosts() ) { for ( final Team team : host.getTeam() ) { - final CredentialsProvider credentials = - new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); - team.getRepos().forEach( repo -> { + for ( final RepositoryConfig repo : team.getRepos() ) { + final CredentialsProvider credentials = + new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); final File repoFolder = new File( config.getWorkspace(), repo.getName() ); Git localRepo = null; final String repoUrl = host.getUrl() + team.getName() + "/" + repo.getName() + ".git"; @@ -63,7 +63,7 @@ public RebaseService( final RebazerConfig config ) { } repo.setGit( localRepo ); cleanUp( repo ); - } ); + } } } } From a40eea0047a9d4b0494e84b2b5b4b955a50c64fc Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Thu, 25 Jan 2018 13:26:51 +0100 Subject: [PATCH 28/86] Add Type as Enum to distinguish supported Provider --- .../rebazer/service/HandleServices.java | 28 +++++++++++-------- .../retest/rebazer/service/KnownProvider.java | 8 ++++++ src/main/resources/application.yml.example | 4 +-- 3 files changed, 27 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/retest/rebazer/service/KnownProvider.java diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index 90a7641..a3986c2 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -35,17 +35,23 @@ public void pollBitbucket() { for ( final Team team : hosts.getTeam() ) { for ( final RepositoryConfig repo : team.getRepos() ) { log.debug( "Processing {}.", repo ); - if ( "bitbucket".equals( hosts.getType() ) ) { - final RestTemplate bitbucketLegacyTemplate = - bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ); - final RestTemplate bitbucketTemplate = - bitbucketConfig.bitbucketTemplate( builder, team.getUser(), team.getPass() ); - hosts.setProvider( new BitbucketService( rebaseService, team, repo, bitbucketLegacyTemplate, - bitbucketTemplate ) ); - } else if ( "github".equals( hosts.getType() ) ) { - final RestTemplate githubTemplate = - githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ); - hosts.setProvider( new GithubService( rebaseService, team, repo, githubTemplate ) ); + final KnownProvider knownProvider = KnownProvider.valueOf( hosts.getType() ); + switch ( knownProvider ) { + case BITBUCKET: + final RestTemplate bitbucketLegacyTemplate = + bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ); + final RestTemplate bitbucketTemplate = + bitbucketConfig.bitbucketTemplate( builder, team.getUser(), team.getPass() ); + hosts.setProvider( new BitbucketService( rebaseService, team, repo, bitbucketLegacyTemplate, + bitbucketTemplate ) ); + break; + case GITHUB: + final RestTemplate githubTemplate = + githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ); + hosts.setProvider( new GithubService( rebaseService, team, repo, githubTemplate ) ); + break; + default: + log.info( "The hosting Service via: {} is not supported", hosts.getType() ); } for ( final PullRequest pr : hosts.getProvider().getAllPullRequests( repo ) ) { handlePR( hosts.getProvider(), repo, pr ); diff --git a/src/main/java/org/retest/rebazer/service/KnownProvider.java b/src/main/java/org/retest/rebazer/service/KnownProvider.java new file mode 100644 index 0000000..c887607 --- /dev/null +++ b/src/main/java/org/retest/rebazer/service/KnownProvider.java @@ -0,0 +1,8 @@ +package org.retest.rebazer.service; + +public enum KnownProvider { + + BITBUCKET, + GITHUB; + +} diff --git a/src/main/resources/application.yml.example b/src/main/resources/application.yml.example index aa04327..5e0da73 100644 --- a/src/main/resources/application.yml.example +++ b/src/main/resources/application.yml.example @@ -7,7 +7,7 @@ rebazer: garbageCollectionCountdown: 20 pollInterval: 10000 hosts: - - type: bitbucket + - type: BITBUCKET url: https://bitbucket.org/ team: - name: your_company @@ -19,7 +19,7 @@ rebazer: - name: bla branch: bla - - type: github + - type: GITHUB url: https://github.com/ team: - name: your_company From eab91d12e43829ee2f6775101f188ef997a8c235 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Thu, 25 Jan 2018 14:28:13 +0100 Subject: [PATCH 29/86] Add parameterized delay value *to make delay value configurable *add default delay value *remove obsolete method --- src/main/java/org/retest/rebazer/config/RebazerConfig.java | 2 +- .../java/org/retest/rebazer/service/HandleServices.java | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 3b970cb..906e922 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -16,7 +16,7 @@ public class RebazerConfig { private String workspace = "./rebazer-workspace"; private int garbageCollectionCountdown = 20; - private int pollInterval; + private long pollInterval; private List hosts; @Data diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index a3986c2..29f0eb4 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -29,7 +29,7 @@ public class HandleServices { private final GithubConfig githubConfig = new GithubConfig(); private final RestTemplateBuilder builder; - @Scheduled( fixedDelay = 60 * 1000 ) + @Scheduled( fixedDelayString = "${rebazer.pollInterval:60}000" ) public void pollBitbucket() { for ( final RepositoryHost hosts : config.getHosts() ) { for ( final Team team : hosts.getTeam() ) { @@ -90,8 +90,4 @@ public void handlePR( final Provider provider, final RepositoryConfig repositori } } - public int getCurrentPollInterval( final RebazerConfig config ) { - return config.getPollInterval(); - } - } From 9bb2f672d3408edb1cd1e2d53ff22a813dbef324 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Fri, 26 Jan 2018 11:03:53 +0100 Subject: [PATCH 30/86] Extract provider from RebazerConfig --- .../java/org/retest/rebazer/config/RebazerConfig.java | 2 -- .../org/retest/rebazer/service/BitbucketService.java | 6 +++--- .../org/retest/rebazer/service/GithubService.java | 4 ++-- .../org/retest/rebazer/service/HandleServices.java | 11 ++++++----- .../org/retest/rebazer/service/RebaseService.java | 8 ++++---- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 906e922..ef141ac 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -4,7 +4,6 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.transport.CredentialsProvider; -import org.retest.rebazer.service.Provider; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -24,7 +23,6 @@ public static class RepositoryHost { private String type; private String url; private List team; - private Provider provider; } @Data diff --git a/src/main/java/org/retest/rebazer/service/BitbucketService.java b/src/main/java/org/retest/rebazer/service/BitbucketService.java index 21ec666..877c3bc 100644 --- a/src/main/java/org/retest/rebazer/service/BitbucketService.java +++ b/src/main/java/org/retest/rebazer/service/BitbucketService.java @@ -23,9 +23,9 @@ public class BitbucketService implements Provider { private final RebaseService rebaseService; - RestTemplate bitbucketLegacyTemplate; - RestTemplate bitbucketTemplate; - Team team; + private RestTemplate bitbucketLegacyTemplate; + private RestTemplate bitbucketTemplate; + private Team team; RepositoryConfig repo; public BitbucketService( final RebaseService rebaseService, final Team team, final RepositoryConfig repo, diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 1f87d43..33682f8 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -25,8 +25,8 @@ public class GithubService implements Provider { private final RebaseService rebaseService; - RestTemplate githubTemplate; - Team team; + private RestTemplate githubTemplate; + private Team team; RepositoryConfig repo; public GithubService( final RebaseService rebaseService, final Team team, final RepositoryConfig repo, diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index 29f0eb4..bc4f088 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -28,6 +28,7 @@ public class HandleServices { private final BitbucketConfig bitbucketConfig = new BitbucketConfig(); private final GithubConfig githubConfig = new GithubConfig(); private final RestTemplateBuilder builder; + private Provider provider; @Scheduled( fixedDelayString = "${rebazer.pollInterval:60}000" ) public void pollBitbucket() { @@ -42,19 +43,19 @@ public void pollBitbucket() { bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ); final RestTemplate bitbucketTemplate = bitbucketConfig.bitbucketTemplate( builder, team.getUser(), team.getPass() ); - hosts.setProvider( new BitbucketService( rebaseService, team, repo, bitbucketLegacyTemplate, - bitbucketTemplate ) ); + provider = new BitbucketService( rebaseService, team, repo, bitbucketLegacyTemplate, + bitbucketTemplate ); break; case GITHUB: final RestTemplate githubTemplate = githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ); - hosts.setProvider( new GithubService( rebaseService, team, repo, githubTemplate ) ); + provider = new GithubService( rebaseService, team, repo, githubTemplate ); break; default: log.info( "The hosting Service via: {} is not supported", hosts.getType() ); } - for ( final PullRequest pr : hosts.getProvider().getAllPullRequests( repo ) ) { - handlePR( hosts.getProvider(), repo, pr ); + for ( final PullRequest pr : provider.getAllPullRequests( repo ) ) { + handlePR( provider, repo, pr ); } } } diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 38c34e2..bb0f734 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -39,9 +39,9 @@ public RebaseService( final RebazerConfig config ) { currentGcCountdown = config.getGarbageCollectionCountdown(); for ( final RepositoryHost host : config.getHosts() ) { for ( final Team team : host.getTeam() ) { - for ( final RepositoryConfig repo : team.getRepos() ) { - final CredentialsProvider credentials = - new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); + final CredentialsProvider credentials = + new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); + team.getRepos().forEach( repo -> { final File repoFolder = new File( config.getWorkspace(), repo.getName() ); Git localRepo = null; final String repoUrl = host.getUrl() + team.getName() + "/" + repo.getName() + ".git"; @@ -63,7 +63,7 @@ public RebaseService( final RebazerConfig config ) { } repo.setGit( localRepo ); cleanUp( repo ); - } + } ); } } } From 3c96dd5844dba860dba26fbaeacc4583a7075b8a Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Fri, 26 Jan 2018 11:06:33 +0100 Subject: [PATCH 31/86] Remove obsolete code from getLastCommonCommitId --- .../org/retest/rebazer/service/GithubService.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 33682f8..80a7b0c 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -84,16 +84,8 @@ public String getLastCommonCommitId( final PullRequest pullRequest ) { final List commitIds = jp.read( "$..sha" ); final List parentIds = jp.read( "$..parents..sha" ); - // return parentIds.stream().filter( parent -> !commitIds.contains( parent ) ).findFirst() - // .orElseThrow( IllegalStateException::new ); - for ( final String parent : parentIds ) { - if ( commitIds.contains( parent ) ) { - return parent; - } else { - throw new IllegalStateException(); - } - } - return null; + return parentIds.stream().filter( parent -> commitIds.contains( parent ) ).findFirst() + .orElseThrow( IllegalStateException::new ); } @Override From 5a334abc028427678e26592bb3f153e8dde3c772 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Fri, 26 Jan 2018 11:10:53 +0100 Subject: [PATCH 32/86] Change for-loop to Java 8 forEach-loop --- .../java/org/retest/rebazer/service/RebaseService.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index bb0f734..014231d 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -16,8 +16,6 @@ import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; -import org.retest.rebazer.config.RebazerConfig.RepositoryHost; -import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -37,8 +35,8 @@ public class RebaseService { public RebaseService( final RebazerConfig config ) { this.config = config; currentGcCountdown = config.getGarbageCollectionCountdown(); - for ( final RepositoryHost host : config.getHosts() ) { - for ( final Team team : host.getTeam() ) { + config.getHosts().forEach( host -> { + host.getTeam().forEach( team -> { final CredentialsProvider credentials = new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); team.getRepos().forEach( repo -> { @@ -64,8 +62,8 @@ public RebaseService( final RebazerConfig config ) { repo.setGit( localRepo ); cleanUp( repo ); } ); - } - } + } ); + } ); } private static Git tryToOpenExistingRepoAndCheckRemote( final File repoFolder, final String expectedRepoUrl ) { From d7a6f99aa2f93385dd673f87608038eb8138990b Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Fri, 26 Jan 2018 11:20:35 +0100 Subject: [PATCH 33/86] Rename hosts to host to use Singular form --- .../java/org/retest/rebazer/service/HandleServices.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index bc4f088..702b9ca 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -32,11 +32,11 @@ public class HandleServices { @Scheduled( fixedDelayString = "${rebazer.pollInterval:60}000" ) public void pollBitbucket() { - for ( final RepositoryHost hosts : config.getHosts() ) { - for ( final Team team : hosts.getTeam() ) { + for ( final RepositoryHost host : config.getHosts() ) { + for ( final Team team : host.getTeam() ) { for ( final RepositoryConfig repo : team.getRepos() ) { log.debug( "Processing {}.", repo ); - final KnownProvider knownProvider = KnownProvider.valueOf( hosts.getType() ); + final KnownProvider knownProvider = KnownProvider.valueOf( host.getType() ); switch ( knownProvider ) { case BITBUCKET: final RestTemplate bitbucketLegacyTemplate = @@ -52,7 +52,7 @@ public void pollBitbucket() { provider = new GithubService( rebaseService, team, repo, githubTemplate ); break; default: - log.info( "The hosting Service via: {} is not supported", hosts.getType() ); + log.info( "The hosting Service via: {} is not supported", host.getType() ); } for ( final PullRequest pr : provider.getAllPullRequests( repo ) ) { handlePR( provider, repo, pr ); From a1b375537a8dfbe902dcac262a789b1ceb02e5ba Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Fri, 26 Jan 2018 11:29:25 +0100 Subject: [PATCH 34/86] Exract unused methods from interface *change visibility of methods *add unimplement tests --- .../retest/rebazer/service/BitbucketService.java | 9 +++------ .../org/retest/rebazer/service/GithubService.java | 9 +++------ .../java/org/retest/rebazer/service/Provider.java | 6 ------ .../rebazer/service/BitbucketServiceTest.java | 15 ++++++++++++--- .../retest/rebazer/service/GithubServiceTest.java | 9 +++++++++ 5 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/BitbucketService.java b/src/main/java/org/retest/rebazer/service/BitbucketService.java index 877c3bc..c5e02d0 100644 --- a/src/main/java/org/retest/rebazer/service/BitbucketService.java +++ b/src/main/java/org/retest/rebazer/service/BitbucketService.java @@ -62,14 +62,12 @@ public boolean rebaseNeeded( final PullRequest pullRequest ) { return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest ) ); } - @Override - public String getHeadOfBranch( final PullRequest pullRequest ) { + String getHeadOfBranch( final PullRequest pullRequest ) { final String url = "/repositories/" + team.getName() + "/" + pullRequest.getRepo() + "/"; return jsonPathForPath( url + "refs/branches/" + pullRequest.getDestination() ).read( "$.target.hash" ); } - @Override - public String getLastCommonCommitId( final PullRequest pullRequest ) { + String getLastCommonCommitId( final PullRequest pullRequest ) { DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); final int pageLength = jp.read( "$.pagelen" ); @@ -146,8 +144,7 @@ public void rebase( final RepositoryConfig repo, final PullRequest pullRequest ) } } - @Override - public void addComment( final PullRequest pullRequest ) { + private void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "content", "This pull request needs some manual love ..." ); diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 80a7b0c..372cba9 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -71,14 +71,12 @@ public boolean rebaseNeeded( final PullRequest pullRequest ) { return !getLastCommonCommitId( pullRequest ).equals( getHeadOfBranch( pullRequest ) ); } - @Override - public String getHeadOfBranch( final PullRequest pullRequest ) { + String getHeadOfBranch( final PullRequest pullRequest ) { final String url = "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/"; return jsonPathForPath( url + "git/refs/heads/" + pullRequest.getDestination() ).read( "$.object.sha" ); } - @Override - public String getLastCommonCommitId( final PullRequest pullRequest ) { + String getLastCommonCommitId( final PullRequest pullRequest ) { final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); final List commitIds = jp.read( "$..sha" ); @@ -149,8 +147,7 @@ public void rebase( final RepositoryConfig repo, final PullRequest pullRequest ) } } - @Override - public void addComment( final PullRequest pullRequest ) { + private void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "body", "This pull request needs some manual love ..." ); githubTemplate.postForObject( "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/issues/" diff --git a/src/main/java/org/retest/rebazer/service/Provider.java b/src/main/java/org/retest/rebazer/service/Provider.java index c7da306..1723191 100644 --- a/src/main/java/org/retest/rebazer/service/Provider.java +++ b/src/main/java/org/retest/rebazer/service/Provider.java @@ -13,18 +13,12 @@ public interface Provider { boolean rebaseNeeded( PullRequest pullRequest ); - String getHeadOfBranch( PullRequest pullRequest ); - - String getLastCommonCommitId( PullRequest pullRequest ); - void merge( PullRequest pullRequest ); boolean greenBuildExists( PullRequest pullRequest ); List getAllPullRequests( RepositoryConfig repo ); - void addComment( PullRequest pullRequest ); - void rebase( RepositoryConfig repo, PullRequest pullRequest ); } diff --git a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java index f32d5d6..0f72e28 100644 --- a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java @@ -30,7 +30,7 @@ public class BitbucketServiceTest { RebazerConfig config; Team team; - Provider cut; + BitbucketService cut; @Before public void setUp() { @@ -48,7 +48,7 @@ public void setUp() { @Test public void rebaseNeeded_should_return_false_if_headOfBranch_is_equal_to_lastCommonCommitId() { final PullRequest pullRequest = mock( PullRequest.class ); - final Provider cut = mock( BitbucketService.class ); + final BitbucketService cut = mock( BitbucketService.class ); final String head = "12325345923759135"; when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( head ); @@ -60,7 +60,7 @@ public void rebaseNeeded_should_return_false_if_headOfBranch_is_equal_to_lastCom @Test public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCommonCommitId() { final PullRequest pullRequest = mock( PullRequest.class ); - final Provider cut = mock( BitbucketService.class ); + final BitbucketService cut = mock( BitbucketService.class ); final String head = "12325345923759135"; final String lcci = "21342343253253452"; when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); @@ -129,4 +129,13 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws assertThat( actual ).isEqualTo( expected ); } + @Test + public void getLatestUpdate_should_return_updated_PullRequest() { + final PullRequest pullRequest = mock( PullRequest.class ); + final String json = "{\"updated_on\": \"someTimestamp\"}"; + when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + + assertThat( cut.getLatestUpdate( pullRequest ).getLastUpdate() ).isEqualTo( "someTimestamp" ); + } + } diff --git a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java index b6f17ab..71bd779 100644 --- a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java @@ -124,4 +124,13 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws assertThat( actual ).isEqualTo( expected ); } + @Test + public void getLatestUpdate_should_return_updated_PullRequest() { + final PullRequest pullRequest = mock( PullRequest.class ); + final String json = "{\"updated_at\": \"someTimestamp\"}"; + when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + + assertThat( cut.getLatestUpdate( pullRequest ).getLastUpdate() ).isEqualTo( "someTimestamp" ); + } + } From 8cbc2227dc9f8d9914d44069a8c2d8aaf3f186b7 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Fri, 26 Jan 2018 11:36:46 +0100 Subject: [PATCH 35/86] Extract methods to improve readability --- .../retest/rebazer/service/RebaseService.java | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 014231d..b36a779 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -16,6 +16,8 @@ import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; +import org.retest.rebazer.config.RebazerConfig.RepositoryHost; +import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -40,25 +42,7 @@ public RebaseService( final RebazerConfig config ) { final CredentialsProvider credentials = new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); team.getRepos().forEach( repo -> { - final File repoFolder = new File( config.getWorkspace(), repo.getName() ); - Git localRepo = null; - final String repoUrl = host.getUrl() + team.getName() + "/" + repo.getName() + ".git"; - repo.setUrl( repoUrl ); - repo.setCredentials( credentials ); - - if ( repoFolder.exists() ) { - localRepo = tryToOpenExistingRepoAndCheckRemote( repoFolder, repoUrl ); - if ( localRepo == null ) { - try { - FileUtils.deleteDirectory( repoFolder ); - } catch ( final IOException e ) { - throw new RuntimeException( e ); - } - } - } - if ( localRepo == null ) { - localRepo = cloneNewRepo( repoFolder, repoUrl, credentials ); - } + final Git localRepo = createUrl( config, host, team, credentials, repo ); repo.setGit( localRepo ); cleanUp( repo ); } ); @@ -66,6 +50,34 @@ public RebaseService( final RebazerConfig config ) { } ); } + private Git createUrl( final RebazerConfig config, final RepositoryHost host, final Team team, + final CredentialsProvider credentials, final RepositoryConfig repo ) { + final File repoFolder = new File( config.getWorkspace(), repo.getName() ); + Git localRepo = null; + final String repoUrl = host.getUrl() + team.getName() + "/" + repo.getName() + ".git"; + repo.setUrl( repoUrl ); + repo.setCredentials( credentials ); + return localRepo = checkRepoFolder( credentials, repoFolder, localRepo, repoUrl ); + } + + private Git checkRepoFolder( final CredentialsProvider credentials, final File repoFolder, Git localRepo, + final String repoUrl ) { + if ( repoFolder.exists() ) { + localRepo = tryToOpenExistingRepoAndCheckRemote( repoFolder, repoUrl ); + if ( localRepo == null ) { + try { + FileUtils.deleteDirectory( repoFolder ); + } catch ( final IOException e ) { + throw new RuntimeException( e ); + } + } + } + if ( localRepo == null ) { + localRepo = cloneNewRepo( repoFolder, repoUrl, credentials ); + } + return localRepo; + } + private static Git tryToOpenExistingRepoAndCheckRemote( final File repoFolder, final String expectedRepoUrl ) { try { final Git repo = Git.open( repoFolder ); From a059d08e1b5573aa28ba7fab6bd1c11dc991a359 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Fri, 26 Jan 2018 11:40:37 +0100 Subject: [PATCH 36/86] Change String url to java URL url --- src/main/java/org/retest/rebazer/config/RebazerConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index ef141ac..9afe124 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -1,5 +1,6 @@ package org.retest.rebazer.config; +import java.net.URL; import java.util.List; import org.eclipse.jgit.api.Git; @@ -21,7 +22,7 @@ public class RebazerConfig { @Data public static class RepositoryHost { private String type; - private String url; + private URL url; private List team; } From 021df28a0ba4f7d5bc2aa5cfc449947f2288922b Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Fri, 26 Jan 2018 12:03:04 +0100 Subject: [PATCH 37/86] Change String type to Enum type --- src/main/java/org/retest/rebazer/config/RebazerConfig.java | 3 ++- src/main/java/org/retest/rebazer/service/HandleServices.java | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 9afe124..317bd7a 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -5,6 +5,7 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.transport.CredentialsProvider; +import org.retest.rebazer.service.KnownProvider; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -21,7 +22,7 @@ public class RebazerConfig { @Data public static class RepositoryHost { - private String type; + private KnownProvider type; private URL url; private List team; } diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index 702b9ca..852e112 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -36,8 +36,7 @@ public void pollBitbucket() { for ( final Team team : host.getTeam() ) { for ( final RepositoryConfig repo : team.getRepos() ) { log.debug( "Processing {}.", repo ); - final KnownProvider knownProvider = KnownProvider.valueOf( host.getType() ); - switch ( knownProvider ) { + switch ( host.getType() ) { case BITBUCKET: final RestTemplate bitbucketLegacyTemplate = bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ); From eb3aee27ec2756baa19ba5f98a6845e05d874b04 Mon Sep 17 00:00:00 2001 From: Jakob Herdt Date: Mon, 29 Jan 2018 11:06:59 +0100 Subject: [PATCH 38/86] Extract attributes from RebazerConfig --- .../retest/rebazer/config/RebazerConfig.java | 10 ------- .../retest/rebazer/service/RebaseService.java | 29 +++++++++++-------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 317bd7a..dc9cb5c 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -3,8 +3,6 @@ import java.net.URL; import java.util.List; -import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.transport.CredentialsProvider; import org.retest.rebazer.service.KnownProvider; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -39,14 +37,6 @@ public static class Team { public static class RepositoryConfig { private String name; private String branch; - private String url; - private CredentialsProvider credentials; - private Git git; - - @Override - public String toString() { - return "Repo " + name + " (" + url + ")"; - } } } diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index b36a779..b3f1f3b 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -2,6 +2,8 @@ import java.io.File; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import org.apache.commons.io.FileUtils; import org.eclipse.jgit.api.Git; @@ -33,17 +35,21 @@ public class RebaseService { private int currentGcCountdown; + private final Map repoCredentials = new HashMap<>(); + private final Map repoGit = new HashMap<>(); + private final Map repoUrl = new HashMap<>(); + @Autowired public RebaseService( final RebazerConfig config ) { this.config = config; currentGcCountdown = config.getGarbageCollectionCountdown(); config.getHosts().forEach( host -> { host.getTeam().forEach( team -> { - final CredentialsProvider credentials = - new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); team.getRepos().forEach( repo -> { - final Git localRepo = createUrl( config, host, team, credentials, repo ); - repo.setGit( localRepo ); + repoCredentials.put( repo.getName(), + new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ) ); + final Git localRepo = createUrl( config, host, team, repoCredentials.get( repo.getName() ), repo ); + repoGit.put( repo.getName(), localRepo ); cleanUp( repo ); } ); } ); @@ -51,13 +57,12 @@ public RebaseService( final RebazerConfig config ) { } private Git createUrl( final RebazerConfig config, final RepositoryHost host, final Team team, - final CredentialsProvider credentials, final RepositoryConfig repo ) { + CredentialsProvider credentials, final RepositoryConfig repo ) { + credentials = repoCredentials.get( repo.getName() ); final File repoFolder = new File( config.getWorkspace(), repo.getName() ); Git localRepo = null; - final String repoUrl = host.getUrl() + team.getName() + "/" + repo.getName() + ".git"; - repo.setUrl( repoUrl ); - repo.setCredentials( credentials ); - return localRepo = checkRepoFolder( credentials, repoFolder, localRepo, repoUrl ); + repoUrl.put( repo.getName(), host.getUrl() + team.getName() + "/" + repo.getName() + ".git" ); + return localRepo = checkRepoFolder( credentials, repoFolder, localRepo, repoUrl.get( repo.getName() ) ); } private Git checkRepoFolder( final CredentialsProvider credentials, final File repoFolder, Git localRepo, @@ -112,8 +117,8 @@ public boolean rebase( final RepositoryConfig repo, final PullRequest pullReques log.info( "Rebasing {}.", pullRequest ); try { - final Git repository = repo.getGit(); - final CredentialsProvider credentials = repo.getCredentials(); + final Git repository = repoGit.get( repo.getName() ); + final CredentialsProvider credentials = repoCredentials.get( repo.getName() ); repository.fetch().setCredentialsProvider( credentials ).setRemoveDeletedRefs( true ).call(); repository.checkout().setCreateBranch( true ).setName( pullRequest.getSource() ) .setStartPoint( "origin/" + pullRequest.getSource() ).call(); @@ -151,7 +156,7 @@ public boolean rebase( final RepositoryConfig repo, final PullRequest pullReques @SneakyThrows private void cleanUp( final RepositoryConfig repo ) { - final Git repository = repo.getGit(); + final Git repository = repoGit.get( repo.getName() ); resetAndRemoveUntrackedFiles( repository ); repository.checkout().setName( "remotes/origin/" + repo.getBranch() ).call(); removeAllLocalBranches( repository ); From 0bde7425adc430e11b5dc10944953a90368d6c1b Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 7 Jun 2018 11:29:14 +0200 Subject: [PATCH 39/86] Refactoring, there can be multiple team*s* --- src/main/java/org/retest/rebazer/config/RebazerConfig.java | 2 +- .../java/org/retest/rebazer/service/HandleServices.java | 2 +- src/main/java/org/retest/rebazer/service/RebaseService.java | 2 +- src/main/resources/application.yml.example | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index dc9cb5c..0bd84b2 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -22,7 +22,7 @@ public class RebazerConfig { public static class RepositoryHost { private KnownProvider type; private URL url; - private List team; + private List teams; } @Data diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index 852e112..af329a1 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -33,7 +33,7 @@ public class HandleServices { @Scheduled( fixedDelayString = "${rebazer.pollInterval:60}000" ) public void pollBitbucket() { for ( final RepositoryHost host : config.getHosts() ) { - for ( final Team team : host.getTeam() ) { + for ( final Team team : host.getTeams() ) { for ( final RepositoryConfig repo : team.getRepos() ) { log.debug( "Processing {}.", repo ); switch ( host.getType() ) { diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index b3f1f3b..416489a 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -44,7 +44,7 @@ public RebaseService( final RebazerConfig config ) { this.config = config; currentGcCountdown = config.getGarbageCollectionCountdown(); config.getHosts().forEach( host -> { - host.getTeam().forEach( team -> { + host.getTeams().forEach( team -> { team.getRepos().forEach( repo -> { repoCredentials.put( repo.getName(), new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ) ); diff --git a/src/main/resources/application.yml.example b/src/main/resources/application.yml.example index 5e0da73..29f3197 100644 --- a/src/main/resources/application.yml.example +++ b/src/main/resources/application.yml.example @@ -9,7 +9,7 @@ rebazer: hosts: - type: BITBUCKET url: https://bitbucket.org/ - team: + teams: - name: your_company user: service_user pass: dont_use_this_pass_at_home @@ -18,10 +18,10 @@ rebazer: branch: blub - name: bla branch: bla - + - type: GITHUB url: https://github.com/ - team: + teams: - name: your_company user: service_user pass: dont_use_this_pass_at_home From bab4beaa64665f93e6e906709f627ff908c8a5bd Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Wed, 11 Jul 2018 13:49:37 +0200 Subject: [PATCH 40/86] Update maven project description --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 51edf0e..ada3c0b 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ rebazer - Helper service to handle PullRequests on Bitbucket. + Helper service to handle PullRequests on GitHub/Bitbucket. Rebase PullRequests against target to streamline commit history. Merge the PullRequest if it's rebased, approved and the build is green. From 14a9e72afd6a7599d31800e50ee70ce029fddc58 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Wed, 11 Jul 2018 13:49:53 +0200 Subject: [PATCH 41/86] Update dependencies --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index ada3c0b..b0ffb7e 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ org.springframework.boot spring-boot-starter-parent - 2.0.0.RELEASE + 2.0.3.RELEASE @@ -42,7 +42,7 @@ org.eclipse.jgit org.eclipse.jgit - 4.11.0.201803080745-r + 5.0.1.201806211838-r commons-io @@ -80,8 +80,8 @@ - jdeb org.vafer + jdeb 1.6 From 7a6b4b408c5fb1259b44b5667be6729458fffc11 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Wed, 11 Jul 2018 14:04:26 +0200 Subject: [PATCH 42/86] Fix tests after dependencies updates --- .../org/retest/rebazer/service/BitbucketServiceTest.java | 7 +++++-- .../java/org/retest/rebazer/service/GithubServiceTest.java | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java index 0f72e28..9af1744 100644 --- a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java @@ -1,8 +1,8 @@ package org.retest.rebazer.service; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -73,6 +73,7 @@ public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCo @Test public void isApproved_should_return_false_if_approved_is_false() { final PullRequest pullRequest = mock( PullRequest.class ); + when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{participants: [{\"approved\": false}]}\""; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); @@ -82,6 +83,7 @@ public void isApproved_should_return_false_if_approved_is_false() { @Test public void isApproved_should_return_ture_if_approved_is_true() { final PullRequest pullRequest = mock( PullRequest.class ); + when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{participants: [{\"approved\": true}]}\""; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); @@ -132,6 +134,7 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws @Test public void getLatestUpdate_should_return_updated_PullRequest() { final PullRequest pullRequest = mock( PullRequest.class ); + when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{\"updated_on\": \"someTimestamp\"}"; when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); diff --git a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java index 71bd779..666c037 100644 --- a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java @@ -1,8 +1,8 @@ package org.retest.rebazer.service; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -127,6 +127,7 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws @Test public void getLatestUpdate_should_return_updated_PullRequest() { final PullRequest pullRequest = mock( PullRequest.class ); + when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{\"updated_at\": \"someTimestamp\"}"; when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); From 883f2d1b7f338b8912fd114c4591e8136e8f9faf Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Wed, 18 Jul 2018 16:33:33 +0200 Subject: [PATCH 43/86] Document pollInterval config default and rename poll method --- src/main/java/org/retest/rebazer/config/RebazerConfig.java | 4 ++++ src/main/java/org/retest/rebazer/service/HandleServices.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 0bd84b2..c758469 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -13,8 +13,12 @@ @Configuration @ConfigurationProperties( "rebazer" ) public class RebazerConfig { + private String workspace = "./rebazer-workspace"; private int garbageCollectionCountdown = 20; + /** + * For default value see {@link org.retest.rebazer.service.HandleServices#pollToHandleAllPullRequests()} + */ private long pollInterval; private List hosts; diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index af329a1..6f3836c 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -31,7 +31,7 @@ public class HandleServices { private Provider provider; @Scheduled( fixedDelayString = "${rebazer.pollInterval:60}000" ) - public void pollBitbucket() { + public void pollToHandleAllPullRequests() { for ( final RepositoryHost host : config.getHosts() ) { for ( final Team team : host.getTeams() ) { for ( final RepositoryConfig repo : team.getRepos() ) { From 4c3415dad357439c701062c5f729e444b9dc4da6 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Wed, 18 Jul 2018 16:38:10 +0200 Subject: [PATCH 44/86] Rename Provider to Repository, to what it actual represents --- .../java/org/retest/rebazer/service/BitbucketService.java | 2 +- src/main/java/org/retest/rebazer/service/GithubService.java | 2 +- src/main/java/org/retest/rebazer/service/HandleServices.java | 4 ++-- .../retest/rebazer/service/{Provider.java => Repository.java} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename src/main/java/org/retest/rebazer/service/{Provider.java => Repository.java} (94%) diff --git a/src/main/java/org/retest/rebazer/service/BitbucketService.java b/src/main/java/org/retest/rebazer/service/BitbucketService.java index c5e02d0..e5b0f76 100644 --- a/src/main/java/org/retest/rebazer/service/BitbucketService.java +++ b/src/main/java/org/retest/rebazer/service/BitbucketService.java @@ -19,7 +19,7 @@ @Service @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) -public class BitbucketService implements Provider { +public class BitbucketService implements Repository { private final RebaseService rebaseService; diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 372cba9..b2138a2 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -21,7 +21,7 @@ @Slf4j @Service @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) -public class GithubService implements Provider { +public class GithubService implements Repository { private final RebaseService rebaseService; diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index 6f3836c..fda9e80 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -28,7 +28,7 @@ public class HandleServices { private final BitbucketConfig bitbucketConfig = new BitbucketConfig(); private final GithubConfig githubConfig = new GithubConfig(); private final RestTemplateBuilder builder; - private Provider provider; + private Repository provider; @Scheduled( fixedDelayString = "${rebazer.pollInterval:60}000" ) public void pollToHandleAllPullRequests() { @@ -62,7 +62,7 @@ public void pollToHandleAllPullRequests() { } - public void handlePR( final Provider provider, final RepositoryConfig repositories, + public void handlePR( final Repository provider, final RepositoryConfig repositories, final PullRequest pullRequest ) { log.debug( "Processing {}.", pullRequest ); diff --git a/src/main/java/org/retest/rebazer/service/Provider.java b/src/main/java/org/retest/rebazer/service/Repository.java similarity index 94% rename from src/main/java/org/retest/rebazer/service/Provider.java rename to src/main/java/org/retest/rebazer/service/Repository.java index 1723191..75c67b6 100644 --- a/src/main/java/org/retest/rebazer/service/Provider.java +++ b/src/main/java/org/retest/rebazer/service/Repository.java @@ -5,7 +5,7 @@ import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.domain.PullRequest; -public interface Provider { +public interface Repository { PullRequest getLatestUpdate( PullRequest pullRequest ); From a8f3ed470d604d1bf989e70ce0b750ad34be7eea Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Wed, 18 Jul 2018 17:59:51 +0200 Subject: [PATCH 45/86] Move rebase method to HandleServices --- .../retest/rebazer/service/BitbucketService.java | 15 +++------------ .../org/retest/rebazer/service/GithubService.java | 14 ++------------ .../retest/rebazer/service/HandleServices.java | 9 +++++---- .../org/retest/rebazer/service/Repository.java | 2 +- 4 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/BitbucketService.java b/src/main/java/org/retest/rebazer/service/BitbucketService.java index e5b0f76..73fe282 100644 --- a/src/main/java/org/retest/rebazer/service/BitbucketService.java +++ b/src/main/java/org/retest/rebazer/service/BitbucketService.java @@ -21,16 +21,13 @@ @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class BitbucketService implements Repository { - private final RebaseService rebaseService; - private RestTemplate bitbucketLegacyTemplate; private RestTemplate bitbucketTemplate; private Team team; RepositoryConfig repo; - public BitbucketService( final RebaseService rebaseService, final Team team, final RepositoryConfig repo, - final RestTemplate bitbucketLegacyTemplate, final RestTemplate bitbucketTemplate ) { - this.rebaseService = rebaseService; + public BitbucketService( final Team team, final RepositoryConfig repo, final RestTemplate bitbucketLegacyTemplate, + final RestTemplate bitbucketTemplate ) { this.team = team; this.bitbucketLegacyTemplate = bitbucketLegacyTemplate; this.bitbucketTemplate = bitbucketTemplate; @@ -138,13 +135,7 @@ private DocumentContext jsonPathForPath( final String urlPath ) { } @Override - public void rebase( final RepositoryConfig repo, final PullRequest pullRequest ) { - if ( !rebaseService.rebase( repo, pullRequest ) ) { - addComment( pullRequest ); - } - } - - private void addComment( final PullRequest pullRequest ) { + public void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "content", "This pull request needs some manual love ..." ); diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index b2138a2..9bc51c3 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -23,15 +23,11 @@ @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class GithubService implements Repository { - private final RebaseService rebaseService; - private RestTemplate githubTemplate; private Team team; RepositoryConfig repo; - public GithubService( final RebaseService rebaseService, final Team team, final RepositoryConfig repo, - final RestTemplate githubTemplate ) { - this.rebaseService = rebaseService; + public GithubService( final Team team, final RepositoryConfig repo, final RestTemplate githubTemplate ) { this.team = team; this.githubTemplate = githubTemplate; this.repo = repo; @@ -141,13 +137,7 @@ private DocumentContext jsonPathForPath( final String urlPath ) { } @Override - public void rebase( final RepositoryConfig repo, final PullRequest pullRequest ) { - if ( !rebaseService.rebase( repo, pullRequest ) ) { - addComment( pullRequest ); - } - } - - private void addComment( final PullRequest pullRequest ) { + public void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "body", "This pull request needs some manual love ..." ); githubTemplate.postForObject( "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/issues/" diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index fda9e80..f1ceb4a 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -42,13 +42,12 @@ public void pollToHandleAllPullRequests() { bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ); final RestTemplate bitbucketTemplate = bitbucketConfig.bitbucketTemplate( builder, team.getUser(), team.getPass() ); - provider = new BitbucketService( rebaseService, team, repo, bitbucketLegacyTemplate, - bitbucketTemplate ); + provider = new BitbucketService( team, repo, bitbucketLegacyTemplate, bitbucketTemplate ); break; case GITHUB: final RestTemplate githubTemplate = githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ); - provider = new GithubService( rebaseService, team, repo, githubTemplate ); + provider = new GithubService( team, repo, githubTemplate ); break; default: log.info( "The hosting Service via: {} is not supported", host.getType() ); @@ -75,7 +74,9 @@ public void handlePR( final Repository provider, final RepositoryConfig reposito pullRequestLastUpdateStore.setHandled( repositories, pullRequest ); } else if ( provider.rebaseNeeded( pullRequest ) ) { - provider.rebase( repositories, pullRequest ); + if ( !rebaseService.rebase( repositories, pullRequest ) ) { + provider.addComment( pullRequest ); + } // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called pullRequestLastUpdateStore.setHandled( repositories, provider.getLatestUpdate( pullRequest ) ); diff --git a/src/main/java/org/retest/rebazer/service/Repository.java b/src/main/java/org/retest/rebazer/service/Repository.java index 75c67b6..58620c1 100644 --- a/src/main/java/org/retest/rebazer/service/Repository.java +++ b/src/main/java/org/retest/rebazer/service/Repository.java @@ -19,6 +19,6 @@ public interface Repository { List getAllPullRequests( RepositoryConfig repo ); - void rebase( RepositoryConfig repo, PullRequest pullRequest ); + void addComment( PullRequest pullRequest ); } From 292ed9198c2781782611e52a6cd130300f1f099d Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Wed, 18 Jul 2018 18:26:03 +0200 Subject: [PATCH 46/86] Inline restTemplates, because they aren't beans --- .../rebazer/config/BitbucketConfig.java | 23 ---------------- .../retest/rebazer/config/GithubConfig.java | 16 ------------ .../rebazer/service/BitbucketService.java | 26 ++++++++++++------- .../retest/rebazer/service/GithubService.java | 17 +++++++----- .../rebazer/service/HandleServices.java | 15 ++--------- .../rebazer/service/BitbucketServiceTest.java | 26 +++++++++++-------- .../rebazer/service/GithubServiceTest.java | 25 +++++++++++------- 7 files changed, 60 insertions(+), 88 deletions(-) delete mode 100644 src/main/java/org/retest/rebazer/config/BitbucketConfig.java delete mode 100644 src/main/java/org/retest/rebazer/config/GithubConfig.java diff --git a/src/main/java/org/retest/rebazer/config/BitbucketConfig.java b/src/main/java/org/retest/rebazer/config/BitbucketConfig.java deleted file mode 100644 index 5d1e3f3..0000000 --- a/src/main/java/org/retest/rebazer/config/BitbucketConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.retest.rebazer.config; - -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.web.client.RestTemplate; - -public class BitbucketConfig { - - private final static String baseUrlV1 = "https://api.bitbucket.org/1.0"; - private final static String baseUrlV2 = "https://api.bitbucket.org/2.0"; - - @Bean - public RestTemplate bitbucketLegacyTemplate( final RestTemplateBuilder builder, final String user, - final String pass ) { - return builder.basicAuthorization( user, pass ).rootUri( baseUrlV1 ).build(); - } - - @Bean - public RestTemplate bitbucketTemplate( final RestTemplateBuilder builder, final String user, final String pass ) { - return builder.basicAuthorization( user, pass ).rootUri( baseUrlV2 ).build(); - } - -} diff --git a/src/main/java/org/retest/rebazer/config/GithubConfig.java b/src/main/java/org/retest/rebazer/config/GithubConfig.java deleted file mode 100644 index 06d5967..0000000 --- a/src/main/java/org/retest/rebazer/config/GithubConfig.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.retest.rebazer.config; - -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.web.client.RestTemplate; - -public class GithubConfig { - - private final static String baseUrl = "https://api.github.com/"; - - @Bean - public RestTemplate githubTemplate( final RestTemplateBuilder builder, final String user, final String pass ) { - return builder.basicAuthorization( user, pass ).rootUri( baseUrl ).build(); - } - -} diff --git a/src/main/java/org/retest/rebazer/service/BitbucketService.java b/src/main/java/org/retest/rebazer/service/BitbucketService.java index 73fe282..e038a4a 100644 --- a/src/main/java/org/retest/rebazer/service/BitbucketService.java +++ b/src/main/java/org/retest/rebazer/service/BitbucketService.java @@ -9,6 +9,7 @@ import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @@ -21,17 +22,24 @@ @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class BitbucketService implements Repository { - private RestTemplate bitbucketLegacyTemplate; - private RestTemplate bitbucketTemplate; + private final static String baseUrlV1 = "https://api.bitbucket.org/1.0"; + private final static String baseUrlV2 = "https://api.bitbucket.org/2.0"; + private Team team; RepositoryConfig repo; - public BitbucketService( final Team team, final RepositoryConfig repo, final RestTemplate bitbucketLegacyTemplate, - final RestTemplate bitbucketTemplate ) { + private RestTemplate legacyTemplate; + private RestTemplate template; + + public BitbucketService( final Team team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { this.team = team; - this.bitbucketLegacyTemplate = bitbucketLegacyTemplate; - this.bitbucketTemplate = bitbucketTemplate; this.repo = repo; + + legacyTemplate = builder // + .basicAuthorization( team.getUser(), team.getPass() ) // + .rootUri( baseUrlV1 ) // + .build(); + template = builder.basicAuthorization( team.getUser(), team.getPass() ).rootUri( baseUrlV2 ).build(); } @Override @@ -92,7 +100,7 @@ public void merge( final PullRequest pullRequest ) { request.put( "message", message ); request.put( "merge_strategy", "merge_commit" ); - bitbucketTemplate.postForObject( pullRequest.getUrl() + "/merge", request, Object.class ); + template.postForObject( pullRequest.getUrl() + "/merge", request, Object.class ); } @Override @@ -130,7 +138,7 @@ public static List parsePullRequestsJson( final RepositoryConfig re } private DocumentContext jsonPathForPath( final String urlPath ) { - final String json = bitbucketTemplate.getForObject( urlPath, String.class ); + final String json = template.getForObject( urlPath, String.class ); return JsonPath.parse( json ); } @@ -139,7 +147,7 @@ public void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "content", "This pull request needs some manual love ..." ); - bitbucketLegacyTemplate.postForObject( pullRequest.getUrl() + "/comments", request, String.class ); + legacyTemplate.postForObject( pullRequest.getUrl() + "/comments", request, String.class ); } } diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/service/GithubService.java index 9bc51c3..c10f234 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/service/GithubService.java @@ -9,6 +9,7 @@ import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @@ -23,14 +24,18 @@ @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class GithubService implements Repository { - private RestTemplate githubTemplate; + private final static String baseUrl = "https://api.github.com/"; + private Team team; RepositoryConfig repo; - public GithubService( final Team team, final RepositoryConfig repo, final RestTemplate githubTemplate ) { + private RestTemplate template; + + public GithubService( final Team team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { this.team = team; - this.githubTemplate = githubTemplate; this.repo = repo; + + template = builder.basicAuthorization( team.getUser(), team.getPass() ).rootUri( baseUrl ).build(); } @Override @@ -91,7 +96,7 @@ public void merge( final PullRequest pullRequest ) { request.put( "commit_title", message ); request.put( "merge_method", "merge" ); - githubTemplate.put( pullRequest.getUrl() + "/merge", request, Object.class ); + template.put( pullRequest.getUrl() + "/merge", request, Object.class ); } @Override @@ -132,7 +137,7 @@ public static List parsePullRequestsJson( final RepositoryConfig re } private DocumentContext jsonPathForPath( final String urlPath ) { - final String json = githubTemplate.getForObject( urlPath, String.class ); + final String json = template.getForObject( urlPath, String.class ); return JsonPath.parse( json ); } @@ -140,7 +145,7 @@ private DocumentContext jsonPathForPath( final String urlPath ) { public void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "body", "This pull request needs some manual love ..." ); - githubTemplate.postForObject( "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/issues/" + template.postForObject( "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/issues/" + pullRequest.getId() + "/comments", request, String.class ); } diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index f1ceb4a..d3bb80d 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -1,7 +1,5 @@ package org.retest.rebazer.service; -import org.retest.rebazer.config.BitbucketConfig; -import org.retest.rebazer.config.GithubConfig; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryHost; @@ -11,7 +9,6 @@ import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -25,8 +22,6 @@ public class HandleServices { private final RebazerConfig config; private final PullRequestLastUpdateStore pullRequestLastUpdateStore; - private final BitbucketConfig bitbucketConfig = new BitbucketConfig(); - private final GithubConfig githubConfig = new GithubConfig(); private final RestTemplateBuilder builder; private Repository provider; @@ -38,16 +33,10 @@ public void pollToHandleAllPullRequests() { log.debug( "Processing {}.", repo ); switch ( host.getType() ) { case BITBUCKET: - final RestTemplate bitbucketLegacyTemplate = - bitbucketConfig.bitbucketLegacyTemplate( builder, team.getUser(), team.getPass() ); - final RestTemplate bitbucketTemplate = - bitbucketConfig.bitbucketTemplate( builder, team.getUser(), team.getPass() ); - provider = new BitbucketService( team, repo, bitbucketLegacyTemplate, bitbucketTemplate ); + provider = new BitbucketService( team, repo, builder ); break; case GITHUB: - final RestTemplate githubTemplate = - githubConfig.githubTemplate( builder, team.getUser(), team.getPass() ); - provider = new GithubService( team, repo, githubTemplate ); + provider = new GithubService( team, repo, builder ); break; default: log.info( "The hosting Service via: {} is not supported", host.getType() ); diff --git a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java index 9af1744..0743ef6 100644 --- a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java @@ -1,6 +1,7 @@ package org.retest.rebazer.service; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -18,6 +19,7 @@ import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.web.client.RestTemplate; import com.jayway.jsonpath.DocumentContext; @@ -26,7 +28,7 @@ public class BitbucketServiceTest { PullRequestLastUpdateStore pullRequestUpdateStates; - RestTemplate bitbucketTemplate; + RestTemplate template; RebazerConfig config; Team team; @@ -34,15 +36,17 @@ public class BitbucketServiceTest { @Before public void setUp() { - bitbucketTemplate = mock( RestTemplate.class ); + template = mock( RestTemplate.class ); config = mock( RebazerConfig.class ); team = mock( Team.class ); final RepositoryConfig repo = mock( RepositoryConfig.class ); - final RebaseService rebaseService = mock( RebaseService.class ); - final RestTemplate bitbucketLegacyTemplate = mock( RestTemplate.class ); + final RestTemplateBuilder builder = mock( RestTemplateBuilder.class ); + when( builder.basicAuthorization( any(), any() ) ).thenReturn( builder ); + when( builder.rootUri( anyString() ) ).thenReturn( builder ); + when( builder.build() ).thenReturn( template ); pullRequestUpdateStates = mock( PullRequestLastUpdateStore.class ); - cut = new BitbucketService( rebaseService, team, repo, bitbucketLegacyTemplate, bitbucketTemplate ); + cut = new BitbucketService( team, repo, builder ); } @Test @@ -75,7 +79,7 @@ public void isApproved_should_return_false_if_approved_is_false() { final PullRequest pullRequest = mock( PullRequest.class ); when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{participants: [{\"approved\": false}]}\""; - when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.isApproved( pullRequest ) ).isFalse(); } @@ -85,7 +89,7 @@ public void isApproved_should_return_ture_if_approved_is_true() { final PullRequest pullRequest = mock( PullRequest.class ); when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{participants: [{\"approved\": true}]}\""; - when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.isApproved( pullRequest ) ).isTrue(); } @@ -94,7 +98,7 @@ public void isApproved_should_return_ture_if_approved_is_true() { public void greenBuildExists_should_return_false_if_state_is_failed() { final PullRequest pullRequest = mock( PullRequest.class ); final String json = "{values: [{\"state\": FAILED}]}"; - when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.greenBuildExists( pullRequest ) ).isFalse(); } @@ -103,7 +107,7 @@ public void greenBuildExists_should_return_false_if_state_is_failed() { public void greenBuildExists_should_return_true_if_state_is_successful() { final PullRequest pullRequest = mock( PullRequest.class ); final String json = "{values: [{\"state\": SUCCESSFUL}]}"; - when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.greenBuildExists( pullRequest ) ).isTrue(); } @@ -117,7 +121,7 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws when( team.getName() ).thenReturn( "test_team" ); when( repo.getName() ).thenReturn( "test_repo_name" ); - when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); final int expectedId = (int) documentContext.read( "$.values[0].id" ); final String expectedUrl = @@ -136,7 +140,7 @@ public void getLatestUpdate_should_return_updated_PullRequest() { final PullRequest pullRequest = mock( PullRequest.class ); when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{\"updated_on\": \"someTimestamp\"}"; - when( bitbucketTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.getLatestUpdate( pullRequest ).getLastUpdate() ).isEqualTo( "someTimestamp" ); } diff --git a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java index 666c037..8217765 100644 --- a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java +++ b/src/test/java/org/retest/rebazer/service/GithubServiceTest.java @@ -1,6 +1,7 @@ package org.retest.rebazer.service; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -18,6 +19,7 @@ import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.web.client.RestTemplate; import com.jayway.jsonpath.DocumentContext; @@ -25,7 +27,7 @@ public class GithubServiceTest { - RestTemplate githubTemplate; + RestTemplate template; RebazerConfig config; Team team; @@ -33,13 +35,16 @@ public class GithubServiceTest { @Before public void setUp() { - githubTemplate = mock( RestTemplate.class ); + template = mock( RestTemplate.class ); config = mock( RebazerConfig.class ); team = mock( Team.class ); final RepositoryConfig repo = mock( RepositoryConfig.class ); - final RebaseService rebaseService = mock( RebaseService.class ); + final RestTemplateBuilder builder = mock( RestTemplateBuilder.class ); + when( builder.basicAuthorization( any(), any() ) ).thenReturn( builder ); + when( builder.rootUri( anyString() ) ).thenReturn( builder ); + when( builder.build() ).thenReturn( template ); - cut = new GithubService( rebaseService, team, repo, githubTemplate ); + cut = new GithubService( team, repo, builder ); } @Test @@ -71,7 +76,7 @@ public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCo public void isApproved_should_return_false_if_approved_is_false() { final PullRequest pullRequest = mock( PullRequest.class ); final String json = "{review: [{\"state\": \"CHANGES_REQUESTED\"}]}\""; - when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.isApproved( pullRequest ) ).isFalse(); } @@ -80,7 +85,7 @@ public void isApproved_should_return_false_if_approved_is_false() { public void isApproved_should_return_true_if_approved_is_true() { final PullRequest pullRequest = mock( PullRequest.class ); final String json = "{review: [{\"state\": \"APPROVED\"}]}\""; - when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.isApproved( pullRequest ) ).isTrue(); } @@ -89,7 +94,7 @@ public void isApproved_should_return_true_if_approved_is_true() { public void greenBuildExists_should_return_false_if_state_is_failed() { final PullRequest pullRequest = mock( PullRequest.class ); final String json = "{statuses: [{\"state\": \"failure_or_error\"}]}"; - when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.greenBuildExists( pullRequest ) ).isFalse(); } @@ -98,7 +103,7 @@ public void greenBuildExists_should_return_false_if_state_is_failed() { public void greenBuildExists_should_return_true_if_state_is_successful() { final PullRequest pullRequest = mock( PullRequest.class ); final String json = "{statuses: [{\"state\": \"success\"}]}"; - when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.greenBuildExists( pullRequest ) ).isTrue(); } @@ -111,7 +116,7 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws final DocumentContext documentContext = JsonPath.parse( json ); when( team.getName() ).thenReturn( "test_team" ); when( repo.getName() ).thenReturn( "test_repo_name" ); - when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); final int expectedId = (int) documentContext.read( "$.[0].number" ); final String expectedUrl = "/repos/" + team.getName() + "/" + repo.getName() + "/pulls/" + expectedId; @@ -129,7 +134,7 @@ public void getLatestUpdate_should_return_updated_PullRequest() { final PullRequest pullRequest = mock( PullRequest.class ); when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{\"updated_at\": \"someTimestamp\"}"; - when( githubTemplate.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); + when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); assertThat( cut.getLatestUpdate( pullRequest ).getLastUpdate() ).isEqualTo( "someTimestamp" ); } From 98d145e87d5e1f5e3f6f8905235093a81c7103bb Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 09:26:03 +0200 Subject: [PATCH 47/86] Move pollInterval config default to RebazerConfig --- .../org/retest/rebazer/config/RebazerConfig.java | 12 ++++++++---- .../org/retest/rebazer/service/HandleServices.java | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index c758469..19ddf22 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -14,12 +14,16 @@ @ConfigurationProperties( "rebazer" ) public class RebazerConfig { - private String workspace = "./rebazer-workspace"; - private int garbageCollectionCountdown = 20; /** - * For default value see {@link org.retest.rebazer.service.HandleServices#pollToHandleAllPullRequests()} + * Values used for {@link org.retest.rebazer.service.HandleServices#pollToHandleAllPullRequests()} */ - private long pollInterval; + public final static String POLL_INTERVAL_KEY = "rebazer.pollInterval"; + public final static int POLL_INTERVAL_DEFAULT = 60; + private long pollInterval = POLL_INTERVAL_DEFAULT; + + private String workspace = "./rebazer-workspace"; + private int garbageCollectionCountdown = 20; + private List hosts; @Data diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index d3bb80d..91191a2 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -25,7 +25,8 @@ public class HandleServices { private final RestTemplateBuilder builder; private Repository provider; - @Scheduled( fixedDelayString = "${rebazer.pollInterval:60}000" ) + @Scheduled( fixedDelayString = "${" + RebazerConfig.POLL_INTERVAL_KEY + ":" + RebazerConfig.POLL_INTERVAL_DEFAULT + + "}000" ) public void pollToHandleAllPullRequests() { for ( final RepositoryHost host : config.getHosts() ) { for ( final Team team : host.getTeams() ) { From 2eadbf2480b5eb509840814543df12e8454a5ee0 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 09:30:41 +0200 Subject: [PATCH 48/86] Refactore pollToHandleAllPullRequests --- .../rebazer/service/HandleServices.java | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index 91191a2..44ff4c9 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -28,27 +28,31 @@ public class HandleServices { @Scheduled( fixedDelayString = "${" + RebazerConfig.POLL_INTERVAL_KEY + ":" + RebazerConfig.POLL_INTERVAL_DEFAULT + "}000" ) public void pollToHandleAllPullRequests() { - for ( final RepositoryHost host : config.getHosts() ) { - for ( final Team team : host.getTeams() ) { - for ( final RepositoryConfig repo : team.getRepos() ) { - log.debug( "Processing {}.", repo ); - switch ( host.getType() ) { - case BITBUCKET: - provider = new BitbucketService( team, repo, builder ); - break; - case GITHUB: - provider = new GithubService( team, repo, builder ); - break; - default: - log.info( "The hosting Service via: {} is not supported", host.getType() ); - } - for ( final PullRequest pr : provider.getAllPullRequests( repo ) ) { - handlePR( provider, repo, pr ); - } - } - } - } + config.getHosts().forEach( host -> { + host.getTeams().forEach( team -> { + team.getRepos().forEach( repo -> { + handleRepo( host, team, repo ); + } ); + } ); + } ); + } + private void handleRepo( final RepositoryHost host, final Team team, final RepositoryConfig repo ) { + log.debug( "Processing {}.", repo ); + switch ( host.getType() ) { + case BITBUCKET: + provider = new BitbucketService( team, repo, builder ); + break; + case GITHUB: + provider = new GithubService( team, repo, builder ); + break; + default: + log.info( "The hosting Service via: {} is not supported", host.getType() ); + } + for ( final PullRequest pr : provider.getAllPullRequests( repo ) ) { + handlePR( provider, repo, pr ); + } + log.debug( "Processing done for {}.", repo ); } public void handlePR( final Repository provider, final RepositoryConfig repositories, From 8de817912ccaf3989d625267a49213f536037a53 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 09:36:31 +0200 Subject: [PATCH 49/86] Set sane default in application.yml.example for pollInterval --- .../java/org/retest/rebazer/service/HandleServices.java | 6 ++++-- src/main/resources/application.yml.example | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/service/HandleServices.java index 44ff4c9..5607604 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/service/HandleServices.java @@ -1,5 +1,8 @@ package org.retest.rebazer.service; +import static org.retest.rebazer.config.RebazerConfig.POLL_INTERVAL_DEFAULT; +import static org.retest.rebazer.config.RebazerConfig.POLL_INTERVAL_KEY; + import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryHost; @@ -25,8 +28,7 @@ public class HandleServices { private final RestTemplateBuilder builder; private Repository provider; - @Scheduled( fixedDelayString = "${" + RebazerConfig.POLL_INTERVAL_KEY + ":" + RebazerConfig.POLL_INTERVAL_DEFAULT - + "}000" ) + @Scheduled( fixedDelayString = "${" + POLL_INTERVAL_KEY + ":" + POLL_INTERVAL_DEFAULT + "}000" ) public void pollToHandleAllPullRequests() { config.getHosts().forEach( host -> { host.getTeams().forEach( team -> { diff --git a/src/main/resources/application.yml.example b/src/main/resources/application.yml.example index 29f3197..cc45c0c 100644 --- a/src/main/resources/application.yml.example +++ b/src/main/resources/application.yml.example @@ -5,7 +5,7 @@ spring: rebazer: workspace: ./rebazer-workspace garbageCollectionCountdown: 20 - pollInterval: 10000 + pollInterval: 60 hosts: - type: BITBUCKET url: https://bitbucket.org/ From ea096a2c93de8e358cbb1d1f0b80d08cfe664a3b Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 09:55:05 +0200 Subject: [PATCH 50/86] Refactore extract RebaseService.setupRepo() --- .../org/retest/rebazer/service/RebaseService.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 416489a..15b0adb 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -46,16 +46,21 @@ public RebaseService( final RebazerConfig config ) { config.getHosts().forEach( host -> { host.getTeams().forEach( team -> { team.getRepos().forEach( repo -> { - repoCredentials.put( repo.getName(), - new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ) ); - final Git localRepo = createUrl( config, host, team, repoCredentials.get( repo.getName() ), repo ); - repoGit.put( repo.getName(), localRepo ); - cleanUp( repo ); + setupRepo( config, host, team, repo ); } ); } ); } ); } + private void setupRepo( final RebazerConfig config, final RepositoryHost host, final Team team, + final RepositoryConfig repo ) { + repoCredentials.put( repo.getName(), + new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ) ); + final Git localRepo = createUrl( config, host, team, repoCredentials.get( repo.getName() ), repo ); + repoGit.put( repo.getName(), localRepo ); + cleanUp( repo ); + } + private Git createUrl( final RebazerConfig config, final RepositoryHost host, final Team team, CredentialsProvider credentials, final RepositoryConfig repo ) { credentials = repoCredentials.get( repo.getName() ); From a0e42c80a53dc6f74fd6b93fdc9ef4c2a2738605 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 10:01:20 +0200 Subject: [PATCH 51/86] Remove dupplicate variable --- src/main/java/org/retest/rebazer/service/RebaseService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 15b0adb..252260b 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -62,8 +62,7 @@ private void setupRepo( final RebazerConfig config, final RepositoryHost host, f } private Git createUrl( final RebazerConfig config, final RepositoryHost host, final Team team, - CredentialsProvider credentials, final RepositoryConfig repo ) { - credentials = repoCredentials.get( repo.getName() ); + final CredentialsProvider credentials, final RepositoryConfig repo ) { final File repoFolder = new File( config.getWorkspace(), repo.getName() ); Git localRepo = null; repoUrl.put( repo.getName(), host.getUrl() + team.getName() + "/" + repo.getName() + ".git" ); From b193128a7e4963f40f797330997418071140539e Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 10:02:02 +0200 Subject: [PATCH 52/86] Remove obsolete RebaseService.repoUrl --- .../java/org/retest/rebazer/service/RebaseService.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 252260b..47a1de5 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -37,7 +37,6 @@ public class RebaseService { private final Map repoCredentials = new HashMap<>(); private final Map repoGit = new HashMap<>(); - private final Map repoUrl = new HashMap<>(); @Autowired public RebaseService( final RebazerConfig config ) { @@ -64,13 +63,12 @@ private void setupRepo( final RebazerConfig config, final RepositoryHost host, f private Git createUrl( final RebazerConfig config, final RepositoryHost host, final Team team, final CredentialsProvider credentials, final RepositoryConfig repo ) { final File repoFolder = new File( config.getWorkspace(), repo.getName() ); - Git localRepo = null; - repoUrl.put( repo.getName(), host.getUrl() + team.getName() + "/" + repo.getName() + ".git" ); - return localRepo = checkRepoFolder( credentials, repoFolder, localRepo, repoUrl.get( repo.getName() ) ); + final String url = host.getUrl() + "/" + team.getName() + "/" + repo.getName() + ".git"; + return checkRepoFolder( credentials, repoFolder, url ); } - private Git checkRepoFolder( final CredentialsProvider credentials, final File repoFolder, Git localRepo, - final String repoUrl ) { + private Git checkRepoFolder( final CredentialsProvider credentials, final File repoFolder, final String repoUrl ) { + Git localRepo = null; if ( repoFolder.exists() ) { localRepo = tryToOpenExistingRepoAndCheckRemote( repoFolder, repoUrl ); if ( localRepo == null ) { From 3f7df38770308ce1c18da0dedc716a151ef4028f Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 10:13:47 +0200 Subject: [PATCH 53/86] RebaseService refactoring Rename member variables Use RepositoryConfig as map key Use RebazerConfig only to setup member variables --- .../retest/rebazer/service/RebaseService.java | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 47a1de5..3a32bcb 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -31,38 +31,42 @@ @Service public class RebaseService { - private final RebazerConfig config; + private final String workspace; + private final int gcCountdownResetValue; - private int currentGcCountdown; + private int gcCountdownCurrent; - private final Map repoCredentials = new HashMap<>(); - private final Map repoGit = new HashMap<>(); + private final Map repoCredentials = new HashMap<>(); + private final Map repoGit = new HashMap<>(); @Autowired public RebaseService( final RebazerConfig config ) { - this.config = config; - currentGcCountdown = config.getGarbageCollectionCountdown(); + workspace = config.getWorkspace(); + gcCountdownResetValue = config.getGarbageCollectionCountdown(); + gcCountdownCurrent = config.getGarbageCollectionCountdown(); + config.getHosts().forEach( host -> { host.getTeams().forEach( team -> { team.getRepos().forEach( repo -> { - setupRepo( config, host, team, repo ); + setupRepo( host, team, repo ); } ); } ); } ); } - private void setupRepo( final RebazerConfig config, final RepositoryHost host, final Team team, - final RepositoryConfig repo ) { - repoCredentials.put( repo.getName(), - new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ) ); - final Git localRepo = createUrl( config, host, team, repoCredentials.get( repo.getName() ), repo ); - repoGit.put( repo.getName(), localRepo ); + private void setupRepo( final RepositoryHost host, final Team team, final RepositoryConfig repo ) { + final CredentialsProvider credentials = + new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); + final Git localRepo = createUrl( host, team, credentials, repo ); + + repoCredentials.put( repo, credentials ); + repoGit.put( repo, localRepo ); cleanUp( repo ); } - private Git createUrl( final RebazerConfig config, final RepositoryHost host, final Team team, - final CredentialsProvider credentials, final RepositoryConfig repo ) { - final File repoFolder = new File( config.getWorkspace(), repo.getName() ); + private Git createUrl( final RepositoryHost host, final Team team, final CredentialsProvider credentials, + final RepositoryConfig repo ) { + final File repoFolder = new File( workspace, repo.getName() ); final String url = host.getUrl() + "/" + team.getName() + "/" + repo.getName() + ".git"; return checkRepoFolder( credentials, repoFolder, url ); } @@ -119,8 +123,8 @@ public boolean rebase( final RepositoryConfig repo, final PullRequest pullReques log.info( "Rebasing {}.", pullRequest ); try { - final Git repository = repoGit.get( repo.getName() ); - final CredentialsProvider credentials = repoCredentials.get( repo.getName() ); + final Git repository = repoGit.get( repo ); + final CredentialsProvider credentials = repoCredentials.get( repo ); repository.fetch().setCredentialsProvider( credentials ).setRemoveDeletedRefs( true ).call(); repository.checkout().setCreateBranch( true ).setName( pullRequest.getSource() ) .setStartPoint( "origin/" + pullRequest.getSource() ).call(); @@ -158,7 +162,7 @@ public boolean rebase( final RepositoryConfig repo, final PullRequest pullReques @SneakyThrows private void cleanUp( final RepositoryConfig repo ) { - final Git repository = repoGit.get( repo.getName() ); + final Git repository = repoGit.get( repo ); resetAndRemoveUntrackedFiles( repository ); repository.checkout().setName( "remotes/origin/" + repo.getBranch() ).call(); removeAllLocalBranches( repository ); @@ -194,10 +198,10 @@ private void removeAllLocalBranches( final Git repository ) } private void triggerGc( final Git repository ) throws GitAPIException { - currentGcCountdown--; - if ( currentGcCountdown == 0 ) { - currentGcCountdown = config.getGarbageCollectionCountdown(); - log.info( "Running git gc on {}, next gc after {} rebases.", repository, currentGcCountdown ); + gcCountdownCurrent--; + if ( gcCountdownCurrent == 0 ) { + gcCountdownCurrent = gcCountdownResetValue; + log.info( "Running git gc on {}, next gc after {} rebases.", repository, gcCountdownCurrent ); repository.gc() // .setPrunePreserved( true ) // .setExpire( null ) // From 717a7172f36da3f52eaa07615fdfb4a4f9bcb3b9 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 16:07:26 +0200 Subject: [PATCH 54/86] Extract GitRepoCleaner code in seperate class --- .../rebazer/service/GitRepoCleaner.java | 60 +++++++++++++++++++ .../retest/rebazer/service/RebaseService.java | 56 ++--------------- 2 files changed, 64 insertions(+), 52 deletions(-) create mode 100644 src/main/java/org/retest/rebazer/service/GitRepoCleaner.java diff --git a/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java new file mode 100644 index 0000000..b91509c --- /dev/null +++ b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java @@ -0,0 +1,60 @@ +package org.retest.rebazer.service; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.ResetCommand.ResetType; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class GitRepoCleaner { + + private final int gcCountdownResetValue; + private int gcCountdownCurrent; + + public GitRepoCleaner( final int gcCountdown ) { + gcCountdownResetValue = gcCountdown; + gcCountdownCurrent = gcCountdown; + } + + public void cleanUp( final Git repoGit, final String fallbackBranchName ) { + resetAndRemoveUntrackedFiles( repoGit ); + checkoutFallbackBranch( repoGit, fallbackBranchName ); + removeAllLocalBranches( repoGit ); + triggerGcIfNeeded( repoGit ); + } + + @SneakyThrows + private void resetAndRemoveUntrackedFiles( final Git gitRepo ) { + gitRepo.clean().setCleanDirectories( true ).setForce( true ).setIgnore( false ).call(); + gitRepo.reset().setMode( ResetType.HARD ).call(); + } + + @SneakyThrows + private void checkoutFallbackBranch( final Git repoGit, final String fallbackBranchName ) { + repoGit.checkout().setName( "remotes/origin/" + fallbackBranchName ).call(); + } + + @SneakyThrows + private void removeAllLocalBranches( final Git repoGit ) { + final String[] localBranches = repoGit.branchList() // + .call().stream() // + .filter( r -> r.getName() // + .startsWith( "refs/heads/" ) ) // + .map( r -> r.getName() ) // + .toArray( String[]::new ); + + repoGit.branchDelete().setForce( true ).setBranchNames( localBranches ).call(); + } + + @SneakyThrows + private void triggerGcIfNeeded( final Git repoGit ) { + gcCountdownCurrent--; + if ( gcCountdownCurrent == 0 ) { + gcCountdownCurrent = gcCountdownResetValue; + log.info( "Running git gc on {}, next gc after {} cleanups.", repoGit, gcCountdownResetValue ); + repoGit.gc().setPrunePreserved( true ).setExpire( null ).call(); + } + } + +} diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 3a32bcb..04447a6 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -32,9 +32,7 @@ public class RebaseService { private final String workspace; - private final int gcCountdownResetValue; - - private int gcCountdownCurrent; + private final GitRepoCleaner cleaner; private final Map repoCredentials = new HashMap<>(); private final Map repoGit = new HashMap<>(); @@ -42,8 +40,7 @@ public class RebaseService { @Autowired public RebaseService( final RebazerConfig config ) { workspace = config.getWorkspace(); - gcCountdownResetValue = config.getGarbageCollectionCountdown(); - gcCountdownCurrent = config.getGarbageCollectionCountdown(); + cleaner = new GitRepoCleaner( config.getGarbageCollectionCountdown() ); config.getHosts().forEach( host -> { host.getTeams().forEach( team -> { @@ -160,53 +157,8 @@ public boolean rebase( final RepositoryConfig repo, final PullRequest pullReques } } - @SneakyThrows - private void cleanUp( final RepositoryConfig repo ) { - final Git repository = repoGit.get( repo ); - resetAndRemoveUntrackedFiles( repository ); - repository.checkout().setName( "remotes/origin/" + repo.getBranch() ).call(); - removeAllLocalBranches( repository ); - triggerGc( repository ); - } - - private void resetAndRemoveUntrackedFiles( final Git repository ) - throws GitAPIException, CheckoutConflictException { - repository.clean() // - .setCleanDirectories( true ) // - .setForce( true ) // - .setIgnore( false ) // - .call(); // - - repository.reset() // - .setMode( ResetType.HARD ) // - .call(); // - } - - private void removeAllLocalBranches( final Git repository ) - throws GitAPIException, NotMergedException, CannotDeleteCurrentBranchException { - final String[] localBranches = repository.branchList() // - .call().stream() // - .filter( r -> r.getName() // - .startsWith( "refs/heads/" ) ) // - .map( r -> r.getName() ) // - .toArray( String[]::new ); // - - repository.branchDelete() // - .setForce( true ) // - .setBranchNames( localBranches ) // - .call(); // - } - - private void triggerGc( final Git repository ) throws GitAPIException { - gcCountdownCurrent--; - if ( gcCountdownCurrent == 0 ) { - gcCountdownCurrent = gcCountdownResetValue; - log.info( "Running git gc on {}, next gc after {} rebases.", repository, gcCountdownCurrent ); - repository.gc() // - .setPrunePreserved( true ) // - .setExpire( null ) // - .call(); // - } + private void cleanUp( final RepositoryConfig repoConfig ) { + cleaner.cleanUp( repoGit.get( repoConfig ), repoConfig.getBranch() ); } } From aa008c2c33cfc14fe67460b2a72f8e910255b3c8 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 16:12:06 +0200 Subject: [PATCH 55/86] Improve code readability in GitRepoCleaner.removeAllLocalBranches() --- .../org/retest/rebazer/service/GitRepoCleaner.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java index b91509c..506344f 100644 --- a/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java +++ b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java @@ -1,7 +1,10 @@ package org.retest.rebazer.service; +import java.util.List; + import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ResetCommand.ResetType; +import org.eclipse.jgit.lib.Ref; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -37,11 +40,10 @@ private void checkoutFallbackBranch( final Git repoGit, final String fallbackBra @SneakyThrows private void removeAllLocalBranches( final Git repoGit ) { - final String[] localBranches = repoGit.branchList() // - .call().stream() // - .filter( r -> r.getName() // - .startsWith( "refs/heads/" ) ) // - .map( r -> r.getName() ) // + final List allBranches = repoGit.branchList().call(); + final String[] localBranches = allBranches.stream() // + .map( branch -> branch.getName() ) // + .filter( name -> name.startsWith( "refs/heads/" ) ) // .toArray( String[]::new ); repoGit.branchDelete().setForce( true ).setBranchNames( localBranches ).call(); From 15f203ef6a27a23966fcca8bb057245a6744a82e Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 16:13:01 +0200 Subject: [PATCH 56/86] Refactore RebaseService --- .../retest/rebazer/service/RebaseService.java | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 04447a6..f36b536 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -1,7 +1,6 @@ package org.retest.rebazer.service; import java.io.File; -import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -9,11 +8,6 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RebaseCommand.Operation; import org.eclipse.jgit.api.RebaseResult; -import org.eclipse.jgit.api.ResetCommand.ResetType; -import org.eclipse.jgit.api.errors.CannotDeleteCurrentBranchException; -import org.eclipse.jgit.api.errors.CheckoutConflictException; -import org.eclipse.jgit.api.errors.GitAPIException; -import org.eclipse.jgit.api.errors.NotMergedException; import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.retest.rebazer.config.RebazerConfig; @@ -31,7 +25,7 @@ @Service public class RebaseService { - private final String workspace; + private final File workspace; private final GitRepoCleaner cleaner; private final Map repoCredentials = new HashMap<>(); @@ -39,7 +33,7 @@ public class RebaseService { @Autowired public RebaseService( final RebazerConfig config ) { - workspace = config.getWorkspace(); + workspace = new File( config.getWorkspace() ).getAbsoluteFile(); cleaner = new GitRepoCleaner( config.getGarbageCollectionCountdown() ); config.getHosts().forEach( host -> { @@ -52,38 +46,44 @@ public RebaseService( final RebazerConfig config ) { } private void setupRepo( final RepositoryHost host, final Team team, final RepositoryConfig repo ) { - final CredentialsProvider credentials = - new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); - final Git localRepo = createUrl( host, team, credentials, repo ); + final CredentialsProvider credentials = repoCredentials( team ); + final File repoFolder = repoFolder( host, team, repo ); + final String url = repoUrl( host, team, repo ); + + final Git localRepo = setupLocalGitRepo( credentials, repoFolder, url ); repoCredentials.put( repo, credentials ); repoGit.put( repo, localRepo ); cleanUp( repo ); } - private Git createUrl( final RepositoryHost host, final Team team, final CredentialsProvider credentials, - final RepositoryConfig repo ) { - final File repoFolder = new File( workspace, repo.getName() ); - final String url = host.getUrl() + "/" + team.getName() + "/" + repo.getName() + ".git"; - return checkRepoFolder( credentials, repoFolder, url ); + private CredentialsProvider repoCredentials( final Team team ) { + return new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); + } + + private File repoFolder( final RepositoryHost host, final Team team, final RepositoryConfig repo ) { + return new File( new File( new File( workspace, host.getUrl().getHost() ), team.getName() ), repo.getName() ); + } + + private String repoUrl( final RepositoryHost host, final Team team, final RepositoryConfig repo ) { + return host.getUrl() + "/" + team.getName() + "/" + repo.getName() + ".git"; } - private Git checkRepoFolder( final CredentialsProvider credentials, final File repoFolder, final String repoUrl ) { - Git localRepo = null; + private Git setupLocalGitRepo( final CredentialsProvider credentials, final File repoFolder, + final String repoUrl ) { if ( repoFolder.exists() ) { - localRepo = tryToOpenExistingRepoAndCheckRemote( repoFolder, repoUrl ); - if ( localRepo == null ) { - try { - FileUtils.deleteDirectory( repoFolder ); - } catch ( final IOException e ) { - throw new RuntimeException( e ); - } + final Git localRepo = tryToOpenExistingRepoAndCheckRemote( repoFolder, repoUrl ); + if ( localRepo != null ) { + return localRepo; } + deleteDirectory( repoFolder ); } - if ( localRepo == null ) { - localRepo = cloneNewRepo( repoFolder, repoUrl, credentials ); - } - return localRepo; + return cloneNewRepo( repoFolder, repoUrl, credentials ); + } + + @SneakyThrows + private void deleteDirectory( final File repoFolder ) { + FileUtils.deleteDirectory( repoFolder ); } private static Git tryToOpenExistingRepoAndCheckRemote( final File repoFolder, final String expectedRepoUrl ) { From 9b733234db45e7b7ec07d92141fcefbc8468d078 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 18:42:54 +0200 Subject: [PATCH 57/86] Better name for classes and better package structure --- .../rebazer/{service => }/KnownProvider.java | 2 +- .../HandleServices.java => RebazerService.java} | 17 +++++++++++------ .../retest/rebazer/config/RebazerConfig.java | 4 ++-- .../BitbucketConnector.java} | 6 +++--- .../GithubConnector.java} | 6 +++--- .../RepositoryConnector.java} | 4 ++-- .../service/PullRequestLastUpdateStore.java | 8 ++++---- .../BitbucketConnectorTest.java} | 13 +++++++------ .../GithubConnectorTest.java} | 12 ++++++------ 9 files changed, 39 insertions(+), 33 deletions(-) rename src/main/java/org/retest/rebazer/{service => }/KnownProvider.java (60%) rename src/main/java/org/retest/rebazer/{service/HandleServices.java => RebazerService.java} (83%) rename src/main/java/org/retest/rebazer/{service/BitbucketService.java => connector/BitbucketConnector.java} (96%) rename src/main/java/org/retest/rebazer/{service/GithubService.java => connector/GithubConnector.java} (96%) rename src/main/java/org/retest/rebazer/{service/Repository.java => connector/RepositoryConnector.java} (86%) rename src/test/java/org/retest/rebazer/{service/BitbucketServiceTest.java => connector/BitbucketConnectorTest.java} (94%) rename src/test/java/org/retest/rebazer/{service/GithubServiceTest.java => connector/GithubConnectorTest.java} (95%) diff --git a/src/main/java/org/retest/rebazer/service/KnownProvider.java b/src/main/java/org/retest/rebazer/KnownProvider.java similarity index 60% rename from src/main/java/org/retest/rebazer/service/KnownProvider.java rename to src/main/java/org/retest/rebazer/KnownProvider.java index c887607..4890d0a 100644 --- a/src/main/java/org/retest/rebazer/service/KnownProvider.java +++ b/src/main/java/org/retest/rebazer/KnownProvider.java @@ -1,4 +1,4 @@ -package org.retest.rebazer.service; +package org.retest.rebazer; public enum KnownProvider { diff --git a/src/main/java/org/retest/rebazer/service/HandleServices.java b/src/main/java/org/retest/rebazer/RebazerService.java similarity index 83% rename from src/main/java/org/retest/rebazer/service/HandleServices.java rename to src/main/java/org/retest/rebazer/RebazerService.java index 5607604..1ee6f77 100644 --- a/src/main/java/org/retest/rebazer/service/HandleServices.java +++ b/src/main/java/org/retest/rebazer/RebazerService.java @@ -1,4 +1,4 @@ -package org.retest.rebazer.service; +package org.retest.rebazer; import static org.retest.rebazer.config.RebazerConfig.POLL_INTERVAL_DEFAULT; import static org.retest.rebazer.config.RebazerConfig.POLL_INTERVAL_KEY; @@ -7,7 +7,12 @@ import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryHost; import org.retest.rebazer.config.RebazerConfig.Team; +import org.retest.rebazer.connector.BitbucketConnector; +import org.retest.rebazer.connector.GithubConnector; +import org.retest.rebazer.connector.RepositoryConnector; import org.retest.rebazer.domain.PullRequest; +import org.retest.rebazer.service.PullRequestLastUpdateStore; +import org.retest.rebazer.service.RebaseService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.scheduling.annotation.Scheduled; @@ -19,14 +24,14 @@ @Slf4j @Service @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) -public class HandleServices { +public class RebazerService { private final RebaseService rebaseService; private final RebazerConfig config; private final PullRequestLastUpdateStore pullRequestLastUpdateStore; private final RestTemplateBuilder builder; - private Repository provider; + private RepositoryConnector provider; @Scheduled( fixedDelayString = "${" + POLL_INTERVAL_KEY + ":" + POLL_INTERVAL_DEFAULT + "}000" ) public void pollToHandleAllPullRequests() { @@ -43,10 +48,10 @@ private void handleRepo( final RepositoryHost host, final Team team, final Repos log.debug( "Processing {}.", repo ); switch ( host.getType() ) { case BITBUCKET: - provider = new BitbucketService( team, repo, builder ); + provider = new BitbucketConnector( team, repo, builder ); break; case GITHUB: - provider = new GithubService( team, repo, builder ); + provider = new GithubConnector( team, repo, builder ); break; default: log.info( "The hosting Service via: {} is not supported", host.getType() ); @@ -57,7 +62,7 @@ private void handleRepo( final RepositoryHost host, final Team team, final Repos log.debug( "Processing done for {}.", repo ); } - public void handlePR( final Repository provider, final RepositoryConfig repositories, + public void handlePR( final RepositoryConnector provider, final RepositoryConfig repositories, final PullRequest pullRequest ) { log.debug( "Processing {}.", pullRequest ); diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 19ddf22..91c30ba 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -3,7 +3,7 @@ import java.net.URL; import java.util.List; -import org.retest.rebazer.service.KnownProvider; +import org.retest.rebazer.KnownProvider; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -15,7 +15,7 @@ public class RebazerConfig { /** - * Values used for {@link org.retest.rebazer.service.HandleServices#pollToHandleAllPullRequests()} + * Values used for {@link org.retest.rebazer.RebazerService#pollToHandleAllPullRequests()} */ public final static String POLL_INTERVAL_KEY = "rebazer.pollInterval"; public final static int POLL_INTERVAL_DEFAULT = 60; diff --git a/src/main/java/org/retest/rebazer/service/BitbucketService.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java similarity index 96% rename from src/main/java/org/retest/rebazer/service/BitbucketService.java rename to src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index e038a4a..0a99e5b 100644 --- a/src/main/java/org/retest/rebazer/service/BitbucketService.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -1,4 +1,4 @@ -package org.retest.rebazer.service; +package org.retest.rebazer.connector; import java.util.ArrayList; import java.util.HashMap; @@ -20,7 +20,7 @@ @Service @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) -public class BitbucketService implements Repository { +public class BitbucketConnector implements RepositoryConnector { private final static String baseUrlV1 = "https://api.bitbucket.org/1.0"; private final static String baseUrlV2 = "https://api.bitbucket.org/2.0"; @@ -31,7 +31,7 @@ public class BitbucketService implements Repository { private RestTemplate legacyTemplate; private RestTemplate template; - public BitbucketService( final Team team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { + public BitbucketConnector( final Team team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { this.team = team; this.repo = repo; diff --git a/src/main/java/org/retest/rebazer/service/GithubService.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java similarity index 96% rename from src/main/java/org/retest/rebazer/service/GithubService.java rename to src/main/java/org/retest/rebazer/connector/GithubConnector.java index c10f234..882f326 100644 --- a/src/main/java/org/retest/rebazer/service/GithubService.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -1,4 +1,4 @@ -package org.retest.rebazer.service; +package org.retest.rebazer.connector; import java.util.ArrayList; import java.util.HashMap; @@ -22,7 +22,7 @@ @Slf4j @Service @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) -public class GithubService implements Repository { +public class GithubConnector implements RepositoryConnector { private final static String baseUrl = "https://api.github.com/"; @@ -31,7 +31,7 @@ public class GithubService implements Repository { private RestTemplate template; - public GithubService( final Team team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { + public GithubConnector( final Team team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { this.team = team; this.repo = repo; diff --git a/src/main/java/org/retest/rebazer/service/Repository.java b/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java similarity index 86% rename from src/main/java/org/retest/rebazer/service/Repository.java rename to src/main/java/org/retest/rebazer/connector/RepositoryConnector.java index 58620c1..db5657a 100644 --- a/src/main/java/org/retest/rebazer/service/Repository.java +++ b/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java @@ -1,11 +1,11 @@ -package org.retest.rebazer.service; +package org.retest.rebazer.connector; import java.util.List; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.domain.PullRequest; -public interface Repository { +public interface RepositoryConnector { PullRequest getLatestUpdate( PullRequest pullRequest ); diff --git a/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java b/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java index 6eb6451..9074061 100644 --- a/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java +++ b/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java @@ -12,7 +12,7 @@ public class PullRequestLastUpdateStore { private final Map> pullRequestUpdateStates = new HashMap<>(); - void setHandled( final RepositoryConfig repo, final PullRequest pullRequest ) { + public void setHandled( final RepositoryConfig repo, final PullRequest pullRequest ) { Map repoMap = pullRequestUpdateStates.get( repo ); if ( repoMap == null ) { repoMap = new HashMap<>(); @@ -21,19 +21,19 @@ void setHandled( final RepositoryConfig repo, final PullRequest pullRequest ) { repoMap.put( pullRequest.getId(), pullRequest.getLastUpdate() ); } - String getLastDate( final RepositoryConfig repo, final PullRequest pullRequest ) { + public String getLastDate( final RepositoryConfig repo, final PullRequest pullRequest ) { final Map repoMap = pullRequestUpdateStates.get( repo ); return repoMap != null ? repoMap.get( pullRequest.getId() ) : null; } - void resetAllInThisRepo( final RepositoryConfig repo ) { + public void resetAllInThisRepo( final RepositoryConfig repo ) { final Map repoMap = pullRequestUpdateStates.get( repo ); if ( repoMap != null ) { repoMap.clear(); } } - boolean isHandled( final RepositoryConfig repo, final PullRequest pullRequest ) { + public boolean isHandled( final RepositoryConfig repo, final PullRequest pullRequest ) { return pullRequest.getLastUpdate().equals( getLastDate( repo, pullRequest ) ); } diff --git a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java b/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java similarity index 94% rename from src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java rename to src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java index 0743ef6..43064aa 100644 --- a/src/test/java/org/retest/rebazer/service/BitbucketServiceTest.java +++ b/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java @@ -1,4 +1,4 @@ -package org.retest.rebazer.service; +package org.retest.rebazer.connector; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -19,20 +19,21 @@ import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; +import org.retest.rebazer.service.PullRequestLastUpdateStore; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.web.client.RestTemplate; import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; -public class BitbucketServiceTest { +public class BitbucketConnectorTest { PullRequestLastUpdateStore pullRequestUpdateStates; RestTemplate template; RebazerConfig config; Team team; - BitbucketService cut; + BitbucketConnector cut; @Before public void setUp() { @@ -46,13 +47,13 @@ public void setUp() { when( builder.build() ).thenReturn( template ); pullRequestUpdateStates = mock( PullRequestLastUpdateStore.class ); - cut = new BitbucketService( team, repo, builder ); + cut = new BitbucketConnector( team, repo, builder ); } @Test public void rebaseNeeded_should_return_false_if_headOfBranch_is_equal_to_lastCommonCommitId() { final PullRequest pullRequest = mock( PullRequest.class ); - final BitbucketService cut = mock( BitbucketService.class ); + final BitbucketConnector cut = mock( BitbucketConnector.class ); final String head = "12325345923759135"; when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( head ); @@ -64,7 +65,7 @@ public void rebaseNeeded_should_return_false_if_headOfBranch_is_equal_to_lastCom @Test public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCommonCommitId() { final PullRequest pullRequest = mock( PullRequest.class ); - final BitbucketService cut = mock( BitbucketService.class ); + final BitbucketConnector cut = mock( BitbucketConnector.class ); final String head = "12325345923759135"; final String lcci = "21342343253253452"; when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); diff --git a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java b/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java similarity index 95% rename from src/test/java/org/retest/rebazer/service/GithubServiceTest.java rename to src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java index 8217765..fb170f2 100644 --- a/src/test/java/org/retest/rebazer/service/GithubServiceTest.java +++ b/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java @@ -1,4 +1,4 @@ -package org.retest.rebazer.service; +package org.retest.rebazer.connector; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -25,13 +25,13 @@ import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; -public class GithubServiceTest { +public class GithubConnectorTest { RestTemplate template; RebazerConfig config; Team team; - GithubService cut; + GithubConnector cut; @Before public void setUp() { @@ -44,13 +44,13 @@ public void setUp() { when( builder.rootUri( anyString() ) ).thenReturn( builder ); when( builder.build() ).thenReturn( template ); - cut = new GithubService( team, repo, builder ); + cut = new GithubConnector( team, repo, builder ); } @Test public void rebaseNeeded_should_return_false_if_headOfBranch_is_equal_to_lastCommonCommitId() { final PullRequest pullRequest = mock( PullRequest.class ); - final GithubService cut = mock( GithubService.class ); + final GithubConnector cut = mock( GithubConnector.class ); final String head = "12325345923759135"; when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); when( cut.getLastCommonCommitId( pullRequest ) ).thenReturn( head ); @@ -62,7 +62,7 @@ public void rebaseNeeded_should_return_false_if_headOfBranch_is_equal_to_lastCom @Test public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCommonCommitId() { final PullRequest pullRequest = mock( PullRequest.class ); - final GithubService cut = mock( GithubService.class ); + final GithubConnector cut = mock( GithubConnector.class ); final String head = "12325345923759135"; final String lcci = "21342343253253452"; when( cut.getHeadOfBranch( pullRequest ) ).thenReturn( head ); From 6175ce5fea89332e021ec8766a8787fd04dc6e54 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 18:47:18 +0200 Subject: [PATCH 58/86] Use @Service where it makes sense --- .../retest/rebazer/connector/BitbucketConnector.java | 5 ----- .../org/retest/rebazer/connector/GithubConnector.java | 9 ++------- .../org/retest/rebazer/service/GitRepoCleaner.java | 11 ++++++++--- .../rebazer/service/PullRequestLastUpdateStore.java | 4 ++-- .../org/retest/rebazer/service/RebaseService.java | 4 ++-- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index 0a99e5b..8cc3b51 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -8,18 +8,13 @@ import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; -import lombok.RequiredArgsConstructor; -@Service -@RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class BitbucketConnector implements RepositoryConnector { private final static String baseUrlV1 = "https://api.bitbucket.org/1.0"; diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index 882f326..9a42450 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -8,28 +8,23 @@ import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.Team; import org.retest.rebazer.domain.PullRequest; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j -@Service -@RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class GithubConnector implements RepositoryConnector { private final static String baseUrl = "https://api.github.com/"; - private Team team; + private final Team team; RepositoryConfig repo; - private RestTemplate template; + private final RestTemplate template; public GithubConnector( final Team team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { this.team = team; diff --git a/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java index 506344f..a15483b 100644 --- a/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java +++ b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java @@ -5,19 +5,24 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ResetCommand.ResetType; import org.eclipse.jgit.lib.Ref; +import org.retest.rebazer.config.RebazerConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @Slf4j +@Service public class GitRepoCleaner { private final int gcCountdownResetValue; private int gcCountdownCurrent; - public GitRepoCleaner( final int gcCountdown ) { - gcCountdownResetValue = gcCountdown; - gcCountdownCurrent = gcCountdown; + @Autowired + public GitRepoCleaner( final RebazerConfig config ) { + gcCountdownResetValue = config.getGarbageCollectionCountdown(); + gcCountdownCurrent = gcCountdownResetValue; } public void cleanUp( final Git repoGit, final String fallbackBranchName ) { diff --git a/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java b/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java index 9074061..b9938bb 100644 --- a/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java +++ b/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java @@ -5,9 +5,9 @@ import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.domain.PullRequest; -import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; -@Component +@Service public class PullRequestLastUpdateStore { private final Map> pullRequestUpdateStates = new HashMap<>(); diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index f36b536..e4bdc5a 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -32,9 +32,9 @@ public class RebaseService { private final Map repoGit = new HashMap<>(); @Autowired - public RebaseService( final RebazerConfig config ) { + public RebaseService( final RebazerConfig config, final GitRepoCleaner cleaner ) { + this.cleaner = cleaner; workspace = new File( config.getWorkspace() ).getAbsoluteFile(); - cleaner = new GitRepoCleaner( config.getGarbageCollectionCountdown() ); config.getHosts().forEach( host -> { host.getTeams().forEach( team -> { From fdfdadf8e100680a558dd5dd6ec8e86b351bb587 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 18:53:40 +0200 Subject: [PATCH 59/86] Refactoring: Sort methods in RepositoryConnector --- .../org/retest/rebazer/connector/RepositoryConnector.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java b/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java index db5657a..a837c8c 100644 --- a/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java +++ b/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java @@ -7,17 +7,17 @@ public interface RepositoryConnector { + List getAllPullRequests( RepositoryConfig repo ); + PullRequest getLatestUpdate( PullRequest pullRequest ); boolean isApproved( PullRequest pullRequest ); boolean rebaseNeeded( PullRequest pullRequest ); - void merge( PullRequest pullRequest ); - boolean greenBuildExists( PullRequest pullRequest ); - List getAllPullRequests( RepositoryConfig repo ); + void merge( PullRequest pullRequest ); void addComment( PullRequest pullRequest ); From e2760ec7563f36ff1553f0b0735a6d97817275e3 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 18:56:18 +0200 Subject: [PATCH 60/86] Centralise url handling in BitbucketConnector --- .../rebazer/connector/BitbucketConnector.java | 31 +++++++------------ .../connector/BitbucketConnectorTest.java | 3 +- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index 8cc3b51..017156a 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -20,21 +20,15 @@ public class BitbucketConnector implements RepositoryConnector { private final static String baseUrlV1 = "https://api.bitbucket.org/1.0"; private final static String baseUrlV2 = "https://api.bitbucket.org/2.0"; - private Team team; - RepositoryConfig repo; - - private RestTemplate legacyTemplate; - private RestTemplate template; + private final RestTemplate legacyTemplate; + private final RestTemplate template; public BitbucketConnector( final Team team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { - this.team = team; - this.repo = repo; + final String basePath = "/repositories/" + team.getName() + "/" + repo.getName(); - legacyTemplate = builder // - .basicAuthorization( team.getUser(), team.getPass() ) // - .rootUri( baseUrlV1 ) // - .build(); - template = builder.basicAuthorization( team.getUser(), team.getPass() ).rootUri( baseUrlV2 ).build(); + legacyTemplate = + builder.basicAuthorization( team.getUser(), team.getPass() ).rootUri( baseUrlV1 + basePath ).build(); + template = builder.basicAuthorization( team.getUser(), team.getPass() ).rootUri( baseUrlV2 + basePath ).build(); } @Override @@ -63,8 +57,7 @@ public boolean rebaseNeeded( final PullRequest pullRequest ) { } String getHeadOfBranch( final PullRequest pullRequest ) { - final String url = "/repositories/" + team.getName() + "/" + pullRequest.getRepo() + "/"; - return jsonPathForPath( url + "refs/branches/" + pullRequest.getDestination() ).read( "$.target.hash" ); + return jsonPathForPath( "/refs/branches/" + pullRequest.getDestination() ).read( "$.target.hash" ); } String getLastCommonCommitId( final PullRequest pullRequest ) { @@ -106,13 +99,11 @@ public boolean greenBuildExists( final PullRequest pullRequest ) { @Override public List getAllPullRequests( final RepositoryConfig repo ) { - final String urlPath = "/repositories/" + team.getName() + "/" + repo.getName() + "/pullrequests"; - final DocumentContext jp = jsonPathForPath( urlPath ); - return parsePullRequestsJson( repo, urlPath, jp ); + final DocumentContext jp = jsonPathForPath( "/pullrequests" ); + return parsePullRequestsJson( repo, jp ); } - public static List parsePullRequestsJson( final RepositoryConfig repo, final String urlPath, - final DocumentContext jp ) { + public List parsePullRequestsJson( final RepositoryConfig repo, final DocumentContext jp ) { final int numPullRequests = (int) jp.read( "$.size" ); final List results = new ArrayList<>( numPullRequests ); for ( int i = 0; i < numPullRequests; i++ ) { @@ -125,7 +116,7 @@ public static List parsePullRequestsJson( final RepositoryConfig re .repo( repo.getName() ) // .source( source ) // .destination( destination ) // - .url( urlPath + "/" + id ) // + .url( "/pullrequests/" + id ) // .lastUpdate( lastUpdate ) // .build() ); // } diff --git a/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java b/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java index 43064aa..efc88db 100644 --- a/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java +++ b/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java @@ -125,8 +125,7 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); final int expectedId = (int) documentContext.read( "$.values[0].id" ); - final String expectedUrl = - "/repositories/" + team.getName() + "/" + repo.getName() + "/pullrequests/" + expectedId; + final String expectedUrl = "/pullrequests/" + expectedId; final List expected = Arrays.asList( PullRequest.builder().id( expectedId ).repo( repo.getName() ) .source( documentContext.read( "$.values[0].source.branch.name" ) ) .destination( documentContext.read( "$.values[0].destination.branch.name" ) ).url( expectedUrl ) From 15bee35c24da79cd1356ecd28ef95acf39071601 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 19 Jul 2018 19:02:18 +0200 Subject: [PATCH 61/86] Better variable names and RepositoryConnector selction to KnownProvider --- .../org/retest/rebazer/KnownProvider.java | 19 ++++++++ .../org/retest/rebazer/RebazerService.java | 44 +++++++------------ 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/main/java/org/retest/rebazer/KnownProvider.java b/src/main/java/org/retest/rebazer/KnownProvider.java index 4890d0a..35207a3 100644 --- a/src/main/java/org/retest/rebazer/KnownProvider.java +++ b/src/main/java/org/retest/rebazer/KnownProvider.java @@ -1,8 +1,27 @@ package org.retest.rebazer; +import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; +import org.retest.rebazer.config.RebazerConfig.Team; +import org.retest.rebazer.connector.BitbucketConnector; +import org.retest.rebazer.connector.GithubConnector; +import org.retest.rebazer.connector.RepositoryConnector; +import org.springframework.boot.web.client.RestTemplateBuilder; + public enum KnownProvider { BITBUCKET, GITHUB; + public RepositoryConnector getRepository( final Team team, final RepositoryConfig repo, + final RestTemplateBuilder builder ) { + switch ( this ) { + case BITBUCKET: + return new BitbucketConnector( team, repo, builder ); + case GITHUB: + return new GithubConnector( team, repo, builder ); + default: + throw new RuntimeException( "No Repository defined for provider: " + this ); + } + } + } diff --git a/src/main/java/org/retest/rebazer/RebazerService.java b/src/main/java/org/retest/rebazer/RebazerService.java index 1ee6f77..b6f6f19 100644 --- a/src/main/java/org/retest/rebazer/RebazerService.java +++ b/src/main/java/org/retest/rebazer/RebazerService.java @@ -7,8 +7,6 @@ import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryHost; import org.retest.rebazer.config.RebazerConfig.Team; -import org.retest.rebazer.connector.BitbucketConnector; -import org.retest.rebazer.connector.GithubConnector; import org.retest.rebazer.connector.RepositoryConnector; import org.retest.rebazer.domain.PullRequest; import org.retest.rebazer.service.PullRequestLastUpdateStore; @@ -31,64 +29,54 @@ public class RebazerService { private final PullRequestLastUpdateStore pullRequestLastUpdateStore; private final RestTemplateBuilder builder; - private RepositoryConnector provider; @Scheduled( fixedDelayString = "${" + POLL_INTERVAL_KEY + ":" + POLL_INTERVAL_DEFAULT + "}000" ) public void pollToHandleAllPullRequests() { config.getHosts().forEach( host -> { host.getTeams().forEach( team -> { - team.getRepos().forEach( repo -> { - handleRepo( host, team, repo ); + team.getRepos().forEach( repoConfig -> { + handleRepo( host, team, repoConfig ); } ); } ); } ); } - private void handleRepo( final RepositoryHost host, final Team team, final RepositoryConfig repo ) { - log.debug( "Processing {}.", repo ); - switch ( host.getType() ) { - case BITBUCKET: - provider = new BitbucketConnector( team, repo, builder ); - break; - case GITHUB: - provider = new GithubConnector( team, repo, builder ); - break; - default: - log.info( "The hosting Service via: {} is not supported", host.getType() ); + private void handleRepo( final RepositoryHost host, final Team team, final RepositoryConfig repoConfig ) { + log.debug( "Processing {}.", repoConfig ); + final RepositoryConnector repoConnector = host.getType().getRepository( team, repoConfig, builder ); + for ( final PullRequest pullRequest : repoConnector.getAllPullRequests( repoConfig ) ) { + handlePullRequest( repoConnector, repoConfig, pullRequest ); } - for ( final PullRequest pr : provider.getAllPullRequests( repo ) ) { - handlePR( provider, repo, pr ); - } - log.debug( "Processing done for {}.", repo ); + log.debug( "Processing done for {}.", repoConfig ); } - public void handlePR( final RepositoryConnector provider, final RepositoryConfig repositories, + public void handlePullRequest( final RepositoryConnector provider, final RepositoryConfig repoConfig, final PullRequest pullRequest ) { log.debug( "Processing {}.", pullRequest ); - if ( pullRequestLastUpdateStore.isHandled( repositories, pullRequest ) ) { + if ( pullRequestLastUpdateStore.isHandled( repoConfig, pullRequest ) ) { log.info( "{} is unchanged since last run (last change: {}).", pullRequest, - pullRequestLastUpdateStore.getLastDate( repositories, pullRequest ) ); + pullRequestLastUpdateStore.getLastDate( repoConfig, pullRequest ) ); } else if ( !provider.greenBuildExists( pullRequest ) ) { log.info( "Waiting for green build of {}.", pullRequest ); - pullRequestLastUpdateStore.setHandled( repositories, pullRequest ); + pullRequestLastUpdateStore.setHandled( repoConfig, pullRequest ); } else if ( provider.rebaseNeeded( pullRequest ) ) { - if ( !rebaseService.rebase( repositories, pullRequest ) ) { + if ( !rebaseService.rebase( repoConfig, pullRequest ) ) { provider.addComment( pullRequest ); } // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called - pullRequestLastUpdateStore.setHandled( repositories, provider.getLatestUpdate( pullRequest ) ); + pullRequestLastUpdateStore.setHandled( repoConfig, provider.getLatestUpdate( pullRequest ) ); } else if ( !provider.isApproved( pullRequest ) ) { log.info( "Waiting for approval of {}.", pullRequest ); - pullRequestLastUpdateStore.setHandled( repositories, pullRequest ); + pullRequestLastUpdateStore.setHandled( repoConfig, pullRequest ); } else { log.info( "Merging pull request " + pullRequest ); provider.merge( pullRequest ); - pullRequestLastUpdateStore.resetAllInThisRepo( repositories ); + pullRequestLastUpdateStore.resetAllInThisRepo( repoConfig ); } } From 8eab324bf99cb3b7f9ca9ecafef584ab402570a1 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Fri, 20 Jul 2018 06:15:13 +0200 Subject: [PATCH 62/86] Rename RepositoryTeam equal to other configs --- src/main/java/org/retest/rebazer/KnownProvider.java | 4 ++-- src/main/java/org/retest/rebazer/RebazerService.java | 4 ++-- .../org/retest/rebazer/config/RebazerConfig.java | 4 ++-- .../retest/rebazer/connector/BitbucketConnector.java | 4 ++-- .../retest/rebazer/connector/GithubConnector.java | 6 +++--- .../org/retest/rebazer/service/RebaseService.java | 12 ++++++------ .../rebazer/connector/BitbucketConnectorTest.java | 6 +++--- .../rebazer/connector/GithubConnectorTest.java | 6 +++--- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/retest/rebazer/KnownProvider.java b/src/main/java/org/retest/rebazer/KnownProvider.java index 35207a3..ad634f8 100644 --- a/src/main/java/org/retest/rebazer/KnownProvider.java +++ b/src/main/java/org/retest/rebazer/KnownProvider.java @@ -1,7 +1,7 @@ package org.retest.rebazer; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; -import org.retest.rebazer.config.RebazerConfig.Team; +import org.retest.rebazer.config.RebazerConfig.RepositoryTeam; import org.retest.rebazer.connector.BitbucketConnector; import org.retest.rebazer.connector.GithubConnector; import org.retest.rebazer.connector.RepositoryConnector; @@ -12,7 +12,7 @@ public enum KnownProvider { BITBUCKET, GITHUB; - public RepositoryConnector getRepository( final Team team, final RepositoryConfig repo, + public RepositoryConnector getRepository( final RepositoryTeam team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { switch ( this ) { case BITBUCKET: diff --git a/src/main/java/org/retest/rebazer/RebazerService.java b/src/main/java/org/retest/rebazer/RebazerService.java index b6f6f19..6b74202 100644 --- a/src/main/java/org/retest/rebazer/RebazerService.java +++ b/src/main/java/org/retest/rebazer/RebazerService.java @@ -6,7 +6,7 @@ import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryHost; -import org.retest.rebazer.config.RebazerConfig.Team; +import org.retest.rebazer.config.RebazerConfig.RepositoryTeam; import org.retest.rebazer.connector.RepositoryConnector; import org.retest.rebazer.domain.PullRequest; import org.retest.rebazer.service.PullRequestLastUpdateStore; @@ -41,7 +41,7 @@ public void pollToHandleAllPullRequests() { } ); } - private void handleRepo( final RepositoryHost host, final Team team, final RepositoryConfig repoConfig ) { + private void handleRepo( final RepositoryHost host, final RepositoryTeam team, final RepositoryConfig repoConfig ) { log.debug( "Processing {}.", repoConfig ); final RepositoryConnector repoConnector = host.getType().getRepository( team, repoConfig, builder ); for ( final PullRequest pullRequest : repoConnector.getAllPullRequests( repoConfig ) ) { diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 91c30ba..b564455 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -30,11 +30,11 @@ public class RebazerConfig { public static class RepositoryHost { private KnownProvider type; private URL url; - private List teams; + private List teams; } @Data - public static class Team { + public static class RepositoryTeam { private String name; private String user; private String pass; diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index 017156a..0f20fc6 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -6,7 +6,7 @@ import java.util.Map; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; -import org.retest.rebazer.config.RebazerConfig.Team; +import org.retest.rebazer.config.RebazerConfig.RepositoryTeam; import org.retest.rebazer.domain.PullRequest; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.web.client.RestTemplate; @@ -23,7 +23,7 @@ public class BitbucketConnector implements RepositoryConnector { private final RestTemplate legacyTemplate; private final RestTemplate template; - public BitbucketConnector( final Team team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { + public BitbucketConnector( final RepositoryTeam team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { final String basePath = "/repositories/" + team.getName() + "/" + repo.getName(); legacyTemplate = diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index 9a42450..6c25a70 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -6,7 +6,7 @@ import java.util.Map; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; -import org.retest.rebazer.config.RebazerConfig.Team; +import org.retest.rebazer.config.RebazerConfig.RepositoryTeam; import org.retest.rebazer.domain.PullRequest; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.web.client.RestTemplate; @@ -21,12 +21,12 @@ public class GithubConnector implements RepositoryConnector { private final static String baseUrl = "https://api.github.com/"; - private final Team team; + private final RepositoryTeam team; RepositoryConfig repo; private final RestTemplate template; - public GithubConnector( final Team team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { + public GithubConnector( final RepositoryTeam team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { this.team = team; this.repo = repo; diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index e4bdc5a..e08f6e8 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -13,7 +13,7 @@ import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryHost; -import org.retest.rebazer.config.RebazerConfig.Team; +import org.retest.rebazer.config.RebazerConfig.RepositoryTeam; import org.retest.rebazer.domain.PullRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -45,8 +45,8 @@ public RebaseService( final RebazerConfig config, final GitRepoCleaner cleaner ) } ); } - private void setupRepo( final RepositoryHost host, final Team team, final RepositoryConfig repo ) { - final CredentialsProvider credentials = repoCredentials( team ); + private void setupRepo( final RepositoryHost host, final RepositoryTeam team, final RepositoryConfig repo ) { + final CredentialsProvider credentials = repoCredential( team ); final File repoFolder = repoFolder( host, team, repo ); final String url = repoUrl( host, team, repo ); @@ -57,15 +57,15 @@ private void setupRepo( final RepositoryHost host, final Team team, final Reposi cleanUp( repo ); } - private CredentialsProvider repoCredentials( final Team team ) { + private CredentialsProvider repoCredential( final RepositoryTeam team ) { return new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); } - private File repoFolder( final RepositoryHost host, final Team team, final RepositoryConfig repo ) { + private File repoFolder( final RepositoryHost host, final RepositoryTeam team, final RepositoryConfig repo ) { return new File( new File( new File( workspace, host.getUrl().getHost() ), team.getName() ), repo.getName() ); } - private String repoUrl( final RepositoryHost host, final Team team, final RepositoryConfig repo ) { + private String repoUrl( final RepositoryHost host, final RepositoryTeam team, final RepositoryConfig repo ) { return host.getUrl() + "/" + team.getName() + "/" + repo.getName() + ".git"; } diff --git a/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java b/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java index efc88db..bea7c3a 100644 --- a/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java +++ b/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java @@ -17,7 +17,7 @@ import org.junit.Test; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; -import org.retest.rebazer.config.RebazerConfig.Team; +import org.retest.rebazer.config.RebazerConfig.RepositoryTeam; import org.retest.rebazer.domain.PullRequest; import org.retest.rebazer.service.PullRequestLastUpdateStore; import org.springframework.boot.web.client.RestTemplateBuilder; @@ -31,7 +31,7 @@ public class BitbucketConnectorTest { PullRequestLastUpdateStore pullRequestUpdateStates; RestTemplate template; RebazerConfig config; - Team team; + RepositoryTeam team; BitbucketConnector cut; @@ -39,7 +39,7 @@ public class BitbucketConnectorTest { public void setUp() { template = mock( RestTemplate.class ); config = mock( RebazerConfig.class ); - team = mock( Team.class ); + team = mock( RepositoryTeam.class ); final RepositoryConfig repo = mock( RepositoryConfig.class ); final RestTemplateBuilder builder = mock( RestTemplateBuilder.class ); when( builder.basicAuthorization( any(), any() ) ).thenReturn( builder ); diff --git a/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java b/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java index fb170f2..fd3876c 100644 --- a/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java +++ b/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java @@ -17,7 +17,7 @@ import org.junit.Test; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; -import org.retest.rebazer.config.RebazerConfig.Team; +import org.retest.rebazer.config.RebazerConfig.RepositoryTeam; import org.retest.rebazer.domain.PullRequest; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.web.client.RestTemplate; @@ -29,7 +29,7 @@ public class GithubConnectorTest { RestTemplate template; RebazerConfig config; - Team team; + RepositoryTeam team; GithubConnector cut; @@ -37,7 +37,7 @@ public class GithubConnectorTest { public void setUp() { template = mock( RestTemplate.class ); config = mock( RebazerConfig.class ); - team = mock( Team.class ); + team = mock( RepositoryTeam.class ); final RepositoryConfig repo = mock( RepositoryConfig.class ); final RestTemplateBuilder builder = mock( RestTemplateBuilder.class ); when( builder.basicAuthorization( any(), any() ) ).thenReturn( builder ); From 37ad3c3459f3cea748149eb716d645ac1ee1fe4b Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Fri, 20 Jul 2018 07:15:03 +0200 Subject: [PATCH 63/86] Use better consistent variable names RebazerConfig rebazerConfig RepositoryHost repoHost RepositoryTeam repoTeam RepositoryConfig repoConfig Git localRepo DocumentContext jsonPath RepositoryConnector repoConnector --- .../org/retest/rebazer/KnownProvider.java | 8 +- .../org/retest/rebazer/RebazerService.java | 29 +++--- .../rebazer/connector/BitbucketConnector.java | 59 +++++------ .../rebazer/connector/GithubConnector.java | 49 +++++----- .../connector/RepositoryConnector.java | 2 +- .../rebazer/service/GitRepoCleaner.java | 36 +++---- .../service/PullRequestLastUpdateStore.java | 18 ++-- .../retest/rebazer/service/RebaseService.java | 98 +++++++++---------- 8 files changed, 152 insertions(+), 147 deletions(-) diff --git a/src/main/java/org/retest/rebazer/KnownProvider.java b/src/main/java/org/retest/rebazer/KnownProvider.java index ad634f8..e3311ba 100644 --- a/src/main/java/org/retest/rebazer/KnownProvider.java +++ b/src/main/java/org/retest/rebazer/KnownProvider.java @@ -12,13 +12,13 @@ public enum KnownProvider { BITBUCKET, GITHUB; - public RepositoryConnector getRepository( final RepositoryTeam team, final RepositoryConfig repo, - final RestTemplateBuilder builder ) { + public RepositoryConnector getRepository( final RepositoryTeam repoTeam, final RepositoryConfig repoConfig, + final RestTemplateBuilder templateBuilder ) { switch ( this ) { case BITBUCKET: - return new BitbucketConnector( team, repo, builder ); + return new BitbucketConnector( repoTeam, repoConfig, templateBuilder ); case GITHUB: - return new GithubConnector( team, repo, builder ); + return new GithubConnector( repoTeam, repoConfig, templateBuilder ); default: throw new RuntimeException( "No Repository defined for provider: " + this ); } diff --git a/src/main/java/org/retest/rebazer/RebazerService.java b/src/main/java/org/retest/rebazer/RebazerService.java index 6b74202..89f6845 100644 --- a/src/main/java/org/retest/rebazer/RebazerService.java +++ b/src/main/java/org/retest/rebazer/RebazerService.java @@ -25,32 +25,33 @@ public class RebazerService { private final RebaseService rebaseService; - private final RebazerConfig config; + private final RebazerConfig rebazerConfig; private final PullRequestLastUpdateStore pullRequestLastUpdateStore; private final RestTemplateBuilder builder; @Scheduled( fixedDelayString = "${" + POLL_INTERVAL_KEY + ":" + POLL_INTERVAL_DEFAULT + "}000" ) public void pollToHandleAllPullRequests() { - config.getHosts().forEach( host -> { - host.getTeams().forEach( team -> { - team.getRepos().forEach( repoConfig -> { - handleRepo( host, team, repoConfig ); + rebazerConfig.getHosts().forEach( repoHost -> { + repoHost.getTeams().forEach( repoTeam -> { + repoTeam.getRepos().forEach( repoConfig -> { + handleRepo( repoHost, repoTeam, repoConfig ); } ); } ); } ); } - private void handleRepo( final RepositoryHost host, final RepositoryTeam team, final RepositoryConfig repoConfig ) { + private void handleRepo( final RepositoryHost repoHost, final RepositoryTeam repoTeam, + final RepositoryConfig repoConfig ) { log.debug( "Processing {}.", repoConfig ); - final RepositoryConnector repoConnector = host.getType().getRepository( team, repoConfig, builder ); + final RepositoryConnector repoConnector = repoHost.getType().getRepository( repoTeam, repoConfig, builder ); for ( final PullRequest pullRequest : repoConnector.getAllPullRequests( repoConfig ) ) { handlePullRequest( repoConnector, repoConfig, pullRequest ); } log.debug( "Processing done for {}.", repoConfig ); } - public void handlePullRequest( final RepositoryConnector provider, final RepositoryConfig repoConfig, + public void handlePullRequest( final RepositoryConnector repoConnector, final RepositoryConfig repoConfig, final PullRequest pullRequest ) { log.debug( "Processing {}.", pullRequest ); @@ -58,24 +59,24 @@ public void handlePullRequest( final RepositoryConnector provider, final Reposit log.info( "{} is unchanged since last run (last change: {}).", pullRequest, pullRequestLastUpdateStore.getLastDate( repoConfig, pullRequest ) ); - } else if ( !provider.greenBuildExists( pullRequest ) ) { + } else if ( !repoConnector.greenBuildExists( pullRequest ) ) { log.info( "Waiting for green build of {}.", pullRequest ); pullRequestLastUpdateStore.setHandled( repoConfig, pullRequest ); - } else if ( provider.rebaseNeeded( pullRequest ) ) { + } else if ( repoConnector.rebaseNeeded( pullRequest ) ) { if ( !rebaseService.rebase( repoConfig, pullRequest ) ) { - provider.addComment( pullRequest ); + repoConnector.addComment( pullRequest ); } // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called - pullRequestLastUpdateStore.setHandled( repoConfig, provider.getLatestUpdate( pullRequest ) ); + pullRequestLastUpdateStore.setHandled( repoConfig, repoConnector.getLatestUpdate( pullRequest ) ); - } else if ( !provider.isApproved( pullRequest ) ) { + } else if ( !repoConnector.isApproved( pullRequest ) ) { log.info( "Waiting for approval of {}.", pullRequest ); pullRequestLastUpdateStore.setHandled( repoConfig, pullRequest ); } else { log.info( "Merging pull request " + pullRequest ); - provider.merge( pullRequest ); + repoConnector.merge( pullRequest ); pullRequestLastUpdateStore.resetAllInThisRepo( repoConfig ); } } diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index 0f20fc6..d3a5c11 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -23,32 +23,34 @@ public class BitbucketConnector implements RepositoryConnector { private final RestTemplate legacyTemplate; private final RestTemplate template; - public BitbucketConnector( final RepositoryTeam team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { - final String basePath = "/repositories/" + team.getName() + "/" + repo.getName(); - - legacyTemplate = - builder.basicAuthorization( team.getUser(), team.getPass() ).rootUri( baseUrlV1 + basePath ).build(); - template = builder.basicAuthorization( team.getUser(), team.getPass() ).rootUri( baseUrlV2 + basePath ).build(); + public BitbucketConnector( final RepositoryTeam repoTeam, final RepositoryConfig repoConfig, + final RestTemplateBuilder templateBuilder ) { + final String basePath = "/repositories/" + repoTeam.getName() + "/" + repoConfig.getName(); + + legacyTemplate = templateBuilder.basicAuthorization( repoTeam.getUser(), repoTeam.getPass() ) + .rootUri( baseUrlV1 + basePath ).build(); + template = templateBuilder.basicAuthorization( repoTeam.getUser(), repoTeam.getPass() ) + .rootUri( baseUrlV2 + basePath ).build(); } @Override public PullRequest getLatestUpdate( final PullRequest pullRequest ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); + final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() ); final PullRequest updatedPullRequest = PullRequest.builder() // .id( pullRequest.getId() ) // .repo( pullRequest.getRepo() ) // .source( pullRequest.getSource() ) // .destination( pullRequest.getDestination() ) // .url( pullRequest.getUrl() ) // - .lastUpdate( jp.read( "$.updated_on" ) ) // + .lastUpdate( jsonPath.read( "$.updated_on" ) ) // .build(); return updatedPullRequest; } @Override public boolean isApproved( final PullRequest pullRequest ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); - return jp.> read( "$.participants[*].approved" ).stream().anyMatch( approved -> approved ); + final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() ); + return jsonPath.> read( "$.participants[*].approved" ).stream().anyMatch( approved -> approved ); } @Override @@ -61,18 +63,18 @@ String getHeadOfBranch( final PullRequest pullRequest ) { } String getLastCommonCommitId( final PullRequest pullRequest ) { - DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); + DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() + "/commits" ); - final int pageLength = jp.read( "$.pagelen" ); - final int size = jp.read( "$.size" ); + final int pageLength = jsonPath.read( "$.pagelen" ); + final int size = jsonPath.read( "$.size" ); final int lastPage = (pageLength + size - 1) / pageLength; if ( lastPage > 1 ) { - jp = jsonPathForPath( pullRequest.getUrl() + "/commits?page=" + lastPage ); + jsonPath = jsonPathForPath( pullRequest.getUrl() + "/commits?page=" + lastPage ); } - final List commitIds = jp.read( "$.values[*].hash" ); - final List parentIds = jp.read( "$.values[*].parents[0].hash" ); + final List commitIds = jsonPath.read( "$.values[*].hash" ); + final List parentIds = jsonPath.read( "$.values[*].parents[0].hash" ); return parentIds.stream().filter( parent -> !commitIds.contains( parent ) ).findFirst() .orElseThrow( IllegalStateException::new ); @@ -93,27 +95,28 @@ public void merge( final PullRequest pullRequest ) { @Override public boolean greenBuildExists( final PullRequest pullRequest ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/statuses" ); - return jp.> read( "$.values[*].state" ).stream().anyMatch( s -> s.equals( "SUCCESSFUL" ) ); + final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() + "/statuses" ); + return jsonPath.> read( "$.values[*].state" ).stream().anyMatch( s -> s.equals( "SUCCESSFUL" ) ); } @Override - public List getAllPullRequests( final RepositoryConfig repo ) { - final DocumentContext jp = jsonPathForPath( "/pullrequests" ); - return parsePullRequestsJson( repo, jp ); + public List getAllPullRequests( final RepositoryConfig repoConfig ) { + final DocumentContext jsonPath = jsonPathForPath( "/pullrequests" ); + return parsePullRequestsJson( repoConfig, jsonPath ); } - public List parsePullRequestsJson( final RepositoryConfig repo, final DocumentContext jp ) { - final int numPullRequests = (int) jp.read( "$.size" ); + public List parsePullRequestsJson( final RepositoryConfig repoConfig, + final DocumentContext jsonPath ) { + final int numPullRequests = (int) jsonPath.read( "$.size" ); final List results = new ArrayList<>( numPullRequests ); for ( int i = 0; i < numPullRequests; i++ ) { - final int id = jp.read( "$.values[" + i + "].id" ); - final String source = jp.read( "$.values[" + i + "].source.branch.name" ); - final String destination = jp.read( "$.values[" + i + "].destination.branch.name" ); - final String lastUpdate = jp.read( "$.values[" + i + "].updated_on" ); + final int id = jsonPath.read( "$.values[" + i + "].id" ); + final String source = jsonPath.read( "$.values[" + i + "].source.branch.name" ); + final String destination = jsonPath.read( "$.values[" + i + "].destination.branch.name" ); + final String lastUpdate = jsonPath.read( "$.values[" + i + "].updated_on" ); results.add( PullRequest.builder() // .id( id ) // - .repo( repo.getName() ) // + .repo( repoConfig.getName() ) // .source( source ) // .destination( destination ) // .url( "/pullrequests/" + id ) // diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index 6c25a70..c240762 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -26,31 +26,32 @@ public class GithubConnector implements RepositoryConnector { private final RestTemplate template; - public GithubConnector( final RepositoryTeam team, final RepositoryConfig repo, final RestTemplateBuilder builder ) { - this.team = team; - this.repo = repo; + public GithubConnector( final RepositoryTeam repoTeam, final RepositoryConfig repoConfig, + final RestTemplateBuilder builder ) { + team = repoTeam; + repo = repoConfig; - template = builder.basicAuthorization( team.getUser(), team.getPass() ).rootUri( baseUrl ).build(); + template = builder.basicAuthorization( repoTeam.getUser(), repoTeam.getPass() ).rootUri( baseUrl ).build(); } @Override public PullRequest getLatestUpdate( final PullRequest pullRequest ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() ); + final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() ); final PullRequest updatedPullRequest = PullRequest.builder() // .id( pullRequest.getId() ) // .repo( pullRequest.getRepo() ) // .source( pullRequest.getSource() ) // .destination( pullRequest.getDestination() ) // .url( pullRequest.getUrl() ) // - .lastUpdate( jp.read( "$.updated_at" ) ) // + .lastUpdate( jsonPath.read( "$.updated_at" ) ) // .build(); return updatedPullRequest; } @Override public boolean isApproved( final PullRequest pullRequest ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/reviews" ); - final List states = jp.read( "$..state" ); + final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() + "/reviews" ); + final List states = jsonPath.read( "$..state" ); boolean approved = false; for ( final String state : states ) { if ( state.equals( "APPROVED" ) ) { @@ -73,10 +74,10 @@ String getHeadOfBranch( final PullRequest pullRequest ) { } String getLastCommonCommitId( final PullRequest pullRequest ) { - final DocumentContext jp = jsonPathForPath( pullRequest.getUrl() + "/commits" ); + final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() + "/commits" ); - final List commitIds = jp.read( "$..sha" ); - final List parentIds = jp.read( "$..parents..sha" ); + final List commitIds = jsonPath.read( "$..sha" ); + final List parentIds = jsonPath.read( "$..parents..sha" ); return parentIds.stream().filter( parent -> commitIds.contains( parent ) ).findFirst() .orElseThrow( IllegalStateException::new ); @@ -98,30 +99,30 @@ public void merge( final PullRequest pullRequest ) { public boolean greenBuildExists( final PullRequest pullRequest ) { final String urlPath = "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/commits/" + pullRequest.getSource() + "/status"; - final DocumentContext jp = jsonPathForPath( urlPath ); - return jp.> read( "$.statuses[*].state" ).stream().anyMatch( s -> s.equals( "success" ) ); + final DocumentContext jsonPath = jsonPathForPath( urlPath ); + return jsonPath.> read( "$.statuses[*].state" ).stream().anyMatch( s -> s.equals( "success" ) ); } @Override - public List getAllPullRequests( final RepositoryConfig repo ) { - final String urlPath = "/repos/" + team.getName() + "/" + repo.getName() + "/pulls"; - final DocumentContext jp = jsonPathForPath( urlPath ); - return parsePullRequestsJson( repo, urlPath, jp ); + public List getAllPullRequests( final RepositoryConfig repoConfig ) { + final String urlPath = "/repos/" + team.getName() + "/" + repoConfig.getName() + "/pulls"; + final DocumentContext jsonPath = jsonPathForPath( urlPath ); + return parsePullRequestsJson( repoConfig, urlPath, jsonPath ); } - public static List parsePullRequestsJson( final RepositoryConfig repo, final String urlPath, - final DocumentContext jp ) { - final List pullRequestAmount = jp.read( "$..number" ); + public static List parsePullRequestsJson( final RepositoryConfig repoConfig, final String urlPath, + final DocumentContext jsonPath ) { + final List pullRequestAmount = jsonPath.read( "$..number" ); final int numPullRequests = pullRequestAmount.size(); final List results = new ArrayList<>( numPullRequests ); for ( int i = 0; i < numPullRequests; i++ ) { final int id = pullRequestAmount.get( i ); - final String source = jp.read( "$.[" + i + "].head.ref" ); - final String destination = jp.read( "$.[" + i + "].base.ref" ); - final String lastUpdate = jp.read( "$.[" + i + "].updated_at" ); + final String source = jsonPath.read( "$.[" + i + "].head.ref" ); + final String destination = jsonPath.read( "$.[" + i + "].base.ref" ); + final String lastUpdate = jsonPath.read( "$.[" + i + "].updated_at" ); results.add( PullRequest.builder() // .id( id ) // - .repo( repo.getName() ) // + .repo( repoConfig.getName() ) // .source( source ) // .destination( destination ) // .url( urlPath + "/" + id ) // diff --git a/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java b/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java index a837c8c..da42f3e 100644 --- a/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java +++ b/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java @@ -7,7 +7,7 @@ public interface RepositoryConnector { - List getAllPullRequests( RepositoryConfig repo ); + List getAllPullRequests( RepositoryConfig repoConfig ); PullRequest getLatestUpdate( PullRequest pullRequest ); diff --git a/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java index a15483b..70e2ef9 100644 --- a/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java +++ b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java @@ -20,47 +20,47 @@ public class GitRepoCleaner { private int gcCountdownCurrent; @Autowired - public GitRepoCleaner( final RebazerConfig config ) { - gcCountdownResetValue = config.getGarbageCollectionCountdown(); + public GitRepoCleaner( final RebazerConfig repoConfig ) { + gcCountdownResetValue = repoConfig.getGarbageCollectionCountdown(); gcCountdownCurrent = gcCountdownResetValue; } - public void cleanUp( final Git repoGit, final String fallbackBranchName ) { - resetAndRemoveUntrackedFiles( repoGit ); - checkoutFallbackBranch( repoGit, fallbackBranchName ); - removeAllLocalBranches( repoGit ); - triggerGcIfNeeded( repoGit ); + public void cleanUp( final Git localRepo, final String fallbackBranchName ) { + resetAndRemoveUntrackedFiles( localRepo ); + checkoutFallbackBranch( localRepo, fallbackBranchName ); + removeAllLocalBranches( localRepo ); + triggerGcIfNeeded( localRepo ); } @SneakyThrows - private void resetAndRemoveUntrackedFiles( final Git gitRepo ) { - gitRepo.clean().setCleanDirectories( true ).setForce( true ).setIgnore( false ).call(); - gitRepo.reset().setMode( ResetType.HARD ).call(); + private void resetAndRemoveUntrackedFiles( final Git localRepo ) { + localRepo.clean().setCleanDirectories( true ).setForce( true ).setIgnore( false ).call(); + localRepo.reset().setMode( ResetType.HARD ).call(); } @SneakyThrows - private void checkoutFallbackBranch( final Git repoGit, final String fallbackBranchName ) { - repoGit.checkout().setName( "remotes/origin/" + fallbackBranchName ).call(); + private void checkoutFallbackBranch( final Git localRepo, final String fallbackBranchName ) { + localRepo.checkout().setName( "remotes/origin/" + fallbackBranchName ).call(); } @SneakyThrows - private void removeAllLocalBranches( final Git repoGit ) { - final List allBranches = repoGit.branchList().call(); + private void removeAllLocalBranches( final Git localRepo ) { + final List allBranches = localRepo.branchList().call(); final String[] localBranches = allBranches.stream() // .map( branch -> branch.getName() ) // .filter( name -> name.startsWith( "refs/heads/" ) ) // .toArray( String[]::new ); - repoGit.branchDelete().setForce( true ).setBranchNames( localBranches ).call(); + localRepo.branchDelete().setForce( true ).setBranchNames( localBranches ).call(); } @SneakyThrows - private void triggerGcIfNeeded( final Git repoGit ) { + private void triggerGcIfNeeded( final Git localRepo ) { gcCountdownCurrent--; if ( gcCountdownCurrent == 0 ) { gcCountdownCurrent = gcCountdownResetValue; - log.info( "Running git gc on {}, next gc after {} cleanups.", repoGit, gcCountdownResetValue ); - repoGit.gc().setPrunePreserved( true ).setExpire( null ).call(); + log.info( "Running git gc on {}, next gc after {} cleanups.", localRepo, gcCountdownResetValue ); + localRepo.gc().setPrunePreserved( true ).setExpire( null ).call(); } } diff --git a/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java b/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java index b9938bb..435a349 100644 --- a/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java +++ b/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java @@ -12,29 +12,29 @@ public class PullRequestLastUpdateStore { private final Map> pullRequestUpdateStates = new HashMap<>(); - public void setHandled( final RepositoryConfig repo, final PullRequest pullRequest ) { - Map repoMap = pullRequestUpdateStates.get( repo ); + public void setHandled( final RepositoryConfig repoConfig, final PullRequest pullRequest ) { + Map repoMap = pullRequestUpdateStates.get( repoConfig ); if ( repoMap == null ) { repoMap = new HashMap<>(); - pullRequestUpdateStates.put( repo, repoMap ); + pullRequestUpdateStates.put( repoConfig, repoMap ); } repoMap.put( pullRequest.getId(), pullRequest.getLastUpdate() ); } - public String getLastDate( final RepositoryConfig repo, final PullRequest pullRequest ) { - final Map repoMap = pullRequestUpdateStates.get( repo ); + public String getLastDate( final RepositoryConfig repoConfig, final PullRequest pullRequest ) { + final Map repoMap = pullRequestUpdateStates.get( repoConfig ); return repoMap != null ? repoMap.get( pullRequest.getId() ) : null; } - public void resetAllInThisRepo( final RepositoryConfig repo ) { - final Map repoMap = pullRequestUpdateStates.get( repo ); + public void resetAllInThisRepo( final RepositoryConfig repoConfig ) { + final Map repoMap = pullRequestUpdateStates.get( repoConfig ); if ( repoMap != null ) { repoMap.clear(); } } - public boolean isHandled( final RepositoryConfig repo, final PullRequest pullRequest ) { - return pullRequest.getLastUpdate().equals( getLastDate( repo, pullRequest ) ); + public boolean isHandled( final RepositoryConfig repoConfig, final PullRequest pullRequest ) { + return pullRequest.getLastUpdate().equals( getLastDate( repoConfig, pullRequest ) ); } } diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index e08f6e8..7c28bc7 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -28,49 +28,52 @@ public class RebaseService { private final File workspace; private final GitRepoCleaner cleaner; - private final Map repoCredentials = new HashMap<>(); - private final Map repoGit = new HashMap<>(); + private final Map credentials = new HashMap<>(); + private final Map localGitRepos = new HashMap<>(); @Autowired - public RebaseService( final RebazerConfig config, final GitRepoCleaner cleaner ) { + public RebaseService( final RebazerConfig rebazerConfig, final GitRepoCleaner cleaner ) { this.cleaner = cleaner; - workspace = new File( config.getWorkspace() ).getAbsoluteFile(); + workspace = new File( rebazerConfig.getWorkspace() ).getAbsoluteFile(); - config.getHosts().forEach( host -> { - host.getTeams().forEach( team -> { - team.getRepos().forEach( repo -> { - setupRepo( host, team, repo ); + rebazerConfig.getHosts().forEach( repoHost -> { + repoHost.getTeams().forEach( repoTeam -> { + repoTeam.getRepos().forEach( repoConfig -> { + setupRepo( repoHost, repoTeam, repoConfig ); } ); } ); } ); } - private void setupRepo( final RepositoryHost host, final RepositoryTeam team, final RepositoryConfig repo ) { - final CredentialsProvider credentials = repoCredential( team ); - final File repoFolder = repoFolder( host, team, repo ); - final String url = repoUrl( host, team, repo ); + private void setupRepo( final RepositoryHost repoHost, final RepositoryTeam repoTeam, + final RepositoryConfig repoConfig ) { + final CredentialsProvider credential = repoCredential( repoTeam ); + final File repoFolder = repoFolder( repoHost, repoTeam, repoConfig ); + final String url = repoUrl( repoHost, repoTeam, repoConfig ); - final Git localRepo = setupLocalGitRepo( credentials, repoFolder, url ); + final Git localRepo = setupLocalGitRepo( credential, repoFolder, url ); - repoCredentials.put( repo, credentials ); - repoGit.put( repo, localRepo ); - cleanUp( repo ); + credentials.put( repoConfig, credential ); + localGitRepos.put( repoConfig, localRepo ); + cleaner.cleanUp( localRepo, repoConfig.getBranch() ); } - private CredentialsProvider repoCredential( final RepositoryTeam team ) { - return new UsernamePasswordCredentialsProvider( team.getUser(), team.getPass() ); + private CredentialsProvider repoCredential( final RepositoryTeam repoTeam ) { + return new UsernamePasswordCredentialsProvider( repoTeam.getUser(), repoTeam.getPass() ); } - private File repoFolder( final RepositoryHost host, final RepositoryTeam team, final RepositoryConfig repo ) { - return new File( new File( new File( workspace, host.getUrl().getHost() ), team.getName() ), repo.getName() ); + private File repoFolder( final RepositoryHost repoHost, final RepositoryTeam repoTeam, + final RepositoryConfig repoConfig ) { + return new File( new File( new File( workspace, repoHost.getUrl().getHost() ), repoTeam.getName() ), + repoConfig.getName() ); } - private String repoUrl( final RepositoryHost host, final RepositoryTeam team, final RepositoryConfig repo ) { - return host.getUrl() + "/" + team.getName() + "/" + repo.getName() + ".git"; + private String repoUrl( final RepositoryHost repoHost, final RepositoryTeam repoTeam, + final RepositoryConfig repoConfig ) { + return repoHost.getUrl() + "/" + repoTeam.getName() + "/" + repoConfig.getName() + ".git"; } - private Git setupLocalGitRepo( final CredentialsProvider credentials, final File repoFolder, - final String repoUrl ) { + private Git setupLocalGitRepo( final CredentialsProvider credential, final File repoFolder, final String repoUrl ) { if ( repoFolder.exists() ) { final Git localRepo = tryToOpenExistingRepoAndCheckRemote( repoFolder, repoUrl ); if ( localRepo != null ) { @@ -78,7 +81,7 @@ private Git setupLocalGitRepo( final CredentialsProvider credentials, final File } deleteDirectory( repoFolder ); } - return cloneNewRepo( repoFolder, repoUrl, credentials ); + return cloneNewRepo( repoFolder, repoUrl, credential ); } @SneakyThrows @@ -86,11 +89,11 @@ private void deleteDirectory( final File repoFolder ) { FileUtils.deleteDirectory( repoFolder ); } - private static Git tryToOpenExistingRepoAndCheckRemote( final File repoFolder, final String expectedRepoUrl ) { + private static Git tryToOpenExistingRepoAndCheckRemote( final File repoFolder, final String repoUrl ) { try { - final Git repo = Git.open( repoFolder ); - if ( originIsRepoUrl( repo, expectedRepoUrl ) ) { - return repo; + final Git localRepo = Git.open( repoFolder ); + if ( originIsRepoUrl( localRepo, repoUrl ) ) { + return localRepo; } else { log.error( "Repo has wrong remote URL!" ); return null; @@ -102,32 +105,33 @@ private static Git tryToOpenExistingRepoAndCheckRemote( final File repoFolder, f } @SneakyThrows - private static boolean originIsRepoUrl( final Git repo, final String expectedRepoUrl ) { - return repo.remoteList().call().stream().anyMatch( r -> r.getName().equals( "origin" ) - && r.getURIs().stream().anyMatch( url -> url.toString().equals( expectedRepoUrl ) ) ); + private static boolean originIsRepoUrl( final Git localRepo, final String repoUrl ) { + return localRepo.remoteList().call().stream().anyMatch( r -> r.getName().equals( "origin" ) + && r.getURIs().stream().anyMatch( url -> url.toString().equals( repoUrl ) ) ); } @SneakyThrows - private static Git cloneNewRepo( final File repoFolder, final String gitRepoUrl, + private static Git cloneNewRepo( final File repoFolder, final String repoUrl, final CredentialsProvider credentialsProvider ) { - log.info( "Cloning repository {} to folder {} ...", gitRepoUrl, repoFolder ); - return Git.cloneRepository().setURI( gitRepoUrl ).setCredentialsProvider( credentialsProvider ) + log.info( "Cloning repository {} to folder {} ...", repoUrl, repoFolder ); + return Git.cloneRepository().setURI( repoUrl ).setCredentialsProvider( credentialsProvider ) .setDirectory( repoFolder ).call(); } @SneakyThrows - public boolean rebase( final RepositoryConfig repo, final PullRequest pullRequest ) { + public boolean rebase( final RepositoryConfig repoConfig, final PullRequest pullRequest ) { log.info( "Rebasing {}.", pullRequest ); + final Git localRepo = localGitRepos.get( repoConfig ); + final CredentialsProvider credential = credentials.get( repoConfig ); + try { - final Git repository = repoGit.get( repo ); - final CredentialsProvider credentials = repoCredentials.get( repo ); - repository.fetch().setCredentialsProvider( credentials ).setRemoveDeletedRefs( true ).call(); - repository.checkout().setCreateBranch( true ).setName( pullRequest.getSource() ) + localRepo.fetch().setCredentialsProvider( credential ).setRemoveDeletedRefs( true ).call(); + localRepo.checkout().setCreateBranch( true ).setName( pullRequest.getSource() ) .setStartPoint( "origin/" + pullRequest.getSource() ).call(); final RebaseResult rebaseResult = - repository.rebase().setUpstream( "origin/" + pullRequest.getDestination() ).call(); + localRepo.rebase().setUpstream( "origin/" + pullRequest.getDestination() ).call(); switch ( rebaseResult.getStatus() ) { case UP_TO_DATE: @@ -139,26 +143,22 @@ public boolean rebase( final RepositoryConfig repo, final PullRequest pullReques // fall-through case OK: - repository.push().setCredentialsProvider( credentials ).setForce( true ).call(); + localRepo.push().setCredentialsProvider( credential ).setForce( true ).call(); return true; case STOPPED: log.info( "Merge conflict in {}", pullRequest ); - repository.rebase().setOperation( Operation.ABORT ).call(); + localRepo.rebase().setOperation( Operation.ABORT ).call(); return false; default: - repository.rebase().setOperation( Operation.ABORT ).call(); + localRepo.rebase().setOperation( Operation.ABORT ).call(); throw new RuntimeException( "For " + pullRequest + " rebase causes an unexpected result: " + rebaseResult.getStatus() ); } } finally { - cleanUp( repo ); + cleaner.cleanUp( localRepo, repoConfig.getBranch() ); } } - private void cleanUp( final RepositoryConfig repoConfig ) { - cleaner.cleanUp( repoGit.get( repoConfig ), repoConfig.getBranch() ); - } - } From 247179cfdef9a5b7dcb493eb6a145a7b57d22785 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Fri, 20 Jul 2018 07:28:57 +0200 Subject: [PATCH 64/86] Fix bug that GitRepoCleaner don't handle multiple repos correctly --- .../org/retest/rebazer/service/GitRepoCleaner.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java index 70e2ef9..30cbea8 100644 --- a/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java +++ b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java @@ -1,6 +1,9 @@ package org.retest.rebazer.service; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ResetCommand.ResetType; @@ -17,12 +20,12 @@ public class GitRepoCleaner { private final int gcCountdownResetValue; - private int gcCountdownCurrent; + private final Map gcCountdownCurrents; @Autowired public GitRepoCleaner( final RebazerConfig repoConfig ) { gcCountdownResetValue = repoConfig.getGarbageCollectionCountdown(); - gcCountdownCurrent = gcCountdownResetValue; + gcCountdownCurrents = new HashMap<>(); } public void cleanUp( final Git localRepo, final String fallbackBranchName ) { @@ -56,9 +59,10 @@ private void removeAllLocalBranches( final Git localRepo ) { @SneakyThrows private void triggerGcIfNeeded( final Git localRepo ) { - gcCountdownCurrent--; - if ( gcCountdownCurrent == 0 ) { - gcCountdownCurrent = gcCountdownResetValue; + final AtomicInteger gcCountdownCurrent = + gcCountdownCurrents.computeIfAbsent( localRepo, key -> new AtomicInteger( gcCountdownResetValue ) ); + if ( gcCountdownCurrent.decrementAndGet() <= 0 ) { + gcCountdownCurrent.set( gcCountdownResetValue ); log.info( "Running git gc on {}, next gc after {} cleanups.", localRepo, gcCountdownResetValue ); localRepo.gc().setPrunePreserved( true ).setExpire( null ).call(); } From 0b0658d604efb985d2aab62b5b644fd896af03eb Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Fri, 20 Jul 2018 07:52:46 +0200 Subject: [PATCH 65/86] Centralise url handling in GithubConnector --- .../rebazer/connector/GithubConnector.java | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index c240762..f2c24f4 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -21,17 +21,14 @@ public class GithubConnector implements RepositoryConnector { private final static String baseUrl = "https://api.github.com/"; - private final RepositoryTeam team; - RepositoryConfig repo; - private final RestTemplate template; public GithubConnector( final RepositoryTeam repoTeam, final RepositoryConfig repoConfig, final RestTemplateBuilder builder ) { - team = repoTeam; - repo = repoConfig; + final String basePath = "/repos/" + repoTeam.getName() + "/" + repoConfig.getName(); - template = builder.basicAuthorization( repoTeam.getUser(), repoTeam.getPass() ).rootUri( baseUrl ).build(); + template = builder.basicAuthorization( repoTeam.getUser(), repoTeam.getPass() ).rootUri( baseUrl + basePath ) + .build(); } @Override @@ -69,8 +66,7 @@ public boolean rebaseNeeded( final PullRequest pullRequest ) { } String getHeadOfBranch( final PullRequest pullRequest ) { - final String url = "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/"; - return jsonPathForPath( url + "git/refs/heads/" + pullRequest.getDestination() ).read( "$.object.sha" ); + return jsonPathForPath( "/git/refs/heads/" + pullRequest.getDestination() ).read( "$.object.sha" ); } String getLastCommonCommitId( final PullRequest pullRequest ) { @@ -97,20 +93,18 @@ public void merge( final PullRequest pullRequest ) { @Override public boolean greenBuildExists( final PullRequest pullRequest ) { - final String urlPath = "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/commits/" - + pullRequest.getSource() + "/status"; + final String urlPath = "/commits/" + pullRequest.getSource() + "/status"; final DocumentContext jsonPath = jsonPathForPath( urlPath ); return jsonPath.> read( "$.statuses[*].state" ).stream().anyMatch( s -> s.equals( "success" ) ); } @Override public List getAllPullRequests( final RepositoryConfig repoConfig ) { - final String urlPath = "/repos/" + team.getName() + "/" + repoConfig.getName() + "/pulls"; - final DocumentContext jsonPath = jsonPathForPath( urlPath ); - return parsePullRequestsJson( repoConfig, urlPath, jsonPath ); + final DocumentContext jsonPath = jsonPathForPath( "/pulls" ); + return parsePullRequestsJson( repoConfig, jsonPath ); } - public static List parsePullRequestsJson( final RepositoryConfig repoConfig, final String urlPath, + public static List parsePullRequestsJson( final RepositoryConfig repoConfig, final DocumentContext jsonPath ) { final List pullRequestAmount = jsonPath.read( "$..number" ); final int numPullRequests = pullRequestAmount.size(); @@ -125,7 +119,7 @@ public static List parsePullRequestsJson( final RepositoryConfig re .repo( repoConfig.getName() ) // .source( source ) // .destination( destination ) // - .url( urlPath + "/" + id ) // + .url( "/pulls/" + id ) // .lastUpdate( lastUpdate ) // .build() ); // } @@ -141,8 +135,7 @@ private DocumentContext jsonPathForPath( final String urlPath ) { public void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "body", "This pull request needs some manual love ..." ); - template.postForObject( "/repos/" + team.getName() + "/" + pullRequest.getRepo() + "/issues/" - + pullRequest.getId() + "/comments", request, String.class ); + template.postForObject( "/issues/" + pullRequest.getId() + "/comments", request, String.class ); } } From 2180ca48d525214d3b76bed56b4814e971581aee Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Fri, 20 Jul 2018 08:29:23 +0200 Subject: [PATCH 66/86] Remove repo und url from PullRequest --- .../rebazer/connector/BitbucketConnector.java | 22 +++++++++---------- .../rebazer/connector/GithubConnector.java | 16 +++++++------- .../retest/rebazer/domain/PullRequest.java | 2 -- .../connector/BitbucketConnectorTest.java | 8 ++----- .../connector/GithubConnectorTest.java | 10 ++++----- 5 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index d3a5c11..d2ae36f 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -35,13 +35,11 @@ public BitbucketConnector( final RepositoryTeam repoTeam, final RepositoryConfig @Override public PullRequest getLatestUpdate( final PullRequest pullRequest ) { - final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() ); + final DocumentContext jsonPath = jsonPathForPath( requestPath( pullRequest ) ); final PullRequest updatedPullRequest = PullRequest.builder() // .id( pullRequest.getId() ) // - .repo( pullRequest.getRepo() ) // .source( pullRequest.getSource() ) // .destination( pullRequest.getDestination() ) // - .url( pullRequest.getUrl() ) // .lastUpdate( jsonPath.read( "$.updated_on" ) ) // .build(); return updatedPullRequest; @@ -49,7 +47,7 @@ public PullRequest getLatestUpdate( final PullRequest pullRequest ) { @Override public boolean isApproved( final PullRequest pullRequest ) { - final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() ); + final DocumentContext jsonPath = jsonPathForPath( requestPath( pullRequest ) ); return jsonPath.> read( "$.participants[*].approved" ).stream().anyMatch( approved -> approved ); } @@ -63,14 +61,14 @@ String getHeadOfBranch( final PullRequest pullRequest ) { } String getLastCommonCommitId( final PullRequest pullRequest ) { - DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() + "/commits" ); + DocumentContext jsonPath = jsonPathForPath( requestPath( pullRequest ) + "/commits" ); final int pageLength = jsonPath.read( "$.pagelen" ); final int size = jsonPath.read( "$.size" ); final int lastPage = (pageLength + size - 1) / pageLength; if ( lastPage > 1 ) { - jsonPath = jsonPathForPath( pullRequest.getUrl() + "/commits?page=" + lastPage ); + jsonPath = jsonPathForPath( requestPath( pullRequest ) + "/commits?page=" + lastPage ); } final List commitIds = jsonPath.read( "$.values[*].hash" ); @@ -90,12 +88,12 @@ public void merge( final PullRequest pullRequest ) { request.put( "message", message ); request.put( "merge_strategy", "merge_commit" ); - template.postForObject( pullRequest.getUrl() + "/merge", request, Object.class ); + template.postForObject( requestPath( pullRequest ) + "/merge", request, Object.class ); } @Override public boolean greenBuildExists( final PullRequest pullRequest ) { - final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() + "/statuses" ); + final DocumentContext jsonPath = jsonPathForPath( requestPath( pullRequest ) + "/statuses" ); return jsonPath.> read( "$.values[*].state" ).stream().anyMatch( s -> s.equals( "SUCCESSFUL" ) ); } @@ -116,16 +114,18 @@ public List parsePullRequestsJson( final RepositoryConfig repoConfi final String lastUpdate = jsonPath.read( "$.values[" + i + "].updated_on" ); results.add( PullRequest.builder() // .id( id ) // - .repo( repoConfig.getName() ) // .source( source ) // .destination( destination ) // - .url( "/pullrequests/" + id ) // .lastUpdate( lastUpdate ) // .build() ); // } return results; } + private String requestPath( final PullRequest pullRequest ) { + return "/pullrequests/" + pullRequest.getId(); + } + private DocumentContext jsonPathForPath( final String urlPath ) { final String json = template.getForObject( urlPath, String.class ); return JsonPath.parse( json ); @@ -136,7 +136,7 @@ public void addComment( final PullRequest pullRequest ) { final Map request = new HashMap<>(); request.put( "content", "This pull request needs some manual love ..." ); - legacyTemplate.postForObject( pullRequest.getUrl() + "/comments", request, String.class ); + legacyTemplate.postForObject( requestPath( pullRequest ) + "/comments", request, String.class ); } } diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index f2c24f4..4824e89 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -33,13 +33,11 @@ public GithubConnector( final RepositoryTeam repoTeam, final RepositoryConfig re @Override public PullRequest getLatestUpdate( final PullRequest pullRequest ) { - final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() ); + final DocumentContext jsonPath = jsonPathForPath( requestPath( pullRequest ) ); final PullRequest updatedPullRequest = PullRequest.builder() // .id( pullRequest.getId() ) // - .repo( pullRequest.getRepo() ) // .source( pullRequest.getSource() ) // .destination( pullRequest.getDestination() ) // - .url( pullRequest.getUrl() ) // .lastUpdate( jsonPath.read( "$.updated_at" ) ) // .build(); return updatedPullRequest; @@ -47,7 +45,7 @@ public PullRequest getLatestUpdate( final PullRequest pullRequest ) { @Override public boolean isApproved( final PullRequest pullRequest ) { - final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() + "/reviews" ); + final DocumentContext jsonPath = jsonPathForPath( requestPath( pullRequest ) + "/reviews" ); final List states = jsonPath.read( "$..state" ); boolean approved = false; for ( final String state : states ) { @@ -70,7 +68,7 @@ String getHeadOfBranch( final PullRequest pullRequest ) { } String getLastCommonCommitId( final PullRequest pullRequest ) { - final DocumentContext jsonPath = jsonPathForPath( pullRequest.getUrl() + "/commits" ); + final DocumentContext jsonPath = jsonPathForPath( requestPath( pullRequest ) + "/commits" ); final List commitIds = jsonPath.read( "$..sha" ); final List parentIds = jsonPath.read( "$..parents..sha" ); @@ -88,7 +86,7 @@ public void merge( final PullRequest pullRequest ) { request.put( "commit_title", message ); request.put( "merge_method", "merge" ); - template.put( pullRequest.getUrl() + "/merge", request, Object.class ); + template.put( requestPath( pullRequest ) + "/merge", request, Object.class ); } @Override @@ -116,16 +114,18 @@ public static List parsePullRequestsJson( final RepositoryConfig re final String lastUpdate = jsonPath.read( "$.[" + i + "].updated_at" ); results.add( PullRequest.builder() // .id( id ) // - .repo( repoConfig.getName() ) // .source( source ) // .destination( destination ) // - .url( "/pulls/" + id ) // .lastUpdate( lastUpdate ) // .build() ); // } return results; } + private String requestPath( final PullRequest pullRequest ) { + return "/pulls/" + pullRequest.getId(); + } + private DocumentContext jsonPathForPath( final String urlPath ) { final String json = template.getForObject( urlPath, String.class ); return JsonPath.parse( json ); diff --git a/src/main/java/org/retest/rebazer/domain/PullRequest.java b/src/main/java/org/retest/rebazer/domain/PullRequest.java index c4e48f0..a1c962b 100644 --- a/src/main/java/org/retest/rebazer/domain/PullRequest.java +++ b/src/main/java/org/retest/rebazer/domain/PullRequest.java @@ -8,10 +8,8 @@ public class PullRequest { private final Integer id; - private final String repo; private final String source; private final String destination; - private final String url; private final String lastUpdate; @Override diff --git a/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java b/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java index bea7c3a..652ae54 100644 --- a/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java +++ b/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java @@ -78,7 +78,6 @@ public void rebaseNeeded_should_return_true_if_headOfBranch_isnt_equal_to_lastCo @Test public void isApproved_should_return_false_if_approved_is_false() { final PullRequest pullRequest = mock( PullRequest.class ); - when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{participants: [{\"approved\": false}]}\""; when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); @@ -88,7 +87,6 @@ public void isApproved_should_return_false_if_approved_is_false() { @Test public void isApproved_should_return_ture_if_approved_is_true() { final PullRequest pullRequest = mock( PullRequest.class ); - when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{participants: [{\"approved\": true}]}\""; when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); @@ -125,10 +123,9 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); final int expectedId = (int) documentContext.read( "$.values[0].id" ); - final String expectedUrl = "/pullrequests/" + expectedId; - final List expected = Arrays.asList( PullRequest.builder().id( expectedId ).repo( repo.getName() ) + final List expected = Arrays.asList( PullRequest.builder().id( expectedId ) .source( documentContext.read( "$.values[0].source.branch.name" ) ) - .destination( documentContext.read( "$.values[0].destination.branch.name" ) ).url( expectedUrl ) + .destination( documentContext.read( "$.values[0].destination.branch.name" ) ) .lastUpdate( documentContext.read( "$.values[0].updated_on" ) ).build() ); final List actual = cut.getAllPullRequests( repo ); @@ -138,7 +135,6 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws @Test public void getLatestUpdate_should_return_updated_PullRequest() { final PullRequest pullRequest = mock( PullRequest.class ); - when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{\"updated_on\": \"someTimestamp\"}"; when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); diff --git a/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java b/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java index fd3876c..bb64074 100644 --- a/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java +++ b/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java @@ -119,11 +119,10 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); final int expectedId = (int) documentContext.read( "$.[0].number" ); - final String expectedUrl = "/repos/" + team.getName() + "/" + repo.getName() + "/pulls/" + expectedId; - final List expected = Arrays.asList( PullRequest.builder().id( expectedId ).repo( repo.getName() ) - .source( documentContext.read( "$.[0].head.ref" ) ) - .destination( documentContext.read( "$.[0].base.ref" ) ).url( expectedUrl ) - .lastUpdate( documentContext.read( "$.[0].updated_at" ) ).build() ); + final List expected = + Arrays.asList( PullRequest.builder().id( expectedId ).source( documentContext.read( "$.[0].head.ref" ) ) + .destination( documentContext.read( "$.[0].base.ref" ) ) + .lastUpdate( documentContext.read( "$.[0].updated_at" ) ).build() ); final List actual = cut.getAllPullRequests( repo ); assertThat( actual ).isEqualTo( expected ); @@ -132,7 +131,6 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws @Test public void getLatestUpdate_should_return_updated_PullRequest() { final PullRequest pullRequest = mock( PullRequest.class ); - when( pullRequest.getUrl() ).thenReturn( "url:dummy" ); final String json = "{\"updated_at\": \"someTimestamp\"}"; when( template.getForObject( anyString(), eq( String.class ) ) ).thenReturn( json ); From 47e1318a5b0ff4661e33e606dde692f9407a0a50 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Fri, 20 Jul 2018 08:33:09 +0200 Subject: [PATCH 67/86] Remove obsolete repoConfig in RepositoryConnector.getAllPullRequests --- src/main/java/org/retest/rebazer/RebazerService.java | 2 +- .../org/retest/rebazer/connector/BitbucketConnector.java | 7 +++---- .../java/org/retest/rebazer/connector/GithubConnector.java | 7 +++---- .../org/retest/rebazer/connector/RepositoryConnector.java | 3 +-- .../retest/rebazer/connector/BitbucketConnectorTest.java | 2 +- .../org/retest/rebazer/connector/GithubConnectorTest.java | 2 +- 6 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/retest/rebazer/RebazerService.java b/src/main/java/org/retest/rebazer/RebazerService.java index 89f6845..4a51193 100644 --- a/src/main/java/org/retest/rebazer/RebazerService.java +++ b/src/main/java/org/retest/rebazer/RebazerService.java @@ -45,7 +45,7 @@ private void handleRepo( final RepositoryHost repoHost, final RepositoryTeam rep final RepositoryConfig repoConfig ) { log.debug( "Processing {}.", repoConfig ); final RepositoryConnector repoConnector = repoHost.getType().getRepository( repoTeam, repoConfig, builder ); - for ( final PullRequest pullRequest : repoConnector.getAllPullRequests( repoConfig ) ) { + for ( final PullRequest pullRequest : repoConnector.getAllPullRequests() ) { handlePullRequest( repoConnector, repoConfig, pullRequest ); } log.debug( "Processing done for {}.", repoConfig ); diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index d2ae36f..7d4d694 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -98,13 +98,12 @@ public boolean greenBuildExists( final PullRequest pullRequest ) { } @Override - public List getAllPullRequests( final RepositoryConfig repoConfig ) { + public List getAllPullRequests() { final DocumentContext jsonPath = jsonPathForPath( "/pullrequests" ); - return parsePullRequestsJson( repoConfig, jsonPath ); + return parsePullRequestsJson( jsonPath ); } - public List parsePullRequestsJson( final RepositoryConfig repoConfig, - final DocumentContext jsonPath ) { + public List parsePullRequestsJson( final DocumentContext jsonPath ) { final int numPullRequests = (int) jsonPath.read( "$.size" ); final List results = new ArrayList<>( numPullRequests ); for ( int i = 0; i < numPullRequests; i++ ) { diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index 4824e89..bf22f49 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -97,13 +97,12 @@ public boolean greenBuildExists( final PullRequest pullRequest ) { } @Override - public List getAllPullRequests( final RepositoryConfig repoConfig ) { + public List getAllPullRequests() { final DocumentContext jsonPath = jsonPathForPath( "/pulls" ); - return parsePullRequestsJson( repoConfig, jsonPath ); + return parsePullRequestsJson( jsonPath ); } - public static List parsePullRequestsJson( final RepositoryConfig repoConfig, - final DocumentContext jsonPath ) { + public static List parsePullRequestsJson( final DocumentContext jsonPath ) { final List pullRequestAmount = jsonPath.read( "$..number" ); final int numPullRequests = pullRequestAmount.size(); final List results = new ArrayList<>( numPullRequests ); diff --git a/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java b/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java index da42f3e..ff1995c 100644 --- a/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java +++ b/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java @@ -2,12 +2,11 @@ import java.util.List; -import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.domain.PullRequest; public interface RepositoryConnector { - List getAllPullRequests( RepositoryConfig repoConfig ); + List getAllPullRequests(); PullRequest getLatestUpdate( PullRequest pullRequest ); diff --git a/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java b/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java index 652ae54..a94ec48 100644 --- a/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java +++ b/src/test/java/org/retest/rebazer/connector/BitbucketConnectorTest.java @@ -127,7 +127,7 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws .source( documentContext.read( "$.values[0].source.branch.name" ) ) .destination( documentContext.read( "$.values[0].destination.branch.name" ) ) .lastUpdate( documentContext.read( "$.values[0].updated_on" ) ).build() ); - final List actual = cut.getAllPullRequests( repo ); + final List actual = cut.getAllPullRequests(); assertThat( actual ).isEqualTo( expected ); } diff --git a/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java b/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java index bb64074..dc4cfc4 100644 --- a/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java +++ b/src/test/java/org/retest/rebazer/connector/GithubConnectorTest.java @@ -123,7 +123,7 @@ public void getAllPullRequests_should_return_all_pull_requests_as_list() throws Arrays.asList( PullRequest.builder().id( expectedId ).source( documentContext.read( "$.[0].head.ref" ) ) .destination( documentContext.read( "$.[0].base.ref" ) ) .lastUpdate( documentContext.read( "$.[0].updated_at" ) ).build() ); - final List actual = cut.getAllPullRequests( repo ); + final List actual = cut.getAllPullRequests(); assertThat( actual ).isEqualTo( expected ); } From cd9614f09c1822580a1ca11c29788c0f957b4477 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Fri, 20 Jul 2018 08:36:28 +0200 Subject: [PATCH 68/86] Reduce code in PullRequestLastUpdateStore --- .../service/PullRequestLastUpdateStore.java | 19 +++++++------------ .../PullRequestLastUpdateStoreTest.java | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java b/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java index 435a349..69e4667 100644 --- a/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java +++ b/src/main/java/org/retest/rebazer/service/PullRequestLastUpdateStore.java @@ -13,28 +13,23 @@ public class PullRequestLastUpdateStore { private final Map> pullRequestUpdateStates = new HashMap<>(); public void setHandled( final RepositoryConfig repoConfig, final PullRequest pullRequest ) { - Map repoMap = pullRequestUpdateStates.get( repoConfig ); - if ( repoMap == null ) { - repoMap = new HashMap<>(); - pullRequestUpdateStates.put( repoConfig, repoMap ); - } - repoMap.put( pullRequest.getId(), pullRequest.getLastUpdate() ); + getMapFor( repoConfig ).put( pullRequest.getId(), pullRequest.getLastUpdate() ); } public String getLastDate( final RepositoryConfig repoConfig, final PullRequest pullRequest ) { - final Map repoMap = pullRequestUpdateStates.get( repoConfig ); - return repoMap != null ? repoMap.get( pullRequest.getId() ) : null; + return getMapFor( repoConfig ).get( pullRequest.getId() ); } public void resetAllInThisRepo( final RepositoryConfig repoConfig ) { - final Map repoMap = pullRequestUpdateStates.get( repoConfig ); - if ( repoMap != null ) { - repoMap.clear(); - } + pullRequestUpdateStates.remove( repoConfig ); } public boolean isHandled( final RepositoryConfig repoConfig, final PullRequest pullRequest ) { return pullRequest.getLastUpdate().equals( getLastDate( repoConfig, pullRequest ) ); } + private Map getMapFor( final RepositoryConfig repoConfig ) { + return pullRequestUpdateStates.computeIfAbsent( repoConfig, key -> new HashMap<>() ); + } + } diff --git a/src/test/java/org/retest/rebazer/service/PullRequestLastUpdateStoreTest.java b/src/test/java/org/retest/rebazer/service/PullRequestLastUpdateStoreTest.java index feb1e57..6bbeb4a 100644 --- a/src/test/java/org/retest/rebazer/service/PullRequestLastUpdateStoreTest.java +++ b/src/test/java/org/retest/rebazer/service/PullRequestLastUpdateStoreTest.java @@ -4,6 +4,9 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.util.HashMap; +import java.util.Map; + import org.junit.Before; import org.junit.Test; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; @@ -67,4 +70,16 @@ public void getLastDate_should_return_the_date_if_pr_is_handled_before() { assertThat( cut.getLastDate( repo, pr ) ).isEqualTo( lastUpdate ); } + @Test + public void computeIfAbsent_should_add_value_if_key_not_exist() throws Exception { + final HashMap> multiMap = new HashMap<>(); + final RepositoryConfig key = new RepositoryConfig(); + + final Map mapForKey = multiMap.computeIfAbsent( key, k -> new HashMap<>() ); + + assertThat( mapForKey ).isNotNull(); + assertThat( multiMap.get( key ) ).isSameAs( mapForKey ); + assertThat( multiMap.computeIfAbsent( key, k -> new HashMap<>() ) ).isSameAs( mapForKey ); + } + } From 54e7c3e21f6cfe005d2ad46ce19ac64567d641f6 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Fri, 20 Jul 2018 08:40:08 +0200 Subject: [PATCH 69/86] lastUpdate isn't a usefull criteria to identify a PullRequest --- src/main/java/org/retest/rebazer/domain/PullRequest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/retest/rebazer/domain/PullRequest.java b/src/main/java/org/retest/rebazer/domain/PullRequest.java index a1c962b..fb5732b 100644 --- a/src/main/java/org/retest/rebazer/domain/PullRequest.java +++ b/src/main/java/org/retest/rebazer/domain/PullRequest.java @@ -2,6 +2,7 @@ import lombok.Builder; import lombok.Data; +import lombok.EqualsAndHashCode; @Data @Builder @@ -10,6 +11,7 @@ public class PullRequest { private final Integer id; private final String source; private final String destination; + @EqualsAndHashCode.Exclude private final String lastUpdate; @Override From 3165f4de753b0c689ef47576718ab922139074d0 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Fri, 20 Jul 2018 10:40:26 +0200 Subject: [PATCH 70/86] Make RepositoryHost.url optional --- .../org/retest/rebazer/KnownProvider.java | 20 +++++++++++++++++-- .../retest/rebazer/config/RebazerConfig.java | 8 ++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/retest/rebazer/KnownProvider.java b/src/main/java/org/retest/rebazer/KnownProvider.java index e3311ba..83618fb 100644 --- a/src/main/java/org/retest/rebazer/KnownProvider.java +++ b/src/main/java/org/retest/rebazer/KnownProvider.java @@ -1,5 +1,8 @@ package org.retest.rebazer; +import java.net.MalformedURLException; +import java.net.URL; + import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryTeam; import org.retest.rebazer.connector.BitbucketConnector; @@ -7,10 +10,23 @@ import org.retest.rebazer.connector.RepositoryConnector; import org.springframework.boot.web.client.RestTemplateBuilder; +import lombok.Getter; +import lombok.SneakyThrows; + public enum KnownProvider { - BITBUCKET, - GITHUB; + BITBUCKET( "https://bitbucket.org/" ), + GITHUB( "https://github.com/" ), + + ; + + @Getter + final URL defaultUrl; + + @SneakyThrows( MalformedURLException.class ) + private KnownProvider( final String defaultUrl ) { + this.defaultUrl = new URL( defaultUrl ); + } public RepositoryConnector getRepository( final RepositoryTeam repoTeam, final RepositoryConfig repoConfig, final RestTemplateBuilder templateBuilder ) { diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index b564455..dd3bc7d 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -31,6 +31,14 @@ public static class RepositoryHost { private KnownProvider type; private URL url; private List teams; + + public URL getUrl() { + if ( url != null ) { + return url; + } else { + return type.getDefaultUrl(); + } + } } @Data From c32732d594e22c0358b7b5e4c35fdae594f21519 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Fri, 20 Jul 2018 10:50:36 +0200 Subject: [PATCH 71/86] Make RepositoryTeam.user optional --- .../java/org/retest/rebazer/config/RebazerConfig.java | 8 ++++++++ src/main/resources/application.yml.example | 3 +-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index dd3bc7d..8855265 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -47,6 +47,14 @@ public static class RepositoryTeam { private String user; private String pass; private List repos; + + public String getUser() { + if ( user != null && !user.isEmpty() ) { + return user; + } else { + return name; + } + } } @Data diff --git a/src/main/resources/application.yml.example b/src/main/resources/application.yml.example index cc45c0c..9f58531 100644 --- a/src/main/resources/application.yml.example +++ b/src/main/resources/application.yml.example @@ -11,7 +11,7 @@ rebazer: url: https://bitbucket.org/ teams: - name: your_company - user: service_user + user: service_user # optional value, default is $name pass: dont_use_this_pass_at_home repos: - name: blub @@ -23,7 +23,6 @@ rebazer: url: https://github.com/ teams: - name: your_company - user: service_user pass: dont_use_this_pass_at_home repos: - name: foo From b448faed4944f5a247b82d28cc9ced14dee8a651 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Fri, 20 Jul 2018 10:51:26 +0200 Subject: [PATCH 72/86] Make RepositoryConfig.branch optional, defaults to "master" --- src/main/java/org/retest/rebazer/config/RebazerConfig.java | 2 +- src/main/resources/application.yml.example | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 8855265..ee89086 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -60,7 +60,7 @@ public String getUser() { @Data public static class RepositoryConfig { private String name; - private String branch; + private String branch = "master"; } } diff --git a/src/main/resources/application.yml.example b/src/main/resources/application.yml.example index 9f58531..22d5431 100644 --- a/src/main/resources/application.yml.example +++ b/src/main/resources/application.yml.example @@ -15,7 +15,7 @@ rebazer: pass: dont_use_this_pass_at_home repos: - name: blub - branch: blub + branch: blub # optional value, default is "master" - name: bla branch: bla @@ -26,4 +26,3 @@ rebazer: pass: dont_use_this_pass_at_home repos: - name: foo - branch: foo From f220407fc47a245d0f708e2ab7a3c18b279b4893 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Tue, 24 Jul 2018 15:37:03 +0200 Subject: [PATCH 73/86] Change RepositoryConfig.masterBranch name and update application.yml.example --- .../retest/rebazer/config/RebazerConfig.java | 2 +- .../retest/rebazer/service/RebaseService.java | 4 ++-- src/main/resources/application.yml.example | 19 +++++++++---------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index ee89086..543bcd4 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -60,7 +60,7 @@ public String getUser() { @Data public static class RepositoryConfig { private String name; - private String branch = "master"; + private String masterBranch = "master"; } } diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 7c28bc7..7838631 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -55,7 +55,7 @@ private void setupRepo( final RepositoryHost repoHost, final RepositoryTeam repo credentials.put( repoConfig, credential ); localGitRepos.put( repoConfig, localRepo ); - cleaner.cleanUp( localRepo, repoConfig.getBranch() ); + cleaner.cleanUp( localRepo, repoConfig.getMasterBranch() ); } private CredentialsProvider repoCredential( final RepositoryTeam repoTeam ) { @@ -157,7 +157,7 @@ public boolean rebase( final RepositoryConfig repoConfig, final PullRequest pull "For " + pullRequest + " rebase causes an unexpected result: " + rebaseResult.getStatus() ); } } finally { - cleaner.cleanUp( localRepo, repoConfig.getBranch() ); + cleaner.cleanUp( localRepo, repoConfig.getMasterBranch() ); } } diff --git a/src/main/resources/application.yml.example b/src/main/resources/application.yml.example index 22d5431..575f227 100644 --- a/src/main/resources/application.yml.example +++ b/src/main/resources/application.yml.example @@ -3,24 +3,23 @@ spring: web-environment: false rebazer: - workspace: ./rebazer-workspace - garbageCollectionCountdown: 20 - pollInterval: 60 + workspace: ./rebazer-workspace # optional + garbageCollectionCountdown: 20 # optional + pollInterval: 60 # optional hosts: - - type: BITBUCKET - url: https://bitbucket.org/ + - type: BITBUCKET # possible values GITHUB or BITBUCKET + url: https://bitbucket.org/ # optional, default is type dependent (github.com, bitbucket.org) teams: - name: your_company user: service_user # optional value, default is $name pass: dont_use_this_pass_at_home repos: - - name: blub - branch: blub # optional value, default is "master" - - name: bla - branch: bla + - name: the_repo_name + masterBranch: develop # optional value, default is "master" + - name: otherRepo + masterBranch: trunk - type: GITHUB - url: https://github.com/ teams: - name: your_company pass: dont_use_this_pass_at_home From 27d945d33fa37ae84a7e17e2a925bd5336853b43 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Wed, 25 Jul 2018 19:15:23 +0200 Subject: [PATCH 74/86] Make methods static which can be static --- src/main/java/org/retest/rebazer/config/AppConfig.java | 2 +- .../org/retest/rebazer/connector/BitbucketConnector.java | 4 ++-- .../org/retest/rebazer/connector/GithubConnector.java | 2 +- .../java/org/retest/rebazer/service/GitRepoCleaner.java | 6 +++--- .../java/org/retest/rebazer/service/RebaseService.java | 9 +++++---- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/retest/rebazer/config/AppConfig.java b/src/main/java/org/retest/rebazer/config/AppConfig.java index c9c423e..9128eb5 100644 --- a/src/main/java/org/retest/rebazer/config/AppConfig.java +++ b/src/main/java/org/retest/rebazer/config/AppConfig.java @@ -9,7 +9,7 @@ public class AppConfig { @Bean - public TaskScheduler taskScheduler() { + public static TaskScheduler taskScheduler() { return new ThreadPoolTaskScheduler(); } diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index 7d4d694..b47cf57 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -103,7 +103,7 @@ public List getAllPullRequests() { return parsePullRequestsJson( jsonPath ); } - public List parsePullRequestsJson( final DocumentContext jsonPath ) { + public static List parsePullRequestsJson( final DocumentContext jsonPath ) { final int numPullRequests = (int) jsonPath.read( "$.size" ); final List results = new ArrayList<>( numPullRequests ); for ( int i = 0; i < numPullRequests; i++ ) { @@ -121,7 +121,7 @@ public List parsePullRequestsJson( final DocumentContext jsonPath ) return results; } - private String requestPath( final PullRequest pullRequest ) { + private static String requestPath( final PullRequest pullRequest ) { return "/pullrequests/" + pullRequest.getId(); } diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index bf22f49..9c456a1 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -121,7 +121,7 @@ public static List parsePullRequestsJson( final DocumentContext jso return results; } - private String requestPath( final PullRequest pullRequest ) { + private static String requestPath( final PullRequest pullRequest ) { return "/pulls/" + pullRequest.getId(); } diff --git a/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java index 30cbea8..f3383b2 100644 --- a/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java +++ b/src/main/java/org/retest/rebazer/service/GitRepoCleaner.java @@ -36,18 +36,18 @@ public void cleanUp( final Git localRepo, final String fallbackBranchName ) { } @SneakyThrows - private void resetAndRemoveUntrackedFiles( final Git localRepo ) { + private static void resetAndRemoveUntrackedFiles( final Git localRepo ) { localRepo.clean().setCleanDirectories( true ).setForce( true ).setIgnore( false ).call(); localRepo.reset().setMode( ResetType.HARD ).call(); } @SneakyThrows - private void checkoutFallbackBranch( final Git localRepo, final String fallbackBranchName ) { + private static void checkoutFallbackBranch( final Git localRepo, final String fallbackBranchName ) { localRepo.checkout().setName( "remotes/origin/" + fallbackBranchName ).call(); } @SneakyThrows - private void removeAllLocalBranches( final Git localRepo ) { + private static void removeAllLocalBranches( final Git localRepo ) { final List allBranches = localRepo.branchList().call(); final String[] localBranches = allBranches.stream() // .map( branch -> branch.getName() ) // diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 7838631..55f3ec0 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -58,7 +58,7 @@ private void setupRepo( final RepositoryHost repoHost, final RepositoryTeam repo cleaner.cleanUp( localRepo, repoConfig.getMasterBranch() ); } - private CredentialsProvider repoCredential( final RepositoryTeam repoTeam ) { + private static CredentialsProvider repoCredential( final RepositoryTeam repoTeam ) { return new UsernamePasswordCredentialsProvider( repoTeam.getUser(), repoTeam.getPass() ); } @@ -68,12 +68,13 @@ private File repoFolder( final RepositoryHost repoHost, final RepositoryTeam rep repoConfig.getName() ); } - private String repoUrl( final RepositoryHost repoHost, final RepositoryTeam repoTeam, + private static String repoUrl( final RepositoryHost repoHost, final RepositoryTeam repoTeam, final RepositoryConfig repoConfig ) { return repoHost.getUrl() + "/" + repoTeam.getName() + "/" + repoConfig.getName() + ".git"; } - private Git setupLocalGitRepo( final CredentialsProvider credential, final File repoFolder, final String repoUrl ) { + private static Git setupLocalGitRepo( final CredentialsProvider credential, final File repoFolder, + final String repoUrl ) { if ( repoFolder.exists() ) { final Git localRepo = tryToOpenExistingRepoAndCheckRemote( repoFolder, repoUrl ); if ( localRepo != null ) { @@ -85,7 +86,7 @@ private Git setupLocalGitRepo( final CredentialsProvider credential, final File } @SneakyThrows - private void deleteDirectory( final File repoFolder ) { + private static void deleteDirectory( final File repoFolder ) { FileUtils.deleteDirectory( repoFolder ); } From 183e43a4dd740418694ae21aafe63fe79847eef8 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Wed, 25 Jul 2018 19:49:51 +0200 Subject: [PATCH 75/86] Rename KnownProvider to RepositoryHostingTypes --- .../{KnownProvider.java => RepositoryHostingTypes.java} | 4 ++-- src/main/java/org/retest/rebazer/config/RebazerConfig.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/main/java/org/retest/rebazer/{KnownProvider.java => RepositoryHostingTypes.java} (92%) diff --git a/src/main/java/org/retest/rebazer/KnownProvider.java b/src/main/java/org/retest/rebazer/RepositoryHostingTypes.java similarity index 92% rename from src/main/java/org/retest/rebazer/KnownProvider.java rename to src/main/java/org/retest/rebazer/RepositoryHostingTypes.java index 83618fb..a85bae0 100644 --- a/src/main/java/org/retest/rebazer/KnownProvider.java +++ b/src/main/java/org/retest/rebazer/RepositoryHostingTypes.java @@ -13,7 +13,7 @@ import lombok.Getter; import lombok.SneakyThrows; -public enum KnownProvider { +public enum RepositoryHostingTypes { BITBUCKET( "https://bitbucket.org/" ), GITHUB( "https://github.com/" ), @@ -24,7 +24,7 @@ public enum KnownProvider { final URL defaultUrl; @SneakyThrows( MalformedURLException.class ) - private KnownProvider( final String defaultUrl ) { + private RepositoryHostingTypes( final String defaultUrl ) { this.defaultUrl = new URL( defaultUrl ); } diff --git a/src/main/java/org/retest/rebazer/config/RebazerConfig.java b/src/main/java/org/retest/rebazer/config/RebazerConfig.java index 543bcd4..748010e 100644 --- a/src/main/java/org/retest/rebazer/config/RebazerConfig.java +++ b/src/main/java/org/retest/rebazer/config/RebazerConfig.java @@ -3,7 +3,7 @@ import java.net.URL; import java.util.List; -import org.retest.rebazer.KnownProvider; +import org.retest.rebazer.RepositoryHostingTypes; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -28,7 +28,7 @@ public class RebazerConfig { @Data public static class RepositoryHost { - private KnownProvider type; + private RepositoryHostingTypes type; private URL url; private List teams; From e1eb0570996edcb626f63aa2a84bca4f155e5488 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Wed, 25 Jul 2018 20:02:52 +0200 Subject: [PATCH 76/86] Remove dupplicate logger --- .../java/org/retest/rebazer/connector/BitbucketConnector.java | 1 - .../java/org/retest/rebazer/connector/GithubConnector.java | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index b47cf57..8e31cdf 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -14,7 +14,6 @@ import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; - public class BitbucketConnector implements RepositoryConnector { private final static String baseUrlV1 = "https://api.bitbucket.org/1.0"; diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index 9c456a1..bcf724d 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -14,9 +14,6 @@ import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; -import lombok.extern.slf4j.Slf4j; - -@Slf4j public class GithubConnector implements RepositoryConnector { private final static String baseUrl = "https://api.github.com/"; @@ -79,7 +76,6 @@ String getLastCommonCommitId( final PullRequest pullRequest ) { @Override public void merge( final PullRequest pullRequest ) { - log.warn( "Merging pull request {}", pullRequest ); final String message = String.format( "Merged in %s (pull request #%d) by ReBaZer", pullRequest.getSource(), pullRequest.getId() ); final Map request = new HashMap<>(); From 6a24f9442abf8b05e7edb461980994bb1948a46b Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 2 Aug 2018 18:13:04 +0200 Subject: [PATCH 77/86] Add param message to addComment --- src/main/java/org/retest/rebazer/RebazerService.java | 4 +++- .../java/org/retest/rebazer/connector/BitbucketConnector.java | 4 ++-- .../java/org/retest/rebazer/connector/GithubConnector.java | 4 ++-- .../org/retest/rebazer/connector/RepositoryConnector.java | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/retest/rebazer/RebazerService.java b/src/main/java/org/retest/rebazer/RebazerService.java index 4a51193..4520bcd 100644 --- a/src/main/java/org/retest/rebazer/RebazerService.java +++ b/src/main/java/org/retest/rebazer/RebazerService.java @@ -24,6 +24,8 @@ @RequiredArgsConstructor( onConstructor = @__( @Autowired ) ) public class RebazerService { + private static final String MSG_REBASE_FAILED = "Rebase failed, this pull request needs some manual love ..."; + private final RebaseService rebaseService; private final RebazerConfig rebazerConfig; private final PullRequestLastUpdateStore pullRequestLastUpdateStore; @@ -65,7 +67,7 @@ public void handlePullRequest( final RepositoryConnector repoConnector, final Re } else if ( repoConnector.rebaseNeeded( pullRequest ) ) { if ( !rebaseService.rebase( repoConfig, pullRequest ) ) { - repoConnector.addComment( pullRequest ); + repoConnector.addComment( pullRequest, MSG_REBASE_FAILED ); } // we need to update the "lastUpdate" of a PullRequest to counteract if addComment is called pullRequestLastUpdateStore.setHandled( repoConfig, repoConnector.getLatestUpdate( pullRequest ) ); diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index 8e31cdf..f76a03e 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -130,9 +130,9 @@ private DocumentContext jsonPathForPath( final String urlPath ) { } @Override - public void addComment( final PullRequest pullRequest ) { + public void addComment( final PullRequest pullRequest, final String message ) { final Map request = new HashMap<>(); - request.put( "content", "This pull request needs some manual love ..." ); + request.put( "content", message ); legacyTemplate.postForObject( requestPath( pullRequest ) + "/comments", request, String.class ); } diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index bcf724d..19f993e 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -127,9 +127,9 @@ private DocumentContext jsonPathForPath( final String urlPath ) { } @Override - public void addComment( final PullRequest pullRequest ) { + public void addComment( final PullRequest pullRequest, final String message ) { final Map request = new HashMap<>(); - request.put( "body", "This pull request needs some manual love ..." ); + request.put( "body", message ); template.postForObject( "/issues/" + pullRequest.getId() + "/comments", request, String.class ); } diff --git a/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java b/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java index ff1995c..636a67f 100644 --- a/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java +++ b/src/main/java/org/retest/rebazer/connector/RepositoryConnector.java @@ -18,6 +18,6 @@ public interface RepositoryConnector { void merge( PullRequest pullRequest ); - void addComment( PullRequest pullRequest ); + void addComment( final PullRequest pullRequest, String message ); } From 4af8bda291307387de60e91a05430851cd9a247c Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 2 Aug 2018 18:14:10 +0200 Subject: [PATCH 78/86] Remove unnessary cast --- .../java/org/retest/rebazer/connector/BitbucketConnector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index f76a03e..8bd3ffc 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -103,7 +103,7 @@ public List getAllPullRequests() { } public static List parsePullRequestsJson( final DocumentContext jsonPath ) { - final int numPullRequests = (int) jsonPath.read( "$.size" ); + final int numPullRequests = jsonPath.read( "$.size" ); final List results = new ArrayList<>( numPullRequests ); for ( int i = 0; i < numPullRequests; i++ ) { final int id = jsonPath.read( "$.values[" + i + "].id" ); From cd3ae0c9580fdecab43d5313f17b80ff938e0f8c Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 2 Aug 2018 18:14:46 +0200 Subject: [PATCH 79/86] Use FileUtils.getFile() for multiple combined new File() --- src/main/java/org/retest/rebazer/service/RebaseService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 55f3ec0..0e1adc1 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -64,8 +64,7 @@ private static CredentialsProvider repoCredential( final RepositoryTeam repoTeam private File repoFolder( final RepositoryHost repoHost, final RepositoryTeam repoTeam, final RepositoryConfig repoConfig ) { - return new File( new File( new File( workspace, repoHost.getUrl().getHost() ), repoTeam.getName() ), - repoConfig.getName() ); + return FileUtils.getFile( workspace, repoHost.getUrl().getHost(), repoTeam.getName(), repoConfig.getName() ); } private static String repoUrl( final RepositoryHost repoHost, final RepositoryTeam repoTeam, From 31bc1e70dd040bdf70e0cdbcb2fc2a383245d153 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 2 Aug 2018 18:17:43 +0200 Subject: [PATCH 80/86] Simplify size lookup in parsePullRequestsJson --- .../org/retest/rebazer/connector/GithubConnector.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index 19f993e..fd97243 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -99,11 +99,10 @@ public List getAllPullRequests() { } public static List parsePullRequestsJson( final DocumentContext jsonPath ) { - final List pullRequestAmount = jsonPath.read( "$..number" ); - final int numPullRequests = pullRequestAmount.size(); - final List results = new ArrayList<>( numPullRequests ); - for ( int i = 0; i < numPullRequests; i++ ) { - final int id = pullRequestAmount.get( i ); + final int size = jsonPath.read( "$.length()" ); + final List results = new ArrayList<>( size ); + for ( int i = 0; i < size; i++ ) { + final int id = jsonPath.read( "$.[" + i + "].number" ); final String source = jsonPath.read( "$.[" + i + "].head.ref" ); final String destination = jsonPath.read( "$.[" + i + "].base.ref" ); final String lastUpdate = jsonPath.read( "$.[" + i + "].updated_at" ); From 123a8191527e360984d035a09f6043c6918c7527 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 2 Aug 2018 18:40:02 +0200 Subject: [PATCH 81/86] Make RebaseService.originIsRepoUrl more readable --- .../org/retest/rebazer/service/RebaseService.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/retest/rebazer/service/RebaseService.java b/src/main/java/org/retest/rebazer/service/RebaseService.java index 0e1adc1..600ccc8 100644 --- a/src/main/java/org/retest/rebazer/service/RebaseService.java +++ b/src/main/java/org/retest/rebazer/service/RebaseService.java @@ -9,6 +9,7 @@ import org.eclipse.jgit.api.RebaseCommand.Operation; import org.eclipse.jgit.api.RebaseResult; import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.retest.rebazer.config.RebazerConfig; import org.retest.rebazer.config.RebazerConfig.RepositoryConfig; @@ -106,8 +107,14 @@ private static Git tryToOpenExistingRepoAndCheckRemote( final File repoFolder, f @SneakyThrows private static boolean originIsRepoUrl( final Git localRepo, final String repoUrl ) { - return localRepo.remoteList().call().stream().anyMatch( r -> r.getName().equals( "origin" ) - && r.getURIs().stream().anyMatch( url -> url.toString().equals( repoUrl ) ) ); + return localRepo.remoteList().call().stream() // + .filter( r -> r.getName().equals( "origin" ) ) // + .anyMatch( r -> remoteConfigContainsRepoUrl( r, repoUrl ) ); + + } + + private static boolean remoteConfigContainsRepoUrl( final RemoteConfig remoteConfig, final String repoUrl ) { + return remoteConfig.getURIs().stream().anyMatch( url -> url.toString().equals( repoUrl ) ); } @SneakyThrows From 15d4e3a3679c6cc89a2118c0add777b85d346f01 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 2 Aug 2018 18:40:27 +0200 Subject: [PATCH 82/86] Simplify GithubConnector.isApproved() --- .../org/retest/rebazer/connector/GithubConnector.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index fd97243..e5fbce3 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -43,16 +43,7 @@ public PullRequest getLatestUpdate( final PullRequest pullRequest ) { @Override public boolean isApproved( final PullRequest pullRequest ) { final DocumentContext jsonPath = jsonPathForPath( requestPath( pullRequest ) + "/reviews" ); - final List states = jsonPath.read( "$..state" ); - boolean approved = false; - for ( final String state : states ) { - if ( state.equals( "APPROVED" ) ) { - approved = true; - } else { - approved = false; - } - } - return approved; + return jsonPath.> read( "$..state" ).stream().anyMatch( s -> s.equals( "APPROVED" ) ); } @Override From 1d6190c422c9d621e48da12fa351ea2b94869aa7 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 2 Aug 2018 18:41:09 +0200 Subject: [PATCH 83/86] Use underscore_style for all demo variables in application.yml.example --- src/main/resources/application.yml.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.yml.example b/src/main/resources/application.yml.example index 575f227..7ce4e26 100644 --- a/src/main/resources/application.yml.example +++ b/src/main/resources/application.yml.example @@ -16,7 +16,7 @@ rebazer: repos: - name: the_repo_name masterBranch: develop # optional value, default is "master" - - name: otherRepo + - name: other_repo masterBranch: trunk - type: GITHUB From a7a46337f71f2cf93ef2981d4a33a0a629a913a0 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 2 Aug 2018 18:42:02 +0200 Subject: [PATCH 84/86] Remove obsolete / in baseUrl --- src/main/java/org/retest/rebazer/connector/GithubConnector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index e5fbce3..e536e97 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -16,7 +16,7 @@ public class GithubConnector implements RepositoryConnector { - private final static String baseUrl = "https://api.github.com/"; + private final static String baseUrl = "https://api.github.com"; private final RestTemplate template; From 2e00971e3a5a2ab9a68ca008a5abfbbfaace0d0f Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 2 Aug 2018 18:53:15 +0200 Subject: [PATCH 85/86] Merge dupplicate mergeCommitMessage code --- .../org/retest/rebazer/connector/BitbucketConnector.java | 5 +---- .../java/org/retest/rebazer/connector/GithubConnector.java | 4 +--- src/main/java/org/retest/rebazer/domain/PullRequest.java | 5 +++++ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index 8bd3ffc..f77d476 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -79,12 +79,9 @@ String getLastCommonCommitId( final PullRequest pullRequest ) { @Override public void merge( final PullRequest pullRequest ) { - final String message = String.format( "Merged in %s (pull request #%d) by ReBaZer", pullRequest.getSource(), - pullRequest.getId() ); - // TODO add approver to message? final Map request = new HashMap<>(); request.put( "close_source_branch", true ); - request.put( "message", message ); + request.put( "message", pullRequest.mergeCommitMessage() ); request.put( "merge_strategy", "merge_commit" ); template.postForObject( requestPath( pullRequest ) + "/merge", request, Object.class ); diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index e536e97..00846cd 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -67,10 +67,8 @@ String getLastCommonCommitId( final PullRequest pullRequest ) { @Override public void merge( final PullRequest pullRequest ) { - final String message = String.format( "Merged in %s (pull request #%d) by ReBaZer", pullRequest.getSource(), - pullRequest.getId() ); final Map request = new HashMap<>(); - request.put( "commit_title", message ); + request.put( "commit_title", pullRequest.mergeCommitMessage() ); request.put( "merge_method", "merge" ); template.put( requestPath( pullRequest ) + "/merge", request, Object.class ); diff --git a/src/main/java/org/retest/rebazer/domain/PullRequest.java b/src/main/java/org/retest/rebazer/domain/PullRequest.java index fb5732b..cebf5ed 100644 --- a/src/main/java/org/retest/rebazer/domain/PullRequest.java +++ b/src/main/java/org/retest/rebazer/domain/PullRequest.java @@ -18,4 +18,9 @@ public class PullRequest { public String toString() { return "PR #" + id + " (" + source + " -> " + destination + ")"; } + + public String mergeCommitMessage() { + return String.format( "Merged in %s (pull request #%d) by ReBaZer", source, id ); + } + } From 4a769b4382e9f86c164475998a07d7213731e497 Mon Sep 17 00:00:00 2001 From: Martin Vietz Date: Thu, 2 Aug 2018 18:54:19 +0200 Subject: [PATCH 86/86] Prevent NPE when using string literals --- .../java/org/retest/rebazer/connector/BitbucketConnector.java | 2 +- .../java/org/retest/rebazer/connector/GithubConnector.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java index f77d476..7679e70 100644 --- a/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java +++ b/src/main/java/org/retest/rebazer/connector/BitbucketConnector.java @@ -90,7 +90,7 @@ public void merge( final PullRequest pullRequest ) { @Override public boolean greenBuildExists( final PullRequest pullRequest ) { final DocumentContext jsonPath = jsonPathForPath( requestPath( pullRequest ) + "/statuses" ); - return jsonPath.> read( "$.values[*].state" ).stream().anyMatch( s -> s.equals( "SUCCESSFUL" ) ); + return jsonPath.> read( "$.values[*].state" ).stream().anyMatch( s -> "SUCCESSFUL".equals( s ) ); } @Override diff --git a/src/main/java/org/retest/rebazer/connector/GithubConnector.java b/src/main/java/org/retest/rebazer/connector/GithubConnector.java index 00846cd..0ae2449 100644 --- a/src/main/java/org/retest/rebazer/connector/GithubConnector.java +++ b/src/main/java/org/retest/rebazer/connector/GithubConnector.java @@ -43,7 +43,7 @@ public PullRequest getLatestUpdate( final PullRequest pullRequest ) { @Override public boolean isApproved( final PullRequest pullRequest ) { final DocumentContext jsonPath = jsonPathForPath( requestPath( pullRequest ) + "/reviews" ); - return jsonPath.> read( "$..state" ).stream().anyMatch( s -> s.equals( "APPROVED" ) ); + return jsonPath.> read( "$..state" ).stream().anyMatch( s -> "APPROVED".equals( s ) ); } @Override @@ -78,7 +78,7 @@ public void merge( final PullRequest pullRequest ) { public boolean greenBuildExists( final PullRequest pullRequest ) { final String urlPath = "/commits/" + pullRequest.getSource() + "/status"; final DocumentContext jsonPath = jsonPathForPath( urlPath ); - return jsonPath.> read( "$.statuses[*].state" ).stream().anyMatch( s -> s.equals( "success" ) ); + return jsonPath.> read( "$.statuses[*].state" ).stream().anyMatch( s -> "success".equals( s ) ); } @Override