Skip to content

Commit

Permalink
JENKINS-7824 Allow assigning builds/tests to other users
Browse files Browse the repository at this point in the history
  • Loading branch information
Marc Carter committed Mar 16, 2014
1 parent 7cf3e18 commit c235979
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 12 deletions.
2 changes: 1 addition & 1 deletion readme.md
@@ -1,7 +1,7 @@
Jenkins Claim Plugin
=========================

A plugin for Jenkins CI that allows users to claim(take responsibility) for a failing build.<br>
A plugin for Jenkins CI that allows users to claim (take responsibility) for a failing build or assign it to another user (aka blame).<br>
Look at [wiki] for detailed instructions.

Change Log
Expand Down
18 changes: 16 additions & 2 deletions src/main/java/hudson/plugins/claim/AbstractClaimBuildAction.java 100644 → 100755
Expand Up @@ -9,6 +9,8 @@

import java.io.IOException;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;

Expand All @@ -24,6 +26,7 @@ public abstract class AbstractClaimBuildAction<T extends Saveable> extends TestA
ProminentProjectAction {

private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger("claim-plugin");

private boolean claimed;
private String claimedBy;
Expand All @@ -49,8 +52,19 @@ public String getUrlName() {
public void doClaim(StaplerRequest req, StaplerResponse resp)
throws ServletException, IOException {
Authentication authentication = Hudson.getAuthentication();
String name = authentication.getName();
String reason = (String) req.getSubmittedForm().get("reason");
String name = authentication.getName(); // Default to self-assignment
String assignee = req.getSubmittedForm().getString("assignee");
if (!StringUtils.isEmpty(assignee) && !name.equals(assignee)) {
// Validate the specified assignee.
User resolvedAssignee = User.get(assignee, false);
if (resolvedAssignee == null) {
LOGGER.log(Level.WARNING, "Invalid username specified for assignment: {0}", assignee);
resp.forwardToPreviousPage(req);
return;
}
name = assignee;
}
String reason = req.getSubmittedForm().getString("reason");
boolean sticky = req.getSubmittedForm().getBoolean("sticky");
if (StringUtils.isEmpty(reason)) reason = null;
claim(name, reason, sticky);
Expand Down
Expand Up @@ -30,6 +30,7 @@
</j:choose>
<j:if test="${it.canRelease()}">
<a id="dropClaim" href="claim/unclaim">${%Drop the claim.}</a>
<st:nbsp/><a id="reassign" href="#" onClick="ShowPopup(this); return false;">${%Reassign the claim.}</a>
</j:if>
</p>
<j:if test="${it.hasReason()}">
Expand All @@ -48,7 +49,7 @@
</j:otherwise>
</j:choose>
<j:if test="${it.canClaim()}">
<a id="claimForYourself" href="#" onClick="ShowPopup(this); return false;">${%Claim for yourself.}</a>
<a id="reassign" href="#" onClick="ShowPopup(this); return false;">${%Reassign the claim.}</a>
</j:if>
</p>
<j:if test="${it.hasReason()}">
Expand All @@ -64,6 +65,9 @@
</j:choose>
<div id="claimHoverPopup" style="display:none; width:500px; z-index:1000; border:1px solid #bbb;">
<f:form method="post" action="claim/claim" name="claim">
<f:entry title="${%Assignee}" help="/plugin/claim/help-assignee.html">
<f:textbox name="assignee" value="${it.assignee}"/>
</f:entry>
<f:entry title="${%Reason}" help="/plugin/claim/help-reason.html">
<f:textarea name="reason" value="${it.reason}"/>
</f:entry>
Expand Down
3 changes: 3 additions & 0 deletions src/main/webapp/help-assignee.html
@@ -0,0 +1,3 @@
<div>
The user you are assigning the claim to. Blank means yourself.
</div>
49 changes: 41 additions & 8 deletions src/test/java/hudson/plugins/claim/ClaimTest.java
Expand Up @@ -23,11 +23,9 @@
*/
package hudson.plugins.claim;

import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlTextArea;
import hudson.model.Build;
import hudson.model.Project;
import hudson.security.FullControlOnceLoggedInAuthorizationStrategy;
Expand Down Expand Up @@ -56,6 +54,9 @@ public void setUp() throws Exception {

j.jenkins.setAuthorizationStrategy(new FullControlOnceLoggedInAuthorizationStrategy());
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
JenkinsRule.WebClient wc = j.createWebClient();
wc.login("user2", "user2");
wc.closeAllWindows();

project = j.createFreeStyleProject("x");
project.getBuildersList().add(new FailureBuilder());
Expand All @@ -78,12 +79,22 @@ public void failed_build_can_be_claimed_by_you() throws Exception {
assertThat(action.isClaimed(), is(true));
}

@Test
public void failed_build_can_be_assigned() throws Exception {
// When:
ClaimBuildAction action = whenAssigningBuildByClicking("claim");
// Then:
assertThat(action.getClaimedBy(), is("user2"));
assertThat(action.getReason(), is(claimText));
assertThat(action.isClaimed(), is(true));
}

@Test
public void claimed_build_can_be_reclaimed_by_you() throws Exception {
// Given:
givenBuildClaimedByOtherUser();
// When:
ClaimBuildAction action = whenClaimingBuildByClicking("claimForYourself");
ClaimBuildAction action = whenClaimingBuildByClicking("reassign");
// Then:
assertThat(action.getClaimedBy(), is("user1"));
assertThat(action.getReason(), is(claimText));
Expand All @@ -101,6 +112,18 @@ public void claim_can_be_dropped() throws Exception {
assertThat(action.isClaimed(), is(false));
}

@Test
public void claim_can_be_reassigned() throws Exception {
// Given:
givenBuildClaimedByCurrentUser();
// When:
ClaimBuildAction action = whenAssigningBuildByClicking("reassign");
// Then:
assertThat(action.getClaimedBy(), is("user2"));
assertThat(action.getReason(), is(claimText));
assertThat(action.isClaimed(), is(true));
}

@Test
public void sticky_claim_propagates_to_next_build() throws Exception {
// Given:
Expand Down Expand Up @@ -140,13 +163,23 @@ private ClaimBuildAction givenBuildClaimedByCurrentUser() {
}

private ClaimBuildAction whenClaimingBuildByClicking(String claimElement) throws Exception {
HtmlPage page = whenNavigatingToClaimPageAndClicking(claimElement);
return applyClaim(claimElement, "", claimText);
}

private ClaimBuildAction whenAssigningBuildByClicking(String claimElement) throws Exception {
return applyClaim(claimElement, "user2", claimText);
}

private ClaimBuildAction applyClaim(String claimElement, String assignee, String reason) throws Exception {
HtmlPage page = whenNavigatingToClaimPageAndClicking(claimElement);
HtmlForm form = page.getFormByName("claim");
HtmlTextArea textArea = (HtmlTextArea) j.last(form.selectNodes(".//textarea"));
textArea.setText(claimText);

form.submit((HtmlButton) j.last(form.selectNodes(".//button")));
form.getTextAreaByName("reason").setText(reason);
if ( assignee!=null ) {
j.last(form.getInputsByName("assignee")).setValueAttribute(assignee);
}

form.submit((HtmlButton) j.last(form.getHtmlElementsByTagName("button")));

ClaimBuildAction action = build.getAction(ClaimBuildAction.class);
return action;
Expand All @@ -156,7 +189,7 @@ private HtmlPage whenNavigatingToClaimPageAndClicking(String claimElement) throw
JenkinsRule.WebClient wc = j.createWebClient();
wc.login("user1", "user1");
HtmlPage page = wc.goTo("job/x/" + build.getNumber());
((HtmlAnchor) page.getElementById(claimElement)).click();
page.getElementById(claimElement).click();
return page;
}
}

0 comments on commit c235979

Please sign in to comment.