#[derive(Debug, Clone)]
pub struct PipelineConfig {
pub platform: String,
pub trigger: String,
pub branches: Vec<String>,
pub secret_name: String,
}
#[derive(Debug, Clone)]
pub struct BuildStage {
pub name: String,
pub runs_on: String,
pub steps: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct TestStage {
pub name: String,
pub runs_on: String,
pub steps: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct DeployStage {
pub name: String,
pub environment: String,
pub runs_on: String,
pub steps: Vec<String>,
}
#[derive(Debug, Clone)]
pub enum PipelineStage {
Build {
name: String,
runs_on: String,
steps: Vec<String>,
},
Test {
name: String,
runs_on: String,
steps: Vec<String>,
},
Deploy {
name: String,
environment: String,
runs_on: String,
steps: Vec<String>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub enum PipelineStatus {
Pending,
Running,
Success,
Failed,
Cancelled,
}
#[derive(Debug, Clone)]
pub enum PipelineEvent {
Push,
PullRequest,
Release,
Schedule,
Manual,
}
#[derive(Debug, Clone)]
pub struct PipelineCache {
pub paths: Vec<String>,
pub key: String,
pub restore_keys: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct PipelineArtifact {
pub name: String,
pub path: String,
pub retention_days: u32,
}
#[derive(Debug, Clone)]
pub struct PipelineSecret {
pub name: String,
pub description: String,
}
#[derive(Debug, Clone)]
pub struct GitHubActionsWorkflow {
pub file_name: String,
pub name: String,
pub description: String,
pub on: Vec<String>,
pub events: Vec<String>,
pub stages: Vec<PipelineStage>,
pub cache: Option<PipelineCache>,
pub artifacts: Vec<String>,
pub secrets: Vec<String>,
pub status: PipelineStatus,
}
impl GitHubActionsWorkflow {
pub fn new(file_name: String, name: String) -> Self {
Self {
file_name,
name,
description: String::new(),
on: Vec::new(),
events: Vec::new(),
stages: Vec::new(),
cache: None,
artifacts: Vec::new(),
secrets: Vec::new(),
status: PipelineStatus::Pending,
}
}
pub fn description(mut self, description: String) -> Self {
self.description = description;
self
}
pub fn on(mut self, event: String) -> Self {
self.on.push(event);
self
}
pub fn add_event_listener(&mut self, event: String) {
self.events.push(event);
}
pub fn add_stage(&mut self, stage: PipelineStage) {
self.stages.push(stage);
}
pub fn enable_cache(&mut self, path: String, key: String) {
let cache: _ = PipelineCache {
paths: vec![path],
key,
restore_keys: Vec::new(),
};
self.cache = Some(cache);
}
pub fn add_artifact(&mut self, artifact: String) {
self.artifacts.push(artifact);
}
pub fn add_secret(&mut self, secret: String) {
self.secrets.push(secret);
}
pub fn set_status(&mut self, status: PipelineStatus) {
self.status = status;
}
pub fn get_file_name(&self) -> &str {
&self.file_name
}
}
#[derive(Debug, Clone)]
pub struct GitLabCIPipeline {
pub name: String,
pub description: String,
pub environment: String,
pub stages: Vec<String>,
pub jobs: std::collections::HashMap<String, PipelineJob>,
pub variables: std::collections::HashMap<String, String>,
pub cache: Option<PipelineCache>,
pub artifacts: Vec<PipelineArtifact>,
pub secrets: Vec<String>,
pub status: PipelineStatus,
}
#[derive(Debug, Clone)]
pub struct PipelineJob {
pub name: String,
pub stage: String,
pub steps: Vec<String>,
pub tags: Vec<String>,
pub dependencies: Vec<String>,
}
impl GitLabCIPipeline {
pub fn new(name: String, environment: String) -> Self {
Self {
name,
description: String::new(),
environment,
stages: Vec::new(),
jobs: std::collections::HashMap::new(),
variables: std::collections::HashMap::new(),
cache: None,
artifacts: Vec::new(),
secrets: Vec::new(),
status: PipelineStatus::Pending,
}
}
pub fn description(mut self, description: String) -> Self {
self.description = description;
self
}
pub fn add_stage(&mut self, stage: String) {
self.stages.push(stage);
}
pub fn has_stage(&self, stage: &str) -> bool {
self.stages.contains(&stage.to_string())
}
pub fn add_job(&mut self, name: String, stage: String, steps: Vec<String>) {
let job: _ = PipelineJob {
name: name.clone(),
stage,
steps,
tags: Vec::new(),
dependencies: Vec::new(),
};
self.jobs.insert(name, job);
}
pub fn has_job(&self, name: &str) -> bool {
self.jobs.contains_key(name)
}
pub fn add_variable(&mut self, key: String, value: String) {
self.variables.insert(key, value);
}
pub fn add_artifact(&mut self, artifact: PipelineArtifact) {
self.artifacts.push(artifact);
}
pub fn add_secret(&mut self, secret: String) {
self.secrets.push(secret);
}
pub fn set_status(&mut self, status: PipelineStatus) {
self.status = status;
}
}
#[derive(Debug, Clone)]
pub struct JenkinsPipeline {
pub name: String,
pub description: String,
pub stages: Vec<JenkinsStage>,
pub agent: String,
pub post: Vec<String>,
pub environment: std::collections::HashMap<String, String>,
pub tools: std::collections::HashMap<String, String>,
pub status: PipelineStatus,
}
#[derive(Debug, Clone)]
pub struct JenkinsStage {
pub name: String,
pub steps: Vec<String>,
}
impl JenkinsPipeline {
pub fn new(name: String) -> Self {
Self {
name,
description: String::new(),
stages: Vec::new(),
agent: "kubernetes".to_string(),
post: vec!["always".to_string(), "cleanup".to_string()],
environment: std::collections::HashMap::new(),
tools: std::collections::HashMap::new(),
status: PipelineStatus::Pending,
}
}
pub fn description(mut self, description: String) -> Self {
self.description = description;
self
}
pub fn add_stage(&mut self, name: String, steps: Vec<String>) {
let stage: _ = JenkinsStage { name, steps };
self.stages.push(stage);
}
pub fn agent(mut self, agent: String) -> Self {
self.agent = agent;
self
}
pub fn add_post(&mut self, action: String) {
self.post.push(action);
}
pub fn add_env_var(&mut self, key: String, value: String) {
self.environment.insert(key, value);
}
pub fn add_tool(&mut self, name: String, version: String) {
self.tools.insert(name, version);
}
pub fn set_status(&mut self, status: PipelineStatus) {
self.status = status;
}
}
pub struct PipelineManager {
platform: String,
pub workflows: Vec<GitHubActionsWorkflow>,
pub pipelines: Vec<GitLabCIPipeline>,
pub jenkins_pipelines: Vec<JenkinsPipeline>,
}
impl PipelineManager {
pub fn new(platform: String) -> Self {
Self {
platform,
workflows: Vec::new(),
pipelines: Vec::new(),
jenkins_pipelines: Vec::new(),
}
}
pub fn add_workflow(&mut self, workflow: GitHubActionsWorkflow) {
self.workflows.push(workflow);
}
pub fn get_workflow(&self, file_name: &str) -> Option<&GitHubActionsWorkflow> {
self.workflows.iter().find(|w| w.file_name == file_name)
}
pub fn add_pipeline(&mut self, pipeline: GitLabCIPipeline) {
self.pipelines.push(pipeline);
}
pub fn get_pipeline(&self, name: &str) -> Option<&GitLabCIPipeline> {
self.pipelines.iter().find(|p| p.name == name)
}
pub fn add_jenkins_pipeline(&mut self, pipeline: JenkinsPipeline) {
self.jenkins_pipelines.push(pipeline);
}
pub fn get_jenkins_pipeline(&self, name: &str) -> Option<&JenkinsPipeline> {
self.jenkins_pipelines.iter().find(|p| p.name == name)
}
pub fn get_platform(&self) -> &str {
&self.platform
}
pub fn get_workflows(&self) -> &[GitHubActionsWorkflow] {
&self.workflows
}
pub fn get_pipelines(&self) -> &[GitLabCIPipeline] {
&self.pipelines
}
pub fn get_jenkins_pipelines(&self) -> &[JenkinsPipeline] {
&self.jenkins_pipelines
}
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Invalid platform: {0}")]
InvalidPlatform(String),
#[error("Workflow not found: {file_name}")]
WorkflowNotFound { file_name: String },
#[error("Pipeline not found: {name}")]
PipelineNotFound { name: String },
#[error("Stage not found: {name}")]
StageNotFound { name: String },
#[error("Pipeline error: {0}")]
PipelineError(String),
#[error("Configuration error: {0}")]
ConfigurationError(String),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_github_actions_workflow() {
let mut workflow =
GitHubActionsWorkflow::new("ci.yml".to_string(), "Build and Test".to_string());
workflow.add_event_listener("push".to_string());
workflow.add_stage(PipelineStage::Build {
name: "build".to_string(),
runs_on: "ubuntu-latest".to_string(),
steps: vec!["npm run build".to_string()],
});
assert_eq!(workflow.stages.len(), 1);
assert!(workflow.events.contains(&"push".to_string()));
}
#[test]
fn test_gitlab_ci_pipeline() {
let mut pipeline =
GitLabCIPipeline::new("amberjs-pipeline".to_string(), "production".to_string());
pipeline.add_stage("build".to_string());
pipeline.add_job(
"build-job".to_string(),
"build".to_string(),
vec!["docker build -t amberjs .".to_string()],
);
assert_eq!(pipeline.stages.len(), 1);
assert!(pipeline.has_job("build-job"));
}
#[test]
fn test_jenkins_pipeline() {
let mut pipeline = JenkinsPipeline::new("amberjs-pipeline".to_string());
pipeline.add_stage("Build".to_string(), vec!["sh 'npm install'".to_string()]);
assert_eq!(pipeline.stages.len(), 1);
assert_eq!(pipeline.agent, "kubernetes");
}
#[test]
fn test_pipeline_manager() {
let mut manager = PipelineManager::new("github".to_string());
let workflow: _ =
GitHubActionsWorkflow::new("ci.yml".to_string(), "Build and Test".to_string());
manager.add_workflow(workflow);
assert_eq!(manager.workflows.len(), 1);
assert!(manager.get_workflow("ci.yml").is_some());
}
#[test]
fn test_pipeline_status() {
let workflow: _ =
GitHubActionsWorkflow::new("ci.yml".to_string(), "Build and Test".to_string());
assert_eq!(workflow.status, PipelineStatus::Pending);
}
}
use std::collections::{BTreeMap, HashMap};