Plugin development
Adding a CI/CD provider to Pipedash. Covers the Plugin trait, metadata types, the crate layout, registration and the shared retry policy.
A provider in Pipedash is a Rust crate that implements the Plugin trait from pipedash-plugin-api. The trait has 21 methods. 7 are required and 14 have default bodies.
The Plugin trait
Plugin: Send + Sync uses #[async_trait].
| Method | Required or default |
|---|---|
metadata(&self) -> &PluginMetadata | Required |
initialize(&mut self, provider_id, config, http_client) -> PluginResult<()> | Required |
validate_credentials(&self) -> PluginResult<bool> | Required |
fetch_pipelines(&self) -> PluginResult<Vec<Pipeline>> | Required |
fetch_run_history(&self, pipeline_id, limit) | Required |
fetch_run_details(&self, pipeline_id, run_number) | Required |
trigger_pipeline(&self, params: TriggerParams) -> PluginResult<String> | Required |
fetch_available_pipelines(&self, params) | Default: an empty response |
fetch_organizations(&self) | Default: an empty list |
fetch_available_pipelines_filtered(&self, org, search, params) | Default: filters the discovery response by exact organization and a case-insensitive match on name, ID or description |
fetch_pipelines_paginated(&self, page, page_size) | Default: slices the complete pipeline list |
cancel_run(&self, pipeline_id, run_number) | Default: returns NotSupported |
fetch_workflow_parameters(&self, workflow_id) | Default: an empty list |
fetch_agents(&self) | Default: returns NotSupported |
fetch_artifacts(&self, run_id) | Default: returns NotSupported |
fetch_queues(&self) | Default: returns NotSupported |
get_migrations(&self) -> Vec<String> | Default: an empty list |
provider_type(&self) -> &str | Default: the provider_type from the metadata |
get_field_options(&self, field_key, config) | Default: an empty list |
check_permissions(&self) -> PluginResult<PermissionStatus> | Default: marks the permissions in the metadata as granted |
get_feature_availability(&self, status) | Default: compares each feature requirement with the granted permission names |
Errors use PluginError, which has the variants AuthenticationFailed, ApiError, InvalidConfig, PipelineNotFound, ProviderNotSupported, NetworkError, SerializationError, DatabaseError, NotSupported and Internal.
Metadata types
metadata() returns a PluginMetadata. The plugin builds it once and stores it.
| Field | Type |
|---|---|
name | String |
provider_type | String |
version | String |
description | String |
author | Option<String> |
icon | Option<String> |
config_schema | ConfigSchema |
table_schema | TableSchema |
capabilities | PluginCapabilities |
required_permissions | Vec<Permission>, default empty |
features | Vec<Feature>, default empty |
PluginCapabilities has 7 Boolean flags, all false by default: pipelines, pipeline_runs, trigger, agents, artifacts, queues and custom_tables.
ConfigSchema holds a fields: Vec<ConfigField> list. The setup dialog renders one input per field.
ConfigField field | Type |
|---|---|
key | String |
label | String |
description | Option<String> |
field_type | ConfigFieldType |
required | bool |
default_value | Option<serde_json::Value> |
options | Option<Vec<String>> |
validation_regex | Option<String> |
validation_message | Option<String> |
ConfigFieldType has 7 values: Text, Password, TextArea, Boolean, Select, MultiSelect and Number.
The GitHub plugin builds its metadata like this:
pub fn create_metadata() -> PluginMetadata {
PluginMetadata {
name: "GitHub Actions".to_string(),
provider_type: "github".to_string(),
version: "0.1.0".to_string(),
description: "Monitor and trigger GitHub Actions workflows".to_string(),
author: Some("Pipedash Team".to_string()),
icon: Some("https://cdn.simpleicons.org/github/white".to_string()),
config_schema: create_config_schema(),
table_schema: schema::create_table_schema(),
capabilities: create_capabilities(),
required_permissions: create_required_permissions(),
features: create_features(),
}
}Crate layout
Each plugin lives in crates/pipedash-plugin-{name}/src/ and splits its code into these files. The GitHub crate also has a permissions.rs.
| File | Content |
|---|---|
schema.rs | Table and column definitions for the provider |
metadata.rs | Plugin metadata, config schema and capabilities |
plugin.rs | The Plugin trait implementation |
client.rs | The API client for the provider |
mapper.rs | Conversion between provider API data and domain models |
types.rs | Provider-specific types |
config.rs | Config parsing helpers |
Registration
A new plugin needs 4 changes:
- The root
Cargo.tomllists the crate inmembersand in[workspace.dependencies]. pipedash-coredepends on the crate.- The
pluginsmodule ofpipedash-coreregisters it. The registry builder callsregistry.register(Box::new(...))for each plugin, and the plugin factory has amatcharm on theprovider_typestring. - The frontend holds any provider-specific UI.
PluginRegistry exposes register and is_registered.
Retry policy
RetryPolicy in pipedash-plugin-api retries an async operation. Its defaults are below.
| Field | Default |
|---|---|
max_retries | 3 |
initial_delay | 100 ms |
exponential_backoff | true, so the delay doubles after each failed attempt |
The policy retries only NetworkError and ApiError. Any other error returns at once.
Next step
The existing plugins serve as references. The providers index lists them, and the contributing page covers how a change reaches the repository.