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:
Anders Kaseorg 2021-09-07 15:23:24 -07:00 committed by Anders Kaseorg
parent a6e01b35fc
commit 6145fdf678
40 changed files with 231 additions and 222 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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 —

View File

@ -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)

View File

@ -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

View File

@ -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`:

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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>

View File

@ -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:

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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`, thats exposed as a global variable We have one module, `zulip_test`, thats 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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.

View File

@ -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.

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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`.