pipedash-plugin-bitbucket 0.13.0

Monitor and trigger Bitbucket Cloud Pipelines CI/CD
Documentation
use std::collections::HashMap;

use pipedash_plugin_api::config::{
    invalid_pipeline_id,
    PIPELINE_ID_SEPARATOR,
};
use pipedash_plugin_api::{
    ComponentFilter,
    FeedFormat,
    PluginError,
    PluginResult,
    StatusSource,
};

pub(crate) fn parse_pipeline_id(id: &str) -> PluginResult<(String, String)> {
    let (workspace, rest) = id
        .split_once(PIPELINE_ID_SEPARATOR)
        .ok_or_else(|| invalid_pipeline_id(id))?;
    let repo_slug = rest.split(PIPELINE_ID_SEPARATOR).next().unwrap_or(rest);
    Ok((workspace.to_string(), repo_slug.to_string()))
}

pub(crate) fn check_step_uuid(id: &str) -> PluginResult<()> {
    let is_uuid = id
        .strip_prefix('{')
        .and_then(|rest| rest.strip_suffix('}'))
        .is_some_and(|uuid| {
            uuid.len() == 36
                && uuid.bytes().enumerate().all(|(index, byte)| match index {
                    8 | 13 | 18 | 23 => byte == b'-',
                    _ => byte.is_ascii_hexdigit(),
                })
        });
    if is_uuid {
        Ok(())
    } else {
        Err(PluginError::InvalidConfig(format!(
            "Invalid Bitbucket step ID: {id}"
        )))
    }
}

pub(crate) fn get_api_url() -> String {
    "https://api.bitbucket.org/2.0".to_string()
}

pub(crate) fn get_auth(config: &HashMap<String, String>) -> PluginResult<(String, String)> {
    let email = config
        .get("email")
        .ok_or_else(|| PluginError::InvalidConfig("Missing Atlassian account email".to_string()))?
        .clone();

    let api_token = config
        .get("api_token")
        .ok_or_else(|| PluginError::InvalidConfig("Missing Bitbucket API token".to_string()))?
        .clone();

    Ok((email, api_token))
}

pub(crate) fn status_source() -> PluginResult<StatusSource> {
    let url = |value: &str| {
        reqwest::Url::parse(value)
            .map_err(|e| PluginError::Internal(format!("Invalid Bitbucket status URL: {e}")))
    };
    Ok(StatusSource {
        name: "Bitbucket".to_string(),
        page_url: url("https://bitbucket.status.atlassian.com/")?,
        feed_url: url("https://bitbucket.status.atlassian.com/api/v2/summary.json")?,
        format: FeedFormat::Statuspage,
        components: ComponentFilter::Ids(
            [
                "k0x2yw1435v7",
                "rzh2n85q7vtt",
                "rfzky0v13fbp",
                "c1qmcrcbc5zy",
            ]
            .map(str::to_string)
            .to_vec(),
        ),
    })
}

#[cfg(test)]
mod tests;