Solutions Delivery Platform

Leverage Lifecycle Hooks

Sometimes it is necessary to trigger specific pipeline actions at certain times during pipeline execution. For example, if you wanted to send multiple notification types after a particular pipeline step or at the conclusion of a pipeline if the build was failure.

JTE supports this type of Aspect Oriented Programming style event handling through annotation markers that can be placed on library steps.

The following lifecycle hook annotations are available:

Table 1. JTE LifeCycle Hook annotations
Annotation Description

@Validate

Will get executed at the beginning of a pipeline run, should throw exception if this step does not have its prerequesites

@Init

Will get executed at the beginning of a pipeline run, after Validate

@BeforeStep

Will get executed before every pipeline step invocation

@AfterStep

Will get executed after every pipeline step invocation

@CleanUp

Will get executed at the end of a pipeline run

@Notify

Will get executed after every pipeline step invocation as well as at the end of the pipeline run

Implementation

Lifecycle Hook annotations can be placed on any method inside a step. Hooks must accept a context parameter that is of type HookContext from the JTE plugin. Because of Groovy’s ducktyping functionality, you do not have to declare the Class of the context parameter.

You can name the input parameter whatever you want to. For ease of communication, it is assumed the parameter is named context

Table 2. JTE LifeCycle Hook Context Parameter
Variable Description

context.library

The name of the Library that contributed the step associated with the hook

context.step

The name of the Step associated with the hook

context.library and context.step will be null before and after pipeline execution due to the fact that the hook is not in response to a particular pipeline step.

Conditional Execution

Sometimes you’ll only want to invoke the Hook when certain conditions are met, such as a build failure or in relation to another step (like before static code analysis).

Each annotation accepts a Closure parameter. If the return object of this closure is truthy then the hook will be executed.

While executing, the code within the Closure parameter will be able to resolve the context variable described, the library configuration of the library that loads the step via the config variable, and the currentBuild variable made available in Jenkins Pipelines.

Example Syntax:

@BeforeStep({ context.step.equals("build") })
void call(context){
    // execute something right before the library step called build is executed.
}
  • The closure parameter is optional. If omitted, the hook will always be executed.

  • The context variable is always called context within the Closure parameter, regardless of what the step’s input parameter is named.

Example Implementation

Let’s say we wanted to print to the console log a specific message when the build step fails to execute successfully.

Step 1: Create a Library

Within one of your configured library sources, create a new directory. For this example, let’s call the library slack

Repository Structure:

README.rst
slack/

Step 2: Create the Step

When creating steps whose only purpose is to be invoked at a particular stage of the pipeline, the name of the step does not matter because it is not being called via a pipeline template. These steps are discovered by JTE and invoked dynamically.

This means that if there are multiple steps with the same annotation they will all be executed. This is useful for situations such as creating pipeline templates to be used by multiple teams all using different tools to receive pipeline notifications - or using multiple notification tools (email, slack, sms, etc).

For this example, we’ll call the step sendSlackNotification.

README.rst
slack/
    sendSlackNotification.groovy

We must remember to annotate the method and pass the step a context input parameter. Remember, our goal is to create a step that sends a message when the build step fails.

sendSlackNotification.groovy:

@AfterStep({ context.step.equals("build") })
void call(context){
    slackSend color: '#ff0000', message: "Build Failure: ${env.JOB_URL}"
}

This example assumes you’ve installed and appropriately configured the Slack Notification Plugin.

Step 3: Load the Library

With the library created and slack notification step written all you haveto do to send a slack notification after the build step fails is load the slack library in your pipeline configuration file.

libraries{
    slack
}

JTE will automatically pick up that a library has been loaded that contributes steps with lifecycle hook annotations.