1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use crate::models::ValidationResult;
use crate::validators::{validate_matrix, validate_steps};
use serde_yaml::Value;
pub fn validate_jobs(jobs: &Value, result: &mut ValidationResult) {
if let Value::Mapping(jobs_map) = jobs {
if jobs_map.is_empty() {
result.add_issue("'jobs' section is empty".to_string());
return;
}
for (job_name, job_config) in jobs_map {
if let Some(job_name) = job_name.as_str() {
if let Some(job_config) = job_config.as_mapping() {
// Check for required 'runs-on'
if !job_config.contains_key(&Value::String("runs-on".to_string())) {
result.add_issue(format!("Job '{}' is missing 'runs-on' field", job_name));
}
// Check for steps
match job_config.get(&Value::String("steps".to_string())) {
Some(Value::Sequence(steps)) => {
if steps.is_empty() {
result.add_issue(format!(
"Job '{}' has empty 'steps' section",
job_name
));
} else {
validate_steps(steps, job_name, result);
}
}
Some(_) => {
result.add_issue(format!(
"Job '{}': 'steps' section is not a sequence",
job_name
));
}
None => {
result.add_issue(format!(
"Job '{}' is missing 'steps' section",
job_name
));
}
}
// Check for job dependencies
if let Some(Value::Sequence(needs)) =
job_config.get(&Value::String("needs".to_string()))
{
for need in needs {
if let Some(need_str) = need.as_str() {
if !jobs_map.contains_key(&Value::String(need_str.to_string())) {
result.add_issue(format!(
"Job '{}' depends on non-existent job '{}'",
job_name, need_str
));
}
}
}
} else if let Some(Value::String(need)) =
job_config.get(&Value::String("needs".to_string()))
{
if !jobs_map.contains_key(&Value::String(need.clone())) {
result.add_issue(format!(
"Job '{}' depends on non-existent job '{}'",
job_name, need
));
}
}
// Validate matrix configuration if present
if let Some(matrix) = job_config.get(&Value::String("matrix".to_string())) {
validate_matrix(matrix, result);
}
} else {
result.add_issue(format!("Job '{}' configuration is not a mapping", job_name));
}
}
}
}
}