11/*
22 * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3- *
3+ *
44 * Licensed under the Apache License, Version 2.0 (the "License").
55 * You may not use this file except in compliance with the License.
66 * A copy of the License is located at
7- *
7+ *
88 * http://aws.amazon.com/apache2.0
9- *
9+ *
1010 * or in the "license" file accompanying this file. This file is distributed
1111 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
1212 * express or implied. See the License for the specific language governing
@@ -91,6 +91,7 @@ public class AWSCodeDeployPublisher extends Publisher {
9191 private final String region ;
9292 private final String includes ;
9393 private final String excludes ;
94+ private final String subdirectory ;
9495 private final String proxyHost ;
9596 private final int proxyPort ;
9697
@@ -118,7 +119,8 @@ public AWSCodeDeployPublisher(
118119 String includes ,
119120 String proxyHost ,
120121 int proxyPort ,
121- String excludes ) {
122+ String excludes ,
123+ String subdirectory ) {
122124
123125 this .externalId = externalId ;
124126 this .applicationName = applicationName ;
@@ -127,6 +129,7 @@ public AWSCodeDeployPublisher(
127129 this .region = region ;
128130 this .includes = includes ;
129131 this .excludes = excludes ;
132+ this .subdirectory = subdirectory ;
130133 this .proxyHost = proxyHost ;
131134 this .proxyPort = proxyPort ;
132135 this .credentials = credentials ;
@@ -178,8 +181,8 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListener lis
178181 if ("awsAccessKey" .equals (credentials )) {
179182 if (StringUtils .isEmpty (this .awsAccessKey ) && StringUtils .isEmpty (this .awsSecretKey )) {
180183 aws = AWSClients .fromDefaultCredentialChain (
181- this .region ,
182- this .proxyHost ,
184+ this .region ,
185+ this .proxyHost ,
183186 this .proxyPort );
184187 } else {
185188 aws = AWSClients .fromBasicCredentials (
@@ -205,7 +208,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListener lis
205208 verifyCodeDeployApplication (aws );
206209
207210 String projectName = build .getProject ().getName ();
208- RevisionLocation revisionLocation = zipAndUpload (aws , projectName , build .getWorkspace ());
211+ RevisionLocation revisionLocation = zipAndUpload (aws , projectName , getSourceDirectory ( build .getWorkspace () ));
209212
210213 registerRevision (aws , revisionLocation );
211214 String deploymentId = createDeployment (aws , revisionLocation );
@@ -224,6 +227,30 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListener lis
224227 return success ;
225228 }
226229
230+ private FilePath getSourceDirectory (FilePath basePath ) throws IOException , InterruptedException {
231+ String subdirectory = this .subdirectory .trim ().length () > 0 ? this .subdirectory .trim () : "" ;
232+ if (!subdirectory .isEmpty () && !subdirectory .startsWith ("/" )) {
233+ subdirectory = "/" + subdirectory ;
234+ }
235+ FilePath sourcePath = basePath .withSuffix (subdirectory ).absolutize ();
236+ File sourceDirectory = new File (sourcePath .getRemote ());
237+ if (!sourceDirectory .isDirectory () || !isSubDirectory (basePath , sourcePath )) {
238+ throw new IllegalArgumentException ("Provided path is not a subdirectory of the workspace: " + sourcePath );
239+ }
240+ return sourcePath ;
241+ }
242+
243+ private boolean isSubDirectory (FilePath parent , FilePath child ) {
244+ FilePath parentFolder = child ;
245+ while (parentFolder !=null ) {
246+ if (parent .equals (parentFolder )) {
247+ return true ;
248+ }
249+ parentFolder = child .getParent ();
250+ }
251+ return false ;
252+ }
253+
227254 private void verifyCodeDeployApplication (AWSClients aws ) throws IllegalArgumentException {
228255 // Check that the application exists
229256 ListApplicationsResult applications = aws .codedeploy .listApplications ();
@@ -243,15 +270,15 @@ private void verifyCodeDeployApplication(AWSClients aws) throws IllegalArgumentE
243270 }
244271 }
245272
246- private RevisionLocation zipAndUpload (AWSClients aws , String projectName , FilePath workspace ) throws IOException , InterruptedException {
247-
273+ private RevisionLocation zipAndUpload (AWSClients aws , String projectName , FilePath sourceDirectory ) throws IOException , InterruptedException {
274+
248275 File zipFile = File .createTempFile (projectName + "-" , ".zip" );
249276 String key ;
250-
277+
251278 try {
279+ this .logger .println ("Zipping files into " + zipFile .getAbsolutePath ());
252280
253- this .logger .println ("Zipping workspace into " + zipFile .getAbsolutePath ());
254- workspace .zip (
281+ sourceDirectory .zip (
255282 new FileOutputStream (zipFile ),
256283 new DirScanner .Glob (this .includes , this .excludes )
257284 );
@@ -418,7 +445,7 @@ public FormValidation doCheckName(@QueryParameter String value)
418445 }
419446
420447 public boolean isApplicable (Class <? extends AbstractProject > aClass ) {
421- // Indicates that this builder can be used with all kinds of project types
448+ // Indicates that this builder can be used with all kinds of project types
422449 return true ;
423450 }
424451
@@ -588,6 +615,10 @@ public String getExcludes() {
588615 return excludes ;
589616 }
590617
618+ public String getSubdirectory () {
619+ return subdirectory ;
620+ }
621+
591622 public String getRegion () {
592623 return region ;
593624 }
0 commit comments