1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package com.jcabi.heroku.maven.plugin;
31
32 import com.jcabi.log.Logger;
33 import com.jcabi.velocity.VelocityPage;
34 import java.io.File;
35 import java.util.ArrayList;
36 import java.util.List;
37 import org.apache.maven.artifact.Artifact;
38 import org.apache.maven.artifact.DefaultArtifact;
39 import org.apache.maven.plugin.AbstractMojo;
40 import org.apache.maven.plugin.MojoFailureException;
41 import org.apache.maven.project.MavenProject;
42 import org.apache.maven.settings.Server;
43 import org.apache.maven.settings.Settings;
44 import org.jfrog.maven.annomojo.annotations.MojoGoal;
45 import org.jfrog.maven.annomojo.annotations.MojoParameter;
46 import org.jfrog.maven.annomojo.annotations.MojoPhase;
47 import org.slf4j.impl.StaticLoggerBinder;
48
49
50
51
52
53
54
55
56 @MojoGoal("deploy")
57 @MojoPhase("deploy")
58 public final class DeployMojo extends AbstractMojo {
59
60
61
62
63 @MojoParameter(
64 expression = "${project}",
65 required = true,
66 readonly = true,
67 description = "Maven project"
68 )
69 private transient MavenProject project;
70
71
72
73
74 @MojoParameter(
75 expression = "${settings}",
76 required = true,
77 readonly = true,
78 description = "Maven settings.xml reference"
79 )
80 private transient Settings settings;
81
82
83
84
85 @MojoParameter(
86 defaultValue = "false",
87 required = false,
88 description = "Skips execution"
89 )
90 private transient boolean skip;
91
92
93
94
95 @MojoParameter(
96 defaultValue = "heroku.com",
97 required = false,
98 description = "Server ID from settings.xml"
99 )
100 private transient String server;
101
102
103
104
105 @MojoParameter(
106 required = true,
107 description = "Heroku application name"
108 )
109 private transient String name;
110
111
112
113
114 @MojoParameter(
115 required = true,
116 description = "Content of Procfile"
117 )
118 private transient String procfile;
119
120
121
122
123 @MojoParameter(
124 required = true,
125 description = "Artifacts to download during deployment"
126 )
127 private transient String[] artifacts;
128
129
130
131
132
133 public void setSkip(final boolean skp) {
134 this.skip = skp;
135 }
136
137 @Override
138 @SuppressWarnings("PMD.PrematureDeclaration")
139 public void execute() throws MojoFailureException {
140 StaticLoggerBinder.getSingleton().setMavenLog(this.getLog());
141 if (this.skip) {
142 Logger.info(this, "execution skipped because of 'skip' option");
143 return;
144 }
145 final long start = System.currentTimeMillis();
146 final Heroku heroku = new Heroku(this.git(), this.name);
147 final Repo repo = heroku.clone(
148 new File(new File(this.project.getBuild().getDirectory()), "heroku")
149 );
150 try {
151 repo.add(
152 "settings.xml",
153 new VelocityPage(
154 "com/jcabi/heroku/maven/plugin/settings.xml.vm"
155 ).set("settings", this.settings).toString()
156 );
157 repo.add(
158 "pom.xml",
159 new VelocityPage(
160 "com/jcabi/heroku/maven/plugin/pom.xml.vm"
161 ).set("project", this.project)
162 .set("deps", this.deps())
163 .set("timestamp", System.currentTimeMillis())
164 .toString()
165 );
166 repo.add("Procfile", this.procfile.trim());
167 } catch (final java.io.IOException ex) {
168 throw new MojoFailureException("failed to save files", ex);
169 }
170 repo.commit();
171 Logger.info(this, "Done in %[ms]s", System.currentTimeMillis() - start);
172 }
173
174
175
176
177
178
179 private Git git() throws MojoFailureException {
180 final Server srv = this.settings.getServer(this.server);
181 if (srv == null) {
182 throw new MojoFailureException(
183 String.format(
184 "Server '%s' not found in settings.xml",
185 this.server
186 )
187 );
188 }
189 final String location = srv.getPrivateKey();
190 if (location == null || location.isEmpty()) {
191 throw new MojoFailureException(
192 String.format(
193 "privateKey is not defined for '%s' server in settings.xml",
194 srv.getId()
195 )
196 );
197 }
198 final File file = new File(location);
199 if (!file.exists()) {
200 throw new MojoFailureException(
201 String.format("SSH key file '%s' doesn't exist", file)
202 );
203 }
204 try {
205 return new Git(
206 file,
207 new File(this.project.getBuild().getDirectory())
208 );
209 } catch (final java.io.IOException ex) {
210 throw new MojoFailureException("failed to initialize git", ex);
211 }
212 }
213
214
215
216
217
218
219
220
221
222
223
224 @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
225 private List<Artifact> deps() throws MojoFailureException {
226 if (this.artifacts.length == 0) {
227 throw new MojoFailureException(
228 "At least one artifact should be configured"
229 );
230 }
231 final List<Artifact> deps = new ArrayList<Artifact>(
232 this.artifacts.length
233 );
234 for (final String coordinates : this.artifacts) {
235 final String[] parts = coordinates.split(":");
236
237 if (parts.length != 5) {
238 throw new MojoFailureException(
239 String.format(
240 "Maven artifact coordinates '%s' is not absolute",
241 coordinates
242 )
243 );
244 }
245 deps.add(
246
247 new DefaultArtifact(
248 parts[0],
249 parts[1],
250 parts[4],
251 "runtime",
252 parts[2],
253 parts[3],
254 null
255 )
256 );
257 }
258 return deps;
259 }
260
261 }