summaryrefslogtreecommitdiffstats
path: root/test/test_eco.py
blob: 6463b7173d9e1e9b14f6c1206d8ae653d949afec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"""Test a set of 3rd party Ansible repositories for possible regressions."""
import os
import pathlib
import re
import shlex
import subprocess

import pytest

from ansiblelint.testing import run_ansible_lint

eco_repos = {
    "bootstrap": "https://github.com/robertdebock/ansible-role-bootstrap",
    "cisco.nxos": "https://github.com/ansible-collections/cisco.nxos",
    "colsystem": "https://github.com/devroles/ansible_collection_system",
    "debops": "https://github.com/debops/debops",
    "docker-rootless": "https://github.com/konstruktoid/ansible-docker-rootless",
    "hardening": "https://github.com/konstruktoid/ansible-role-hardening",
    "mysql": "https://github.com/geerlingguy/ansible-role-mysql.git",
}


def sanitize_output(text: str) -> str:
    """Make the output less likely to vary between runs or minor changes."""
    # replace full path to home directory with ~.
    result = text.replace(os.path.expanduser("~"), "~")
    # removes warning related to PATH alteration
    result = re.sub(
        r"^WARNING: PATH altered to include.+\n", "", result, flags=re.MULTILINE
    )
    # replace venv path
    result = result.replace(".tox/venv", ".tox/eco")

    return result


@pytest.mark.eco()
@pytest.mark.parametrize(("repo"), (eco_repos.keys()))
def test_eco(repo: str) -> None:
    """Test a set of 3rd party Ansible repositories for possible regressions."""
    url = eco_repos[repo]
    cache_dir = os.path.expanduser("~/.cache/ansible-lint-eco")
    my_dir = (pathlib.Path(__file__).parent / "eco").resolve()
    os.makedirs(cache_dir, exist_ok=True)
    # clone repo
    if os.path.exists(f"{cache_dir}/{repo}/.git"):
        subprocess.run("git pull", cwd=f"{cache_dir}/{repo}", shell=True, check=True)
    else:
        subprocess.run(
            f"git clone --recurse-submodules {url} {cache_dir}/{repo}",
            shell=True,
            check=True,
        )
    # run ansible lint and paths from user home in order to produce
    # consistent results regardless on its location.
    for step in ["before", "after"]:
        args = ["-f", "pep8"]
        executable = (
            "ansible-lint"
            if step == "after"
            else f"{pathlib.Path(__file__).parent.parent}/.tox/venv/bin/ansible-lint"
        )
        result = run_ansible_lint(
            *args,
            executable=executable,
            cwd=f"{cache_dir}/{repo}",
        )

        # Ensure that cmd looks the same for later diff, even if the path was different
        result.args[0] = "ansible-lint"
        # sort stderr because parallel runs can
        result.stderr = "\n".join(sorted(result.stderr.split("\n")))

        result_txt = f"CMD: {shlex.join(result.args)}\n\nRC: {result.returncode}\n\nSTDERR:\n{result.stderr}\n\nSTDOUT:\n{result.stdout}"

        os.makedirs(f"{my_dir}/{step}", exist_ok=True)
        with open(f"{my_dir}/{step}/{repo}.result", "w", encoding="utf-8") as f:
            f.write(sanitize_output(result_txt))

    # fail if result is different than our expected one
    result = subprocess.run(
        f"git --no-pager diff --exit-code --no-index test/eco/before/{repo}.result test/eco/after/{repo}.result",
        shell=True,
        check=False,
        capture_output=True,
        text=True,
    )
    assert result.returncode == 0, result_txt + f"\nDIFF:\n{result.stdout}"