diff --git a/src/main/java/org/jenkins/plugins/lockableresources/LockStepExecution.java b/src/main/java/org/jenkins/plugins/lockableresources/LockStepExecution.java index 776926014..313a4b06f 100644 --- a/src/main/java/org/jenkins/plugins/lockableresources/LockStepExecution.java +++ b/src/main/java/org/jenkins/plugins/lockableresources/LockStepExecution.java @@ -41,25 +41,28 @@ public LockStepExecution(LockStep step, StepContext context) { @Override public boolean start() throws Exception { - step.validate(); - // normally it might raise a exception, but we check it in the function .validate() // therefore we can skip the try-catch here. ResourceSelectStrategy resourceSelectStrategy = ResourceSelectStrategy.valueOf(step.resourceSelectStrategy.toUpperCase(Locale.ENGLISH)); - getContext().get(FlowNode.class).addAction(new PauseAction("Lock")); PrintStream logger = getContext().get(TaskListener.class).getLogger(); Run run = getContext().get(Run.class); - LockableResourcesManager.printLogs("Trying to acquire lock on [" + step + "]", Level.FINE, LOGGER, logger); List resourceHolderList = new ArrayList<>(); - LockableResourcesManager lrm = LockableResourcesManager.get(); List available = null; - LinkedHashMap> resourceNames = new LinkedHashMap<>(); + LinkedHashMap> lockedResources = new LinkedHashMap<>(); + LockableResourcesManager lrm = LockableResourcesManager.get(); synchronized (lrm.syncResources) { + step.validate(); + + LockableResourcesManager.printLogs("Trying to acquire lock on [" + step + "]", Level.FINE, LOGGER, logger); + + getContext().get(FlowNode.class).addAction(new PauseAction("Lock")); + + List resourceNames = new ArrayList<>(); for (LockStepResource resource : step.getResources()) { List resources = new ArrayList<>(); if (resource.resource != null) { @@ -71,10 +74,15 @@ public boolean start() throws Exception { logger); } resources.add(resource.resource); + resourceNames.addAll(resources); + } else { + resourceNames.add("N/A"); } resourceHolderList.add(new LockableResourcesStruct(resources, resource.label, resource.quantity)); } + LockedResourcesBuildAction.addLog(run, resourceNames, "try", step.toString()); + // determine if there are enough resources available to proceed available = lrm.getAvailableResources(resourceHolderList, logger, resourceSelectStrategy); if (available == null || available.isEmpty()) { @@ -95,10 +103,10 @@ public boolean start() throws Exception { // since LockableResource contains transient variables, they cannot be correctly serialized // hence we use their unique resource names and properties for (LockableResource resource : available) { - resourceNames.put(resource.getName(), resource.getProperties()); + lockedResources.put(resource.getName(), resource.getProperties()); } + LockStepExecution.proceed(lockedResources, getContext(), step.toString(), step.variable); } - LockStepExecution.proceed(resourceNames, getContext(), step.toString(), step.variable); return false; } @@ -166,11 +174,12 @@ public static void proceed( } try { - - LockedResourcesBuildAction.updateAction(build, new ArrayList<>(lockedResources.keySet())); + List resourceNames = new ArrayList<>(lockedResources.keySet()); + final String resourceNamesAsString = String.join(",", lockedResources.keySet()); + LockedResourcesBuildAction.addLog(build, resourceNames, "acquired", resourceDescription); PauseAction.endCurrentPause(node); - BodyInvoker bodyInvoker = context.newBodyInvoker() - .withCallback(new Callback(new ArrayList<>(lockedResources.keySet()), resourceDescription)); + BodyInvoker bodyInvoker = + context.newBodyInvoker().withCallback(new Callback(resourceNames, resourceDescription)); if (variable != null && !variable.isEmpty()) { // set the variable for the duration of the block bodyInvoker.withContext( @@ -180,8 +189,7 @@ public static void proceed( @Override public void expand(@NonNull EnvVars env) { final LinkedHashMap variables = new LinkedHashMap<>(); - final String resourceNames = String.join(",", lockedResources.keySet()); - variables.put(variable, resourceNames); + variables.put(variable, resourceNamesAsString); int index = 0; for (Entry> lockResourceEntry : lockedResources.entrySet()) { @@ -222,9 +230,11 @@ private static final class Callback extends BodyExecutionCallback.TailCall { @Override protected void finished(StepContext context) throws Exception { - LockableResourcesManager.get().unlockNames(this.resourceNames, context.get(Run.class)); + Run build = context.get(Run.class); + LockedResourcesBuildAction.addLog(build, this.resourceNames, "released", this.resourceDescription); + LockableResourcesManager.get().unlockNames(this.resourceNames, build); LockableResourcesManager.printLogs( - "Lock released on resource [" + resourceDescription + "]", + "Lock released on resource [" + this.resourceDescription + "]", Level.FINE, LOGGER, context.get(TaskListener.class).getLogger()); diff --git a/src/main/java/org/jenkins/plugins/lockableresources/LockableResource.java b/src/main/java/org/jenkins/plugins/lockableresources/LockableResource.java index cbe20dab4..509f8abb8 100644 --- a/src/main/java/org/jenkins/plugins/lockableresources/LockableResource.java +++ b/src/main/java/org/jenkins/plugins/lockableresources/LockableResource.java @@ -494,14 +494,18 @@ public String getLockCauseDetail() { return build; } + // --------------------------------------------------------------------------- @Exported public String getBuildName() { if (getBuild() != null) return getBuild().getFullDisplayName(); else return null; } + // --------------------------------------------------------------------------- public void setBuild(@Nullable Run lockedBy) { + this.build = lockedBy; + if (lockedBy != null) { this.buildExternalizableId = lockedBy.getExternalizableId(); setReservedTimestamp(new Date()); diff --git a/src/main/java/org/jenkins/plugins/lockableresources/LockableResourcesManager.java b/src/main/java/org/jenkins/plugins/lockableresources/LockableResourcesManager.java index 71a8bdb52..94dddd59e 100644 --- a/src/main/java/org/jenkins/plugins/lockableresources/LockableResourcesManager.java +++ b/src/main/java/org/jenkins/plugins/lockableresources/LockableResourcesManager.java @@ -41,6 +41,7 @@ import jenkins.util.SystemProperties; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; +import org.jenkins.plugins.lockableresources.actions.LockedResourcesBuildAction; import org.jenkins.plugins.lockableresources.queue.LockableResourcesStruct; import org.jenkins.plugins.lockableresources.queue.QueuedContextStruct; import org.jenkins.plugins.lockableresources.util.Constants; @@ -106,9 +107,10 @@ public List getReadOnlyResources() { // --------------------------------------------------------------------------- /** Get declared resources, means only defined in config file (xml or JCaC yaml). */ + @Restricted(NoExternalUse.class) public List getDeclaredResources() { ArrayList declaredResources = new ArrayList<>(); - for (LockableResource r : this.getReadOnlyResources()) { + for (LockableResource r : this.getResources()) { if (!r.isEphemeral() && !r.isNodeResource()) { declaredResources.add(r); } @@ -165,7 +167,7 @@ public void setDeclaredResources(List declaredResources) { @Restricted(NoExternalUse.class) public List getResourcesFromProject(String fullName) { List matching = new ArrayList<>(); - for (LockableResource r : this.getReadOnlyResources()) { + for (LockableResource r : this.getResources()) { String rName = r.getQueueItemProject(); if (rName != null && rName.equals(fullName)) { matching.add(r); @@ -174,20 +176,6 @@ public List getResourcesFromProject(String fullName) { return matching; } - // --------------------------------------------------------------------------- - /** Get all resources used by build. */ - @Restricted(NoExternalUse.class) - public List getResourcesFromBuild(Run build) { - List matching = new ArrayList<>(); - for (LockableResource r : this.getReadOnlyResources()) { - Run rBuild = r.getBuild(); - if (rBuild != null && rBuild == build) { - matching.add(r); - } - } - return matching; - } - // --------------------------------------------------------------------------- /** * Check if the label is valid. Valid in this context means, if is configured on someone resource. @@ -198,9 +186,11 @@ public Boolean isValidLabel(@Nullable String label) { return false; } - for (LockableResource r : this.getReadOnlyResources()) { - if (r != null && r.isValidLabel(label)) { - return true; + synchronized (this.syncResources) { + for (LockableResource r : this.getResources()) { + if (r != null && r.isValidLabel(label)) { + return true; + } } } @@ -326,8 +316,10 @@ public LockableResource fromName(@CheckForNull String resourceName) { if (resourceName != null) { - for (LockableResource r : this.getReadOnlyResources()) { - if (resourceName.equals(r.getName())) return r; + synchronized (this.syncResources) { + for (LockableResource r : this.getResources()) { + if (resourceName.equals(r.getName())) return r; + } } } else { LOGGER.warning("Internal failure, fromName is empty or null:" + getStack()); @@ -590,47 +582,51 @@ public boolean lock( // --------------------------------------------------------------------------- /** Try to lock the resource and return true if locked. */ - public boolean lock(List resources, Run build) { + public boolean lock(List resourcesToLock, Run build) { - LOGGER.fine("lock it: " + resources + " for build " + build); + LOGGER.fine("lock it: " + resourcesToLock + " for build " + build); if (build == null) { - LOGGER.warning("lock() will fails, because the build does not exits. " + resources); + LOGGER.warning("lock() will fails, because the build does not exits. " + resourcesToLock); return false; // not locked } - String cause = getCauses(resources); + String cause = getCauses(resourcesToLock); if (!cause.isEmpty()) { LOGGER.warning("lock() for build " + build + " will fails, because " + cause); return false; // not locked } - for (LockableResource r : resources) { + for (LockableResource r : resourcesToLock) { r.unqueue(); r.setBuild(build); } + LockedResourcesBuildAction.findAndInitAction(build).addUsedResources(getResourcesNames(resourcesToLock)); + save(); return true; } // --------------------------------------------------------------------------- - private void freeResources(List unlockResources, @Nullable Run build) { + private void freeResources(List unlockResources, Run build) { LOGGER.fine("free it: " + unlockResources); // make sure there is a list of resource names to unlock - if (unlockResources == null || unlockResources.isEmpty()) { + if (unlockResources == null || unlockResources.isEmpty() || build == null) { return; } List toBeRemoved = new ArrayList<>(); + for (LockableResource resource : unlockResources) { // No more contexts, unlock resource - if (build != null && build != resource.getBuild()) { - continue; // this happens, when you push the unlock button in LRM page - } + + // the resource has been currently unlocked (like by LRM page - button unlock, or by API) + if (!build.equals(resource.getBuild())) continue; + resource.unqueue(); resource.setBuild(null); uncacheIfFreeing(resource, true, false); @@ -640,43 +636,53 @@ private void freeResources(List unlockResources, @Nullable Run toBeRemoved.add(resource); } } + + LockedResourcesBuildAction.findAndInitAction(build).removeUsedResources(getResourcesNames(unlockResources)); + // remove all ephemeral resources removeResources(toBeRemoved); } - // --------------------------------------------------------------------------- - @Deprecated - @ExcludeFromJacocoGeneratedReport - public void unlock(List resourcesToUnLock, @Nullable Run build) { - List resourceNamesToUnLock = LockableResourcesManager.getResourcesNames(resourcesToUnLock); - this.unlockNames(resourceNamesToUnLock, build); - } + public void unlockBuild(@Nullable Run build) { - // --------------------------------------------------------------------------- - @Deprecated - @ExcludeFromJacocoGeneratedReport - public void unlock( - @Nullable List resourcesToUnLock, @Nullable Run build, boolean inversePrecedence) { - unlock(resourcesToUnLock, build); - } + if (build == null) { + return; + } - @Deprecated - @ExcludeFromJacocoGeneratedReport - public void unlockNames( - @Nullable List resourceNamesToUnLock, @Nullable Run build, boolean inversePrecedence) { - this.unlockNames(resourceNamesToUnLock, build); + List resourcesInUse = + LockedResourcesBuildAction.findAndInitAction(build).getCurrentUsedResourceNames(); + + if (resourcesInUse.size() == 0) { + return; + } + unlockNames(resourcesInUse, build); } + // --------------------------------------------------------------------------- @SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "not sure which exceptions might be catch.") - public void unlockNames(@Nullable List resourceNamesToUnLock, @Nullable Run build) { + public void unlockNames(@Nullable List resourceNamesToUnLock, Run build) { // make sure there is a list of resource names to unlock if (resourceNamesToUnLock == null || resourceNamesToUnLock.isEmpty()) { return; } + synchronized (this.syncResources) { + unlockResources(this.fromNames(resourceNamesToUnLock), build); + } + } + // --------------------------------------------------------------------------- + public void unlockResources(List resourcesToUnLock) { + unlockResources(resourcesToUnLock, resourcesToUnLock.get(0).getBuild()); + } + + // --------------------------------------------------------------------------- + public void unlockResources(List resourcesToUnLock, Run build) { + if (resourcesToUnLock == null || resourcesToUnLock.isEmpty()) { + return; + } synchronized (this.syncResources) { - this.freeResources(this.fromNames(resourceNamesToUnLock), build); + this.freeResources(resourcesToUnLock, build); while (proceedNextContext()) { // process as many contexts as possible @@ -913,8 +919,7 @@ public boolean steal(List resources, String userName) { r.setReservedBy(userName); r.setStolen(); } - unlock(resources, null, false); - // unlock() nulls resource.reservedTimestamp via resource.setBuild(null), so set it afterwards + unlockResources(resources); Date date = new Date(); for (LockableResource r : resources) { r.setReservedTimestamp(date); @@ -999,7 +1004,7 @@ public void recycle(List resources) { synchronized (this.syncResources) { // Not calling reset() because that also un-queues the resource // and we want to proclaim it is usable (if anyone is waiting) - this.unlock(resources, null); + this.unlockResources(resources); this.unreserve(resources); } } diff --git a/src/main/java/org/jenkins/plugins/lockableresources/actions/LockableResourcesRootAction.java b/src/main/java/org/jenkins/plugins/lockableresources/actions/LockableResourcesRootAction.java index 45ffd3137..269928c94 100644 --- a/src/main/java/org/jenkins/plugins/lockableresources/actions/LockableResourcesRootAction.java +++ b/src/main/java/org/jenkins/plugins/lockableresources/actions/LockableResourcesRootAction.java @@ -521,7 +521,7 @@ public void doUnlock(StaplerRequest req, StaplerResponse rsp) throws IOException return; } - LockableResourcesManager.get().unlock(resources, null); + LockableResourcesManager.get().unlockResources(resources); rsp.forwardToPreviousPage(req); } diff --git a/src/main/java/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction.java b/src/main/java/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction.java index 470421fc3..dd3f9054d 100644 --- a/src/main/java/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction.java +++ b/src/main/java/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction.java @@ -1,20 +1,11 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright (c) 2013, 6WIND S.A. All rights reserved. * - * * - * This file is part of the Jenkins Lockable Resources Plugin and is * - * published under the MIT license. * - * * - * See the "LICENSE.txt" file for more information. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ package org.jenkins.plugins.lockableresources.actions; import hudson.model.Action; import hudson.model.Run; import java.util.ArrayList; -import java.util.Collection; +import java.util.Collections; +import java.util.Date; import java.util.List; -import org.jenkins.plugins.lockableresources.LockableResource; -import org.jenkins.plugins.lockableresources.LockableResourcesManager; import org.jenkins.plugins.lockableresources.Messages; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -27,18 +18,13 @@ @Restricted(NoExternalUse.class) public class LockedResourcesBuildAction implements Action { - // ------------------------------------------------------------------------- - private final List lockedResources; + private static final long serialVersionUID = 1L; - // ------------------------------------------------------------------------- - public LockedResourcesBuildAction(List lockedResources) { - this.lockedResources = lockedResources; - } + private List logs = new ArrayList<>(); + private final transient Object syncLogs = new Object(); + private List resourcesInUse = new ArrayList<>(); - // ------------------------------------------------------------------------- - public List getLockedResources() { - return lockedResources; - } + public LockedResourcesBuildAction() {} // ------------------------------------------------------------------------- @Override @@ -58,107 +44,105 @@ public String getUrlName() { return "locked-resources"; } - // ------------------------------------------------------------------------- - /** Adds *resourceNames* to *build*. - * When the action does not exists, will be created as well. - * When the resource has been used by this build just now, the counter will - * increased to eliminate multiple entries. - * Used in pipelines - lock() step - */ - @Restricted(NoExternalUse.class) - public static void updateAction(Run build, List resourceNames) { - LockedResourcesBuildAction action = build.getAction(LockedResourcesBuildAction.class); + public List getCurrentUsedResourceNames() { + return resourcesInUse; + } - if (action == null) { - List resPojos = new ArrayList<>(); - action = new LockedResourcesBuildAction(resPojos); - build.addAction(action); + public void addUsedResources(List resourceNames) { + synchronized (resourcesInUse) { + resourcesInUse.addAll(resourceNames); } + } - for (String name : resourceNames) { - LockableResource r = LockableResourcesManager.get().fromName(name); - if (r != null) { - action.add(new ResourcePOJO(r)); + public void removeUsedResources(List resourceNames) { + synchronized (resourcesInUse) { + resourcesInUse.removeAll(resourceNames); + } + } + + public static LockedResourcesBuildAction findAndInitAction(final Run build) { + if (build == null) { + return null; + } + LockedResourcesBuildAction action; + synchronized (build) { + List actions = build.getActions(LockedResourcesBuildAction.class); + + if (actions.size() <= 0) { + action = new LockedResourcesBuildAction(); + build.addAction(action); } else { - // probably a ephemeral resource has been deleted - action.add(new ResourcePOJO(name, "")); + action = actions.get(0); } } + return action; } - // ------------------------------------------------------------------------- - /** Add the resource to build action.*/ - @Restricted(NoExternalUse.class) - // since the list *this.lockedResources* might be updated from multiple (parallel) - // stages, this operation need to be synchronized - private synchronized void add(ResourcePOJO r) { - for (ResourcePOJO pojo : this.lockedResources) { - if (pojo.getName().equals(r.getName())) { - pojo.inc(); - return; - } + public static void addLog( + final Run build, final List resourceNames, final String step, final String action) { + + for (String resourceName : resourceNames) addLog(build, resourceName, step, action); + } + + public static void addLog( + final Run build, final String resourceName, final String step, final String action) { + + LockedResourcesBuildAction buildAction = findAndInitAction(build); + + buildAction.addLog(resourceName, step, action); + } + + public void addLog(final String resourceName, final String step, final String action) { + + synchronized (this.logs) { + this.logs.add(new LogEntry(step, action, resourceName)); } - this.lockedResources.add(r); } - // ------------------------------------------------------------------------- - /** Create action from resources. - * Used in free-style projects. - */ @Restricted(NoExternalUse.class) - public static LockedResourcesBuildAction fromResources(Collection resources) { - List resPojos = new ArrayList<>(); - for (LockableResource r : resources) { - if (r != null) { - resPojos.add(new ResourcePOJO(r)); - } + public List getReadOnlyLogs() { + synchronized (this.logs) { + return new ArrayList<>(Collections.unmodifiableCollection(this.logs)); } - return new LockedResourcesBuildAction(resPojos); } - // ------------------------------------------------------------------------- - public static class ResourcePOJO { - - // --------------------------------------------------------------------- - private String name; - private String description; - private int count = 1; + public static class LogEntry { - // --------------------------------------------------------------------- - public ResourcePOJO(String name, String description) { - this.name = name; - this.description = description; - } + private String step; + private String action; + private String resourceName; + private long timeStamp; - // --------------------------------------------------------------------- - public ResourcePOJO(LockableResource r) { - this.name = r.getName(); - this.description = r.getDescription(); + @Restricted(NoExternalUse.class) + public LogEntry(final String step, final String action, final String resourceName) { + this.step = step; + this.action = action; + this.resourceName = resourceName; + this.timeStamp = new Date().getTime(); } // --------------------------------------------------------------------- + @Restricted(NoExternalUse.class) public String getName() { - return this.name; + return this.resourceName; } // --------------------------------------------------------------------- - public String getDescription() { - return this.description; + @Restricted(NoExternalUse.class) + public String getStep() { + return this.step; } // --------------------------------------------------------------------- - /** Return the counter, how many was / is the resource used in the build. - * Example: you can use the lock() function in parallel stages for the - * same resource. - */ - public int getCounter() { - return this.count; + @Restricted(NoExternalUse.class) + public String getAction() { + return this.action; } // --------------------------------------------------------------------- - /** Increment counter */ - public void inc() { - this.count++; + @Restricted(NoExternalUse.class) + public Date getTimeStamp() { + return new Date(this.timeStamp); } } } diff --git a/src/main/java/org/jenkins/plugins/lockableresources/queue/LockRunListener.java b/src/main/java/org/jenkins/plugins/lockableresources/queue/LockRunListener.java index 8d0063625..caceece3e 100644 --- a/src/main/java/org/jenkins/plugins/lockableresources/queue/LockRunListener.java +++ b/src/main/java/org/jenkins/plugins/lockableresources/queue/LockRunListener.java @@ -24,7 +24,6 @@ import org.jenkins.plugins.lockableresources.LockableResource; import org.jenkins.plugins.lockableresources.LockableResourceProperty; import org.jenkins.plugins.lockableresources.LockableResourcesManager; -import org.jenkins.plugins.lockableresources.actions.LockedResourcesBuildAction; import org.jenkins.plugins.lockableresources.actions.ResourceVariableNameAction; @Extension @@ -44,6 +43,7 @@ public void onStarted(Run build, TaskListener listener) { synchronized (lrm.syncResources) { Job proj = Utils.getProject(build); List required = new ArrayList<>(); + LockableResourcesStruct resources = Utils.requiredResources(proj); if (resources != null) { @@ -56,7 +56,7 @@ public void onStarted(Run build, TaskListener listener) { } if (lrm.lock(required, build)) { - build.addAction(LockedResourcesBuildAction.fromResources(required)); + // build.addAction(LockedResourcesBuildAction.fromResources(required)); listener.getLogger().printf("%s acquired lock on %s%n", LOG_PREFIX, required); LOGGER.info(build.getFullDisplayName() + " acquired lock on " + required); if (resources.requiredVar != null) { @@ -97,20 +97,8 @@ public void onCompleted(Run build, @NonNull TaskListener listener) { // Skip unlocking for multiple configuration projects, // only the child jobs will actually unlock resources. if (build instanceof MatrixBuild) return; - - LockableResourcesManager lrm = LockableResourcesManager.get(); - synchronized (lrm.syncResources) { - // obviously project name cannot be obtained here - List required = lrm.getResourcesFromBuild(build); - if (!required.isEmpty()) { - lrm.unlock(required, build); - listener.getLogger().printf("%s released lock on %s%n", LOG_PREFIX, required); - LOGGER.info(build.getFullDisplayName() - + " released lock on " - + required - + ", because the build has been finished."); - } - } + LOGGER.info(build.getFullDisplayName()); + LockableResourcesManager.get().unlockBuild(build); } @Override @@ -118,16 +106,7 @@ public void onDeleted(Run build) { // Skip unlocking for multiple configuration projects, // only the child jobs will actually unlock resources. if (build instanceof MatrixBuild) return; - LockableResourcesManager lrm = LockableResourcesManager.get(); - synchronized (lrm.syncResources) { - List required = lrm.getResourcesFromBuild(build); - if (!required.isEmpty()) { - lrm.unlock(required, build); - LOGGER.warning(build.getFullDisplayName() - + " released lock on " - + required - + ", because the build has been deleted."); - } - } + LOGGER.info(build.getFullDisplayName()); + LockableResourcesManager.get().unlockBuild(build); } } diff --git a/src/main/resources/org/jenkins/plugins/lockableresources/Messages.properties b/src/main/resources/org/jenkins/plugins/lockableresources/Messages.properties index 195b34781..4ea8e98b0 100644 --- a/src/main/resources/org/jenkins/plugins/lockableresources/Messages.properties +++ b/src/main/resources/org/jenkins/plugins/lockableresources/Messages.properties @@ -23,7 +23,7 @@ LockableResourcesRootAction.ViewPermission.Description=This permission grants th LockableResourcesRootAction.QueueChangeOrderPermission=Queue LockableResourcesRootAction.QueueChangeOrderPermission.Description=This permission grants the ability to \ manually manipulate the lockable resources queue.. -LockedResourcesBuildAction.displayName=Used lockable resources +LockedResourcesBuildAction.displayName=Lockable resources # Java errors error.labelDoesNotExist=The resource label does not exist: {0}. error.resourceDoesNotExist=The resource does not exist: {0}. diff --git a/src/main/resources/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction/index.jelly b/src/main/resources/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction/index.jelly index 0cace6df6..b570e6c7c 100644 --- a/src/main/resources/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction/index.jelly +++ b/src/main/resources/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction/index.jelly @@ -52,26 +52,43 @@ THE SOFTWARE.
+ + + - - - + + - - - + + + + diff --git a/src/main/resources/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction/index.properties b/src/main/resources/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction/index.properties index 7ae8bdb15..3574b830c 100644 --- a/src/main/resources/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction/index.properties +++ b/src/main/resources/org/jenkins/plugins/lockableresources/actions/LockedResourcesBuildAction/index.properties @@ -20,10 +20,12 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -app.bar.used.resources=Used lockable resources +app.bar.used.resources=Lockable resources app.bar.resources=Lockable resources table.column.index=Index table.column.name=Resource Name -table.column.description=Description -table.column.counter=Counter +table.column.step=Step +table.column.timeStamp=Timestamp +table.column.action=Action +table.settings.page.length.all=ALL diff --git a/src/test/java/org/jenkins/plugins/lockableresources/LockStepTest.java b/src/test/java/org/jenkins/plugins/lockableresources/LockStepTest.java index 0bd111b95..60d6770aa 100644 --- a/src/test/java/org/jenkins/plugins/lockableresources/LockStepTest.java +++ b/src/test/java/org/jenkins/plugins/lockableresources/LockStepTest.java @@ -759,16 +759,22 @@ public void unlockButtonWithWaitingRuns() throws Exception { testHelpers.clickButton("unlock", "resource1"); } + LOGGER.info("wait for 1 " + rNext); j.waitForMessage("Trying to acquire lock on [Resource: resource1]", rNext); + + LOGGER.info("wait sem 1 " + rNext); SemaphoreStep.waitForStart("wait-inside/" + (i + 1), rNext); + LOGGER.info("is paused 1 " + rNext); isPaused(rNext, 1, 0); if (prevBuild != null) { + LOGGER.info("wait sem 2" + rNext); SemaphoreStep.success("wait-inside/" + i, null); j.assertBuildStatusSuccess(j.waitForCompletion(prevBuild)); } prevBuild = rNext; } + LOGGER.info("wait sem 3"); SemaphoreStep.success("wait-inside/3", null); j.assertBuildStatusSuccess(j.waitForCompletion(prevBuild)); } @@ -1713,12 +1719,10 @@ public void inversePrecedenceAndPriorityAreSet() throws Exception { LockableResourcesManager.get().createResourceWithLabel("resource1", "label1"); WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "lock(label: 'label1', inversePrecedence: true, priority: -1000000000, resourceSelectStrategy: '') {}", - true)); + "lock(label: 'label1', inversePrecedence: true, priority: -1000000000) {}", true)); WorkflowRun b1 = p.scheduleBuild2(0).waitForStart(); j.assertBuildStatus(Result.FAILURE, j.waitForCompletion(b1)); j.assertLogContains("The \"inverse precedence\" option is not compatible with \"queue priority\" option!", b1); - isPaused(b1, 0, 0); } @Test diff --git a/src/test/java/org/jenkins/plugins/lockableresources/PressureTest.java b/src/test/java/org/jenkins/plugins/lockableresources/PressureTest.java index a053655d6..7ea057cc0 100644 --- a/src/test/java/org/jenkins/plugins/lockableresources/PressureTest.java +++ b/src/test/java/org/jenkins/plugins/lockableresources/PressureTest.java @@ -31,7 +31,7 @@ public class PressureTest extends LockStepTestBase { @WithTimeout(900) public void pressureEnableSave() throws Exception { // keep in mind, that the windows nodes at jenkins-infra are not very fast - pressure(Functions.isWindows() ? 5 : 10); + pressure(Functions.isWindows() ? 10 : 10); } @Test @@ -39,12 +39,12 @@ public void pressureEnableSave() throws Exception { public void pressureDisableSave() throws Exception { System.setProperty(Constants.SYSTEM_PROPERTY_DISABLE_SAVE, "true"); // keep in mind, that the windows nodes at jenkins-infra are not very fast - pressure(Functions.isWindows() ? 5 : 10); + pressure(Functions.isWindows() ? 10 : 10); } public void pressure(final int resourcesCount) throws Exception { // count of parallel jobs - final int jobsCount = (resourcesCount / 2) + 1; + final int jobsCount = (resourcesCount * 2) + 1; final int nodesCount = (resourcesCount / 10) + 1; // enable node mirroring to make more chaos System.setProperty(Constants.SYSTEM_PROPERTY_ENABLE_NODE_MIRROR, "true");
${%table.column.index}${%table.column.timeStamp}${%table.column.action}${%table.column.step} ${%table.column.name}${%table.column.description}${%table.column.counter}
${idx.index + 1}${resource.name}${resource.description}${resource.counter} + + ${loEntry.action}${loEntry.step}${loEntry.name}