opal/compiler/
instances.rs1use 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 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}