================== Contributing Guide ================== First and foremost, thank you for wanting to contribute! It's the only way open source works! Before you dive into writing patches, here are some of the basics: * Project page: http://launchpad.net/horizon * Bug tracker: https://bugs.launchpad.net/horizon * Source code: https://github.com/openstack/horizon * Code review: https://review.openstack.org/#q,status:open+project:openstack/horizon,n,z * Continuous integration: * Jenkins: https://jenkins.openstack.org * Zuul: http://status.openstack.org/zuul * IRC Channel: #openstack-horizon on Freenode. Making Contributions ==================== Getting Started --------------- We'll start by assuming you've got a working checkout of the repository (if not then please see the :ref:`quickstart`). Second, you'll need to take care of a couple administrative tasks: #. Create an account on Launchpad. #. Sign the `OpenStack Contributor License Agreement`_ and follow the associated instructions to verify your signature. #. Join the `Horizon Developers`_ team on Launchpad. #. Follow the `instructions for setting up git-review`_ in your development environment. Whew! Got all that? Okay! You're good to go. .. _`OpenStack Contributor License Agreement`: http://wiki.openstack.org/CLA .. _`Horizon Developers`: https://launchpad.net/~horizon .. _`instructions for setting up git-review`: https://docs.openstack.org/infra/manual/developers.html#development-workflow Ways To Contribute ------------------ The easiest way to get started with Horizon's code is to pick a bug on Launchpad that interests you, and start working on that. Bugs tagged as ``low-hanging-fruit`` are a good place to start. Alternatively, if there's an OpenStack API feature you would like to see implemented in Horizon feel free to try building it. If those are too big, there are lots of great ways to get involved without plunging in head-first: * Report bugs, triage new tickets, and review old tickets on the `bug tracker`_. * Propose ideas for improvements via `Launchpad Blueprints`_, via the mailing list on the project page, or on IRC. * Write documentation! * Write unit tests for untested code! * Help improve the `User Experience Design`_ or contribute to the `Persona Working Group`_. .. _`bug tracker`: https://bugs.launchpad.net/horizon .. _`Launchpad Blueprints`: https://blueprints.launchpad.net/horizon .. _`User Experience Design`: https://wiki.openstack.org/wiki/UX#Getting_Started .. _`Persona Working Group`: https://wiki.openstack.org/wiki/Personas Choosing Issues To Work On -------------------------- In general, if you want to write code, there are three cases for issues you might want to work on: #. Confirmed bugs #. Approved blueprints (features) #. New bugs you've discovered If you have an idea for a new feature that isn't in a blueprint yet, it's a good idea to write the blueprint first, so you don't end up writing a bunch of code that may not go in the direction the community wants. For bugs, open the bug first, but if you can reproduce the bug reliably and identify its cause then it's usually safe to start working on it. However, getting independent confirmation (and verifying that it's not a duplicate) is always a good idea if you can be patient. After You Write Your Patch -------------------------- Once you've made your changes, there are a few things to do: * Make sure the unit tests and linting tasks pass by running ``tox`` * Take a look at your patch in API profiler, i.e. how it impacts the performance. See `Profiling Pages`_. * Make sure your code is ready for translation: See :ref:`pseudo_translation`. * Make sure your code is up-to-date with the latest master: ``git pull --rebase`` * Finally, run ``git review`` to upload your changes to Gerrit for review. The Horizon core developers will be notified of the new review and will examine it in a timely fashion, either offering feedback or approving it to be merged. If the review is approved, it is sent to Jenkins to verify the unit tests pass and it can be merged cleanly. Once Jenkins approves it, the change will be merged to the master repository and it's time to celebrate! Profiling Pages --------------- In the Ocata release of Horizon a new "OpenStack Profiler" panel was introduced. Once it is enabled and all prerequisites are set up, you can see which API calls Horizon actually makes when rendering a specific page. To re-render the page while profiling it, you'll need to use the "Profile" dropdown menu located in the top right corner of the screen. In order to be able to use "Profile" menu, the following steps need to be completed: #. Enable the Developer dashboard by copying ``_9001_developer.py`` from ``openstack_dashboard/contrib/developer/enabled/`` to ``openstack_dashboard/local/enabled/``. #. Copy ``openstack_dashboard/local/local_settings.d/_9030_profiler_settings.py.example`` to ``openstack_dashboard/local/local_settings.d/_9030_profiler_settings.py`` #. Copy ``openstack_dashboard/contrib/developer/enabled/_9030_profiler.py`` to ``openstack_dashboard/local/enabled/_9030_profiler.py``. #. To support storing profiler data on server-side, MongoDB cluster needs to be installed on your Devstack host (default configuration), see `Installing MongoDB`_. Then, change the ``bindIp`` key in ``/etc/mongod.conf`` to ``0.0.0.0`` and invoke ``sudo service mongod restart``. #. Collect and compress static assets with ``python manage.py collectstatic -c`` and ``python manage.py compress`` #. Restart the web server. #. The "Profile" drop-down menu should appear in the top-right corner, you are ready to profile your pages! .. _installing MongoDB: https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/#install-mongodb-community-edition Etiquette ========= The community's guidelines for etiquette are fairly simple: * Treat everyone respectfully and professionally. * If a bug is "in progress" in the bug tracker, don't start working on it without contacting the author. Try on IRC, or via the launchpad email contact link. If you don't get a response after a reasonable time, then go ahead. Checking first avoids duplicate work and makes sure nobody's toes get stepped on. * If a blueprint is assigned, even if it hasn't been started, be sure you contact the assignee before taking it on. These larger issues often have a history of discussion or specific implementation details that the assignee may be aware of that you are not. * Please don't re-open tickets closed by a core developer. If you disagree with the decision on the ticket, the appropriate solution is to take it up on IRC or the mailing list. * Give credit where credit is due; if someone helps you substantially with a piece of code, it's polite (though not required) to thank them in your commit message. Code Style ========== As a project, Horizon adheres to code quality standards. Python ------ We follow PEP8_ for all our Python code, and use ``pep8.py`` (available via the shortcut ``tox -e pep8``) to validate that our code meets proper Python style guidelines. .. _PEP8: http://www.python.org/dev/peps/pep-0008/ Django ------ Additionally, we follow `Django's style guide`_ for templates, views, and other miscellany. .. _Django's style guide: https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/ JavaScript ---------- The following standards are divided into required and recommended sections. Our main goal in establishing these best practices is to have code that is reliable, readable, and maintainable. Required ~~~~~~~~ **Reliable** * The code has to work on the stable and latest versions of Firefox, Chrome, Safari, and Opera web browsers, and on Microsoft Internet Explorer 11 and later. * If you turned compression off during development via ``COMPRESS_ENABLED = False`` in local_settings.py, re-enable compression and test your code before submitting. * Use ``===`` as opposed to ``==`` for equality checks. The ``==`` will do a type cast before comparing, which can lead to unwanted results. .. note:: If typecasting is desired, explicit casting is preferred to keep the meaning of your code clear. * Keep document reflows to a minimum. DOM manipulation is expensive, and can become a performance issue. If you are accessing the DOM, make sure that you are doing it in the most optimized way. One example is to build up a document fragment and then append the fragment to the DOM in one pass instead of doing multiple smaller DOM updates. * Use “strict”, enclosing each JavaScript file inside a self-executing function. The self-executing function keeps the strict scoped to the file, so its variables and methods are not exposed to other JavaScript files in the product. .. Note :: Using strict will throw exceptions for common coding errors, like accessing global vars, that normally are not flagged. Example: :: (function(){ 'use strict'; // code... })(); * Use ``forEach`` | ``each`` when looping whenever possible. AngularJS and jQuery both provide for each loops that provide both iteration and scope. AngularJS: :: angular.forEach(objectToIterateOver, function(value, key) { // loop logic }); jQuery: :: $.each(objectToIterateOver, function(key, value) { // loop logic }); * Do not put variables or functions in the global namespace. There are several reasons why globals are bad, one being that all JavaScript included in an application runs in the same scope. The issue with that is if another script has the same method or variable names they overwrite each other. * Always put ``var`` in front of your variables. Not putting ``var`` in front of a variable puts that variable into the global space, see above. * Do not use ``eval( )``. The eval (expression) evaluates the expression passed to it. This can open up your code to security vulnerabilities and other issues. * Do not use '``with`` object {code}'. The ``with`` statement is used to access properties of an object. The issue with ``with`` is that its execution is not consistent, so by reading the statement in the code it is not always clear how it is being used. **Readable & Maintainable** * Give meaningful names to methods and variables. * Avoid excessive nesting. * Avoid HTML and CSS in JS code. HTML and CSS belong in templates and stylesheets respectively. For example: * In our HTML files, we should focus on layout. 1. Reduce the small/random ``