Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove idle executors from widget #9177

Merged
merged 13 commits into from
Jun 18, 2024
286 changes: 176 additions & 110 deletions core/src/main/resources/lib/hudson/executors.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -33,130 +33,196 @@ THE SOFTWARE.
</st:documentation>
<d:taglib uri="local">
<d:tag name="computerCaption">

<a href="${rootURL}/${c.url}" class="jenkins-link--with-icon model-link inside"><l:icon src="${c.iconClassName}" alt="${altText}"/>
<span style="margin-left: 1ch;">${title}</span>
</a>
<span style="float: right; font-weight: normal;">
<j:if test="${c.offline}">
<j:choose>
<j:when test="${c.offlineCause!=null and !c.connecting}">
(<img src="${imagesURL}/svgs/error.svg" width="16" height="16" title="${c.offlineCause}"/> ${%offline})
</j:when>
<j:when test="${c.connecting}">
(<l:icon src="symbol-hourglass" class="icon-sm"/>${%launching})
</j:when>
<j:otherwise>
(${%offline})
</j:otherwise>
</j:choose>
</j:if>
<j:if test="${!c.acceptingTasks}"> <st:nbsp/> (${%suspended})</j:if>
</span>
</d:tag>
<d:tag name="executor">
<j:if test="${!c.offline or (c.offline and !e.idle)}">
<tr>
<td class="pane" align="right" style="vertical-align: top">
${name}
</td>
<j:choose>
<j:when test="${c.offline}">
<j:choose>
<j:when test="${e.idle}">
<td class="pane">
<j:choose>
<j:when test="${c.offline}">
<a href="${rootURL}/${c.url}" class="model-link inside">${%Offline}</a>
</j:when>
<j:otherwise>
${%Idle}
</j:otherwise>
</j:choose>
</td>
<td class="pane"/>
<td class="pane"/>
<j:when test="${c.offlineCause!=null and !c.connecting}">
<div>
(<l:icon src="symbol-error" class="icon-xs jenkins-!-error-color" title="${c.offlineCause}"/> ${%offline})
</div>
</j:when>
<j:when test="${c.connecting}">
<div>(<l:icon src="symbol-hourglass" class="icon-xs"/>${%launching})</div>
</j:when>
<j:otherwise>
<!-- not actually optional, but it helps with backward compatibility -->
<j:set var="executor" value="${e}" />
<st:include it="${e.currentExecutable}" page="executorCell.jelly" optional="true">
<td class="pane">
<div style="white-space: normal">
<j:set var="exe" value="${e.currentExecutable}" />
<j:set var="wu" value="${e.currentWorkUnit}" />
<j:choose>
<j:when test="${exe == null and wu != null}">
<j:set var="exeparent" value="${wu.work}"/>
<j:choose>
<j:when test="${h.hasPermission(exeparent,exeparent.READ)}">
<a href="${rootURL}/${exeparent.url}"><l:breakable value="${exeparent.fullDisplayName}"/></a>
<t:progressBar tooltip="${%Pending}" pos="-1" href="${rootURL}/${exeparent.url}"/>
</j:when>
<j:otherwise>
<span>${%Unknown Task}</span>
</j:otherwise>
</j:choose>
</j:when>
<j:when test="${exe == null and wu == null}">
<!-- went idle concurrent with testing for idle -->
${%Idle}
</j:when>
<j:otherwise>
<j:invokeStatic var="exeparent"
className="hudson.model.queue.Executables" method="getParentOf">
<j:arg type="hudson.model.Queue$Executable" value="${exe}" />
</j:invokeStatic>
<j:choose>
<j:when test="${h.hasPermission(exeparent,exeparent.READ)}">
<a href="${rootURL}/${exeparent.url}"><l:breakable value="${exeparent.fullDisplayName}"/></a>
<t:buildProgressBar build="${exe}" executor="${executor}"/>
</j:when>
<j:otherwise>
<span>${%Unknown Task}</span>
</j:otherwise>
</j:choose>
</j:otherwise>
</j:choose>
</div>
</td>
<td class="pane">
<j:if test="${h.hasPermission(exeparent,exeparent.READ)}">
<a href="${rootURL}/${exe.url}" class="model-link inside" style="display: block;"><l:breakable value="${exe.displayName}"/></a>
</j:if>
</td>
</st:include>
<td class="pane" align="center" valign="middle">
<j:if test="${h.hasPermission(exeparent,exeparent.READ) and e.hasStopPermission()}">
<l:stopButton href="${rootURL}/${c.url}${url}/stopBuild?runExtId=${h.urlEncode(exe.externalizableId)}" confirm="${%confirm(exe.fullDisplayName)}" alt="${%terminate this build}" />
</j:if>
</td>
<div>(${%offline})</div>
</j:otherwise>
</j:choose>
</tr>
</j:when>
<j:otherwise>
<div tooltip="${%busy(c.countBusy(), c.countExecutors())}" data-tooltip-append-to-parent="true">${c.countBusy()}/${c.countExecutors()}</div>
</j:otherwise>
</j:choose>
<j:if test="${!c.acceptingTasks}"> <st:nbsp/> (${%suspended})</j:if>
</d:tag>
<d:tag name="executor">
<j:if test="${!e.idle}">
<div class="executor-row">
<div class="executor-type">
<j:if test="${name == ''}">
<span tooltip="${%Light weight executor}" data-tooltip-append-to-parent="true">
<l:icon src="symbol-paper-plane-outline" class="icon-sm"/>
</span>
</j:if>
</div>
<div class="executor-cell">
<table class="executor-cell-table">
<tr>
<!-- not actually optional, but it helps with backward compatibility -->
<j:set var="executor" value="${e}" />
<st:include it="${e.currentExecutable}" page="executorCell.jelly" optional="true">
<td class="pane">
<div style="white-space: normal">
<j:set var="exe" value="${e.currentExecutable}" />
<j:set var="wu" value="${e.currentWorkUnit}" />
<j:choose>
<j:when test="${exe == null and wu != null}">
<j:set var="exeparent" value="${wu.work}"/>
<j:choose>
<j:when test="${h.hasPermission(exeparent,exeparent.READ)}">
<a href="${rootURL}/${exeparent.url}"><l:breakable value="${exeparent.fullDisplayName}"/></a>
<t:progressBar tooltip="${%Pending}" pos="-1" href="${rootURL}/${exeparent.url}"/>
</j:when>
<j:otherwise>
<span>${%Unknown Task}</span>
</j:otherwise>
</j:choose>
</j:when>
<j:when test="${exe == null and wu == null}">
<!-- went idle concurrent with testing for idle -->
${%Idle}
</j:when>
<j:otherwise>
<j:invokeStatic var="exeparent"
className="hudson.model.queue.Executables" method="getParentOf">
<j:arg type="hudson.model.Queue$Executable" value="${exe}" />
</j:invokeStatic>
<j:choose>
<j:when test="${h.hasPermission(exeparent,exeparent.READ)}">
<a href="${rootURL}/${exeparent.url}"><l:breakable value="${exeparent.fullDisplayName}"/></a>
<t:buildProgressBar build="${exe}" executor="${executor}"/>
</j:when>
<j:otherwise>
<span>${%Unknown Task}</span>
</j:otherwise>
</j:choose>
</j:otherwise>
</j:choose>
</div>
</td>
<td class="pane">
<j:if test="${h.hasPermission(exeparent,exeparent.READ)}">
<a href="${rootURL}/${exe.url}" class="model-link inside" style="display: block;"><l:breakable value="${exe.displayName}"/></a>
</j:if>
</td>
</st:include>
</tr>
</table>
</div>
<div class="executor-stop">
<j:if test="${h.hasPermission(exeparent,exeparent.READ) and e.hasStopPermission()}">
<l:stopButton href="${rootURL}/${c.url}${url}/stopBuild?runExtId=${h.urlEncode(exe.externalizableId)}" confirm="${%confirm(exe.fullDisplayName)}" alt="${%terminate this build}" />
</j:if>
</div>
</div>
</j:if>
</d:tag>
</d:taglib>
<j:set var="paneIsCollapsed" value="${h.isCollapsed('executors')}" />
<j:set var="computers" value="${attrs.computers?:app.computers}" />
<j:set var="origComputersSize" value="${computers.size()}"/>

<!-- Check if the built-in has to be shown, this is the case when it has either executors configured or is running
an asynchronous execution that doesn't want to hide the displaycell -->
<j:set var="builtInHasExecutors" value="${!app.toComputer().displayExecutors.isEmpty()}"/>
<j:set var="singleComputer" value="${computers.size() == 1
or (computers.size() == 2 and computers.get(0).node == app
and !builtInHasExecutors)}"/>
<!-- Remove the built-in from the list when it is included but has no executors to show -->
<j:choose>
<j:when test="${!builtInHasExecutors and computers.get(0).node == app and computers.size() gt 1}">
<j:set var="computers" value="${computers.subList(1, computers.size())}"/>
</j:when>
</j:choose>

<j:set var="computersSize" value="${computers.size()}"/>
<l:pane width="3" id="executors"
title="&lt;a href='${rootURL}/computer/'>${%Build Executor Status}&lt;/a>"
collapsedText="${%Computers(computersSize - 1, app.unlabeledLoad.computeTotalExecutors() - app.unlabeledLoad.computeIdleExecutors(), app.unlabeledLoad.computeTotalExecutors())}">
<colgroup><col width="30"/><col width="200*"/><col width="24"/></colgroup>
<j:choose>
<j:when test="${!builtInHasExecutors and app.clouds.isEmpty() and app.nodes.isEmpty()}">
<j:set var="collapsedText" value="${%noExecutors}"/>
<j:set var="showCollapsedText" value="true" />
</j:when>
<j:when test="${singleComputer}">
<j:set var="sc" value="${computers.get(0)}"/>
<j:set var="executorDetails" value="${sc.countBusy()}/${sc.countExecutors()}"/>
<j:set var="collapsedText" value="${%CollapsedSingle(sc.countBusy(), sc.countExecutors())}"/>
<j:set var="singleToolTip" value="${%busy(sc.countBusy(), sc.countExecutors())}"/>
</j:when>
<j:when test="${computersSize > 1 and !builtInHasExecutors}">
<j:set var="collapsedText" value="${%CollapsedMulti(computersSize, app.unlabeledLoad.computeTotalExecutors() - app.unlabeledLoad.computeIdleExecutors(), app.unlabeledLoad.computeTotalExecutors())}"/>
</j:when>
<j:when test="${computersSize > 1 and builtInHasExecutors}">
<j:set var="collapsedText" value="${%Computers(computersSize - 1, app.unlabeledLoad.computeTotalExecutors() - app.unlabeledLoad.computeIdleExecutors(), app.unlabeledLoad.computeTotalExecutors())}"/>
</j:when>
</j:choose>
<div class="pane-frame ${paneIsCollapsed ? 'collapsed' : 'expanded'}" id="executors">
<div class="pane-header">
<span class="pane-header-title">
<a href="${rootURL}/computer/">${%Build Executor Status}</a>
</span>
<j:if test="${origComputersSize == 1 and !paneIsCollapsed}">
<span class="pane-header-details" tooltip="${singleToolTip}" data-tooltip-append-to-parent="true">
${executorDetails}
</span>
</j:if>
<a class="collapse" href="${rootURL}/toggleCollapse?paneId=executors"
tooltip="${paneIsCollapsed ? '%Expand' : '%Collapse'}" data-tooltip-append-to-parent="true">
<j:set var="svgIconId" value="${paneIsCollapsed ? 'chevron-up' : 'chevron-down'}" />
<l:icon src="symbol-${svgIconId}" />
</a>
</div>
<j:choose>
<div class="pane-content">
<j:when test="${paneIsCollapsed or showCollapsedText}">
<div class="executors-collapsed">
${collapsedText}
</div>
</j:when>
<j:otherwise>
<j:forEach var="c" items="${computers}">
<div class="computer-row">
<j:set var="cDisplayExecutors" value="${c.displayExecutors}"/>
<j:choose>
<j:when test="${!singleComputer or origComputersSize > 1 or c.offline}">
<j:if test="${!cDisplayExecutors.isEmpty()}">
<div class="computer-caption">
<local:computerCaption title="${c.displayName}" />
</div>
</j:if>
</j:when>
</j:choose>
<j:if test="${!cDisplayExecutors.isEmpty()}">
<div class="executors-cell">
<j:forEach var="de" items="${cDisplayExecutors}" varStatus="eloop">
<j:set var="e" value="${de.executor}"/>
<local:executor name="${de.displayName}" url="${de.url}" />
</j:forEach>
</div>
</j:if>
</div>
</j:forEach>
</j:otherwise>
</div>
</j:choose>
<j:if test="${attrs.footer != null}">
<div class="pane-footer">
<j:out value="${attrs.footer}"/>
</div>
</j:if>
</div>

<j:forEach var="c" items="${computers}">
<j:set var="cDisplayExecutors" value="${c.displayExecutors}"/>
<tr>
<j:if test="${(computersSize gt 1 and !cDisplayExecutors.isEmpty()) or (c.node == app and c.offline)}">
<th class="pane" colspan="4">
<local:computerCaption title="${c.displayName}" />
</th>
</j:if>
</tr>
<j:forEach var="de" items="${cDisplayExecutors}" varStatus="eloop">
<j:set var="e" value="${de.executor}"/>
<local:executor name="${de.displayName}" url="${de.url}" />
</j:forEach>
</j:forEach>
</l:pane>
<!-- schedule updates only for the full page reload -->
<j:if test="${ajax==null and h.hasPermission(app.READ)}">
<div class="widget-refresh-reference" data-id="executors" data-url="${rootURL}/${it.url}ajax"/>
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/resources/lib/hudson/executors.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ Computers=built-in node{0,choice,0# ({1} of {2} executors busy)|1# + {0,number}
confirm=Are you sure you want to abort {0}?
launching=launching...
terminate\ this\ build=Cancel
busy={1,choice,1# {0} of {1} executor busy|1< {0} of {1} executors busy}
CollapsedSingle={1,choice,1# ({0} of {1} executor busy)|1< ({0} of {1} executors busy)}
CollapsedMulti={0} agents ({1} of {2} executors busy)}
noExecutors=No executors, agents or clouds are configured.
4 changes: 4 additions & 0 deletions core/src/main/resources/lib/hudson/executors_de.properties
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ Unknown\ Task=Unbekannter Task
Pending=Wartend
Computers=Master{0,choice,0#|1# + {0,number} Agent ({1} von {2} Build-Prozessoren)|1< + {0,number} Agenten ({1} von {2} Build-Prozessoren)}
confirm=Möchten Sie {0} wirklich abbrechen?
busy={0} von {1} Build-Prozessoren belegt
CollapsedSingle={1,choice,1# ({0} von {1} Prozessor belegt)|1< ({0} von {1} Prozessoren belegt)}
CollapsedMulti={0} Agenten ({1} von {2} Build-Prozessoren belegt)}
noExecutors=Es sind keine Prozessoren, Agenten oder Clouds konfiguriert.
1 change: 1 addition & 0 deletions war/src/main/resources/images/symbols/error.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions war/src/main/scss/base/_style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,18 @@ body.no-sticker #bottom-sticker {
}

/* see the Icon class for the definition of these CSS classes */
.icon-xs,
svg.icon-xs {
width: 12px;
height: 12px;
vertical-align: middle;

svg {
width: 12px;
height: 12px;
}
}

.icon-sm,
svg.icon-sm {
width: 16px;
Expand Down
Loading
Loading