syncable_cli/analyzer/hadolint/rules/
dl3057.rs1use crate::analyzer::hadolint::parser::instruction::Instruction;
7use crate::analyzer::hadolint::rules::{CheckFailure, RuleState, VeryCustomRule, very_custom_rule};
8use crate::analyzer::hadolint::shell::ParsedShell;
9use crate::analyzer::hadolint::types::Severity;
10
11pub fn rule() -> VeryCustomRule<
12 impl Fn(&mut RuleState, u32, &Instruction, Option<&ParsedShell>) + Send + Sync,
13 impl Fn(RuleState) -> Vec<CheckFailure> + Send + Sync,
14> {
15 very_custom_rule(
16 "DL3057",
17 Severity::Info,
18 "HEALTHCHECK instruction missing.",
19 |state, _line, instr, _shell| {
21 if matches!(instr, Instruction::Healthcheck(_)) {
22 state.data.set_bool("has_healthcheck", true);
23 }
24 if !matches!(instr, Instruction::From(_) | Instruction::Comment(_)) {
26 state.data.set_bool("has_instructions", true);
27 }
28 },
29 |state| {
31 if !state.data.get_bool("has_healthcheck") && state.data.get_bool("has_instructions") {
33 let mut failures = state.failures;
34 failures.push(CheckFailure::new(
35 "DL3057",
36 Severity::Info,
37 "HEALTHCHECK instruction missing.",
38 1,
39 ));
40 failures
41 } else {
42 state.failures
43 }
44 },
45 )
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use crate::analyzer::hadolint::config::HadolintConfig;
52 use crate::analyzer::hadolint::lint::{LintResult, lint};
53
54 fn lint_dockerfile(content: &str) -> LintResult {
55 lint(content, &HadolintConfig::default())
56 }
57
58 #[test]
59 fn test_missing_healthcheck() {
60 let result = lint_dockerfile("FROM ubuntu:20.04\nRUN echo hello");
61 assert!(result.failures.iter().any(|f| f.code.as_str() == "DL3057"));
62 }
63
64 #[test]
65 fn test_has_healthcheck() {
66 let result = lint_dockerfile(
67 "FROM ubuntu:20.04\nHEALTHCHECK CMD curl -f http://localhost/ || exit 1",
68 );
69 assert!(!result.failures.iter().any(|f| f.code.as_str() == "DL3057"));
70 }
71
72 #[test]
73 fn test_healthcheck_none() {
74 let result = lint_dockerfile("FROM ubuntu:20.04\nHEALTHCHECK NONE");
75 assert!(!result.failures.iter().any(|f| f.code.as_str() == "DL3057"));
76 }
77}