package lint import ( "regexp" "github.com/vladimir/goherence/internal/parser" ) // WhenGrammarRule разрешает в `when` только чистые предикаты: // сравнения (==, !=, <, >, <=, >=), логику (and, or, not) и обращения // к переменным. Вызов функций (sprig или любых других) в when запрещён — // это первый и самый частый путь протащить в условие вычисление с // побочным эффектом (случайные числа, текущее время, счётчики). // // Реализация первой версии — не полноценный парсер выражений, а // консервативный regex-фильтр: ищем характерный синтаксис вызова функции // `имя(...)` и паттерн `| filterName` (пайп — тоже вызов функции в Go-шаблонах). // Ложные срабатывания возможны и это осознанный компромисс: лучше // требовать явный allow_shell-подобный обход, чем пропустить реальный вызов. type WhenGrammarRule struct{} func (r *WhenGrammarRule) Name() string { return "when-grammar" } var ( funcCallPattern = regexp.MustCompile(`[a-zA-Z_][a-zA-Z0-9_]*\s*\(`) pipePattern = regexp.MustCompile(`\|\s*[a-zA-Z_]`) ) func (r *WhenGrammarRule) Check(pb *parser.Playbook) []Violation { var out []Violation walkTasks(pb, func(loc string, t *parser.Task) { if t.When == "" { return } if funcCallPattern.MatchString(t.When) || pipePattern.MatchString(t.When) { out = append(out, Violation{ Rule: r.Name(), Severity: Error, Location: loc, Message: "when-выражение должно быть чистым предикатом " + "(сравнения / and / or / not над переменными), вызовы функций и " + "фильтры (|) внутри when запрещены: " + t.When, }) } }) return out }