Skip to main content

opal/compiler/
instances.rs

1use crate::model::{JobDependencySpec, JobSpec, RetryPolicySpec};
2use crate::pipeline::rules::RuleEvaluation;
3use std::collections::HashMap;
4use std::time::Duration;
5
6#[derive(Clone, Debug)]
7pub struct JobVariantInfo {
8    pub name: String,
9    pub labels: HashMap<String, String>,
10    pub ordered_values: Vec<String>,
11}
12
13#[derive(Debug, Clone)]
14pub struct JobInstance {
15    pub job: JobSpec,
16    pub stage_name: String,
17    pub dependencies: Vec<String>,
18    pub rule: RuleEvaluation,
19    pub timeout: Option<Duration>,
20    pub retry: RetryPolicySpec,
21    pub interruptible: bool,
22    pub resource_group: Option<String>,
23}
24
25#[derive(Debug, Clone)]
26pub struct CompiledPipeline {
27    pub ordered: Vec<String>,
28    pub jobs: HashMap<String, JobInstance>,
29    pub dependents: HashMap<String, Vec<String>>,
30    pub order_index: HashMap<String, usize>,
31    pub variants: HashMap<String, Vec<JobVariantInfo>>,
32}
33
34impl CompiledPipeline {
35    pub fn variants_for_dependency(&self, dep: &JobDependencySpec) -> Vec<String> {
36        let Some(entries) = self.variants.get(&dep.job) else {
37            return Vec::new();
38        };
39        select_variants(entries, dep)
40            .into_iter()
41            .map(|variant| variant.name.clone())
42            .collect()
43    }
44}
45
46fn select_variants<'a>(
47    variants: &'a [JobVariantInfo],
48    dep: &JobDependencySpec,
49) -> Vec<&'a JobVariantInfo> {
50    // TODO: nested functions with filters within filters
51    // lots of if else else if
52    if let Some(filters) = &dep.parallel {
53        variants
54            .iter()
55            .filter(|variant| {
56                filters.iter().any(|filter| {
57                    filter.iter().all(|(key, value)| {
58                        variant
59                            .labels
60                            .get(key)
61                            .map(|current| current == value)
62                            .unwrap_or(false)
63                    })
64                })
65            })
66            .collect()
67    } else if let Some(expected) = &dep.inline_variant {
68        variants
69            .iter()
70            .filter(|variant| &variant.ordered_values == expected)
71            .collect()
72    } else {
73        variants.iter().collect()
74    }
75}