• Icon: New Feature New Feature
    • Resolution: Fixed
    • Icon: Major Major
    • email-ext-plugin
    • None

      It would be great if this plugin could add support for the Claim Plugin (https://wiki.jenkins-ci.org/display/JENKINS/Claim+plugin, 1800 installations).

      I imagine two additional features shown to the user in the Project configuration, if the Claim Plugin is installed:

      • A "recipient group" called "Claimer" or something so that we can select when this person gets an email.
      • One or more triggers related to a failed build which is already claimed. Maybe it could be a checkbox to the existing triggers ("...and is already claimed")

      The end result would be that the user can configure that for example only the owners and the claimer (i.e. not the other culprits) will be emailed when a build with a sticky Claim fails again.

          [JENKINS-16861] Add support for the Claim Plugin

          Markus added a comment -

          I don't think the Claim Plugin exports any variables, but I don't know. I've seen the claim status in the builds' APIs.

          What I'm looking for is a possibility to make Jenkins not send "build is still failing" e-mails to all committers if a user has Claimed the failing build. Only the claimer (and maybe the default recipients) should get e-mails if the build is claimed. But if no-one has claimed the failing build, then all committers should get emails as normal. Therefore I don't think it would help to add a variable to the recipient list, if such a variable is exported by the Claim Plugin.

          I was also considering the custom script that can execute before e-mailing. But this can only stop all e-mails (cancel=true), not modify the recipients list (I think?). I would like it to send e-mails to different recipients depending on the claim status.

          The end result and goal is less spam. I think this would fit nicely in email-ext, since I can select who'll get emails when (1st fail, next fails etc). It only needs a "if claimed" option to the triggers and the ability to fetch the claimer's username from the job's API.

          Markus added a comment - I don't think the Claim Plugin exports any variables, but I don't know. I've seen the claim status in the builds' APIs. What I'm looking for is a possibility to make Jenkins not send "build is still failing" e-mails to all committers if a user has Claimed the failing build. Only the claimer (and maybe the default recipients) should get e-mails if the build is claimed. But if no-one has claimed the failing build, then all committers should get emails as normal. Therefore I don't think it would help to add a variable to the recipient list, if such a variable is exported by the Claim Plugin. I was also considering the custom script that can execute before e-mailing. But this can only stop all e-mails (cancel=true), not modify the recipients list (I think?). I would like it to send e-mails to different recipients depending on the claim status. The end result and goal is less spam. I think this would fit nicely in email-ext, since I can select who'll get emails when (1st fail, next fails etc). It only needs a "if claimed" option to the triggers and the ability to fetch the claimer's username from the job's API.

          Alex Earl added a comment -

          One of the little known features is that you can use a script in the recipient list. There are two pieces that you can use to do what you want I think.

          1) Use the SCRIPT token and provide a script parameter directly so it doesn't try and use a template. This script would be used in the recipient field and would check if the build was claimed, if it was it would only return the person's email address that claimed it and this would be put into the recipient list. If no one has claimed the build, then you could return the full email list.

          The pre-send script can indeed modify the recipient list since you have access to the message object.

          In the future, the triggers will be an extension point, so anyone could implement a trigger, I think that would do what you want and allow for more portability and extensibility.

          Alex Earl added a comment - One of the little known features is that you can use a script in the recipient list. There are two pieces that you can use to do what you want I think. 1) Use the SCRIPT token and provide a script parameter directly so it doesn't try and use a template. This script would be used in the recipient field and would check if the build was claimed, if it was it would only return the person's email address that claimed it and this would be put into the recipient list. If no one has claimed the build, then you could return the full email list. The pre-send script can indeed modify the recipient list since you have access to the message object. In the future, the triggers will be an extension point, so anyone could implement a trigger, I think that would do what you want and allow for more portability and extensibility.

          Markus added a comment -

          You are right. I should be able to create a script for that, which changes the recipient list based on the claim status.

          I've never done any groovy scripts before, but at least I've been able to get the claim status. But after hours of searching, I've not been able to get the users e-mail address from the Jenkins user database. For now, I'll use the returned username as email address (username@domain.com), unless you could point me in the right directions? I'm looking for something like hudson.users.getEmailAddress(claim.getClaimedBy()).

          For future searchers, this is what I've got so far. It is not production ready - It must be modified to set the email address before it can be used. I'll see if I can attach the finished script when (or if) I'm able to finish it.

          def claim = it.getAction("hudson.plugins.claim.ClaimBuildAction")
            if (claim != null) {
              if (claim.isClaimed() == true) {
                %>Claimed by: ${claim.getClaimedBy()} (${claim.getClaimedByName()})\n<%
                if (claim.hasReason() == true ) {
                  %>Reason: ${claim.getReason()}\n<%
                }
                if (claim.hasClaimDate() == true ){
                  %>Claimed at: ${claim.getClaimDate()}\n<%
                }
              } else {
                %>Not claimed\n<%
              }
            } else {
              %>Claim not supported for this job\n<%
            }
          

          Markus added a comment - You are right. I should be able to create a script for that, which changes the recipient list based on the claim status. I've never done any groovy scripts before, but at least I've been able to get the claim status. But after hours of searching, I've not been able to get the users e-mail address from the Jenkins user database. For now, I'll use the returned username as email address (username@domain.com), unless you could point me in the right directions? I'm looking for something like hudson.users.getEmailAddress(claim.getClaimedBy()) . For future searchers, this is what I've got so far. It is not production ready - It must be modified to set the email address before it can be used. I'll see if I can attach the finished script when (or if) I'm able to finish it. def claim = it.getAction( "hudson.plugins.claim.ClaimBuildAction" ) if (claim != null ) { if (claim.isClaimed() == true ) { %>Claimed by: ${claim.getClaimedBy()} (${claim.getClaimedByName()})\n<% if (claim.hasReason() == true ) { %>Reason: ${claim.getReason()}\n<% } if (claim.hasClaimDate() == true ){ %>Claimed at: ${claim.getClaimDate()}\n<% } } else { %>Not claimed\n<% } } else { %>Claim not supported for this job\n<% }

          Alex Earl added a comment -

          You need to get a property from the user object. This is how it is done internally in the email-ext plugin.

          public static String getUserConfiguredEmail(User user) {
              String addr = null;
              if(user != null) {
                  Mailer.UserProperty mailProperty = user.getProperty(Mailer.UserProperty.class);
                  if (mailProperty != null) {
                      addr = mailProperty.getAddress();
                  }
              }
              return addr;
          }
          

          Also, just as an FYI, when using groovy, for getters and setters you don't need the get/set; for example: claim.claimedByName is the same as claim.getClaimedByName()

          Alex Earl added a comment - You need to get a property from the user object. This is how it is done internally in the email-ext plugin. public static String getUserConfiguredEmail(User user) { String addr = null ; if (user != null ) { Mailer.UserProperty mailProperty = user.getProperty(Mailer.UserProperty.class); if (mailProperty != null ) { addr = mailProperty.getAddress(); } } return addr; } Also, just as an FYI, when using groovy, for getters and setters you don't need the get/set; for example: claim.claimedByName is the same as claim.getClaimedByName()

          Markus added a comment -

          Thank you very much Alex. Your pointers, combined with Chris's implementation in JENKINS-12421, did the trick. I now have a way to solve this, but I was only able to make it run when I did it as a pre-send script, which means that the script must be duplicated in every job (hundreds).

          So, you say it is possible to run this script directly from the Project Recipient List? I've added ${SCRIPT, script="get-claim-recipient.groovy"} to a job's Default Content (for debugging) and it seems to run. But I'm not able to output any text from the script. It does not accept %>sometext<% (unexpected token: <). I've also tried println("Hello"); but nothing is written in the email. logger.println() also does not work (No such property: logger for class).

          Also, I'm not able to make mailext/groovy accept "address = user.getProperty(hudson.tasks.Mailer.UserProperty).getAddress();". (No such property: hudson for class). This line works well if it is a pre-send script. I've tried to import hudson.model.User.* as well.

          And finally, if I do it like this, then will I be able to provide any default recipients (for non-claimed jobs) in the job configuration? Maybe I should simply wait for JENKINS-14508.

          I obviously don't have enough knowledge here, so I apologize for all my novice questions and humbly hope for some more guidelines.

          Markus added a comment - Thank you very much Alex. Your pointers, combined with Chris's implementation in JENKINS-12421 , did the trick. I now have a way to solve this, but I was only able to make it run when I did it as a pre-send script, which means that the script must be duplicated in every job (hundreds). So, you say it is possible to run this script directly from the Project Recipient List? I've added ${SCRIPT, script="get-claim-recipient.groovy"} to a job's Default Content (for debugging) and it seems to run. But I'm not able to output any text from the script. It does not accept %>sometext<% (unexpected token: <). I've also tried println("Hello"); but nothing is written in the email. logger.println() also does not work (No such property: logger for class). Also, I'm not able to make mailext/groovy accept "address = user.getProperty(hudson.tasks.Mailer.UserProperty).getAddress();". (No such property: hudson for class). This line works well if it is a pre-send script. I've tried to import hudson.model.User.* as well. And finally, if I do it like this, then will I be able to provide any default recipients (for non-claimed jobs) in the job configuration? Maybe I should simply wait for JENKINS-14508 . I obviously don't have enough knowledge here, so I apologize for all my novice questions and humbly hope for some more guidelines.

          Alex Earl added a comment -

          When using a script in the recipient list, your last line of the script must be a string with comma separated addresses.

          def committers = []
          // loop through and grab committers from somewhere cool
          // here comes the last line
          committers.unique().join(',')
          

          When trying to do content (body) you want to create a template, not a script.
          ${SCRIPT, template="output-claim-info.template"}

          Did you try this?

          import hudson.tasks.Mailer.UserProperty
          
          address = user.getProperty(hudson.tasks.Mailer.UserProperty.class).address
          

          You can definitely provide default recipients, just do something like this:

          Project Recipient List: someone@somewhere.com, ${SCRIPT, script="get-claim-recipient.groovy"}

          Alex Earl added a comment - When using a script in the recipient list, your last line of the script must be a string with comma separated addresses. def committers = [] // loop through and grab committers from somewhere cool // here comes the last line committers.unique().join( ',' ) When trying to do content (body) you want to create a template, not a script. ${SCRIPT, template="output-claim-info.template"} Did you try this? import hudson.tasks.Mailer.UserProperty address = user.getProperty(hudson.tasks.Mailer.UserProperty.class).address You can definitely provide default recipients, just do something like this: Project Recipient List: someone@somewhere.com, ${SCRIPT, script="get-claim-recipient.groovy"}

          Markus added a comment -

          Thank you again. After a lot of trial and errors, the UserProperty problem was resolved: The class exists on the Jenkins production server, not on my simple test server. I guess it is because my test server only has the AD plugin installed but it does not use it. It uses Jenkins's own user database. Also, then "last line" trick did the trick.

          But I've realized, now that this works, that I have to do this as a pre-mail script. I'd like to replace the default recipients and I'd like it not to email the Culprits and Committers if the job is claimed. So I have to edit the complete recipients list just before the mail is sent, which is a pre-send script. I'll guess I'll have to do some scripting to distribute the pre-send script to all the jobs until we can add global pre-mail scripts (JENKINS-14508).

          Here's what I ended up with, for future googlers. I kept the array in case I'd like to add more recipients from other sources later.

          def committers = []
          
          build.actions.each { action ->
          if(action.class.name == "hudson.plugins.claim.ClaimBuildAction" && action.isClaimed()) {
            hudson.model.User user = hudson.model.User.get(action.getClaimedBy());  
            address = user.getProperty(hudson.tasks.Mailer.UserProperty.class).address  
            committers[0]=address
          }
          }
          
          // here comes the last line, it MUST be the last line for this to work!!
          committers.unique().join(',')
          

          I'd still like a built-in support for the Claim plugin, which was the initial request, so I'd prefer to leave this as open. But I'll accept a Won't Fix if you prefer that such things are resolved using the (excellent) scripting features.

          Markus added a comment - Thank you again. After a lot of trial and errors, the UserProperty problem was resolved: The class exists on the Jenkins production server, not on my simple test server. I guess it is because my test server only has the AD plugin installed but it does not use it. It uses Jenkins's own user database. Also, then "last line" trick did the trick. But I've realized, now that this works, that I have to do this as a pre-mail script. I'd like to replace the default recipients and I'd like it not to email the Culprits and Committers if the job is claimed. So I have to edit the complete recipients list just before the mail is sent, which is a pre-send script. I'll guess I'll have to do some scripting to distribute the pre-send script to all the jobs until we can add global pre-mail scripts ( JENKINS-14508 ). Here's what I ended up with, for future googlers. I kept the array in case I'd like to add more recipients from other sources later. def committers = [] build.actions.each { action -> if (action. class. name == "hudson.plugins.claim.ClaimBuildAction" && action.isClaimed()) { hudson.model.User user = hudson.model.User.get(action.getClaimedBy()); address = user.getProperty(hudson.tasks.Mailer.UserProperty.class).address committers[0]=address } } // here comes the last line, it MUST be the last line for this to work!! committers.unique().join( ',' ) I'd still like a built-in support for the Claim plugin, which was the initial request, so I'd prefer to leave this as open. But I'll accept a Won't Fix if you prefer that such things are resolved using the (excellent) scripting features.

          Alex Earl added a comment -

          I think that in the future I'll make two extension points available

          1) Recipient list, which can override the other recipient categories similar to how the triggers can override other triggers. This would make it so that the Claim plugin could implement their own recipient category if they wanted to.
          2) I am already working on making the triggers into a better model of the extension point mechanism so that other plugins or code could cause triggers to occur.

          I am also adding a ScriptTrigger and PreBuildScriptTrigger so that you could script your own triggers. Would these meet your needs? Basically the idea would be to empower other plugins to implement features like this so that the dependencies of email-ext don't grow exponentially with each plugin that people would like to have support for.

          Alex Earl added a comment - I think that in the future I'll make two extension points available 1) Recipient list, which can override the other recipient categories similar to how the triggers can override other triggers. This would make it so that the Claim plugin could implement their own recipient category if they wanted to. 2) I am already working on making the triggers into a better model of the extension point mechanism so that other plugins or code could cause triggers to occur. I am also adding a ScriptTrigger and PreBuildScriptTrigger so that you could script your own triggers. Would these meet your needs? Basically the idea would be to empower other plugins to implement features like this so that the dependencies of email-ext don't grow exponentially with each plugin that people would like to have support for.

          Markus added a comment -

          You're right. You cannot customize support for every plugin for everyone. I don't fully understand how your planned features will be, but I understand the basic ideas and I think they will meet my needs.

          Markus added a comment - You're right. You cannot customize support for every plugin for everyone. I don't fully understand how your planned features will be, but I understand the basic ideas and I think they will meet my needs.

          Alex Earl added a comment -

          Added the script triggers that allow you to define your own custom logic for when an email should be triggered (2.28)

          Added default pre-send script (2.29)

          Alex Earl added a comment - Added the script triggers that allow you to define your own custom logic for when an email should be triggered (2.28) Added default pre-send script (2.29)

            slide_o_mix Alex Earl
            mabahj Markus
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: