certbot/docs/contributing.rst
2015-10-21 17:06:36 -07:00

371 lines
10 KiB
ReStructuredText

============
Contributing
============
.. _hacking:
Hacking
=======
All changes in your pull request **must** have 100% unit test coverage, pass
our `integration`_ tests, **and** be compliant with the
:ref:`coding style <coding-style>`.
Bootstrap
---------
Start by :ref:`installing Let's Encrypt prerequisites
<prerequisites>`. Then run:
.. code-block:: shell
./bootstrap/dev/venv.sh
Activate the virtualenv:
.. code-block:: shell
source ./$VENV_NAME/bin/activate
This step should prepend you prompt with ``($VENV_NAME)`` and save you
from typing ``./$VENV_NAME/bin/...``. It is also required to run some
of the `testing`_ tools. Virtualenv can be disabled at any time by
typing ``deactivate``. More information can be found in `virtualenv
documentation`_.
Note that packages are installed in so called *editable mode*, in
which any source code changes in the current working directory are
"live" and no further ``./bootstrap/dev/venv.sh`` or ``pip install
...`` invocations are necessary while developing.
.. _`virtualenv documentation`: https://virtualenv.pypa.io
Testing
-------
The following tools are there to help you:
- ``tox`` starts a full set of tests. Please make sure you run it
before submitting a new pull request.
- ``tox -e cover`` checks the test coverage only. Calling the
``./tox.cover.sh`` script directly (or even ``./tox.cover.sh $pkg1
$pkg2 ...`` for any subpackages) might be a bit quicker, though.
- ``tox -e lint`` checks the style of the whole project, while
``pylint --rcfile=.pylintrc path`` will check a single file or
specific directory only.
- For debugging, we recommend ``pip install ipdb`` and putting
``import ipdb; ipdb.set_trace()`` statement inside the source
code. Alternatively, you can use Python's standard library `pdb`,
but you won't get TAB completion...
Integration
~~~~~~~~~~~
Mac OS X users: Run `./tests/mac-bootstrap.sh` instead of `boulder-start.sh` to
install dependencies, configure the environment, and start boulder.
Otherwise, install `Go`_ 1.5, libtool-ltdl, mariadb-server and
rabbitmq-server and then start Boulder_, an ACME CA server::
./tests/boulder-start.sh
The script will download, compile and run the executable; please be
patient - it will take some time... Once its ready, you will see
``Server running, listening on 127.0.0.1:4000...``. Add an
``/etc/hosts`` entry pointing ``le.wtf`` to 127.0.0.1. You may now
run (in a separate terminal)::
./tests/boulder-integration.sh && echo OK || echo FAIL
If you would like to test `letsencrypt_nginx` plugin (highly
encouraged) make sure to install prerequisites as listed in
``letsencrypt-nginx/tests/boulder-integration.sh`` and rerun
the integration tests suite.
.. _Boulder: https://github.com/letsencrypt/boulder
.. _Go: https://golang.org
Vagrant
-------
If you are a Vagrant user, Let's Encrypt comes with a Vagrantfile that
automates setting up a development environment in an Ubuntu 14.04
LTS VM. To set it up, simply run ``vagrant up``. The repository is
synced to ``/vagrant``, so you can get started with:
.. code-block:: shell
vagrant ssh
cd /vagrant
./venv/bin/pip install -r requirements.txt .[dev,docs,testing]
sudo ./venv/bin/letsencrypt
Support for other Linux distributions coming soon.
.. note::
Unfortunately, Python distutils and, by extension, setup.py and
tox, use hard linking quite extensively. Hard linking is not
supported by the default sync filesystem in Vagrant. As a result,
all actions with these commands are *significantly slower* in
Vagrant. One potential fix is to `use NFS`_ (`related issue`_).
.. _use NFS: http://docs.vagrantup.com/v2/synced-folders/nfs.html
.. _related issue: https://github.com/ClusterHQ/flocker/issues/516
Docker
------
OSX users will probably find it easiest to set up a Docker container for
development. Let's Encrypt comes with a Dockerfile (``Dockerfile-dev``)
for doing so. To use Docker on OSX, install and setup docker-machine using the
instructions at https://docs.docker.com/installation/mac/.
To build the development Docker image::
docker build -t letsencrypt -f Dockerfile-dev .
Now run tests inside the Docker image:
.. code-block:: shell
docker run -it letsencrypt bash
cd src
tox -e py27
Code components and layout
==========================
acme
contains all protocol specific code
letsencrypt
all client code
Plugin-architecture
-------------------
Let's Encrypt has a plugin architecture to facilitate support for
different webservers, other TLS servers, and operating systems.
The interfaces available for plugins to implement are defined in
`interfaces.py`_.
The most common kind of plugin is a "Configurator", which is likely to
implement the `~letsencrypt.interfaces.IAuthenticator` and
`~letsencrypt.interfaces.IInstaller` interfaces (though some
Configurators may implement just one of those).
There are also `~letsencrypt.interfaces.IDisplay` plugins,
which implement bindings to alternative UI libraries.
.. _interfaces.py: https://github.com/letsencrypt/letsencrypt/blob/master/letsencrypt/interfaces.py
Authenticators
--------------
Authenticators are plugins designed to solve challenges received from
the ACME server. From the protocol, there are essentially two
different types of challenges. Challenges that must be solved by
individual plugins in order to satisfy domain validation (subclasses
of `~.DVChallenge`, i.e. `~.challenges.DVSNI`,
`~.challenges.SimpleHTTPS`, `~.challenges.DNS`) and continuity specific
challenges (subclasses of `~.ContinuityChallenge`,
i.e. `~.challenges.RecoveryToken`, `~.challenges.RecoveryContact`,
`~.challenges.ProofOfPossession`). Continuity challenges are
always handled by the `~.ContinuityAuthenticator`, while plugins are
expected to handle `~.DVChallenge` types.
Right now, we have two authenticator plugins, the `~.ApacheConfigurator`
and the `~.StandaloneAuthenticator`. The Standalone and Apache
authenticators only solve the `~.challenges.DVSNI` challenge currently.
(You can set which challenges your authenticator can handle through the
:meth:`~.IAuthenticator.get_chall_pref`.
(FYI: We also have a partial implementation for a `~.DNSAuthenticator`
in a separate branch).
Installer
---------
Installers classes exist to actually setup the certificate and be able
to enhance the configuration. (Turn on HSTS, redirect to HTTPS,
etc). You can indicate your abilities through the
:meth:`~.IInstaller.supported_enhancements` call. We currently only
have one Installer written (still developing), `~.ApacheConfigurator`.
Installers and Authenticators will oftentimes be the same
class/object. Installers and Authenticators are kept separate because
it should be possible to use the `~.StandaloneAuthenticator` (it sets
up its own Python server to perform challenges) with a program that
cannot solve challenges itself. (Imagine MTA installers).
Installer Development
---------------------
There are a few existing classes that may be beneficial while
developing a new `~letsencrypt.interfaces.IInstaller`.
Installers aimed to reconfigure UNIX servers may use Augeas for
configuration parsing and can inherit from `~.AugeasConfigurator` class
to handle much of the interface. Installers that are unable to use
Augeas may still find the `~.Reverter` class helpful in handling
configuration checkpoints and rollback.
Display
~~~~~~~
We currently offer a pythondialog and "text" mode for displays. Display
plugins implement the `~letsencrypt.interfaces.IDisplay`
interface.
.. _coding-style:
Coding style
============
Please:
1. **Be consistent with the rest of the code**.
2. Read `PEP 8 - Style Guide for Python Code`_.
3. Follow the `Google Python Style Guide`_, with the exception that we
use `Sphinx-style`_ documentation::
def foo(arg):
"""Short description.
:param int arg: Some number.
:returns: Argument
:rtype: int
"""
return arg
4. Remember to use ``pylint``.
.. _Google Python Style Guide:
https://google-styleguide.googlecode.com/svn/trunk/pyguide.html
.. _Sphinx-style: http://sphinx-doc.org/
.. _PEP 8 - Style Guide for Python Code:
https://www.python.org/dev/peps/pep-0008
Submitting a pull request
=========================
Steps:
1. Write your code!
2. Make sure your environment is set up properly and that you're in your
virtualenv. You can do this by running ``./bootstrap/dev/venv.sh``.
(this is a **very important** step)
3. Run ``./pep8.travis.sh`` to do a cursory check of your code style.
Fix any errors.
4. Run ``tox -e lint`` to check for pylint errors. Fix any errors.
5. Run ``tox`` to run the entire test suite including coverage. Fix any errors.
6. If your code touches communication with an ACME server/Boulder, you
should run the integration tests, see `integration`_.
7. Submit the PR.
Updating the documentation
==========================
In order to generate the Sphinx documentation, run the following
commands:
.. code-block:: shell
make -C docs clean html
This should generate documentation in the ``docs/_build/html``
directory.
.. _prerequisites:
Notes on OS depedencies
=======================
OS level dependencies are managed by scripts in ``bootstrap``. Some notes
are provided here mainly for the :ref:`developers <hacking>` reference.
In general:
* ``sudo`` is required as a suggested way of running privileged process
* `Augeas`_ is required for the Python bindings
* ``virtualenv`` and ``pip`` are used for managing other python library
dependencies
.. _Augeas: http://augeas.net/
.. _Virtualenv: https://virtualenv.pypa.io
Ubuntu
------
.. code-block:: shell
sudo ./bootstrap/ubuntu.sh
Debian
------
.. code-block:: shell
sudo ./bootstrap/debian.sh
For squeeze you will need to:
- Use ``virtualenv --no-site-packages -p python`` instead of ``-p python2``.
.. _`#280`: https://github.com/letsencrypt/letsencrypt/issues/280
Mac OSX
-------
.. code-block:: shell
./bootstrap/mac.sh
Fedora
------
.. code-block:: shell
sudo ./bootstrap/fedora.sh
Centos 7
--------
.. code-block:: shell
sudo ./bootstrap/centos.sh
FreeBSD
-------
.. code-block:: shell
sudo ./bootstrap/freebsd.sh
Bootstrap script for FreeBSD uses ``pkg`` for package installation,
i.e. it does not use ports.
FreeBSD by default uses ``tcsh``. In order to activate virtualenv (see
below), you will need a compatible shell, e.g. ``pkg install bash &&
bash``.