A static-analysis bot for Github

Overview

Imhotep

Imhotep, the peaceful builder.

Build Status codecov.io Requirements Status

What is it?

Imhotep is a tool which will comment on commits coming into your repository and check for syntactic errors and general lint warnings.

Installation

Currently, installation is done from source through Python packaging system. We first need to download it from GitHub. We then setup a virtualenv which will keep our python packages separate from other things on your system, lest we have version conflicts. Finally, we install the required packages.

virtualenv env
. env/bin/activate
pip install imhotep

If you want to hack on imhotep, that looks more like this:

git clone git://github.com/justinabrahms/imhotep.git
cd imhotep
virtualenv env
. env/bin/activate
pip install -r requirements.txt
pip install -e .

You'll also need to install the plugins you'd like to run. Examples include jshint, flake8, pep8, pylint, rubocop, foodcritic, and jsl. You can install those with pip. Example: pip install imhotep_jshint.

Usage

To use imhotep, we must tell it which repository to look at, who to authenticate as and what to comment on. Imhotep is able to comment in two ways: either on a single commit or on a pull request.

Commenting on a pull request

    imhotep \
       --repo_name="justinabrahms/imhotep" \
       --github-username="your_username" \
       --github-password="a_sha_generated_by_github" \
       --pr-number=1

Commenting on a single commit

    imhotep \
       --repo_name="justinabrahms/imhotep" \
       --github-username="your_username" \
       --github-password="a_sha_generated_by_github" \
       --commit="a123445714cfa89d1e843d9950ea8f249cd6e4df"

Where do I get that SHA?

The SHA generated by github is done through your user's settings page. Generate a personal access token and use that for the --github-password above.

Full Usage Info

usage: imhotep [-h] [--config-file CONFIG_FILE] --repo_name REPO_NAME
               [--commit COMMIT] [--origin-commit ORIGIN_COMMIT]
               [--filenames FILENAMES [FILENAMES ...]] [--debug]
               [--github-username GITHUB_USERNAME]
               [--github-password GITHUB_PASSWORD] [--no-post]
               [--authenticated] [--pr-number PR_NUMBER]
               [--cache-directory CACHE_DIRECTORY] [--report-file-violations]

Posts static analysis results to github.

optional arguments:
  -h, --help            show this help message and exit
  --config-file CONFIG_FILE
                        Configuration file in json.
  --repo_name REPO_NAME
                        Github repository name in owner/repo format
  --commit COMMIT       The sha of the commit to run static analysis on.
  --origin-commit ORIGIN_COMMIT
                        Commit to use as the comparison point.
  --filenames FILENAMES [FILENAMES ...]
                        filenames you want static analysis to be limited to.
  --debug               Will dump debugging output and won't clean up after
                        itself.
  --github-username GITHUB_USERNAME
                        Github user to post comments as.
  --github-password GITHUB_PASSWORD
                        Github password for the above user.
  --no-post             [DEBUG] will print out comments rather than posting to
                        github.
  --authenticated       Indicates the repository requires authentication
  --pr-number PR_NUMBER
                        Number of the pull request to comment on
  --cache-directory CACHE_DIRECTORY
                        Path to directory to cache the repository
  --report-file-violations
                        Report file-level violations, i.e. those not on
                        individual lines

Note: if you get a error where the plugin cannot find imhotep.tools, make sure you installed imhotep into your virtualenv with pip install -e .. See the Installation instructions above.

Linter Support

There is currently support for 2 linters: PyLint and JSHint. If it finds violations, it will post those violations to GitHub. New linting tools are encouraged!

By default, imhotep runs all plugins it can find on your source code. If you'd like to only run a subset of linters, you should specify the --linter directive with a dotted path to the module. An example of this is imhotep.tools:PyLint or imhotep_pep8.plugin:Pep8Linter. If you want to specify multiple tools, just pass multiple things to the --linter flag.

Writing Plugins

Imhotep supports adding linters through a plugin API based around Python's setuptools entrypoints. This means that plugins can live as separate Python packages which are installable alongside imhotep.

To write your own tool, subclass the Tool class and override the process_line, get_file_extensions, and get_command methods. If you need greater control over how the tool is run, you can override the invoke method which gives you maximal control over how the tools are run.

To make your plugin discoverable, you need to add an entry_points stanza to your setup.py. It looks like this.

setup(
  # ...
  entry_points={
    'imhotep_linter': [
      '.py = path.to.module:ToolClassName'
    ]
  }
  # ...
)

The key pieces of this are the name of the entrypoint which must be imhotep_linter. This is how we know where to find the plugins. The list that follows it is a list of strings that map file extensions to a tool that knows how to lint them. So for the entry above, we'll do something like from path.to.module import ToolClassName and run that on all .py files in the repository.

You can find a working example of a setup.py file in the imhotep_pep8 repository.

What's with the name?

Imhotep, the first Egyptian architect, is known as "the one who comes in peace". In keeping with that name, the goal of this tool is to keep code reviews peaceful and productive by having robots point out the nitpicky details, leaving people to critique bigger picture things, not spacing and misspelling issues.

Release Notes

1.1.1

Bugfixes:

  • Improved discovery of build tools

1.1.0

This is the first release where I'm tracking release notes. This release is majoritively the work of danpalmer. Thanks, Dan!

Features:

  • Support for file level violations

Backwards incompatible change:

  • The printer reporter was broken, not using the correct interface for reporting individual lines. I've chosen to not bump the major version, because this change was to get something to work. Any work built on top of this class would have not be operational code, so I'm not worried about breaking someone.

Bugfixes:

  • Different reporters that report errors on the same line don't clobber each other.
  • File extensions are properly filtered before reporting.
Comments
  • New PyPI release

    New PyPI release

    Hi @justinabrahms.

    I've just changed the supported Python versions (to drop 2.6 and add 3.5/3.6, I hope that's not too bold). I've also restructured the travis build matrix to support that, and merged an outstanding bugfix PR that I had where the tests had been failing due to the Python build issues.

    I believe master should be in a shippable state now with the bugfix. Could you do a PyPI release when you have a chance? I believe this should be 1.1.1, and have updated the changelog.

    opened by danpalmer 11
  • GitHub reporter no longer takes a repo name

    GitHub reporter no longer takes a repo name

    Fixes reporting to GitHub.

    Note: I'm doing this all from the web interface, have not actually run the tests myself yet, hopefully Travis will tell me if it works.

    opened by danpalmer 9
  • Make sure we can always find the right file

    Make sure we can always find the right file

    Looks like there was an edge case in how find was finding particular files. This fixes it.

    Would appreciate review from @justinabrahms in case you can think of any knock-on issues this might cause.

    opened by danpalmer 6
  • Initial Stash support for PRs

    Initial Stash support for PRs

    Not quite ready for merge (only PRs are working), but wanted to see if this is something you'd like contributed.

    If so, I figure you'll have some ideas about how you want to handle the extra arguments necessary for stash. Currently just passing around kwargs everywhere but obviously that's not optimal.

    Since stash is always (I think) hosted privately, we need a stash_hostname. Also, stash is organized by project then by repo, so there is a project_name argument as well.

    Lastly, I changed github_username/password to drop the github_ part so it can be reused.

    opened by jbeluch 5
  • Don't clobber errors

    Don't clobber errors

    Say I lint the following file:

    requests.get('https://python.org', verify=False)
    

    ...with Bandit and Flake8. Bandit will run and return:

    {"file.py": {"1": ["something about SSL"]}}
    

    ...and then Flake8 will run and return:

    {"file.py": {"1": ["Module requests not found"]}}
    

    These results will get dict.merge'd together, therefore clobbering the Bandit result with the Flake8 result, as it's a shallow merge.

    This change fixes that issue by deep merging the results. Since that requires that the API is conformed to, I've updated tests so that they return valid data.

    Side note – can we have a new PyPI release? I noticed that none of the recent changes are on PyPI (including the printing reporter being broken).

    opened by danpalmer 4
  • File-level Violations

    File-level Violations

    This PR adds optional reporting for linting violations at the file level, addressing issue #85.

    A concrete example of this is flake8-isort, which reports a file not being “isorted” as having a violation on line 0.

    This change adds the option --report-file-violations, which will cause the value 0 to be forcibly added to the ‘changed lines’, so that Imhotep will include violations on line 0. This behaviour is then documented in tools.py. Finally, the mapping of line numbers to diff positions is updated to include a mapping form 0 to the lowest value line in the diff, so that Imhotep will report file violations on the first line it can in a given file.

    Comments and thoughts on implementation/documentation/etc welcomed.

    opened by danpalmer 4
  • Add some documentation around how to release plugins as separate modules

    Add some documentation around how to release plugins as separate modules

    @mghayes: Can you validate that this makes sense? Do you need more information around this to convert the JSL plugin to a separate repository? Does this feel like too much work?

    opened by justinabrahms 4
  • Make report_line function signatures consistent across all reporters

    Make report_line function signatures consistent across all reporters

    It seems like this needs to be done? I'm currently getting this error when running with --no-post:

    Traceback (most recent call last):
      File "/mnt/services/jenkins/workspace/imhotep/imhotep/bin/imhotep", line 9, in <module>
        load_entry_point('imhotep==1.0.1', 'console_scripts', 'imhotep')()
      File "/mnt/services/jenkins/workspace/imhotep/imhotep/imhotep/main.py", line 54, in main
        imhotep.invoke()
      File "/mnt/services/jenkins/workspace/imhotep/imhotep/imhotep/app.py", line 135, in invoke
        x, pos_map[x], violations['%s' % x])
    TypeError: report_line() takes exactly 7 arguments (6 given)
    

    Here are the signatures before and after the changes:

    screen shot 2016-07-24 at 2 08 03 pm screen shot 2016-07-24 at 2 07 46 pm

    Let me know if I misunderstood. Thanks!

    opened by harveyr 3
  • hasattr(self.response_format) results in TypeError

    hasattr(self.response_format) results in TypeError

    There is an error inimhotep/tools.py for version 0.4.0 installed via pip that results in TypeError:

        if not hasattr(self.response_format):
        # TypeError: hasattr expected 2 arguments, got 1
    

    The error is here

    The fix appears to be to change the source to hasattr(self, 'response_format') but the fact no-one has raised this since the code was introduced ~4 months ago makes me a bit suspicious that something odd is happening.

    opened by richtier 3
  • Add __main__ module to enable “python -m imhotep”

    Add __main__ module to enable “python -m imhotep”

    Python 2.6 supports directory execution (i.e. “python imhotep” instead of “python imhotep/main.py” and 2.7 supports direct package execution (“python -m imhotep” regardless of where it’s installed). In both cases, what’s needed is a file named __main__.py in the imhotep package/directory. This can make the doc simpler for both non-installed and installed usage.

    opened by merwok 3
  • Can't get running based off README

    Can't get running based off README

    So the readme says to call imhotep.py to run the script, but it looks like that file doesn't exist. At least not on master (as of c4ee47e457). So I tried instead to call imhotep/main.py, but got the following error:

    Traceback (most recent call last):
      File "imhotep/main.py", line 305, in <module>
        imhotep = gen_imhotep(**params)
      File "imhotep/main.py", line 200, in gen_imhotep
        plugins = load_plugins()
      File "imhotep/main.py", line 112, in load_plugins
        klass = ep.load()
      File "/Users/streeter/.virtualenvs/tmp-2582e1239fbec948/lib/python2.7/site-packages/pkg_resources.py", line 2021, in load
        entry = __import__(self.module_name, globals(),globals(), ['__name__'])
      File "/Users/streeter/.virtualenvs/tmp-2582e1239fbec948/lib/python2.7/site-packages/imhotep_pylint/plugin.py", line 1, in <module>
        from imhotep.tools import Tool
    ImportError: No module named imhotep.tools
    

    I fixed that by first running:

    python setup.py install
    

    from within the imhotep checkout. So we should update the readme to reflect the new installation instructions.

    opened by streeter 3
  • Support custom base branch name

    Support custom base branch name

    Currently, Imhotep assumes the base branch is called master.

    https://github.com/justinabrahms/imhotep/blob/046ec49f7d337fcbcd81dd30b883a3c4bcf6ecc0/imhotep/repomanagers.py#L107

    This name is getting deprecated.

    We should at least make this a CLI argument.

    opened by tslmy 1
  • Support for test coverage diff report

    Support for test coverage diff report

    Didn't find anything like this either as an old issue or as a plugin so I decided to post it here. Perfectly happy to develop it myself as a plugin (assuming it is feasible).

    I would like to have a imhotep plugin that adds a coverage difference report to PRs as a comment on top. Something like this:

    Filename          Stmts    Miss    Cover     Missing
    ----------------  -------  ------  --------  ---------
    dummy/dummy.py    -        -2      +50.00%   -2, -5
    dummy/dummy2.py   +2       -       +100.00%
    TOTAL             +2       -2      +50.00%
    

    I think this will be very helpful to see test coverage improvements with each PR.

    There are several tools for this including pycobertura and diffcover. Assuming pycobertura I would need to do this:

    • Check master
    • Check code under the given PR
    • Run pytest with coverage on for master
    • Run pytest with coverage on for the given PR.
    • Run pycobertura diff coverage.old.xml coverage.new.xml --source1 old_source/ --source2 new_source/. This will generate a text report
    • Return that from imhotep invoke(). The output would have to be for the whole PR and not for specific lines. Does imhotep supports this?

    Would this be something sensible? Happy to develop it as a separate plugin but I'll need some guidance.

    opened by arturmatos 1
  • Cannot post comments if PR is from a third party

    Cannot post comments if PR is from a third party

    WARNING:imhotep.http:Error on POST to https://api.github.com/repos/xxxxxx/xxxxxx/pulls/xxx/comments. Response: {"message":"Validation Failed","errors":[{"resource":"PullRequestReviewComment","code":"invalid","field":"path"}],"documentation_url":"https://developer.github.com/v3/pulls/comments/#create-a-comment"} ERROR:imhotep.reporters.github:Error posting line to github. {u'documentation_url': u'https://developer.github.com/v3/pulls/comments/#create-a-comment', u'message': u'Validation Failed', u'errors': [{u'field': u'path', u'code': u'invalid', u'resource': u'PullRequestReviewComment'}]}

    To be clear, the bot user I'm using has admin access to the organization and the upstream repo, and also for the remote third party repo. It can comment just fine, via the Github web UI.

    opened by gordol 0
  • The Boy Scout Rule

    The Boy Scout Rule

    http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule

    At Thread, we adhere to the Boy Scout rule of "try and leave the world a little better than how you found it". As a result, code review comments often point to style changes in surrounding code that is not in the actual diff.

    I propose to implement a Boy Scout option (name not confirmed of course, open to suggestions) that would be the number of lines either side of a diff'd line that are eligible for reporting.

    This would allow the following use cases:

    • Boy Scout = 0, current behaviour, only lint changes.
    • Boy Scout = ~1-5, small additional linting, includes lines that show in the GitHub diffs without actually being a changed line.
    • Boy Scout = ~10000, allows for incremental but aggressive, large scale style changes by considering essentially the whole file.

    I plan to attempt implementing this soon, please let me know if this isn't a feature you'd accept, or if you have any thoughts about the implementation.

    opened by danpalmer 3
  • support c/c++ linting

    support c/c++ linting

    i've written a preliminary package: https://github.com/JerrySievert/imhotep_clangtidy

    can you please give it a once-over and let me know how it looks?

    thanks!

    opened by JerrySievert 2
  • handle symlinks in mac

    handle symlinks in mac

    I had a problem where a lint tool plugin returned symlink paths, but imhotep was looking for the realpath.

    so the plugin returned '/private/var/...', but imhotep was looking for '/var/...'

    This stopped imhotep from detecting the errors here

    This is mac specific.

    So far I cannot tell how to determine if the folder is a symlink...the os.path.realpath does not work here :(

    opened by richtier 1
Owner
Justin Abrahms
Justin Abrahms
Optional static typing for Python 3 and 2 (PEP 484)

Mypy: Optional Static Typing for Python Got a question? Join us on Gitter! We don't have a mailing list; but we are always happy to answer questions o

Python 14.4k Jan 8, 2023
A static type analyzer for Python code

pytype - ?? ✔ Pytype checks and infers types for your Python code - without requiring type annotations. Pytype can: Lint plain Python code, flagging c

Google 4k Dec 31, 2022
Static type checker for Python

Static type checker for Python Speed Pyright is a fast type checker meant for large Python source bases. It can run in a “watch” mode and performs fas

Microsoft 9.2k Jan 3, 2023
The official GitHub mirror of https://gitlab.com/pycqa/flake8

Flake8 Flake8 is a wrapper around these tools: PyFlakes pycodestyle Ned Batchelder's McCabe script Flake8 runs all the tools by launching the single f

Python Code Quality Authority 2.6k Jan 3, 2023
An open-source, mini imitation of GitHub Copilot for Emacs.

Second Mate An open-source, mini imitation of GitHub Copilot using EleutherAI GPT-Neo-2.7B (via Huggingface Model Hub) for Emacs. This is a much small

Sam Rawal 238 Dec 27, 2022
Pylint plugin for improving code analysis for when using Django

pylint-django About pylint-django is a Pylint plugin for improving code analysis when analysing code using Django. It is also used by the Prospector t

Python Code Quality Authority 544 Jan 6, 2023
Static Features Classifier - A static features classifier for Point-Could clusters using an Attention-RNN model

Static Features Classifier This is a static features classifier for Point-Could

ABDALKARIM MOHTASIB 1 Jan 25, 2022
CodeAnalysis - Static Code Analysis: a code comprehensive analysis platform

TCA, Tencent Cloud Code Analysis English | 简体中文 What is TCA Tencent Cloud Code A

Tencent 1.3k Jan 7, 2023
🤖 Automated follow/unfollow bot for GitHub. Uses GitHub API. Written in python.

GitHub Follow Bot Table of Contents Disclaimer How to Use Install requirements Authenticate Get a GitHub Personal Access Token Add your GitHub usernam

João Correia 37 Dec 27, 2022
A static analysis tool for Python

pyanalyze Pyanalyze is a tool for programmatically detecting common mistakes in Python code, such as references to undefined variables and some catego

Quora 212 Jan 7, 2023
Various capabilities for static malware analysis.

Malchive The malchive serves as a compendium for a variety of capabilities mainly pertaining to malware analysis, such as scripts supporting day to da

MITRE Cybersecurity 64 Nov 22, 2022
Awesome autocompletion, static analysis and refactoring library for python

Jedi - an awesome autocompletion, static analysis and refactoring library for Python Jedi is a static analysis tool for Python that is typically used

Dave Halter 5.3k Dec 29, 2022
A Static Analysis Tool for Detecting Security Vulnerabilities in Python Web Applications

This project is no longer maintained March 2020 Update: Please go see the amazing Pysa tutorial that should get you up to speed finding security vulne

null 2.1k Dec 25, 2022
A static analysis library for computing graph representations of Python programs suitable for use with graph neural networks.

python_graphs This package is for computing graph representations of Python programs for machine learning applications. It includes the following modu

Google Research 258 Dec 29, 2022
Cross-platform MachO/ObjC Static binary analysis tool & library. class-dump + otool + lipo + more

ktool Static Mach-O binary metadata analysis tool / information dumper pip3 install k2l Development is currently taking place on the @python3.10 branc

Kritanta 301 Dec 28, 2022
TidyPy is a tool that encapsulates a number of other static analysis tools and makes it easy to configure, execute, and review their results.

TidyPy Contents Overview Features Usage Docker Configuration Ignoring Issues Included Tools Included Reporters Included Integrations Extending TidyPy

Jason Simeone 33 Nov 27, 2022
A simple tool to extract python code from a Jupyter notebook, and then run pylint on it for static analysis.

Jupyter Pylinter A simple tool to extract python code from a Jupyter notebook, and then run pylint on it for static analysis. If you find this tool us

Edmund Goodman 10 Oct 13, 2022
Tool for automatically reordering python imports. Similar to isort but uses static analysis more.

reorder_python_imports Tool for automatically reordering python imports. Similar to isort but uses static analysis more. Installation pip install reor

Anthony Sottile 589 Dec 26, 2022
Robocop is a tool that performs static code analysis of Robot Framework code.

Robocop Introduction Documentation Values Requirements Installation Usage Example Robotidy FAQ Watch our talk from RoboCon 2021 about Robocop and Robo

marketsquare 132 Dec 29, 2022