NAV
Switch version:

Notification Plugins

Extension Information

Availability GoCD version 18.9.0 onwards
Extension Name notification
Extension API Version 4.0

Current Version

This document is for version 4.0 (the latest) of the notification endpoint.

Introduction

Notification extension endpoint allows GoCD to send notifications about builds and agent state changes over various channels.

If you’re looking to start away with a basic template for notification plugins, we recommend forking this github repository.

Requests from the GoCD server

In order to implement the notification extension point the following messages must be implemented by the plugin.

These are general purpose messages that a plugin may implement to allow users to configure the plugin through the browser.

Notifications Interested In

This message is a request to the plugin to check what sort of notifications the plugin is interested to receive.

Request name

notifications-interested-in

Request body

The server will not provide a request body.

Response code

The plugin is expected to return status 200 if it can understand the request.

Response Body

The plugin is expected to return a JSON object with the key notifications that lists all notifications.

Currently supported notifications include:

An example response body:

{
  "notifications": ["stage-status"]
}

Stage Status Changed

This message is sent by the server, when it wants to notify the plugin about a “stage status change”.

Stage status changed notifications only get sent when a stage gets scheduled or when it completes.

Request-Response basics

Request name

stage-status

Response code

The plugin is expected to return status 200 if it can understand the request.

Response Body

An example response body if the plugin could send the notification successfully

{
  "status": "success"
}

An example response body if the plugin could not send the notification

{
  "status": "failure",
  "messages": ["Could not send email for build/1/compile/1"]
}

The plugin is expected to return a JSON object to indicate if the notifications could be processed.

Stage start notifications

A sample body when a stage with three jobs gets scheduled.

{
  "pipeline": {
    "name": "pipeline-name",
    "counter": "9",
    "group": "defaultGroup",
    "build-cause": [
      {
        "material": {
          "git-configuration": {
            "shallow-clone": false,
            "branch": "2.x",
            "url": "https://github.com/organization/repository"
          },
          "type": "git"
        },
        "changed": false,
        "modifications": [
          {
            "revision": "8f60b12439840e5a0a4d464379dd3a48881008b4",
            "modified-time": "2017-03-23T17:27:58.000+0000",
            "data": {}
          }
        ]
      }
    ],
    "stage": {
      "name": "stage-2",
      "counter": "1",
      "approval-type": "success",
      "approved-by": "timer",
      "previous-stage-name": "stage-1",
      "previous-stage-counter": 1,
      "state": "Building",
      "result": "Unknown",
      "create-time": "2017-03-23T20:44:02.119+0000",
      "jobs": [
        {
          "name": "job1",
          "schedule-time": "2017-03-23T20:44:02.119+0000",
          "state": "Scheduled",
          "result": "Unknown"
        },
        {
          "name": "job2",
          "schedule-time": "2017-03-23T20:44:02.119+0000",
          "state": "Scheduled",
          "result": "Unknown"
        },
        {
          "name": "job3",
          "schedule-time": "2017-03-23T20:44:02.119+0000",
          "state": "Scheduled",
          "result": "Unknown"
        }
      ]
    }
  }
}

These notifications get sent out when a stage starts. The request body will contain a JSON representing the stage that is starting.

Stage completion notifications

A sample body when a stage with one job completes successfully.

{
  "pipeline": {
    "name": "pipeline-name",
    "counter": "1",
    "label": "pipeline-label",
    "group": "pipeline-group",
    "build-cause": [
      {
        "material": {
          "git-configuration": {
            "shallow-clone": false,
            "branch": "branch",
            "url": "http://user:******@gitrepo.com"
          },
          "type": "git"
        },
        "changed": true,
        "modifications": [
          {
            "revision": "1",
            "modified-time": "2016-04-06T12:50:03.317+0000",
            "data": {}
          }
        ]
      }
    ],
    "stage": {
      "name": "stage-2",
      "counter": "1",
      "approval-type": "success",
      "approved-by": "changes",
      "previous-stage-name": "stage-1",
      "previous-stage-counter": 1,
      "state": "Passed",
      "result": "Passed",
      "create-time": "2011-07-13T19:43:37.100+0000",
      "last-transition-time": "2011-07-13T19:43:39.100+0000",
      "jobs": [
        {
          "name": "job-name",
          "schedule-time": "2011-07-13T19:43:37.100+0000",
          "assign-time": "2011-07-13T19:43:38.100+0000",
          "complete-time": "2011-07-13T19:43:39.100+0000",
          "state": "Completed",
          "result": "Passed",
          "agent-uuid": "uuid"
        }
      ]
    }
  }
}

These notifications get sent out after a stage completes. The request body will contain a JSON representing the stage that completed.

Agent Status Changed

This message is sent by the server, when it wants to notify the plugin about any change in agent state.

Agent status changed notifications only get sent when the the state of the agent has changed.

Request-Response basics

Request name

agent-status

Response code

The plugin is expected to return status 200 if it can understand the request.

Response Body

An example response body if the plugin could send the notification successfully

{
  "status": "success"
}

An example response body if the plugin could not send the notification

{
  "status": "failure",
  "messages": ["Could not send email for agent agent_hostname"]
}

The plugin is expected to return a JSON object to indicate if the notifications could be processed.

Agent state change notifications

A sample body when the agent state changes building.

{
    "agent_config_state": "enabled",
    "agent_state": "building",
    "build_state": "building",
    "is_elastic": true,
    "free_space": "100",
    "host_name": "agent_hostname",
    "ip_address": "127.0.0.1",
    "operating_system": "rh",
    "transition_time": "2018-02-15T06:31:28.998+0000",
    "uuid": "agent_uuid"
}

The agent status notifications is sent out when the state of an agent changes. The change of state can be either to agent_config_state, build_state or the agent_state. The request body will contain a JSON representing the agent.

Get Settings View

This is an optional message that the plugin may implement, should users want to configure the plugin from the GoCD admin page.

Request name

go.plugin-settings.get-view

Request body

The server will not provide a request body.

Response code

The plugin is expected to return status 200 if it can understand the request.

Response Body

A JSON settings view object

An example response body:

{
  "template": "<div>some html</div>"
}

Get Plugin Configuration

This is an optional message that the plugin may implement, should users want to configure the plugin from the GoCD admin page. This message allows the server to query a plugin about what properties are supported by this plugin.

Request name

go.plugin-settings.get-configuration

Request body

The server will not provide a request body.

Response code

The plugin is expected to return status 200 if it can understand the request.

Response Body

A JSON plugin settings configuration object.

Validate Plugin Configuration

If a plugin requires any configuration, this message must be implemented in order to validate the configuration.

Request name

go.plugin-settings.validate-configuration

Request body

An example validation request body

{
  "plugin-settings": {
      "server_url": {
        "value": "http://localhost.com"
      },
      "username": {
        "value": "user"
      },
      "password": {
        "value": "password"
      }
  }
}

The request body will contain a JSON with an attribute plugin-settings, which contains an object with the configuration keys and values that the plugin is expected to validate.

Response code

The plugin is expected to return status 200 if it can understand the request.

Response Body

The plugin should respond with JSON array response for each configuration key that has a validation error

[
  {
   "key": "server_url",
   "message": "Server URL cannot be localhost"
  }
]

If any of the input keys have a validation error on them, the plugin is expected to return a list of validation error objects. If the configuration is valid, the plugin should return an empty JSON array.

Requests to the GoCD server

The plugin may make the following requests to the server using GoApplicationAccessor#submit(GoApiRequest)

Get Plugin Settings

import com.thoughtworks.go.plugin.api.*;
import com.thoughtworks.go.plugin.api.annotation.Extension;
import com.thoughtworks.go.plugin.api.logging.Logger;
import com.thoughtworks.go.plugin.api.request.*;
import com.thoughtworks.go.plugin.api.response.*;
import com.google.gson.Gson;
import java.util.*;

@Extension
public class ConsoleLogNotificationPlugin implements GoPlugin {
  private GoApplicationAccessor accessor;
  public static final Logger LOG = Logger.getLoggerFor(ConsoleLogNotificationPlugin.class);

  public void initializeGoApplicationAccessor(GoApplicationAccessor accessor) {
    this.accessor = accessor;
  }

  public GoPluginIdentifier pluginIdentifier() {
    return new GoPluginIdentifier("notification", Arrays.asList("1.0"))
  }

  private PluginSettings getSettings() {
    Gson gson = new Gson();
    // create a request
    DefaultGoApiRequest request = new DefaultGoApiRequest(
      "go.processor.plugin-settings.get",
      "1.0",
      pluginIdentifier()
    );

    // set the request body
    Map<String, String> map = new HashMap<>();
    map.put("plugin-id", "com.example.rocket.launcher");
    request.setRequestBody(gson.toJson(map));

    // submit the request
    GoApiResponse response = accessor.submit(request);

    // check status
    if (response.responseCode() != 200) {
      LOG.error("The server sent an unexpected status code " + response.responseCode() + " with the response body " + response.responseBody());
    }

    // parse the response, using a json parser of your choice
    return gson.fromJson(response.responseBody(), PluginSettings.class);
  }
}

This messages allows a plugin to query the server to get the user configured settings for this plugin.

Request name

go.processor.plugin-settings.get

Request version

The request version must be set to 1.0.

Request body

An example request body:

{
  "plugin-id": "sample-plugin-id"
}

Must be a JSON object with a key plugin-id with the value being the ID of your plugin.

Response code

The server is expected to return status 200 if it could process the request.

Response Body

An example response body:

{
  "server_url": "https://build.go.cd",
  "username": "view",
  "password": "password"
}

The server will send a map of settings.

Get Server Info

This messages allows a plugin to query the server to get some metadata about the server.

Available since v17.9.0.

Request name

go.processor.server-info.get

Request version

The request version must be set to 1.0.

Request body

The plugin should not provide a request body.

Response code

The server is expected to return status 200 if it could process the request.

Response Body

The plugin will provide a server info object.

An example response body:

{
  "server_id": "df0cb9be-2696-4689-8d46-1ef3c4e4447c",
  "site_url": "http://example.com:8153/go",
  "secure_site_url": "https://example.com:8154/go"
}

Add Server Health Messages

import com.thoughtworks.go.plugin.api.*;
import com.thoughtworks.go.plugin.api.annotation.Extension;
import com.thoughtworks.go.plugin.api.logging.Logger;
import com.thoughtworks.go.plugin.api.request.*;
import com.thoughtworks.go.plugin.api.response.*;
import com.google.gson.Gson;
import java.util.*;

@Extension
public class ConsoleLogNotificationPlugin implements GoPlugin {
  private GoApplicationAccessor accessor;
  public static final Logger LOG = Logger.getLoggerFor(ConsoleLogNotificationPlugin.class);

  public void initializeGoApplicationAccessor(GoApplicationAccessor accessor) {
    this.accessor = accessor;
  }

  public GoPluginIdentifier pluginIdentifier() {
    return new GoPluginIdentifier("notification", Arrays.asList("2.0"));
  }

  private void addErrorsAndWarnings() {
    Gson gson = new Gson();
    // create a request
    DefaultGoApiRequest request = new DefaultGoApiRequest(
      "go.processor.server-health.add-messages",
      "1.0",
      pluginIdentifier()
    );

    // set the request body
    List<Map<String, String>> messages = new ArrayList<>();

    Map<String, String> message1 = new HashMap<>();
    message1.put("type", "warning");
    message1.put("message", "A warning message from the plugin.");

    Map<String, String> message2 = new HashMap<>();
    message2.put("type", "error");
    message2.put("message", "An error message from the plugin.");

    messages.add(message1);
    messages.add(message2);

    request.setRequestBody(gson.toJson(messages));

    // submit the request
    GoApiResponse response = accessor.submit(request);

    // check status
    if (response.responseCode() != 200) {
      LOG.error("The server sent an unexpected status code " + response.responseCode() + " with the response body " + response.responseBody());
    }
  }
}

This message allows a plugin to add error and warning messages to be shown in GoCD. Any previous messages sent by the plugin will be cleared and replaced with the newly specified messages (or cleared if the body is an empty list).

Available since v18.3.0.

Request name

go.processor.server-health.add-messages

Request version

The request version must be set to 1.0.

Request body

An example request body:

[
  {
    "type": "warning",
    "message": "A warning message from the plugin."
  },
  {
    "type": "error",
    "message": "An error message from the plugin."
  }
]

Must be a JSON array made up of JSON objects as described below:

Key Type Description
type String Should be either warning or error, corresponding to the type of message to be shown.
message String A message to be shown in the “Errors and Warnings” box.

Response code

The server is expected to return status 200 if it could process the request. It is expected to return status 500 if it failed to process the request.

Response Body

An example response body for a failure:

{
  "message": "An error occurred ..."
}

The server will respond with a single JSON object with an error message with the key message, if it is unable to process the request. If successful, the response body will be empty.

Request/Response JSON Objects

The Settings View Object

Here’s an example of the settings view object:

{
  "template": "<div class=\"form_item_block\">...</div>"
}

Attribute Type Description
template String A string containing an HTML AngularJS based view.

This template is an AngularJS based template.

GoCD uses Angular JS as its template engine for the plugin UI. This allows plugin authors to use a limited set of AngularJS features to specify how the UI of their plugins looks.

Getting started with AngularJS based templates

Given a configuration:

<configuration>
  <property>
    <key>username</key>
    <value>alice</username>
  </property>
</configuration>

This gets converted into the following JSON representation in the browser:

{
  "username": "alice"
}

The AngularJS template is expected to bind to the JSON object shown above:

<div class="form_item_block">
  <label>Username:<span class='asterix'>*</span></label>
  <input ng-model="username" />
</div>

When an Angular template is used in a Go plugin, to define the configuration UI, the configuration key which is stored in the configuration XML is used everywhere and is expected to be consistent. Since Angular works off of JSON, GoCD will make sure that the key in the JSON provided to the Angular template is the same as the key in the configuration XML.

Suppose the key of the configuration property stored in the XML is “username”, with value, “alice”, then Go will make sure that the value is available to the template as “username” when used in an Angular-specific HTML attribute like “ng-model”.

Plugin Angular Architecture

So, the name “foobar” needs to be the same across the configuration XML, the Angular template as well as in any code that the plugin has.

Showing validation errors in the UI

We use some simple string replacement
to substitute GOINPUTNAME with a unique identifier
for your plugin in order to render
any server side errors

<div class="form_item_block">
  <label>Username:<span class='asterix'>*</span></label>
  <input ng-model="username" />
  <span class="form_error" ng-show="GOINPUTNAME[username].$error.server">
    {{ GOINPUTNAME[username].$error.server}}
  </span>
</div>

In case of validation errors returned by go.plugin-settings.validate-configuration, the error messages needs to be populated on the UI, use the snippet here to show the validation errors.

The Plugin Settings Configuration Object

Here’s an example of the plugin settings configuration object:

{
  "server_url": {
    "display-name": "Server URL",
    "display-order": "0"
  },
  "username": {
    "required": false,
    "display-name": "Username",
    "display-order": "1"
  },
  "password": {
    "secure": true,
    "required": false,
    "display-name": "Password",
    "display-order": "2"
  }
}

Attribute Type Description
display-name String The name of the property.
default-value String The default value of the property.
display-order String A string containing a numerical value.
required Boolean If the field is mandatory.
secure Boolean If the data in the field should be stored encrypted.

The Validation Error Object

Here’s an example of the validation error object:

[
  {
    "key": "email_address",
    "message": "Email address is invalid"
  },
  {
    "key": "password",
    "message": "Password must be provided"
  }
]

Attribute Type Description
key String The name of configuration key that has an error.
message String The error message associated with that key.

The server info object

Here’s an example of the server info object:

{
  "server_id": "df0cb9be-2696-4689-8d46-1ef3c4e4447c",
  "site_url": "http://example.com:8153/go",
  "secure_site_url": "https://example.com:8154/go"
}

Attribute Type Description
server_id String This contains a unique identifier for this server.
site_url String This contains the site url configured for this server.
secure_site_url String This contains the secure site url configured for this server.