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
use std::path::PathBuf;
use thiserror::Error;
/// Errors that can occur when working with workflow files.
#[derive(Debug, Error)]
pub enum Error {
/// Failed to scan workflow files.
#[error("failed to scan workflows: {reason}")]
ScanFailed { reason: String },
/// Failed to parse a workflow file.
#[error("failed to parse workflow {path}: {reason}")]
ParseFailed { path: String, reason: String },
/// Failed to update a workflow file.
#[error("failed to update workflow {path}: {reason}")]
UpdateFailed { path: String, reason: String },
}
/// Result of updating a single workflow file.
pub struct UpdateResult {
pub file: PathBuf,
pub changes: Vec<String>,
}
/// Trait for scanning workflow files and extracting action references.
pub trait Scanner {
/// Scan all workflow files, yielding one `LocatedAction` per step.
///
/// Each item is a `Result` — errors are per-file and do not abort the scan.
/// The caller decides whether to collect, short-circuit, or continue past errors.
fn scan(
&self,
) -> Box<dyn Iterator<Item = Result<crate::domain::workflow_actions::Located, Error>> + '_>;
/// Enumerate all workflow file paths.
///
/// Each item is a `Result` — errors are per-file.
fn scan_paths(&self) -> Box<dyn Iterator<Item = Result<std::path::PathBuf, Error>> + '_>;
/// Scan all workflow files and collect into a `Vec`. Fails on the first error.
///
/// # Errors
///
/// Returns an error if any workflow file cannot be read or parsed.
fn scan_all_located(&self) -> Result<Vec<crate::domain::workflow_actions::Located>, Error> {
self.scan().collect()
}
/// Find all workflow file paths and collect into a `Vec`.
///
/// # Errors
///
/// Returns an error if the workflow directory cannot be read.
fn find_workflow_paths(&self) -> Result<Vec<std::path::PathBuf>, Error> {
self.scan_paths().collect()
}
/// Parse every workflow once and return both the structural `Parsed` model
/// and the existing `Located` action list. The lint command uses this to
/// feed both action-hygiene rules and workflow-security rules from a single
/// parse pass.
///
/// # Errors
///
/// Returns an error if any workflow file cannot be read or parsed.
fn scan_all_with_parsed(
&self,
) -> Result<
(
Vec<crate::domain::workflow_actions::Located>,
Vec<crate::domain::workflow_parsed::Parsed>,
),
Error,
>;
}