Skip to content

Commit 45ce120

Browse files
committed
Additional functionality for the Git module.
Added functionality to reset a release train which actively resets to the latest state of the remote branch. Added functionality to push changes to the remote server and push tags individually. Added functionality to create commits for modules. Release operations now create two commits for the changelog update and the pom modifications. Release conclude does so for the preparation of the next development iteration. Added git.author infrastructure property to make sure we use a real user for the git commits.
1 parent eeb511a commit 45ce120

File tree

6 files changed

+197
-30
lines changed

6 files changed

+197
-30
lines changed

infrastructure.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
io.workDir=~/temp/spring-data-shell
1+
io.workDir=~/temp/spring-data-shell
2+
3+
git.author=Oliver Gierke <[email protected]>

src/main/java/org/springframework/data/release/cli/ReleaseCommands.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,18 @@ public void prepare(@CliOption(key = "", mandatory = true) TrainIteration iterat
106106

107107
maven.updatePom(iteration, Phase.PREPARE);
108108
gradle.updateProject(iteration, Phase.PREPARE);
109+
110+
git.commit(iteration, "Prepare %s.", null);
109111
}
110112

111113
@CliCommand(value = "release conclude")
112114
public void conclude(@CliOption(key = "", mandatory = true) TrainIteration iteration) throws Exception {
113115

114116
git.tagRelease(iteration);
115117

116-
// - post release pom updates
117-
118118
maven.updatePom(iteration, Phase.CLEANUP);
119119
gradle.updateProject(iteration, Phase.CLEANUP);
120120

121-
// - push
121+
git.commit(iteration, "After release cleanups.", null);
122122
}
123123
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.release.git;
17+
18+
import lombok.EqualsAndHashCode;
19+
import lombok.RequiredArgsConstructor;
20+
21+
import org.springframework.data.release.jira.Ticket;
22+
23+
/**
24+
* @author Oliver Gierke
25+
*/
26+
@EqualsAndHashCode
27+
@RequiredArgsConstructor
28+
public class Commit {
29+
30+
private final Ticket ticket;
31+
private final String summary;
32+
private final String details;
33+
34+
/*
35+
* (non-Javadoc)
36+
* @see java.lang.Object#toString()
37+
*/
38+
@Override
39+
public String toString() {
40+
41+
StringBuilder builder = new StringBuilder();
42+
43+
builder.append(ticket.getId()).append(" - ").append(summary).append("\n");
44+
45+
if (details != null) {
46+
builder.append("\n");
47+
builder.append(details).append("\n");
48+
}
49+
50+
return builder.toString();
51+
}
52+
}

src/main/java/org/springframework/data/release/git/GitCommands.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,35 @@ public String tags(@CliOption(key = { "project" }, mandatory = true) String proj
6363
* @throws Exception
6464
*/
6565
@CliCommand("git reset")
66-
public void reset(@CliOption(key = { "", "train" }, mandatory = true) String trainName) throws Exception {
67-
git.reset(ReleaseTrains.getTrainByName(trainName));
66+
public void reset(@CliOption(key = "", mandatory = true) TrainIteration iteration) throws Exception {
67+
git.reset(iteration);
6868
}
6969

7070
@CliCommand("git prepare")
7171
public void prepare(@CliOption(key = "", mandatory = true) TrainIteration iteration) throws Exception {
7272
git.prepare(iteration);
7373
}
74+
75+
/**
76+
* Pushes all changes of all modules of the given {@link TrainIteration} to the remote server. If {@code tags} is
77+
* given, only the tags are pushed.
78+
*
79+
* @param iteration
80+
* @param tags
81+
* @throws Exception
82+
*/
83+
@CliCommand("git push")
84+
public void push(//
85+
@CliOption(key = "", mandatory = true) TrainIteration iteration, //
86+
@CliOption(key = "tags", specifiedDefaultValue = "true", unspecifiedDefaultValue = "false") String tags)
87+
throws Exception {
88+
89+
boolean pushTags = Boolean.parseBoolean(tags);
90+
91+
if (pushTags) {
92+
git.pushTags(iteration.getTrain());
93+
} else {
94+
git.push(iteration);
95+
}
96+
}
7497
}

src/main/java/org/springframework/data/release/git/GitOperations.java

Lines changed: 94 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import lombok.RequiredArgsConstructor;
2525

2626
import org.springframework.beans.factory.annotation.Autowired;
27+
import org.springframework.core.env.Environment;
2728
import org.springframework.data.release.io.CommandResult;
2829
import org.springframework.data.release.io.OsCommandOperations;
2930
import org.springframework.data.release.io.Workspace;
@@ -52,10 +53,11 @@
5253
public class GitOperations {
5354

5455
private final GitServer server = new GitServer();
55-
private final OsCommandOperations osCommandOperations;
56+
private final OsCommandOperations os;
5657
private final Workspace workspace;
5758
private final Logger logger;
5859
private final PluginRegistry<IssueTracker, Project> issueTracker;
60+
private final Environment environment;
5961

6062
public GitProject getGitProject(Project project) {
6163
return new GitProject(project, server);
@@ -67,12 +69,15 @@ public GitProject getGitProject(Project project) {
6769
* @param train must not be {@literal null}.
6870
* @throws Exception
6971
*/
70-
public void reset(Train train) throws Exception {
72+
public void reset(TrainIteration train) throws Exception {
7173

7274
Assert.notNull(train, "Train must not be null!");
7375

74-
for (Module module : train) {
75-
osCommandOperations.executeCommand("git reset --hard", module.getProject()).get();
76+
for (ModuleIteration module : train) {
77+
78+
Branch branch = Branch.from(module);
79+
80+
os.executeCommand(String.format("git reset --hard origin/%s", branch), module.getProject()).get();
7681
}
7782
}
7883

@@ -99,7 +104,7 @@ public void checkout(TrainIteration iteration) throws Exception {
99104
artifactVersion, project));
100105
}
101106

102-
osCommandOperations.executeCommand(String.format("git checkout %s", tag), project).get();
107+
os.executeCommand(String.format("git checkout %s", tag), project).get();
103108
}
104109

105110
logger.log(iteration, "Successfully checked out projects.");
@@ -114,7 +119,7 @@ public void prepare(TrainIteration iteration) throws Exception {
114119
update(module.getProject()).get();
115120

116121
String checkoutCommand = String.format("git checkout %s && git pull origin %s", branch, branch);
117-
osCommandOperations.executeCommand(checkoutCommand, module.getProject()).get();
122+
os.executeCommand(checkoutCommand, module.getProject()).get();
118123
}
119124
}
120125

@@ -131,6 +136,22 @@ public void update(Train train) throws Exception {
131136
}
132137
}
133138

139+
public void push(TrainIteration iteration) throws Exception {
140+
141+
for (ModuleIteration module : iteration) {
142+
143+
Branch branch = Branch.from(module);
144+
os.executeCommand(String.format("git push origin %s", branch), module.getProject()).get();
145+
}
146+
}
147+
148+
public void pushTags(Train train) throws Exception {
149+
150+
for (Module module : train) {
151+
os.executeCommand("git push --tags", module.getProject()).get();
152+
}
153+
}
154+
134155
public Future<CommandResult> update(Project project) throws Exception {
135156

136157
GitProject gitProject = new GitProject(project, server);
@@ -140,8 +161,8 @@ public Future<CommandResult> update(Project project) throws Exception {
140161

141162
logger.log(project, "Found existing repository %s. Obtaining latest changes…", repositoryName);
142163

143-
return osCommandOperations.executeCommand(
144-
"git checkout master && git reset --hard && git fetch --tags && git pull origin master", project);
164+
return os.executeCommand("git checkout master && git reset --hard && git fetch --tags && git pull origin master",
165+
project);
145166

146167
} else {
147168

@@ -150,13 +171,13 @@ public Future<CommandResult> update(Project project) throws Exception {
150171
File projectDirectory = workspace.getProjectDirectory(project);
151172
String command = String.format("git clone %s %s", gitProject.getProjectUri(), projectDirectory.getName());
152173

153-
return osCommandOperations.executeCommand(command);
174+
return os.executeCommand(command);
154175
}
155176
}
156177

157178
public Tags getTags(Project project) throws Exception {
158179

159-
String result = osCommandOperations.executeForResult("git tag -l", project);
180+
String result = os.executeForResult("git tag -l", project);
160181
List<Tag> tags = new ArrayList<>();
161182

162183
for (String line : result.split("\n")) {
@@ -177,23 +198,82 @@ public void tagRelease(TrainIteration iteration) throws Exception {
177198
Project project = module.getProject();
178199

179200
String checkoutCommand = String.format("git checkout %s", branch);
180-
osCommandOperations.executeCommand(checkoutCommand, project).get();
201+
os.executeCommand(checkoutCommand, project).get();
181202

182203
String updateCommand = String.format("git pull origin %s", branch);
183-
osCommandOperations.executeCommand(updateCommand, project).get();
204+
os.executeCommand(updateCommand, project).get();
184205

185206
String hash = getReleaseHash(module);
186207
Tag tag = getTags(project).createTag(module);
187208
String tagCommand = String.format("git tag %s %s", tag, hash);
188-
osCommandOperations.executeCommand(tagCommand, project).get();
209+
os.executeCommand(tagCommand, project).get();
210+
}
211+
}
212+
213+
/**
214+
* Commits all changes currently made to all modules of the given {@link TrainIteration}. The summary can contain a
215+
* single {@code %s} placeholder which the version of the current module will get replace into.
216+
*
217+
* @param iteration must not be {@literal null}.
218+
* @param summary must not be {@literal null} or empty.
219+
* @param details can be {@literal null} or empty.
220+
* @throws Exception
221+
*/
222+
public void commit(TrainIteration iteration, String summary, String details) throws Exception {
223+
224+
Assert.notNull(iteration, "Train iteration must not be null!");
225+
Assert.hasText(summary, "Summary must not be null or empty!");
226+
227+
for (ModuleIteration module : iteration) {
228+
229+
if (summary.contains("%s")) {
230+
summary = String.format(summary, module.getVersionString());
231+
}
232+
233+
commit(module, summary, details);
234+
}
235+
}
236+
237+
/**
238+
* Commits the given files for the given {@link ModuleIteration} using the given summary and details for the commit
239+
* message. If no files are given, all pending changes are commited.
240+
*
241+
* @param module must not be {@literal null}.
242+
* @param summary must not be {@literal null} or empty.
243+
* @param details can be {@literal null} or empty.
244+
* @param files can be empty.
245+
* @throws Exception
246+
*/
247+
public void commit(ModuleIteration module, String summary, String details, File... files) throws Exception {
248+
249+
Assert.notNull(module, "Module iteration must not be null!");
250+
Assert.hasText(summary, "Summary must not be null or empty!");
251+
252+
Project project = module.getProject();
253+
IssueTracker tracker = issueTracker.getPluginFor(project);
254+
Ticket ticket = tracker.getReleaseTicketFor(module);
255+
256+
Commit commit = new Commit(ticket, summary, details);
257+
String author = environment.getProperty("git.author");
258+
String commitCommand = String.format("git commit -m \"%s\" --author \"%s\"", commit, author);
259+
260+
if (files.length != 0) {
261+
262+
for (File file : files) {
263+
os.executeCommand(String.format("git add %s", file.getAbsolutePath()), project).get();
264+
}
265+
266+
os.executeCommand(commitCommand, project).get();
267+
} else {
268+
os.executeCommand(commitCommand.concat(" -a"), project).get();
189269
}
190270
}
191271

192272
private String getReleaseHash(ModuleIteration module) throws Exception {
193273

194274
Project project = module.getProject();
195275

196-
String result = osCommandOperations.executeForResult("git log --pretty=format:'%h %s'", project);
276+
String result = os.executeForResult("git log --pretty=format:'%h %s'", project);
197277
Ticket releaseTicket = issueTracker.getPluginFor(project).getReleaseTicketFor(module);
198278
String trigger = String.format("%s - Release", releaseTicket.getId());
199279

src/main/java/org/springframework/data/release/misc/ReleaseOperations.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@
1515
*/
1616
package org.springframework.data.release.misc;
1717

18+
import java.io.File;
1819
import java.util.Collections;
1920
import java.util.HashSet;
2021
import java.util.Set;
2122

2223
import lombok.RequiredArgsConstructor;
2324

2425
import org.springframework.beans.factory.annotation.Autowired;
26+
import org.springframework.data.release.git.GitOperations;
2527
import org.springframework.data.release.io.Workspace;
2628
import org.springframework.data.release.io.Workspace.LineCallback;
2729
import org.springframework.data.release.jira.Changelog;
@@ -56,6 +58,7 @@ public class ReleaseOperations {
5658

5759
private final PluginRegistry<IssueTracker, Project> trackers;
5860
private final Workspace workspace;
61+
private final GitOperations git;
5962
private final Logger logger;
6063

6164
/**
@@ -94,6 +97,10 @@ public String doWith(String line, long number) {
9497
});
9598

9699
if (processed) {
100+
101+
File file = workspace.getFile(location, module.getProject());
102+
git.commit(module, "Updated changelog.", null, file);
103+
97104
logger.log(module.getProject(), "Updated changelog %s.", location);
98105
}
99106
}
@@ -104,20 +111,23 @@ public void updateResources(TrainIteration iteration) throws Exception {
104111

105112
for (final ModuleIteration module : iteration) {
106113

107-
workspace.processFile("src/main/resources/notice.txt", module.getProject(), new LineCallback() {
114+
boolean processed = workspace.processFile("src/main/resources/notice.txt", module.getProject(),
115+
new LineCallback() {
108116

109-
@Override
110-
public String doWith(String line, long number) {
117+
@Override
118+
public String doWith(String line, long number) {
111119

112-
if (number != 0) {
113-
return line;
114-
}
120+
if (number != 0) {
121+
return line;
122+
}
115123

116-
return module.toString();
117-
}
118-
});
124+
return module.toString();
125+
}
126+
});
119127

120-
logger.log(module, "Updated notice.txt.");
128+
if (processed) {
129+
logger.log(module, "Updated notice.txt.");
130+
}
121131
}
122132
}
123133
}

0 commit comments

Comments
 (0)