Пример #1
0
def handle_pull_request(payload):
    repo = payload['repository']
    scm = repo['scm']
    if scm.lower() != 'git':
        logger.info('Unsupported version system: %s', scm)
        return

    pr = payload['pullrequest']
    title = pr['title']
    description = pr['description'] or ''
    if 'ci skip' in title or 'ci skip' in description:
        logger.info('ci skip found, ignore tests.')
        return

    if pr['state'] != 'OPEN':
        logger.info('Pull request state is not OPEN, ignore tests.')
        return

    rebuild = False
    if 'ci rebuild' in title.lower() or 'ci rebuild' in description.lower():
        rebuild = True

    source = pr['source']
    target = pr['destination']

    context = Context(repo['full_name'],
                      payload['actor'],
                      'pullrequest',
                      title,
                      source,
                      target,
                      rebuild=rebuild,
                      pr_id=pr['id'])
    start_pipeline.delay(context)
Пример #2
0
def handle_repo_commit_comment(payload):
    comment = payload['comment']
    comment_content = comment['content']['raw']

    retry = 'ci retry' in comment_content
    rebuild = 'ci rebuild' in comment_content
    nocache = 'no cache' in comment_content
    if not (retry or rebuild):
        return

    commit_hash = payload['commit']['hash']
    repo = payload['repository']
    repo_name = repo['full_name']

    context = Context(
        repo_name,
        payload['actor'],
        'commit',
        payload['commit']['message'],
        {
            'repository': {
                'full_name': repo_name
            },
            'branch': {
                'name': 'master'
            },
            'commit': {
                'hash': commit_hash
            },
        },
        rebuild=rebuild,
        nocache=nocache,
        clone_depth=0,  # Force a full git clone
    )
    start_pipeline.delay(context)
Пример #3
0
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 = Context(
        '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()
Пример #4
0
def handle_pull_request_comment(payload):
    comment = payload['comment']
    comment_content = comment['content']['raw'].lower()
    retry = 'ci retry' in comment_content
    rebuild = 'ci rebuild' in comment_content
    cleanup_lint = 'cleanup lint' in comment_content
    nocache = 'no cache' in comment_content
    if not (retry or rebuild or cleanup_lint):
        return

    repo = payload['repository']
    pr = payload['pullrequest']
    title = pr['title']

    if pr['state'] != 'OPEN':
        logger.info('Pull request state is not OPEN, ignore tests.')
        return

    source = pr['source']
    target = pr['destination']

    context = Context(repo['full_name'],
                      payload['actor'],
                      'pullrequest',
                      title,
                      source,
                      target,
                      rebuild=rebuild,
                      pr_id=pr['id'],
                      cleanup_lint=cleanup_lint,
                      nocache=nocache)
    start_pipeline.delay(context)
Пример #5
0
def handle_repo_push(payload):
    changes = payload['push']['changes']
    if not changes:
        return

    repo = payload['repository']
    scm = repo['scm']
    if scm.lower() != 'git':
        logger.info('Unsupported version system: %s', scm)
        return

    for change in changes:
        if not change['new']:
            logger.info('No new changes found')
            continue

        repo_name = repo['full_name']
        push_type = change['new']['type']
        rebuild = False
        if push_type == 'tag':
            commit_hash = change['new']['target']['hash']
            commit_message = change['new']['target']['message']
        elif push_type == 'branch':
            if not change['commits']:
                logger.warning('Can not find any commits')
                continue
            commit_hash = change['commits'][0]['hash']
            commit_message = change['commits'][0]['message']
            if 'ci skip' in commit_message.lower():
                logger.info('ci skip found, ignore tests.')
                continue
            if 'ci rebuild' in commit_message.lower():
                rebuild = True
        else:
            logger.error('Unsupported push type: %s', push_type)
            continue

        source = {
            'repository': {'full_name': repo_name},
            'branch': {'name': change['new']['name']},
            'commit': {'hash': commit_hash}
        }
        context = Context(
            repo_name,
            payload['actor'],
            push_type,
            commit_message,
            source,
            rebuild=rebuild,
        )
        try:
            _cancel_outdated_pipelines(context)
        except Exception:
            sentry.captureException()
        future = start_pipeline.delay(context)
        future.add_done_callback(lambda fut: _RUNNING_PIPELINES.pop(context.task_id, None))
        _RUNNING_PIPELINES[context.task_id] = future
        if push_type == 'branch':
            check_pr_mergeable.delay(context)
Пример #6
0
def push_context():
    return Context('deepanalyzer/badwolf', {}, 'commit', 'Update', {
        'repository': {
            'full_name': 'deepanalyzer/badwolf'
        },
        'branch': {
            'name': 'master'
        },
        'commit': {
            'hash': '2cedc1af762'
        },
    })
Пример #7
0
def handle_repo_push(payload):
    changes = payload['push']['changes']
    if not changes:
        return

    repo = payload['repository']
    scm = repo['scm']
    if scm.lower() != 'git':
        logger.info('Unsupported version system: %s', scm)
        return

    latest_change = changes[0]
    if not latest_change['new'] or latest_change['new']['type'] != 'branch':
        logger.info('Unsupported push type: %s', latest_change['new']['type'])
        return
    if not latest_change['commits']:
        logger.warning('Can not find any commits')
        return

    commit_hash = latest_change['commits'][0]['hash']
    commit_message = latest_change['commits'][0]['message']
    if 'ci skip' in commit_message.lower():
        logger.info('ci skip found, ignore tests.')
        return

    rebuild = False
    if 'ci rebuild' in commit_message.lower():
        rebuild = True

    repo_name = repo['full_name']

    context = Context(
        repo_name,
        payload['actor'],
        'commit',
        commit_message,
        {
            'repository': {
                'full_name': repo_name
            },
            'branch': {
                'name': latest_change['new']['name']
            },
            'commit': {
                'hash': commit_hash
            },
        },
        rebuild=rebuild,
    )
    start_pipeline.delay(context)
Пример #8
0
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 = Context(
        '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 = (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.js'
    assert problem.line == 1
Пример #9
0
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 = Context('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
Пример #10
0
def test_no_linters_ignore(app):
    context = Context(
        '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()
Пример #11
0
def pr_context():
    return Context('deepanalyzer/badwolf',
                   None,
                   'pullrequest',
                   'message', {
                       'repository': {
                           'full_name': 'deepanalyzer/badwolf'
                       },
                       'branch': {
                           'name': 'master'
                       },
                       'commit': {
                           'hash': '000000'
                       }
                   }, {'commit': {
                       'hash': '111111'
                   }},
                   pr_id=1)
Пример #12
0
def handle_pull_request(payload):
    repo = payload['repository']
    scm = repo['scm']
    if scm.lower() != 'git':
        logger.info('Unsupported version system: %s', scm)
        return

    pr = payload['pullrequest']
    title = pr['title']
    description = pr['description'] or ''
    if 'ci skip' in title or 'ci skip' in description:
        logger.info('ci skip found, ignore tests.')
        return

    if pr['state'] != 'OPEN':
        logger.info('Pull request state is not OPEN, ignore tests.')
        return

    title_lower = title.lower()
    desc_lower = description.lower()
    rebuild = 'ci rebuild' in title_lower or 'ci rebuild' in desc_lower
    skip_lint = 'lint skip' in title_lower or 'lint skip' in desc_lower

    source = pr['source']
    target = pr['destination']

    context = Context(
        repo['full_name'],
        payload['actor'],
        'pullrequest',
        title,
        source,
        target,
        rebuild=rebuild,
        pr_id=pr['id'],
        skip_lint=skip_lint
    )
    try:
        _cancel_outdated_pipelines(context)
    except Exception:
        sentry.captureException()
    future = start_pipeline.delay(context)
    future.add_done_callback(lambda fut: _RUNNING_PIPELINES.pop(context.task_id, None))
    _RUNNING_PIPELINES[context.task_id] = future
Пример #13
0
def handle_pull_request_comment(payload):
    comment = payload['comment']
    comment_content = comment['content']['raw'].lower()
    retry = 'ci retry' in comment_content
    rebuild = 'ci rebuild' in comment_content
    nocache = 'no cache' in comment_content
    if not (retry or rebuild):
        return

    repo = payload['repository']
    pr = payload['pullrequest']
    title = pr['title']

    if pr['state'] != 'OPEN':
        logger.info('Pull request state is not OPEN, ignore tests.')
        return

    title_lower = title.lower()
    description = pr['description'] or ''
    desc_lower = description.lower()
    skip_lint = 'lint skip' in title_lower or 'lint skip' in desc_lower
    source = pr['source']
    target = pr['destination']

    context = Context(
        repo['full_name'],
        payload['actor'],
        'pullrequest',
        title,
        source,
        target,
        rebuild=rebuild,
        pr_id=pr['id'],
        nocache=nocache,
        skip_lint=skip_lint
    )
    try:
        _cancel_outdated_pipelines(context)
    except Exception:
        sentry.captureException()
    future = start_pipeline.delay(context)
    future.add_done_callback(lambda fut: _RUNNING_PIPELINES.pop(context.task_id, None))
    _RUNNING_PIPELINES[context.task_id] = future
Пример #14
0
def test_flake8_lint_a_py(app, caplog):
    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
"""

    context = Context(
        '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, 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
Пример #15
0
def test_mypy_lint_a_py(app, caplog):
    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()
"""

    context = Context(
        'deepanalyzer/badwolf',
        None,
        'pullrequest',
        'message',
        {'commit': {'hash': '000000'}},
        {'commit': {'hash': '111111'}},
        pr_id=1
    )
    spec = Specification()
    spec.linters.append(ObjectDict(name='mypy', pattern=None))
    lint = LintProcessor(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'
Пример #16
0
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 = Context('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
Пример #17
0
def test_load_changes_failed_ignore(app, caplog):
    context = Context(
        '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()
Пример #18
0
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 = Context('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
Пример #19
0
def test_jsonlint_a_json_changes_in_range(app, caplog):
    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
 }
"""

    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) == 1
    problem = lint.problems[0]
    assert problem.filename == 'b.json'
    assert problem.line == 2
Пример #20
0
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 = (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
Пример #21
0
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 = (1, 2)
        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'
Пример #22
0
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