Skip to main content

Write custom plugins

Plugins perform predefined tasks. They are essentially templated scripts that can be written in any programming language. While you can run scripts in CI pipelines, if you reuse a script, it is easier to maintain a single plugin rather than modify multiple instances of a script.

You can write your own plugins and run them in a Plugin step in your Harness CI pipelines. There are also many preexisting plugins you can use.

You can write plugins for anything. If it can be scripted, it can be a plugin. For example, you could write plugins that:

  • Scrape commit information from a Git repo.
  • Extract Jira issue numbers from Git commit messages.
  • Print an extended build history.
  • Create a file, write to it, and store it remotely.

Create your plugin

To create a plugin, you need to prepare a script, create a Docker image to run the script, and then build and publish the plugin image to a Docker registry.

  1. Write the script that you want the plugin to run. You can write plugins in any programming language. For example, the following Bash script, called clone.sh, clones a Git repo and prints the latest commit information.

    #!/bin/sh
    set -xe

    # If path setting is not set, then use current directory
    path=${PLUGIN_PATH:-.}
    mkdir -p ${path}
    cd ${path}

    # Clones the public git repo and checkout to a branch
    git clone ${PLUGIN_REPO_URL} .
    git checkout ${PLUGIN_BRANCH}

    # Prints the last commit
    git log -1 --stat
    Variables

    The above example script includes variable inputs: PLUGIN_PATH, PLUGIN_REPO_URL, and PLUGIN_BRANCH. Variables in plugin scripts become the plugin's Settings when you add the Plugin step to your CI pipeline.

  2. Create a Docker image to run your script by specifying the script as the ENTRYPOINT in a Dockerfile. For example, the following Dockerfile runs the clone.sh script:

    FROM alpine/git

    # Copies the clone script to the Docker image
    COPY clone.sh /usr/local/bin/

    # Makes the clone script executable
    RUN chmod +x /usr/local/bin/clone.sh

    ENTRYPOINT [ "/usr/local/bin/clone.sh" ]
  3. Using the method of your choice, build and publish the plugin image to a Docker registry. Take note of the Docker repo and image name, such as my-docker-repo/git-clone-plugin. You need it when you add the Plugin step to your CI pipeline.

    docker build -t my-docker-repo/git-clone-plugin .
    docker push my-docker-repo/git-clone-plugin

Test plugins locally

You can test your plugin in a local environment by running it as a Docker container. For example, the following Docker command runs the clone.sh plugin locally by supplying the required inputs (PLUGIN_PATH, PLUGIN_REPO_URL, and PLUGIN_BRANCH) and specifying the plugin's Docker repo and image (my-docker-repo/git-clone-plugin).

docker run --rm \
-e PLUGIN_PATH=codebase \
-e PLUGIN_REPO_URL=https://github.com/<some-account>/<some-repo>.git \
-e PLUGIN_BRANCH=main \
my-docker-repo/git-clone-plugin

Distribute plugins

Plugins are distributed as Docker images.

If your plugin image is private, others in your organization can use your plugin in their Harness CI pipelines by using a Docker connector configured for the private registry where your plugin image is stored.

If your plugin image is public, you can share it with anyone. You can submit a pull request to the drone-plugin-index repository if you'd like your plugin to be considered for the Drone Plugins Marketplace.

Add the Plugin step

Use a Plugin step to run a plugin in a Harness CI pipeline. The following instructions use the clone.sh plugin example from Create a plugin.

For more information about configuring Plugin steps, go to the Plugin step settings reference and Use Drone plugins.

Add the Plugin step to your CI stage. The following settings are always or usually required:

  • type: Plugin
  • name: A name for the step
  • connectorRef: The ID of a Docker connector that can connect to the Docker registry where you uploaded the plugin image.
  • image: The plugin's Docker repo and image.
  • settings: A mapping of key-value pairs representing plugin settings. Settings are derived from variables in your plugin script.

For example, the following YAML definition could be used for the clone.sh plugin:

              - step:
type: Plugin
name: git clone plugin
identifier: git_clone_plugin
spec:
connectorRef: account.docker-connector
image: my-docker-repo/git-clone-plugin
settings:
repo_url: https://github.com/<some-account>/<some-repo>.git ## URL of the repo to clone.
branch: main ## Branch to clone.
path: codebase ## Location in the stage workspace to clone the repo.

Variables in plugin scripts

Settings keys in Plugin steps originate as environment variables prefixed by PLUGIN_ in your plugin script. For example, the following script includes three variables: PLUGIN_PATH, PLUGIN_REPO_URL, and PLUGIN_BRANCH.

#!/bin/sh
set -xe

# If path setting is not set, then use current directory
path=${PLUGIN_PATH:-.}
mkdir -p ${path}
cd ${path}

# Clones the public git repo and checkout to a branch
git clone ${PLUGIN_REPO_URL} .
git checkout ${PLUGIN_BRANCH}

# Prints the last commit
git log -1 --stat

When defined in a Plugin step's Settings, don't include the PLUGIN_ prefix. For example, PLUGIN_PATH becomes path, PLUGIN_REPO_URL becomes repo_url, and PLUGIN_BRANCH becomes branch.

                settings:
path: value
repo_url: value
branch: value
Expressions and secrets

You can use Harness expressions for Settings values. For example password: <+stage.variables.[TOKEN_SECRET]> supplies a stage variable containing a secret to a setting called password.

Related to this, it is a best practice to use text secrets for sensitive information, such as passwords and tokens, required by plugins.

Custom plugin demos and examples

The following resources demonstrate how to create Drone plugins. The process for creating the plugin is the same, but, when using the plugin in a pipeline, be aware that there are differences between Drone YAML and Harness YAML.

tip

Harness CI supports DRONE_ environment variables. For more information, go to the CI environment variables reference.