54b5850835
Add rule GL033 that warns when every rule in a job's rules: block has an explicit when: never, making the job permanently excluded from any pipeline run. This is a pure static check — no if: evaluation or context required. Only rules with literal when: never trigger it; rules with no when: (defaults to on_success), when: manual, when: always, or when: on_failure are treated as reachable. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
91 lines
1.9 KiB
Go
91 lines
1.9 KiB
Go
package linter
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.k3nny.fr/glint/internal/model"
|
|
)
|
|
|
|
func TestCheckDeadRules(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
rules []model.Rule
|
|
wantHit bool // whether GL033 should fire
|
|
}{
|
|
{
|
|
name: "no rules — not dead",
|
|
rules: nil,
|
|
wantHit: false,
|
|
},
|
|
{
|
|
name: "single bare when:never — dead",
|
|
rules: []model.Rule{{When: "never"}},
|
|
wantHit: true,
|
|
},
|
|
{
|
|
name: "all rules when:never with if — dead",
|
|
rules: []model.Rule{
|
|
{If: `$CI_COMMIT_BRANCH == "main"`, When: "never"},
|
|
{If: `$CI_COMMIT_BRANCH == "develop"`, When: "never"},
|
|
{When: "never"},
|
|
},
|
|
wantHit: true,
|
|
},
|
|
{
|
|
name: "first rule on_success — not dead",
|
|
rules: []model.Rule{
|
|
{If: `$CI_COMMIT_BRANCH == "main"`, When: "on_success"},
|
|
{When: "never"},
|
|
},
|
|
wantHit: false,
|
|
},
|
|
{
|
|
name: "rule with empty when (defaults to on_success) — not dead",
|
|
rules: []model.Rule{
|
|
{If: `$CI_COMMIT_BRANCH == "main"`},
|
|
{When: "never"},
|
|
},
|
|
wantHit: false,
|
|
},
|
|
{
|
|
name: "when:manual — not dead",
|
|
rules: []model.Rule{{When: "manual"}},
|
|
wantHit: false,
|
|
},
|
|
{
|
|
name: "when:always — not dead",
|
|
rules: []model.Rule{{When: "always"}},
|
|
wantHit: false,
|
|
},
|
|
{
|
|
name: "when:on_failure — not dead",
|
|
rules: []model.Rule{{When: "on_failure"}},
|
|
wantHit: false,
|
|
},
|
|
{
|
|
name: "mixed never and manual — not dead",
|
|
rules: []model.Rule{
|
|
{If: `$CI_COMMIT_BRANCH == "main"`, When: "never"},
|
|
{When: "manual"},
|
|
},
|
|
wantHit: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
job := model.Job{Rules: tc.rules}
|
|
findings := checkDeadRules("test-job", job)
|
|
hit := false
|
|
for _, f := range findings {
|
|
if f.Rule == RuleDeadRules {
|
|
hit = true
|
|
}
|
|
}
|
|
if hit != tc.wantHit {
|
|
t.Errorf("checkDeadRules: got hit=%v, want hit=%v; findings=%v", hit, tc.wantHit, findings)
|
|
}
|
|
})
|
|
}
|
|
}
|