mirror of https://github.com/zulip/zulip.git
docs: Rewrap to avoid line breaks in inline code spans.
This works around https://github.com/prettier/prettier/issues/11372. Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
a6e01b35fc
commit
6145fdf678
|
@ -168,8 +168,8 @@ cause time-related bugs that are hard to catch with a test suite, or bugs
|
||||||
that only show up during daylight savings time.
|
that only show up during daylight savings time.
|
||||||
|
|
||||||
Good ways to make timezone-aware datetimes are below. We import timezone
|
Good ways to make timezone-aware datetimes are below. We import timezone
|
||||||
libraries as `from datetime import datetime, timezone` and `from
|
libraries as `from datetime import datetime, timezone` and
|
||||||
django.utils.timezone import now as timezone_now`.
|
`from django.utils.timezone import now as timezone_now`.
|
||||||
|
|
||||||
Use:
|
Use:
|
||||||
* `timezone_now()` to get a datetime when Django is available, such as
|
* `timezone_now()` to get a datetime when Django is available, such as
|
||||||
|
@ -241,10 +241,8 @@ generally use modern
|
||||||
[ECMAScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Language_Resources)
|
[ECMAScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Language_Resources)
|
||||||
primitives such as [`for … of`
|
primitives such as [`for … of`
|
||||||
loops](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of),
|
loops](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of),
|
||||||
[`Array.prototype.{entries, every, filter, find, indexOf, map,
|
[`Array.prototype.{entries, every, filter, find, indexOf, map, some}`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array),
|
||||||
some}`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array),
|
[`Object.{assign, entries, keys, values}`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object),
|
||||||
[`Object.{assign, entries, keys,
|
|
||||||
values}`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object),
|
|
||||||
[spread
|
[spread
|
||||||
syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax),
|
syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax),
|
||||||
and so on. Our Babel configuration automatically transpiles and
|
and so on. Our Babel configuration automatically transpiles and
|
||||||
|
@ -266,8 +264,8 @@ code a lot uglier, in which case it's fine to go up to 120 or so.
|
||||||
|
|
||||||
Our JavaScript and TypeScript code is formatted with
|
Our JavaScript and TypeScript code is formatted with
|
||||||
[Prettier](https://prettier.io/). You can ask Prettier to reformat
|
[Prettier](https://prettier.io/). You can ask Prettier to reformat
|
||||||
all code via our [linter tool](../testing/linters.md) with `tools/lint
|
all code via our [linter tool](../testing/linters.md) with
|
||||||
--only=prettier --fix`. You can also [integrate it with your
|
`tools/lint --only=prettier --fix`. You can also [integrate it with your
|
||||||
editor](https://prettier.io/docs/en/editors.html).
|
editor](https://prettier.io/docs/en/editors.html).
|
||||||
|
|
||||||
Combine adjacent on-ready functions, if they are logically related.
|
Combine adjacent on-ready functions, if they are logically related.
|
||||||
|
@ -328,8 +326,9 @@ type changes in the future.
|
||||||
[Black](https://github.com/psf/black) and
|
[Black](https://github.com/psf/black) and
|
||||||
[isort](https://pycqa.github.io/isort/). The [linter
|
[isort](https://pycqa.github.io/isort/). The [linter
|
||||||
tool](../testing/linters.md) enforces this by running Black and
|
tool](../testing/linters.md) enforces this by running Black and
|
||||||
isort in check mode, or in write mode with `tools/lint
|
isort in check mode, or in write mode with
|
||||||
--only=black,isort --fix`. You may find it helpful to [integrate
|
`tools/lint --only=black,isort --fix`. You may find it helpful to
|
||||||
|
[integrate
|
||||||
Black](https://black.readthedocs.io/en/stable/editor_integration.html)
|
Black](https://black.readthedocs.io/en/stable/editor_integration.html)
|
||||||
and
|
and
|
||||||
[isort](https://pycqa.github.io/isort/#installing-isorts-for-your-preferred-text-editor)
|
[isort](https://pycqa.github.io/isort/#installing-isorts-for-your-preferred-text-editor)
|
||||||
|
|
|
@ -36,11 +36,12 @@ details worth understanding:
|
||||||
which shows all emails that the Zulip server has "sent" (emails are
|
which shows all emails that the Zulip server has "sent" (emails are
|
||||||
not actually sent by the development environment), to make it
|
not actually sent by the development environment), to make it
|
||||||
convenient to click through the UI of signup, password reset, etc.
|
convenient to click through the UI of signup, password reset, etc.
|
||||||
* There's a management command, `manage.py print_initial_password
|
* There's a management command,
|
||||||
username@example.com`, that prints out **default** passwords for the
|
`manage.py print_initial_password username@example.com`, that prints
|
||||||
development environment users. Note that if you change a user's
|
out **default** passwords for the development environment users.
|
||||||
password in the development environment, those passwords will no longer
|
Note that if you change a user's password in the development
|
||||||
work. It also prints out the user's **current** API key.
|
environment, those passwords will no longer work. It also prints
|
||||||
|
out the user's **current** API key.
|
||||||
|
|
||||||
### Google
|
### Google
|
||||||
|
|
||||||
|
|
|
@ -37,14 +37,14 @@ to the next section.
|
||||||
|
|
||||||
You can create a new user with sudo privileges by running the
|
You can create a new user with sudo privileges by running the
|
||||||
following commands as root:
|
following commands as root:
|
||||||
* You can create a `zulipdev` user by running the command `adduser
|
* You can create a `zulipdev` user by running the command
|
||||||
zulipdev`. Run through the prompts to assign a password and user
|
`adduser zulipdev`. Run through the prompts to assign a password and
|
||||||
information. (You can pick any username you like for this user
|
user information. (You can pick any username you like for this user
|
||||||
account.)
|
account.)
|
||||||
* You can add the user to the sudo group by running the command
|
* You can add the user to the sudo group by running the command
|
||||||
`usermod -aG sudo zulipdev`.
|
`usermod -aG sudo zulipdev`.
|
||||||
* Finally, you can switch to the user by running the command `su -
|
* Finally, you can switch to the user by running the command
|
||||||
zulipdev` (or just log in to that user using `ssh`).
|
`su - zulipdev` (or just log in to that user using `ssh`).
|
||||||
|
|
||||||
## Setting up the development environment
|
## Setting up the development environment
|
||||||
|
|
||||||
|
@ -311,9 +311,9 @@ different.
|
||||||
service nginx reload # Actually enabled your nginx configuration
|
service nginx reload # Actually enabled your nginx configuration
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Edit `zproject/dev_settings.py` to set `EXTERNAL_URI_SCHEME =
|
1. Edit `zproject/dev_settings.py` to set
|
||||||
"https://"`, so that URLs served by the development environment
|
`EXTERNAL_URI_SCHEME = "https://"`, so that URLs served by the
|
||||||
will be HTTPS.
|
development environment will be HTTPS.
|
||||||
|
|
||||||
1. Start the Zulip development environment with the following command:
|
1. Start the Zulip development environment with the following command:
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -251,10 +251,10 @@ expected.
|
||||||
1. If you get the error `Hyper-V could not initialize memory`, this is
|
1. If you get the error `Hyper-V could not initialize memory`, this is
|
||||||
likely because your system has insufficient free memory to start
|
likely because your system has insufficient free memory to start
|
||||||
the virtual machine. You can generally work around this error by
|
the virtual machine. You can generally work around this error by
|
||||||
closing all other running programs and running `vagrant up
|
closing all other running programs and running
|
||||||
--provider=hyperv` again. You can reopen the other programs after
|
`vagrant up --provider=hyperv` again. You can reopen the other
|
||||||
the provisioning is completed. If it still isn't enough, try
|
programs after the provisioning is completed. If it still isn't
|
||||||
restarting your system and running the command again.
|
enough, try restarting your system and running the command again.
|
||||||
|
|
||||||
2. Be patient the first time you run `./tools/run-dev.py`.
|
2. Be patient the first time you run `./tools/run-dev.py`.
|
||||||
|
|
||||||
|
@ -295,13 +295,14 @@ you can sign up [here](https://aws.amazon.com/cloud9/).
|
||||||
* Resize the workspace to be 1GB of memory and 4GB of disk
|
* Resize the workspace to be 1GB of memory and 4GB of disk
|
||||||
space. (This is under free limit for both the old Cloud9 and the AWS
|
space. (This is under free limit for both the old Cloud9 and the AWS
|
||||||
Free Tier).
|
Free Tier).
|
||||||
* Clone the zulip repo: `git clone --config pull.rebase
|
* Clone the zulip repo:
|
||||||
https://github.com/<your-username>/zulip.git`
|
`git clone --config pull.rebase https://github.com/<your-username>/zulip.git`
|
||||||
* Restart rabbitmq-server since its broken on Cloud9: `sudo service
|
* Restart rabbitmq-server since its broken on Cloud9:
|
||||||
rabbitmq-server restart`.
|
`sudo service rabbitmq-server restart`.
|
||||||
* And run provision `cd zulip && ./tools/provision`, once this is done.
|
* And run provision `cd zulip && ./tools/provision`, once this is done.
|
||||||
* Activate the Zulip virtual environment by `source
|
* Activate the Zulip virtual environment by
|
||||||
/srv/zulip-py3-venv/bin/activate` or by opening a new terminal.
|
`source /srv/zulip-py3-venv/bin/activate` or by opening a new
|
||||||
|
terminal.
|
||||||
|
|
||||||
#### Install zulip-cloud9
|
#### Install zulip-cloud9
|
||||||
|
|
||||||
|
|
|
@ -321,8 +321,9 @@ section. If that doesn't help, please visit
|
||||||
in the [Zulip development community server](https://zulip.com/developer-community/) for
|
in the [Zulip development community server](https://zulip.com/developer-community/) for
|
||||||
real-time help.
|
real-time help.
|
||||||
|
|
||||||
On Windows, you will see the message `The system cannot find the path
|
On Windows, you will see the message
|
||||||
specified.` several times. This is normal and is not a problem.
|
`The system cannot find the path specified.` several times. This is
|
||||||
|
normal and is not a problem.
|
||||||
|
|
||||||
Once `vagrant up` has completed, connect to the development
|
Once `vagrant up` has completed, connect to the development
|
||||||
environment with `vagrant ssh`:
|
environment with `vagrant ssh`:
|
||||||
|
@ -804,11 +805,11 @@ The `vagrant up` command basically does the following:
|
||||||
|
|
||||||
To debug such errors, you can log in to the Vagrant guest machine by
|
To debug such errors, you can log in to the Vagrant guest machine by
|
||||||
running `vagrant ssh`, which should present you with a standard shell
|
running `vagrant ssh`, which should present you with a standard shell
|
||||||
prompt. You can debug interactively by using e.g. `cd zulip &&
|
prompt. You can debug interactively by using e.g.
|
||||||
./tools/provision`, and then running the individual subcommands
|
`cd zulip && ./tools/provision`, and then running the individual
|
||||||
that failed. Once you've resolved the problem, you can rerun
|
subcommands that failed. Once you've resolved the problem, you can
|
||||||
`tools/provision` to proceed; the provisioning system is designed
|
rerun `tools/provision` to proceed; the provisioning system is
|
||||||
to recover well from failures.
|
designed to recover well from failures.
|
||||||
|
|
||||||
The Zulip provisioning system is generally highly reliable; the most common
|
The Zulip provisioning system is generally highly reliable; the most common
|
||||||
cause of issues here is a poor network connection (or one where you need a
|
cause of issues here is a poor network connection (or one where you need a
|
||||||
|
@ -883,9 +884,10 @@ enabled in your BIOS.
|
||||||
|
|
||||||
If the error persists, you may have run into an incompatibility
|
If the error persists, you may have run into an incompatibility
|
||||||
between VirtualBox and Hyper-V on Windows. To disable Hyper-V, open
|
between VirtualBox and Hyper-V on Windows. To disable Hyper-V, open
|
||||||
command prompt as administrator, run `bcdedit /set
|
command prompt as administrator, run
|
||||||
hypervisorlaunchtype off`, and reboot. If you need to enable it
|
`bcdedit /set hypervisorlaunchtype off`, and reboot. If you need to
|
||||||
later, run `bcdedit /deletevalue hypervisorlaunchtype`, and reboot.
|
enable it later, run `bcdedit /deletevalue hypervisorlaunchtype`, and
|
||||||
|
reboot.
|
||||||
|
|
||||||
#### OSError: [Errno 26] Text file busy
|
#### OSError: [Errno 26] Text file busy
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,10 @@ the development environment][authentication-dev-server].
|
||||||
## Common
|
## Common
|
||||||
|
|
||||||
* Zulip's `main` branch moves quickly, and you should rebase
|
* Zulip's `main` branch moves quickly, and you should rebase
|
||||||
constantly with e.g. `git fetch upstream; git rebase
|
constantly with e.g.
|
||||||
upstream/main` to avoid developing on an old version of the Zulip
|
`git fetch upstream; git rebase upstream/main` to avoid developing
|
||||||
codebase (leading to unnecessary merge conflicts).
|
on an old version of the Zulip codebase (leading to unnecessary
|
||||||
|
merge conflicts).
|
||||||
* Remember to run `tools/provision` to update your development
|
* Remember to run `tools/provision` to update your development
|
||||||
environment after switching branches; it will run in under a second
|
environment after switching branches; it will run in under a second
|
||||||
if no changes are required.
|
if no changes are required.
|
||||||
|
@ -55,8 +56,8 @@ the development environment][authentication-dev-server].
|
||||||
console output, which will show tracebacks for any 500 errors your
|
console output, which will show tracebacks for any 500 errors your
|
||||||
Zulip development server encounters (which are probably caused by
|
Zulip development server encounters (which are probably caused by
|
||||||
bugs in your code).
|
bugs in your code).
|
||||||
* To manually query Zulip's database interactively, use `./manage.py
|
* To manually query Zulip's database interactively, use
|
||||||
shell` or `manage.py dbshell`.
|
`./manage.py shell` or `manage.py dbshell`.
|
||||||
* The database(s) used for the automated tests are independent from
|
* The database(s) used for the automated tests are independent from
|
||||||
the one you use for manual testing in the UI, so changes you make to
|
the one you use for manual testing in the UI, so changes you make to
|
||||||
the database manually will never affect the automated tests.
|
the database manually will never affect the automated tests.
|
||||||
|
|
|
@ -141,20 +141,20 @@ base class `icon-vector` and have dropped support for it. We now only support
|
||||||
icons from [FontAwesome](https://fontawesome.com/v4.7.0/) (version 4.7.0) which
|
icons from [FontAwesome](https://fontawesome.com/v4.7.0/) (version 4.7.0) which
|
||||||
make use of `fa` as a base class.
|
make use of `fa` as a base class.
|
||||||
|
|
||||||
* cog (<i class="fa fa-cog"></i>) icon — `cog (<i
|
* cog (<i class="fa fa-cog"></i>) icon —
|
||||||
class="fa fa-cog"></i>) icon`
|
`cog (<i class="fa fa-cog"></i>) icon`
|
||||||
* down chevron (<i class="fa fa-chevron-down"></i>) icon —
|
* down chevron (<i class="fa fa-chevron-down"></i>) icon —
|
||||||
`down chevron (<i class="fa fa-chevron-down"></i>) icon`
|
`down chevron (<i class="fa fa-chevron-down"></i>) icon`
|
||||||
* eye (<i class="fa fa-eye"></i>) icon — `eye (<i
|
* eye (<i class="fa fa-eye"></i>) icon —
|
||||||
class="fa fa-eye"></i>) icon`
|
`eye (<i class="fa fa-eye"></i>) icon`
|
||||||
* file (<i class="fa fa-file-code-o"></i>) icon — `file (<i
|
* file (<i class="fa fa-file-code-o"></i>) icon —
|
||||||
class="fa fa-file-code-o"></i>) icon`
|
`file (<i class="fa fa-file-code-o"></i>) icon`
|
||||||
* filled star (<i class="fa fa-star"></i>) icon —
|
* filled star (<i class="fa fa-star"></i>) icon —
|
||||||
`filled star (<i class="fa fa-star"></i>) icon`
|
`filled star (<i class="fa fa-star"></i>) icon`
|
||||||
* formatting (<i class="fa fa-font"></i>) icon —
|
* formatting (<i class="fa fa-font"></i>) icon —
|
||||||
`formatting (<i class="fa fa-font"></i>) icon`
|
`formatting (<i class="fa fa-font"></i>) icon`
|
||||||
* menu (<i class="fa fa-bars"></i>) icon — `menu (<i
|
* menu (<i class="fa fa-bars"></i>) icon —
|
||||||
class="fa fa-bars"></i>) icon`
|
`menu (<i class="fa fa-bars"></i>) icon`
|
||||||
* overflow ( <i class="fa fa-ellipsis-v"></i> ) icon —
|
* overflow ( <i class="fa fa-ellipsis-v"></i> ) icon —
|
||||||
`overflow ( <i class="fa fa-ellipsis-v"></i> ) icon`
|
`overflow ( <i class="fa fa-ellipsis-v"></i> ) icon`
|
||||||
* paperclip (<i class="fa fa-paperclip"></i>) icon —
|
* paperclip (<i class="fa fa-paperclip"></i>) icon —
|
||||||
|
|
|
@ -32,12 +32,12 @@ Checking connectivity... done.
|
||||||
```
|
```
|
||||||
|
|
||||||
(The `--config pull.rebase` option configures Git so that `git pull`
|
(The `--config pull.rebase` option configures Git so that `git pull`
|
||||||
will behave like `git pull --rebase` by default. Using `git pull
|
will behave like `git pull --rebase` by default. Using
|
||||||
--rebase` to update your changes to resolve merge conflicts is
|
`git pull --rebase` to update your changes to resolve merge conflicts
|
||||||
expected by essentially all of open source projects, including Zulip.
|
is expected by essentially all of open source projects, including
|
||||||
You can also set that option after cloning using `git config --add
|
Zulip. You can also set that option after cloning using
|
||||||
pull.rebase true`, or just be careful to always run `git pull
|
`git config --add pull.rebase true`, or just be careful to always run
|
||||||
--rebase`, never `git pull`).
|
`git pull --rebase`, never `git pull`).
|
||||||
|
|
||||||
Note: If you receive an error while cloning, you may not have [added your ssh
|
Note: If you receive an error while cloning, you may not have [added your ssh
|
||||||
key to GitHub][github-help-add-ssh-key].
|
key to GitHub][github-help-add-ssh-key].
|
||||||
|
@ -65,8 +65,8 @@ origin git@github.com:YOUR_USERNAME/zulip.git (push)
|
||||||
Note: If you've cloned the repository using a graphical client, you may already
|
Note: If you've cloned the repository using a graphical client, you may already
|
||||||
have the upstream remote repository configured. For example, when you clone
|
have the upstream remote repository configured. For example, when you clone
|
||||||
[zulip/zulip][github-zulip-zulip] with the GitHub desktop client it configures
|
[zulip/zulip][github-zulip-zulip] with the GitHub desktop client it configures
|
||||||
the remote repository `zulip` and you see the following output from `git remote
|
the remote repository `zulip` and you see the following output from
|
||||||
-v`:
|
`git remote -v`:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
origin git@github.com:YOUR_USERNAME/zulip.git (fetch)
|
origin git@github.com:YOUR_USERNAME/zulip.git (fetch)
|
||||||
|
|
|
@ -129,9 +129,9 @@ $ git log
|
||||||
* 13bea0e (HEAD -> main) test commit for docs.
|
* 13bea0e (HEAD -> main) test commit for docs.
|
||||||
```
|
```
|
||||||
|
|
||||||
And then realize you actually needed to keep commit 67aea58. First, use `git
|
And then realize you actually needed to keep commit 67aea58. First, use
|
||||||
reflog` to confirm that commit you want to restore and then run `git
|
`git reflog` to confirm that commit you want to restore and then run
|
||||||
cherry-pick <commit>`:
|
`git cherry-pick <commit>`:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ git reflog
|
$ git reflog
|
||||||
|
|
|
@ -46,9 +46,9 @@ from Zulip's main repositories.
|
||||||
|
|
||||||
**Note about git pull**: You might be used to using `git pull` on other
|
**Note about git pull**: You might be used to using `git pull` on other
|
||||||
projects. With Zulip, because we don't use merge commits, you'll want to avoid
|
projects. With Zulip, because we don't use merge commits, you'll want to avoid
|
||||||
it. Rather than using `git pull`, which by default is a shortcut for `git fetch
|
it. Rather than using `git pull`, which by default is a shortcut for
|
||||||
&& git merge FETCH_HEAD` ([docs][gitbook-git-pull]), you should use `git fetch`
|
`git fetch && git merge FETCH_HEAD` ([docs][gitbook-git-pull]), you
|
||||||
and then `git rebase`.
|
should use `git fetch` and then `git rebase`.
|
||||||
|
|
||||||
First, [fetch][gitbook-fetch] changes from Zulip's upstream repository you
|
First, [fetch][gitbook-fetch] changes from Zulip's upstream repository you
|
||||||
configured in the step above:
|
configured in the step above:
|
||||||
|
@ -166,9 +166,10 @@ nothing added to commit but untracked files present (use "git add" to track)
|
||||||
|
|
||||||
### Stage additions with git add
|
### Stage additions with git add
|
||||||
|
|
||||||
To add changes to your staging area, use `git add <filename>`. Because `git
|
To add changes to your staging area, use `git add <filename>`. Because
|
||||||
add` is all about staging the changes you want to commit, you use it to add
|
`git add` is all about staging the changes you want to commit, you use
|
||||||
*new files* as well as *files with changes* to your staging area.
|
it to add *new files* as well as *files with changes* to your staging
|
||||||
|
area.
|
||||||
|
|
||||||
Continuing our example from above, after we run `git add newfile.py`, we'll see
|
Continuing our example from above, after we run `git add newfile.py`, we'll see
|
||||||
the following from `git status`:
|
the following from `git status`:
|
||||||
|
|
|
@ -45,6 +45,6 @@ working copies:
|
||||||
- `git remote`: This helps you configure short names for remotes.
|
- `git remote`: This helps you configure short names for remotes.
|
||||||
- `git pull`: This pulls code, but by default creates a merge commit
|
- `git pull`: This pulls code, but by default creates a merge commit
|
||||||
(which you definitely don't want). However, if you've followed our
|
(which you definitely don't want). However, if you've followed our
|
||||||
[cloning documentation](../git/cloning.md), this will do `git pull
|
[cloning documentation](../git/cloning.md), this will do
|
||||||
--rebase` instead, which is the only mode you'll want to use when
|
`git pull --rebase` instead, which is the only mode you'll want to
|
||||||
working on Zulip.
|
use when working on Zulip.
|
||||||
|
|
|
@ -405,8 +405,9 @@ log][commit-log] for an up-to-date list of raw changes.
|
||||||
- Fixed Postfix configuration error which would prevent outgoing email
|
- Fixed Postfix configuration error which would prevent outgoing email
|
||||||
to any email address containing `.`, `+`, or starting with `mm`, when
|
to any email address containing `.`, `+`, or starting with `mm`, when
|
||||||
configured to use the local Postfix to deliver outgoing email.
|
configured to use the local Postfix to deliver outgoing email.
|
||||||
- Fixed a backporting error which caused the `manage.py
|
- Fixed a backporting error which caused the
|
||||||
change_user_role` tool to not work for `admin`, `member`, or `guest` roles.
|
`manage.py change_user_role` tool to not work for `admin`, `member`,
|
||||||
|
or `guest` roles.
|
||||||
- Add support for logout events sent from modern versions of the
|
- Add support for logout events sent from modern versions of the
|
||||||
desktop application.
|
desktop application.
|
||||||
- Upgraded minor python dependencies.
|
- Upgraded minor python dependencies.
|
||||||
|
@ -545,8 +546,8 @@ log][commit-log] for an up-to-date list of raw changes.
|
||||||
[our new PostgreSQL upgrade guide][postgresql-upgrade].
|
[our new PostgreSQL upgrade guide][postgresql-upgrade].
|
||||||
- The format of the `JWT_AUTH_KEYS` setting has changed to include an
|
- The format of the `JWT_AUTH_KEYS` setting has changed to include an
|
||||||
[algorithms](https://pyjwt.readthedocs.io/en/latest/algorithms.html)
|
[algorithms](https://pyjwt.readthedocs.io/en/latest/algorithms.html)
|
||||||
list: `{"subdomain": "key"}` becomes `{"subdomain": {"key": "key",
|
list: `{"subdomain": "key"}` becomes
|
||||||
"algorithms": ["HS256"]}}`.
|
`{"subdomain": {"key": "key", "algorithms": ["HS256"]}}`.
|
||||||
- Added a new organization owner permission above the previous
|
- Added a new organization owner permission above the previous
|
||||||
organization administrator. All existing organization
|
organization administrator. All existing organization
|
||||||
administrators are automatically converted into organization owners.
|
administrators are automatically converted into organization owners.
|
||||||
|
|
|
@ -53,8 +53,8 @@ In either configuration, you will need to do the following:
|
||||||
integration, part 1: Connecting to the LDAP server".
|
integration, part 1: Connecting to the LDAP server".
|
||||||
* If a password is required, put it in
|
* If a password is required, put it in
|
||||||
`/etc/zulip/zulip-secrets.conf` by setting
|
`/etc/zulip/zulip-secrets.conf` by setting
|
||||||
`auth_ldap_bind_password`. For example: `auth_ldap_bind_password
|
`auth_ldap_bind_password`. For example:
|
||||||
= abcd1234`.
|
`auth_ldap_bind_password = abcd1234`.
|
||||||
|
|
||||||
1. Decide how you want to map the information in your LDAP database to
|
1. Decide how you want to map the information in your LDAP database to
|
||||||
users' account data in Zulip. For each Zulip user, two closely
|
users' account data in Zulip. For each Zulip user, two closely
|
||||||
|
@ -207,11 +207,11 @@ to the `AUTH_LDAP_USER_ATTR_MAP`.
|
||||||
|
|
||||||
Starting with Zulip 2.0, Zulip supports synchronizing the
|
Starting with Zulip 2.0, Zulip supports synchronizing the
|
||||||
disabled/deactivated status of users from Active Directory. You can
|
disabled/deactivated status of users from Active Directory. You can
|
||||||
configure this by uncommenting the sample line `"userAccountControl":
|
configure this by uncommenting the sample line
|
||||||
"userAccountControl",` in `AUTH_LDAP_USER_ATTR_MAP` (and restarting
|
`"userAccountControl": "userAccountControl",` in
|
||||||
the Zulip server). Zulip will then treat users that are disabled via
|
`AUTH_LDAP_USER_ATTR_MAP` (and restarting the Zulip server). Zulip
|
||||||
the "Disable Account" feature in Active Directory as deactivated in
|
will then treat users that are disabled via the "Disable Account"
|
||||||
Zulip.
|
feature in Active Directory as deactivated in Zulip.
|
||||||
|
|
||||||
Users disabled in active directory will be immediately unable to log in
|
Users disabled in active directory will be immediately unable to log in
|
||||||
to Zulip, since Zulip queries the LDAP/Active Directory server on
|
to Zulip, since Zulip queries the LDAP/Active Directory server on
|
||||||
|
@ -360,8 +360,7 @@ it as follows:
|
||||||
The `Entity ID` should match the value of
|
The `Entity ID` should match the value of
|
||||||
`SOCIAL_AUTH_SAML_SP_ENTITY_ID` computed in the Zulip settings.
|
`SOCIAL_AUTH_SAML_SP_ENTITY_ID` computed in the Zulip settings.
|
||||||
You can get the correct value by running the following:
|
You can get the correct value by running the following:
|
||||||
`/home/zulip/deployments/current/scripts/get-django-setting
|
`/home/zulip/deployments/current/scripts/get-django-setting SOCIAL_AUTH_SAML_SP_ENTITY_ID`.
|
||||||
SOCIAL_AUTH_SAML_SP_ENTITY_ID`.
|
|
||||||
|
|
||||||
* **SSO URL**:
|
* **SSO URL**:
|
||||||
`https://yourzulipdomain.example.com/complete/saml/`. This is
|
`https://yourzulipdomain.example.com/complete/saml/`. This is
|
||||||
|
@ -485,11 +484,11 @@ correctly authenticate the user to Zulip.
|
||||||
|
|
||||||
If you're hosting multiple organizations and thus using the
|
If you're hosting multiple organizations and thus using the
|
||||||
`SOCIAL_AUTH_SUBDOMAIN` setting, you'll need to configure a custom
|
`SOCIAL_AUTH_SUBDOMAIN` setting, you'll need to configure a custom
|
||||||
`RelayState` in your IdP of the form `{"subdomain":
|
`RelayState` in your IdP of the form
|
||||||
"yourzuliporganization"}` to let Zulip know which organization to
|
`{"subdomain": "yourzuliporganization"}` to let Zulip know which
|
||||||
authenticate the user to when they visit your SSO URL from the IdP.
|
organization to authenticate the user to when they visit your SSO URL
|
||||||
(If the organization is on the root domain, use the empty string:
|
from the IdP. (If the organization is on the root domain, use the
|
||||||
`{"subdomain": ""}`.).
|
empty string: `{"subdomain": ""}`.).
|
||||||
|
|
||||||
### Restricting access to specific organizations
|
### Restricting access to specific organizations
|
||||||
|
|
||||||
|
@ -568,8 +567,8 @@ straightforward way to deploy that SSO solution with Zulip.
|
||||||
5. Run `a2ensite zulip-sso` to enable the SSO integration within Apache.
|
5. Run `a2ensite zulip-sso` to enable the SSO integration within Apache.
|
||||||
|
|
||||||
6. Run `service apache2 reload` to use your new configuration. If
|
6. Run `service apache2 reload` to use your new configuration. If
|
||||||
Apache isn't already running, you may need to run `service apache2
|
Apache isn't already running, you may need to run
|
||||||
start` instead.
|
`service apache2 start` instead.
|
||||||
|
|
||||||
Now you should be able to visit your Zulip server in a browser (e.g.,
|
Now you should be able to visit your Zulip server in a browser (e.g.,
|
||||||
at `https://zulip.example.com/`) and log in via the SSO solution.
|
at `https://zulip.example.com/`) and log in via the SSO solution.
|
||||||
|
@ -702,8 +701,8 @@ By default, users who attempt to login with OIDC using an email
|
||||||
address that does not have a current Zulip account will be prompted
|
address that does not have a current Zulip account will be prompted
|
||||||
for whether they intend to create a new account or would like to login
|
for whether they intend to create a new account or would like to login
|
||||||
using another authentication method. You can configure automatic
|
using another authentication method. You can configure automatic
|
||||||
account creation on first login attempt by setting `"auto_signup":
|
account creation on first login attempt by setting
|
||||||
True` in the IdP configuration dictionary.
|
`"auto_signup": True` in the IdP configuration dictionary.
|
||||||
|
|
||||||
The global setting `SOCIAL_AUTH_OIDC_FULL_NAME_VALIDATED` controls how
|
The global setting `SOCIAL_AUTH_OIDC_FULL_NAME_VALIDATED` controls how
|
||||||
Zulip uses the Full Name provided by the IdP. By default, Zulip
|
Zulip uses the Full Name provided by the IdP. By default, Zulip
|
||||||
|
|
|
@ -371,8 +371,8 @@ make the following changes in two configuration files.
|
||||||
following. Place it the appropriate path for your Apache2
|
following. Place it the appropriate path for your Apache2
|
||||||
installation and enable it (E.g. if you use Debian or Ubuntu, then
|
installation and enable it (E.g. if you use Debian or Ubuntu, then
|
||||||
place it in `/etc/apache2/sites-available/zulip.example.com.conf`
|
place it in `/etc/apache2/sites-available/zulip.example.com.conf`
|
||||||
and then run `a2ensite zulip.example.com && systemctl reload
|
and then run
|
||||||
apache2`):
|
`a2ensite zulip.example.com && systemctl reload apache2`):
|
||||||
|
|
||||||
```apache
|
```apache
|
||||||
<VirtualHost *:80>
|
<VirtualHost *:80>
|
||||||
|
|
|
@ -13,8 +13,8 @@ you'd like to watch the downtime phase of the upgrade closely, you
|
||||||
can run them manually before starting the upgrade:
|
can run them manually before starting the upgrade:
|
||||||
|
|
||||||
1. Log in to your Zulip server as the `zulip` user (or as `root` and
|
1. Log in to your Zulip server as the `zulip` user (or as `root` and
|
||||||
then run `su zulip` to drop privileges), and `cd
|
then run `su zulip` to drop privileges), and
|
||||||
/home/zulip/deployments/current`
|
`cd /home/zulip/deployments/current`
|
||||||
2. Run `./manage.py dbshell`. This will open a shell connected to the
|
2. Run `./manage.py dbshell`. This will open a shell connected to the
|
||||||
PostgreSQL database.
|
PostgreSQL database.
|
||||||
3. In the PostgreSQL shell, run the following commands:
|
3. In the PostgreSQL shell, run the following commands:
|
||||||
|
|
|
@ -90,10 +90,11 @@ your organization, and your own user account as an administrator.
|
||||||
Then, log in!
|
Then, log in!
|
||||||
|
|
||||||
The link is a secure one-time-use link. If you need another
|
The link is a secure one-time-use link. If you need another
|
||||||
later, you can generate a new one by running `manage.py
|
later, you can generate a new one by running
|
||||||
generate_realm_creation_link` on the server. See also our doc on
|
`manage.py generate_realm_creation_link` on the server. See also our
|
||||||
running [multiple organizations on the same server](multiple-organizations.md)
|
doc on running [multiple organizations on the same
|
||||||
if that's what you're planning to do.
|
server](multiple-organizations.md) if that's what you're planning to
|
||||||
|
do.
|
||||||
|
|
||||||
## Step 4: Configure and use
|
## Step 4: Configure and use
|
||||||
|
|
||||||
|
|
|
@ -111,9 +111,9 @@ There are dozens of useful management commands under
|
||||||
with SQL will often not behave correctly because PostgreSQL doesn't
|
with SQL will often not behave correctly because PostgreSQL doesn't
|
||||||
know to flush Zulip's caches or notify browsers of changes.
|
know to flush Zulip's caches or notify browsers of changes.
|
||||||
* `./manage.py send_custom_email`: Can be used to send an email to a set
|
* `./manage.py send_custom_email`: Can be used to send an email to a set
|
||||||
of users. The `--help` documents how to run it from a `manage.py
|
of users. The `--help` documents how to run it from a
|
||||||
shell` for use with more complex programmatically computed sets of
|
`manage.py shell` for use with more complex programmatically
|
||||||
users.
|
computed sets of users.
|
||||||
* `./manage.py send_password_reset_email`: Sends password reset email(s)
|
* `./manage.py send_password_reset_email`: Sends password reset email(s)
|
||||||
to one or more users.
|
to one or more users.
|
||||||
* `./manage.py change_realm_subdomain`: Change subdomain of a realm.
|
* `./manage.py change_realm_subdomain`: Change subdomain of a realm.
|
||||||
|
|
|
@ -25,12 +25,13 @@ first.
|
||||||
|
|
||||||
You can enable this for your Zulip server as follows:
|
You can enable this for your Zulip server as follows:
|
||||||
|
|
||||||
1. Uncomment the `PUSH_NOTIFICATION_BOUNCER_URL =
|
1. Uncomment the
|
||||||
'https://push.zulipchat.com'` line in your `/etc/zulip/settings.py`
|
`PUSH_NOTIFICATION_BOUNCER_URL = 'https://push.zulipchat.com'` line
|
||||||
file (i.e. remove the `#` at the start of the line), and
|
in your `/etc/zulip/settings.py` file (i.e. remove the `#` at the
|
||||||
[restart your Zulip server](../production/settings.html#making-changes).
|
start of the line), and [restart your Zulip
|
||||||
If you installed your Zulip server with a version older than 1.6,
|
server](../production/settings.html#making-changes). If you
|
||||||
you'll need to add the line (it won't be there to uncomment).
|
installed your Zulip server with a version older than 1.6, you'll
|
||||||
|
need to add the line (it won't be there to uncomment).
|
||||||
|
|
||||||
1. If you're running Zulip 1.8.1 or newer, you can run the
|
1. If you're running Zulip 1.8.1 or newer, you can run the
|
||||||
registration command:
|
registration command:
|
||||||
|
@ -82,9 +83,9 @@ in the installer). You can update your server's registration data by
|
||||||
running `manage.py register_server` again.
|
running `manage.py register_server` again.
|
||||||
|
|
||||||
If you'd like to rotate your server's API key for this service
|
If you'd like to rotate your server's API key for this service
|
||||||
(`zulip_org_key`), you need to use `manage.py register_server
|
(`zulip_org_key`), you need to use
|
||||||
--rotate-key` option; it will automatically generate a new
|
`manage.py register_server --rotate-key` option; it will automatically
|
||||||
`zulip_org_key` and store that new key in
|
generate a new `zulip_org_key` and store that new key in
|
||||||
`/etc/zulip/zulip-secrets.conf`.
|
`/etc/zulip/zulip-secrets.conf`.
|
||||||
|
|
||||||
## Why this is necessary
|
## Why this is necessary
|
||||||
|
|
|
@ -46,9 +46,9 @@ things:
|
||||||
[the notes on `SOCIAL_AUTH_SUBDOMAIN` below](#authentication).
|
[the notes on `SOCIAL_AUTH_SUBDOMAIN` below](#authentication).
|
||||||
|
|
||||||
For servers hosting a large number of organizations, like
|
For servers hosting a large number of organizations, like
|
||||||
[zulip.com](https://zulip.com), one can set `ROOT_DOMAIN_LANDING_PAGE
|
[zulip.com](https://zulip.com), one can set
|
||||||
= True` in `/etc/zulip/settings.py` so that the homepage for the
|
`ROOT_DOMAIN_LANDING_PAGE = True` in `/etc/zulip/settings.py` so that
|
||||||
server is a copy of the Zulip homepage.
|
the homepage for the server is a copy of the Zulip homepage.
|
||||||
|
|
||||||
### SSL certificates
|
### SSL certificates
|
||||||
|
|
||||||
|
|
|
@ -84,14 +84,15 @@ which shows the currently running backends and their activity. This is
|
||||||
similar to the pg_top output, with the added advantage of showing the
|
similar to the pg_top output, with the added advantage of showing the
|
||||||
complete query, which can be valuable in debugging.
|
complete query, which can be valuable in debugging.
|
||||||
|
|
||||||
To stop a runaway query, you can run `SELECT pg_cancel_backend(pid
|
To stop a runaway query, you can run
|
||||||
int)` or `SELECT pg_terminate_backend(pid int)` as the 'postgres'
|
`SELECT pg_cancel_backend(pid int)` or
|
||||||
user. The former cancels the backend's current query and the latter
|
`SELECT pg_terminate_backend(pid int)` as the 'postgres' user. The
|
||||||
terminates the backend process. They are implemented by sending SIGINT
|
former cancels the backend's current query and the latter terminates
|
||||||
and SIGTERM to the processes, respectively. We recommend against
|
the backend process. They are implemented by sending SIGINT and
|
||||||
sending a PostgreSQL process SIGKILL. Doing so will cause the database
|
SIGTERM to the processes, respectively. We recommend against sending
|
||||||
to kill all current connections, roll back any pending transactions,
|
a PostgreSQL process SIGKILL. Doing so will cause the database to kill
|
||||||
and enter recovery mode.
|
all current connections, roll back any pending transactions, and enter
|
||||||
|
recovery mode.
|
||||||
|
|
||||||
#### Stopping the Zulip PostgreSQL database
|
#### Stopping the Zulip PostgreSQL database
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,10 @@ Two good tests include:
|
||||||
|
|
||||||
* Alternatively, run a command like `curl -SsI https://zulip.example.com`
|
* Alternatively, run a command like `curl -SsI https://zulip.example.com`
|
||||||
(using your server's URL) from a machine that can reach your server.
|
(using your server's URL) from a machine that can reach your server.
|
||||||
Make sure that on the same machine, `curl -SsI
|
Make sure that on the same machine,
|
||||||
https://incomplete-chain.badssl.com` gives an error; `curl` on some
|
`curl -SsI https://incomplete-chain.badssl.com` gives an error;
|
||||||
machines, including Macs, will accept incomplete chains.
|
`curl` on some machines, including Macs, will accept incomplete
|
||||||
|
chains.
|
||||||
|
|
||||||
[ssllabs-tester]: https://www.ssllabs.com/ssltest/analyze.html
|
[ssllabs-tester]: https://www.ssllabs.com/ssltest/analyze.html
|
||||||
|
|
||||||
|
|
|
@ -256,8 +256,8 @@ Database monitoring:
|
||||||
|
|
||||||
Standard server monitoring:
|
Standard server monitoring:
|
||||||
|
|
||||||
* `check_debian_packages`: Checks whether the system is behind on `apt
|
* `check_debian_packages`: Checks whether the system is behind on
|
||||||
upgrade`.
|
`apt upgrade`.
|
||||||
|
|
||||||
If you're using these plugins, bug reports and pull requests to make
|
If you're using these plugins, bug reports and pull requests to make
|
||||||
it easier to monitor Zulip and maintain it in production are
|
it easier to monitor Zulip and maintain it in production are
|
||||||
|
|
|
@ -59,9 +59,9 @@ as world-readable, whereas the "uploaded files" one is not.
|
||||||
|
|
||||||
With older Zulip, you need to edit
|
With older Zulip, you need to edit
|
||||||
`/etc/nginx/sites-available/zulip-enterprise` to comment out the
|
`/etc/nginx/sites-available/zulip-enterprise` to comment out the
|
||||||
`nginx` configuration block for `/user_avatars` and the `include
|
`nginx` configuration block for `/user_avatars` and the
|
||||||
/etc/nginx/zulip-include/uploads.route` line and then reload the
|
`include /etc/nginx/zulip-include/uploads.route` line and then
|
||||||
`nginx` service (`service nginx reload`).
|
reload the `nginx` service (`service nginx reload`).
|
||||||
|
|
||||||
1. Finally, restart the Zulip server so that your settings changes
|
1. Finally, restart the Zulip server so that your settings changes
|
||||||
take effect
|
take effect
|
||||||
|
|
|
@ -137,11 +137,11 @@ system:
|
||||||
- Tests for the backend views code logic for extracting data from the
|
- Tests for the backend views code logic for extracting data from the
|
||||||
database and serving it to clients.
|
database and serving it to clients.
|
||||||
|
|
||||||
For manual backend testing, it sometimes can be valuable to use `./manage.py
|
For manual backend testing, it sometimes can be valuable to use
|
||||||
dbshell` to inspect the tables manually to check that things look right; but
|
`./manage.py dbshell` to inspect the tables manually to check that
|
||||||
usually anything you feel the need to check manually, you should add some
|
things look right; but usually anything you feel the need to check
|
||||||
sort of assertion for to the backend analytics tests, to make sure it stays
|
manually, you should add some sort of assertion for to the backend
|
||||||
that way as we refactor.
|
analytics tests, to make sure it stays that way as we refactor.
|
||||||
|
|
||||||
## LoggingCountStats
|
## LoggingCountStats
|
||||||
|
|
||||||
|
|
|
@ -269,11 +269,11 @@ the browser console, but for debugging convenience, we have a custom
|
||||||
webpack plugin (`tools/debug-require-webpack-plugin.ts`) that exposes
|
webpack plugin (`tools/debug-require-webpack-plugin.ts`) that exposes
|
||||||
a version of the `require()` function to the development environment
|
a version of the `require()` function to the development environment
|
||||||
browser console for this purpose. For example, you can access our
|
browser console for this purpose. For example, you can access our
|
||||||
`people` module by evaluating `people =
|
`people` module by evaluating
|
||||||
require("./static/js/people")`, or the third-party `lodash` module
|
`people = require("./static/js/people")`, or the third-party `lodash`
|
||||||
with `_ = require("lodash")`. This mechanism is **not** a stable API
|
module with `_ = require("lodash")`. This mechanism is **not** a
|
||||||
and should not be used for any purpose other than interactive
|
stable API and should not be used for any purpose other than
|
||||||
debugging.
|
interactive debugging.
|
||||||
|
|
||||||
We have one module, `zulip_test`, that’s exposed as a global variable
|
We have one module, `zulip_test`, that’s exposed as a global variable
|
||||||
using `expose-loader` for direct use in Puppeteer tests and in the
|
using `expose-loader` for direct use in Puppeteer tests and in the
|
||||||
|
|
|
@ -131,8 +131,8 @@ new feature hard to miss.
|
||||||
* Blueslip keeps a log of all the notices it has received during a
|
* Blueslip keeps a log of all the notices it has received during a
|
||||||
browser session, and includes them in reports to the server, so that
|
browser session, and includes them in reports to the server, so that
|
||||||
one can see cases where exceptions chained together. You can print
|
one can see cases where exceptions chained together. You can print
|
||||||
this log from the browser console using `blueslip =
|
this log from the browser console using
|
||||||
require("./static/js/blueslip"); blueslip.get_log()`.
|
`blueslip = require("./static/js/blueslip"); blueslip.get_log()`.
|
||||||
|
|
||||||
Blueslip supports several error levels:
|
Blueslip supports several error levels:
|
||||||
* `throw new Error(…)`: For fatal errors that cannot be easily
|
* `throw new Error(…)`: For fatal errors that cannot be easily
|
||||||
|
|
|
@ -106,16 +106,16 @@ memcached to do work.
|
||||||
As one can see, there are two categories of endpoints that are
|
As one can see, there are two categories of endpoints that are
|
||||||
important for scalability: those with extremely high request volumes,
|
important for scalability: those with extremely high request volumes,
|
||||||
and those with moderately high request volumes that are also
|
and those with moderately high request volumes that are also
|
||||||
expensive. It doesn't matter how expensive, for example, `POST
|
expensive. It doesn't matter how expensive, for example,
|
||||||
/users/me/subscriptions` is for scalability, because the volume is
|
`POST /users/me/subscriptions` is for scalability, because the volume
|
||||||
negligible.
|
is negligible.
|
||||||
|
|
||||||
### Tornado
|
### Tornado
|
||||||
|
|
||||||
Zulip's Tornado-based [real-time push
|
Zulip's Tornado-based [real-time push
|
||||||
system](../subsystems/events-system.md), and in particular `GET
|
system](../subsystems/events-system.md), and in particular
|
||||||
/events`, accounts for something like 50% of all HTTP requests to a
|
`GET /events`, accounts for something like 50% of all HTTP requests to
|
||||||
production Zulip server. Despite `GET /events` being extremely
|
a production Zulip server. Despite `GET /events` being extremely
|
||||||
high-volume, the typical request takes 1-3ms to process, and doesn't
|
high-volume, the typical request takes 1-3ms to process, and doesn't
|
||||||
use the database at all (though it will access `memcached` and
|
use the database at all (though it will access `memcached` and
|
||||||
`redis`), so they aren't a huge contributor to the overall CPU usage
|
`redis`), so they aren't a huge contributor to the overall CPU usage
|
||||||
|
@ -228,10 +228,10 @@ of active optimization work.
|
||||||
|
|
||||||
### Fetching message history
|
### Fetching message history
|
||||||
|
|
||||||
Bulk requests for message content and metadata ([`GET
|
Bulk requests for message content and metadata
|
||||||
/messages`](https://zulip.com/api/get-messages)) account for ~3% of
|
([`GET /messages`](https://zulip.com/api/get-messages)) account for
|
||||||
total HTTP requests. The zulip web app has a few major reasons it does
|
~3% of total HTTP requests. The zulip web app has a few major reasons
|
||||||
a large number of these requests:
|
it does a large number of these requests:
|
||||||
|
|
||||||
* Most of these requests are from users clicking into different views
|
* Most of these requests are from users clicking into different views
|
||||||
-- to avoid certain subtle bugs, Zulip's web app currently fetches
|
-- to avoid certain subtle bugs, Zulip's web app currently fetches
|
||||||
|
|
|
@ -95,10 +95,10 @@ thread; search views will never mark messages as read.
|
||||||
|
|
||||||
## Testing and development
|
## Testing and development
|
||||||
|
|
||||||
In a Zulip development environment, you can use `manage.py
|
In a Zulip development environment, you can use
|
||||||
mark_all_messages_unread` to set every user's pointer to 0 and all
|
`manage.py mark_all_messages_unread` to set every user's pointer to 0
|
||||||
messages as unread, for convenience in testing unread count related
|
and all messages as unread, for convenience in testing unread count
|
||||||
logic.
|
related logic.
|
||||||
|
|
||||||
It can be useful to combine this with `manage.py populate_db -n 3000`
|
It can be useful to combine this with `manage.py populate_db -n 3000`
|
||||||
(which rebuilds the database with 3000 initial messages) to ensure a
|
(which rebuilds the database with 3000 initial messages) to ensure a
|
||||||
|
|
|
@ -41,8 +41,8 @@ To add a new queue processor:
|
||||||
queue worker in the Zulip development environment
|
queue worker in the Zulip development environment
|
||||||
(`tools/run-dev.py` will automatically restart the queue processors
|
(`tools/run-dev.py` will automatically restart the queue processors
|
||||||
and start running your new queue processor code). You can also run
|
and start running your new queue processor code). You can also run
|
||||||
a single queue processor manually using e.g. `./manage.py
|
a single queue processor manually using e.g.
|
||||||
process_queue --queue=user_activity`.
|
`./manage.py process_queue --queue=user_activity`.
|
||||||
|
|
||||||
* So that supervisord will know to run the queue processor in
|
* So that supervisord will know to run the queue processor in
|
||||||
production, you will need to add to the `queues` variable in
|
production, you will need to add to the `queues` variable in
|
||||||
|
|
|
@ -22,19 +22,19 @@ migrations.
|
||||||
* Commit your changes.
|
* Commit your changes.
|
||||||
* For more complicated migrations where you need to run custom Python
|
* For more complicated migrations where you need to run custom Python
|
||||||
code as part of the migration, it's best to read past migrations to
|
code as part of the migration, it's best to read past migrations to
|
||||||
understand how to write them well. `git grep RunPython
|
understand how to write them well.
|
||||||
zerver/migrations/02*` will find many good examples. Before writing
|
`git grep RunPython zerver/migrations/02*` will find many good
|
||||||
migrations of this form, you should read Django's docs and the
|
examples. Before writing migrations of this form, you should read
|
||||||
sections below.
|
Django's docs and the sections below.
|
||||||
* **Numbering conflicts across branches**: If you've done your schema
|
* **Numbering conflicts across branches**: If you've done your schema
|
||||||
change in a branch, and meanwhile another schema change has taken
|
change in a branch, and meanwhile another schema change has taken
|
||||||
place, Django will now have two migrations with the same
|
place, Django will now have two migrations with the same
|
||||||
number. There are two easy way to fix this:
|
number. There are two easy way to fix this:
|
||||||
* If your migrations were automatically generated using `manage.py
|
* If your migrations were automatically generated using
|
||||||
makemigrations`, a good option is to just remove your migration
|
`manage.py makemigrations`, a good option is to just remove your
|
||||||
and rerun the command after rebasing. Remember to `git rebase` to
|
migration and rerun the command after rebasing. Remember to
|
||||||
do this in the the commit that changed `models.py` if you have a
|
`git rebase` to do this in the the commit that changed `models.py`
|
||||||
multi-commit branch.
|
if you have a multi-commit branch.
|
||||||
* If you wrote code as part of preparing your migrations, or prefer
|
* If you wrote code as part of preparing your migrations, or prefer
|
||||||
this workflow, you can use run `./tools/renumber-migrations`,
|
this workflow, you can use run `./tools/renumber-migrations`,
|
||||||
which renumbers your migration(s) and fixes up the "dependencies"
|
which renumbers your migration(s) and fixes up the "dependencies"
|
||||||
|
|
|
@ -138,9 +138,9 @@ want those settings.
|
||||||
|
|
||||||
### Testing non-default settings
|
### Testing non-default settings
|
||||||
|
|
||||||
You can write tests for settings using e.g. `with
|
You can write tests for settings using e.g.
|
||||||
self.settings(TERMS_OF_SERVICE=None)`. However, this only works for
|
`with self.settings(TERMS_OF_SERVICE=None)`. However, this only works
|
||||||
settings which are checked at runtime, not settings which are only
|
for settings which are checked at runtime, not settings which are only
|
||||||
accessed in initialization of Django (or Zulip) internals
|
accessed in initialization of Django (or Zulip) internals
|
||||||
(e.g. `DATABASES`). See the [Django docs on overriding settings in
|
(e.g. `DATABASES`). See the [Django docs on overriding settings in
|
||||||
tests][django-test-settings] for more details.
|
tests][django-test-settings] for more details.
|
||||||
|
|
|
@ -27,10 +27,10 @@ run to iteratively debug something.
|
||||||
### Useful debugging tips and tools
|
### Useful debugging tips and tools
|
||||||
|
|
||||||
* GitHub Actions stores timestamps for every line in the logs. They
|
* GitHub Actions stores timestamps for every line in the logs. They
|
||||||
are hidden by default; you can see them by toggling the `Show
|
are hidden by default; you can see them by toggling the
|
||||||
timestamps` option in the menu on any job's log page. (You can get
|
`Show timestamps` option in the menu on any job's log page. (You can
|
||||||
this sort of timestamp in a development environment by piping output
|
get this sort of timestamp in a development environment by piping
|
||||||
to `ts`).
|
output to `ts`).
|
||||||
|
|
||||||
* GitHub Actions runs on every branch you push on your Zulip fork.
|
* GitHub Actions runs on every branch you push on your Zulip fork.
|
||||||
This is helpful when debugging something complicated.
|
This is helpful when debugging something complicated.
|
||||||
|
|
|
@ -41,8 +41,8 @@ CI testing process in the `backend` build.
|
||||||
mypy is installed by default in the Zulip development environment. If
|
mypy is installed by default in the Zulip development environment. If
|
||||||
you'd like to install just the version of `mypy` that we're using
|
you'd like to install just the version of `mypy` that we're using
|
||||||
(useful if e.g. you want `mypy` installed on your laptop outside the
|
(useful if e.g. you want `mypy` installed on your laptop outside the
|
||||||
Vagrant guest), you can do that with `pip install -r
|
Vagrant guest), you can do that with
|
||||||
requirements/mypy.txt`.
|
`pip install -r requirements/mypy.txt`.
|
||||||
|
|
||||||
## Running mypy on Zulip's code locally
|
## Running mypy on Zulip's code locally
|
||||||
|
|
||||||
|
@ -277,8 +277,8 @@ alternatives first:
|
||||||
single site, you may want a [**`Union`
|
single site, you may want a [**`Union`
|
||||||
type**](https://mypy.readthedocs.io/en/stable/kinds_of_types.html#union-types).
|
type**](https://mypy.readthedocs.io/en/stable/kinds_of_types.html#union-types).
|
||||||
`Union` is checked: before using `value: Union[str, int]` as a
|
`Union` is checked: before using `value: Union[str, int]` as a
|
||||||
`str`, mypy requires that you validate it with an `instance(value,
|
`str`, mypy requires that you validate it with an
|
||||||
str)` test.
|
`instance(value, str)` test.
|
||||||
|
|
||||||
* If you really have no information about the type of a value, use the
|
* If you really have no information about the type of a value, use the
|
||||||
**`object` type**. Since every type is a subtype of `object`, you
|
**`object` type**. Since every type is a subtype of `object`, you
|
||||||
|
@ -325,8 +325,8 @@ Instead of using `cast`:
|
||||||
|
|
||||||
### Avoid `# type: ignore` comments
|
### Avoid `# type: ignore` comments
|
||||||
|
|
||||||
Mypy allows you to ignore any type checking error with a [`# type:
|
Mypy allows you to ignore any type checking error with a
|
||||||
ignore`
|
[`# type: ignore`
|
||||||
comment](https://mypy.readthedocs.io/en/stable/common_issues.html#spurious-errors-and-locally-silencing-the-checker),
|
comment](https://mypy.readthedocs.io/en/stable/common_issues.html#spurious-errors-and-locally-silencing-the-checker),
|
||||||
but you should avoid this in the absence of a very good reason, such
|
but you should avoid this in the absence of a very good reason, such
|
||||||
as a bug in mypy itself. If there are no safe options for dealing
|
as a bug in mypy itself. If there are no safe options for dealing
|
||||||
|
@ -378,9 +378,9 @@ collection. For example:
|
||||||
* An exclude list where the default is to exclude nothing should be
|
* An exclude list where the default is to exclude nothing should be
|
||||||
non-`Optional` with default `[]`.
|
non-`Optional` with default `[]`.
|
||||||
|
|
||||||
Don't test an `Optional` value using truthiness (`if value:`, `not
|
Don't test an `Optional` value using truthiness (`if value:`,
|
||||||
value`, `value or default_value`), especially when the type might have
|
`not value`, `value or default_value`), especially when the type might
|
||||||
falsy values other than `None`.
|
have falsy values other than `None`.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
s: Optional[str]
|
s: Optional[str]
|
||||||
|
@ -491,8 +491,8 @@ def f(s: str) -> str:
|
||||||
return s
|
return s
|
||||||
```
|
```
|
||||||
|
|
||||||
(A generic decorator with an argument would return `Callable[[FuncT],
|
(A generic decorator with an argument would return
|
||||||
FuncT]`.)
|
`Callable[[FuncT], FuncT]`.)
|
||||||
|
|
||||||
But Mypy doesn't yet support the advanced type annotations that would
|
But Mypy doesn't yet support the advanced type annotations that would
|
||||||
be needed to correctly type generic signature-changing decorators,
|
be needed to correctly type generic signature-changing decorators,
|
||||||
|
|
|
@ -58,10 +58,11 @@ that failed in the last test run.
|
||||||
**Webhook integrations**. For performance, `test-backend` with no
|
**Webhook integrations**. For performance, `test-backend` with no
|
||||||
arguments will not run webhook integration tests (`zerver/webhooks/`),
|
arguments will not run webhook integration tests (`zerver/webhooks/`),
|
||||||
which would otherwise account for about 25% of the total runtime.
|
which would otherwise account for about 25% of the total runtime.
|
||||||
When working on webhooks, we recommend instead running `test-backend
|
When working on webhooks, we recommend instead running
|
||||||
zerver/webhooks` manually (or better, the direction for the specific
|
`test-backend zerver/webhooks` manually (or better, the direction for
|
||||||
webhooks you're working on). And of course our CI is configured to
|
the specific webhooks you're working on). And of course our CI is
|
||||||
always use `test-backend --include-webhooks` and run all of the tests.
|
configured to always use `test-backend --include-webhooks` and run all
|
||||||
|
of the tests.
|
||||||
|
|
||||||
## Writing tests
|
## Writing tests
|
||||||
|
|
||||||
|
@ -483,8 +484,8 @@ is exposed in your development environment).
|
||||||
the console; use `with self.assertLogs` to capture and verify any
|
the console; use `with self.assertLogs` to capture and verify any
|
||||||
logging output. Note that we reconfigure various loggers in
|
logging output. Note that we reconfigure various loggers in
|
||||||
`zproject/test_extra_settings.py` where the output is unlikely to be
|
`zproject/test_extra_settings.py` where the output is unlikely to be
|
||||||
interesting when running our test suite. `test-backend
|
interesting when running our test suite.
|
||||||
--ban-console-output` checks for stray print statements.
|
`test-backend --ban-console-output` checks for stray print statements.
|
||||||
|
|
||||||
Note that `test-backend --coverage` will assert that
|
Note that `test-backend --coverage` will assert that
|
||||||
various specific files in the project have 100% test coverage and
|
various specific files in the project have 100% test coverage and
|
||||||
|
|
|
@ -204,8 +204,8 @@ These instructions assume you're using the Vagrant development environment.
|
||||||
3. You'll now need to set up a WebStorm "Debug Configuration". Open
|
3. You'll now need to set up a WebStorm "Debug Configuration". Open
|
||||||
the `Run/Debug Configuration` menu and create a new `Node.js` config:
|
the `Run/Debug Configuration` menu and create a new `Node.js` config:
|
||||||
1. Under `Node interpreter:` click the 3 dots to the right side and
|
1. Under `Node interpreter:` click the 3 dots to the right side and
|
||||||
click on the little plus in the bottom left of the `Node.js
|
click on the little plus in the bottom left of the
|
||||||
Interpreters` window.
|
`Node.js Interpreters` window.
|
||||||
1. Select `Add Remote...`.
|
1. Select `Add Remote...`.
|
||||||
1. In the `Configure Node.js Remote Interpreter`, window select `Vagrant`
|
1. In the `Configure Node.js Remote Interpreter`, window select `Vagrant`
|
||||||
1. Wait for WebStorm to connect to Vagrant. This will be displayed
|
1. Wait for WebStorm to connect to Vagrant. This will be displayed
|
||||||
|
|
|
@ -148,13 +148,13 @@ notes above:
|
||||||
wait function to make sure the page or element is ready before you
|
wait function to make sure the page or element is ready before you
|
||||||
interact with it. The [puppeteer docs site](https://pptr.dev/) is a
|
interact with it. The [puppeteer docs site](https://pptr.dev/) is a
|
||||||
useful reference for the available wait functions.
|
useful reference for the available wait functions.
|
||||||
- When using `waitForSelector`, you always want to use the `{visible:
|
- When using `waitForSelector`, you always want to use the
|
||||||
true}` option; otherwise the test will stop waiting as soon as the
|
`{visible: true}` option; otherwise the test will stop waiting as
|
||||||
target selector is present in the DOM even if it's hidden. For the
|
soon as the target selector is present in the DOM even if it's
|
||||||
common UI pattern of having an element always be present in the DOM
|
hidden. For the common UI pattern of having an element always be
|
||||||
whose presence is managed via show/hide rather than adding/removing
|
present in the DOM whose presence is managed via show/hide rather
|
||||||
it from the DOM, `waitForSelector` without `visible: true` won't
|
than adding/removing it from the DOM, `waitForSelector` without
|
||||||
wait at all.
|
`visible: true` won't wait at all.
|
||||||
- The test suite uses a smaller set of default user accounts and other
|
- The test suite uses a smaller set of default user accounts and other
|
||||||
data initialized in the database than the normal development
|
data initialized in the database than the normal development
|
||||||
environment; specifically, it uses the same setup as the [backend
|
environment; specifically, it uses the same setup as the [backend
|
||||||
|
|
|
@ -78,8 +78,8 @@ those that:
|
||||||
* Don't have large open pull requests (to avoid merge conflicts); one
|
* Don't have large open pull requests (to avoid merge conflicts); one
|
||||||
can scan for these using [TinglingGit](https://github.com/zulip/TinglingGit).
|
can scan for these using [TinglingGit](https://github.com/zulip/TinglingGit).
|
||||||
* Have good unit test coverage, which limits the risk of breaking
|
* Have good unit test coverage, which limits the risk of breaking
|
||||||
correctness through refactoring. Use `tools/test-js-with-node
|
correctness through refactoring. Use
|
||||||
--coverage` to get a coverage report.
|
`tools/test-js-with-node --coverage` to get a coverage report.
|
||||||
|
|
||||||
When migrating a module, we want to be especially thoughtful about
|
When migrating a module, we want to be especially thoughtful about
|
||||||
putting together a commit structure that makes mistakes unlikely and
|
putting together a commit structure that makes mistakes unlikely and
|
||||||
|
|
|
@ -77,10 +77,10 @@ The end-to-end tooling process for translations in Zulip is as follows.
|
||||||
[frontend](#frontend-translations) translations for details on
|
[frontend](#frontend-translations) translations for details on
|
||||||
this).
|
this).
|
||||||
|
|
||||||
2. Translation resource files are created using the `./manage.py
|
2. Translation resource files are created using the
|
||||||
makemessages` command. This command will create, for each language,
|
`./manage.py makemessages` command. This command will create, for
|
||||||
a resource file called `translations.json` for the frontend strings
|
each language, a resource file called `translations.json` for the
|
||||||
and `django.po` for the backend strings.
|
frontend strings and `django.po` for the backend strings.
|
||||||
|
|
||||||
The `makemessages` command is idempotent in that:
|
The `makemessages` command is idempotent in that:
|
||||||
|
|
||||||
|
|
|
@ -183,11 +183,10 @@ REQ also helps us with request variable validation. For example:
|
||||||
as JSON, and pass it into the function as the `msg_ids` Python
|
as JSON, and pass it into the function as the `msg_ids` Python
|
||||||
keyword argument.
|
keyword argument.
|
||||||
|
|
||||||
* `streams_raw = REQ("subscriptions",
|
* `streams_raw = REQ("subscriptions", json_validator=check_list(check_string))`
|
||||||
json_validator=check_list(check_string))` will check that the
|
will check that the "subscriptions" HTTP parameter is a list of
|
||||||
"subscriptions" HTTP parameter is a list of strings, marshalled as
|
strings, marshalled as JSON, and pass it into the function with the
|
||||||
JSON, and pass it into the function with the Python keyword argument
|
Python keyword argument `streams_raw`.
|
||||||
`streams_raw`.
|
|
||||||
|
|
||||||
* `message_id=REQ(converter=to_non_negative_int)` will check that the
|
* `message_id=REQ(converter=to_non_negative_int)` will check that the
|
||||||
`message_id` HTTP parameter is a string containing a non-negative
|
`message_id` HTTP parameter is a string containing a non-negative
|
||||||
|
|
|
@ -138,8 +138,8 @@ Rough steps:
|
||||||
and shut down the droplet.
|
and shut down the droplet.
|
||||||
1. Go to the Images tab on DigitalOcean, and "Take a Snapshot".
|
1. Go to the Images tab on DigitalOcean, and "Take a Snapshot".
|
||||||
1. Wait for several minutes.
|
1. Wait for several minutes.
|
||||||
1. Do something like `curl -X GET -H "Content-Type: application/json"
|
1. Do something like
|
||||||
-u <API_KEY>: "https://api.digitalocean.com/v2/images?page=11" | grep --color=always base.zulipdev.org`
|
`curl -X GET -H "Content-Type: application/json" -u <API_KEY>: "https://api.digitalocean.com/v2/images?page=11" | grep --color=always base.zulipdev.org`
|
||||||
(maybe with a different page number, and replace your API_KEY).
|
(maybe with a different page number, and replace your API_KEY).
|
||||||
1. Replace `template_id` in `create.py` in this directory with the
|
1. Replace `template_id` in `create.py` in this directory with the
|
||||||
appropriate `id`.
|
appropriate `id`.
|
||||||
|
@ -181,8 +181,8 @@ Rough steps:
|
||||||
1. `> ~/.bash_history && history -c && sudo shutdown -h now`
|
1. `> ~/.bash_history && history -c && sudo shutdown -h now`
|
||||||
1. Go to the Images tab on DigitalOcean, and "Take a Snapshot".
|
1. Go to the Images tab on DigitalOcean, and "Take a Snapshot".
|
||||||
1. Wait for several minutes.
|
1. Wait for several minutes.
|
||||||
1. Do something like `curl -X GET -H "Content-Type: application/json"
|
1. Do something like
|
||||||
-u <API_KEY>: "https://api.digitalocean.com/v2/images?page=11" | grep --color=always base.zulipdev.org`
|
`curl -X GET -H "Content-Type: application/json" -u <API_KEY>: "https://api.digitalocean.com/v2/images?page=11" | grep --color=always base.zulipdev.org`
|
||||||
(maybe with a different page number, and replace your API_KEY).
|
(maybe with a different page number, and replace your API_KEY).
|
||||||
1. Replace `template_id` in `create.py` in this directory with the
|
1. Replace `template_id` in `create.py` in this directory with the
|
||||||
appropriate `id`.
|
appropriate `id`.
|
||||||
|
|
Loading…
Reference in New Issue