feat: add conditional job execution and flexible needs parsing

- Add support for job-level if conditions with basic expression evaluation
- Support both string and array formats for job needs field (needs: job vs needs: [job])
- Add missing job fields: if_condition, outputs, permissions to Job struct
- Implement job condition evaluation in executor with pattern matching for:
  - Simple boolean conditions (true/false)
  - GitHub event conditions (github.event.pull_request.draft == false)
  - Job output conditions (needs.jobname.outputs.outputname == 'value')
- Jobs with false conditions are now properly skipped with appropriate logging
- Fixes parsing issues with workflows that use changes jobs and conditional execution

Resolves compatibility with workflows like iceoryx2 that use path filtering patterns.
This commit is contained in:
bahdotsh
2025-08-09 13:36:03 +05:30
parent 4251e6469d
commit cff8e3f4bd
5 changed files with 867 additions and 2 deletions

View File

@@ -1,11 +1,31 @@
use matrix::MatrixConfig;
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize};
use std::collections::HashMap;
use std::fs;
use std::path::Path;
use super::schema::SchemaValidator;
// Custom deserializer for needs field that handles both string and array formats
fn deserialize_needs<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum StringOrVec {
String(String),
Vec(Vec<String>),
}
let value = Option::<StringOrVec>::deserialize(deserializer)?;
match value {
Some(StringOrVec::String(s)) => Ok(Some(vec![s])),
Some(StringOrVec::Vec(v)) => Ok(Some(v)),
None => Ok(None),
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct WorkflowDefinition {
pub name: String,
@@ -20,7 +40,7 @@ pub struct WorkflowDefinition {
pub struct Job {
#[serde(rename = "runs-on")]
pub runs_on: String,
#[serde(default)]
#[serde(default, deserialize_with = "deserialize_needs")]
pub needs: Option<Vec<String>>,
pub steps: Vec<Step>,
#[serde(default)]
@@ -29,6 +49,12 @@ pub struct Job {
pub matrix: Option<MatrixConfig>,
#[serde(default)]
pub services: HashMap<String, Service>,
#[serde(default, rename = "if")]
pub if_condition: Option<String>,
#[serde(default)]
pub outputs: Option<HashMap<String, String>>,
#[serde(default)]
pub permissions: Option<HashMap<String, String>>,
}
#[derive(Debug, Deserialize, Serialize)]