Skip to content

Commit f0290f4

Browse files
Merge pull request #12 from TechnologyBrewery/group_feature
Added Group migration functionality to Baton plugin
2 parents 952e03d + ec25096 commit f0290f4

File tree

15 files changed

+394
-202
lines changed

15 files changed

+394
-202
lines changed

README.md

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,22 @@ The following example configures the migration to only look in the `./src/main/r
5656
one file, `original-specification-example.foo` alone.
5757
```json
5858
[
59-
{
60-
"name": "upgrade-foo-extension-files-migration",
61-
"implementation": "org.technologybrewery.baton.example.FooToBarMigration",
62-
"fileSets": [
63-
{
64-
"includes": ["**/legacy/*.foo"],
65-
"excludes": ["original-specification-example.foo"]
66-
}
67-
]
68-
}
59+
{
60+
"group": "group-1",
61+
"migrations": [
62+
"name": "upgrade-foo-extension-files-migration",
63+
"implementation": "org.technologybrewery.baton.example.FooToBarMigration",
64+
"fileSets": [
65+
{
66+
"includes": ["**/legacy/*.foo"],
67+
"excludes": ["original-specification-example.foo"]
68+
}
69+
]
70+
]
71+
}
6972
]
7073
```
74+
Migration files contain groups of migrations. Each group is executed in its entirety before moving on to the next. Groups are executed in the order in which they appear in the migration file.
7175

7276
### Add `baton-maven-plugin` to your Maven build
7377
The last step is to add `baton-maven-plugin` to your Maven build process just like any other plugin.
@@ -206,7 +210,25 @@ Default: `10`
206210
When specifying your configurations in `migrations.json` or your custom `migrationsConfigurationFile` file name, the
207211
following options are available.
208212

209-
### name
213+
### Group Configurations
214+
215+
#### group
216+
The name of the group. Simply used to give a distinctive identifier to a group.
217+
218+
Required? `true`
219+
220+
Default: None
221+
222+
#### migrations
223+
List of all the migrations in a group. This must be a non-zero list of migrations.
224+
225+
Required? `true`
226+
227+
Default: None
228+
229+
### Migration Configurations
230+
231+
#### name
210232
The name of the migration to perform. As of 0.1.0, `name` is not particularly impactful. However, in subsequent
211233
releases it will gain importance as a means to order migration execution (convention-driven in the style of Flyway) as
212234
well as inactivate specific migrations.
@@ -215,14 +237,14 @@ Required? `true`
215237

216238
Default: None
217239

218-
### description
240+
#### description
219241
The description of the migration. This is intended to provide context on why the migration is needed.
220242

221243
Required? `false`
222244

223245
Default: None
224246

225-
### implementation
247+
#### implementation
226248
The fully qualified Java class name that will perform the migration. This **MUST** implement the
227249
`org.technologybrewery.baton.Migration` interface, however it is recommended that it extend
228250
`org.technologybrewery.baton.AbstractMigration` to allow implementations to be more consistent and focus on migration
@@ -232,7 +254,7 @@ Required? `true`
232254

233255
Default: None
234256

235-
### fileSet
257+
#### fileSet
236258
A Maven-inspired object that allows specification of common file sets. **MUST** be added as a list item.
237259

238260
Required? `false`

baton-maven-plugin/src/main/java/org/technologybrewery/baton/AbstractMigration.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
import com.vlkan.rfos.RotatingFileOutputStream;
44
import com.vlkan.rfos.RotationConfig;
55
import com.vlkan.rfos.policy.SizeBasedRotationPolicy;
6-
import org.apache.commons.collections4.CollectionUtils;
76
import org.apache.commons.io.FileUtils;
87
import org.apache.commons.lang3.StringUtils;
9-
import org.apache.maven.plugins.annotations.Parameter;
108
import org.apache.maven.project.MavenProject;
119
import org.apache.maven.shared.model.fileset.FileSet;
1210
import org.apache.maven.shared.model.fileset.util.FileSetManager;
Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.technologybrewery.baton;
22

3+
import java.util.ArrayList;
4+
import java.util.List;
35
import org.slf4j.Logger;
46
import org.slf4j.LoggerFactory;
57

@@ -10,49 +12,49 @@ public class BatonExecutionSummary {
1012

1113
private static final Logger logger = LoggerFactory.getLogger(BatonExecutionSummary.class);
1214

13-
private int filesSuccessfullyMigrated;
14-
15-
private int filesUnsuccessfullyMigrated;
16-
17-
private int numberOfTargetsExecuted;
15+
private List<GroupSummary> groupSummaries = new ArrayList<>();
1816

1917
/**
2018
* Adds a specific migration summary run to the cross-migration summary..
2119
*
2220
* @param summary summary to add
2321
*/
24-
public void addMigrationSummary(MigrationSummary summary) {
22+
public void addGroupSummary(GroupSummary summary) {
2523
if (summary == null) {
2624
logger.warn("Mission migration summary details - file counts may be inaccurate!");
2725
} else {
28-
filesSuccessfullyMigrated += summary.getFilesSuccessfullyMigrated();
29-
filesUnsuccessfullyMigrated += summary.getFilesUnsuccessfullyMigrated();
26+
groupSummaries.add(summary);
3027
}
31-
32-
numberOfTargetsExecuted++;
33-
34-
}
35-
36-
public int getFilesSuccessfullyMigrated() {
37-
return filesSuccessfullyMigrated;
38-
}
39-
40-
public int getFilesUnsuccessfullyMigrated() {
41-
return filesUnsuccessfullyMigrated;
4228
}
4329

4430
public int getNumberOfTargetsExecuted() {
31+
int numberOfTargetsExecuted = 0;
32+
for(GroupSummary groupSummary : groupSummaries) {
33+
numberOfTargetsExecuted += groupSummary.getMigrationSummaries().size();
34+
}
4535
return numberOfTargetsExecuted;
4636
}
4737

38+
public List<GroupSummary> getGroupSummaries() {
39+
return this.groupSummaries;
40+
}
41+
4842
/**
4943
* Human-readable summary information.
5044
*
5145
* @return the summary as a readable string
5246
*/
5347
public String getSummary() {
48+
int filesSuccess = 0;
49+
int filesUnsuccess = 0;
50+
for(GroupSummary groupSummary : groupSummaries) {
51+
for(MigrationSummary migrationSummary : groupSummary.getMigrationSummaries()) {
52+
filesSuccess += migrationSummary.getFilesSuccessfullyMigrated();
53+
filesUnsuccess += migrationSummary.getFilesUnsuccessfullyMigrated();
54+
}
55+
}
5456
return String.format("Migrations Processed: %d, Successfully Migrated Files: %d, Unsuccessfully Migrated Files: %d",
55-
numberOfTargetsExecuted, filesSuccessfullyMigrated, filesUnsuccessfullyMigrated);
57+
getNumberOfTargetsExecuted(), filesSuccess, filesUnsuccess);
5658
}
5759

5860
}

baton-maven-plugin/src/main/java/org/technologybrewery/baton/BatonMojo.java

Lines changed: 31 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.apache.maven.plugins.annotations.ResolutionScope;
1313
import org.apache.maven.project.MavenProject;
1414
import org.apache.maven.shared.model.fileset.FileSet;
15+
import org.technologybrewery.baton.config.GroupTarget;
1516
import org.technologybrewery.baton.config.MigrationTarget;
1617
import org.technologybrewery.commons.json.AbstractValidatedElement;
1718
import org.technologybrewery.commons.json.ValidatedElement;
@@ -26,9 +27,7 @@
2627
import java.util.ArrayList;
2728
import java.util.Collection;
2829
import java.util.Enumeration;
29-
import java.util.HashMap;
3030
import java.util.List;
31-
import java.util.Map;
3231
import java.util.Set;
3332

3433
/**
@@ -109,13 +108,13 @@ public class BatonMojo extends AbstractMojo {
109108

110109
private final ObjectMapper objectMapper = initializeObjectMapper();
111110

112-
private Map<String, MigrationTarget> migrations = new HashMap<>();
111+
private List<GroupTarget> groups = new ArrayList<>();
113112

114113
protected ObjectMapper initializeObjectMapper() {
115114
ObjectMapper localObjectMapper = new ObjectMapper();
116115

117116
SimpleModule module = new SimpleModule();
118-
module.addAbstractTypeMapping(ValidatedElement.class, MigrationTarget.class);
117+
module.addAbstractTypeMapping(ValidatedElement.class, GroupTarget.class);
119118

120119
localObjectMapper.registerModule(module);
121120

@@ -161,36 +160,39 @@ public void execute() throws MojoExecutionException, MojoFailureException {
161160

162161
defaultFileSets();
163162

164-
BatonExecutionSummary summary = performMigration(migrations.values());
163+
BatonExecutionSummary summary = performMigration(groups);
165164
getLog().info(summary.getSummary());
166165

167166
}
168167

169-
BatonExecutionSummary performMigration(Collection<MigrationTarget> targets) {
168+
BatonExecutionSummary performMigration(Collection<GroupTarget> groupTargets) {
170169
BatonExecutionSummary executionSummary = new BatonExecutionSummary();
171-
for (MigrationTarget target : targets) {
172-
if (isActive(target)) {
173-
try {
174-
getLog().debug(String.format("Executing Migration: %s (%s)", target.getName(), target.getImplementation()));
175-
Class<Migration> implementationClass = (Class<Migration>) Class.forName(target.getImplementation());
176-
Constructor<Migration> constructor = implementationClass.getConstructor();
177-
Migration migration = constructor.newInstance();
178-
migration.setName(target.getName());
179-
migration.setDescription(target.getDescription());
180-
migration.setMavenProject(project);
181-
migration.setBackupMigratedOriginalFiles(backupOriginalMigratedFiles);
182-
migration.setBackupCustomLocation(backupCustomLocation);
183-
migration.setNumberOfBacksUpsToKeep(numberOfBackupsToKeep);
184-
FileSet[] migrationSpecificFileSets = (CollectionUtils.isNotEmpty(target.getFileSets())) ? getFileSetsForTarget(target) : fileSets;
185-
MigrationSummary migrationSummary = migration.execute(migrationSpecificFileSets);
186-
executionSummary.addMigrationSummary(migrationSummary);
187-
188-
} catch (Exception e) {
189-
throw new BatonException("Could not complete migrations!", e);
170+
for(GroupTarget groupTarget : groupTargets) {
171+
GroupSummary groupSummary = new GroupSummary(groupTarget.getGroup());
172+
for (MigrationTarget migrationTarget : groupTarget.getMigrations()) {
173+
if (isActive(migrationTarget)) {
174+
try {
175+
getLog().debug(String.format("Executing Migration: %s (%s)", migrationTarget.getName(), migrationTarget.getImplementation()));
176+
Class<Migration> implementationClass = (Class<Migration>) Class.forName(migrationTarget.getImplementation());
177+
Constructor<Migration> constructor = implementationClass.getConstructor();
178+
Migration migration = constructor.newInstance();
179+
migration.setName(migrationTarget.getName());
180+
migration.setDescription(migrationTarget.getDescription());
181+
migration.setMavenProject(project);
182+
migration.setBackupMigratedOriginalFiles(backupOriginalMigratedFiles);
183+
migration.setBackupCustomLocation(backupCustomLocation);
184+
migration.setNumberOfBacksUpsToKeep(numberOfBackupsToKeep);
185+
FileSet[] migrationSpecificFileSets = (CollectionUtils.isNotEmpty(migrationTarget.getFileSets())) ? getFileSetsForTarget(migrationTarget) : fileSets;
186+
MigrationSummary migrationSummary = migration.execute(migrationSpecificFileSets);
187+
groupSummary.addMigrationSummary(migrationSummary);
188+
189+
} catch (Exception e) {
190+
throw new BatonException("Could not complete migrations!", e);
191+
}
190192
}
191193
}
194+
executionSummary.addGroupSummary(groupSummary);
192195
}
193-
194196
return executionSummary;
195197
}
196198

@@ -230,37 +232,17 @@ protected void loadMigrations() {
230232
migrationsStream,
231233
tempMigrationsFile.toPath(),
232234
StandardCopyOption.REPLACE_EXISTING);
233-
migrations = loadMigrationsJson(tempMigrationsFile, migrations);
235+
List<GroupTarget> groupTargets = AbstractValidatedElement.readAndValidateJsonList(tempMigrationsFile,objectMapper, GroupTarget.class);
236+
groups.addAll(groupTargets);
234237

235-
getLog().info(String.format("Found %d migrations", migrations.size()));
238+
getLog().info(String.format("Found %d migrations", groups.size()));
236239
} catch (IOException e) {
237240
throw new BatonException("Unable to parse " + migrationsFileName, e);
238241
}
239242
}
240243

241244
}
242245

243-
/**
244-
* Loads all {@link MigrationTarget}s contained within the given {@link InputStream}, which is expected to
245-
* reference the desired migrations.json file to load.
246-
*
247-
* @param migrationsFile {@link File} referencing migrations.json file desired to load.
248-
* @param migrationTargets the migration targets already loaded to this point
249-
* @return {@link Map} containing all loaded {@link MigrationTarget}s with their corresponding name as the map key.
250-
*/
251-
protected Map<String, MigrationTarget> loadMigrationsJson(File migrationsFile,
252-
Map<String, MigrationTarget> migrationTargets) {
253-
254-
List<MigrationTarget> loadedMigrations = AbstractValidatedElement.readAndValidateJsonList(migrationsFile,
255-
objectMapper, MigrationTarget.class);
256-
257-
for (MigrationTarget migrationTarget : loadedMigrations) {
258-
migrationTargets.put(migrationTarget.getName(), migrationTarget);
259-
}
260-
261-
return migrationTargets;
262-
}
263-
264246
protected FileSet[] getFileSetsForTarget(MigrationTarget target) {
265247
List<FileSet> localFileSets = new ArrayList<>();
266248
for (org.technologybrewery.baton.config.FileSet targetFileSet : target.getFileSets()) {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.technologybrewery.baton;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
* High level summarization information for a specific Group.
8+
*/
9+
public class GroupSummary {
10+
11+
private String groupName;
12+
13+
private List<MigrationSummary> migrationSummaries;
14+
15+
public GroupSummary(String groupName) {
16+
this.groupName = groupName;
17+
migrationSummaries = new ArrayList<>();
18+
}
19+
20+
/**
21+
* Adds a migration summary to the group summary
22+
* @param migrationSummary
23+
*/
24+
public void addMigrationSummary(MigrationSummary migrationSummary) {
25+
migrationSummaries.add(migrationSummary);
26+
}
27+
28+
public List<MigrationSummary> getMigrationSummaries() {
29+
return this.migrationSummaries;
30+
}
31+
32+
public String getGroupName() {
33+
return this.groupName;
34+
}
35+
36+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package org.technologybrewery.baton.config;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
import org.technologybrewery.commons.json.AbstractValidatedElement;
7+
8+
import com.fasterxml.jackson.annotation.JsonIgnore;
9+
import com.fasterxml.jackson.annotation.JsonInclude;
10+
import com.fasterxml.jackson.annotation.JsonProperty;
11+
12+
/**
13+
* Holds target information to support group execution.
14+
*/
15+
public class GroupTarget extends AbstractValidatedElement {
16+
17+
@JsonProperty(required = true)
18+
private String group;
19+
20+
@JsonProperty(required = true)
21+
@JsonInclude(JsonInclude.Include.NON_EMPTY)
22+
private List<MigrationTarget> migrations = new ArrayList<>();
23+
24+
public GroupTarget(){}
25+
26+
public void setGroup(String group) {
27+
this.group = group;
28+
}
29+
30+
public String getGroup() {
31+
return this.group;
32+
}
33+
34+
@JsonIgnore
35+
public void addMigration(MigrationTarget migration) {
36+
this.migrations.add(migration);
37+
}
38+
39+
public List<MigrationTarget> getMigrations() {
40+
return this.migrations;
41+
}
42+
43+
@Override
44+
public String getSchemaFileName() {
45+
return "migration-target-schema.json";
46+
}
47+
48+
}

0 commit comments

Comments
 (0)