def test_rstlint_a_rst(app, pr_context): diff = """diff --git a/a.rst b/a.rst new file mode 100644 index 0000000..4e46cf9 --- /dev/null +++ b/a.rst @@ -0,0 +1,2 @@ +Hello World +==== """ spec = Specification() spec.linters.append(ObjectDict(name='rstlint')) lint = LintProcessor(pr_context, spec, os.path.join(FIXTURES_PATH, 'rstlint')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = (1, 2) lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 1 problem = lint.problems[0] assert problem.filename == 'a.rst' assert problem.line == 2
def test_stylelint_lint_a_scss(app, pr_context): diff = """diff --git a/a.scss b/a.scss new file mode 100644 index 0000000..e545209 --- /dev/null +++ b/a.scss @@ -0,0 +1 @@ +a[id="foo"] { content: "x"; } """ spec = Specification() spec.linters.append(ObjectDict(name='stylelint', pattern=None)) lint = LintProcessor(pr_context, spec, os.path.join(FIXTURES_PATH, 'stylelint')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = (1, 2) lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 2 problem = lint.problems[0] assert problem.filename == 'a.scss'
def test_flake8_lint_a_py(app, pr_context): diff = """diff --git a/a.py b/a.py new file mode 100644 index 0000000..fdeea15 --- /dev/null +++ b/a.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + + +def add(a, b): + return a+ b """ spec = Specification() spec.linters.append(ObjectDict(name='flake8', pattern=None)) lint = LintProcessor(pr_context, spec, os.path.join(FIXTURES_PATH, 'flake8')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = (1, 2) lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 1 problem = lint.problems[0] assert problem.filename == 'a.py' assert problem.line == 6
def test_mypy_lint_a_py(app, pr_context): diff = """diff --git a/a.py b/a.py new file mode 100644 index 0000000..87604af --- /dev/null +++ b/a.py @@ -0,0 +1,5 @@ +def p() -> None: + print('hello') + + +a = p() """ spec = Specification() spec.linters.append(ObjectDict(name='mypy', pattern=None)) lint = LintProcessor(pr_context, spec, os.path.join(FIXTURES_PATH, 'mypy')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = (1, 2) lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 1 problem = lint.problems[0] assert problem.line == 5 assert problem.filename == 'a.py'
def test_hadolint_lint_a_dockerfile(app, pr_context): diff = """diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cd19857 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install file """ spec = Specification() spec.linters.append(ObjectDict(name='hadolint', pattern=None)) lint = LintProcessor(pr_context, spec, os.path.join(FIXTURES_PATH, 'hadolint')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = (1, 2) lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 4 problem = lint.problems[0] assert problem.line == 3 assert problem.filename == 'Dockerfile'
def test_jsonlint_a_json_changes_in_range(app, pr_context): diff = """diff --git a/b.json b/b.json index 6ebebfe..6be8d74 100644 --- a/b.json +++ b/b.json @@ -1,3 +1,4 @@ { "a": 1 + "b": 2 } """ spec = Specification() spec.linters.append(ObjectDict(name='jsonlint', pattern=None)) lint = LintProcessor(pr_context, spec, os.path.join(FIXTURES_PATH, 'jsonlint')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = (1, 2) lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 1 problem = lint.problems[0] assert problem.filename == 'b.json' assert problem.line == 2
def test_bandit_lint_a_py(app, pr_context): diff = """diff --git a/a.py b/a.py new file mode 100644 index 0000000..719cd56 --- /dev/null +++ b/a.py @@ -0,0 +1,4 @@ +try: + a = 1 +except Exception: + pass """ spec = Specification() spec.linters.append(ObjectDict(name='bandit')) lint = LintProcessor(pr_context, spec, os.path.join(FIXTURES_PATH, 'bandit')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = (1, 2) lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 1 problem = lint.problems[0] assert problem.filename == 'a.py' assert problem.line == 3 assert not problem.is_error
def test_yamllint_a_yml(app, pr_context): diff = """diff --git a/a.yml b/a.yml new file mode 100644 index 0000000..1eccee8 --- /dev/null +++ b/a.yml @@ -0,0 +1,3 @@ +--- +a: 1 +a: 2 """ spec = Specification() spec.linters.append(ObjectDict(name='yamllint', pattern=None)) lint = LintProcessor(pr_context, spec, os.path.join(FIXTURES_PATH, 'yamllint')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = (1, 2) lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 1 problem = lint.problems[0] assert problem.filename == 'a.yml' assert problem.line == 3
def test_no_changed_files_ignore(app, caplog): diff = """diff --git a/removed_file b/removed_file deleted file mode 100644 index 1f38447..0000000 --- a/removed_file +++ /dev/null @@ -1,3 +0,0 @@ -This content shouldn't be here. - -This file will be removed. """ context = TestContext('deepanalyzer/badwolf', None, 'pullrequest', 'message', {'commit': { 'hash': '000000' }}, {'commit': { 'hash': '111111' }}, pr_id=1) spec = Specification() spec.linters.append(ObjectDict(name='flake8', pattern=None)) lint = LintProcessor(context, spec, '/tmp') patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes: load_changes.return_value = patch lint.process() assert load_changes.called assert 'No changed files found' in caplog.text()
def test_shellcheck_a_sh(app, pr_context): diff = """diff --git a/a.sh b/a.sh new file mode 100644 index 0000000..9fb9840 --- /dev/null +++ b/a.sh @@ -0,0 +2 @@ +#!/bin/sh +$foo=42 """ spec = Specification() spec.linters.append(ObjectDict(name='shellcheck', pattern=None)) lint = LintProcessor(pr_context, spec, os.path.join(FIXTURES_PATH, 'shellcheck')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = (1, 2) lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) > 0 problem = lint.problems[0] assert problem.filename == 'a.sh' assert problem.line == 2
def test_jsonlint_a_json_changes_out_of_range(app, pr_context): diff = """diff --git a/c.json b/c.json index 9b90002..c36a2a4 100644 --- a/c.json +++ b/c.json @@ -3,4 +3,5 @@ "b": 2, c: 3, d: 4 + e: 5 } """ spec = Specification() spec.linters.append(ObjectDict(name='jsonlint', pattern=None)) lint = LintProcessor(pr_context, spec, os.path.join(FIXTURES_PATH, 'jsonlint')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = (1, 2) lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 0
def test_load_changes_failed_ignore(app, pr_context, caplog): spec = Specification() spec.linters.append('flake8') lint = LintProcessor(pr_context, spec, '/tmp') with mock.patch.object(lint, 'load_changes') as load_changes: load_changes.return_value = None lint.process() assert load_changes.called assert 'Load changes failed' in caplog.text
def test_eslint_lint_a_js(app, caplog): diff = """diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..45e5d69 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,5 @@ +{ + "rules": { + "quotes": [2, "single"] + } +} diff --git a/a.js b/a.js new file mode 100644 index 0000000..f119a7f --- /dev/null +++ b/a.js @@ -0,0 +1 @@ +console.log("bar") """ context = TestContext('deepanalyzer/badwolf', None, 'pullrequest', 'message', {'commit': { 'hash': '000000' }}, {'commit': { 'hash': '111111' }}, pr_id=1) spec = Specification() spec.linters.append(ObjectDict(name='eslint', pattern=None)) lint = LintProcessor(context, spec, os.path.join(FIXTURES_PATH, 'eslint')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = None lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 1 problem = lint.problems[0] assert problem.filename == 'a.js' assert problem.line == 1
def test_jscs_lint_a_js(app, caplog): diff = """diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000..c287019 --- /dev/null +++ b/.jscsrc @@ -0,0 +1,3 @@ +{ + "preset": "node-style-guide" +} \ No newline at end of file diff --git a/jscs/a.js b/a.js new file mode 100644 index 0000000..66f319a --- /dev/null +++ b/a.js @@ -0,0 +1,2 @@ +var foo = 'bar'; +if(foo === 'bar') {} """ context = TestContext('deepanalyzer/badwolf', None, 'pullrequest', 'message', {'commit': { 'hash': '000000' }}, {'commit': { 'hash': '111111' }}, pr_id=1) spec = Specification() spec.linters.append(ObjectDict(name='jscs', pattern=None)) lint = LintProcessor(context, spec, os.path.join(FIXTURES_PATH, 'jscs')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = None lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 1 problem = lint.problems[0] assert problem.filename == 'a.js' assert problem.line == 2
def test_no_linters_ignore(app): context = TestContext('deepanalyzer/badwolf', None, 'pullrequest', 'message', {'commit': { 'hash': '000000' }}, {'commit': { 'hash': '111111' }}, pr_id=1) spec = Specification() lint = LintProcessor(context, spec, '/tmp') with mock.patch.object(lint, 'load_changes') as load_changes: lint.process() load_changes.assert_not_called()
def test_flake8_lint_a_py_with_multi_custom_glob_patterns(app, caplog): diff = """diff --git a/b.pyx b/b.pyx new file mode 100644 index 0000000..fdeea15 --- /dev/null +++ b/b.pyx @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + + +def add(a, b): + return a+ b """ context = TestContext('deepanalyzer/badwolf', None, 'pullrequest', 'message', {'commit': { 'hash': '000000' }}, {'commit': { 'hash': '111111' }}, pr_id=1) spec = Specification() spec.linters.append(ObjectDict(name='flake8', pattern='*.py *.pyx')) lint = LintProcessor(context, spec, os.path.join(FIXTURES_PATH, 'flake8')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = None lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 1 problem = lint.problems[0] assert problem.filename == 'b.pyx' assert problem.line == 6
def test_bandit_lint_a_py(app, caplog): diff = """diff --git a/a.py b/a.py new file mode 100644 index 0000000..719cd56 --- /dev/null +++ b/a.py @@ -0,0 +1,4 @@ +try: + a = 1 +except Exception: + pass """ context = TestContext('deepanalyzer/badwolf', None, 'pullrequest', 'message', {'commit': { 'hash': '000000' }}, {'commit': { 'hash': '111111' }}, pr_id=1) spec = Specification() spec.linters.append(ObjectDict(name='bandit')) lint = LintProcessor(context, spec, os.path.join(FIXTURES_PATH, 'bandit')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = None lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 1 problem = lint.problems[0] assert problem.filename == 'a.py' assert problem.line == 3 assert not problem.is_error
def test_load_changes_failed_ignore(app, caplog): context = TestContext('deepanalyzer/badwolf', None, 'pullrequest', 'message', {'commit': { 'hash': '000000' }}, {'commit': { 'hash': '111111' }}, pr_id=1) spec = Specification() spec.linters.append('flake8') lint = LintProcessor(context, spec, '/tmp') with mock.patch.object(lint, 'load_changes') as load_changes: load_changes.return_value = None lint.process() assert load_changes.called assert 'Load changes failed' in caplog.text()
def test_yamllint_a_yml(app, caplog): diff = """diff --git a/a.yml b/a.yml new file mode 100644 index 0000000..1eccee8 --- /dev/null +++ b/a.yml @@ -0,0 +1,3 @@ +--- +a: 1 +a: 2 """ context = TestContext('deepanalyzer/badwolf', None, 'pullrequest', 'message', {'commit': { 'hash': '000000' }}, {'commit': { 'hash': '111111' }}, pr_id=1) spec = Specification() spec.linters.append(ObjectDict(name='yamllint', pattern=None)) lint = LintProcessor(context, spec, os.path.join(FIXTURES_PATH, 'yamllint')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = None lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 1 problem = lint.problems[0] assert problem.filename == 'a.yml' assert problem.line == 3
def test_sasslint_lint_a_scss(app, caplog): diff = """diff --git a/a.scss b/a.scss new file mode 100644 index 0000000..48b3ebe --- /dev/null +++ b/a.scss @@ -0,0 +1,3 @@ +.test { + background-color: "#FFF" +} """ context = Context('deepanalyzer/badwolf', None, 'pullrequest', 'message', {'commit': { 'hash': '000000' }}, {'commit': { 'hash': '111111' }}, pr_id=1) spec = Specification() spec.linters.append(ObjectDict(name='sasslint', pattern=None)) lint = LintProcessor(context, spec, os.path.join(FIXTURES_PATH, 'sasslint')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = None lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 3 problem = lint.problems[0] assert problem.filename == 'a.scss'
def test_shellcheck_a_sh(app, caplog): diff = """diff --git a/a.sh b/a.sh new file mode 100644 index 0000000..9fb9840 --- /dev/null +++ b/a.sh @@ -0,0 +2 @@ +#!/bin/sh +$foo=42 """ context = Context('deepanalyzer/badwolf', None, 'pullrequest', 'message', {'commit': { 'hash': '000000' }}, {'commit': { 'hash': '111111' }}, pr_id=1) spec = Specification() spec.linters.append(ObjectDict(name='shellcheck', pattern=None)) lint = LintProcessor(context, spec, os.path.join(FIXTURES_PATH, 'shellcheck')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = None lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) > 0 problem = lint.problems[0] assert problem.filename == 'a.sh' assert problem.line == 2
def test_jsonlint_a_json_changes_out_of_range(app, caplog): diff = """diff --git a/c.json b/c.json index 9b90002..c36a2a4 100644 --- a/c.json +++ b/c.json @@ -3,4 +3,5 @@ "b": 2, c: 3, d: 4 + e: 5 } """ context = Context( 'deepanalyzer/badwolf', None, 'pullrequest', 'message', {'commit': {'hash': '000000'}}, {'commit': {'hash': '111111'}}, pr_id=1 ) spec = Specification() spec.linters.append(ObjectDict(name='jsonlint', pattern=None)) lint = LintProcessor(context, spec, os.path.join(FIXTURES_PATH, 'jsonlint')) patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes,\ mock.patch.object(lint, 'update_build_status') as build_status,\ mock.patch.object(lint, '_report') as report: load_changes.return_value = patch build_status.return_value = None report.return_value = (1, 2) lint.problems.set_changes(patch) lint.process() assert load_changes.called assert len(lint.problems) == 0
def test_no_changed_files_ignore(app, pr_context, caplog): diff = """diff --git a/removed_file b/removed_file deleted file mode 100644 index 1f38447..0000000 --- a/removed_file +++ /dev/null @@ -1,3 +0,0 @@ -This content shouldn't be here. - -This file will be removed. """ spec = Specification() spec.linters.append(ObjectDict(name='flake8', pattern=None)) lint = LintProcessor(pr_context, spec, '/tmp') patch = PatchSet(diff.split('\n')) with mock.patch.object(lint, 'load_changes') as load_changes: load_changes.return_value = patch lint.process() assert load_changes.called assert 'No changed files found' in caplog.text
def run(self): start_time = time.time() self.branch = self.context.source['branch']['name'] try: self.clone_repository() except git.GitCommandError as e: logger.exception('Git command error') self.update_build_status('FAILED', 'Git clone repository failed') content = ':broken_heart: **Git error**: {}'.format(to_text(e)) if self.context.pr_id: pr = PullRequest(bitbucket, self.repo_full_name) pr.comment(self.context.pr_id, content) else: cs = Changesets(bitbucket, self.repo_full_name) cs.comment(self.commit_hash, content) self.cleanup() return if not self.validate_settings(): self.cleanup() return context = { 'context': self.context, 'task_id': self.task_id, 'build_log_url': url_for('log.build_log', sha=self.commit_hash, _external=True), 'branch': self.branch, 'scripts': self.spec.scripts, } if self.spec.scripts: self.update_build_status('INPROGRESS', 'Test in progress') docker_image_name, build_output = self.get_docker_image() context['build_logs'] = to_text(build_output) context.update({ 'build_logs': to_text(build_output), 'elapsed_time': int(time.time() - start_time), }) if not docker_image_name: self.update_build_status('FAILED', 'Build or get Docker image failed') context['exit_code'] = -1 self.send_notifications(context) self.cleanup() return exit_code, output = self.run_tests_in_container(docker_image_name) if exit_code == 0: # Success logger.info('Test succeed for repo: %s', self.repo_full_name) self.update_build_status('SUCCESSFUL', '1 of 1 test succeed') else: # Failed logger.info('Test failed for repo: %s, exit code: %s', self.repo_full_name, exit_code) self.update_build_status('FAILED', '1 of 1 test failed') context.update({ 'logs': to_text(output), 'exit_code': exit_code, 'elapsed_time': int(time.time() - start_time), }) self.send_notifications(context) # Code linting if self.context.pr_id and self.spec.linters: lint = LintProcessor(self.context, self.spec, self.clone_path) lint.process() self.cleanup()
def test_no_linters_ignore(app, pr_context): spec = Specification() lint = LintProcessor(pr_context, spec, '/tmp') with mock.patch.object(lint, 'load_changes') as load_changes: lint.process() load_changes.assert_not_called()