syncable_cli/analyzer/hadolint/rules/
dl3020.rs1use crate::analyzer::hadolint::parser::instruction::Instruction;
7use crate::analyzer::hadolint::rules::{simple_rule, SimpleRule};
8use crate::analyzer::hadolint::shell::ParsedShell;
9use crate::analyzer::hadolint::types::Severity;
10
11pub fn rule() -> SimpleRule<impl Fn(&Instruction, Option<&ParsedShell>) -> bool + Send + Sync> {
12 simple_rule(
13 "DL3020",
14 Severity::Error,
15 "Use COPY instead of ADD for files and folders",
16 |instr, _shell| {
17 match instr {
18 Instruction::Add(args, _) => {
19 args.has_url() || args.has_archive()
21 }
22 _ => true,
23 }
24 },
25 )
26}
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31 use crate::analyzer::hadolint::parser::instruction::{AddArgs, AddFlags};
32 use crate::analyzer::hadolint::rules::{Rule, RuleState};
33
34 #[test]
35 fn test_add_file() {
36 let rule = rule();
37 let mut state = RuleState::new();
38
39 let args = AddArgs::new(vec!["app.js".to_string()], "/app/");
40 let instr = Instruction::Add(args, AddFlags::default());
41 rule.check(&mut state, 1, &instr, None);
42 assert_eq!(state.failures.len(), 1);
43 assert_eq!(state.failures[0].code.as_str(), "DL3020");
44 }
45
46 #[test]
47 fn test_add_url() {
48 let rule = rule();
49 let mut state = RuleState::new();
50
51 let args = AddArgs::new(vec!["https://example.com/file.tar.gz".to_string()], "/app/");
52 let instr = Instruction::Add(args, AddFlags::default());
53 rule.check(&mut state, 1, &instr, None);
54 assert!(state.failures.is_empty());
55 }
56
57 #[test]
58 fn test_add_archive() {
59 let rule = rule();
60 let mut state = RuleState::new();
61
62 let args = AddArgs::new(vec!["app.tar.gz".to_string()], "/app/");
63 let instr = Instruction::Add(args, AddFlags::default());
64 rule.check(&mut state, 1, &instr, None);
65 assert!(state.failures.is_empty());
66 }
67
68 #[test]
69 fn test_copy_ok() {
70 let rule = rule();
71 let mut state = RuleState::new();
72
73 let instr = Instruction::Workdir("/app".to_string()); rule.check(&mut state, 1, &instr, None);
76 assert!(state.failures.is_empty());
77 }
78}