From e06492ec3a6fe79e0d5eb143d4d3df4d3788b8c4 Mon Sep 17 00:00:00 2001 From: Christie Koehler Date: Wed, 4 May 2016 16:16:31 -0700 Subject: [PATCH] Improve first-time contributor docs. Fixes #747. Fixes #748. This updates README.dev.md to include clear, step-by-step instructions for setting up the Zulip dev environment Windows 10, OS X El Capitan, Ubuntu 14.04 Trusty, and Ubuntu 16.04 Xenial. It is aimed at first-time contributors. I tested these instructions multiple times on each of the target systems. Also added is a "trobleshooting and common errors" section which documents the most common errors contributors are likely to encounter during setup and how to fix them. Improvements based on feedback from @timabbott. - Fixes whitespace issues so linter will pass. - Updates memory requirement. - Re-orders so operating systems are listed alphabetically. - Updates headings to be clearer. - Updates and adds ToC entries for clarity. - Adds screen shot of Zulip dev environment running in browser. - Adds details about using dev environment, including about logging. - Misc other minor changes for clarity. - Adds a stub for docs/logging.md - Adds details about configuring Cygwin for native symlinks. --- README.dev.md | 807 +++++++++++++++++++++++++++++++++++++- docs/images/zulip-dev.png | Bin 0 -> 67657 bytes docs/index.rst | 1 + docs/logging.md | 24 ++ 4 files changed, 812 insertions(+), 20 deletions(-) create mode 100644 docs/images/zulip-dev.png create mode 100644 docs/logging.md diff --git a/README.dev.md b/README.dev.md index c0829846c7..24b81607e0 100644 --- a/README.dev.md +++ b/README.dev.md @@ -2,13 +2,740 @@ Installing the Zulip Development environment ============================================ -You will need a machine with at least 1.25GB of RAM available. +* [Development environment setup for first-time + contributors](#development-environment-setup-for-first-time-contributors) +* [Brief installation instructions for Vagrant development + environment](#brief-installation-instructions-for-vagrant-development-environment) +* [Installing on Ubuntu 14.04 Trusty without + Vagrant](#installing-on-ubuntu-1404-trusty-without-vagrant) (possibly more + convenient but more work to maintain/uninstall) +* [Installing manually on UNIX-based + platforms](#installing-manually-on-unix-based-platforms) +* [Using Docker (experimental)](#using-docker-experimental) +* [Using the Development Environment](#using-the-development-environment) +* [Running the test suite](#running-the-test-suite) +* [Possible testing issues](#possible-testing-issues) + +Those who have installed Zulip before or are experienced at administering Linux +may wish to skip ahead to [Brief installation instructions for Vagrant +development environment](#brief-installation-instructions-for-vagrant-development-environment), +[Using Docker (experimental)](#using-docker-experimental), or [Installing +manually on UNIX-based platforms](#installing-manually-on-unix-based-platforms). + +## Development environment setup for first-time contributors + +This section guides first-time contributors through installing the Zulip dev +environment on Windows 10, OS X El Capitan, Ubuntu 14.04, and Ubuntu 16.04. + +The recommended method for installing the Zulip dev environment is to use +Vagrant with VirtualBox on Windows and OS X, and Vagrant with LXC on +Ubuntu. This method creates a virtual machine (for Windows and OS X) +or a Linux container (for Ubuntu) inside which the Zulip server and +all related services will run. + +Contents: +* [Requirements](#requirements) +* [Step 1: Install Prerequisites](#step-1-install-prerequisites) +* [Step 2: Get Zulip code](#step-2-get-zulip-code) +* [Step 3: Start the dev environment](#step-3-start-the-dev-environment) +* [Step 4: Developing](#step-4-developing) +* [Troubleshooting & Common Errors](#troubleshooting--common-errors) + +If you encounter errors installing the Zulip dev environment and they are not addressed in [Troubleshooting & Common Errors](#troubleshooting--common-errors), send a note to the [Zulip-devel Google group](https://groups.google.com/forum/#!forum/zulip-devel) or [file an issue](https://github.com/zulip/zulip/issues). + +### Requirements + +Installing the Zulip dev environment requires downloading several +hundred megabytes of dependencies. You will need an active internet +connection throughout the entire installation processes. (See +[Specifying a proxy](#specifying-a-proxy) if you need a proxy to +access the internet.) + + +- **All**: 1.5GB available RAM, Active broadband internet connection. +- **OS X**: OS X (El Capitan recommended, untested on previous versions), Git, + [VirtualBox][vbox-dl], [Vagrant][vagrant-dl]. +- **Ubuntu**: 14.04 64-bit or 16.04 64-bit, Git, [Vagrant][vagrant-dl], lxc. +- **Windows**: Windows 64-bit (Win 10 recommended; Win 7 untested), hardware + virtualization enabled (VT-X or AMD-V), administrator access, + [Cygwin][cygwin-dl], [VirtualBox][vbox-dl], [Vagrant][vagrant-dl]. + +Don't see your system listed above? Check out: +* [Brief installation instructions for Vagrant development + environment](#brief-installation-instructions-for-vagrant-development-environment) +* [Installing manually on UNIX-based + platforms](#installing-manually-on-unix-based-platforms) + +[cygwin-dl]: http://cygwin.com/ + +### Step 1: Install Prerequisites + +Jump to: + +* [OS X](#os-x) +* [Ubuntu 14.04 Trusty](#ubuntu-1404) +* [Ubuntu 16.04 Xenial](#ubuntu-1604) +* [Windows](#windows-10) + +#### OS X + +1. Install [VirtualBox][vbox-dl] +2. Install [Vagrant][vagrant-dl] + +Now you are ready for [Step 2: Get Zulip Code.](#step-2-get-zulip-code) + +#### Ubuntu 14.04 + +If you're in a hurry, you can copy and paste into your terminal after which you +can jump to [Step 2: Get Zulip Code](#step-2-get-zulip-code): + +``` +sudo apt-get purge vagrant +wget https://releases.hashicorp.com/vagrant/1.8.1/vagrant_1.8.1_x86_64.deb +sudo dpkg -i vagrant*.deb +sudo apt-get install git lxc lxc-templates cgroup-lite redir +vagrant plugin install vagrant-lxc +``` + +For a step-by-step explanation, read on. + +##### 1. Install Vagrant + +For 14.04 Trusty you'll need a more recent version of Vagrant than what's +available in the official Ubuntu repositories. + +First uninstall any vagrant package you may have installed from the Ubuntu +repository: + +``` +christie@trusty-desktop:~ +$ sudo apt-get purge vagrant +``` + +Now download and install the most recent .deb package from [Vagrant][vagrant-dl]: + +``` +christie@trusty-desktop:~ +$ wget https://releases.hashicorp.com/vagrant/1.8.1/vagrant_1.8.1_x86_64.deb + +christie@trusty-desktop:~ +$ sudo dpkg -i vagrant*.deb +``` + + +##### 2. Install remaining dependencies + +Now install git and lxc-related packages: + +``` +christie@trusty-desktop:~ +$ sudo apt-get install git lxc lxc-templates cgroup-lite redir +``` + +##### 3. Install the vagrant lxc plugin: + +``` +christie@trusty-desktop:~ +$ vagrant plugin install vagrant-lxc +Installing the 'vagrant-lxc' plugin. This can take a few minutes... +Installed the plugin 'vagrant-lxc (1.2.1)'! +``` + +Now you are ready for [Step 2: Get Zulip Code.](#step-2-get-zulip-code) + +#### Ubuntu 16.04 + +If you're in a hurry, you can copy and paste into your terminal after which you +can jump to [Step 2: Get Zulip Code](#step-2-get-zulip-code): + +``` +sudo apt-get install git vagrant lxc lxc-templates cgroup-lite redir +vagrant plugin install vagrant-lxc +vagrant lxc sudoers +``` + +For a step-by-step explanation, read on. + +##### 1. Install git, vagrant, lxc, and related dependencies: + +``` +christie@xenial-desktop:~ +$ sudo apt-get install git vagrant lxc lxc-templates cgroup-lite redir +``` + +##### 2. Install the vagrant lxc plugin: + +``` +christie@xenial-desktop:~ +$ vagrant plugin install vagrant-lxc +Installing the 'vagrant-lxc' plugin. This can take a few minutes... +Installed the plugin 'vagrant-lxc (1.2.1)'! +``` + +If you encounter an error when trying to install the vagrant-lxc plugin, [see +this](#nomethoderror-when-installing-vagrant-lxc-plugin-ubuntu-1604). + +##### 3. Configure sudo to be passwordless + +Finally, [configure sudo to be passwordless when using Vagrant LXC][avoiding-sudo]: + +``` +christie@xenial-desktop:~ +$ vagrant lxc sudoers +[sudo] password for christie: +``` + +Now you are ready for [Step 2: Get Zulip Code.](#step-2-get-zulip-code) + +#### Windows 10 + +1. Install [Cygwin][cygwin-dl]. Make sure to install default required + packages along with **git**, **curl**, **openssh**, and **rsync** + binaries. +2. Install [VirtualBox][vbox-dl] +3. Install [Vagrant][vagrant-dl] + +##### Configure Cygwin + +In order for symlinks to work within the Ubuntu virtual machine, you must tell +Cygwin to create them as [native Windows +symlinks](https://cygwin.com/cygwin-ug-net/using.html#pathnames-symlinks). The +easiest way to do this is to add a line to `~/.bash_profile` setting the CYGWIN +environment variable. + +Open a Cygwin window and do this: + +``` +christie@win10 ~ +$ echo 'export "CYGWIN=$CYGWIN winsymlinks:native"' >> ~/.bash_profile +``` + +Next, close that Cygwin window and open another. If you `echo` $CYGWIN you +should see: + +``` +christie@win10 ~ +$ echo $CYGWIN +winsymlinks:native +``` + +Now you are ready for [Step 2: Get Zulip Code.](#step-2-get-zulip-code) + +### Step 2: Get Zulip Code + +If you haven't already created an ssh key and added it to your Github account, +you should do that now by following [these +instructions](https://help.github.com/articles/generating-an-ssh-key/). + +1. In your browser, visit https://github.com/zulip/zulip and click the + `fork` button. You will need to be logged in to Github to do this. +2. Open Terminal (OS X/Ubuntu) or Cygwin (Windows; must run as an Administrator) +3. In Terminal/Cygwin, clone your fork: +``` +git clone git@github.com:YOURUSERNAME/zulip.git +``` + +This will create a 'zulip' directory and download the Zulip code into it. + +Don't forget to replace YOURUSERNAME with your git username. You will see +something like: + +``` +christie@win10 ~ +$ git clone git@github.com:YOURUSERNAME/zulip.git +Cloning into 'zulip'... +remote: Counting objects: 73571, done. +remote: Compressing objects: 100% (2/2), done. +remote: Total 73571 (delta 1), reused 0 (delta 0), pack-reused 73569 +Receiving objects: 100% (73571/73571), 105.30 MiB | 6.46 MiB/s, done. +Resolving deltas: 100% (51448/51448), done. +Checking connectivity... done. +Checking out files: 100% (1912/1912), done.` +``` + +Now you are ready for [Step 3: Start the dev +environment.](#step-3-start-the-dev-environment) + +### Step 3: Start the dev environment + +Change into the zulip directory and tell vagrant to start the Zulip +dev environment with `vagrant up`. + +``` +christie@win10 ~ +$ cd zulip + +christie@win10 ~/zulip +$ vagrant up +``` + +The first time you run this command it will take some time because vagrant +does the following: + +- downloads the base Ubuntu 14.04 virtual machine image (for OS X and Windows) + or container (for Ubuntu) +- configures this virtual machine/container for use with Zulip, +- creates a shared directory mapping your clone of the Zulip code inside the + virtual machine/container at `/srv/zulip` +- runs the `provision.py` script inside the virtual machine/container, which + downloads all required dependencies, sets up the python environment for + the Zulip dev environment, and initializes a default test database. + +You will need an active internet connection during the entire processes. (See +[Specifying a proxy](#specifying-a-proxy) if you need a proxy to access the +internet.) + +Once `vagrant up` has completed, connect to the dev environment with `vagrant +ssh`: + +``` +christie@win10 ~/zulip +$ vagrant ssh +``` + +You should see something like this on Windows and OS X: + +``` +Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.13.0-85-generic x86_64) + + * Documentation: https://help.ubuntu.com/ + + System information as of Wed May 4 21:45:43 UTC 2016 + + System load: 0.61 Processes: 88 + Usage of /: 3.5% of 39.34GB Users logged in: 0 + Memory usage: 7% IP address for eth0: 10.0.2.15 + Swap usage: 0% + + Graph this data and manage this system at: + https://landscape.canonical.com/ + + Get cloud support with Ubuntu Advantage Cloud Guest: + http://www.ubuntu.com/business/services/cloud + +0 packages can be updated. +0 updates are security updates. +``` + +Or something as brief as this in the case of Ubuntu: + +``` +Welcome to Ubuntu 14.04.1 LTS (GNU/Linux 4.4.0-21-generic x86_64) + + * Documentation: https://help.ubuntu.com/ +``` + +Congrats, you're now inside the Zulip dev environment! + +You can confirm this by looking at the command prompt, which starts with +`(zulip-venv)`. + +Next, start the Zulip server: + +``` +(zulip-venv)vagrant@vagrant-ubuntu-trusty-64:~ $ +/srv/zulip/tools/run-dev.py --interface='' +``` + +You will see several lines of output starting with something like: + +``` +2016-05-04 22:20:33,895 INFO: process_fts_updates starting +Recompiling templates +2016-05-04 18:20:34,804 INFO: Not in recovery; listening for FTS updates +done +Validating Django models.py... +System check identified no issues (0 silenced). + +Django version 1.8 +Tornado server is running at http://localhost:9993/ +Quit the server with CTRL-C. +2016-05-04 18:20:40,716 INFO Tornado loaded 0 event queues in 0.001s +2016-05-04 18:20:40,722 INFO Tornado 95.5% busy over the past 0.0 seconds +Performing system checks... +``` +And ending with something similar to: + +``` +http://localhost:9994/webpack-dev-server/ +webpack result is served from http://localhost:9991/webpack/ +content is served from /srv/zulip + +webpack: bundle is now VALID. +2016-05-06 21:43:29,553 INFO Tornado 31.6% busy over the past 10.6 seconds +2016-05-06 21:43:35,007 INFO Tornado 23.9% busy over the past 16.0 seconds +``` + +Now the Zulip server should be running and accessible. Verify this by +navigating to [http://localhost:9991/](http://localhost:9991/) in your browser +on your main machine. + +You should see something like this: + +![Image of Zulip dev environment](/docs/images/zulip-dev.png) + +The Zulip server will continue to run and send output to the terminal window. +When you navigate to Zulip in your browser, check your terminal and you +should see something like: + +``` +2016-05-04 18:21:57,547 INFO 127.0.0.1 GET 302 582ms (+start: 417ms) / (unauth via ?) +[04/May/2016 18:21:57]"GET / HTTP/1.0" 302 0 +2016-05-04 18:21:57,568 INFO 127.0.0.1 GET 301 4ms /login (unauth via ?) +[04/May/2016 18:21:57]"GET /login HTTP/1.0" 301 0 +2016-05-04 18:21:57,819 INFO 127.0.0.1 GET 200 209ms (db: 7ms/2q) /login/ (unauth via ?) +``` + +Now you're ready for [Step 4: Developing.](#step-4-developing) + +### Step 4: Developing + +#### Where to edit files + +You'll work by editing files on your host machine, in the directory where you +cloned Zulip. Use your favorite editor (Sublime, Atom, Vim, Emacs, Notepad++, +etc.). + +When you save changes they will be synced automatically to the Zulip dev environment +on the virtual machine/container. + +The Zulip server will automatically restart itself when you make changes to +everything except [queue +workers](https://zulip.readthedocs.io/en/latest/queuing.html). So, to see your +changes, all you usually have to do is reload your browser. + +Don't forget to read through the [code style +guidelines](https://zulip.readthedocs.io/en/latest/code-style.html#general) for +details about how to configure your editor for Zulip. For example, indentation +should be set to 4 spaces rather than tabs. + +#### Understanding run-dev.py debugging output + +It's good to have the terminal running `run-dev.py` up as you work since error +messages including tracebacks along with every backend request will be printed +there. + +See [Logging](http://zulip.readthedocs.io/en/latest/logging.html) for +further details on the run-dev.py console output. + +#### Committing and pushing changes with git + +When you're ready to commit or push changes via git, you will do this by +running git commands in Terminal (OS X/Ubuntu) or Cygwin (Windows) in the directory +where you cloned Zulip on your main machine. + +If you're new to working with Git/Github, check out [this +guide](https://help.github.com/articles/create-a-repo/#commit-your-first-change). + +#### Maintaining the dev environment + +If after rebasing onto a new version of the Zulip server, you receive +new errors while starting the Zulip server or running tests, this is +probably not because Zulip's master branch is broken. Instead, this +is likely because we've recently merged changes to the development +environment provisioning process that you need to apply to your +development environmnet. To update your environment, you'll need to +re-provision your vagrant machine using `vagrant reload --provision` +(or just `python provision.py` from `/srv/zulip` inside the Vagrant +guest); this should be pretty fast and we're working to make it faster. + +See also the documentation on the [testing +page](http://zulip.readthedocs.io/en/latest/testing.html#manual-testing-local-app-web-browser) +for how to destroy and rebuild your database if you want to clear out test data. + +#### Rebuilding the dev environment + +If you ever want to recreate your development environment again from +scratch (e.g. to test as change you've made to the provisioning +process, or because you think something is broken), you can do so +using `vagrant destroy` and then `vagrant up`. This will usually be +much faster than the original `vagrant up` since the base image is +already cached on your machine (it takes about 5 minutes to run with a +fast Internet connection). + +#### Shutting down the dev environment for use later + +To shut down but preserve the dev environment so you can use it again +later use `vagrant halt` or `vagrant suspend`. + +You can do this from the same Terminal/Cygwin window that is running +run-dev.py by pressing ^C to halt the server and then typing `exit`. Or you +can halt vagrant from another Terminal/Cygwin window. + +From the window where run-dev.py is running: + +``` +2016-05-04 18:33:13,330 INFO 127.0.0.1 GET 200 92ms /register/ (unauth via ?) +^C +KeyboardInterrupt +(zulip-venv)vagrant@vagrant-ubuntu-trusty-64:/srv/zulip$ exit +logout +Connection to 127.0.0.1 closed. +christie@win10 ~/zulip +``` +Now you can suspend the dev environment: + +``` +christie@win10 ~/zulip +$ vagrant suspend +==> default: Saving VM state and suspending execution... +``` + +If `vagrant suspend` doesn't work, try `vagrant halt`: + +``` +christie@win10 ~/zulip +$ vagrant halt +==> default: Attempting graceful shutdown of VM... +``` + +Check out the Vagrant documentation to learn more about +[suspend](https://www.vagrantup.com/docs/cli/suspend.html) and +[halt](https://www.vagrantup.com/docs/cli/halt.html). + +#### Resuming the dev environment + +When you're ready to work on Zulip again, run `vagrant up`. You will also need +to connect to the virtual machine with `vagrant ssh` and re-start the Zulip +server: + +``` +christie@win10 ~/zulip +$ vagrant up +$ vagrant ssh +/srv/zulip/tools/run-dev.py --interface='' +``` + +#### Next Steps + +At this point you should [read about using the development +environment][using-dev]. + +### Troubleshooting & Common Errors + +#### The box 'ubuntu/trusty64' could not be found (Windows/Cygwin) + +If you see the following error when you run `vagrant up` on Windows: + +``` +The box 'ubuntu/trusty64' could not be found or +could not be accessed in the remote catalog. If this is a private +box on HashiCorp's Atlas, please verify you're logged in via +`vagrant login`. Also, please double-check the name. The expanded +URL and error message are shown below: +URL: ["https://atlas.hashicorp.com/ubuntu/trusty64"] +``` + +Then the version of curl that ships with Vagrant is not working on your +machine. The fix is simple: replace it with the version from Cygwin. + +First, determine the location of Cygwin's curl with `which curl`: + +``` +christie@win10 ~/zulip +$ which curl +/usr/bin/curl +``` +Now determine the location of Vagrant with `which vagrant`: +``` +christie@win10 ~/zulip +$ which vagrant +/cygdrive/c/HashiCorp/Vagrant/bin/vagrant +``` +The path **up until `/bin/vagrant`** is what you need to know. In the example above it's `/cygdrive/c/HashiCorp/Vagrant`. + +Finally, copy Cygwin's curl to Vagrant `embedded/bin` directory: +``` +christie@win10 ~/zulip +$ cp /usr/bin/curl.exe /cygdrive/c/HashiCorp/Vagrant/embedded/bin/ +``` + +Now re-run `vagrant up` and vagrant should be able to fetch the required +box file. + +#### os.symlink error + +If you receive the following error while running `vagrant up`: + +``` +==> default: Traceback (most recent call last): +==> default: File "./emoji_dump.py", line 75, in +==> default: +==> default: os.symlink('unicode/{}.png'.format(code_point), 'out/{}.png'.format(name)) +==> default: OSError +==> default: : +==> default: [Errno 71] Protocol error +``` + +Then Vagrant was not able to create a symbolic link. + +First, if you are using Windows, **make sure you have run Cygwin as an +administrator**. By default, only administrators can create symbolic links on +Windows. + +Second, VirtualBox does not enable symbolic links by default. Vagrant +starting with version 1.6.0 enables symbolic links for VirtualBox shared +folder. + +You can check to see that this is enabled for your virtual machine with +`vboxmanage` command. + +Get the name of your virtual machine by running `vboxmanage list vms` and +then print out the custom settings for this virtual machine with +`vboxmanage getextradata YOURVMNAME enumerate`: + +``` +christie@win10 ~/zulip +$ vboxmanage list vms +"zulip_default_1462498139595_55484" {5a65199d-8afa-4265-b2f6-6b1f162f157d} + +christie@win10 ~/zulip +$ vboxmanage getextradata zulip_default_1462498139595_55484 enumerate +Key: VBoxInternal2/SharedFoldersEnableSymlinksCreate/srv_zulip, Value: 1 +Key: supported, Value: false +``` + +If you see "command not found" when you try to run VBoxManage, you need to +add the VirtualBox directory to your path. On Windows this is mostly likely +`C:\Program Files\Oracle\VirtualBox\`. + +If `vboxmanage enumerate` prints nothing, or shows a value of 0 for +VBoxInternal2/SharedFoldersEnableSymlinksCreate/srv_zulip, then enable +symbolic links by running this command in Terminal/Cygwin: + +``` +vboxmanage setextradata YOURVMNAME VBoxInternal2/SharedFoldersEnableSymlinksCreate/srv_zulip 1 +``` + +The virtual machine needs to be shut down when you run this command. + +#### Connection timeout on `vagrant up` + +If you see the following error after running `vagrant up`: + +``` +default: SSH address: 127.0.0.1:2222 +default: SSH username: vagrant +default: SSH auth method: private key +default: Error: Connection timeout. Retrying... +default: Error: Connection timeout. Retrying... +default: Error: Connection timeout. Retrying... + +``` +A likely cause is that hardware virtualization is not enabled for your +computer. This must be done via your computer's BIOS settings. Look for a +setting called VT-x (Intel) or (AMD-V). + +If this is already enabled in your BIOS, double-check that you are running a +64-bit operating system. + +For further information about troubleshooting vagrant timeout errors [see +this post](http://stackoverflow.com/questions/22575261/vagrant-stuck-connection-timeout-retrying#22575302). + +#### npm install error + +The `provision.py` script may encounter an error related to `npm install` +that looks something like: + +``` +==> default: + npm install +==> default: Traceback (most recent call last): +==> default: File "/srv/zulip/provision.py", line 195, in +==> default: +==> default: sys.exit(main()) +==> default: File "/srv/zulip/provision.py", line 191, in main +==> default: +==> default: run(["npm", "install"]) +==> default: File "/srv/zulip/zulip_tools.py", line 78, in run +==> default: +==> default: raise subprocess.CalledProcessError(rc, args) +==> default: subprocess +==> default: . +==> default: CalledProcessError +==> default: : +==> default: Command '['npm', 'install']' returned non-zero exit status 34 +The SSH command responded with a non-zero exit status. Vagrant +assumes that this means the command failed. The output for this command +should be in the log above. Please read the output to determine what +went wrong. +``` + +Usually this error is not fatal. Try connecting to the dev environment and +re-trying the command from withing the virtual machine: + +``` +christie@win10 ~/zulip +$ vagrant ssh +(zulip-venv)vagrant@vagrant-ubuntu-trusty-64:~ +$ cd /srv/zulip +(zulip-venv)vagrant@vagrant-ubuntu-trusty-64:/srv/zulip +$ npm install +npm WARN optional Skipping failed optional dependency /chokidar/fsevents: +npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.12 +``` + +These are just warnings so it is okay to proceed and start the Zulip server. + +#### NoMethodError when installing vagrant-lxc plugin (Ubuntu 16.04) + +If you see the following error when you try to install the vagrant-lxc plugin: + +``` +/usr/lib/ruby/2.3.0/rubygems/specification.rb:946:in `all=': undefined method `group_by' for nil:NilClass (NoMethodError) + from /usr/lib/ruby/vendor_ruby/vagrant/bundler.rb:275:in `with_isolated_gem' + from /usr/lib/ruby/vendor_ruby/vagrant/bundler.rb:231:in `internal_install' + from /usr/lib/ruby/vendor_ruby/vagrant/bundler.rb:102:in `install' + from /usr/lib/ruby/vendor_ruby/vagrant/plugin/manager.rb:62:in `block in install_plugin' + from /usr/lib/ruby/vendor_ruby/vagrant/plugin/manager.rb:72:in `install_plugin' + from /usr/share/vagrant/plugins/commands/plugin/action/install_gem.rb:37:in `call' + from /usr/lib/ruby/vendor_ruby/vagrant/action/warden.rb:34:in `call' + from /usr/lib/ruby/vendor_ruby/vagrant/action/builder.rb:116:in `call' + from /usr/lib/ruby/vendor_ruby/vagrant/action/runner.rb:66:in `block in run' + from /usr/lib/ruby/vendor_ruby/vagrant/util/busy.rb:19:in `busy' + from /usr/lib/ruby/vendor_ruby/vagrant/action/runner.rb:66:in `run' + from /usr/share/vagrant/plugins/commands/plugin/command/base.rb:14:in `action' + from /usr/share/vagrant/plugins/commands/plugin/command/install.rb:32:in `block in execute' + from /usr/share/vagrant/plugins/commands/plugin/command/install.rb:31:in `each' + from /usr/share/vagrant/plugins/commands/plugin/command/install.rb:31:in `execute' + from /usr/share/vagrant/plugins/commands/plugin/command/root.rb:56:in `execute' + from /usr/lib/ruby/vendor_ruby/vagrant/cli.rb:42:in `execute' + from /usr/lib/ruby/vendor_ruby/vagrant/environment.rb:268:in `cli' + from /usr/bin/vagrant:173:in `
' +``` + +And you have vagrant version 1.8.1, then you need to patch vagrant manually. +See [this post](https://github.com/mitchellh/vagrant/issues/7073) for an +explanation of the issue, which should be fixed when Vagrant 1.8.2 is released. + +In the meantime, read [this +post](http://stackoverflow.com/questions/36811863/cant-install-vagrant-plugins-in-ubuntu-16-04/36991648#36991648) +for how to create and apply the patch. + +It will look something like this: + +``` +christie@xenial:~ +$ sudo patch --directory /usr/lib/ruby/vendor_ruby/vagrant < vagrant-plugin.patch +patching file bundler.rb +``` + +#### Permissions errors when running the test suite in LXC + +When building the development environment using Vagrant and the LXC provider, +if you encounter permissions errors, you may need to `chown -R 1000:$(whoami) +/path/to/zulip` on the host before running `vagrant up` in order to ensure that +the synced directory has the correct owner during provision. This issue will +arise if you run `id username` on the host where `username` is the user running +Vagrant and the output is anything but 1000. + +This seems to be caused by Vagrant behavior; for more information, see [the +vagrant-lxc FAQ entry about shared folder permissions ][lxc-sf]. + +Brief installation instructions for Vagrant development environment +------------- Start by cloning this repository: `git clone https://github.com/zulip/zulip.git` -Using Vagrant -------------- - This is the recommended approach for all platforms, and will install the Zulip development environment inside a VM or container and works on any platform that supports Vagrant. @@ -67,11 +794,9 @@ will be much faster. Once that finishes, you can run the development server as follows: ``` -vagrant ssh -- -L9991:localhost:9991 +vagrant ssh # Now inside the container -cd /srv/zulip -source /srv/zulip-venv/bin/activate -./tools/run-dev.py --interface='' +/srv/zulip/tools/run-dev.py --interface='' ``` To get shell access to the virtual machine running the server to run @@ -88,7 +813,7 @@ environment][using-dev]. [using-dev]: #using-the-development-environment -## Specifying a proxy +### Specifying a proxy If you need to use a proxy server to access the Internet, you will need to specify the proxy settings before running `Vagrant up`. @@ -112,8 +837,10 @@ Now run `vagrant up` in your terminal to install the development server. If you ran `vagrant up` before and failed, you'll need to run `vagrant destroy` first to clean up the failed installation. -Using provision.py without Vagrant +Installing on Ubuntu 14.04 Trusty without Vagrant ---------------------------------- +Start by cloning this repository: `git clone +https://github.com/zulip/zulip.git` If you'd like to install a Zulip development environment on a server that's already running Ubuntu 14.04 Trusty, you can do that by just @@ -132,10 +859,18 @@ Note that there is no supported uninstallation process without Vagrant (with Vagrant, you can just do `vagrant destroy` to clean up the development environment). -By hand +Installing manually on UNIX-based platforms ------- -If you really want to install everything by hand, the below -instructions should work. + +* [Debian or Ubuntu systems](#on-debian-or-ubuntu-systems) +* [Fedora 22 (experimental)](#on-fedora-22-experimental) +* [CentOS 7 Core (experimental)](#on-centos-7-core-experimental) +* [OpenBSD 5.8 (experimental)](#on-openbsd-58-experimental) +* [Fedora/CentOS](#common-to-fedoracentos-instructions) +* [Steps for all systems](#all-systems) + +If you really want to install everything manually, the below instructions +should work. Install the following non-Python dependencies: * libffi-dev — needed for some Python extensions @@ -151,7 +886,10 @@ Install the following non-Python dependencies: ### On Debian or Ubuntu systems: -* Using the official Ubuntu repositories and `tsearch-extras` deb package: +#### Using the official Ubuntu repositories and `tsearch-extras` deb package: + +Start by cloning this repository: `git clone +https://github.com/zulip/zulip.git` ``` sudo apt-get install closure-compiler libfreetype6-dev libffi-dev \ @@ -176,7 +914,12 @@ wget https://dl.dropboxusercontent.com/u/283158365/zuliposs/postgresql-9.4-tsear sudo dpkg -i postgresql-9.4-tsearch-extras_0.1_amd64.deb ``` -* Using the [official Zulip PPA](https://launchpad.net/~tabbott/+archive/ubuntu/zulip/+packages) (for 14.04 Trusty): +Now continue with the [All Systems](#all-systems) instructions below. + +#### Using the [official Zulip PPA](https://launchpad.net/~tabbott/+archive/ubuntu/zulip/+packages) (for 14.04 Trusty): + +Start by cloning this repository: `git clone +https://github.com/zulip/zulip.git` ``` sudo add-apt-repository ppa:tabbott/zulip @@ -188,13 +931,16 @@ sudo apt-get install closure-compiler libfreetype6-dev libffi-dev \ puppet gettext tsearch-extras ``` -Now continue with the "All systems" instructions below. +Now continue with the [All Systems](#all-systems) instructions below. ### On Fedora 22 (experimental): These instructions are experimental and may have bugs; patches welcome! +Start by cloning this repository: `git clone +https://github.com/zulip/zulip.git` + ``` sudo dnf install libffi-devel memcached rabbitmq-server \ openldap-devel python-devel redis postgresql-server \ @@ -202,13 +948,16 @@ sudo dnf install libffi-devel memcached rabbitmq-server \ nodejs npm yuicompressor closure-compiler gettext ``` -Now continue with the Common to Fedora/CentOS instructions below. +Finally continue with the [All Systems](#all-systems) instructions below. ### On CentOS 7 Core (experimental): These instructions are experimental and may have bugs; patches welcome! +Start by cloning this repository: `git clone +https://github.com/zulip/zulip.git` + ``` # Add user zulip to the system (not necessary if you configured zulip # as the administrator user during the install process of CentOS 7). @@ -257,13 +1006,16 @@ host all all 127.0.0.1/32 md5 host all all ::1/128 md5 ``` -Now continue with the Common to Fedora/CentOS instructions below. +Now continue with the [Common to Fedora/CentOS](#common-to-fedoracentos-instructions) instructions below. ### On OpenBSD 5.8 (experimental): These instructions are experimental and may have bugs; patches welcome! +Start by cloning this repository: `git clone +https://github.com/zulip/zulip.git` + ``` doas pkg_add sudo bash gcc postgresql-server redis rabbitmq \ memcached node libmemcached py-Pillow py-cryptography py-cffi @@ -291,10 +1043,13 @@ sudo touch /usr/local/share/postgresql/tsearch_data/en_us.dict sudo touch /usr/local/share/postgresql/tsearch_data/en_us.affix ``` -Now continue with the All Systems instructions below. +Finally continue with the [All Systems](#all-systems) instructions below. ### Common to Fedora/CentOS instructions +Start by cloning this repository: `git clone +https://github.com/zulip/zulip.git` + ``` # Build and install postgres tsearch-extras module wget https://launchpad.net/~tabbott/+archive/ubuntu/zulip/+files/tsearch-extras_0.1.3.tar.gz @@ -324,10 +1079,20 @@ sudo systemctl start redis memcached rabbitmq-server postgresql sudo systemctl enable redis rabbitmq-server memcached postgresql ``` -Finally continue with the All Systems instructions below. +Finally continue with the [All Systems](#all-systems) instructions below. ### All Systems: +Make sure you have followed the steps specific for your platform: + +* [Debian or Ubuntu systems](#on-debian-or-ubuntu-systems) +* [Fedora 22 (experimental)](#on-fedora-22-experimental) +* [CentOS 7 Core (experimental)](#on-centos-7-core-experimental) +* [OpenBSD 5.8 (experimental)](#on-openbsd-58-experimental) +* [Fedora/CentOS](#common-to-fedoracentos-instructions) + +And then do the following steps that are common to all platforms: + ``` pip install --no-deps -r requirements.txt ./tools/setup/install-phantomjs @@ -377,6 +1142,8 @@ proxy in the environment as follows: Using Docker (experimental) --------------------------- +Start by cloning this repository: `git clone +https://github.com/zulip/zulip.git` The docker instructions for development are experimental, so they may have bugs. If you try them and run into any issues, please report diff --git a/docs/images/zulip-dev.png b/docs/images/zulip-dev.png new file mode 100644 index 0000000000000000000000000000000000000000..5260c596f74c87f156916e8487356c48534eecea GIT binary patch literal 67657 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 UUlh~uUI0Jh!ZJdI0=i%SFG)1AfdBvi literal 0 HcmV?d00001 diff --git a/docs/index.rst b/docs/index.rst index 38d1acf139..1911beb850 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,6 +16,7 @@ Contents: directory-structure code-style testing + logging markdown queuing schema-migrations diff --git a/docs/logging.md b/docs/logging.md new file mode 100644 index 0000000000..2bab392032 --- /dev/null +++ b/docs/logging.md @@ -0,0 +1,24 @@ +# Logging and Performance Debugging + +It's good to have the terminal running `run-dev.py` up as you work since error +messages including tracebacks along with every backend request will be printed +there. + +The messages will look similar to: + +``` +2016-05-20 14:50:22,056 INFO 127.0.0.1 GET 302 528ms (db: 1ms/1q) (+start: 123ms) / (unauth via ?) +[20/May/2016 14:50:22]"GET / HTTP/1.0" 302 0 +2016-05-20 14:50:22,272 INFO 127.0.0.1 GET 200 124ms (db: 3ms/2q) /login/ (unauth via ?) +2016-05-20 14:50:26,333 INFO 127.0.0.1 POST 302 37ms (db: 6ms/7q) /accounts/login/local/ (unauth via ?) +[20/May/2016 14:50:26]"POST /accounts/login/local/ HTTP/1.0" 302 0 +2016-05-20 14:50:26,538 INFO 127.0.0.1 GET 200 12ms (db: 1ms/2q) (+start: 53ms) /api/v1/events [1463769771:0/0] (cordelia@zulip.com via internal) +2016-05-20 14:50:26,657 INFO 127.0.0.1 GET 200 10ms (+start: 8ms) /api/v1/events [1463769771:0/0] (cordelia@zulip.com via internal) +2016-05-20 14:50:26,959 INFO 127.0.0.1 GET 200 588ms (db: 26ms/21q) / [1463769771:0] (cordelia@zulip.com via website) +``` + +The format of this output is: timestamp, loglevel, IP, HTTP Method, HTTP status +code, time to process, (optional perf data details, e.g. database time/queries, +memcached time/queries, Django process startup time, markdown processing time, +etc.), URL, and "email via client" showing user account involved (if logged in) +and the type of client they used ("web", "Android", etc.).