├── .gitignore ├── README ├── LICENSE ├── src └── main │ ├── resources │ ├── index.jelly │ └── org │ │ └── jenkins │ │ └── plugins │ │ └── appaloosa │ │ ├── AppaloosaPublisher │ │ ├── help-token.html │ │ ├── help-filePattern.html │ │ ├── help-changelog.html │ │ ├── help-description.html │ │ ├── help-groups.html │ │ └── config.jelly │ │ └── Messages.properties │ └── java │ └── org │ └── jenkins │ └── plugins │ └── appaloosa │ ├── AppaloosaBuildAction.java │ ├── FileFinder.java │ ├── AppaloosaRunListener.java │ └── AppaloosaPublisher.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *iml 3 | .project 4 | .classpath 5 | .settings 6 | target 7 | work 8 | .DS_Store 9 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Publish your mobile applications (Android, iOS, ...) to the http://www.appaloosa-store.com platform. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2011 Arnaud Héritier 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 28 |
29 | Publish your mobile applications (Android, iOS, ...) to the appaloosa-store platform. 30 |
31 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkins/plugins/appaloosa/AppaloosaPublisher/help-token.html: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 | Appaloosa token dedicated for your store. You'll find it in your store settings. 27 | More help on appaloosa plugin wiki 28 |
29 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkins/plugins/appaloosa/AppaloosaPublisher/help-filePattern.html: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 | Can use wildcards like 'module/dist/**/*.zip'. 27 | See 28 | the @includes of Ant fileset for the exact format. 29 | The base directory is the workspace. 30 |
-------------------------------------------------------------------------------- /src/main/resources/org/jenkins/plugins/appaloosa/AppaloosaPublisher/help-changelog.html: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 |

New changelog of this version. This can be either a file path or a string. Optional.

27 | See available environment variables here.
28 |

29 | Example:
30 | File Path:
31 | - path/to/my/changelog.txt
32 | Content:
33 | - Added logout button in profile view. 34 |

35 |
-------------------------------------------------------------------------------- /src/main/resources/org/jenkins/plugins/appaloosa/AppaloosaPublisher/help-description.html: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 |

New description of this version. This can be either a file path or a string. Leave this field blank if you want to use the previous description.

27 | See available environment variables here.
28 |

29 | Example:
30 | File Path:
31 | - path/to/my/description.txt
32 | Content:
33 | - $GIT_COMMIT 34 |

35 |
-------------------------------------------------------------------------------- /src/main/java/org/jenkins/plugins/appaloosa/AppaloosaBuildAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2011 eXo platform 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkins.plugins.appaloosa; 26 | 27 | import hudson.model.Action; 28 | import hudson.model.ProminentProjectAction; 29 | 30 | public class AppaloosaBuildAction implements ProminentProjectAction { 31 | public String iconFileName; 32 | public String displayName; 33 | public String urlName; 34 | 35 | public AppaloosaBuildAction() { 36 | } 37 | 38 | public AppaloosaBuildAction(Action action) { 39 | iconFileName = action.getIconFileName(); 40 | displayName = action.getDisplayName(); 41 | urlName = action.getUrlName(); 42 | } 43 | 44 | public String getIconFileName() { 45 | return iconFileName; 46 | } 47 | 48 | public String getDisplayName() { 49 | return displayName; 50 | } 51 | 52 | public String getUrlName() { 53 | return urlName; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkins/plugins/appaloosa/AppaloosaPublisher/help-groups.html: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 |

Names of the groups, separated by "|" that will allowed to see this version. 27 | Example: "Group 1 | Group 2". 28 | When empty the update will be publish to previous allowed groups if a previous update exists, 29 | otherwise it will be published to default group "everybody". 30 | You can also specify to publish your file to the default group "everybody", you have to use the name "everybody" (even if your store is in French). 31 |

32 | See available environment variables here.
33 |

34 | Example:
35 | File Path:
36 | - path/to/my/groups.txt
37 | Content:
38 | - Group 1 | Group 2 39 |

40 |
-------------------------------------------------------------------------------- /src/main/resources/org/jenkins/plugins/appaloosa/Messages.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2011 eXo platform 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | AppaloosaPublisher.noToken = No Appaloosa token defined in your project configuration. 26 | AppaloosaPublisher.noFilePattern = No Appaloosa file pattern defined in your project configuration. 27 | AppaloosaPublisher.noArtifactsFound = Could not find the file specified by the pattern {0} 28 | AppaloosaPublisher.deploying=Deploying archive {0} to Appaloosa (description="{1}", groups="{2}", changelog="{3}) 29 | AppaloosaPublisher.deployed=Deployment to Appaloosa Done. 30 | AppaloosaPublisher.foundFiles=found remote files : {0} 31 | AppaloosaPublisher.deploymentFailed=Deployment failed : {0} 32 | AppaloosaPublisher.buildWorkspaceUnavailable=Build workspace unavailable. 33 | AppaloosaPublisher.uploadToAppaloosa=Upload to Appaloosa 34 | AppaloosaPublisher.proxyHost=Proxy Host 35 | AppaloosaPublisher.proxyPort=Proxy Port 36 | AppaloosaPublisher.proxyUser=Proxy User 37 | AppaloosaPublisher.proxyPass=Proxy Pass 38 | AppaloosaPublisher.RootDirectory=Root directory to find files to upload : {0} 39 | AppaloosaRunListener.AppaloosaInPromotion=There is an appaloosa step in a promotion, we need to archive artifacts ({0}) to deploy them later. 40 | AppaloosaRunListener.BackupError=Error while backing up 41 | AppaloosaPublisher.description=Description 42 | AppaloosaPublisher.changelog=Changelog 43 | AppaloosaPublisher.groups=Groups 44 | -------------------------------------------------------------------------------- /src/main/java/org/jenkins/plugins/appaloosa/FileFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2011 eXo platform 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package org.jenkins.plugins.appaloosa; 25 | 26 | import hudson.FilePath; 27 | import hudson.remoting.VirtualChannel; 28 | import org.apache.tools.ant.BuildException; 29 | import org.apache.tools.ant.Project; 30 | import org.apache.tools.ant.types.FileSet; 31 | 32 | import java.io.File; 33 | import java.io.IOException; 34 | import java.util.Arrays; 35 | import java.util.Collections; 36 | import java.util.List; 37 | 38 | public class FileFinder implements FilePath.FileCallable> { 39 | 40 | private final String pattern; 41 | 42 | public FileFinder(final String pattern) { 43 | this.pattern = pattern; 44 | } 45 | 46 | public List invoke(File directory, VirtualChannel channel) throws IOException, InterruptedException { 47 | return find(directory); 48 | } 49 | 50 | public List find(final File directory) { 51 | try { 52 | FileSet fileSet = new FileSet(); 53 | Project antProject = new Project(); 54 | fileSet.setProject(antProject); 55 | fileSet.setDir(directory); 56 | fileSet.setIncludes(pattern); 57 | 58 | String[] files = fileSet.getDirectoryScanner(antProject).getIncludedFiles(); 59 | return files == null ? Collections.emptyList() : Arrays.asList(files); 60 | } 61 | catch (BuildException exception) { 62 | return Collections.emptyList(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkins/plugins/appaloosa/AppaloosaPublisher/config.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 27 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/org/jenkins/plugins/appaloosa/AppaloosaRunListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2012 eXo platform 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkins.plugins.appaloosa; 26 | 27 | import java.io.IOException; 28 | 29 | import hudson.Extension; 30 | import hudson.model.AbstractBuild; 31 | import hudson.model.BuildListener; 32 | import hudson.model.JobProperty; 33 | import hudson.model.TaskListener; 34 | import hudson.model.listeners.RunListener; 35 | import hudson.plugins.promoted_builds.JobPropertyImpl; 36 | import hudson.plugins.promoted_builds.PromotedProjectAction; 37 | import hudson.plugins.promoted_builds.PromotionProcess; 38 | import hudson.tasks.ArtifactArchiver; 39 | import hudson.tasks.BuildStep; 40 | 41 | /** 42 | * @author Arnaud Héritier 43 | */ 44 | @Extension(optional = true) 45 | public class AppaloosaRunListener extends RunListener { 46 | 47 | public void onCompleted(AbstractBuild r, TaskListener listener) { 48 | // Searching for the promotion plugin 49 | if (r.getProject().getProperty(JobPropertyImpl.class) != null) { 50 | JobProperty promotionJobProperty = r.getProject().getProperty(JobPropertyImpl.class); 51 | // Search in promotions if one of them is using Appaloosa 52 | for (PromotionProcess process : ((PromotedProjectAction) promotionJobProperty.getProjectAction(r.getProject())).getProcesses()) { 53 | // Search for a build step using Appaloosa 54 | for (BuildStep buildStep : process.getBuildSteps()) { 55 | if (buildStep instanceof AppaloosaPublisher) { 56 | listener.getLogger().println(Messages.AppaloosaRunListener_AppaloosaInPromotion(((AppaloosaPublisher) buildStep).filePattern)); 57 | // If appaloosa is activated in a promotion it may be needed to deploy binaries that 58 | // aren't the latest in the workspace. 59 | // Thus we will silently archive required artifacts to use them. 60 | try { 61 | // TODO : Do we need avoid to archive something already done by the job itself ? 62 | // It is from POV complex to check if all artifacts deployed by appaloosa are 63 | // saved by the archiver 64 | //if (r.getProject().getPublishersList().get(ArtifactArchiver.class) == null) { 65 | //} 66 | new ArtifactArchiver(((AppaloosaPublisher) buildStep).filePattern, null, true).perform(r, null, (BuildListener) listener); 67 | } catch (InterruptedException e) { 68 | listener.error(Messages.AppaloosaRunListener_BackupError(), e); 69 | } catch (IOException e) { 70 | // TODO Auto-generated catch block 71 | listener.error(Messages.AppaloosaRunListener_BackupError(), e); 72 | } 73 | } 74 | } 75 | } 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | 20 | org.jenkins-ci.plugins 21 | plugin 22 | 1.580 23 | 24 | 25 | 26 | appaloosa-plugin 27 | 1.4.13-SNAPSHOT 28 | hpi 29 | Appaloosa Plugin 30 | Publish your mobile applications (Android, iOS, ...) to the <a href="https://www.appaloosa-store.com">appaloosa-store</a> platform. 31 | http://wiki.jenkins-ci.org/display/JENKINS/Appaloosa+Plugin 32 | 33 | 34 | MIT 35 | LICENSE.txt 36 | repo 37 | 38 | 39 | 40 | 41 | aheritier 42 | Arnaud Heritier 43 | aheritier@apache.org 44 | 45 | 46 | joel1di1 47 | Benoit Lafontaine 48 | joel1di1@gmail.com 49 | 50 | 51 | rsfez 52 | Robin Sfez 53 | rsfez@octo.com 54 | 55 | 56 | 57 | scm:git:ssh://github.com/jenkinsci/appaloosa-plugin.git 58 | scm:git:ssh://git@github.com/jenkinsci/appaloosa-plugin.git 59 | https://github.com/jenkinsci/appaloosa-plugin 60 | appaloosa-plugin-1.4.4 61 | 62 | 63 | 64 | repo.jenkins-ci.org 65 | https://repo.jenkins-ci.org/public/ 66 | 67 | 68 | joel1di1-mvn-repo 69 | https://github.com/joel1di1/joel1di1-mvn-repo/raw/master/releases/ 70 | 71 | 72 | 73 | 74 | 75 | org.jenkins-ci.tools 76 | maven-hpi-plugin 77 | 2.0 78 | 79 | true 80 | 81 | 82 | 83 | org.kohsuke 84 | access-modifier-checker 85 | 1.20 86 | 87 | 88 | 89 | 90 | 91 | repo.jenkins-ci.org 92 | https://repo.jenkins-ci.org/public/ 93 | 94 | 95 | 96 | 97 | org.apache.httpcomponents 98 | httpmime 99 | 4.5.9 100 | compile 101 | 102 | 103 | org.apache.httpcomponents 104 | httpcore 105 | 4.4.11 106 | compile 107 | 108 | 109 | org.jenkins-ci.plugins 110 | promoted-builds 111 | 3.4 112 | true 113 | 114 | 115 | com.appaloosa-store 116 | appaloosa-client 117 | 2.0 118 | 119 | 120 | 121 | 122 | repo.jenkins-ci.org 123 | https://repo.jenkins-ci.org/releases 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /src/main/java/org/jenkins/plugins/appaloosa/AppaloosaPublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2011 eXo platform 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkins.plugins.appaloosa; 26 | 27 | import hudson.EnvVars; 28 | import hudson.Extension; 29 | import hudson.FilePath; 30 | import hudson.Launcher; 31 | import hudson.model.Action; 32 | import hudson.model.BuildListener; 33 | import hudson.model.Result; 34 | import hudson.model.AbstractBuild; 35 | import hudson.model.AbstractProject; 36 | import hudson.model.Hudson; 37 | import hudson.model.Node; 38 | import hudson.plugins.promoted_builds.Promotion; 39 | import hudson.tasks.BuildStepDescriptor; 40 | import hudson.tasks.BuildStepMonitor; 41 | import hudson.tasks.Publisher; 42 | import hudson.tasks.Recorder; 43 | import hudson.util.FormValidation; 44 | import hudson.util.RunList; 45 | import hudson.util.Secret; 46 | 47 | import java.io.File; 48 | import java.io.IOException; 49 | import java.util.ArrayList; 50 | import java.util.Collection; 51 | import java.util.Collections; 52 | import java.util.List; 53 | 54 | import net.sf.json.JSONObject; 55 | 56 | import org.apache.commons.collections.CollectionUtils; 57 | import org.apache.commons.collections.Predicate; 58 | import org.apache.commons.io.FileUtils; 59 | import org.apache.commons.io.FilenameUtils; 60 | import org.apache.commons.lang.StringUtils; 61 | import org.kohsuke.stapler.AncestorInPath; 62 | import org.kohsuke.stapler.DataBoundConstructor; 63 | import org.kohsuke.stapler.QueryParameter; 64 | import org.kohsuke.stapler.StaplerRequest; 65 | 66 | import com.appaloosastore.client.AppaloosaClient; 67 | 68 | public class AppaloosaPublisher extends Recorder { 69 | 70 | public final Secret token; 71 | public final String filePattern; 72 | public final String proxyHost; 73 | public final String proxyUser; 74 | public final String proxyPass; 75 | public final int proxyPort; 76 | public String description; 77 | public String changelog; 78 | public final String groups; 79 | 80 | @DataBoundConstructor 81 | public AppaloosaPublisher(String token, String filePattern, 82 | String proxyHost, String proxyUser, String proxyPass, 83 | int proxyPort, String description, String groups, String changelog) { 84 | this.token = Secret.fromString(token); 85 | this.filePattern = filePattern; 86 | this.proxyHost = proxyHost; 87 | this.proxyUser = proxyUser; 88 | this.proxyPass = proxyPass; 89 | this.proxyPort = proxyPort; 90 | this.description = description; 91 | this.changelog = changelog; 92 | this.groups = groups; 93 | } 94 | 95 | @Override 96 | public DescriptorImpl getDescriptor() { 97 | return (DescriptorImpl) super.getDescriptor(); 98 | } 99 | 100 | public BuildStepMonitor getRequiredMonitorService() { 101 | return BuildStepMonitor.NONE; 102 | } 103 | 104 | @Override 105 | public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { 106 | if (build.getResult().isWorseOrEqualTo(Result.FAILURE)) 107 | return true; // nothing to do 108 | 109 | // Validates that the organization token is filled in the project configuration. 110 | if (StringUtils.isBlank(Secret.toString(token))) { 111 | listener.error(Messages._AppaloosaPublisher_noToken().toString()); 112 | return false; 113 | } 114 | 115 | // Validates that the file pattern is filled in the project configuration. 116 | if (StringUtils.isBlank(filePattern)) { 117 | listener.error(Messages._AppaloosaPublisher_noFilePattern().toString()); 118 | return false; 119 | } 120 | 121 | //search file in the workspace with the pattern 122 | FileFinder fileFinder = new FileFinder(filePattern); 123 | 124 | // Where we'll get artifacts from 125 | FilePath rootDir; 126 | // If the promotion plugin is used we have to take care to get data from the original build (not the promotion build) 127 | if (Hudson.getInstance().getPlugin("promoted-builds") != null && build instanceof Promotion) { 128 | rootDir = new FilePath (((Promotion) build).getTargetBuild().getArtifactsDir()); 129 | } else { 130 | rootDir = build.getWorkspace(); 131 | if (rootDir==null) { // slave down? 132 | listener.error(Messages.AppaloosaPublisher_buildWorkspaceUnavailable()); 133 | return false; 134 | } 135 | } 136 | listener.getLogger().println(Messages.AppaloosaPublisher_RootDirectory(rootDir)); 137 | 138 | List fileNames = rootDir.act(fileFinder); 139 | listener.getLogger().println(Messages.AppaloosaPublisher_foundFiles(fileNames)); 140 | 141 | if (fileNames.isEmpty()) { 142 | listener.error(Messages._AppaloosaPublisher_noArtifactsFound(filePattern).toString()); 143 | return false; 144 | } 145 | 146 | String descriptionToSend = evaluateField(description, build, listener, rootDir); 147 | String changelogToSend = evaluateField(changelog, build, listener, rootDir); 148 | String groupsToSend = evaluateField(groups, build, listener, rootDir); 149 | 150 | // Initialize Appaloosa Client 151 | AppaloosaClient appaloosaClient = new AppaloosaClient(Secret.toString(token),proxyHost,proxyPort,proxyUser,proxyPass); 152 | appaloosaClient.useLogger(listener.getLogger()); 153 | 154 | boolean result=true; 155 | // Deploy each artifact found 156 | for (String filename : fileNames) { 157 | File tmpArchive = File.createTempFile("jenkins", "temp-appaloosa-deploy."+FilenameUtils.getExtension(filename)); 158 | 159 | try { 160 | // handle remote slave case so copy binary locally 161 | Node buildNode = Hudson.getInstance().getNode(build.getBuiltOnStr()); 162 | FilePath tmpLocalFile = new FilePath(tmpArchive); 163 | FilePath remoteFile = rootDir.child(filename); 164 | remoteFile.copyTo(tmpLocalFile); 165 | 166 | listener.getLogger().println(Messages.AppaloosaPublisher_deploying(filename, descriptionToSend, groupsToSend, changelogToSend)); 167 | appaloosaClient.deployFile(tmpArchive.getAbsolutePath(), descriptionToSend, groupsToSend, changelogToSend); 168 | listener.getLogger().println(Messages.AppaloosaPublisher_deployed()); 169 | } catch (Exception e) { 170 | listener.getLogger().println(Messages.AppaloosaPublisher_deploymentFailed(e.getMessage())); 171 | result=false; 172 | } finally { 173 | FileUtils.deleteQuietly(tmpArchive); 174 | } 175 | 176 | } 177 | return result; 178 | } 179 | 180 | private String evaluateField(String field, AbstractBuild build, BuildListener listener, FilePath rootDirectory) throws IOException, InterruptedException { 181 | EnvVars vars = build.getEnvironment(listener); 182 | String fieldValue = vars.expand(field); 183 | 184 | if (!fieldValue.isEmpty()) { 185 | //If the field is a file path and it exists, we grab the content, otherwise the field is taken as is. 186 | FilePath filePath = new FilePath(rootDirectory, fieldValue); 187 | if (filePath.exists()) { 188 | fieldValue = filePath.readToString(); 189 | } 190 | } 191 | return fieldValue; 192 | } 193 | 194 | @Override 195 | public Collection getProjectActions(AbstractProject project) { 196 | ArrayList actions = new ArrayList(); 197 | RunList> builds = project.getBuilds(); 198 | 199 | Collection predicated = CollectionUtils.select(builds, new Predicate() { 200 | public boolean evaluate(Object o) { 201 | Result r = ((AbstractBuild) o).getResult(); 202 | return r!=null && r.isBetterOrEqualTo(Result.SUCCESS); 203 | } 204 | }); 205 | 206 | ArrayList> filteredList = new ArrayList>(predicated); 207 | 208 | 209 | Collections.reverse(filteredList); 210 | for (AbstractBuild build : filteredList) { 211 | List appaloosaActions = build.getActions(AppaloosaBuildAction.class); 212 | if (appaloosaActions != null && appaloosaActions.size() > 0) { 213 | for (AppaloosaBuildAction action : appaloosaActions) { 214 | actions.add(new AppaloosaBuildAction(action)); 215 | } 216 | break; 217 | } 218 | } 219 | 220 | return actions; 221 | } 222 | 223 | @Extension // This indicates to Jenkins that this is an implementation of an extension point. 224 | public static final class DescriptorImpl extends BuildStepDescriptor { 225 | public DescriptorImpl() { 226 | super(AppaloosaPublisher.class); 227 | load(); 228 | } 229 | 230 | public boolean isApplicable(Class aClass) { 231 | // Indicates that this builder can be used with all kinds of project types 232 | return true; 233 | } 234 | 235 | @Override 236 | public boolean configure(StaplerRequest req, JSONObject json) throws FormException { 237 | // XXX is this now the right style? 238 | req.bindJSON(this, json); 239 | save(); 240 | return true; 241 | } 242 | 243 | /** 244 | * Performs on-the-fly validation on the file mask wildcard. 245 | */ 246 | public FormValidation doCheckFilePattern(@AncestorInPath AbstractProject project, @QueryParameter String value) throws IOException { 247 | return FilePath.validateFileMask(project.getSomeWorkspace(),value); 248 | } 249 | 250 | /** 251 | * This human readable name is used in the configuration screen. 252 | */ 253 | public String getDisplayName() { 254 | return Messages.AppaloosaPublisher_uploadToAppaloosa(); 255 | } 256 | } 257 | } 258 | --------------------------------------------------------------------------------