Task Plugins
Extension Information
Availability | GoCD version 15.1.0 onwards |
Extension Name | task |
Extension API Version | 1.0 |
The Task extension endpoint allows plugin authors to extend GoCD to run new tasks in addition to the defaults that GoCD provides.
If you’re looking to start away with a basic template for task plugins, we recommend forking this github repository.
Requests from GoCD
In order to implement a task point the following messages must be implemented by the plugin.
Task Configuration
An example response body:
{
"url": {
"default-value": "",
"secure": false,
"required": true
},
"user": {
"default-value": "bob",
"secure": true,
"required": true
},
"password": {}
}
This message is sent by the GoCD server to the plugin to know what properties are supported by this plugin that should to be stored in the cruise-config.xml
file.
Request name
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
The plugin is expected to return an object containing the configuration property along with task configuration properties
Task View
An example response body:
{
"displayValue": "MavenTask",
"template": "<div class=\"form_item_block\">...</div>"
}
This message is sent by the GoCD server to the plugin to get an AngularJS based HTML template to allow the task to be configured.
Request name
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
The plugin is expected to return an object containing the view rendering information task view response object
Validate Configuration
An example validation request body
{
"URL": {
"secure": false,
"value": "http://localhost.com",
"required": true
},
"USERNAME": {
"secure": false,
"value": "user",
"required": false
},
"PASSWORD": {
"secure": true,
"value": "password",
"required": false
}
}
An example response body, in case there are validation errors
{
"errors": {
"URL": "URL is not well formed",
"USERNAME": "Invalid character present"
}
}
An example response body, in case there are no validation errors
{
"errors": {}
}
This message is sent by the GoCD server to the plugin to validate if the settings entered by the user are valid, so that the server may persist those settings in the cruise-config.xml
file.
Request name
validate
Request body
The request body will contain a JSON, which contains an object with the configuration keys and values that the plugin is expected to validate. If the configuration is valid, the errors
object should be empty {}
.
Response code
The plugin is expected to return status 200
if it can understand the request.
Response Body
The plugin is expected to return an error object validation errors.
Execute Task
An example request body:
{
"config": {
"ftp_server": {
"secure": false,
"value": "ftp.example.com",
"required": true
},
"remote_dir": {
"secure": false,
"value": "/pub/",
"required": true
}
},
"context": {
"workingDirectory": "working-dir",
"environmentVariables": {
"ENV1": "VAL1",
"ENV2": "VAL2"
}
}
}
An example response body, in case of success
{
"success": true,
"message": "Finished executing task"
}
An example response body, in case of failure
{
"success": false,
"message": "Failed to execute task. The error was: 'Server not found'"
}
Here’s an example snippet of code to help execute custom commands and send their output to GoCD
import com.google.gson.GsonBuilder;
import com.thoughtworks.go.plugin.api.request.GoPluginApiRequest;
import com.thoughtworks.go.plugin.api.response.DefaultGoPluginApiResponse;
import com.thoughtworks.go.plugin.api.task.JobConsoleLogger;
import java.io.File;
import java.util.*;
public class PluginExecutor {
public DefaultGoPluginApiResponse execute(GoPluginApiRequest request) throws Exception {
JobConsoleLogger console = JobConsoleLogger.getConsoleLogger();
// create the process with the right cli args environment variables and working directory
// all this is available in the requestBody
ProcessBuilder builder = new ProcessBuilder(...);
builder.directory(...);
builder.environment().putAll(...);
// print out the environment variables to the console
console.printEnvironment(builder.environment());
// start the process
Process process = builder.start();
// ensure that the process's stderr and stdout and connected to GoCD
console.readErrorOf(process.getErrorStream());
console.readOutputOf(process.getInputStream());
// wait for the process to exit
int exitCode = process.waitFor();
if (exitCode != 0) {
// send error response
return new DefaultGoPluginApiResponse(200, "...");
} else {
// send success response
return new DefaultGoPluginApiResponse(200, "...");
}
}
}
This message is sent by the GoCD agent to the plugin to execute the task.
Request name
execute
Request body
The request body will contain a JSON containing the necessary configuration provided by the user, along with the working directory where the task is expected to run, and the environment variables configured.
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 status object indicating success
, and a message
. During the execution of the plugin, messages that need to be shown on the output console of the job can be sent to the Go Server using the an instance of JobConsoleLogger
.
Request/Response JSON Objects
The Task Configuration Response Object
Here’s an example of the task configuration response object:
{
"url": {
"default-value": "",
"secure": false,
"required": true
},
"user": {
"default-value": "bob",
"secure": true,
"required": true
},
"password": {
}
}
Attribute | Type | Description |
---|---|---|
default-value |
String | A value to be used as the default if the user provides no value. |
secure |
Boolean | If the value should be stored in an encrypted form in the cruise-config.xml file. |
required |
Boolean | Whether the field is required. |
The Task View Response Object
Here’s an example of the task view response object:
{
"displayValue": "MavenTask",
"template": "<div class=\"form_item_block\">...</div>"
}
Attribute | Type | Description |
---|---|---|
displayValue |
String | The name of the task that should be rendered in the view. |
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”.
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 substituteGOINPUTNAME
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.