Developer Setup
===============
The following describes how to set up an instance of the site on your
computer for development.

Prerequisites
-------------
This guide assumes you have already installed and set up the following:

1. Git_
2. `Python 3.9`_, and `Poetry`_
3. `Node.js 8`_ and NPM 5 or higher
4. `Postgres 9.4`_
5. ``openssl``

These docs assume a Unix-like operating system, although the site should, in
theory, run on Windows as well. All the example commands given below are
intended to be run in a terminal.

.. _Git: https://git-scm.com/
.. _Python 3.9: https://www.python.org/
.. _pip 8: https://pip.pypa.io/en/stable/
.. _Node.js 8: https://nodejs.org/en/
.. _virtualenv: https://virtualenv.pypa.io/en/latest/
.. _Postgres 9.4: http://www.postgresql.org/
.. _Poetry: https://python-poetry.org/docs/

Installation
------------
1. Clone this repository or your fork_:

   .. code-block:: bash

      git clone https://github.com/mozilla/normandy.git
      cd normandy

2. Install the dependencies using Poetry:

   .. code-block:: bash

      poetry install

3. Activate the poetry virtual environment. The easiest way to do this is to start a
   new shell with Poetry.

      poetry shell

4. (Optional) Install frontend dependencies using yarn_
   and build the legacy action code:

   .. code-block:: bash

      yarn install
      yarn build

   This JS code is only used for legacy clients that do not have actions
   implemented directly in the client. It can be safely ignored in most
   development environments.

.. _yarn: https://yarnpkg.com/lang/en/docs/install/

5. Create a Postgres database for Normandy. By default it is assumed to be named
   ``normandy``:

   .. code-block:: bash

      createdb normandy

   .. note::

      By default, it will connect to ``localhost`` using the global ``postgres``
      user. If you use a different name for the database, or otherwise want to
      customize how you connect to the database, you may specify the database
      URL by adding the following to a ``.env`` file at the root of the repo:

      .. code-block:: ini

         DATABASE_URL=postgres://username:password@server_addr/database_name

6. Initialize your database by running the migrations:

   .. code-block:: bash

      python manage.py migrate

7. Create a new superuser account:

   .. code-block:: bash

      python manage.py createsuperuser

8. (Optional) Pull the latest geolocation database using the ``download_geolite2.sh``
   script:

   .. code-block:: bash

      ./bin/download_geolite2.sh

   The geolocation database is used for the classify client API endpoint. It
   is required for recipes that use geolocation filters, but can be omitted.

9. (Optional) If you built the JS actions, load them into the database:

   .. code-block:: bash

      python manage.py update_actions

10. Update product details to provide a list of languages supported by Firefox.

   .. code-block:: bash

      python manage.py update_product_details

11. Load in initial data:

   .. code-block:: bash

      python manage.py initial_data

Once you've finished these steps, you should be able to start the site by
running:

.. code-block:: bash

   ./bin/runsslserver.sh

.. note::

   The ``runsslserver.sh`` command automatically creates a self-signed
   certificate in the ``etc/ssl`` directory of the repository. When viewing the
   site for the first time, you will have to create a certificate exception to
   allow Firefox to accept the certificate and access the site over HTTPS.

The site should be available at https://localhost:8000/. The main page will
have the message "This interface has been removed". The API is available at
the endpoint ``/api/v3/``. No user interface is provided.

.. _fork: http://help.github.com/fork-a-repo/

Alternative Setup and Use
_________________________

If you would like to use docker instead please reference the docker_ section.

.. _docker: Docker Setup for local development

Autograph
---------
If you want to execute recipes on your local instance using the recipe
client, you'll need to set up Autograph_ to sign recipes as you save them:

1. Follow the `Autograph installation instructions`_ to launch a development
   instance of Autograph.

2. Add the following configuration to ``.env`` (create the file
   if it does not exist yet):

   .. code-block:: ini

      DJANGO_AUTOGRAPH_URL=http://localhost:8765/
      DJANGO_AUTOGRAPH_HAWK_ID=normandev
      DJANGO_AUTOGRAPH_HAWK_SECRET_KEY=3dhoaupudifjjvm7xznd9bn73159xn3xwr77b61kzdjwzzsjts

.. note:

   The credentials provided here are not arbitrary. They are part of the
   default autograph configuration. They should be used exactly unless you
   are using an advanced Autograph configuration.

With the configuration in place, you should see log messages when saving recipes
that look like this::

   INFO 2017-05-01 19:58:04,274 normandy.recipes.models Requesting signatures for recipes with ids [16] from Autograph
   INFO 2017-05-01 19:58:04,301 normandy.recipes.utils Got 1 signatures from Autograph

.. _Autograph: https://github.com/mozilla-services/autograph
.. _Autograph installation instructions: https://github.com/mozilla-services/autograph#installation

.. _therapist-install:

Therapist
---------
If you want to automatically enforce Normandy code style guidelines, you can
use the `Therapist`_ pre-commit hook. To install Therapist, simply run:

.. code-block:: bash

      pip install therapist

After that, you should be able to run
the following to set up the git pre-commit hook:

.. code-block:: bash

      therapist install

After that, whenever you make a new commit Therapist will check the changed
code. This will save time when submitting pull requests.

If you want Therapist to attempt to automatically fix linting issues you can
install the hook using:

.. code-block:: bash

      therapist install --fix

If you ever need to bypass Therapist, you can do so by passing
``--no-verify`` to your ``git commit`` command.

.. _Therapist: http://therapist.readthedocs.io/en/latest/overview.html

.. _remote-settings-install:

Remote Settings
---------------
If you want to enable the publication of recipes on `Remote Settings`_, you'll need to set up
an instance locally.

1. Follow the `Remote Settings installation instructions`_ to launch a development
   instance of Remote Settings locally.

2. Configure Normandy to enable the integration by adding the following lines
   to ``.env`` (create the file if it does not exist yet):

   .. code-block:: ini

      DJANGO_REMOTE_SETTINGS_URL=http://localhost:8888/v1
      DJANGO_REMOTE_SETTINGS_USERNAME=normandy
      DJANGO_REMOTE_SETTINGS_PASSWORD=n0rm4ndy

3. Adjust the Remote Settings configuration in ``server.ini`` for the Normandy
   recipes collection, and restart the Remote Settings container:

   .. code-block:: ini

      kinto.signer.main-workspace.normandy-recipes.to_review_enabled = false
      kinto.signer.main-workspace.normandy-recipes.group_check_enabled = false

4. Create the dedicated Remote Settings user and collection for Normandy:

   .. code-block:: bash

      SERVER=http://localhost:8888/v1

      curl -X PUT ${SERVER}/accounts/normandy \
           -d '{"data": {"password": "n0rm4ndy"}}' \
           -H 'Content-Type:application/json'

      curl -X PUT ${SERVER}/buckets/main-workspace \
           -H 'Content-Type:application/json' \
           -u 'normandy:n0rm4ndy'

      curl -X PUT ${SERVER}/buckets/main-workspace/collections/normandy-recipes \
           -H 'Content-Type:application/json' \
           -u 'normandy:n0rm4ndy'

      curl -X PUT ${SERVER}/buckets/main-workspace/collections/normandy-recipes-capabilities \
           -H 'Content-Type:application/json' \
           -u 'normandy:n0rm4ndy'

With both configurations in place, Normandy should start without error.

.. seealso::

   The :ref:`documentation section dedicated to Remote Settings <remote-settings>`

.. _Remote Settings: https://remote-settings.readthedocs.io
.. _Remote Settings installation instructions: https://remote-settings.readthedocs.io/en/latest/tutorial-local-server.html