#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Server URL is required.\n Set via: --server, DEVELOCITY_SERVER env var, or server in ~/.develocity/config.toml")]
MissingServer,
#[error("Access token is required.\n Set via: --token, DEVELOCITY_API_KEY env var, or token in ~/.develocity/config.toml")]
MissingToken,
#[error("Invalid server URL: {0}")]
InvalidUrl(#[from] url::ParseError),
#[error("HTTP request failed: {0}")]
Http(#[from] reqwest::Error),
#[error("Request timed out after {0} seconds")]
Timeout(u64),
#[error(
"Authentication failed (401).\n Check your access key or token is valid and not expired."
)]
Unauthorized,
#[error(
"Access denied (403).\n Ensure you have the 'Access build data via the API' permission."
)]
Forbidden,
#[error("Build not found: {0}\n Verify the Build Scan ID is correct.")]
BuildNotFound(String),
#[error(
"Build '{0}' is not a Gradle build (type: {1}).\n This CLI only supports Gradle builds."
)]
NotGradleBuild(String, String),
#[error("API error ({status}): {message}")]
ApiError { status: u16, message: String },
#[error("Failed to parse API response: {0}")]
Parse(String),
#[error("Failed to read config file '{path}': {source}")]
ConfigRead {
path: String,
#[source]
source: std::io::Error,
},
#[error("Failed to parse config file '{path}': {source}")]
ConfigParse {
path: String,
#[source]
source: toml::de::Error,
},
}
impl Error {
pub fn exit_code(&self) -> i32 {
match self {
Error::MissingServer
| Error::MissingToken
| Error::InvalidUrl(_)
| Error::ConfigRead { .. }
| Error::ConfigParse { .. } => 1,
Error::Http(_) | Error::Timeout(_) => 2,
Error::Unauthorized | Error::Forbidden => 3,
Error::BuildNotFound(_) => 4,
Error::NotGradleBuild(_, _) => 5,
Error::ApiError { .. } | Error::Parse(_) => 6,
}
}
}
pub type Result<T> = std::result::Result<T, Error>;
pub mod exit_codes {
pub const SUCCESS: i32 = 0;
pub const CONFIG_ERROR: i32 = 1;
pub const NETWORK_ERROR: i32 = 2;
pub const AUTH_ERROR: i32 = 3;
pub const NOT_FOUND: i32 = 4;
pub const WRONG_BUILD_TYPE: i32 = 5;
pub const API_ERROR: i32 = 6;
}