use std::borrow::Borrow; use std::borrow::Cow; use kube::api::PostParams; use kube::Api; use kube::CustomResourceExt; use regex::Regex; use tracing::debug; use tracing::info; use crate::crd_pipeline_run::PipelineParam; use crate::crd_pipeline_run::PipelineRun; use crate::discovery::PipelineTemplate; use crate::hook_push::HookPush; use crate::hook_push::PipelineParamters; pub(crate) async fn run_pipelines( hook: HookPush, pipelines: Vec, kubernetes_client: kube::Client, ) -> Result<(), Box> { // let jobs: Api = Api::namespaced(kubernetes_client, "webhook-bridge"); let jobs: Api = Api::default_namespaced(kubernetes_client); tracing::debug!("Using crd: {}", serde_json::to_string(&PipelineRun::crd())?); for mut pipeline in pipelines { info!( "Kicking off {} for repo {}/{}", pipeline.name, hook.get_repo_owner()?, hook.get_repo_name()?, ); if pipeline.pipeline.spec.params.is_none() { pipeline.pipeline.spec.params = Some(Vec::new()); } if let Some(param_list) = pipeline.pipeline.spec.params.as_mut() { param_list.push(PipelineParam { name: Some("JOB_NAME".to_owned()), value: Some(serde_json::Value::String(pipeline.name.clone())), }); param_list.push(PipelineParam { name: Some("REPO_OWNER".to_owned()), value: Some(serde_json::Value::String( hook.get_repo_owner()?.into_owned(), )), }); param_list.push(PipelineParam { name: Some("REPO_NAME".to_owned()), value: Some(serde_json::Value::String( hook.get_repo_name()?.into_owned(), )), }); let hook_repo_url = hook.get_repo_url()?; param_list.push(PipelineParam { name: Some("REPO_URL".to_owned()), value: pipeline .clone_uri .map(|uri| serde_json::Value::String(uri)) .or_else(|| Some(serde_json::Value::String(hook_repo_url.into_owned()))), }); param_list.push(PipelineParam { name: Some("PULL_BASE_SHA".to_owned()), value: Some(serde_json::Value::String( hook.get_pull_base_sha()?.into_owned(), )), }); param_list.push(PipelineParam { name: Some("PULL_BASE_REF".to_owned()), value: Some(serde_json::Value::String( hook.get_pull_base_ref()?.into_owned(), )), }); } if pipeline.pipeline.metadata.generate_name.is_none() && pipeline.pipeline.metadata.name.is_some() { std::mem::swap( &mut pipeline.pipeline.metadata.generate_name, &mut pipeline.pipeline.metadata.name, ); if let Some(ref mut name) = pipeline.pipeline.metadata.generate_name { let mut new_name_stub = sanitize_kubernetes_identifier(format!( "{}-{}-{}", name, hook.get_repo_name()?, hook.get_repo_owner()? ))? .into_owned(); new_name_stub.truncate(63); (*name) = new_name_stub + "-"; debug!("Using generate name: {}", name); } } let pp = PostParams::default(); let created_run = jobs.create(&pp, &pipeline.pipeline).await?; info!("Created PipelineRun {:?}", created_run.metadata.name); } Ok(()) } fn sanitize_kubernetes_identifier<'a, O: Into>>( original: O, ) -> Result, Box> { let validate_identifier_regex = Regex::new(r"[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*")?; let original = original.into(); if !validate_identifier_regex.is_match(original.borrow()) { return Ok(original); } let mut clean_identifier = String::with_capacity(original.len()); for c in original.chars() { match c { 'a'..='z' | 'A'..='Z' | '0'..='9' | '.' | '-' => { clean_identifier.push(c); } _ => { clean_identifier.push('-'); } }; } Ok(Cow::Owned(clean_identifier)) }