1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package br.com.ingenieux.mojo.beanstalk.bundle;
18
19 import com.amazonaws.services.elasticbeanstalk.model.ApplicationVersionDescription;
20 import com.amazonaws.services.elasticbeanstalk.model.DescribeApplicationVersionsRequest;
21 import com.amazonaws.services.elasticbeanstalk.model.DescribeApplicationVersionsResult;
22
23 import org.apache.maven.plugins.annotations.Mojo;
24 import org.apache.maven.plugins.annotations.Parameter;
25 import org.apache.maven.project.MavenProject;
26 import org.eclipse.jgit.api.AddCommand;
27 import org.eclipse.jgit.api.Git;
28 import org.eclipse.jgit.api.PushCommand;
29 import org.eclipse.jgit.api.Status;
30 import org.eclipse.jgit.lib.ObjectId;
31 import org.eclipse.jgit.lib.Ref;
32 import org.eclipse.jgit.lib.Repository;
33 import org.eclipse.jgit.lib.RepositoryBuilder;
34 import org.eclipse.jgit.lib.TextProgressMonitor;
35 import org.eclipse.jgit.transport.PushResult;
36 import org.eclipse.jgit.transport.RefSpec;
37
38 import java.io.File;
39 import java.util.Date;
40
41 import br.com.ingenieux.mojo.beanstalk.AbstractNeedsEnvironmentMojo;
42
43 import static java.lang.String.format;
44
45
46
47
48
49
50 @Mojo(name = "fast-deploy")
51 public class FastDeployMojo extends AbstractNeedsEnvironmentMojo {
52
53
54
55
56 @Parameter(defaultValue = "${project.build.directory}/${project.build.finalName}")
57 File sourceDirectory;
58
59
60
61
62 @Parameter(property = "beanstalk.stagingDirectory", defaultValue = "${project.basedir}/tmp-git-deployment-staging")
63 File stagingDirectory;
64
65
66
67
68 @Parameter(property = "beanstalk.useStagingDirectory", defaultValue = "false")
69 boolean useStagingDirectory = false;
70
71 @Parameter(defaultValue = "${project}")
72 MavenProject project;
73
74
75
76
77 @Parameter(property = "beanstalk.versionDescription", defaultValue = "Update from fast-deploy")
78 String versionDescription;
79
80
81
82
83 @Parameter(property = "beanstalk.skipEnvironmentUpdate", defaultValue = "false")
84 boolean skipEnvironmentUpdate = false;
85
86
87
88
89 @Parameter(property = "beanstalk.silentUpload", defaultValue = "false")
90 boolean silentUpload = false;
91
92 @Override
93 protected void configure() {
94 try {
95 super.configure();
96 } catch (Exception exc) {
97
98 }
99 }
100
101 @Override
102 protected Object executeInternal() throws Exception {
103 Git git = getGitRepo();
104 String versionLabel = null;
105
106 String commitId = null;
107
108 Ref masterRef = git.getRepository().getRef("master");
109 if (null != masterRef) {
110 commitId = ObjectId.toString(masterRef.getObjectId());
111 }
112
113 Status status = git.status().call();
114
115 boolean pushAhead = false;
116
117 if (null != commitId && status.isClean()) {
118 versionLabel = lookupVersionLabelForCommitId(commitId);
119
120 if (null == versionLabel) {
121 getLog().info("No Changes. However, we've didn't get something close in AWS Elastic Beanstalk and we're pushing ahead");
122 pushAhead = true;
123 } else {
124 getLog().info("No Changes. However, we've got something close in AWS Elastic Beanstalk and we're continuing");
125
126 project.getProperties().put("beanstalk.versionLabel", versionLabel);
127
128 return null;
129 }
130 }
131
132 if (!pushAhead) {
133
134 git.add().setUpdate(true).addFilepattern(".").call();
135
136
137
138 AddCommand addCommand = git.add();
139
140 if (!status.getUntracked().isEmpty()) {
141 for (String s : status.getUntracked()) {
142 getLog().info("Adding file " + s);
143 addCommand.addFilepattern(s);
144 }
145
146 addCommand.call();
147 }
148
149 git.commit().setAll(true).setMessage(versionDescription).call();
150
151 masterRef = git.getRepository().getRef("master");
152
153 commitId = ObjectId.toString(masterRef.getObjectId());
154 }
155
156 String environmentName = null;
157
158
159
160
161 if (null != curEnv && !skipEnvironmentUpdate) {
162 environmentName = curEnv.getEnvironmentName();
163 }
164
165 String remote = getRemoteUrl(commitId, environmentName);
166
167 getLog().info("Using remote: " + remote);
168
169
170
171
172 {
173 PushCommand cmd =
174 git.
175 push();
176
177 if (!silentUpload) {
178 cmd.setProgressMonitor(new TextProgressMonitor());
179 }
180
181 Iterable<PushResult> pushResults = null;
182 try {
183 pushResults =
184 cmd.setRefSpecs(new RefSpec("HEAD:refs/heads/master"))
185 .
186 setForce(true)
187 .
188 setRemote(remote)
189 .
190 call();
191 } catch (Exception exc) {
192
193 getLog().debug("(Actually Expected) Exception", exc);
194 }
195
196
197
198
199 if (null != pushResults) {
200 for (PushResult pushResult : pushResults) {
201 getLog().debug(" * " + pushResult.getMessages());
202 }
203 }
204 }
205
206 versionLabel = lookupVersionLabelForCommitId(commitId);
207
208 if (null != versionLabel) {
209 getLog().info("Deployed version " + versionLabel);
210
211 project.getProperties().put("beanstalk.versionLabel", versionLabel);
212 } else {
213 getLog().warn("No version found. Ignoring.");
214 }
215
216 return null;
217 }
218
219 protected String getRemoteUrl(String commitId, String environmentName) throws org.apache.maven.plugin.MojoFailureException {
220 return new RequestSigner(getAWSCredentials(), applicationName, regionName, commitId, environmentName, new Date()).getPushUrl();
221 }
222
223 protected String lookupVersionLabelForCommitId(String commitId) throws Exception {
224 String versionLabel = null;
225 String prefixToLookup = format("git-%s-", commitId);
226
227 DescribeApplicationVersionsResult describeApplicationVersions =
228 getService().describeApplicationVersions(new DescribeApplicationVersionsRequest().withApplicationName(applicationName));
229
230 for (ApplicationVersionDescription avd : describeApplicationVersions.getApplicationVersions()) {
231 if (avd.getVersionLabel().startsWith(prefixToLookup)) {
232 versionLabel = avd.getVersionLabel();
233 break;
234 }
235 }
236
237 return versionLabel;
238 }
239
240 protected Git getGitRepo() throws Exception {
241 Git git = null;
242
243 if (!useStagingDirectory) {
244 File gitRepo = new File(sourceDirectory, ".git");
245
246 if (!gitRepo.exists()) {
247 git = Git.init().setDirectory(sourceDirectory).call();
248 } else {
249 git = Git.open(gitRepo);
250 }
251 } else {
252 File gitRepo = stagingDirectory;
253 Repository r = null;
254
255 RepositoryBuilder b = new RepositoryBuilder().setGitDir(stagingDirectory).setWorkTree(sourceDirectory);
256
257 if (!gitRepo.exists()) {
258 gitRepo.getParentFile().mkdirs();
259
260 r = b.build();
261
262 r.create();
263 } else {
264 r = b.build();
265 }
266
267 git = Git.wrap(r);
268 }
269
270 return git;
271 }
272 }