Questions on updating flowdock plugin to support pipeline

62 views
Skip to first unread message

Tim Downey

unread,
Nov 1, 2016, 2:04:58 PM11/1/16
to Jenkins Developers
Hi,

I'm working on updating the Flowdock plugin to support pipeline and am getting hung up in how to map some of the old calls to the new API.  In general, I've gone through and replaced AbstractProject with Run<?, ?>.  I've got a few hangups that I was hoping that someone with direct knowledge could help me through.

I have this:

    public static ChatMessage fromBuild(Run<?, ?> build, BuildResult buildResult, TaskListener listener) {


        ChatMessage msg = new ChatMessage();


        StringBuilder content = new StringBuilder();


        String projectName = "";

        String configuration = "";

       

       if(build.getProject().getRootProject() != build.getProject()) {

           projectName = build.getProject().getRootProject().getDisplayName();

           configuration = " on " + build.getProject().getDisplayName();

       } else {

           projectName = build.getProject().getDisplayName();

       }


From the call, I've switched the fromBuild method to take Run<?,?> instead of AbstractProject, but the issue is that I'm not clear on what needs to be done in the conditional.  The existing code seems to be trying to figure out if it is the root project in order to construct the message (which will be sent to flowdock) but I'm not sure what the equivalent would be when working from Run instead of AbstractProject.

I have a similar problem with trying to figure out ChangeSets here, although it looks like I found some code on this forum to go after the changesets via reflection.

    public static List<Entry> parseCommits(Run<?, ?> build) {


        final ChangeLogSet<? extends Entry> cs = build.getChangeSet();


        if(cs == null || cs.isEmptySet())

           return null;


        List<Entry> commits = new ArrayList();


        for (final Entry entry : cs) {

           // reverse order in order to have recent commits first

           commits.add(0, entry);

       }


        return commits;

   }


Thanks for any suggestions!
Tim

Jesse Glick

unread,
Nov 1, 2016, 5:55:55 PM11/1/16
to Jenkins Dev
On Tue, Nov 1, 2016 at 2:04 PM, Tim Downey <timothy...@gmail.com> wrote:
> if(build.getProject().getRootProject() != build.getProject()) {
> projectName =
> build.getProject().getRootProject().getDisplayName();
> configuration = " on " + build.getProject().getDisplayName();
> } else {
> projectName = build.getProject().getDisplayName();
> }
>
>
> From the call, I've switched the fromBuild method to take Run<?,?> instead
> of AbstractProject

Instead of `AbstractBuild` I suppose you mean.

> but the issue is that I'm not clear on what needs to be
> done in the conditional. The existing code seems to be trying to figure out
> if it is the root project in order to construct the message (which will be
> sent to flowdock) but I'm not sure what the equivalent would be when working
> from Run instead of AbstractProject.

There is no generalization of `AbstractProject.getRootProject`
currently. You can check if the `Job` is in fact an `AbstractProject`
and if so call `getRootProject` on it, else just use the job as is.

Tim Downey

unread,
Nov 2, 2016, 2:31:53 PM11/2/16
to Jenkins Developers
Yes, thanks Jesse.  I wasn't sure if there was a generalization.  I'll do as you suggest and check the type for now.  Thanks.

Tim Downey

unread,
Nov 7, 2016, 2:26:29 PM11/7/16
to Jenkins Developers
Hi Jesse,

I'm hoping you can point me in the right direction for one more thing.  I'm trying to understand at what point in the pipeline process does the build result (via run.getResult()) become available?  As you can see below, I'm calling the original FlowdockNotifier code in a step execution in order to be able to use the "legacy" plugin in a pipeline.  I'm including two blocks below.  First is how it's being used in a pipeline, and the second is the step execution code.

The issue is that run.getResult() is returning null even when used in a pipeline *after* which the build should have failed (e.g. after failing to pass unit tests or compilation).  I'm wondering if there is something I need to do to ensure that I get the proper build result from the job and have this step run only after that.

Here's the pipeline.  In this example, I was assuming that by running the flowdockNotifier in the pipeline, I'd already have the correct build result in place as a result of the mvn build in the previous section.  Instead, I'm getting null for run.getResult() no matter what.  Is there something different I should be doing to ensure that the flowdockNotifier is only run after we've received some sort of build result?  The Flowdock plugin traditionally has been a Notifier and run as a post build action.

        try {
            sshagent([config.gitCredentials]) {

                withMaven(maven: 'Maven', mavenLocalRepo: '.repository', mavenSettingsConfig: 'org.jenkinsci.plugins.configfiles.maven.MavenSettingsConfig1450194231885') {
                    sh "mvn versions:set -DnewVersion=${version}"
                    sh "mvn clean install"
                }                
                          }

             } catch (err) {
            mail body: "Please go to ${BUILD_URL} and verify the build." ,
                from: config.email,
                replyTo: config.email,
                subject: "Build failed in Jenkins: ${JOB_NAME} ${version}",
                to: config.recipients

            throw err
        } finally {
            // Post build items here -- build will have already passed or failed by now?
            flowdockNotifier(flowToken: 'myflowdocktoken', notificationTags: "jenkins, ${JOB_NAME}",
                chatNotification:true, notifyFailure: true)

        }

Here's the step execution.

    public static class Execution extends AbstractSynchronousStepExecution<Void> {

       

       @StepContextParameter private transient Launcher launcher;

       @StepContextParameter private transient FilePath workspace;

       @StepContextParameter private transient TaskListener listener;

       @StepContextParameter private transient Run<?, ?> run;

       @StepContextParameter private transient EnvVars env;

       @Inject(optional=true) private transient FlowdockNotifierStep step;


        @Override

       protected Void run() throws Exception {

           listener.getLogger().println("Running flowdock notifier.");

           

           FlowdockNotifier notifier = new FlowdockNotifier(step.flowToken,

                        step.notificationTags,

                        convertToString(step.chatNotification),

                        convertToString(step.notifySuccess),

                        convertToString(step.notifyFailure),

                        convertToString(step.notifyFixed),

                        convertToString(step.notifyUnstable),

                        convertToString(step.notifyAborted),

                        convertToString(step.notifyNotBuilt));

           

           notifier.perform(run, workspace, launcher, listener);


            return null;        

       }


        private static final long serialVersionUID = 1L;


        private static String convertToString(Boolean bool) {

          return bool != null ? bool.toString() : null;

       }

   }


Thanks for any help,
Tim


On Tuesday, November 1, 2016 at 5:55:55 PM UTC-4, Jesse Glick wrote:

Jesse Glick

unread,
Nov 7, 2016, 3:52:09 PM11/7/16
to Jenkins Dev
On Mon, Nov 7, 2016 at 2:26 PM, Tim Downey <timothy...@gmail.com> wrote:
> The issue is that run.getResult() is returning null even when used in a
> pipeline *after* which the build should have failed (e.g. after failing to
> pass unit tests or compilation). I'm wondering if there is something I need
> to do to ensure that I get the proper build result from the job and have
> this step run only after that.

For a `SimpleBuildStep` this would apply:

https://github.com/jenkinsci/workflow-basic-steps-plugin/blob/master/CORE-STEPS.md#interacting-with-build-status

but you are apparently writing a `Step`, so:

> Is there something
> different I should be doing to ensure that the flowdockNotifier is only run
> after we've received some sort of build result? The Flowdock plugin
> traditionally has been a Notifier and run as a post build action.

It is generally the responsibility of the script to decide whether or
not to run a given publisher and with what settings. Avoid calling
`Run.getResult`.

Tim Downey

unread,
Nov 7, 2016, 4:23:38 PM11/7/16
to jenkin...@googlegroups.com
Ok, so you're saying the convention would be that under pipeline, traditional Notifiers would not be used and instead flow control around build status should be inside of the pipeline as opposed to the plugin?  In other words, instead of having the flowdockNotifier() figure out what to do based on build status (from within the plugin), I should instead just require the pipeline script writer to pass the correct args based on the pipeline script logic directly (using try, catch logic in the pipeline)?

I can see that doing so would provide the most flexibility, but it also seems to require the most work for pipeline script writers.  A specific example would be crafting the logic to notify of a "fixed" build from a pipeline.  As of now, the plugin does the work to determine if a build has transitioned from failed to success and is now "fixed".  If that work is now the job of the pipeline script, it will certainly complicate things and result in lots of duplication and variance from one persons pipeline to anothers.

That said, I appreciate the feedback and am still trying to digest what folks are looking for in terms of idiomatic pipeline code.

Thanks for your time,
Tim



--
You received this message because you are subscribed to a topic in the Google Groups "Jenkins Developers" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jenkinsci-dev/kI0BtRoE7kM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jenkinsci-dev+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jenkinsci-dev/CANfRfr2igFVJW-gMuaUvrFW%2Btf-874Cx3CaRY1yD1FzJRYemLg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Jesse Glick

unread,
Nov 7, 2016, 6:56:46 PM11/7/16
to Jenkins Dev
On Mon, Nov 7, 2016 at 4:23 PM, Tim Downey <timothy...@gmail.com> wrote:
> under pipeline,
> traditional Notifiers would not be used and instead flow control around
> build status should be inside of the pipeline as opposed to the plugin?

Right.

> also
> seems to require the most work for pipeline script writers

See Pipeline Model Definition plugin.

Tim Downey

unread,
Nov 8, 2016, 9:57:29 AM11/8/16
to jenkin...@googlegroups.com
Ok, that helps.  Thanks again.

And for anyone searching the mailing list in the future, here's the relevant bit for post build activity from the Pipeline Model Definition plugin.



--
You received this message because you are subscribed to a topic in the Google Groups "Jenkins Developers" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jenkinsci-dev/kI0BtRoE7kM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jenkinsci-dev+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages