mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-31 12:03:46 +00:00 
			
		
		
		
	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:
		
				
					committed by
					
						 Anders Kaseorg
						Anders Kaseorg
					
				
			
			
				
	
			
			
			
						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. | ||||
|  | ||||
| Good ways to make timezone-aware datetimes are below. We import timezone | ||||
| libraries as `from datetime import datetime, timezone` and `from | ||||
| django.utils.timezone import now as timezone_now`. | ||||
| libraries as `from datetime import datetime, timezone` and | ||||
| `from django.utils.timezone import now as timezone_now`. | ||||
|  | ||||
| Use: | ||||
| * `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) | ||||
| primitives such as [`for … of` | ||||
| loops](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of), | ||||
| [`Array.prototype.{entries, every, filter, find, indexOf, map, | ||||
| 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), | ||||
| [`Array.prototype.{entries, every, filter, find, indexOf, map, 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), | ||||
| [spread | ||||
| syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax), | ||||
| 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 | ||||
| [Prettier](https://prettier.io/).  You can ask Prettier to reformat | ||||
| all code via our [linter tool](../testing/linters.md) with `tools/lint | ||||
| --only=prettier --fix`.  You can also [integrate it with your | ||||
| all code via our [linter tool](../testing/linters.md) with | ||||
| `tools/lint --only=prettier --fix`.  You can also [integrate it with your | ||||
| editor](https://prettier.io/docs/en/editors.html). | ||||
|  | ||||
| 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 | ||||
|     [isort](https://pycqa.github.io/isort/).  The [linter | ||||
|     tool](../testing/linters.md) enforces this by running Black and | ||||
|     isort in check mode, or in write mode with `tools/lint | ||||
|     --only=black,isort --fix`.  You may find it helpful to [integrate | ||||
|     isort in check mode, or in write mode with | ||||
|     `tools/lint --only=black,isort --fix`.  You may find it helpful to | ||||
|     [integrate | ||||
|     Black](https://black.readthedocs.io/en/stable/editor_integration.html) | ||||
|     and | ||||
|     [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 | ||||
|   not actually sent by the development environment), to make it | ||||
|   convenient to click through the UI of signup, password reset, etc. | ||||
| * There's a management command, `manage.py print_initial_password | ||||
|   username@example.com`, that prints out **default** passwords for the | ||||
|   development environment users.  Note that if you change a user's | ||||
|   password in the development environment, those passwords will no longer | ||||
|   work.  It also prints out the user's **current** API key. | ||||
| * There's a management command, | ||||
|   `manage.py print_initial_password username@example.com`, that prints | ||||
|   out **default** passwords for the development environment users. | ||||
|   Note that if you change a user's password in the development | ||||
|   environment, those passwords will no longer work.  It also prints | ||||
|   out the user's **current** API key. | ||||
|  | ||||
| ### Google | ||||
|  | ||||
|   | ||||
| @@ -37,14 +37,14 @@ to the next section. | ||||
|  | ||||
| You can create a new user with sudo privileges by running the | ||||
| following commands as root: | ||||
| * You can create a `zulipdev` user by running the command `adduser | ||||
| zulipdev`. Run through the prompts to assign a password and user | ||||
| information.  (You can pick any username you like for this user | ||||
| * You can create a `zulipdev` user by running the command | ||||
| `adduser zulipdev`. Run through the prompts to assign a password and | ||||
| user information.  (You can pick any username you like for this user | ||||
| account.) | ||||
| * You can add the user to the sudo group by running the command | ||||
| `usermod -aG sudo zulipdev`. | ||||
| * Finally, you can switch to the user by running the command `su - | ||||
| zulipdev` (or just log in to that user using `ssh`). | ||||
| * Finally, you can switch to the user by running the command | ||||
| `su - zulipdev` (or just log in to that user using `ssh`). | ||||
|  | ||||
| ## Setting up the development environment | ||||
|  | ||||
| @@ -311,9 +311,9 @@ different. | ||||
|     service nginx reload  # Actually enabled your nginx configuration | ||||
|     ``` | ||||
|  | ||||
| 1. Edit `zproject/dev_settings.py` to set `EXTERNAL_URI_SCHEME = | ||||
|    "https://"`, so that URLs served by the development environment | ||||
|    will be HTTPS. | ||||
| 1. Edit `zproject/dev_settings.py` to set | ||||
|    `EXTERNAL_URI_SCHEME = "https://"`, so that URLs served by the | ||||
|    development environment will be HTTPS. | ||||
|  | ||||
| 1. Start the Zulip development environment with the following command: | ||||
|    ```bash | ||||
|   | ||||
| @@ -251,10 +251,10 @@ expected. | ||||
| 1. If you get the error `Hyper-V could not initialize memory`, this is | ||||
|    likely because your system has insufficient free memory to start | ||||
|    the virtual machine.  You can generally work around this error by | ||||
|    closing all other running programs and running `vagrant up | ||||
|    --provider=hyperv` again. You can reopen the other programs after | ||||
|    the provisioning is completed. If it still isn't enough, try | ||||
|    restarting your system and running the command again. | ||||
|    closing all other running programs and running | ||||
|    `vagrant up --provider=hyperv` again. You can reopen the other | ||||
|    programs after the provisioning is completed. If it still isn't | ||||
|    enough, try restarting your system and running the command again. | ||||
|  | ||||
| 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 | ||||
|   space. (This is under free limit for both the old Cloud9 and the AWS | ||||
|   Free Tier). | ||||
| * Clone the zulip repo: `git clone --config pull.rebase | ||||
|   https://github.com/<your-username>/zulip.git` | ||||
| * Restart rabbitmq-server since its broken on Cloud9: `sudo service | ||||
|   rabbitmq-server restart`. | ||||
| * Clone the zulip repo: | ||||
|   `git clone --config pull.rebase https://github.com/<your-username>/zulip.git` | ||||
| * Restart rabbitmq-server since its broken on Cloud9: | ||||
|   `sudo service rabbitmq-server restart`. | ||||
| * And run provision `cd zulip && ./tools/provision`, once this is done. | ||||
| * Activate the Zulip virtual environment by `source | ||||
|   /srv/zulip-py3-venv/bin/activate` or by opening a new terminal. | ||||
| * Activate the Zulip virtual environment by | ||||
|   `source /srv/zulip-py3-venv/bin/activate` or by opening a new | ||||
|   terminal. | ||||
|  | ||||
| #### 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 | ||||
| real-time help. | ||||
|  | ||||
| On Windows, you will see the message `The system cannot find the path | ||||
| specified.` several times.  This is normal and is not a problem. | ||||
| On Windows, you will see the message | ||||
| `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 | ||||
| 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 | ||||
| running `vagrant ssh`, which should present you with a standard shell | ||||
| prompt.  You can debug interactively by using e.g. `cd zulip && | ||||
| ./tools/provision`, and then running the individual subcommands | ||||
| that failed.  Once you've resolved the problem, you can rerun | ||||
| `tools/provision` to proceed; the provisioning system is designed | ||||
| to recover well from failures. | ||||
| prompt.  You can debug interactively by using e.g. | ||||
| `cd zulip && ./tools/provision`, and then running the individual | ||||
| subcommands that failed.  Once you've resolved the problem, you can | ||||
| rerun `tools/provision` to proceed; the provisioning system is | ||||
| designed to recover well from failures. | ||||
|  | ||||
| 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 | ||||
| @@ -883,9 +884,10 @@ enabled in your BIOS. | ||||
|  | ||||
| If the error persists, you may have run into an incompatibility | ||||
| between VirtualBox and Hyper-V on Windows.  To disable Hyper-V, open | ||||
| command prompt as administrator, run `bcdedit /set | ||||
| hypervisorlaunchtype off`, and reboot.  If you need to enable it | ||||
| later, run `bcdedit /deletevalue hypervisorlaunchtype`, and reboot. | ||||
| command prompt as administrator, run | ||||
| `bcdedit /set hypervisorlaunchtype off`, and reboot.  If you need to | ||||
| enable it later, run `bcdedit /deletevalue hypervisorlaunchtype`, and | ||||
| reboot. | ||||
|  | ||||
| #### OSError: [Errno 26] Text file busy | ||||
|  | ||||
|   | ||||
| @@ -14,9 +14,10 @@ the development environment][authentication-dev-server]. | ||||
| ## Common | ||||
|  | ||||
| * Zulip's `main` branch moves quickly, and you should rebase | ||||
|   constantly with e.g. `git fetch upstream; git rebase | ||||
|   upstream/main` to avoid developing on an old version of the Zulip | ||||
|   codebase (leading to unnecessary merge conflicts). | ||||
|   constantly with e.g. | ||||
|   `git fetch upstream; git rebase upstream/main` to avoid developing | ||||
|   on an old version of the Zulip codebase (leading to unnecessary | ||||
|   merge conflicts). | ||||
| * Remember to run `tools/provision` to update your development | ||||
|   environment after switching branches; it will run in under a second | ||||
|   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 | ||||
|   Zulip development server encounters (which are probably caused by | ||||
|   bugs in your code). | ||||
| * To manually query Zulip's database interactively, use `./manage.py | ||||
|   shell` or `manage.py dbshell`. | ||||
| * To manually query Zulip's database interactively, use | ||||
|   `./manage.py shell` or `manage.py dbshell`. | ||||
| * 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 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 | ||||
| make use of `fa` as a base class. | ||||
|  | ||||
| * cog (<i class="fa fa-cog"></i>) icon — `cog (<i | ||||
| class="fa fa-cog"></i>) icon` | ||||
| * cog (<i 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` | ||||
| * eye (<i 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 | ||||
| class="fa fa-file-code-o"></i>) icon` | ||||
| * eye (<i 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 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` | ||||
| * 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 | ||||
| class="fa fa-bars"></i>) icon` | ||||
| * menu (<i 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` | ||||
| * 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` | ||||
| will behave like `git pull --rebase` by default.  Using `git pull | ||||
| --rebase` to update your changes to resolve merge conflicts is | ||||
| expected by essentially all of open source projects, including Zulip. | ||||
| You can also set that option after cloning using `git config --add | ||||
| pull.rebase true`, or just be careful to always run `git pull | ||||
| --rebase`, never `git pull`). | ||||
| will behave like `git pull --rebase` by default.  Using | ||||
| `git pull --rebase` to update your changes to resolve merge conflicts | ||||
| is expected by essentially all of open source projects, including | ||||
| Zulip.  You can also set that option after cloning using | ||||
| `git config --add pull.rebase true`, or just be careful to always run | ||||
| `git pull --rebase`, never `git pull`). | ||||
|  | ||||
| Note: If you receive an error while cloning, you may not have [added your ssh | ||||
| 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 | ||||
| have the upstream remote repository configured. For example, when you clone | ||||
| [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 | ||||
| -v`: | ||||
| the remote repository `zulip` and you see the following output from | ||||
| `git remote -v`: | ||||
|  | ||||
| ```console | ||||
| origin  git@github.com:YOUR_USERNAME/zulip.git (fetch) | ||||
|   | ||||
| @@ -129,9 +129,9 @@ $ git log | ||||
| * 13bea0e (HEAD -> main) test commit for docs. | ||||
| ``` | ||||
|  | ||||
| And then realize you actually needed to keep commit 67aea58. First, use `git | ||||
| reflog` to confirm that commit you want to restore and then run `git | ||||
| cherry-pick <commit>`: | ||||
| And then realize you actually needed to keep commit 67aea58. First, use | ||||
| `git reflog` to confirm that commit you want to restore and then run | ||||
| `git cherry-pick <commit>`: | ||||
|  | ||||
| ```console | ||||
| $ 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 | ||||
| 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 | ||||
| && git merge FETCH_HEAD` ([docs][gitbook-git-pull]), you should use `git fetch` | ||||
| and then `git rebase`. | ||||
| it. Rather than using `git pull`, which by default is a shortcut for | ||||
| `git fetch && git merge FETCH_HEAD` ([docs][gitbook-git-pull]), you | ||||
| should use `git fetch` and then `git rebase`. | ||||
|  | ||||
| First, [fetch][gitbook-fetch] changes from Zulip's upstream repository you | ||||
| 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 | ||||
|  | ||||
| To add changes to your staging area, use `git add <filename>`. Because `git | ||||
| add` is all about staging the changes you want to commit, you use it to add | ||||
| *new files* as well as *files with changes* to your staging area. | ||||
| To add changes to your staging area, use `git add <filename>`. Because | ||||
| `git add` is all about staging the changes you want to commit, you use | ||||
| 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 | ||||
| the following from `git status`: | ||||
|   | ||||
| @@ -45,6 +45,6 @@ working copies: | ||||
| - `git remote`: This helps you configure short names for remotes. | ||||
| - `git pull`: This pulls code, but by default creates a merge commit | ||||
|   (which you definitely don't want).  However, if you've followed our | ||||
|   [cloning documentation](../git/cloning.md), this will do `git pull | ||||
|   --rebase` instead, which is the only mode you'll want to use when | ||||
|   working on Zulip. | ||||
|   [cloning documentation](../git/cloning.md), this will do | ||||
|   `git pull --rebase` instead, which is the only mode you'll want to | ||||
|   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 | ||||
|   to any email address containing `.`, `+`, or starting with `mm`, when | ||||
|   configured to use the local Postfix to deliver outgoing email. | ||||
| - Fixed a backporting error which caused the `manage.py | ||||
|   change_user_role` tool to not work for `admin`, `member`, or `guest` roles. | ||||
| - Fixed a backporting error which caused the | ||||
|   `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 | ||||
|   desktop application. | ||||
| - 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]. | ||||
| - The format of the `JWT_AUTH_KEYS` setting has changed to include an | ||||
|   [algorithms](https://pyjwt.readthedocs.io/en/latest/algorithms.html) | ||||
|   list: `{"subdomain": "key"}` becomes `{"subdomain": {"key": "key", | ||||
|   "algorithms": ["HS256"]}}`. | ||||
|   list: `{"subdomain": "key"}` becomes | ||||
|   `{"subdomain": {"key": "key", "algorithms": ["HS256"]}}`. | ||||
| - Added a new organization owner permission above the previous | ||||
|   organization administrator.  All existing organization | ||||
|   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". | ||||
|    * If a password is required, put it in | ||||
|      `/etc/zulip/zulip-secrets.conf` by setting | ||||
|      `auth_ldap_bind_password`.  For example: `auth_ldap_bind_password | ||||
|      = abcd1234`. | ||||
|      `auth_ldap_bind_password`.  For example: | ||||
|      `auth_ldap_bind_password = abcd1234`. | ||||
|  | ||||
| 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 | ||||
| @@ -207,11 +207,11 @@ to the `AUTH_LDAP_USER_ATTR_MAP`. | ||||
|  | ||||
| Starting with Zulip 2.0, Zulip supports synchronizing the | ||||
| disabled/deactivated status of users from Active Directory.  You can | ||||
| configure this by uncommenting the sample line `"userAccountControl": | ||||
| "userAccountControl",` in `AUTH_LDAP_USER_ATTR_MAP` (and restarting | ||||
| the Zulip server).  Zulip will then treat users that are disabled via | ||||
| the "Disable Account" feature in Active Directory as deactivated in | ||||
| Zulip. | ||||
| configure this by uncommenting the sample line | ||||
| `"userAccountControl": "userAccountControl",` in | ||||
| `AUTH_LDAP_USER_ATTR_MAP` (and restarting the Zulip server).  Zulip | ||||
| will then treat users that are disabled via the "Disable Account" | ||||
| feature in Active Directory as deactivated in Zulip. | ||||
|  | ||||
| Users disabled in active directory will be immediately unable to log in | ||||
| 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 | ||||
|       `SOCIAL_AUTH_SAML_SP_ENTITY_ID` computed in the Zulip settings. | ||||
|       You can get the correct value by running the following: | ||||
|       `/home/zulip/deployments/current/scripts/get-django-setting | ||||
|       SOCIAL_AUTH_SAML_SP_ENTITY_ID`. | ||||
|       `/home/zulip/deployments/current/scripts/get-django-setting SOCIAL_AUTH_SAML_SP_ENTITY_ID`. | ||||
|  | ||||
|     * **SSO URL**: | ||||
|       `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 | ||||
| `SOCIAL_AUTH_SUBDOMAIN` setting, you'll need to configure a custom | ||||
| `RelayState` in your IdP of the form `{"subdomain": | ||||
| "yourzuliporganization"}` to let Zulip know which organization to | ||||
| authenticate the user to when they visit your SSO URL from the IdP. | ||||
| (If the organization is on the root domain, use the empty string: | ||||
| `{"subdomain": ""}`.). | ||||
| `RelayState` in your IdP of the form | ||||
| `{"subdomain": "yourzuliporganization"}` to let Zulip know which | ||||
| organization to authenticate the user to when they visit your SSO URL | ||||
| from the IdP.  (If the organization is on the root domain, use the | ||||
| empty string: `{"subdomain": ""}`.). | ||||
|  | ||||
| ### 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. | ||||
|  | ||||
| 6. Run `service apache2 reload` to use your new configuration.  If | ||||
|    Apache isn't already running, you may need to run `service apache2 | ||||
|    start` instead. | ||||
|    Apache isn't already running, you may need to run | ||||
|    `service apache2 start` instead. | ||||
|  | ||||
| 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. | ||||
| @@ -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 | ||||
| for whether they intend to create a new account or would like to login | ||||
| using another authentication method. You can configure automatic | ||||
| account creation on first login attempt by setting `"auto_signup": | ||||
| True` in the IdP configuration dictionary. | ||||
| account creation on first login attempt by setting | ||||
| `"auto_signup": True` in the IdP configuration dictionary. | ||||
|  | ||||
| The global setting `SOCIAL_AUTH_OIDC_FULL_NAME_VALIDATED` controls how | ||||
| 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 | ||||
|    installation and enable it (E.g. if you use Debian or Ubuntu, then | ||||
|    place it in `/etc/apache2/sites-available/zulip.example.com.conf` | ||||
|    and then run `a2ensite zulip.example.com && systemctl reload | ||||
|    apache2`): | ||||
|    and then run | ||||
|    `a2ensite zulip.example.com && systemctl reload apache2`): | ||||
|  | ||||
|     ```apache | ||||
|     <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: | ||||
|  | ||||
| 1. Log in to your Zulip server as the `zulip` user (or as `root` and | ||||
|   then run `su zulip` to drop privileges), and `cd | ||||
|   /home/zulip/deployments/current` | ||||
|   then run `su zulip` to drop privileges), and | ||||
|   `cd /home/zulip/deployments/current` | ||||
| 2. Run `./manage.py dbshell`.  This will open a shell connected to the | ||||
|   PostgreSQL database. | ||||
| 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! | ||||
|  | ||||
| The link is a secure one-time-use link.  If you need another | ||||
| later, you can generate a new one by running `manage.py | ||||
| generate_realm_creation_link` on the server.  See also our doc on | ||||
| running [multiple organizations on the same server](multiple-organizations.md) | ||||
| if that's what you're planning to do. | ||||
| later, you can generate a new one by running | ||||
| `manage.py generate_realm_creation_link` on the server.  See also our | ||||
| doc on running [multiple organizations on the same | ||||
| server](multiple-organizations.md) if that's what you're planning to | ||||
| do. | ||||
|  | ||||
| ## 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 | ||||
|   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 | ||||
|   of users.  The `--help` documents how to run it from a `manage.py | ||||
|   shell` for use with more complex programmatically computed sets of | ||||
|   users. | ||||
|   of users.  The `--help` documents how to run it from a | ||||
|   `manage.py shell` for use with more complex programmatically | ||||
|   computed sets of users. | ||||
| * `./manage.py send_password_reset_email`: Sends password reset email(s) | ||||
|   to one or more users. | ||||
| * `./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: | ||||
|  | ||||
| 1. Uncomment the `PUSH_NOTIFICATION_BOUNCER_URL = | ||||
|    'https://push.zulipchat.com'` line in your `/etc/zulip/settings.py` | ||||
|    file (i.e. remove the `#` at the start of the line), and | ||||
|    [restart your Zulip server](../production/settings.html#making-changes). | ||||
|    If you 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. Uncomment the | ||||
|    `PUSH_NOTIFICATION_BOUNCER_URL = 'https://push.zulipchat.com'` line | ||||
|    in your `/etc/zulip/settings.py` file (i.e. remove the `#` at the | ||||
|    start of the line), and [restart your Zulip | ||||
|    server](../production/settings.html#making-changes).  If you | ||||
|    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 | ||||
|     registration command: | ||||
| @@ -82,9 +83,9 @@ in the installer).  You can update your server's registration data by | ||||
| running `manage.py register_server` again. | ||||
|  | ||||
| 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 | ||||
| --rotate-key` option; it will automatically generate a new | ||||
| `zulip_org_key` and store that new key in | ||||
| (`zulip_org_key`), you need to use | ||||
| `manage.py register_server --rotate-key` option; it will automatically | ||||
| generate a new `zulip_org_key` and store that new key in | ||||
| `/etc/zulip/zulip-secrets.conf`. | ||||
|  | ||||
| ## Why this is necessary | ||||
|   | ||||
| @@ -46,9 +46,9 @@ things: | ||||
|   [the notes on `SOCIAL_AUTH_SUBDOMAIN` below](#authentication). | ||||
|  | ||||
| For servers hosting a large number of organizations, like | ||||
| [zulip.com](https://zulip.com), one can set `ROOT_DOMAIN_LANDING_PAGE | ||||
| = True` in `/etc/zulip/settings.py` so that the homepage for the | ||||
| server is a copy of the Zulip homepage. | ||||
| [zulip.com](https://zulip.com), one can set | ||||
| `ROOT_DOMAIN_LANDING_PAGE = True` in `/etc/zulip/settings.py` so that | ||||
| the homepage for the server is a copy of the Zulip homepage. | ||||
|  | ||||
| ### 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 | ||||
| complete query, which can be valuable in debugging. | ||||
|  | ||||
| To stop a runaway query, you can run `SELECT pg_cancel_backend(pid | ||||
| int)` or `SELECT pg_terminate_backend(pid int)` as the 'postgres' | ||||
| user. The former cancels the backend's current query and the latter | ||||
| terminates the backend process. They are implemented by sending SIGINT | ||||
| and SIGTERM to the processes, respectively.  We recommend against | ||||
| sending a PostgreSQL process SIGKILL. Doing so will cause the database | ||||
| to kill all current connections, roll back any pending transactions, | ||||
| and enter recovery mode. | ||||
| To stop a runaway query, you can run | ||||
| `SELECT pg_cancel_backend(pid int)` or | ||||
| `SELECT pg_terminate_backend(pid int)` as the 'postgres' user. The | ||||
| former cancels the backend's current query and the latter terminates | ||||
| the backend process. They are implemented by sending SIGINT and | ||||
| SIGTERM to the processes, respectively.  We recommend against sending | ||||
| a PostgreSQL process SIGKILL. Doing so will cause the database to kill | ||||
| all current connections, roll back any pending transactions, and enter | ||||
| recovery mode. | ||||
|  | ||||
| #### Stopping the Zulip PostgreSQL database | ||||
|  | ||||
|   | ||||
| @@ -38,9 +38,10 @@ Two good tests include: | ||||
|  | ||||
| * Alternatively, run a command like `curl -SsI https://zulip.example.com` | ||||
|   (using your server's URL) from a machine that can reach your server. | ||||
|   Make sure that on the same machine, `curl -SsI | ||||
|   https://incomplete-chain.badssl.com` gives an error; `curl` on some | ||||
|   machines, including Macs, will accept incomplete chains. | ||||
|   Make sure that on the same machine, | ||||
|   `curl -SsI https://incomplete-chain.badssl.com` gives an error; | ||||
|   `curl` on some machines, including Macs, will accept incomplete | ||||
|   chains. | ||||
|  | ||||
| [ssllabs-tester]: https://www.ssllabs.com/ssltest/analyze.html | ||||
|  | ||||
|   | ||||
| @@ -256,8 +256,8 @@ Database monitoring: | ||||
|  | ||||
| Standard server monitoring: | ||||
|  | ||||
| * `check_debian_packages`: Checks whether the system is behind on `apt | ||||
|   upgrade`. | ||||
| * `check_debian_packages`: Checks whether the system is behind on | ||||
|   `apt upgrade`. | ||||
|  | ||||
| If you're using these plugins, bug reports and pull requests to make | ||||
| 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 | ||||
|    `/etc/nginx/sites-available/zulip-enterprise` to comment out the | ||||
|    `nginx` configuration block for `/user_avatars` and the `include | ||||
|    /etc/nginx/zulip-include/uploads.route` line and then reload the | ||||
|    `nginx` service (`service nginx reload`). | ||||
|    `nginx` configuration block for `/user_avatars` and the | ||||
|    `include /etc/nginx/zulip-include/uploads.route` line and then | ||||
|    reload the `nginx` service (`service nginx reload`). | ||||
|  | ||||
| 1. Finally, restart the Zulip server so that your settings changes | ||||
|    take effect | ||||
|   | ||||
| @@ -137,11 +137,11 @@ system: | ||||
| - Tests for the backend views code logic for extracting data from the | ||||
|   database and serving it to clients. | ||||
|  | ||||
| For manual backend testing, it sometimes can be valuable to use `./manage.py | ||||
| dbshell` to inspect the tables manually to check that things look right; but | ||||
| usually anything you feel the need to check manually, you should add some | ||||
| sort of assertion for to the backend analytics tests, to make sure it stays | ||||
| that way as we refactor. | ||||
| For manual backend testing, it sometimes can be valuable to use | ||||
| `./manage.py dbshell` to inspect the tables manually to check that | ||||
| things look right; but usually anything you feel the need to check | ||||
| manually, you should add some sort of assertion for to the backend | ||||
| analytics tests, to make sure it stays that way as we refactor. | ||||
|  | ||||
| ## 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 | ||||
| a version of the `require()` function to the development environment | ||||
| browser console for this purpose.  For example, you can access our | ||||
| `people` module by evaluating `people = | ||||
| require("./static/js/people")`, or the third-party `lodash` module | ||||
| with `_ = require("lodash")`.  This mechanism is **not** a stable API | ||||
| and should not be used for any purpose other than interactive | ||||
| debugging. | ||||
| `people` module by evaluating | ||||
| `people = require("./static/js/people")`, or the third-party `lodash` | ||||
| module with `_ = require("lodash")`.  This mechanism is **not** a | ||||
| stable API and should not be used for any purpose other than | ||||
| interactive debugging. | ||||
|  | ||||
| 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 | ||||
|   | ||||
| @@ -131,8 +131,8 @@ new feature hard to miss. | ||||
| * 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 | ||||
|   one can see cases where exceptions chained together.  You can print | ||||
|   this log from the browser console using `blueslip = | ||||
|   require("./static/js/blueslip"); blueslip.get_log()`. | ||||
|   this log from the browser console using | ||||
|   `blueslip = require("./static/js/blueslip"); blueslip.get_log()`. | ||||
|  | ||||
| Blueslip supports several error levels: | ||||
| * `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 | ||||
| important for scalability: those with extremely high request volumes, | ||||
| and those with moderately high request volumes that are also | ||||
| expensive.  It doesn't matter how expensive, for example, `POST | ||||
| /users/me/subscriptions` is for scalability, because the volume is | ||||
| negligible. | ||||
| expensive.  It doesn't matter how expensive, for example, | ||||
| `POST /users/me/subscriptions` is for scalability, because the volume | ||||
| is negligible. | ||||
|  | ||||
| ### Tornado | ||||
|  | ||||
| Zulip's Tornado-based [real-time push | ||||
| system](../subsystems/events-system.md), and in particular `GET | ||||
| /events`, accounts for something like 50% of all HTTP requests to a | ||||
| production Zulip server.  Despite `GET /events` being extremely | ||||
| system](../subsystems/events-system.md), and in particular | ||||
| `GET /events`, accounts for something like 50% of all HTTP requests to | ||||
| a production Zulip server.  Despite `GET /events` being extremely | ||||
| high-volume, the typical request takes 1-3ms to process, and doesn't | ||||
| use the database at all (though it will access `memcached` and | ||||
| `redis`), so they aren't a huge contributor to the overall CPU usage | ||||
| @@ -228,10 +228,10 @@ of active optimization work. | ||||
|  | ||||
| ### Fetching message history | ||||
|  | ||||
| Bulk requests for message content and metadata ([`GET | ||||
| /messages`](https://zulip.com/api/get-messages)) account for ~3% of | ||||
| total HTTP requests.  The zulip web app has a few major reasons it does | ||||
| a large number of these requests: | ||||
| Bulk requests for message content and metadata | ||||
| ([`GET /messages`](https://zulip.com/api/get-messages)) account for | ||||
| ~3% of total HTTP requests.  The zulip web app has a few major reasons | ||||
| it does a large number of these requests: | ||||
|  | ||||
| * Most of these requests are from users clicking into different views | ||||
|   -- 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 | ||||
|  | ||||
| In a Zulip development environment, you can use `manage.py | ||||
| mark_all_messages_unread` to set every user's pointer to 0 and all | ||||
| messages as unread, for convenience in testing unread count related | ||||
| logic. | ||||
| In a Zulip development environment, you can use | ||||
| `manage.py mark_all_messages_unread` to set every user's pointer to 0 | ||||
| and all messages as unread, for convenience in testing unread count | ||||
| related logic. | ||||
|  | ||||
| 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 | ||||
|   | ||||
| @@ -41,8 +41,8 @@ To add a new queue processor: | ||||
|   queue worker in the Zulip development environment | ||||
|   (`tools/run-dev.py` will automatically restart the queue processors | ||||
|   and start running your new queue processor code).  You can also run | ||||
|   a single queue processor manually using e.g. `./manage.py | ||||
|   process_queue --queue=user_activity`. | ||||
|   a single queue processor manually using e.g. | ||||
|   `./manage.py process_queue --queue=user_activity`. | ||||
|  | ||||
| * So that supervisord will know to run the queue processor in | ||||
|   production, you will need to add to the `queues` variable in | ||||
|   | ||||
| @@ -22,19 +22,19 @@ migrations. | ||||
|   * Commit your changes. | ||||
| * 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 | ||||
|   understand how to write them well.  `git grep RunPython | ||||
|   zerver/migrations/02*` will find many good examples.  Before writing | ||||
|   migrations of this form, you should read Django's docs and the | ||||
|   sections below. | ||||
|   understand how to write them well. | ||||
|   `git grep RunPython zerver/migrations/02*` will find many good | ||||
|   examples.  Before writing migrations of this form, you should read | ||||
|   Django's docs and the sections below. | ||||
| * **Numbering conflicts across branches**: If you've done your schema | ||||
|   change in a branch, and meanwhile another schema change has taken | ||||
|   place, Django will now have two migrations with the same | ||||
|   number. There are two easy way to fix this: | ||||
|   * If your migrations were automatically generated using `manage.py | ||||
|     makemigrations`, a good option is to just remove your migration | ||||
|     and rerun the command after rebasing.  Remember to `git rebase` to | ||||
|     do this in the the commit that changed `models.py` if you have a | ||||
|     multi-commit branch. | ||||
|   * If your migrations were automatically generated using | ||||
|     `manage.py makemigrations`, a good option is to just remove your | ||||
|     migration and rerun the command after rebasing.  Remember to | ||||
|     `git rebase` to do this in the the commit that changed `models.py` | ||||
|     if you have a multi-commit branch. | ||||
|   * If you wrote code as part of preparing your migrations, or prefer | ||||
|     this workflow, you can use run `./tools/renumber-migrations`, | ||||
|     which renumbers your migration(s) and fixes up the "dependencies" | ||||
|   | ||||
| @@ -138,9 +138,9 @@ want those settings. | ||||
|  | ||||
| ### Testing non-default settings | ||||
|  | ||||
| You can write tests for settings using e.g. `with | ||||
| self.settings(TERMS_OF_SERVICE=None)`.  However, this only works for | ||||
| settings which are checked at runtime, not settings which are only | ||||
| You can write tests for settings using e.g. | ||||
| `with self.settings(TERMS_OF_SERVICE=None)`.  However, this only works | ||||
| for settings which are checked at runtime, not settings which are only | ||||
| accessed in initialization of Django (or Zulip) internals | ||||
| (e.g. `DATABASES`).  See the [Django docs on overriding settings in | ||||
| tests][django-test-settings] for more details. | ||||
|   | ||||
| @@ -27,10 +27,10 @@ run to iteratively debug something. | ||||
| ### Useful debugging tips and tools | ||||
|  | ||||
| * GitHub Actions stores timestamps for every line in the logs. They | ||||
| are hidden by default; you can see them by toggling the `Show | ||||
| timestamps` option in the menu on any job's log page.  (You can get | ||||
| this sort of timestamp in a development environment by piping output | ||||
| to `ts`). | ||||
| are hidden by default; you can see them by toggling the | ||||
| `Show timestamps` option in the menu on any job's log page.  (You can | ||||
| get this sort of timestamp in a development environment by piping | ||||
| output to `ts`). | ||||
|  | ||||
| * GitHub Actions runs on every branch you push on your Zulip fork. | ||||
| 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 | ||||
| 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 | ||||
| Vagrant guest), you can do that with `pip install -r | ||||
| requirements/mypy.txt`. | ||||
| Vagrant guest), you can do that with | ||||
| `pip install -r requirements/mypy.txt`. | ||||
|  | ||||
| ## Running mypy on Zulip's code locally | ||||
|  | ||||
| @@ -277,8 +277,8 @@ alternatives first: | ||||
|   single site, you may want a [**`Union` | ||||
|   type**](https://mypy.readthedocs.io/en/stable/kinds_of_types.html#union-types). | ||||
|   `Union` is checked: before using `value: Union[str, int]` as a | ||||
|   `str`, mypy requires that you validate it with an `instance(value, | ||||
|   str)` test. | ||||
|   `str`, mypy requires that you validate it with an | ||||
|   `instance(value, str)` test. | ||||
|  | ||||
| * 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 | ||||
| @@ -325,8 +325,8 @@ Instead of using `cast`: | ||||
|  | ||||
| ### Avoid `# type: ignore` comments | ||||
|  | ||||
| Mypy allows you to ignore any type checking error with a [`# type: | ||||
| ignore` | ||||
| Mypy allows you to ignore any type checking error with a | ||||
| [`# type: ignore` | ||||
| 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 | ||||
| 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 | ||||
|   non-`Optional` with default `[]`. | ||||
|  | ||||
| Don't test an `Optional` value using truthiness (`if value:`, `not | ||||
| value`, `value or default_value`), especially when the type might have | ||||
| falsy values other than `None`. | ||||
| Don't test an `Optional` value using truthiness (`if value:`, | ||||
| `not value`, `value or default_value`), especially when the type might | ||||
| have falsy values other than `None`. | ||||
|  | ||||
| ```python | ||||
| s: Optional[str] | ||||
| @@ -491,8 +491,8 @@ def f(s: str) -> str: | ||||
|     return s | ||||
| ``` | ||||
|  | ||||
| (A generic decorator with an argument would return `Callable[[FuncT], | ||||
| FuncT]`.) | ||||
| (A generic decorator with an argument would return | ||||
| `Callable[[FuncT], FuncT]`.) | ||||
|  | ||||
| But Mypy doesn't yet support the advanced type annotations that would | ||||
| 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 | ||||
| arguments will not run webhook integration tests (`zerver/webhooks/`), | ||||
| which would otherwise account for about 25% of the total runtime. | ||||
| When working on webhooks, we recommend instead running `test-backend | ||||
| zerver/webhooks` manually (or better, the direction for the specific | ||||
| webhooks you're working on).  And of course our CI is configured to | ||||
| always use `test-backend --include-webhooks` and run all of the tests. | ||||
| When working on webhooks, we recommend instead running | ||||
| `test-backend zerver/webhooks` manually (or better, the direction for | ||||
| the specific webhooks you're working on).  And of course our CI is | ||||
| configured to always use `test-backend --include-webhooks` and run all | ||||
| of the tests. | ||||
|  | ||||
| ## Writing tests | ||||
|  | ||||
| @@ -483,8 +484,8 @@ is exposed in your development environment). | ||||
| the console; use `with self.assertLogs` to capture and verify any | ||||
| logging output.  Note that we reconfigure various loggers in | ||||
| `zproject/test_extra_settings.py` where the output is unlikely to be | ||||
| interesting when running our test suite.  `test-backend | ||||
| --ban-console-output` checks for stray print statements. | ||||
| interesting when running our test suite. | ||||
| `test-backend --ban-console-output` checks for stray print statements. | ||||
|  | ||||
| Note that `test-backend --coverage` will assert that | ||||
| 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 | ||||
|    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 | ||||
|       click on the little plus in the bottom left of the `Node.js | ||||
|       Interpreters` window. | ||||
|       click on the little plus in the bottom left of the | ||||
|       `Node.js Interpreters` window. | ||||
|     1. Select `Add Remote...`. | ||||
|         1. In the `Configure Node.js Remote Interpreter`, window select `Vagrant` | ||||
|         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 | ||||
|   interact with it.  The [puppeteer docs site](https://pptr.dev/) is a | ||||
|   useful reference for the available wait functions. | ||||
| - When using `waitForSelector`, you always want to use the `{visible: | ||||
|   true}` option; otherwise the test will stop waiting as soon as the | ||||
|   target selector is present in the DOM even if it's hidden.  For the | ||||
|   common UI pattern of having an element always be present in the DOM | ||||
|   whose presence is managed via show/hide rather than adding/removing | ||||
|   it from the DOM, `waitForSelector` without `visible: true` won't | ||||
|   wait at all. | ||||
| - When using `waitForSelector`, you always want to use the | ||||
|   `{visible: true}` option; otherwise the test will stop waiting as | ||||
|   soon as the target selector is present in the DOM even if it's | ||||
|   hidden.  For the common UI pattern of having an element always be | ||||
|   present in the DOM whose presence is managed via show/hide rather | ||||
|   than adding/removing it from the DOM, `waitForSelector` without | ||||
|   `visible: true` won't wait at all. | ||||
| - The test suite uses a smaller set of default user accounts and other | ||||
|   data initialized in the database than the normal development | ||||
|   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 | ||||
|   can scan for these using [TinglingGit](https://github.com/zulip/TinglingGit). | ||||
| * Have good unit test coverage, which limits the risk of breaking | ||||
|   correctness through refactoring.  Use `tools/test-js-with-node | ||||
|   --coverage` to get a coverage report. | ||||
|   correctness through refactoring.  Use | ||||
|   `tools/test-js-with-node --coverage` to get a coverage report. | ||||
|  | ||||
| When migrating a module, we want to be especially thoughtful about | ||||
| 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 | ||||
|    this). | ||||
|  | ||||
| 2. Translation resource files are created using the `./manage.py | ||||
|    makemessages` command. This command will create, for each language, | ||||
|    a resource file called `translations.json` for the frontend strings | ||||
|    and `django.po` for the backend strings. | ||||
| 2. Translation resource files are created using the | ||||
|    `./manage.py makemessages` command. This command will create, for | ||||
|    each language, a resource file called `translations.json` for the | ||||
|    frontend strings and `django.po` for the backend strings. | ||||
|  | ||||
|    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 | ||||
|   keyword argument. | ||||
|  | ||||
| * `streams_raw = REQ("subscriptions", | ||||
|   json_validator=check_list(check_string))` will check that the | ||||
|   "subscriptions" HTTP parameter is a list of strings, marshalled as | ||||
|   JSON, and pass it into the function with the Python keyword argument | ||||
|   `streams_raw`. | ||||
| * `streams_raw = REQ("subscriptions", json_validator=check_list(check_string))` | ||||
|   will check that the "subscriptions" HTTP parameter is a list of | ||||
|   strings, marshalled as JSON, and pass it into the function with the | ||||
|   Python keyword argument `streams_raw`. | ||||
|  | ||||
| * `message_id=REQ(converter=to_non_negative_int)` will check that the | ||||
|   `message_id` HTTP parameter is a string containing a non-negative | ||||
|   | ||||
| @@ -138,8 +138,8 @@ Rough steps: | ||||
|    and shut down the droplet. | ||||
| 1. Go to the Images tab on DigitalOcean, and "Take a Snapshot". | ||||
| 1. Wait for several minutes. | ||||
| 1. Do something like `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` | ||||
| 1. Do something like | ||||
|    `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). | ||||
| 1. Replace `template_id` in `create.py` in this directory with the | ||||
|    appropriate `id`. | ||||
| @@ -181,8 +181,8 @@ Rough steps: | ||||
| 1. `> ~/.bash_history && history -c && sudo shutdown -h now` | ||||
| 1. Go to the Images tab on DigitalOcean, and "Take a Snapshot". | ||||
| 1. Wait for several minutes. | ||||
| 1. Do something like `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` | ||||
| 1. Do something like | ||||
|    `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). | ||||
| 1. Replace `template_id` in `create.py` in this directory with the | ||||
|    appropriate `id`. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user