|
| 1 | +# SPDX-License-Identifier: MPL-2.0 |
| 2 | + |
| 3 | +defmodule Hypatia.Rules.GroupBDetectorsTest do |
| 4 | + use ExUnit.Case, async: true |
| 5 | + |
| 6 | + alias Hypatia.Rules.StructuralDrift |
| 7 | + alias Hypatia.Rules.WorkflowAudit |
| 8 | + alias Hypatia.Rules.HonestCompletion |
| 9 | + |
| 10 | + describe "StructuralDrift.check_workflow_branch_refs/3 (SD021, #363)" do |
| 11 | + test "flags inline trigger branches that aren't real branches" do |
| 12 | + wf = %{"ci.yml" => "on:\n push:\n branches: [main, master, develop]\n"} |
| 13 | + findings = StructuralDrift.check_workflow_branch_refs(wf, ["main"]) |
| 14 | + assert findings |> Enum.map(& &1.branch) |> Enum.sort() == ["develop", "master"] |
| 15 | + assert hd(findings).rule == "SD021" |
| 16 | + assert hd(findings).severity == :low |
| 17 | + end |
| 18 | + |
| 19 | + test "flags block-style dead branches, exempts globs and default" do |
| 20 | + body = |
| 21 | + "on:\n pull_request:\n branches:\n - main\n - feature/*\n - legacy\n" |
| 22 | + |
| 23 | + findings = StructuralDrift.check_workflow_branch_refs(%{"ci.yml" => body}, ["main"]) |
| 24 | + assert Enum.map(findings, & &1.branch) == ["legacy"] |
| 25 | + end |
| 26 | + |
| 27 | + test "silent when all trigger branches exist" do |
| 28 | + wf = %{"ci.yml" => "on:\n push:\n branches: [main, master]\n"} |
| 29 | + assert StructuralDrift.check_workflow_branch_refs(wf, ["main", "master"]) == [] |
| 30 | + end |
| 31 | + end |
| 32 | + |
| 33 | + describe "WorkflowAudit.check_stale_continue_on_error/2 (WF023, #364)" do |
| 34 | + @coe "jobs:\n x:\n # remove when #104 lands\n continue-on-error: true\n" |
| 35 | + |
| 36 | + test "flags a continue-on-error mask gated on a closed issue" do |
| 37 | + [f] = WorkflowAudit.check_stale_continue_on_error(%{"ci.yml" => @coe}, [104]) |
| 38 | + assert f.rule == "WF023" |
| 39 | + assert f.issue == 104 |
| 40 | + assert f.severity == :medium |
| 41 | + end |
| 42 | + |
| 43 | + test "silent when the gating issue is still open" do |
| 44 | + assert WorkflowAudit.check_stale_continue_on_error(%{"ci.yml" => @coe}, []) == [] |
| 45 | + end |
| 46 | + |
| 47 | + test "silent when there is no continue-on-error" do |
| 48 | + body = "# remove when #104\n" |
| 49 | + assert WorkflowAudit.check_stale_continue_on_error(%{"ci.yml" => body}, [104]) == [] |
| 50 | + end |
| 51 | + end |
| 52 | + |
| 53 | + describe "HonestCompletion.check_stale_issue_refs/2 (#366)" do |
| 54 | + test "flags a comment referencing a closed issue" do |
| 55 | + [f] = |
| 56 | + HonestCompletion.check_stale_issue_refs(%{"x.ex" => "# blocked by #50 upstream\n"}, [50]) |
| 57 | + |
| 58 | + assert f.type == :stale_issue_reference |
| 59 | + assert f.issue == 50 |
| 60 | + end |
| 61 | + |
| 62 | + test "silent when the referenced issue is still open" do |
| 63 | + assert HonestCompletion.check_stale_issue_refs(%{"x.ex" => "# blocked by #50\n"}, []) == [] |
| 64 | + end |
| 65 | + end |
| 66 | +end |
0 commit comments