use crate::component::Component;
use crate::engine::pipeline::PipelineCapabilityResolver;
use crate::error::{Error, Result};
use crate::extension::{self, ExtensionManifest};
use super::types::ReleaseStepType;
pub(crate) struct ReleaseCapabilityResolver {
extensions: Vec<ExtensionManifest>,
}
impl ReleaseCapabilityResolver {
pub fn new(extensions: Vec<ExtensionManifest>) -> Self {
Self { extensions }
}
fn supports_package(&self) -> bool {
self.extensions
.iter()
.any(|extension| extension.actions.iter().any(|a| a.id == "release.package"))
}
fn supports_publish_target(&self, target: &str) -> bool {
self.extensions.iter().any(|extension| {
extension.id == target && extension.actions.iter().any(|a| a.id == "release.publish")
})
}
}
impl PipelineCapabilityResolver for ReleaseCapabilityResolver {
fn is_supported(&self, step_type: &str) -> bool {
let st = ReleaseStepType::from_str(step_type);
match st {
ReleaseStepType::Version
| ReleaseStepType::GitCommit
| ReleaseStepType::GitTag
| ReleaseStepType::GitPush
| ReleaseStepType::Cleanup
| ReleaseStepType::PostRelease => true,
ReleaseStepType::Package => self.supports_package(),
ReleaseStepType::Publish(ref target) => self.supports_publish_target(target),
}
}
fn missing(&self, step_type: &str) -> Vec<String> {
let st = ReleaseStepType::from_str(step_type);
match st {
ReleaseStepType::Package => {
if !self.supports_package() {
vec!["Missing extension with action 'release.package'".to_string()]
} else {
Vec::new()
}
}
ReleaseStepType::Publish(ref target) => {
vec![format!(
"Missing extension '{}' with action 'release.publish'",
target
)]
}
_ => Vec::new(),
}
}
}
pub(crate) fn resolve_extensions(
component: &Component,
extension_id: Option<&str>,
) -> Result<Vec<ExtensionManifest>> {
if extension_id.is_some() {
return Err(Error::validation_invalid_argument(
"extension",
"Extension selection is configured via component.extensions; --extension is not supported",
None,
None,
));
}
let mut extensions = Vec::new();
if let Some(configured) = component.extensions.as_ref() {
let mut extension_ids: Vec<String> = configured.keys().cloned().collect();
extension_ids.sort();
let suggestions = extension::available_extension_ids();
for extension_id in extension_ids {
let manifest = extension::load_extension(&extension_id).map_err(|_| {
Error::extension_not_found(extension_id.to_string(), suggestions.clone())
})?;
extensions.push(manifest);
}
}
Ok(extensions)
}