diff --git a/.drone.jsonnet b/.drone.jsonnet index 621d169..db0e5a5 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -1,34 +1,89 @@ -local PipelineEmvironment(pyversion="2.7", ansibleversion="2.4") = { - name: "ansible" + ansibleversion, +local PythonVersions(pyversion="2.7", py="27") = { + name: "python" + pyversion + "-ansible", image: "python:" + pyversion, pull: "always", + environment: { + PY_COLORS: 1 + }, commands: [ - "pip install -q ansible~=" + ansibleversion, - "pip install -q -r tests/requirements.txt", - "pip install -q .", - "ansible-later -c tests/config/config.ini tests/data/yaml_success.yml" + "pip install tox -qq", + "tox -e $(tox -l | grep py" + py + " | xargs | sed 's/ /,/g') -q", ], depends_on: [ "clone", ], }; -local PipelineTesting(pyversion="2.7") = { +local PipelineTesting = { kind: "pipeline", - name: "python-" + pyversion, + name: "testing", platform: { os: "linux", arch: "amd64", }, steps: [ - PipelineEmvironment(pyversion, ansibleversion="2.4"), - PipelineEmvironment(pyversion, ansibleversion="2.5"), - PipelineEmvironment(pyversion, ansibleversion="2.6"), - PipelineEmvironment(pyversion, ansibleversion="2.7"), + PythonVersions(pyversion="2.7", py="27"), + PythonVersions(pyversion="3.5", py="35"), + PythonVersions(pyversion="3.6", py="36"), + PythonVersions(pyversion="3.7", py="37"), + { + name: "python-flake8", + image: "python:3.7", + pull: "always", + environment: { + PY_COLORS: 1 + }, + commands: [ + "pip install -r test-requirements.txt -qq", + "pip install -qq .", + "flake8 ./ansiblelater", + ], + depends_on: [ + "clone", + ], + }, + { + name: "python-bandit", + image: "python:3.7", + pull: "always", + environment: { + PY_COLORS: 1 + }, + commands: [ + "pip install -r test-requirements.txt -qq", + "pip install -qq .", + "bandit -r ./ansiblelater", + ], + depends_on: [ + "clone", + ], + }, + { + name: "codecov", + image: "python:3.7", + pull: "always", + environment: { + PY_COLORS: 1, + CODECOV_TOKEN: { "from_secret": "codecov_token" }, + }, + commands: [ + "pip install codecov", + "codecov" + ], + depends_on: [ + "python2.7-ansible", + "python3.5-ansible", + "python3.6-ansible", + "python3.7-ansible" + ], + } ], + trigger: { + ref: ["refs/heads/master", "refs/tags/**", "refs/pull/**"], + }, }; -local PipelineBuild(depends_on=[]) = { +local PipelineBuild = { kind: "pipeline", name: "build", platform: { @@ -63,6 +118,11 @@ local PipelineBuild(depends_on=[]) = { detach_sign: true, files: [ "dist/*" ], }, + when: { + event: { + exclude: ['pull_request'], + }, + }, }, { name: "publish-github", @@ -70,7 +130,10 @@ local PipelineBuild(depends_on=[]) = { pull: "always", settings: { api_key: { "from_secret": "github_token"}, + overwrite: true, files: ["dist/*", "sha256sum.txt"], + title: "${DRONE_TAG}", + note: "CHANGELOG.md", }, when: { event: [ "tag" ], @@ -91,7 +154,12 @@ local PipelineBuild(depends_on=[]) = { }, }, ], - depends_on: depends_on, + depends_on: [ + "testing", + ], + trigger: { + ref: ["refs/heads/master", "refs/tags/**", "refs/pull/**"], + }, }; local PipelineNotifications = { @@ -118,20 +186,13 @@ local PipelineNotifications = { "build", ], trigger: { - status: [ "success", "failure", "skipped" ], + ref: ["refs/heads/master", "refs/tags/**"], + status: [ "success", "failure" ], }, }; [ - PipelineTesting(pyversion="2.7"), - PipelineTesting(pyversion="3.5"), - PipelineTesting(pyversion="3.6"), - PipelineTesting(pyversion="3.7"), - PipelineBuild(depends_on=[ - 'python-2.7', - 'python-3.5', - 'python-3.6', - 'python-3.7', - ]), + PipelineTesting, + PipelineBuild, PipelineNotifications, ] diff --git a/.drone.yml b/.drone.yml index 1729bb7..e8f7337 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,214 +1,101 @@ --- kind: pipeline -name: python-2.7 +name: testing platform: os: linux arch: amd64 steps: -- name: ansible2.4 +- name: python2.7-ansible pull: always image: python:2.7 commands: - - pip install -q ansible~=2.4 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml + - pip install tox -qq + - "tox -e $(tox -l | grep py27 | xargs | sed 's/ /,/g') -q" + environment: + PY_COLORS: 1 depends_on: - clone -- name: ansible2.5 - pull: always - image: python:2.7 - commands: - - pip install -q ansible~=2.5 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml - depends_on: - - clone - -- name: ansible2.6 - pull: always - image: python:2.7 - commands: - - pip install -q ansible~=2.6 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml - depends_on: - - clone - -- name: ansible2.7 - pull: always - image: python:2.7 - commands: - - pip install -q ansible~=2.7 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml - depends_on: - - clone - ---- -kind: pipeline -name: python-3.5 - -platform: - os: linux - arch: amd64 - -steps: -- name: ansible2.4 +- name: python3.5-ansible pull: always image: python:3.5 commands: - - pip install -q ansible~=2.4 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml + - pip install tox -qq + - "tox -e $(tox -l | grep py35 | xargs | sed 's/ /,/g') -q" + environment: + PY_COLORS: 1 depends_on: - clone -- name: ansible2.5 - pull: always - image: python:3.5 - commands: - - pip install -q ansible~=2.5 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml - depends_on: - - clone - -- name: ansible2.6 - pull: always - image: python:3.5 - commands: - - pip install -q ansible~=2.6 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml - depends_on: - - clone - -- name: ansible2.7 - pull: always - image: python:3.5 - commands: - - pip install -q ansible~=2.7 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml - depends_on: - - clone - ---- -kind: pipeline -name: python-3.6 - -platform: - os: linux - arch: amd64 - -steps: -- name: ansible2.4 +- name: python3.6-ansible pull: always image: python:3.6 commands: - - pip install -q ansible~=2.4 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml + - pip install tox -qq + - "tox -e $(tox -l | grep py36 | xargs | sed 's/ /,/g') -q" + environment: + PY_COLORS: 1 depends_on: - clone -- name: ansible2.5 - pull: always - image: python:3.6 - commands: - - pip install -q ansible~=2.5 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml - depends_on: - - clone - -- name: ansible2.6 - pull: always - image: python:3.6 - commands: - - pip install -q ansible~=2.6 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml - depends_on: - - clone - -- name: ansible2.7 - pull: always - image: python:3.6 - commands: - - pip install -q ansible~=2.7 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml - depends_on: - - clone - ---- -kind: pipeline -name: python-3.7 - -platform: - os: linux - arch: amd64 - -steps: -- name: ansible2.4 +- name: python3.7-ansible pull: always image: python:3.7 commands: - - pip install -q ansible~=2.4 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml + - pip install tox -qq + - "tox -e $(tox -l | grep py37 | xargs | sed 's/ /,/g') -q" + environment: + PY_COLORS: 1 depends_on: - clone -- name: ansible2.5 +- name: python-flake8 pull: always image: python:3.7 commands: - - pip install -q ansible~=2.5 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml + - pip install -r test-requirements.txt -qq + - pip install -qq . + - flake8 ./ansiblelater + environment: + PY_COLORS: 1 depends_on: - clone -- name: ansible2.6 +- name: python-bandit pull: always image: python:3.7 commands: - - pip install -q ansible~=2.6 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml + - pip install -r test-requirements.txt -qq + - pip install -qq . + - bandit -r ./ansiblelater + environment: + PY_COLORS: 1 depends_on: - clone -- name: ansible2.7 +- name: codecov pull: always image: python:3.7 commands: - - pip install -q ansible~=2.7 - - pip install -q -r tests/requirements.txt - - pip install -q . - - ansible-later -c tests/config/config.ini tests/data/yaml_success.yml + - pip install codecov + - codecov + environment: + CODECOV_TOKEN: + from_secret: codecov_token + PY_COLORS: 1 depends_on: - - clone + - python2.7-ansible + - python3.5-ansible + - python3.6-ansible + - python3.7-ansible + +trigger: + ref: + - refs/heads/master + - "refs/tags/**" + - "refs/pull/**" --- kind: pipeline @@ -243,6 +130,10 @@ steps: from_secret: gpgsign_key passphrase: from_secret: gpgsign_passphrase + when: + event: + exclude: + - pull_request - name: publish-github pull: always @@ -253,6 +144,9 @@ steps: files: - "dist/*" - sha256sum.txt + note: CHANGELOG.md + overwrite: true + title: "${DRONE_TAG}" when: event: - tag @@ -271,11 +165,14 @@ steps: event: - tag +trigger: + ref: + - refs/heads/master + - "refs/tags/**" + - "refs/pull/**" + depends_on: -- python-2.7 -- python-3.5 -- python-3.6 -- python-3.7 +- testing --- kind: pipeline @@ -298,10 +195,12 @@ steps: from_secret: matrix_username trigger: + ref: + - refs/heads/master + - "refs/tags/**" status: - success - failure - - skipped depends_on: - build diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d5e22e..210b6a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,2 @@ -- BUGFIX - - Controls like `when` used at block level will be added as metadata to each task inside this block [#9](https://github.com/xoxys/ansible-later/issues/9) - - Commands can be used in place of modules if the task use register [#8](https://github.com/xoxys/ansible-later/issues/8) +- ENHANCEMENT + - Respect `PY_COLORS` to get colorized output for nontty environments ([#10](https://github.com/xoxys/ansible-later/pull/10)) diff --git a/README.md b/README.md index a126f53..18490ea 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![](https://img.shields.io/pypi/pyversions/ansible-later.svg)](https://pypi.org/project/ansible-later/) [![](https://img.shields.io/pypi/status/ansible-later.svg)](https://pypi.org/project/ansible-later/) [![](https://img.shields.io/pypi/v/ansible-later.svg)](https://pypi.org/project/ansible-later/) +[![codecov](https://codecov.io/gh/xoxys/ansible-later/branch/master/graph/badge.svg)](https://codecov.io/gh/xoxys/ansible-later) This is a fork of Will Thames [ansible-review](https://github.com/willthames/ansible-review) so credits goes to him for his work on ansible-review and ansible-lint. @@ -18,20 +19,22 @@ The project name is an acronym for **L**ovely **A**utomation **TE**sting f**R**m ## Table of Content -- [Setup](#setup) - - [Using pip](#using-pip) - - [From source](#from-source) -- [Usage](#usage) - - [Configuration](#configuration) - - [Review a git repositories](#review-a-git-repositories) - - [Review a list of files](#review-a-list-of-files) - - [Buildin rules](#buildin-rules) -- [Build your own](#build-your-own) - - [The standards file](#the-standards-file) - - [Candidates](#candidates) - - [Minimal standards checks](#minimal-standards-checks) -- [License](#license) -- [Maintainers and Contributors](#maintainers-and-contributors) +- [ansible-later](#ansible-later) + - [Table of Content](#table-of-content) + - [Setup](#setup) + - [Using pip](#using-pip) + - [From source](#from-source) + - [Usage](#usage) + - [Configuration](#configuration) + - [Review a git repositories](#review-a-git-repositories) + - [Review a list of files](#review-a-list-of-files) + - [Buildin rules](#buildin-rules) + - [Build your own](#build-your-own) + - [The standards file](#the-standards-file) + - [Candidates](#candidates) + - [Minimal standards checks](#minimal-standards-checks) + - [License](#license) + - [Maintainers and Contributors](#maintainers-and-contributors) --- diff --git a/ansiblelater/utils/__init__.py b/ansiblelater/utils/__init__.py index cc3bc11..196c2f9 100644 --- a/ansiblelater/utils/__init__.py +++ b/ansiblelater/utils/__init__.py @@ -3,7 +3,6 @@ from __future__ import print_function import importlib import logging import os -import subprocess import sys import re import colorama @@ -16,13 +15,6 @@ try: except ImportError: import configparser -# try: -# from ansible.utils.color import stringc -# except ImportError: -# from ansible.color import stringc - -# from yamlhelper import * - def should_do_markup(): py_colors = os.environ.get('PY_COLORS', None) @@ -121,18 +113,6 @@ def read_config(config_file): return Settings(config, config_file) -def execute(cmd): - result = ExecuteResult() - encoding = 'UTF-8' - env = dict(os.environ) - env['PYTHONIOENCODING'] = encoding - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, env=env) - result.output = proc.communicate()[0].decode(encoding) - result.rc = proc.returncode - return result - - class Settings(object): def __init__(self, config, config_file): self.rulesdir = None @@ -147,7 +127,3 @@ class Settings(object): self.custom_modules = [x.strip() for x in modules.split(',')] self.configfile = config_file - - -class ExecuteResult(object): - pass diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 9787c3b..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,3 +0,0 @@ -[build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg index 048aeef..7d43296 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,5 +6,10 @@ license_file = LICENSE universal = 1 [flake8] +ignore = E501, W503, F401, N813 max-line-length = 100 -exclude = .git,.hg,.svn,test,setup.py,__pycache__ +exclude = .git,.tox,__pycache__,build,dist,tests,*.pyc,*.egg-info,.cache,.eggs + +[tool:pytest] +filterwarnings = + ignore:.*collections.*:DeprecationWarning diff --git a/tests/requirements.txt b/test-requirements.txt similarity index 60% rename from tests/requirements.txt rename to test-requirements.txt index 7de58af..999acfe 100644 --- a/tests/requirements.txt +++ b/test-requirements.txt @@ -1,5 +1,8 @@ flake8 +flake8-colors pep8-naming wheel -flake8-colors pytest +pytest-mock +pytest-cov +bandit diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/test_logging.py b/tests/unit/test_logging.py new file mode 100644 index 0000000..fd35fa3 --- /dev/null +++ b/tests/unit/test_logging.py @@ -0,0 +1,82 @@ +from __future__ import print_function + +import colorama +import logging + +from ansiblelater.utils import info, warn, abort, error, should_do_markup + + +def test_abort(capsys, mocker): + abort('foo') + stdout, _ = capsys.readouterr() + + print('{}{}{}'.format(colorama.Fore.RED, 'FATAL: foo'.rstrip(), + colorama.Style.RESET_ALL)) + x, _ = capsys.readouterr() + + assert x == stdout + + +def test_error(capsys, mocker): + error('foo') + stdout, _ = capsys.readouterr() + + print('{}{}{}'.format(colorama.Fore.RED, 'ERROR: foo'.rstrip(), + colorama.Style.RESET_ALL)) + x, _ = capsys.readouterr() + + assert x == stdout + + +def test_warn(capsys, mocker): + settings = mocker.MagicMock() + settings.log_level = getattr(logging, 'WARNING') + + warn('foo', settings) + stdout, _ = capsys.readouterr() + + print('{}{}{}'.format(colorama.Fore.YELLOW, 'WARN: foo'.rstrip(), + colorama.Style.RESET_ALL)) + x, _ = capsys.readouterr() + + assert x == stdout + + +def test_info(capsys, mocker): + settings = mocker.MagicMock() + settings.log_level = getattr(logging, 'INFO') + + info('foo', settings) + stdout, _ = capsys.readouterr() + + print('{}{}{}'.format(colorama.Fore.BLUE, 'INFO: foo'.rstrip(), + colorama.Style.RESET_ALL)) + x, _ = capsys.readouterr() + + assert x == stdout + + +def test_markup_detection_pycolors0(monkeypatch): + monkeypatch.setenv('PY_COLORS', '0') + assert not should_do_markup() + + +def test_markup_detection_pycolors1(monkeypatch): + monkeypatch.setenv('PY_COLORS', '1') + assert should_do_markup() + + +def test_markup_detection_tty_yes(mocker): + mocker.patch('sys.stdout.isatty', return_value=True) + mocker.patch('os.environ', {'TERM': 'xterm'}) + assert should_do_markup() + mocker.resetall() + mocker.stopall() + + +def test_markup_detection_tty_no(mocker): + mocker.patch('os.environ', {}) + mocker.patch('sys.stdout.isatty', return_value=False) + assert not should_do_markup() + mocker.resetall() + mocker.stopall() diff --git a/tox.ini b/tox.ini index 8db0157..791fdc9 100644 --- a/tox.ini +++ b/tox.ini @@ -1,46 +1,19 @@ [tox] -minversion = 3.5 -envlist = py27-ansible{21},py{27,35,36,37}-ansible{22,23,24,25,26,27},py{27,35,36,37}-flake8 +minversion = 3.7.0 +envlist = + py{27,35,36,37}-ansible{25,26,27,devel} + isolated_build = True [testenv] +usedevelop = True +passenv = PY_COLORS deps = - flake8 - pep8-naming - wheel - flake8-colors - pytest - ansible21: ansible>=2.1,<2.2 - ansible22: ansible>=2.2,<2.3 - ansible23: ansible>=2.3,<2.4 - ansible24: ansible>=2.4,<2.5 + -rtest-requirements.txt ansible25: ansible>=2.5,<2.6 ansible26: ansible>=2.6,<2.7 ansible27: ansible>=2.7,<2.8 - -commands = ansible-later -c tests/config/config.ini tests/data/yaml_success.yml -passenv = HOME - -[testenv:py27-flake8] -commands = flake8 ansiblelater -usedevelop = True - -[testenv:py36-flake8] -commands = flake8 ansiblelater -usedevelop = True - -[flake8] -ignore = E501, W503, F401, N813 -exclude = - .tox, - .git, - __pycache__, - build, - dist, - tests/fixtures/*, - *.pyc, - *.egg-info, - .cache, - .eggs - -format = %(path)s:%(row)d:%(col)d: ${red}%(code)s %(text)s${reset} + ansibledevel: git+https://github.com/ansible/ansible.git +commands = + ansible-later --help + pytest tests/ --cov={toxinidir}/ansiblelater/ --no-cov-on-fail --cov-append