syncable_cli/analyzer/dclint/rules/
dcl007.rs

1//! DCL007: require-project-name-field
2//!
3//! The `name` field should be present for explicit project naming.
4
5use crate::analyzer::dclint::rules::{LintContext, Rule, SimpleRule, make_failure};
6use crate::analyzer::dclint::types::{CheckFailure, RuleCategory, Severity};
7
8const CODE: &str = "DCL007";
9const NAME: &str = "require-project-name-field";
10const DESCRIPTION: &str = "The top-level `name` field should be set for explicit project naming.";
11const URL: &str = "https://github.com/zavoloklom/docker-compose-linter/blob/main/docs/rules/require-project-name-field-rule.md";
12
13pub fn rule() -> impl Rule {
14    SimpleRule::new(
15        CODE,
16        NAME,
17        Severity::Info,
18        RuleCategory::BestPractice,
19        DESCRIPTION,
20        URL,
21        check,
22    )
23}
24
25fn check(ctx: &LintContext) -> Vec<CheckFailure> {
26    let mut failures = Vec::new();
27
28    if ctx.compose.name.is_none() {
29        let message = "Consider adding a `name` field to explicitly set the project name instead of relying on the directory name.".to_string();
30
31        failures.push(make_failure(
32            &CODE.into(),
33            NAME,
34            Severity::Info,
35            RuleCategory::BestPractice,
36            message,
37            1,
38            1,
39            false,
40        ));
41    }
42
43    failures
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use crate::analyzer::dclint::parser::parse_compose;
50
51    fn check_yaml(yaml: &str) -> Vec<CheckFailure> {
52        let compose = parse_compose(yaml).unwrap();
53        let ctx = LintContext::new(&compose, yaml, "docker-compose.yml");
54        check(&ctx)
55    }
56
57    #[test]
58    fn test_no_violation_has_name() {
59        let yaml = r#"
60name: myproject
61services:
62  web:
63    image: nginx
64"#;
65        assert!(check_yaml(yaml).is_empty());
66    }
67
68    #[test]
69    fn test_violation_no_name() {
70        let yaml = r#"
71services:
72  web:
73    image: nginx
74"#;
75        let failures = check_yaml(yaml);
76        assert_eq!(failures.len(), 1);
77        assert!(failures[0].message.contains("name"));
78    }
79}