Index: src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseAction.java =================================================================== --- src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseAction.java (revision 19178) +++ src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseAction.java (working copy) @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2009, NDS Group Ltd., James Nord - * + * * 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 @@ -23,10 +23,14 @@ */ package org.jvnet.hudson.plugins.m2release; +import hudson.FilePath; import hudson.maven.MavenModule; import hudson.maven.MavenModuleSet; import hudson.model.Action; import hudson.model.Cause; +import hudson.model.Computer; +import hudson.model.Hudson; +import hudson.scm.SCM; import java.io.IOException; import java.util.Collection; @@ -41,7 +45,7 @@ /** * 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 * @version 0.2 */ @@ -64,7 +68,7 @@ if (M2ReleaseBuildWrapper.hasReleasePermission(project)) { return "installer.gif"; //$NON-NLS-1$ } - // by returning null the link will not be shown. + // by returning null the link will not be shown. return null; } @@ -76,11 +80,11 @@ public Collection getModules() { return project.getModules(); } - + public String computeReleaseVersion(String version) { return version.replace("-SNAPSHOT", ""); } - + public String computeNextVersion(String version) { /// XXX would be nice to use maven to do this... String retVal = computeReleaseVersion(version); @@ -102,7 +106,7 @@ } return retVal + "-SNAPSHOT"; } - + public void doSubmit(StaplerRequest req, StaplerResponse resp) throws IOException, ServletException { M2ReleaseBuildWrapper.checkReleasePermission(project); M2ReleaseBuildWrapper m2Wrapper = project.getBuildWrappers().get(M2ReleaseBuildWrapper.class); @@ -122,14 +126,17 @@ } } } - + // schedule release build synchronized (m2Wrapper) { + m2Wrapper.setInitPending(true); if (project.scheduleBuild(0, new Cause.UserCause())) { m2Wrapper.enableRelease(); m2Wrapper.setVersions(versions); m2Wrapper.setAppendHudsonBuildNumber(appendHudsonBuildNumber); } + m2Wrapper.setInitPending(false); + m2Wrapper.notifyAll(); } // redirect to status page resp.sendRedirect(project.getAbsoluteUrl()); Index: src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseBuildWrapper.java =================================================================== --- src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseBuildWrapper.java (revision 19178) +++ src/main/java/org/jvnet/hudson/plugins/m2release/M2ReleaseBuildWrapper.java (working copy) @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2009, NDS Group Ltd., James Nord - * + * * 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 @@ -24,6 +24,7 @@ package org.jvnet.hudson.plugins.m2release; import hudson.Extension; +import hudson.FilePath; import hudson.Launcher; import hudson.maven.AbstractMavenProject; import hudson.maven.MavenBuild; @@ -35,18 +36,24 @@ import hudson.model.Action; import hudson.model.BuildListener; import hudson.model.Item; +import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.model.listeners.RunListener; +import hudson.scm.SCM; import hudson.tasks.BuildWrapper; import hudson.tasks.BuildWrapperDescriptor; +import java.io.File; import java.io.IOException; +import java.lang.reflect.Field; import java.util.Map; import org.kohsuke.stapler.DataBoundConstructor; /** - * Wraps a {@link MavenBuild} to be able to run the + * Wraps a {@link MavenBuild} to be able to run the * maven release plugin on demand. - * + * * @author James Nord * @version 0.2 * @since 0.1 @@ -56,6 +63,7 @@ private transient boolean doRelease = false; private transient Map versions; private transient boolean appendHudsonBuildNumber; + private transient boolean initPending = false; public String releaseGoals = DescriptorImpl.DEFAULT_RELEASE_GOALS; @@ -70,42 +78,36 @@ public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { - if (!doRelease) { + synchronized (this) { + while (initPending) { + wait(); + } + } + + if (!doRelease) { // we are not performing a release so don't need a custom tearDown. return new Environment() { /** intentionally blank */ }; } - // reset for the next build. - doRelease = false; + doRelease = false; - // TODO do we need to set the goals back? + if (versions != null && versions.size() > 0) { + // Just use first version if multiple... + build.setDescription("Release " + versions.values().iterator().next()); + } + + // Store the original goal so it can be set back (builds share the same project instance) final String originalGoals; - if (build instanceof MavenBuild) { - MavenBuild m2Build = (MavenBuild) build; - MavenModule mm = m2Build.getProject(); - MavenModuleSet mmSet = mm.getParent(); - originalGoals = mmSet.getGoals(); - mmSet.setGoals(releaseGoals); - if (versions != null) { - mmSet.setGoals(generateVersionString(build.getNumber()) + releaseGoals); - } - else { - mmSet.setGoals(releaseGoals); - } - } - else if (build instanceof MavenModuleSetBuild) { - MavenModuleSetBuild m2moduleSetBuild = (MavenModuleSetBuild) build; - MavenModuleSet mmSet = m2moduleSetBuild.getProject(); - originalGoals = mmSet.getGoals(); + MavenModuleSet mmSet = getModuleSet(build); + if (mmSet != null) { + originalGoals = mmSet.getGoals(); if (versions != null) { mmSet.setGoals(generateVersionString(build.getNumber()) + releaseGoals); - } - else { + } else { mmSet.setGoals(releaseGoals); } - } - else { + } else { originalGoals = null; } @@ -115,24 +117,33 @@ public boolean tearDown(AbstractBuild bld, BuildListener lstnr) throws IOException, InterruptedException { // TODO only re-set the build goals if they are still releaseGoals to avoid mid-air collisions. - if (bld instanceof MavenBuild) { - MavenBuild m2Build = (MavenBuild) bld; - MavenModule mm = m2Build.getProject(); - MavenModuleSet mmSet = mm.getParent(); + MavenModuleSet mmSet = getModuleSet(bld); + if (mmSet != null) { mmSet.setGoals(originalGoals); } - else if (bld instanceof MavenModuleSetBuild) { - MavenModuleSetBuild m2moduleSetBuild = (MavenModuleSetBuild) bld; - MavenModuleSet mmSet = m2moduleSetBuild.getProject(); - mmSet.setGoals(originalGoals); - } - versions = null; + versions = null; return true; } }; } + private MavenModuleSet getModuleSet(AbstractBuild build) { + if (build instanceof MavenBuild) { + MavenBuild m2Build = (MavenBuild) build; + MavenModule mm = m2Build.getProject(); + MavenModuleSet mmSet = mm.getParent(); + return mmSet; + } else if (build instanceof MavenModuleSetBuild) { + MavenModuleSetBuild m2moduleSetBuild = (MavenModuleSetBuild) build; + MavenModuleSet mmSet = m2moduleSetBuild.getProject(); + return mmSet; + } else { + return null; + } + } + + void enableRelease() { doRelease = true; } @@ -175,11 +186,51 @@ job.checkPermission(Item.BUILD); } - @Extension + + public void setInitPending(boolean initPending) { + this.initPending = initPending; + } + + @Extension + public static class ReleaseBuildListener extends RunListener { + + public ReleaseBuildListener() { + super(AbstractBuild.class); + } + + @Override + public void onStarted(AbstractBuild r, TaskListener listener) { + AbstractProject project = r.getProject(); + if (!(project instanceof MavenModuleSet)) { + return; + } + M2ReleaseBuildWrapper m2Wrapper = ((MavenModuleSet) project).getBuildWrappers().get(M2ReleaseBuildWrapper.class); + if (m2Wrapper == null) { + return; + } + if (!m2Wrapper.doRelease) { + return; + } + + try { + // Wipe out workspace. Could be optional, but there shouldn't be any reason to not want it cleared. + FilePath workspace = r.getProject().getWorkspace(); + r.getProject().getScm().processWorkspaceBeforeDeletion(r.getProject(), workspace, r.getBuiltOn()); + // TODO: is this a proper way to wipe out the workspace? + workspace.deleteRecursive(); + } catch (IOException e) { + listener.error("Problem deleting workspace: " + e.toString()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); /// Preserve interrupted state + } + } + } + + @Extension public static class DescriptorImpl extends BuildWrapperDescriptor { - - public static final String DEFAULT_RELEASE_GOALS = "-Dresume=false release:prepare release:perform"; //$NON-NLS-1$ + public static final String DEFAULT_RELEASE_GOALS = "-Dresume=false release:prepare release:perform"; //$NON-NLS-1$ + public DescriptorImpl() { super(M2ReleaseBuildWrapper.class); // load();