From 31b33ab7e3b08d8ae1345d53822e64d5268283c8 Mon Sep 17 00:00:00 2001 From: Johannes Utzig Date: Mon, 29 Oct 2012 19:04:44 +0100 Subject: [PATCH 1/2] added new field to specifiy submodules --- pom.xml | 2 +- .../plugins/m2release/M2ReleaseAction.java | 683 +++++++++--------- .../m2release/M2ReleaseArgumentsAction.java | 9 + .../m2release/M2ReleaseBuildWrapper.java | 8 +- .../m2release/M2ReleaseAction/index.jelly | 162 +++-- .../help-actionRelease-specifySubmodule.html | 6 + 6 files changed, 455 insertions(+), 415 deletions(-) create mode 100644 src/main/webapp/help-actionRelease-specifySubmodule.html diff --git a/pom.xml b/pom.xml index 28af1e71..b2cdb08e 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ org.jenkins-ci.plugins plugin - 1.442 + 1.488 Jenkins Maven Release Plug-in Plug-in diff --git a/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseAction.java b/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseAction.java index fb7f5946..fc075152 100644 --- a/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseAction.java +++ b/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseAction.java @@ -1,335 +1,348 @@ -/* - * The MIT License - * - * Copyright (c) 2009, NDS Group Ltd., James Nord, CloudBees, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.jvnet.hudson.plugins.m2release; - -import hudson.maven.MavenModule; -import hudson.maven.MavenModuleSet; -import hudson.model.ParameterValue; -import hudson.model.BooleanParameterValue; -import hudson.model.Hudson; -import hudson.model.ParameterDefinition; -import hudson.model.ParametersAction; -import hudson.model.ParametersDefinitionProperty; -import hudson.model.PasswordParameterValue; -import hudson.model.PermalinkProjectAction; -import hudson.model.StringParameterValue; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.servlet.ServletException; - -import net.sf.json.JSONArray; -import net.sf.json.JSONObject; - -import org.apache.commons.lang.StringUtils; -import org.apache.maven.shared.release.versions.DefaultVersionInfo; -import org.apache.maven.shared.release.versions.VersionParseException; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; - -/** - * The action appears as the link in the side bar that users will click on in - * order to start the release process. - * - * @author James Nord - * @author Dominik Bartholdi - * @version 0.3 - */ -public class M2ReleaseAction implements PermalinkProjectAction { - - private MavenModuleSet project; - private boolean selectCustomScmCommentPrefix; - private boolean selectCustomScmTag = false; - private boolean selectAppendHudsonUsername; - private boolean selectScmCredentials; - - public M2ReleaseAction(MavenModuleSet project, boolean selectCustomScmCommentPrefix, boolean selectAppendHudsonUsername, boolean selectScmCredentials) { - this.project = project; - this.selectCustomScmCommentPrefix = selectCustomScmCommentPrefix; - this.selectAppendHudsonUsername = selectAppendHudsonUsername; - this.selectScmCredentials = selectScmCredentials; - if (getRootModule() == null) { - // if the root module is not available, the user should be informed - // about the stuff we are not able to compute - this.selectCustomScmTag = true; - } - } - - public List getParameterDefinitions() { - ParametersDefinitionProperty pdp = project.getProperty(ParametersDefinitionProperty.class); - List pds = Collections.emptyList(); - if (pdp != null) { - pds = pdp.getParameterDefinitions(); - } - return pds; - } - - public List getPermalinks() { - return PERMALINKS; - } - - public String getDisplayName() { - return Messages.ReleaseAction_perform_release_name(); - } - - public String getIconFileName() { - if (M2ReleaseBuildWrapper.hasReleasePermission(project)) { - return "installer.gif"; //$NON-NLS-1$ - } - // by returning null the link will not be shown. - return null; - } - - public String getUrlName() { - return "m2release"; //$NON-NLS-1$ - } - - public boolean isSelectScmCredentials() { - return selectScmCredentials; - } - - public boolean isSelectCustomScmCommentPrefix() { - return selectCustomScmCommentPrefix; - } - - public void setSelectCustomScmCommentPrefix(boolean selectCustomScmCommentPrefix) { - this.selectCustomScmCommentPrefix = selectCustomScmCommentPrefix; - } - - public boolean isSelectAppendHudsonUsername() { - return selectAppendHudsonUsername; - } - - public void setSelectAppendHudsonUsername(boolean selectAppendHudsonUsername) { - this.selectAppendHudsonUsername = selectAppendHudsonUsername; - } - - public boolean isSelectCustomScmTag() { - return selectCustomScmTag; - } - - public Collection getModules() { - return project.getModules(); - } - - public MavenModule getRootModule() { - return project.getRootModule(); - } - - public String computeReleaseVersion() { - String version = "NaN"; - final MavenModule rootModule = getRootModule(); - if (rootModule != null && StringUtils.isNotBlank(rootModule.getVersion())) { - try { - DefaultVersionInfo dvi = new DefaultVersionInfo(rootModule.getVersion()); - version = dvi.getReleaseVersionString(); - } catch (VersionParseException vpEx) { - Logger logger = Logger.getLogger(this.getClass().getName()); - logger.log(Level.WARNING, "Failed to compute next version.", vpEx); - version = rootModule.getVersion().replace("-SNAPSHOT", ""); - } - } - return version; - } - - public String computeRepoDescription() { - StringBuilder sb = new StringBuilder(); - sb.append(project.getRootModule().getName()); - sb.append(':'); - sb.append(computeReleaseVersion()); - return sb.toString(); - } - - public String computeScmTag() { - // maven default is artifact-version - String artifactId = getRootModule() == null ? "M2RELEASE-TAG" : getRootModule().getModuleName().artifactId; - StringBuilder sb = new StringBuilder(); - sb.append(artifactId); - sb.append('-'); - sb.append(computeReleaseVersion()); - return sb.toString(); - } - - public String computeNextVersion() { - String version = "NaN-SNAPSHOT"; - final MavenModule rootModule = getRootModule(); - if (rootModule != null && StringUtils.isNotBlank(rootModule.getVersion())) { - try { - DefaultVersionInfo dvi = new DefaultVersionInfo(rootModule.getVersion()); - version = dvi.getNextVersion().getSnapshotVersionString(); - } catch (Exception vpEx) { - Logger logger = Logger.getLogger(this.getClass().getName()); - logger.log(Level.WARNING, "Failed to compute next version.", vpEx); - } - } - return version; - } - - public boolean isNexusSupportEnabled() { - return project.getBuildWrappersList().get(M2ReleaseBuildWrapper.class).getDescriptor().isNexusSupport(); - } - - public void doSubmit(StaplerRequest req, StaplerResponse resp) throws IOException, ServletException { - M2ReleaseBuildWrapper.checkReleasePermission(project); - M2ReleaseBuildWrapper m2Wrapper = project.getBuildWrappersList().get(M2ReleaseBuildWrapper.class); - - // JSON collapses everything in the dynamic specifyVersions section so - // we need to fall back to - // good old http... - Map httpParams = req.getParameterMap(); - - final boolean appendHudsonBuildNumber = httpParams.containsKey("appendHudsonBuildNumber"); //$NON-NLS-1$ - final boolean closeNexusStage = httpParams.containsKey("closeNexusStage"); //$NON-NLS-1$ - final String repoDescription = closeNexusStage ? getString("repoDescription", httpParams) : ""; //$NON-NLS-1$ - final boolean specifyScmCredentials = httpParams.containsKey("specifyScmCredentials"); //$NON-NLS-1$ - final String scmUsername = specifyScmCredentials ? getString("scmUsername", httpParams) : null; //$NON-NLS-1$ - final String scmPassword = specifyScmCredentials ? getString("scmPassword", httpParams) : null; //$NON-NLS-1$ - final boolean specifyScmCommentPrefix = httpParams.containsKey("specifyScmCommentPrefix"); //$NON-NLS-1$ - final String scmCommentPrefix = specifyScmCommentPrefix ? getString("scmCommentPrefix", httpParams) : null; //$NON-NLS-1$ - final boolean specifyScmTag = httpParams.containsKey("specifyScmTag"); //$NON-NLS-1$ - final String scmTag = specifyScmTag ? getString("scmTag", httpParams) : null; //$NON-NLS-1$ - - final boolean appendHusonUserName = specifyScmCommentPrefix && httpParams.containsKey("appendHudsonUserName"); //$NON-NLS-1$ - final boolean isDryRun = httpParams.containsKey("isDryRun"); //$NON-NLS-1$ - - final String releaseVersion = getString("releaseVersion", httpParams); //$NON-NLS-1$ - final String developmentVersion = getString("developmentVersion", httpParams); //$NON-NLS-1$ - - // TODO make this nicer by showing a html error page. - // this will throw an exception so control will terminate if the dev - // version is not a "SNAPSHOT". - enforceDeveloperVersion(developmentVersion); - - // get the normal job parameters (adapted from - // hudson.model.ParametersDefinitionProperty._doBuild(StaplerRequest, - // StaplerResponse)) - List values = new ArrayList(); - JSONObject formData = req.getSubmittedForm(); - JSONArray a = JSONArray.fromObject(formData.get("parameter")); - for (Object o : a) { - JSONObject jo = (JSONObject) o; - if (jo != null && !jo.isNullObject()) { - String name = jo.optString("name"); - if (name != null) { - ParameterDefinition d = getParameterDefinition(name); - if (d == null) { - throw new IllegalArgumentException("No such parameter definition: " + name); - } - ParameterValue parameterValue = d.createValue(req, jo); - values.add(parameterValue); - } - } - } - - // if configured, expose the SCM credentails as additional parameters - if (StringUtils.isNotBlank(m2Wrapper.getScmPasswordEnvVar())) { - String scmPasswordVal = StringUtils.isEmpty(scmPassword) ? "" : scmPassword; - values.add(new PasswordParameterValue(m2Wrapper.getScmPasswordEnvVar(), scmPasswordVal)); - } - if (StringUtils.isNotBlank(m2Wrapper.getScmUserEnvVar())) { - String scmUsernameVal = StringUtils.isEmpty(scmUsername) ? "" : scmUsername; - values.add(new StringParameterValue(m2Wrapper.getScmUserEnvVar(), scmUsernameVal)); - } - values.add(new StringParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_RELEASE_VERSION_ENVVAR, releaseVersion)); - values.add(new StringParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_DEV_VERSION_ENVVAR, developmentVersion)); - values.add(new BooleanParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_DRYRUN_ENVVAR, isDryRun)); - - // schedule release build - ParametersAction parameters = new ParametersAction(values); - - M2ReleaseArgumentsAction arguments = new M2ReleaseArgumentsAction(); - arguments.setDryRun(isDryRun); - - arguments.setReleaseVersion(releaseVersion); - arguments.setDevelopmentVersion(developmentVersion); - // TODO - re-implement versions on specific modules. - - arguments.setCloseNexusStage(closeNexusStage); - arguments.setRepoDescription(repoDescription); - arguments.setScmUsername(scmUsername); - arguments.setScmPassword(scmPassword); - arguments.setScmTagName(scmTag); - arguments.setScmCommentPrefix(scmCommentPrefix); - arguments.setAppendHusonUserName(appendHusonUserName); - arguments.setHudsonUserName(Hudson.getAuthentication().getName()); - - - if (project.scheduleBuild(0, new ReleaseCause(), parameters, arguments)) { - resp.sendRedirect(req.getContextPath() + '/' + project.getUrl()); - } else { - // redirect to error page. - // TODO try and get this to go back to the form page with an - // error at the top. - resp.sendRedirect(req.getContextPath() + '/' + project.getUrl() + '/' + getUrlName() + "/failed"); - } - } - - /** - * Gets the {@link ParameterDefinition} of the given name, if any. - */ - public ParameterDefinition getParameterDefinition(String name) { - for (ParameterDefinition pd : getParameterDefinitions()) { - if (pd.getName().equals(name)) { - return pd; - } - } - return null; - } - - /** - * returns the value of the key as a String. if multiple values have been - * submitted, the first one will be returned. - * - * @param key - * @param httpParams - * @return - */ - private String getString(String key, Map httpParams) { - return (String) (((Object[]) httpParams.get(key))[0]); - } - - /** - * Enforces that the developer version is actually a developer version and - * ends with "-SNAPSHOT". - * - * @throws IllegalArgumentException - * if the version does not end with "-SNAPSHOT" - */ - private void enforceDeveloperVersion(String version) throws IllegalArgumentException { - if (!version.endsWith("-SNAPSHOT")) { - throw new IllegalArgumentException(String.format(Locale.ENGLISH, "Developer Version (%s) is not a valid version (it must end with \"-SNAPSHOT\")", - version)); - } - } - - private static final List PERMALINKS = Collections.singletonList(LastReleasePermalink.INSTANCE); -} +/* + * The MIT License + * + * Copyright (c) 2009, NDS Group Ltd., James Nord, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.jvnet.hudson.plugins.m2release; + +import hudson.maven.MavenModule; +import hudson.maven.MavenModuleSet; +import hudson.model.ParameterValue; +import hudson.model.BooleanParameterValue; +import hudson.model.Hudson; +import hudson.model.ParameterDefinition; +import hudson.model.ParametersAction; +import hudson.model.ParametersDefinitionProperty; +import hudson.model.PasswordParameterValue; +import hudson.model.PermalinkProjectAction; +import hudson.model.StringParameterValue; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.servlet.ServletException; + +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; + +import org.apache.commons.lang.StringUtils; +import org.apache.maven.shared.release.versions.DefaultVersionInfo; +import org.apache.maven.shared.release.versions.VersionParseException; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; + +/** + * The action appears as the link in the side bar that users will click on in + * order to start the release process. + * + * @author James Nord + * @author Dominik Bartholdi + * @version 0.3 + */ +public class M2ReleaseAction implements PermalinkProjectAction { + + private MavenModuleSet project; + private boolean selectCustomScmCommentPrefix; + private boolean selectCustomScmTag = false; + private boolean selectAppendHudsonUsername; + private boolean selectScmCredentials; + private boolean selectSubmoduleRelease; + + public M2ReleaseAction(MavenModuleSet project, boolean selectCustomScmCommentPrefix, boolean selectAppendHudsonUsername, boolean selectScmCredentials, boolean selectSubmoduleRelease) { + this.project = project; + this.selectCustomScmCommentPrefix = selectCustomScmCommentPrefix; + this.selectAppendHudsonUsername = selectAppendHudsonUsername; + this.selectScmCredentials = selectScmCredentials; + this.selectSubmoduleRelease = selectSubmoduleRelease; + if (getRootModule() == null) { + // if the root module is not available, the user should be informed + // about the stuff we are not able to compute + this.selectCustomScmTag = true; + } + } + + public List getParameterDefinitions() { + ParametersDefinitionProperty pdp = project.getProperty(ParametersDefinitionProperty.class); + List pds = Collections.emptyList(); + if (pdp != null) { + pds = pdp.getParameterDefinitions(); + } + return pds; + } + + public List getPermalinks() { + return PERMALINKS; + } + + public String getDisplayName() { + return Messages.ReleaseAction_perform_release_name(); + } + + public String getIconFileName() { + if (M2ReleaseBuildWrapper.hasReleasePermission(project)) { + return "installer.gif"; //$NON-NLS-1$ + } + // by returning null the link will not be shown. + return null; + } + + public String getUrlName() { + return "m2release"; //$NON-NLS-1$ + } + + public boolean isSelectScmCredentials() { + return selectScmCredentials; + } + + public boolean isSelectCustomScmCommentPrefix() { + return selectCustomScmCommentPrefix; + } + + public void setSelectCustomScmCommentPrefix(boolean selectCustomScmCommentPrefix) { + this.selectCustomScmCommentPrefix = selectCustomScmCommentPrefix; + } + + public boolean isSelectAppendHudsonUsername() { + return selectAppendHudsonUsername; + } + + public void setSelectAppendHudsonUsername(boolean selectAppendHudsonUsername) { + this.selectAppendHudsonUsername = selectAppendHudsonUsername; + } + + public boolean isSelectSubmoduleRelease() { + return selectSubmoduleRelease; + } + + public void setSelectSubmoduleRelease(boolean selectSubmoduleRelease) { + this.selectSubmoduleRelease = selectSubmoduleRelease; + } + + public boolean isSelectCustomScmTag() { + return selectCustomScmTag; + } + + public Collection getModules() { + return project.getModules(); + } + + public MavenModule getRootModule() { + return project.getRootModule(); + } + + public String computeReleaseVersion() { + String version = "NaN"; + final MavenModule rootModule = getRootModule(); + if (rootModule != null && StringUtils.isNotBlank(rootModule.getVersion())) { + try { + DefaultVersionInfo dvi = new DefaultVersionInfo(rootModule.getVersion()); + version = dvi.getReleaseVersionString(); + } catch (VersionParseException vpEx) { + Logger logger = Logger.getLogger(this.getClass().getName()); + logger.log(Level.WARNING, "Failed to compute next version.", vpEx); + version = rootModule.getVersion().replace("-SNAPSHOT", ""); + } + } + return version; + } + + public String computeRepoDescription() { + StringBuilder sb = new StringBuilder(); + sb.append(project.getRootModule().getName()); + sb.append(':'); + sb.append(computeReleaseVersion()); + return sb.toString(); + } + + public String computeScmTag() { + // maven default is artifact-version + String artifactId = getRootModule() == null ? "M2RELEASE-TAG" : getRootModule().getModuleName().artifactId; + StringBuilder sb = new StringBuilder(); + sb.append(artifactId); + sb.append('-'); + sb.append(computeReleaseVersion()); + return sb.toString(); + } + + public String computeNextVersion() { + String version = "NaN-SNAPSHOT"; + final MavenModule rootModule = getRootModule(); + if (rootModule != null && StringUtils.isNotBlank(rootModule.getVersion())) { + try { + DefaultVersionInfo dvi = new DefaultVersionInfo(rootModule.getVersion()); + version = dvi.getNextVersion().getSnapshotVersionString(); + } catch (Exception vpEx) { + Logger logger = Logger.getLogger(this.getClass().getName()); + logger.log(Level.WARNING, "Failed to compute next version.", vpEx); + } + } + return version; + } + + public boolean isNexusSupportEnabled() { + return project.getBuildWrappersList().get(M2ReleaseBuildWrapper.class).getDescriptor().isNexusSupport(); + } + + public void doSubmit(StaplerRequest req, StaplerResponse resp) throws IOException, ServletException { + M2ReleaseBuildWrapper.checkReleasePermission(project); + M2ReleaseBuildWrapper m2Wrapper = project.getBuildWrappersList().get(M2ReleaseBuildWrapper.class); + + // JSON collapses everything in the dynamic specifyVersions section so + // we need to fall back to + // good old http... + Map httpParams = req.getParameterMap(); + + final boolean appendHudsonBuildNumber = httpParams.containsKey("appendHudsonBuildNumber"); //$NON-NLS-1$ + final boolean closeNexusStage = httpParams.containsKey("closeNexusStage"); //$NON-NLS-1$ + final String repoDescription = closeNexusStage ? getString("repoDescription", httpParams) : ""; //$NON-NLS-1$ + final boolean specifyScmCredentials = httpParams.containsKey("specifyScmCredentials"); //$NON-NLS-1$ + final String scmUsername = specifyScmCredentials ? getString("scmUsername", httpParams) : null; //$NON-NLS-1$ + final String scmPassword = specifyScmCredentials ? getString("scmPassword", httpParams) : null; //$NON-NLS-1$ + final boolean specifyScmCommentPrefix = httpParams.containsKey("specifyScmCommentPrefix"); //$NON-NLS-1$ + final String scmCommentPrefix = specifyScmCommentPrefix ? getString("scmCommentPrefix", httpParams) : null; //$NON-NLS-1$ + final boolean specifyScmTag = httpParams.containsKey("specifyScmTag"); //$NON-NLS-1$ + final String scmTag = specifyScmTag ? getString("scmTag", httpParams) : null; //$NON-NLS-1$ + final boolean submoduleRelease = httpParams.containsKey("submoduleRelease"); //$NON-NLS-1$ + final String submodules = submoduleRelease ? getString("submodules", httpParams) : null; //$NON-NLS-1$ + + final boolean appendHusonUserName = specifyScmCommentPrefix && httpParams.containsKey("appendHudsonUserName"); //$NON-NLS-1$ + final boolean isDryRun = httpParams.containsKey("isDryRun"); //$NON-NLS-1$ + + final String releaseVersion = getString("releaseVersion", httpParams); //$NON-NLS-1$ + final String developmentVersion = getString("developmentVersion", httpParams); //$NON-NLS-1$ + + // TODO make this nicer by showing a html error page. + // this will throw an exception so control will terminate if the dev + // version is not a "SNAPSHOT". + enforceDeveloperVersion(developmentVersion); + + // get the normal job parameters (adapted from + // hudson.model.ParametersDefinitionProperty._doBuild(StaplerRequest, + // StaplerResponse)) + List values = new ArrayList(); + JSONObject formData = req.getSubmittedForm(); + JSONArray a = JSONArray.fromObject(formData.get("parameter")); + for (Object o : a) { + JSONObject jo = (JSONObject) o; + if (jo != null && !jo.isNullObject()) { + String name = jo.optString("name"); + if (name != null) { + ParameterDefinition d = getParameterDefinition(name); + if (d == null) { + throw new IllegalArgumentException("No such parameter definition: " + name); + } + ParameterValue parameterValue = d.createValue(req, jo); + values.add(parameterValue); + } + } + } + + // if configured, expose the SCM credentails as additional parameters + if (StringUtils.isNotBlank(m2Wrapper.getScmPasswordEnvVar())) { + String scmPasswordVal = StringUtils.isEmpty(scmPassword) ? "" : scmPassword; + values.add(new PasswordParameterValue(m2Wrapper.getScmPasswordEnvVar(), scmPasswordVal)); + } + if (StringUtils.isNotBlank(m2Wrapper.getScmUserEnvVar())) { + String scmUsernameVal = StringUtils.isEmpty(scmUsername) ? "" : scmUsername; + values.add(new StringParameterValue(m2Wrapper.getScmUserEnvVar(), scmUsernameVal)); + } + values.add(new StringParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_RELEASE_VERSION_ENVVAR, releaseVersion)); + values.add(new StringParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_DEV_VERSION_ENVVAR, developmentVersion)); + values.add(new BooleanParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_DRYRUN_ENVVAR, isDryRun)); + + // schedule release build + ParametersAction parameters = new ParametersAction(values); + + M2ReleaseArgumentsAction arguments = new M2ReleaseArgumentsAction(); + arguments.setDryRun(isDryRun); + + arguments.setReleaseVersion(releaseVersion); + arguments.setDevelopmentVersion(developmentVersion); + // TODO - re-implement versions on specific modules. + + arguments.setCloseNexusStage(closeNexusStage); + arguments.setRepoDescription(repoDescription); + arguments.setScmUsername(scmUsername); + arguments.setScmPassword(scmPassword); + arguments.setScmTagName(scmTag); + arguments.setSubmodules(submodules); + arguments.setScmCommentPrefix(scmCommentPrefix); + arguments.setAppendHusonUserName(appendHusonUserName); + arguments.setHudsonUserName(Hudson.getAuthentication().getName()); + + + if (project.scheduleBuild(0, new ReleaseCause(), parameters, arguments)) { + resp.sendRedirect(req.getContextPath() + '/' + project.getUrl()); + } else { + // redirect to error page. + // TODO try and get this to go back to the form page with an + // error at the top. + resp.sendRedirect(req.getContextPath() + '/' + project.getUrl() + '/' + getUrlName() + "/failed"); + } + } + + /** + * Gets the {@link ParameterDefinition} of the given name, if any. + */ + public ParameterDefinition getParameterDefinition(String name) { + for (ParameterDefinition pd : getParameterDefinitions()) { + if (pd.getName().equals(name)) { + return pd; + } + } + return null; + } + + /** + * returns the value of the key as a String. if multiple values have been + * submitted, the first one will be returned. + * + * @param key + * @param httpParams + * @return + */ + private String getString(String key, Map httpParams) { + return (String) (((Object[]) httpParams.get(key))[0]); + } + + /** + * Enforces that the developer version is actually a developer version and + * ends with "-SNAPSHOT". + * + * @throws IllegalArgumentException + * if the version does not end with "-SNAPSHOT" + */ + private void enforceDeveloperVersion(String version) throws IllegalArgumentException { + if (!version.endsWith("-SNAPSHOT")) { + throw new IllegalArgumentException(String.format(Locale.ENGLISH, "Developer Version (%s) is not a valid version (it must end with \"-SNAPSHOT\")", + version)); + } + } + + private static final List PERMALINKS = Collections.singletonList(LastReleasePermalink.INSTANCE); +} diff --git a/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseArgumentsAction.java b/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseArgumentsAction.java index b5aeccde..d7b682b9 100644 --- a/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseArgumentsAction.java +++ b/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseArgumentsAction.java @@ -59,6 +59,7 @@ public class M2ReleaseArgumentsAction implements Action { private transient String scmPassword; private transient String scmCommentPrefix; private String scmTagName; + private String submodules; private transient boolean appendHusonUserName; private transient String hudsonUserName; @@ -186,4 +187,12 @@ public void setHudsonUserName(String hudsonUserName) { this.hudsonUserName = hudsonUserName; } + public String getSubmodules() { + return submodules; + } + + public void setSubmodules(String submodules) { + this.submodules = submodules; + } + } diff --git a/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseBuildWrapper.java b/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseBuildWrapper.java index eb5b3345..4e6a69df 100644 --- a/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseBuildWrapper.java +++ b/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseBuildWrapper.java @@ -99,6 +99,7 @@ public class M2ReleaseBuildWrapper extends BuildWrapper { public boolean selectCustomScmCommentPrefix = DescriptorImpl.DEFAULT_SELECT_CUSTOM_SCM_COMMENT_PREFIX; public boolean selectAppendHudsonUsername = DescriptorImpl.DEFAULT_SELECT_APPEND_HUDSON_USERNAME; public boolean selectScmCredentials = DescriptorImpl.DEFAULT_SELECT_SCM_CREDENTIALS; + public boolean selectSubmodules = DescriptorImpl.DEFAULT_SELECT_SUBMODULES; public int numberOfReleaseBuildsToKeep = DescriptorImpl.DEFAULT_NUMBER_OF_RELEASE_BUILDS_TO_KEEP; @@ -163,6 +164,10 @@ public void buildEnvVars(Map env) { if (args.getScmTagName() != null) { buildGoals.append("-Dtag=").append(args.getScmTagName()).append(' '); } + + if (args.getSubmodules() != null) { + buildGoals.append("--projects ").append(args.getSubmodules()).append(' '); + } if (args.isDryRun()) { buildGoals.append(getDryRunGoals()); @@ -373,7 +378,7 @@ private Object readResolve() { @Override public Action getProjectAction(@SuppressWarnings("rawtypes") AbstractProject job) { - return new M2ReleaseAction((MavenModuleSet) job, selectCustomScmCommentPrefix, selectAppendHudsonUsername, selectScmCredentials); + return new M2ReleaseAction((MavenModuleSet) job, selectCustomScmCommentPrefix, selectAppendHudsonUsername, selectScmCredentials, selectSubmodules); } /** @@ -465,6 +470,7 @@ public static class DescriptorImpl extends BuildWrapperDescriptor { public static final boolean DEFAULT_SELECT_CUSTOM_SCM_COMMENT_PREFIX = false; public static final boolean DEFAULT_SELECT_APPEND_HUDSON_USERNAME = false; public static final boolean DEFAULT_SELECT_SCM_CREDENTIALS = false; + public static final boolean DEFAULT_SELECT_SUBMODULES = false; public static final int DEFAULT_NUMBER_OF_RELEASE_BUILDS_TO_KEEP = 1; diff --git a/src/main/resources/org/jvnet/hudson/plugins/m2release/M2ReleaseAction/index.jelly b/src/main/resources/org/jvnet/hudson/plugins/m2release/M2ReleaseAction/index.jelly index 31cadf0e..99fc31e8 100644 --- a/src/main/resources/org/jvnet/hudson/plugins/m2release/M2ReleaseAction/index.jelly +++ b/src/main/resources/org/jvnet/hudson/plugins/m2release/M2ReleaseAction/index.jelly @@ -1,78 +1,84 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/help-actionRelease-specifySubmodule.html b/src/main/webapp/help-actionRelease-specifySubmodule.html new file mode 100644 index 00000000..8d7bf233 --- /dev/null +++ b/src/main/webapp/help-actionRelease-specifySubmodule.html @@ -0,0 +1,6 @@ +
+ Enable this option to manually select which sub modules you want to release. If you want to release multiple modules at once, separate them with ','. + By default all modules are released. +

Example:

+

org.example.group:artifact1,org.example.group:artifact2

+

\ No newline at end of file From 411dc0a19f151bec670a8f9b759dc7c678d4ad24 Mon Sep 17 00:00:00 2001 From: Hawk Newton Date: Tue, 9 Apr 2013 14:41:50 -0400 Subject: [PATCH 2/2] Use DOS line endings --- .../plugins/m2release/M2ReleaseAction.java | 696 +++++++++--------- .../m2release/M2ReleaseAction/index.jelly | 168 ++--- 2 files changed, 432 insertions(+), 432 deletions(-) diff --git a/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseAction.java b/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseAction.java index fc075152..b2587ca9 100644 --- a/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseAction.java +++ b/src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseAction.java @@ -1,348 +1,348 @@ -/* - * The MIT License - * - * Copyright (c) 2009, NDS Group Ltd., James Nord, CloudBees, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.jvnet.hudson.plugins.m2release; - -import hudson.maven.MavenModule; -import hudson.maven.MavenModuleSet; -import hudson.model.ParameterValue; -import hudson.model.BooleanParameterValue; -import hudson.model.Hudson; -import hudson.model.ParameterDefinition; -import hudson.model.ParametersAction; -import hudson.model.ParametersDefinitionProperty; -import hudson.model.PasswordParameterValue; -import hudson.model.PermalinkProjectAction; -import hudson.model.StringParameterValue; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.servlet.ServletException; - -import net.sf.json.JSONArray; -import net.sf.json.JSONObject; - -import org.apache.commons.lang.StringUtils; -import org.apache.maven.shared.release.versions.DefaultVersionInfo; -import org.apache.maven.shared.release.versions.VersionParseException; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; - -/** - * The action appears as the link in the side bar that users will click on in - * order to start the release process. - * - * @author James Nord - * @author Dominik Bartholdi - * @version 0.3 - */ -public class M2ReleaseAction implements PermalinkProjectAction { - - private MavenModuleSet project; - private boolean selectCustomScmCommentPrefix; - private boolean selectCustomScmTag = false; - private boolean selectAppendHudsonUsername; - private boolean selectScmCredentials; - private boolean selectSubmoduleRelease; - - public M2ReleaseAction(MavenModuleSet project, boolean selectCustomScmCommentPrefix, boolean selectAppendHudsonUsername, boolean selectScmCredentials, boolean selectSubmoduleRelease) { - this.project = project; - this.selectCustomScmCommentPrefix = selectCustomScmCommentPrefix; - this.selectAppendHudsonUsername = selectAppendHudsonUsername; - this.selectScmCredentials = selectScmCredentials; - this.selectSubmoduleRelease = selectSubmoduleRelease; - if (getRootModule() == null) { - // if the root module is not available, the user should be informed - // about the stuff we are not able to compute - this.selectCustomScmTag = true; - } - } - - public List getParameterDefinitions() { - ParametersDefinitionProperty pdp = project.getProperty(ParametersDefinitionProperty.class); - List pds = Collections.emptyList(); - if (pdp != null) { - pds = pdp.getParameterDefinitions(); - } - return pds; - } - - public List getPermalinks() { - return PERMALINKS; - } - - public String getDisplayName() { - return Messages.ReleaseAction_perform_release_name(); - } - - public String getIconFileName() { - if (M2ReleaseBuildWrapper.hasReleasePermission(project)) { - return "installer.gif"; //$NON-NLS-1$ - } - // by returning null the link will not be shown. - return null; - } - - public String getUrlName() { - return "m2release"; //$NON-NLS-1$ - } - - public boolean isSelectScmCredentials() { - return selectScmCredentials; - } - - public boolean isSelectCustomScmCommentPrefix() { - return selectCustomScmCommentPrefix; - } - - public void setSelectCustomScmCommentPrefix(boolean selectCustomScmCommentPrefix) { - this.selectCustomScmCommentPrefix = selectCustomScmCommentPrefix; - } - - public boolean isSelectAppendHudsonUsername() { - return selectAppendHudsonUsername; - } - - public void setSelectAppendHudsonUsername(boolean selectAppendHudsonUsername) { - this.selectAppendHudsonUsername = selectAppendHudsonUsername; - } - - public boolean isSelectSubmoduleRelease() { - return selectSubmoduleRelease; - } - - public void setSelectSubmoduleRelease(boolean selectSubmoduleRelease) { - this.selectSubmoduleRelease = selectSubmoduleRelease; - } - - public boolean isSelectCustomScmTag() { - return selectCustomScmTag; - } - - public Collection getModules() { - return project.getModules(); - } - - public MavenModule getRootModule() { - return project.getRootModule(); - } - - public String computeReleaseVersion() { - String version = "NaN"; - final MavenModule rootModule = getRootModule(); - if (rootModule != null && StringUtils.isNotBlank(rootModule.getVersion())) { - try { - DefaultVersionInfo dvi = new DefaultVersionInfo(rootModule.getVersion()); - version = dvi.getReleaseVersionString(); - } catch (VersionParseException vpEx) { - Logger logger = Logger.getLogger(this.getClass().getName()); - logger.log(Level.WARNING, "Failed to compute next version.", vpEx); - version = rootModule.getVersion().replace("-SNAPSHOT", ""); - } - } - return version; - } - - public String computeRepoDescription() { - StringBuilder sb = new StringBuilder(); - sb.append(project.getRootModule().getName()); - sb.append(':'); - sb.append(computeReleaseVersion()); - return sb.toString(); - } - - public String computeScmTag() { - // maven default is artifact-version - String artifactId = getRootModule() == null ? "M2RELEASE-TAG" : getRootModule().getModuleName().artifactId; - StringBuilder sb = new StringBuilder(); - sb.append(artifactId); - sb.append('-'); - sb.append(computeReleaseVersion()); - return sb.toString(); - } - - public String computeNextVersion() { - String version = "NaN-SNAPSHOT"; - final MavenModule rootModule = getRootModule(); - if (rootModule != null && StringUtils.isNotBlank(rootModule.getVersion())) { - try { - DefaultVersionInfo dvi = new DefaultVersionInfo(rootModule.getVersion()); - version = dvi.getNextVersion().getSnapshotVersionString(); - } catch (Exception vpEx) { - Logger logger = Logger.getLogger(this.getClass().getName()); - logger.log(Level.WARNING, "Failed to compute next version.", vpEx); - } - } - return version; - } - - public boolean isNexusSupportEnabled() { - return project.getBuildWrappersList().get(M2ReleaseBuildWrapper.class).getDescriptor().isNexusSupport(); - } - - public void doSubmit(StaplerRequest req, StaplerResponse resp) throws IOException, ServletException { - M2ReleaseBuildWrapper.checkReleasePermission(project); - M2ReleaseBuildWrapper m2Wrapper = project.getBuildWrappersList().get(M2ReleaseBuildWrapper.class); - - // JSON collapses everything in the dynamic specifyVersions section so - // we need to fall back to - // good old http... - Map httpParams = req.getParameterMap(); - - final boolean appendHudsonBuildNumber = httpParams.containsKey("appendHudsonBuildNumber"); //$NON-NLS-1$ - final boolean closeNexusStage = httpParams.containsKey("closeNexusStage"); //$NON-NLS-1$ - final String repoDescription = closeNexusStage ? getString("repoDescription", httpParams) : ""; //$NON-NLS-1$ - final boolean specifyScmCredentials = httpParams.containsKey("specifyScmCredentials"); //$NON-NLS-1$ - final String scmUsername = specifyScmCredentials ? getString("scmUsername", httpParams) : null; //$NON-NLS-1$ - final String scmPassword = specifyScmCredentials ? getString("scmPassword", httpParams) : null; //$NON-NLS-1$ - final boolean specifyScmCommentPrefix = httpParams.containsKey("specifyScmCommentPrefix"); //$NON-NLS-1$ - final String scmCommentPrefix = specifyScmCommentPrefix ? getString("scmCommentPrefix", httpParams) : null; //$NON-NLS-1$ - final boolean specifyScmTag = httpParams.containsKey("specifyScmTag"); //$NON-NLS-1$ - final String scmTag = specifyScmTag ? getString("scmTag", httpParams) : null; //$NON-NLS-1$ - final boolean submoduleRelease = httpParams.containsKey("submoduleRelease"); //$NON-NLS-1$ - final String submodules = submoduleRelease ? getString("submodules", httpParams) : null; //$NON-NLS-1$ - - final boolean appendHusonUserName = specifyScmCommentPrefix && httpParams.containsKey("appendHudsonUserName"); //$NON-NLS-1$ - final boolean isDryRun = httpParams.containsKey("isDryRun"); //$NON-NLS-1$ - - final String releaseVersion = getString("releaseVersion", httpParams); //$NON-NLS-1$ - final String developmentVersion = getString("developmentVersion", httpParams); //$NON-NLS-1$ - - // TODO make this nicer by showing a html error page. - // this will throw an exception so control will terminate if the dev - // version is not a "SNAPSHOT". - enforceDeveloperVersion(developmentVersion); - - // get the normal job parameters (adapted from - // hudson.model.ParametersDefinitionProperty._doBuild(StaplerRequest, - // StaplerResponse)) - List values = new ArrayList(); - JSONObject formData = req.getSubmittedForm(); - JSONArray a = JSONArray.fromObject(formData.get("parameter")); - for (Object o : a) { - JSONObject jo = (JSONObject) o; - if (jo != null && !jo.isNullObject()) { - String name = jo.optString("name"); - if (name != null) { - ParameterDefinition d = getParameterDefinition(name); - if (d == null) { - throw new IllegalArgumentException("No such parameter definition: " + name); - } - ParameterValue parameterValue = d.createValue(req, jo); - values.add(parameterValue); - } - } - } - - // if configured, expose the SCM credentails as additional parameters - if (StringUtils.isNotBlank(m2Wrapper.getScmPasswordEnvVar())) { - String scmPasswordVal = StringUtils.isEmpty(scmPassword) ? "" : scmPassword; - values.add(new PasswordParameterValue(m2Wrapper.getScmPasswordEnvVar(), scmPasswordVal)); - } - if (StringUtils.isNotBlank(m2Wrapper.getScmUserEnvVar())) { - String scmUsernameVal = StringUtils.isEmpty(scmUsername) ? "" : scmUsername; - values.add(new StringParameterValue(m2Wrapper.getScmUserEnvVar(), scmUsernameVal)); - } - values.add(new StringParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_RELEASE_VERSION_ENVVAR, releaseVersion)); - values.add(new StringParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_DEV_VERSION_ENVVAR, developmentVersion)); - values.add(new BooleanParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_DRYRUN_ENVVAR, isDryRun)); - - // schedule release build - ParametersAction parameters = new ParametersAction(values); - - M2ReleaseArgumentsAction arguments = new M2ReleaseArgumentsAction(); - arguments.setDryRun(isDryRun); - - arguments.setReleaseVersion(releaseVersion); - arguments.setDevelopmentVersion(developmentVersion); - // TODO - re-implement versions on specific modules. - - arguments.setCloseNexusStage(closeNexusStage); - arguments.setRepoDescription(repoDescription); - arguments.setScmUsername(scmUsername); - arguments.setScmPassword(scmPassword); - arguments.setScmTagName(scmTag); - arguments.setSubmodules(submodules); - arguments.setScmCommentPrefix(scmCommentPrefix); - arguments.setAppendHusonUserName(appendHusonUserName); - arguments.setHudsonUserName(Hudson.getAuthentication().getName()); - - - if (project.scheduleBuild(0, new ReleaseCause(), parameters, arguments)) { - resp.sendRedirect(req.getContextPath() + '/' + project.getUrl()); - } else { - // redirect to error page. - // TODO try and get this to go back to the form page with an - // error at the top. - resp.sendRedirect(req.getContextPath() + '/' + project.getUrl() + '/' + getUrlName() + "/failed"); - } - } - - /** - * Gets the {@link ParameterDefinition} of the given name, if any. - */ - public ParameterDefinition getParameterDefinition(String name) { - for (ParameterDefinition pd : getParameterDefinitions()) { - if (pd.getName().equals(name)) { - return pd; - } - } - return null; - } - - /** - * returns the value of the key as a String. if multiple values have been - * submitted, the first one will be returned. - * - * @param key - * @param httpParams - * @return - */ - private String getString(String key, Map httpParams) { - return (String) (((Object[]) httpParams.get(key))[0]); - } - - /** - * Enforces that the developer version is actually a developer version and - * ends with "-SNAPSHOT". - * - * @throws IllegalArgumentException - * if the version does not end with "-SNAPSHOT" - */ - private void enforceDeveloperVersion(String version) throws IllegalArgumentException { - if (!version.endsWith("-SNAPSHOT")) { - throw new IllegalArgumentException(String.format(Locale.ENGLISH, "Developer Version (%s) is not a valid version (it must end with \"-SNAPSHOT\")", - version)); - } - } - - private static final List PERMALINKS = Collections.singletonList(LastReleasePermalink.INSTANCE); -} +/* + * The MIT License + * + * Copyright (c) 2009, NDS Group Ltd., James Nord, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.jvnet.hudson.plugins.m2release; + +import hudson.maven.MavenModule; +import hudson.maven.MavenModuleSet; +import hudson.model.ParameterValue; +import hudson.model.BooleanParameterValue; +import hudson.model.Hudson; +import hudson.model.ParameterDefinition; +import hudson.model.ParametersAction; +import hudson.model.ParametersDefinitionProperty; +import hudson.model.PasswordParameterValue; +import hudson.model.PermalinkProjectAction; +import hudson.model.StringParameterValue; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.servlet.ServletException; + +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; + +import org.apache.commons.lang.StringUtils; +import org.apache.maven.shared.release.versions.DefaultVersionInfo; +import org.apache.maven.shared.release.versions.VersionParseException; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; + +/** + * The action appears as the link in the side bar that users will click on in + * order to start the release process. + * + * @author James Nord + * @author Dominik Bartholdi + * @version 0.3 + */ +public class M2ReleaseAction implements PermalinkProjectAction { + + private MavenModuleSet project; + private boolean selectCustomScmCommentPrefix; + private boolean selectCustomScmTag = false; + private boolean selectAppendHudsonUsername; + private boolean selectScmCredentials; + private boolean selectSubmoduleRelease; + + public M2ReleaseAction(MavenModuleSet project, boolean selectCustomScmCommentPrefix, boolean selectAppendHudsonUsername, boolean selectScmCredentials, boolean selectSubmoduleRelease) { + this.project = project; + this.selectCustomScmCommentPrefix = selectCustomScmCommentPrefix; + this.selectAppendHudsonUsername = selectAppendHudsonUsername; + this.selectScmCredentials = selectScmCredentials; + this.selectSubmoduleRelease = selectSubmoduleRelease; + if (getRootModule() == null) { + // if the root module is not available, the user should be informed + // about the stuff we are not able to compute + this.selectCustomScmTag = true; + } + } + + public List getParameterDefinitions() { + ParametersDefinitionProperty pdp = project.getProperty(ParametersDefinitionProperty.class); + List pds = Collections.emptyList(); + if (pdp != null) { + pds = pdp.getParameterDefinitions(); + } + return pds; + } + + public List getPermalinks() { + return PERMALINKS; + } + + public String getDisplayName() { + return Messages.ReleaseAction_perform_release_name(); + } + + public String getIconFileName() { + if (M2ReleaseBuildWrapper.hasReleasePermission(project)) { + return "installer.gif"; //$NON-NLS-1$ + } + // by returning null the link will not be shown. + return null; + } + + public String getUrlName() { + return "m2release"; //$NON-NLS-1$ + } + + public boolean isSelectScmCredentials() { + return selectScmCredentials; + } + + public boolean isSelectCustomScmCommentPrefix() { + return selectCustomScmCommentPrefix; + } + + public void setSelectCustomScmCommentPrefix(boolean selectCustomScmCommentPrefix) { + this.selectCustomScmCommentPrefix = selectCustomScmCommentPrefix; + } + + public boolean isSelectAppendHudsonUsername() { + return selectAppendHudsonUsername; + } + + public void setSelectAppendHudsonUsername(boolean selectAppendHudsonUsername) { + this.selectAppendHudsonUsername = selectAppendHudsonUsername; + } + + public boolean isSelectSubmoduleRelease() { + return selectSubmoduleRelease; + } + + public void setSelectSubmoduleRelease(boolean selectSubmoduleRelease) { + this.selectSubmoduleRelease = selectSubmoduleRelease; + } + + public boolean isSelectCustomScmTag() { + return selectCustomScmTag; + } + + public Collection getModules() { + return project.getModules(); + } + + public MavenModule getRootModule() { + return project.getRootModule(); + } + + public String computeReleaseVersion() { + String version = "NaN"; + final MavenModule rootModule = getRootModule(); + if (rootModule != null && StringUtils.isNotBlank(rootModule.getVersion())) { + try { + DefaultVersionInfo dvi = new DefaultVersionInfo(rootModule.getVersion()); + version = dvi.getReleaseVersionString(); + } catch (VersionParseException vpEx) { + Logger logger = Logger.getLogger(this.getClass().getName()); + logger.log(Level.WARNING, "Failed to compute next version.", vpEx); + version = rootModule.getVersion().replace("-SNAPSHOT", ""); + } + } + return version; + } + + public String computeRepoDescription() { + StringBuilder sb = new StringBuilder(); + sb.append(project.getRootModule().getName()); + sb.append(':'); + sb.append(computeReleaseVersion()); + return sb.toString(); + } + + public String computeScmTag() { + // maven default is artifact-version + String artifactId = getRootModule() == null ? "M2RELEASE-TAG" : getRootModule().getModuleName().artifactId; + StringBuilder sb = new StringBuilder(); + sb.append(artifactId); + sb.append('-'); + sb.append(computeReleaseVersion()); + return sb.toString(); + } + + public String computeNextVersion() { + String version = "NaN-SNAPSHOT"; + final MavenModule rootModule = getRootModule(); + if (rootModule != null && StringUtils.isNotBlank(rootModule.getVersion())) { + try { + DefaultVersionInfo dvi = new DefaultVersionInfo(rootModule.getVersion()); + version = dvi.getNextVersion().getSnapshotVersionString(); + } catch (Exception vpEx) { + Logger logger = Logger.getLogger(this.getClass().getName()); + logger.log(Level.WARNING, "Failed to compute next version.", vpEx); + } + } + return version; + } + + public boolean isNexusSupportEnabled() { + return project.getBuildWrappersList().get(M2ReleaseBuildWrapper.class).getDescriptor().isNexusSupport(); + } + + public void doSubmit(StaplerRequest req, StaplerResponse resp) throws IOException, ServletException { + M2ReleaseBuildWrapper.checkReleasePermission(project); + M2ReleaseBuildWrapper m2Wrapper = project.getBuildWrappersList().get(M2ReleaseBuildWrapper.class); + + // JSON collapses everything in the dynamic specifyVersions section so + // we need to fall back to + // good old http... + Map httpParams = req.getParameterMap(); + + final boolean appendHudsonBuildNumber = httpParams.containsKey("appendHudsonBuildNumber"); //$NON-NLS-1$ + final boolean closeNexusStage = httpParams.containsKey("closeNexusStage"); //$NON-NLS-1$ + final String repoDescription = closeNexusStage ? getString("repoDescription", httpParams) : ""; //$NON-NLS-1$ + final boolean specifyScmCredentials = httpParams.containsKey("specifyScmCredentials"); //$NON-NLS-1$ + final String scmUsername = specifyScmCredentials ? getString("scmUsername", httpParams) : null; //$NON-NLS-1$ + final String scmPassword = specifyScmCredentials ? getString("scmPassword", httpParams) : null; //$NON-NLS-1$ + final boolean specifyScmCommentPrefix = httpParams.containsKey("specifyScmCommentPrefix"); //$NON-NLS-1$ + final String scmCommentPrefix = specifyScmCommentPrefix ? getString("scmCommentPrefix", httpParams) : null; //$NON-NLS-1$ + final boolean specifyScmTag = httpParams.containsKey("specifyScmTag"); //$NON-NLS-1$ + final String scmTag = specifyScmTag ? getString("scmTag", httpParams) : null; //$NON-NLS-1$ + final boolean submoduleRelease = httpParams.containsKey("submoduleRelease"); //$NON-NLS-1$ + final String submodules = submoduleRelease ? getString("submodules", httpParams) : null; //$NON-NLS-1$ + + final boolean appendHusonUserName = specifyScmCommentPrefix && httpParams.containsKey("appendHudsonUserName"); //$NON-NLS-1$ + final boolean isDryRun = httpParams.containsKey("isDryRun"); //$NON-NLS-1$ + + final String releaseVersion = getString("releaseVersion", httpParams); //$NON-NLS-1$ + final String developmentVersion = getString("developmentVersion", httpParams); //$NON-NLS-1$ + + // TODO make this nicer by showing a html error page. + // this will throw an exception so control will terminate if the dev + // version is not a "SNAPSHOT". + enforceDeveloperVersion(developmentVersion); + + // get the normal job parameters (adapted from + // hudson.model.ParametersDefinitionProperty._doBuild(StaplerRequest, + // StaplerResponse)) + List values = new ArrayList(); + JSONObject formData = req.getSubmittedForm(); + JSONArray a = JSONArray.fromObject(formData.get("parameter")); + for (Object o : a) { + JSONObject jo = (JSONObject) o; + if (jo != null && !jo.isNullObject()) { + String name = jo.optString("name"); + if (name != null) { + ParameterDefinition d = getParameterDefinition(name); + if (d == null) { + throw new IllegalArgumentException("No such parameter definition: " + name); + } + ParameterValue parameterValue = d.createValue(req, jo); + values.add(parameterValue); + } + } + } + + // if configured, expose the SCM credentails as additional parameters + if (StringUtils.isNotBlank(m2Wrapper.getScmPasswordEnvVar())) { + String scmPasswordVal = StringUtils.isEmpty(scmPassword) ? "" : scmPassword; + values.add(new PasswordParameterValue(m2Wrapper.getScmPasswordEnvVar(), scmPasswordVal)); + } + if (StringUtils.isNotBlank(m2Wrapper.getScmUserEnvVar())) { + String scmUsernameVal = StringUtils.isEmpty(scmUsername) ? "" : scmUsername; + values.add(new StringParameterValue(m2Wrapper.getScmUserEnvVar(), scmUsernameVal)); + } + values.add(new StringParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_RELEASE_VERSION_ENVVAR, releaseVersion)); + values.add(new StringParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_DEV_VERSION_ENVVAR, developmentVersion)); + values.add(new BooleanParameterValue(M2ReleaseBuildWrapper.DescriptorImpl.DEFAULT_DRYRUN_ENVVAR, isDryRun)); + + // schedule release build + ParametersAction parameters = new ParametersAction(values); + + M2ReleaseArgumentsAction arguments = new M2ReleaseArgumentsAction(); + arguments.setDryRun(isDryRun); + + arguments.setReleaseVersion(releaseVersion); + arguments.setDevelopmentVersion(developmentVersion); + // TODO - re-implement versions on specific modules. + + arguments.setCloseNexusStage(closeNexusStage); + arguments.setRepoDescription(repoDescription); + arguments.setScmUsername(scmUsername); + arguments.setScmPassword(scmPassword); + arguments.setScmTagName(scmTag); + arguments.setSubmodules(submodules); + arguments.setScmCommentPrefix(scmCommentPrefix); + arguments.setAppendHusonUserName(appendHusonUserName); + arguments.setHudsonUserName(Hudson.getAuthentication().getName()); + + + if (project.scheduleBuild(0, new ReleaseCause(), parameters, arguments)) { + resp.sendRedirect(req.getContextPath() + '/' + project.getUrl()); + } else { + // redirect to error page. + // TODO try and get this to go back to the form page with an + // error at the top. + resp.sendRedirect(req.getContextPath() + '/' + project.getUrl() + '/' + getUrlName() + "/failed"); + } + } + + /** + * Gets the {@link ParameterDefinition} of the given name, if any. + */ + public ParameterDefinition getParameterDefinition(String name) { + for (ParameterDefinition pd : getParameterDefinitions()) { + if (pd.getName().equals(name)) { + return pd; + } + } + return null; + } + + /** + * returns the value of the key as a String. if multiple values have been + * submitted, the first one will be returned. + * + * @param key + * @param httpParams + * @return + */ + private String getString(String key, Map httpParams) { + return (String) (((Object[]) httpParams.get(key))[0]); + } + + /** + * Enforces that the developer version is actually a developer version and + * ends with "-SNAPSHOT". + * + * @throws IllegalArgumentException + * if the version does not end with "-SNAPSHOT" + */ + private void enforceDeveloperVersion(String version) throws IllegalArgumentException { + if (!version.endsWith("-SNAPSHOT")) { + throw new IllegalArgumentException(String.format(Locale.ENGLISH, "Developer Version (%s) is not a valid version (it must end with \"-SNAPSHOT\")", + version)); + } + } + + private static final List PERMALINKS = Collections.singletonList(LastReleasePermalink.INSTANCE); +} diff --git a/src/main/resources/org/jvnet/hudson/plugins/m2release/M2ReleaseAction/index.jelly b/src/main/resources/org/jvnet/hudson/plugins/m2release/M2ReleaseAction/index.jelly index 99fc31e8..8617ffa8 100644 --- a/src/main/resources/org/jvnet/hudson/plugins/m2release/M2ReleaseAction/index.jelly +++ b/src/main/resources/org/jvnet/hudson/plugins/m2release/M2ReleaseAction/index.jelly @@ -1,84 +1,84 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +