snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-15 15:05:30 +05:00
commit 64898b2c79
8999 changed files with 1757358 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
# Asking great questions
A well-formed question helps you learn, respects the person answering, and makes
efficient use of time for everyone involved. Asking the right question, to the
right person, in the right way, at the right time, is a skill that requires a
lifetime of fine-tuning. This page offers some guidelines and resources the
[Zulip community](https://zulip.com/development-community/) has found helpful in this pursuit.
## Where to ask your question
It is almost always best to ask questions and have a conversation in a public
channel, rather than in direct messages. You’ll get better and faster answers
since many people can help, and it makes it possible for others to benefit from
the discussion.
The [Zulip community
guide](https://zulip.com/development-community/#where-do-i-send-my-message)
offers guidelines on how the major public channels in the community are used.
Don’t stress too much about picking the right place if you’re not sure, as
moderators can [move your question thread to a different
channel](https://zulip.com/help/move-content-to-another-channel) if needed.
## How to ask a great question
Spending some extra time and effort to carefully formulate your question is well
worthwhile, as it makes it much more likely that you'll get the information you
need to move forward. There are a few wonderfully thoughtful blog posts that
explain what it means to ask a good question:
- [Try, Then Ask](https://www.mattringel.com/2013/09/30/you-must-try-and-then-you-must-ask/)
- [We Aren’t Just Making Code, We’re Making History](https://www.harihareswara.net/sumana/2016/10/12/0)
- [How to Ask Good Questions](https://jvns.ca/blog/good-questions/)
In brief, to formulate a great question, you should:
- Try to solve your own problem first, including reading through relevant
documentation and code.
- Identify the precise point on which you feel stuck.
- Formulate a clear question that includes an appropriate amount of context
and a specific request for help.
When your question is answered, follow through on the advice you receive, and (when
appropriate) summarize the resolution of your problem so that others can learn
from your experience.
## Follow the community guidelines
As always, be sure to follow the [Zulip community
norms](https://zulip.com/development-community/). In particular, check out [the
section on getting help](https://zulip.com/development-community/#getting-help)
before you post.

View File

@@ -0,0 +1,429 @@
# Reviewing Zulip code
Code review is a key part of how Zulip does development. It's an essential
aspect of our process to build a high-quality product with a maintainable
codebase. See the [pull request review process](../contributing/review-process.md)
guide for a detailed overview of Zulip's PR review process.
## Principles of code review
Zulip has an active contributor community, and just a small handful
of maintainers who can do the final rounds of code review. As such, we would
love for contributors to help each other with making pull requests that are not
only correct, but easy to review. Doing so ensures that PRs can be finalized and
merged more quickly, and accelerates the pace of progress for the entire
project.
If you're new to open source, this may be the first time you do a code review of
anyone's changes! We have therefore written this step-by-step guide to be
accessible to all Zulip contributors.
### Reviewing your own code
One of the best ways to improve the quality of your own work as a software
engineer is to do a code review of your own work before submitting it to others for
review. We thus strongly encourage you to get into the habit of reviewing your
own code. You can often find things you missed by taking a step back to look
over your work before asking others to do so, and this guide will walk you
through the process. Catching mistakes yourself will help your PRs be merged
faster, and folks will appreciate the quality and professionalism of your
work.
### Reviewing other contributors' code
Doing code reviews is a valuable contribution to the Zulip project.
It's also an important skill to develop for participating in
open-source projects and working in the industry in general. If
you're contributing to Zulip and have been working in our code for a
little while, we would love for you to start doing code reviews!
Anyone can do a code review -- you don't have to have a ton of experience, and
you don't have to have the power to ultimately merge the PR. The sections below
offer accessible, step-by-step guidance for how to go about reviewing Zulip PRs.
For students participating in Google Summer of Code or a similar
program, we expect you to spend a chunk of your time each week (after
the first couple of weeks as you're getting going) doing code reviews.
## How to review code
Whether you are reviewing your own code or somebody else's, this section
describes how to go about it.
If you are reviewing somebody else's code, you will likely need to first fetch
it so that you can play around with the new functionality. If you're working in
the Zulip server codebase, use our [Git tool][git-tool]
`tools/fetch-rebase-pull-request` to check out a pull request locally and rebase
it onto `main`.
### Code review checklist
The following review steps apply to the majority of PRs.
**Think about the issue:**
1. Start by **rereading the issue** the PR is intended to solve. Are you
confident that you **understand everything the issue is asking for**? If not,
try exploring the relevant parts of the Zulip app and reading any linked
discussions on the [development community server][czo] to see if the
additional context helps. If any part is still confusing, post a GitHub
comment or a message on the [development community server][czo] explaining
precisely what points you find confusing.
2. Now that you're confident that you understand the issue, **does the PR
address all the points described in the issue**? If not, is it easy to tell
without reading the code which points are not addressed and why? Here is a
handful of good ways for the author to communicate why the issue as written
might not be fully solved by the PR:
- The issue explicitly notes that it's fine for some parts to be completed
separately, and the PR clearly indicates which parts are solved.
- After discussion of initial prototypes (in GitHub comments or on the
[development community server][czo]), it was decided to change some part of
the specification, and the PR notes this.
- The author explains why the PR is a better way to solve the issue than what
was described.
- The solution changed because of changes in the project or application since
the issue was written, and the author explains the adjustments that were
made.
**Think about the code:**
1. Make sure the PR uses **clear function, argument, variable, and test names.**
Every new piece of Zulip code will be read many times by other developers, and
future developers will `grep` for relevant terms when researching a problem, so
it's important that variable names communicate clearly the purpose of each
piece of the codebase.
1. Make sure the PR **avoids duplicated code.** Code duplication is a huge
source of bugs in large projects and makes the codebase difficult to
understand, so we avoid significant code duplication wherever possible.
Sometimes avoiding code duplication involves some refactoring of existing
code; if so, that should usually be done as its own series of commits (not
squashed into other changes or left as a thing to do later). That series of
commits can be in the same pull request as the feature that they support, and
we recommend ordering the history of commits so that the refactoring comes
_before_ the feature. That way, it's easy to merge the refactoring (and
minimize risk of merge conflicts) if there are still user experience issues
under discussion for the feature itself.
1. **Good comments** help. It's often worth thinking about whether explanation
in a commit message or pull request discussion should be included in
a comment, `/docs`, or other documentation. But it's better yet if
verbose explanation isn't needed. We prefer writing code that is
readable without explanation over a heavily commented codebase using
lots of clever tricks.
1. Make sure the PR follows Zulip's **coding style**. See the Zulip [coding
style documentation][code-style] for details. Our goal is to have as much of
this as possible verified via the linters and tests, but there will always be
unusual forms of Python/JavaScript style that our tools don't check for.
1. If you can, step back and think about the **technical design**. There are a
lot of considerations here: security, migration paths/backwards compatibility,
cost of new dependencies, interactions with features, speed of performance,
API changes. Security is especially important and worth thinking about
carefully with any changes to security-sensitive code like views.
**Think about testing:**
1. **The CI build tests need to pass.** One can investigate
any failures and figure out what to fix by clicking on a red X next
to the commit hash or the Detail links on a pull request. (Example:
in [#17584](https://github.com/zulip/zulip/pull/17584),
click the red X before `49b10a3` to see the build jobs
for that commit. You can see that there are 7 build jobs in total.
All the 7 jobs run in GitHub Actions. You can see what caused
the job to fail by clicking on the failed job. This will open
up a page in the CI that has more details on why the job failed.
For example [this](https://github.com/zulip/zulip/actions/runs/15362225042/job/43230810881)
is the page of an "Ubuntu 22.04 (Python 3.10, backend + frontend)" job.
See our docs on [continuous integration](../testing/continuous-integration.md)
to learn more.
2. Make sure **the code is well-tested**; see below for details. The PR should
summarize any [manual testing](#manual-testing) that was done to validate
that the feature is working as expected.
**Think about the commits:**
1. Does the PR follow the principle that “**Each commit is a minimal coherent
idea**”? See the [commit discipline guide][commit-discipline] to learn more
about commit structure in Zulip.
2. Does each commit have a **clear commit message**? Check for content, format,
spelling and grammar. See the [Zulip commit discipline][commit-messages]
documentation for details on what we look for.
You should also go through any of the following checks that are applicable:
- _Error handling._ The code should always check for invalid user
input. User-facing error messages should be clear and when possible
be actionable (it should be obvious to the user what they need to do
in order to correct the problem).
- _Translation._ Make sure that the strings are marked for
[translation].
- _Completeness of refactoring._ When reviewing a refactor, verify that the changes are
complete. Usually, one can check that efficiently using `git grep`,
and it's worth it, as we very frequently find issues by doing so.
- _Documentation updates._ If this changes how something works, does it
update the documentation in a corresponding way? If it's a new
feature, is it documented, and documented in the right place?
- _mypy annotations in Python code._ New functions should be annotated using
[mypy] and existing annotations should be updated. Use of `Any`, `ignore`, and
unparameterized containers should be limited to cases where a more precise
type cannot be specified.
### Automated testing
- The tests should **validate that the feature works correctly**, and
specifically test for common error conditions, bad user input, and potential
bugs that are likely for the type of change being made. Tests that exclude
whole classes of potential bugs are preferred when possible (e.g., the common
test suite `test_markdown.py` between the Zulip server's [frontend and backend
Markdown processors](../subsystems/markdown.md), or the `GetEventsTest` test
for buggy race condition handling). See the [test writing][test-writing]
documentation to learn more.
- We are trying to maintain ~100% test coverage on the backend, so backend
changes should have negative tests for the various error conditions. See
[backend testing documentation][backend-testing] for details.
- If the feature involves frontend changes, there should be frontend tests. See
[frontend testing documentation][frontend-testing] for details.
### Manual testing
If the PR makes any user-facing changes, make sure to play with the part
of the app being changed to validate that things look and work as expected.
While not all of the situations below will apply, here are some ideas for things
that should be tested if they are applicable. Use the [development
environment][development-environment] to test any web app changes.
This might seem like a long process, but you can go through it quite quickly
once you get the hang of it. Trust us, it will save time and review round-trips
down the line!
Testing a PR is a great opportunity to discover pre-existing bugs or usability
issues. Please verify that the issue you observed is pre-existing by replicating
the behavior on `main`, and [report it](./reporting-bugs.md)!
Describe the manual testing you did in the PR description (for your own work),
or in a comment (as a reviewer), so that the next reviewer knows how thoroughly
the changes were exercised, and can catch any testing gaps.
**Visual appearance:**
- Open up the parts of the UI that were changed, and make sure they look as
you were expecting.
- Is the new UI consistent with similar UI elements? Think about fonts, colors,
sizes, etc. If a new or modified element has multiple states (e.g., "on" and
"off"), consider all of them.
- Is the new UI aligned correctly with the elements around it, both vertically and
horizontally?
- If the PR adds or modifies a clickable element, does it have a hover behavior
that's consistent with similar UI elements?
- If the PR adds or modifies an element (e.g., a button or checkbox) that is
sometimes disabled, is the disabled version of the UI consistent with similar
UI elements?
- Did the PR accidentally affect any other parts of the UI? E.g., if the PR
modifies some CSS, look for other elements that may have been altered
unintentionally. Are you using a shared function or component? Use `git grep`
to see if the code you modified is being used elsewhere. Compare carefully
with the state in `main` to make sure you haven't introduced any incidental
changes.
- Now check all of the above in the other theme (light/dark).
- Now check all of the above at small and large [font
sizes](https://zulip.com/help/font-size).
**Responsiveness and internationalization:**
- Check the new UI at different window sizes, including mobile sizes (you can
use Chrome DevTools if you like). Does it look good in both wide and narrow
windows?
- To simulate what will happen when the UI is translated to different languages,
try changing any new strings, or ones that are now displayed differently, to
make them 1.5x longer, and check if anything breaks. What would happen if the
strings were half as long as in English?
- Are any [plurals and
lists](../translating/internationalization.md#plurals-and-lists)
internationalized correctly?
**Strings (text):**
If the PR adds or modifies strings, check the following:
- Does the wording seem consistent with similar features (similar style, level
of detail, etc.)?
- Are strings appropriate in all situations (e.g., user vs. admin, other users
vs. yourself)?
**Tooltips:**
- Do elements that require tooltips have them? Check similar elements to see
whether a tooltip is needed, and what information it should contain.
**Functionality:**
We're finally getting to the part where you actually use the new/updated
feature. :) Test to see if it works as expected, trying a variety of scenarios.
If it works as described in the issue but seems awkward in some way, note this
on the PR.
If relevant, be sure to check that:
- Live updates are working as expected, in all the places that should be updated.
- Keyboard navigation, including tabbing to the interactive elements, is working
as expected.
Some scenarios to consider:
- Try clicking on any interactive elements, multiple times, in a variety of orders.
- If the feature affects the **message view**, try it out in different types of
narrows: topic, channel, Combined feed, direct messages.
- If the feature affects the **compose box** in the web app, try both ways of
[resizing the compose box](https://zulip.com/help/resize-the-compose-box).
Test both channel messages and direct messages.
- If the feature might require **elevated permissions**, check it out as a user who has
permissions to use it and one who does not.
- If the feature takes user input, check input edge cases (e.g., empty, invalid,
or very long).
- Think about how the feature might **interact with other features**, and try out
such scenarios. For example:
- If the PR adds a banner, is it possible that it would be shown at the same
time as other banners? Does something reasonable happen?
- If the feature has to do with topic editing, do you need to think
about what happens when a topic is resolved/unresolved?
- If it's a message view feature, would anything go wrong if the message was
collapsed or muted? If it was colored like an `@`-mention or a direct message?
**Logged out view:** When appropriate, test as a logged out user. For example,
was a new message menu item correctly added or skipped? If the item was skipped,
did your changes introduce an extraneous separator in the menu?
## Review process and communication
### Asking for a code review
The [pull request review process](../contributing/review-process.md) guide
provides a detailed overview of Zulip's PR review process. Your reviewers and
Zulip's maintainers will help shepherd your PR through the process. There are
also some additional ways to ask for a code review:
- Are there folks who have been working on similar things, or a loosely related
area? If so, they might be a good person to review your PR. `@`-mention them
with something like "`@person`, would you be up for reviewing this?" If
you're not sure whether they are familiar with how Zulip code reviews work, you
can also include a link to this guide.
- If you're not sure who to ask, you can post a message in
[#code-review](https://chat.zulip.org/#narrow/channel/91-code-review) on [the Zulip
development community server](https://zulip.com/development-community/) to reach
out to a wider group of potential reviewers.
Please be patient and mindful of the fact that it isn't always possible to
provide a quick reply. Going through the [review process](#how-to-review-code)
described above for your own PR will make your code easier and faster to review,
which makes it much more likely that it will be reviewed quickly and require
fewer review cycles.
### Reviewing someone else's code
#### Fast replies are key
For the author of a PR, getting feedback quickly is really important
for making progress quickly and staying productive. That means that
if you get @-mentioned on a PR with a request for you to review it,
it helps the author a lot if you reply promptly.
A reply doesn't even have to be a full review; if a PR is big or if
you're pressed for time, then just getting some kind of reply in
quickly -- initial thoughts, feedback on the general direction, or
just saying you're busy and when you'll have time to look harder -- is
still really valuable for the author and for anyone else who might
review the PR.
People in the Zulip project live and work in many time zones, and code
reviewers also need focused chunks of time to write code and do other
things, so an immediate reply isn't always possible. But a good
benchmark is to try to always reply **within one workday**, at least
with a short initial reply, if you're working regularly on Zulip. And
sooner is better.
#### Communication style
Any time you leave a code review, be sure to treat the author with respect.
Remember that they are generously spending their time on an effort to improve
the Zulip project. Thank them for their work, and express your appreciation for
anything the author did especially well, whether it's a nice commit message, a
prompt response to earlier feedback, or a well-written test.
Be as clear and direct as you can when describing requested changes. There is no
need to apologize when asking for a change; you're collaborating with the
author to make the PR as good as you can together.
Be sure to explain the motivation for the changes you're requesting if it's not
obvious, so that the author can learn for next time. It may be helpful to point
to developer documentation, such as the [commit discipline
guide][commit-discipline].
#### Fixing up the PR
If a pull request just needs a little fixing to make it mergeable,
feel free to do that in a new commit, then push your branch to GitHub
and mention the branch in a comment on the pull request. That'll save
the maintainer time and get the PR merged quicker.
### Responding to review feedback
Once you've received a review and resolved any feedback, it's critical
to update the GitHub thread to reflect that. Best practices are to:
- Make sure that CI passes and the PR is rebased onto recent `main`.
- Post comments on each feedback thread explaining at least how you
resolved the feedback, as well as any other useful information
(problems encountered, reasoning for why you picked one of several
options, a test you added to make sure the bug won't recur, etc.).
- Post a summary comment in the main feed for the PR, explaining that
this is ready for another review, and summarizing any changes from
the previous version, details on how you tested the changes, new
screenshots/etc. More detail is better than less, as long as you
take the time to write clearly.
If you resolve the feedback, but the PR has merge conflicts, CI
failures, or the most recent comment is the reviewer asking you to fix
something, it's very likely that a potential reviewer skimming your PR
will assume it isn't ready for review and move on to other work.
If you need help or think an open discussion topic requires more
feedback or a more complex discussion, move the discussion to a topic
in the [Zulip development community server][czo]. Be sure to provide links
from the GitHub PR to the conversation (and vice versa) so that it's
convenient to read both conversations together.
## Additional resources
We also recommend the following resources on code reviews.
- [The Gentle Art of Patch Review](https://sage.thesharps.us/2014/09/01/the-gentle-art-of-patch-review/)
article by Sarah Sharp
- [Zulip & Good Code Review](https://www.harihareswara.net/sumana/2016/05/17/0)
article by Sumana Harihareswara
- [Code Review - A consolidation of advice and stuff from the
internet](https://gist.github.com/porterjamesj/002fb27dd70df003646df46f15e898de)
article by James J. Porter
- [Zulip code of conduct](../code-of-conduct.md)
[code-style]: code-style.md
[commit-discipline]: commit-discipline.md
[commit-messages]: commit-discipline.md#commit-messages
[test-writing]: ../testing/testing.md
[backend-testing]: ../testing/testing-with-django.md
[frontend-testing]: ../testing/testing-with-node.md
[mypy]: ../testing/mypy.md
[git-tool]: ../git/zulip-tools.md#fetch-a-pull-request-and-rebase
[translation]: ../translating/translating.md
[czo]: https://zulip.com/development-community/
[development-environment]: ../development/overview.md

View File

@@ -0,0 +1,369 @@
# Code style and conventions
This page documents code style policies that every Zulip developer
should understand. We aim for this document to be short and focused
only on details that cannot be easily enforced in another way (e.g.,
through linters, automated tests, or subsystem design that makes classes
of mistakes unlikely). This approach minimizes the cognitive
load of ensuring a consistent coding style for both contributors and
maintainers.
One can summarize Zulip's coding philosophy as a relentless focus on
making the codebase easy to understand and difficult to make dangerous
mistakes in (see the sections on [dangerous constructs](#dangerous-constructs-in-django)
at the end of this page). The majority of work in any large software
development project is understanding the existing code so one can debug
or modify it, and investments in code readability usually end up paying
for themselves when someone inevitably needs to debug or improve the code.
When there's something subtle or complex to explain or ensure in the
implementation, we try hard to make it clear through a combination of
clean and intuitive interfaces, well-named variables and functions,
comments/docstrings, and commit messages (roughly in that order of
priority -- if you can make something clear with a good interface,
that's a lot better than writing a comment explaining how the bad
interface works).
After an introduction to our lint tools and test suites, this document
outlines some general
[conventions and practices](#follow-zulip-conventions-and-practices)
applicable to all languages used in the codebase, as well as specific
guidance on [Python](#python-specific-conventions-and-practices) and
[JavaScript and TypeScript](#javascript-and-typescript-conventions-and-practices).
([HTML and CSS](../subsystems/html-css.md) are outlined in their own
documentation.)
At the end of the document, you can read about
[dangerous constructs in Django](#dangerous-constructs-in-django) and
[JavaScript and TypeScript](#dangerous-constructs-in-javascript-and-typescript)
that you should absolutely avoid.
## Be consistent with existing code
Look at the surrounding code, or a similar part of the project, and try
to do the same thing. If you think the other code has actively bad
style, fix it (in a separate commit).
When in doubt, ask in
[#development help](https://chat.zulip.org/#narrow/channel/49-development-help).
### Use the linters
You can run all of the linters at once:
```bash
$ ./tools/lint
```
But, doing that will take a little time, because `./tools/lint`
runs many lint checks in parallel, including:
- JavaScript ([ESLint](https://eslint.org/),
[Prettier](https://prettier.io/))
- Python ([mypy](http://mypy-lang.org/),
[Ruff](https://docs.astral.sh/ruff/))
- templates
- Puppet configuration
- custom checks (e.g., trailing whitespace and spaces-not-tabs)
To speed things up, you can [pass specific files or directories
to the linter](../testing/linters.md):
```
$ ./tools/lint web/src/compose.ts
```
If you'd like, you can also set up a local Git commit hook that
will lint only your changed files each time you commit:
```bash
$ ./tools/setup-git-repo
```
### Use tests to verify your logic
Clear, readable code is important for [tests](../testing/testing.md);
familiarize yourself with our
[testing frameworks](../testing/testing.md#major-test-suites) and
[testing philosophy](../testing/philosophy.md) so that you can write
clean, readable tests. In-test comments about anything subtle that is
being verified are appreciated.
You can run all of the tests like this:
```
$ ./tools/test-all
```
But consult [our documentation on running tests](../testing/testing.md#running-tests),
which covers more targeted approaches to commanding the test-runners.
## Follow Zulip conventions and practices
What follows is language-neutral advice that is beyond the bounds of
linters and automated tests.
### Observe a reasonable line length
We have an absolute hard limit on line length only for some files, but
we should still avoid extremely long lines. A general guideline is:
refactor stuff to get it under 85 characters, unless that makes the
code a lot uglier, in which case it's fine to go up to 120 or so.
### Tag user-facing strings for translation
Remember to
[tag all user-facing strings for translation](../translating/translating.md),
whether the strings are in HTML templates or output by JavaScript/TypeScript
that injects or modifies HTML (e.g., error messages).
### Correctly prepare paths destined for state or log files
When writing out state or log files, always pass an absolute path
through `zulip_path` (found in `zproject/computed_settings.py`), which
will do the right thing in both development and production.
### Never include secrets inline with code
Please don't put any passwords, secret access keys, etc. inline in the
code. Instead, use the `get_secret` function or the `get_mandatory_secret`
function in `zproject/config.py` to read secrets from `/etc/zulip/secrets.conf`.
### Familiarize yourself with rules about third-party code
See [our docs on dependencies](../subsystems/dependencies.md) for discussion of
rules about integrating third-party projects.
## Python-specific conventions and practices
- Our Python code is formatted with
[Ruff](https://docs.astral.sh/ruff/). The [linter
tool](../testing/linters.md) enforces this by running Ruff in check
mode, or in write mode with
`tools/lint --only=ruff,ruff-format --fix`. You may find it helpful
to [integrate Ruff](https://docs.astral.sh/ruff/integrations/) with
your editor.
- Don't put a shebang line on a Python file unless it's meaningful to
run it as a script. (Some libraries can also be run as scripts, e.g.,
to run a test suite.)
- Scripts should be executed directly (`./script.py`), so that the
interpreter is implicitly found from the shebang line, rather than
explicitly overridden (`python script.py`).
- Put all imports together at the top of the file, absent a compelling
reason to do otherwise.
- Unpacking sequences doesn't require list brackets:
```python
[x, y] = xs # unnecessary
x, y = xs # better
```
- For string formatting, use `x % (y,)` rather than `x % y`, to avoid
ambiguity if `y` happens to be a tuple.
## JavaScript and TypeScript conventions and practices
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
editor](https://prettier.io/docs/en/editors.html).
### Build DOM elements in Handlebars
The best way to build complicated DOM elements is a Handlebars template
like `web/templates/message_reactions.hbs`. For simpler things you can
use jQuery DOM-building APIs like this:
```js
const $new_tr = $('<tr />').attr('id', object.id);
```
### Attach behaviors to event listeners
Attach callback functions to events using jQuery code. For example:
```js
$("body").on("click", ".move_message_button", function (e) {
// message-moving UI logic
}
```
That approach has multiple benefits:
- Potential huge performance gains by using delegated events where
possible
- When calling a function from an `onclick` attribute, `this` is not
bound to the element like you might think
- jQuery does event normalization
Do not use `onclick` attributes in the HTML.
### Declare variables using `const` and `let`
Always declare JavaScript variables using `const` or `let` rather than
`var`.
### Manipulate objects and arrays with modern methods
For functions that operate on arrays or JavaScript objects, you should
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),
[spread
syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax),
and so on. Our Babel configuration automatically transpiles and
polyfills these using [`core-js`](https://github.com/zloirock/core-js)
when necessary. We used to use the
[Underscore](https://underscorejs.org/) library, but that should be
avoided in new code.
## HTML and CSS
See the documentation on [HTML and CSS](../subsystems/html-css.md)
for guidance on conventions in those languages.
## Dangerous constructs in Django
### Avoid excessive database queries
Look out for Django code like this:
```python
bars = Bar.objects.filter(...)
for bar in bars:
foo = bar.foo
# Make use of foo
```
...because it equates to:
```python
bars = Bar.objects.filter(...)
for bar in bars:
foo = Foo.objects.get(id=bar.foo.id)
# Make use of foo
```
...which makes a database query for every `Bar`. While this may be fast
locally in development, it may be quite slow in production! Instead,
tell Django's [QuerySet
API](https://docs.djangoproject.com/en/5.0/ref/models/querysets/) to
_prefetch_ the data in the initial query:
```python
bars = Bar.objects.filter(...).select_related()
for bar in bars:
foo = bar.foo # This doesn't take another query, now!
# Make use of foo
```
If you can't rewrite it as a single query, that's a sign that something
is wrong with the database schema. So don't defer this optimization when
performing schema changes, or else you may later find that it's
impossible.
### Never do direct database queries (`UserProfile.objects.get()`, `Client.objects.get()`, etc.)
In our Django code, never do direct `UserProfile.objects.get(email=foo)`
database queries. Instead always use `get_user_profile_by_{email,id}`.
There are 3 reasons for this:
1. It's guaranteed to correctly do a case-insensitive lookup
2. It fetches the user object from remote cache, which is faster
3. It always fetches a UserProfile object which has been queried
using `.select_related()` ([see above](#avoid-excessive-database-queries)!),
and thus will perform well when one later accesses related models
like the Realm.
Similarly we have `get_client` and `access_stream_by_id` /
`access_stream_by_name` functions to fetch those commonly accessed
objects via remote cache.
### Don't use Django model objects as keys in sets/dicts
Don't use Django model objects as keys in sets/dictionaries -- you will
get unexpected behavior when dealing with objects obtained from
different database queries:
For example, the following will, surprisingly, fail:
```python
# Bad example -- will raise!
obj: UserProfile = get_user_profile_by_id(17)
some_objs = UserProfile.objects.get(id=17)
assert obj in set([some_objs])
```
You should work with the IDs instead:
```python
obj: UserProfile = get_user_profile_by_id(17)
some_objs = UserProfile.objects.get(id=17)
assert obj.id in set([o.id for o in some_objs])
```
### Don't call user_profile.save() without `update_fields`
You should always pass the `update_fields` keyword argument to `.save()`
when modifying an existing Django model object. By default, `.save()`
updates all of the model object fields in the database, which results
in lots of race conditions where unrelated changes made by one thread can be
accidentally overwritten by another thread that fetched its `UserProfile`
object before the first thread wrote out its change.
### Don't update important model objects with raw saves
In most cases, we already have a function in `zerver.actions` with
a name like `do_activate_user` that will correctly handle lookups,
caching, and notifying running browsers via the event system about your
change. So please check whether such a function exists before writing
new code to modify a model object, since your new code has a good chance
of getting at least one of these things wrong.
### Don't use naive datetime objects
Python allows datetime objects to not have an associated time zone, which can
cause time-related bugs that are hard to catch with a test suite, or bugs
that only show up during daylight saving time.
Good ways to make time-zone-aware datetimes are below. We import time zone
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
in `zerver/`.
- `datetime.now(tz=timezone.utc)` when Django is not available, such as
for bots and scripts.
- `datetime.fromtimestamp(timestamp, tz=timezone.utc)` if creating a
datetime from a timestamp. This is also available as
`zerver.lib.timestamp.timestamp_to_datetime`.
- `datetime.strptime(date_string, format).replace(tzinfo=timezone.utc)` if
creating a datetime from a formatted string that is in UTC.
Idioms that result in time-zone-naive datetimes, and should be avoided, are
`datetime.now()` and `datetime.fromtimestamp(timestamp)` without a `tz`
parameter, `datetime.utcnow()` and `datetime.utcfromtimestamp()`, and
`datetime.strptime(date_string, format)` without replacing the `tzinfo` at
the end.
Additional notes:
- Especially in scripts and puppet configuration where Django is not
available, using `time.time()` to get timestamps can be cleaner than
dealing with datetimes.
- All datetimes on the backend should be in UTC, unless there is a good
reason to do otherwise.
## Dangerous constructs in JavaScript and TypeScript
### Do not use `for...in` statements to traverse arrays
That construct pulls in properties inherited from the prototype chain.
Don't use it:
[[1]](https://stackoverflow.com/questions/500504/javascript-for-in-with-arrays),
[[2]](https://google.github.io/styleguide/javascriptguide.xml#for-in_loop),
[[3]](https://www.jslint.com/help.html#forin)

View File

@@ -0,0 +1,345 @@
# Commit discipline
We follow the Git project's own commit discipline practice of "Each
commit is a minimal coherent idea". This discipline takes a bit of work,
but it makes it much easier for code reviewers to spot bugs, and
makes the commit history a much more useful resource for developers
trying to understand why the code works the way it does, which also
helps a lot in preventing bugs.
Use `git rebase -i` as much as you need to shape your commit structure. See the
[Git guide](../git/overview.md) for useful resources on mastering Git.
**Tip**: Check out how to use [`git log -p` to study the commit
history](../git/reading-history.md) of the project.
## Each commit must be coherent
- It should pass tests (so test updates needed by a change should be
in the same commit as the original change, not a separate "fix the
tests that were broken by the last commit" commit).
- It should not make Zulip worse. For example, it is fine to add backend
capabilities without adding a frontend to access them. It's not fine to add a
frontend component with no backend to make it work.
- It should be safe to deploy individually, or explain in detail in
the commit message as to why it isn't (maybe with a [manual] tag).
So implementing a new API endpoint in one commit and then adding the
security checks in a future commit should be avoided -- the security
checks should be there from the beginning.
- Error handling should generally be included along with the code that
might trigger the error.
- TODO comments should be in the commit that introduces the issue or
the functionality with further work required.
## Commits should generally be minimal
Whenever possible, find chunks of complexity that you can separate from the
rest of the project.
- If you need to refactor code, add tests for existing functionality,
rename variables or functions, or make other changes that do not
change the functionality of the product, make those changes into a
series of preparatory commits that can be merged independently of
building the feature itself.
- Moving code from one file to another should be done in separate
commits from functional changes or even refactoring within a file.
- 2 different refactorings should be done in different commits.
- 2 different features should be done in different commits.
- If you find yourself writing a commit message that reads like a list
of somewhat dissimilar things that you did, you probably should have
just done multiple commits.
### When not to be overly minimal
- For completely new features, you don't necessarily need to split out
new commits for each little subfeature of the new feature. E.g., if
you're writing a new tool from scratch, it's fine to have the
initial tool have plenty of options/features without doing separate
commits for each one. That said, reviewing a 2000-line giant blob of
new code isn't fun, so please be thoughtful about submitting things
in reviewable units.
- Don't bother to split backend commits from frontend commits, even
though the backend can often be coherent on its own.
## Write a clean commit history
- Overly fine commits are easy to squash later, but not vice versa.
So err toward small commits, and the code reviewer can advise on
squashing.
- If a commit you write doesn't pass tests, you should usually fix
that by amending the commit to fix the bug, not writing a new "fix
tests" commit on top of it.
Zulip expects you to structure the commits in your pull requests to form
a clean history before we will merge them. It's best to write your
commits following these guidelines in the first place, but if you don't,
you can always fix your history using `git rebase -i` (more on that
[here](../git/fixing-commits.md)).
Never mix multiple changes together in a single commit, but it's great
to include several related changes, each in their own commit, in a
single pull request. If you notice an issue that is only somewhat
related to what you were working on, but you feel that it's too minor
to create a dedicated pull request, feel free to append it as an
additional commit in the pull request for your main project (that
commit should have a clear explanation of the bug in its commit
message). This way, the bug gets fixed, but this independent change
is highlighted for reviewers. Or just create a dedicated pull request
for it. Whatever you do, don't squash unrelated changes together in a
single commit; the reviewer will ask you to split the changes out into
their own commits.
It can take some practice to get used to writing your commits with a
clean history so that you don't spend much time doing interactive
rebases. For example, often you'll start adding a feature, and discover
you need to do a refactoring partway through writing the feature. When that
happens, we recommend you stash your partial feature, do the refactoring,
commit it, and then unstash and finish implementing your feature.
For additional guidance on how to structure your commits (and why it matters!),
check out GitHub's excellent [blog post](https://github.blog/2022-06-30-write-better-commits-build-better-projects).
## Commit messages
Commit messages have two parts:
1. A **summary**, which is a brief one-line overview of the changes.
2. A **description**, which provides further details on the changes,
the motivation behind them, and why they improve the project.
In Zulip, commit summaries have a two-part structure:
1. A one or two word description of the part of the codebase changed
by the commit.
2. A short sentence summarizing your changes.
Here is an
[example](https://github.com/zulip/zulip/commit/084dd216f017c32e15c1b13469bcbc928cd0bce9)
of a good commit message:
> tests: Remove ignored realm_str parameter from message send test.
>
> In commit
> [8181ec4](https://github.com/zulip/zulip/commit/8181ec4b56abf598223112e7bc65ce20f3a6236b),
> we removed the `realm_str` as a parameter for `send_message_backend`. This
> removes a missed test that included this as a parameter for that
> endpoint/function.
The commit message is a key piece of how you communicate with reviewers and
future contributors, and is no less important than the code you write. This
section provides detailed guidance on how to write an excellent commit message.
**Tip:** You can set up [Zulip's Git pre-commit hook][commit-hook] to
automatically catch common commit message mistakes.
[commit-hook]: ../git/zulip-tools.md#set-up-git-repo-script
### Commit summary, part 1
The first part of the commit summary should only be 1-2 **lower-case**
words, followed by a `:`, describing what the part of the product the
commit changes. These prefixes are essential for maintainers to
efficiently skim commits when doing release management or
investigating regressions.
Common examples include: settings, message feed, compose, left
sidebar, right sidebar, recent (for **Recent conversations**), search,
markdown, tooltips, popovers, drafts, integrations, email, docs, help,
and api docs.
When it's possible to do so concisely, it's helpful to be a little more
specific, e.g., emoji, spoilers, polls. However, a simple `settings:` is better
than a lengthy description of a specific setting.
If your commit doesn't cleanly map to a part of the product, you might
use something like "css" for CSS-only changes, or the name of the file
or technical subsystem principally being modified (not the full path,
so `realm_icon`, not `zerver/lib/realm_icon.py`).
There is no need to be creative here! If one of the examples above
fits your commit, use it. Consistency makes it easier for others to
scan commit messages to find what they need.
Additional tips:
- Use lowercase (e.g., "settings", not "Settings").
- If it's hard to find a 1-2 word description of the part of the codebase
affected by your commit, consider again whether you have structured your
commits well.
- Never use a generic term like "bug", "fix", or "refactor".
### Commit summary, part 2
This is a **complete sentence** that briefly summarizes your changes. There are
a few rules to keep in mind:
- Start the sentence with an
[imperative](https://en.wikipedia.org/wiki/Imperative_mood) verb, e.g.,
"fix", "add", "change", "rename", etc.
- Use proper capitalization and punctuation.
- Avoid abbreviations and acronyms.
- Be concise, and don't include unnecessary details. For example, "Change X and
update tests/docs," would be better written as just, "Change X," since (as
discussed above) _every_ commit is expected to update tests and documentation
as needed.
- Make it readable to someone who is familiar with Zulip's codebase, but hasn't
been involved with the effort you're working on.
- Use no more than 72 characters for the entire commit summary (parts 1 and 2).
### Examples of good commit summaries
- `provision: Improve performance of installing npm.`
- `channel: Discard all HTTP responses while reloading.`
- `integrations: Add GitLab integration.`
- `typeahead: Rename compare_by_popularity() for clarity.`
- `typeahead: Convert to ES6 module.`
- `tests: Compile Handlebars templates with source maps.`
- `blueslip: Add feature to time common operations.`
- `gather_subscriptions: Fix exception handling bad input.`
- `channel_settings: Fix save/discard widget on narrow screens.`
#### Detailed example
- **Good summary**: "gather_subscriptions: Fix exception handling bad input."
- **Not so good alternatives**:
- "gather_subscriptions was broken": This doesn't explain how it was broken, and
doesn't follow the format guidelines for commit summaries.
- "Fix exception when given bad input": It's impossible to tell what part of the
codebase was changed.
- Not using the imperative:
- "gather_subscriptions: Fixing exception when given bad input."
- "gather_subscriptions: Fixed exception when given bad input."
### Commit description
The body of the commit message should explain why and how the change
was made. Like a good code comment, it should provide context and
motivation that will help both a reviewer now, and a developer looking
at your changes a year later, understand the motivation behind your
decisions.
Many decisions may be documented in multiple places (for example, both
in a commit message and a code comment). The general rules of thumb are:
- Use the commit message for information that's relevant for someone
trying to understand the change this commit is making, or the difference
between the old version of the code and the new version. In particular,
this includes information about why the new version of the code is better than,
or not worse than, the old version.
- Use code comments, or the code itself, for information that's relevant
for someone trying to read and understand the new version of the code
in the future, without comparing it to the old version.
- If the information is helpful for reviewing your work (for example,
an alternative approach that you rejected or are considering,
something you noticed that seemed weird, or an error you aren't sure
you resolved correctly), include it in the PR description /
discussion.
As an example, if you have a question that you expect to be resolved
during the review process, put it in a PR comment attached to a
relevant part of the changes. When the question is resolved, remember
to update code comments and/or the commit description to document the
reasoning behind the decisions.
There are some cases when the best approach is improving the code or commit
structure, not writing up details in a comment or a commit message. For example:
- If the information is the description of a calculation or function,
consider the abstractions you're using. Often, a better name for a
variable or function is a better path to readable code than writing
a prose explanation.
- If the information describes an additional change that you made while working
on the commit, consider whether it is separable from the rest of the changes.
If it is, it should probably be moved to its own commit, with its own commit
message explaining it. Reviewing and integrating a series of several
well-written commits is far easier than reviewing those same changes in a
single commit.
When you fix a GitHub issue, [mark that you have fixed the issue in
your commit
message](https://help.github.com/en/articles/closing-issues-via-commit-messages)
so that the issue is automatically closed when your code is merged,
and the commit has a permanent reference to the issue(s) that it
resolves. Zulip's preferred style for this is to have the final
paragraph of the commit message read, e.g., `Fixes #123.`.
**Note:** Avoid using a phrase like `Partially fixes #1234.`, as
GitHub's regular expressions ignore the "partially" and close the
issue. `Fixes part of #1234.` is a good alternative.
#### The purpose of the commit description
The commit summary and description should, taken together, explain to another
Zulip developer (who may not be deeply familiar with the specific
files/subsystems you're changing) why this commit improves the project. This
means explaining both what it accomplishes, and why it won't break things one
might worry about it breaking.
- Include any important investigation/reasoning that another developer
would need to understand in order to verify the correctness of your
change. For example, if you're removing a parameter from a function,
the commit message might say, "It's safe to remove this parameter
because it was always False," or, "This behavior needs to be removed
because ...". A reviewer will likely check that indeed it was always
`False` as part of checking your work -- what you're doing is
providing them a chain of reasoning that they can verify.
- Provide background context. A good pattern in a commit message
description is, "Previously, when X happened, this caused Y to
happen, which resulted in ...", followed by a description of the
negative outcome.
- Don't include details that are obvious from looking at the diff for
the commit, such as lists of the names of the files or functions
that were changed, or the fact that you updated the tests.
- Avoid unnecessary personal narrative about the process through which
you developed this commit or pull request, like "First I tried X" or
"I changed Y".
#### Mentioning other contributors
You can
[credit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors)
co-authors on a commit by adding a `Co-authored-by:` line after a blank line at
the end of your commit message:
Co-authored-by: Greg Price <greg@zulip.com>
You should always give credit where credit is due. See our [guide on continuing
unfinished work](../contributing/continuing-unfinished-work.md) for step-by-step
guidance on continuing work someone else has started.
You can also add other notes, such as `Reported-by:`, `Debugged-by:`, or
`Suggested-by:`, but we don't typically do so.
@-mentions don't belong in commit messages (and won't notify the user you
mentioned). If you want to send someone a notification about a change, @-mention
them in the PR thread.
#### Formatting guidelines
There are a few specific formatting guidelines to keep in mind:
- The commit description should be separated from the commit summary
by a blank line. Most tools, including GitHub, will misrender commit
messages that don't do this.
- Use full sentences and paragraphs, with proper punctuation and
capitalization. Paragraphs should be separated with a single blank
line.
- Be sure to check your description for typos, spelling, and grammar
mistakes; commit messages are important technical writing and
English mistakes will distract reviewers from your ideas.
- Your commit message should be line-wrapped to about 68 characters
per line, but no more than 70, so that your commit message will be
easy to read in `git log` in a normal terminal. (It's OK for links
to be longer -- ignore `gitlint` when it complains about them.)
**Tip:** You may find it helpful to configure Git to use your preferred editor
using the `EDITOR` environment variable or `git config --global core.editor`,
and configure the editor to automatically wrap text to 70 or fewer columns per
line (all text editors support this).
### Examples of good commit messages
- [A backend testing
commit](https://github.com/zulip/zulip/commit/4869e1b0b2bc6d56fcf44b7d0e36ca20f45d0521)
- [A development environment provisioning
commit](https://github.com/zulip/zulip/commit/cd5b38f5d8bdcc1771ad794f37262a61843c56c0)

View File

@@ -0,0 +1,154 @@
# Continuing unfinished work
Sometimes, work is started on an issue or PR, but not brought to completion.
This may happen for a variety of reasons — the contributor working on the
project gets busy, maintainers cannot prioritize reviewing the work, a
contributor doesn't have the skills required to complete the project, there is
an unexpected technical challenge or blocker, etc.
Completing work that someone else has started is a great way to contribute! Here
are the steps required:
1. [Find work to be completed.](#find-work-to-be-completed)
1. [Review existing work and feedback.](#review-existing-work-and-feedback)
1. [Decide how to use prior work.](#decide-how-to-use-prior-work)
1. [Credit prior work in your commit history.](#credit-prior-work-in-your-commit-history)
1. [Present your pull request.](#present-your-pull-request)
## Find work to be completed
In Zulip's server and web app [repository](https://github.com/zulip/zulip), pull
requests that have significant work towards something valuable are often tagged
with a [completion candidate][completion-candidate] label. You can review
this label for unfinished work that you find interesting and have the skills to
complete.
Note that it's common to see one or more pull requests linked to an issue
you're interested in. The guidelines below apply regardless of whether you
intentionally set out to find work to complete or simply find yourself
building on someone else's work.
## Review existing work and feedback
Any time there are pull requests linked to the issue you are working on, start
by reviewing the existing work. Read the code, and pay close attention to any
feedback the pull request received. This will help you avoid any pitfalls other
contributors encountered.
## Decide how to use prior work
Consider how to use prior work on the issue. In your best judgment, is the
existing PR on the right track? If there's reviewer feedback, it should help you
figure this out.
If prior work looks like a good start:
1. Pull down the existing pull request.
1. Rebase it on the current version of the `main` branch.
1. Carefully address any open feedback from reviewers.
1. Make any other changes you think are needed, including completing any parts
of the work that had not been finished.
1. Make sure the work of others is [properly credited](#credit-prior-work-in-your-commit-history).
1. [Self-review](../contributing/code-reviewing.md), test, and revise the work,
including potentially [splitting out](../contributing/commit-discipline.md)
preparatory commits to make it easier to read. You should be proud of the
resulting series of commits, and be prepared to argue that it is the best
work you can produce to complete the issue.
Otherwise, you can:
1. Make your own changes from scratch.
1. Go through reviewer feedback on prior work. Would any of it apply to the
changes you're proposing? Be sure to address it if so.
## Credit prior work in your commit history
When you use or build upon someone else's unmerged work, it is both
professionally and ethically necessary to [properly
credit][coauthor-git-guide] their contributions in the commit history
of work that you submit. Git, used properly, does a good job of
preserving the original authorship of commits.
However, it's normal to find yourself making changes to commits
originally authored by other contributors, whether resolving merge
conflicts when doing `git rebase` or fixing bugs to create an
atomically correct commit compliant with Zulip's [commit
guidelines](../contributing/commit-discipline.md).
When you do that, it's your responsibility to ensure the resulting
commit series correctly credits the work of everyone who materially
contributed to it. The most direct way to credit the work of someone
beyond the commit's author maintained in the Git metadata is
`Co-authored-by:` line after a blank line at the end of your commit
message:
Co-authored-by: Greg Price <greg@zulip.com>
Be careful to type it precisely, because software parses these commit
message records in generating statistics. You should add such a line
in two scenarios:
- If your own work was squashed into a commit originally authored by
another contributor, add such a line crediting yourself.
- If you used another contributor's work in generating your own
commit, add such a line crediting the other contributor(s).
Sometimes, you make a mistake when rebasing and accidentally squash
commits in a way that messes up Git's authorship records. Often,
undoing the rebase change via `git reflog` is the best way to correct
such mistakes, but there are two other Git commands that can be used
to correct Git's primary authorship information after the fact:
- `git commit --amend --reset-author` will replace the Git commit
metadata (date, author, etc.) of the currently checked out commit
with yourself. This is useful to correct a commit that incorrectly
shows someone else as the author of your work.
- `git commit --amend -C <commit_id>` will replace the commit metadata
(date, author, etc.) on a commit with that of the provided commit
ID. This is useful if you accidentally made someone else's commit
show yourself as the author, or lost a useful commit message via
accidental squashing. (You can usually find the right commit ID to
use with `git reflog` or from GitHub).
As an aside, maintainers who modify commits before merging them are
credited via Git's "Committer" records (visible with `git show
--pretty=fuller`, for example). As a result, they may not bother with
adding a separate `Co-authored-by` record on commits that they revise
as part of merging a pull request.
## Present your pull request
In addition to the usual [guidance](../contributing/reviewable-prs.md) for
putting together your pull request, there are a few key points to keep in mind.
- **Take responsibility for the work.** Any time you propose changes to the
Zulip project, you are accountable for those changes. Do your very best to verify that they are correct.
- Don't submit code you don't understand — dig in to figure out what it's
doing, even if you didn't write it. This is a great way to catch bugs and
make improvements.
- Test the work carefully, even if others have tested it before. There may be
problems that the reviewers missed, or that were introduced by rebasing across other changes.
- **Give credit where credit is due.** Reviewers should be able to examine your
commit history and see that you have [properly credited](#credit-prior-work-in-your-commit-history)
the work of others.
- **Explain the relationship between your PR and prior work** in the description
for your pull request. This is required for your PR to be reviewed, as
reviewing a new PR when there is an existing one is a good use of time only if
the motivation for doing so is clear.
- If you started from an existing PR, explain what changes you made, and how
you addressed each point of reviewer feedback that hadn't been addressed previously.
- If you started from scratch, explain _why_ you decided to do so, and how
your approach differs from prior work. For example:
- "I didn't use the work in PR #12345, because the surrounding code has
changed too much since it was written."
- "I didn't use the work in PR #23154, because [this reviewer
comment](#present-your-pull-request) asked to solve this issue using CSS,
rather than the JavaScript changes made in #23154."
- "I didn't use the work in PRs #12345 and #23154, because both didn't work
properly when a user opened their own profile."
[completion-candidate]: https://github.com/zulip/zulip/pulls?q=is%3Aopen+is%3Apr+label%3A%22completion+candidate%22
[coauthor-git-guide]: https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors

View File

@@ -0,0 +1 @@
../../CONTRIBUTING.md

View File

@@ -0,0 +1,98 @@
# Counting contributions
The [Zulip team page](https://zulip.com/team/) displays commit counts for
contributors to Zulip projects. We display these statistics prominently because
they are easy to compute, and can be fun and motivating for some of our
contributors.
We do not consider commit count to be a good way to measure someone's
contributions to a software project. Many invaluable contributions may not
result in the contributor authoring any code at all, including design, feedback,
translations, bug reports, helping new contributors, and other types of
participation in our [development community][dev-community]. These non-code
contributions are essential to making the Zulip project successful.
Thus, Zulip's policy is to always express appreciation for non-code
contributions to the project whenever we discuss code contribution
statistics, especially in our highest-visibility contexts like release
blog posts.
## How the contribution stats are calculated
The data for all contributors to the Zulip project is aggregated by
querying [GitHub's API endpoint for listing a repository's
contributors][github-list-contrib-endpoint]. The numbers Zulip gets
from this endpoint differs slightly from the data GitHub displays in a
repository's [contributors page][github-contrib-page]. This
discrepancy is due to the following reasons:
- A repository's contributors page excludes commits with author email
addresses that do not have an associated GitHub account. However,
the GitHub API counts such emails in its contributor stats.
- A repository's contributors page does not count commits authored by
email addresses that have been deleted from a GitHub profile by the
user. However, the GitHub API treats these stale emails as
contributors as well.
- Some commits have multiple authors when that is declared via
[Co-Authored-By][co-authored-by] in a commit message.
## Old email addresses
If you remove an email address from your GitHub profile, the commits
you contributed with that email as the `GIT_AUTHOR_EMAIL` will
disappear from your GitHub profile. If you made contributions to Zulip
with an author email address that is no longer associated with your
GitHub profile, here are some important points to keep in mind:
- Zulip's team page will still display your contributions. These
contributions will be grouped under the email that was used for the
commits, but will not link to your GitHub profile.
- If you still have access to the email used for the contributions, you
can link the contributions to your GitHub profile by
[adding the email to your GitHub account][github-add-email].
- If you do not have access to the email in question, you can ask for
help on chat.zulip.org, or submit a pull request editing the
`.mailmap` file at the root of the repository where your
contributed.
The comments at the top of our `.mailmap` files document how to map
your old email address to one currently associated with your GitHub
account.
## Relevant source code
To dig deeper into how the contributor stats are calculated, please check
out the following files in the [Zulip server repository][server-repo]:
- `tools/fetch-contributor-data` - The script that fetches contributor
data from GitHub's API.
- `static/js/portico/team.js` - The JavaScript code that processes and
renders the data received from GitHub.
## Attribution for non-code contributions
As noted above, Zulip's policy is to express appreciation for non-code
contributions to the project whenever we discuss code contribution
statistics.
We do not specifically attribute non-code contributions by name, because the
logistics of giving individual attributions in a consistent and fair way across
50+ features in a release are far more than we have the capacity to manage.
For context, a significant feature usually involves a half-dozen people or more
helping with different parts of the work (suggesting ideas, providing technical
and non-technical feedback, etc.). Contributions can range from multiple rounds
of PR reviews to a 👍 reaction on someone else's suggestion. Even if one could
review everything that happened (in itself a daunting task), it may not be clear
which contributions should "count". At the same time, seeing that your name is
missing from a list of attributions where it belongs can feel really hurtful.
So, while we cannot thank everyone by name, please know that your contributions
are deeply appreciated!
[github-list-contrib-endpoint]: https://docs.github.com/en/rest/reference/repos#list-repository-contributors
[github-contrib-page]: https://docs.github.com/en/repositories/viewing-activity-and-data-for-your-repository/viewing-a-projects-contributors
[dev-community]: https://zulip.com/development-community/
[server-repo]: https://github.com/zulip/zulip
[github-add-email]: https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-user-account/managing-email-preferences/adding-an-email-address-to-your-github-account
[co-authored-by]: https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors

View File

@@ -0,0 +1,296 @@
# Design discussions
We discuss ideas for improving Zulip's user experience, interface, and visual
design in the [Zulip development
community](https://zulip.com/development-community/). The purpose of these
design discussions is to help us make smart, well-informed decisions about
design changes to the Zulip product. We want Zulip to work great for a diverse
array of users and organizations, and discussions in the development community
are an incredibly valuable source of insight and ideas. We welcome all
perspectives, respectfully shared.
Most design discussions take place in the [#design][design channel] channel in the
development community. Discussions about mobile app design happen in
[#mobile-design][mobile-design channel],
and design of the terminal app is discussed in
[#zulip-terminal][zulip-terminal channel].
## Guidelines for all participants
Everyone is encouraged to participate in design discussions! Your participation
greatly helps improve the product, especially when you focus your contributions
on supporting the productivity of the design team. The more we are able to
incorporate a variety of ideas, experiences, and perspectives into the
discussion, the better decisions we'll be able to make.
Please start by reviewing the guide to [how we
communicate](how-we-communicate.md) in the Zulip community. Also, when sharing
your ideas:
- Think about corner cases and interactions with existing features that the
design will need to handle, and bring up problems with them, especially if they
are not obvious. (E.g., “This component also appears with a darker background
in the Drafts UI,” with a screenshot).
- Present technical considerations _where appropriate_. “X requires
some refactoring that would take me another hour,” is probably not
worth bringing up if X would produce a better user
experience. “Adding X might require removing feature Y,” or “X is
incompatible with Zulip's security model,” is important to present
early.
Note that [#design][design channel] is a high-traffic channel, and thoughtful
participation takes time. Don’t let it prevent you from doing your own work. It
can be helpful to pick particular conversations to follow, where you feel that
you have insight to share.
## Participant roles
At this point, it will be helpful to define a few key roles in design
discussions:
- [Code contributor](#guidelines-for-code-contributors): Anyone working on a PR
that includes some frontend changes.
- [Community moderator](#guidelines-for-community-moderators): Any core
contributor or other experienced community member who is helping guide the
discussion (with or without "moderator" permissions in the organization).
- **Design team**: Anyone working actively on the design of the feature at hand
and/or overall design for the Zulip product.
- [Decision makers](#guidelines-for-decision-makers): Project maintainers
responsible for design decisions, including design leaders, product leaders,
and overall project leadership.
## Guidelines for code contributors
When you are working on a PR that includes frontend changes, you may find it helpful
to get interactive feedback on the design. The best way to do so is by posting a
message in the appropriate design channel in the Zulip development
community: [#design][design channel] for the web/desktop app,
[#mobile-design][mobile-design channel] for the mobile app, or
[#zulip-terminal][zulip-terminal channel] for the terminal app.
### When to post
- The issue or a comment on your PR specifically asks you to get feedback in
[#design][design channel] or another design channel.
- The issue you’re working on is not specific about some design point, and you
would like advice.
- You’ve implemented an issue as described, but the UI doesn’t look good or
seems awkward to use.
- You’re prototyping an idea that’s not fully fleshed out.
### Guidelines for requesting design feedback
You will get the most helpful feedback by sharing enough context for community
participants to understand what you're trying to do, and clearly stating the
questions you are looking for feedback on. Some advice:
- Start a new topic, or use an existing one if there is a topic linked from the
issue you’re working on. If you’re starting a new topic, appending the issue
or PR number (e.g., `#1234`) to the topic name will turn it into a handy link.
- Summarize the feature you’re working on. You should provide enough
context for readers to understand your question, and include links
to any relevant issues or in-progress PRs for additional background.
- Post screenshots, and perhaps a short video if there is an interaction that
screenshots fail to show.
- Use the [guide on presenting visual
changes](../contributing/presenting-visual-changes.md) for guidance on what to
show, and how to capture precise Before/After screenshots when appropriate.
- You may want to post a few screenshots of different options you’re
considering.
- Screenshots should show enough of the app to evaluate how the new feature
looks in its context, but not so much that it’s hard to see the feature.
- Screen captures should demonstrate the feature with a minimal amount of
extraneous content.
- Post a clear question or set of questions that you need help with. What
specifically are you looking for feedback on?
- Since you’ve been working on this issue, you have likely gained some expertise
in this area. Educate others by sharing any tradeoffs and relevant
considerations you’re aware of.
Keep in mind that the Zulip community is distributed around the world, and you
should not expect to get realtime feedback. However, feel free to bump the
thread if you don’t see a response after a couple of business days.
## Guidelines for community moderators
Any experienced community participant can guide design discussions, and help
make sure that we use everyone's time productively towards making the best
decisions we can.
### Improving the quality of discussions
Here are some suggestions for how you can help the community have a productive
design discussion:
- If a design discussion seems to have been derailed by a tangent or argument,
consider moving the tangent to another topic so that the conversation can
refocus on the questions at hand.
- If the direction of the discussion seems unproductive, you can explicitly
suggest circling back to a topic where additional discussion seems valuable.
- If someone is repeating the same points in a way that’s unhelpful, you can let
them know that you understand what they are saying and appreciate their
feedback, but at this point would find it helpful to hear feedback from other
participants. People may sometimes repeat themselves because they are not feeling
heard.
- That said, sometimes the best way to deal with questions or feedback that
don’t move the discussion forward is to let them go by without comment, rather
than potentially getting into a protracted back-and-forth that derails the
thread. Examples of such feedback include unmotivated personal opinions,
proposals that ignore counterarguments that have already been discussed, etc.
- It’s totally fine to let the conversation slow down or die, especially if it
seems to be going off-track. If the decision makers feel that they do not have
enough feedback yet, they can revive the conversation as needed, and the pause
can serve as a good reset.
If a conversation is going off-track and you are not sure how to fix it, please
ping someone on the core team to intervene and help get the conversation into a
better state.
### Moving threads to the most appropriate channel
Sometimes it helps to move (part of) a thread to a different channel, so that
it's seen by the appropriate audience.
- We generally aim to discuss raw user feedback on the product’s design in
[#feedback](https://chat.zulip.org/#narrow/channel/137-feedback) (when it
applies to the web and desktop apps, or to all Zulip clients). The
[#design][design channel] should be reserved for design aspects that we’re
actively (considering) working on. This lets the design team focus on
discussions that are expected to result in actionable decisions.
- If a discussion that started in another channel has shifted into the design
phase, moving the discussion to [#design][design channel] helps the design team
follow the conversation.
- Discussion of implementation-related decisions should ideally happen in
non-design channels:
[#frontend](https://chat.zulip.org/#narrow/channel/6-frontend) for the web
app, and see our [guide to chat.zulip.org
channels](https://zulip.com/development-community/#channels-for-code-contributors)
for other Zulip codebases. The line can sometimes blur (and that’s OK), but we
should aim to move (parts of) the thread if there is an extensive conversation
that belongs in the other channel.
- Similarly, for changes to the mobile app:
- We aim to discuss raw user feedback in
[#mobile](https://chat.zulip.org/#narrow/channel/48-mobile).
The [#mobile-design][mobile-design channel] channel is reserved for design
aspects that we're actively (considering) working on.
- A discussion that has shifted into the design phase should be moved to
[#mobile-design][mobile-design channel], to help the design team closely
follow the discussion that calls for their input.
- Discussion of implementation details should move to
[#mobile-team](https://chat.zulip.org/#narrow/channel/243-mobile-team) or to
[#mobile-dev-help](https://chat.zulip.org/#narrow/channel/516-mobile-dev-help).
- Discussions of the mobile app's design should move to
[#mobile-design][mobile-design channel] (instead of #design), which the
mobile team follows closely.
Similarly, discussions of the design of the terminal app should move to
[#zulip-terminal][zulip-terminal channel].
## Guidelines for decision makers
The main purpose of design discussions is to help us make the best design
decisions we can. Decision makers should guide the conversation to elicit the
ideas, feedback and advice they need from the community.
Ideally, design discussions should also help us learn as a community. Community
members who follow the conversation should get a better understanding of the
considerations behind the decisions being discussed, and thus be better able to
contribute to the next conversation.
### Managing the discussion
Decision makers should actively manage the discussion to make sure we're making
good use of everyone's time and attention, and getting useful feedback.
- Decision makers should aim to follow design threads closely and provide input
early and often, so that conversations don’t get blocked waiting for their
opinion.
- Decision makers should actively manage discussion threads when needed in order
to seek the types of inputs that will help them. This may include outlining a
set of alternatives to consider, posing questions to dig into someone’s
feedback, asking for ideas to solve a specific design challenge, etc.
- Decision makers should explain the reasoning behind their proposed decisions,
so that it’s possible to identify any gaps in their thinking, and in order to
build a shared understanding in the community.
- That said, decision makers are not required to respond to every comment being
made regarding a proposal, or to answer every question.
### From discussion to decision
There are a number of factors that affect when it’s time to move a thread from
discussion to a decision. In part, this depends on how significant a commitment
we are making with the decision at hand:
- We want to be very thoughtful about decisions that will take a lot of work to
implement, and/or will be difficult to undo.
- We should try to come up with good designs for the features we're building,
but sometimes it's difficult to foresee how an interaction will feel until we
try it. Prototyping a UI we are not sure about is a normal part of the design
process.
- When the decision results in filing a non-urgent issue, it’s fine to write up
the conclusions on GitHub relatively quickly, and update the issue if more
ideas come in later on.
- We should accept that sometimes an idea we decided on is just not working out,
and be willing to go back to the drawing board or iterate further until we get
to a state we're happy with.
With those considerations in mind, here are rough guidelines for when to move on
to a decision:
- For very small decisions, it may be enough to get a sanity-check from one or
two well-informed community participants.
- For more significant decisions, one should generally allow at least 1-2 business
days for discussion, to give core team members time to share their perspective
if they have something to contribute.
- Beyond that minimum, the decision makers can move to the decision phase
whenever they have enough input to make a well-informed decision. Here are
some situations that would indicate that it’s time to move on:
- There is general consensus on how to proceed. Or, there is consensus
between the well-informed participants in the discussion.
- For a relatively small decision, there is enough useful feedback to
generate a solid proposal.
- If the discussion is primarily rehashing old points, and doesn’t seem to
be generating additional insights, it’s time to redirect the conversation
or move on to a decision.
- If the thread has died down, and the decision makers feel that they have
enough information to go on. (If they don’t, the thread can be bumped.)
[design channel]: https://chat.zulip.org/#narrow/channel/101-design
[mobile-design channel]: https://chat.zulip.org/#narrow/channel/530-mobile-design
[zulip-terminal channel]: https://chat.zulip.org/#narrow/channel/206-zulip-terminal

View File

@@ -0,0 +1,116 @@
# How we communicate
The primary communication forum for the Zulip community is the Zulip server
hosted at [chat.zulip.org](https://chat.zulip.org/). If you are not familiar
with it, start by reading the [Zulip development community
guide](https://zulip.com/development-community/). The guidelines here also apply
to how we communicate on GitHub issues and pull requests, but other pages in
this section go into greater detail about expectations that are specific to pull
requests.
We are deeply committed to maintaining a respectful, collaborative atmosphere
across all interactions in the Zulip community. To get a feel for what that
means to us, please review the [code of conduct](../code-of-conduct.md) for our
community.
Beyond that, the following guidelines should help you communicate effectively to
express your perspective, and support and encourage other participants in the
community. By incorporating these patterns of behavior, we'll be able to reach
better decisions as a group, and learn and have fun along the way.
## Providing suggestions and feedback
- Aim to present your feedback precisely, with reasoning, and in as objective a
fashion as you can manage. E.g., “This button really jumps out at me in a way
that’s distracting; maybe it’s because of the color has a higher contrast than
the surrounding components?” is better than, “Can we make that color less
dark?”.
- Clarify your feedback if there are follow-up questions or points of confusion.
However, avoid simply repeating the same points, as it does not move us closer
to making the best decisions we can.
- When relevant, highlight information you have beyond your personal opinion.
E.g., “I moderate a community, and often have to answer questions about how
this works,” is more helpful than, “This is confusing.”
- In addition to offering constructive feedback, call out specific things that
someone is doing well. This helps folks feel good about their work, and also
helps them learn. E.g., “I particularly like the test you added, because...”
- When asking someone to do something, explain the reasoning behind your
request. This is more motivating, and educates folks on what to do next time.
- If you are not certain about a suggestion you're making, it often works well
to frame it as a question. E.g., “Would this be clearer if we...?” or “Could
we...?”.
- Invite others to disagree or contribute additional thoughts, especially if you
might be considered an authority in the area being discussed. When more folks
feel comfortable speaking up, we are better able to identify problems and
fine-tune solutions.
## Handling disagreements
- Always treat other participants in the discussion with respect, regardless of
whether you agree with their ideas. Ad hominem attacks are never appropriate.
- Approach discussions with a perspective of curiosity. If someone has expressed
an opinion you find odd or surprising, ask them to explain in more detail
where they are coming from.
- If you think someone is factually mistaken, consider how they might have reached
their conclusion, and aim to get to a shared understanding. For example:
- “I wasn't able to replicate this -- is it possible you are on an old Zulip
server?”, rather than “This bug report is wrong.”
- “Using this function won't work here, because...” instead of “That's the
wrong function.”
- If you disagree with someone on the core team, the best way to make progress
is usually to state your opinions and reasoning clearly and respectfully, and
then let the other core team members catch up on the conversation. Other
project members may find your argument persuasive, and may have ideas that
address your concerns.
## Expressing your appreciation
There are many ways to contribute to the Zulip community, and it's important to
express our appreciation for all the different ways in which folks jump in to
help. It helps motivate others, builds consensus towards decisions, and creates
a more positive atmosphere in the community.
For many community participants, it takes stepping out their comfort zone to try
something for the first time, such as submitting a pull request, answering a
question in the development community, or suggesting a new feature. It's
especially important to thank and encourage folks who are stretching themselves
to try something new.
- Remember to say “thanks” when responding to a question or suggestion. For
example:
- “Thanks for the report! ... ” when someone reports a bug.
- “Thanks for reviewing my PR! ... ”
- Express your appreciation for the work that went into a pull request, even
when it turns out that the approach taken in the PR is not successful. E.g.,
“Thanks for working on this! ... ”
- Try especially hard to express your appreciation for others' contributions,
effort and ideas when you are also providing negative (constructive) feedback
on their work.
- You can use a variety of channels to express your appreciation. A comment
directly in a Zulip thread or on a pull request is often best, but in some
cases you may also want to send a friendly direct message. For example:
- “I've noticed that you've been answering lots of questions in #**development
help** lately. Thanks so much for doing that!”
- “Thanks for moving those messages into a new topic -- the discussion was
getting really tangled!”
- Sometimes a quick emoji reaction can help someone feel that their work is
appreciated. 🎉
- Look over the message you just sent. Did you forget to say “thanks”? It's easy
to edit your message, or send a quick follow-up.

View File

@@ -0,0 +1,26 @@
# Contributing to Zulip
```{toctree}
---
maxdepth: 3
---
contributing
../code-of-conduct
how-we-communicate
asking-great-questions
design-discussions
commit-discipline
code-style
presenting-visual-changes
code-reviewing
reviewable-prs
review-process
continuing-unfinished-work
zulipbot-usage
reporting-bugs
reporting-security-vulnerabilities
suggesting-features
counting-contributions
licensing
```

View File

@@ -0,0 +1,40 @@
# Licensing
Zulip is distributed under the [Apache 2.0
license](https://github.com/zulip/zulip/blob/main/LICENSE). This means that all
contributions to Zulip — code, images, sounds, etc. — must be compatible with
this license.
## Contributing your own work
If the work you are contributing is 100% your own, Zulip doesn't require you to
sign a copyright assignment or a contributor license agreement for your
contribution. As noted [in the GitHub Terms of
Service](https://docs.github.com/en/site-policy/github-terms/github-terms-of-service#6-contributions-under-repository-license):
> “Whenever you add Content to a repository containing notice of a license, you
> license that Content under the same terms, and you agree that you have the
> right to license that Content under those terms... This is widely accepted as
> the norm in the open-source community; ...”
## Contributing someone else's work
If any part of your contribution is from someone else (code snippets, images,
sounds, or any other copyrightable work, modified or unmodified), you need to
check whether it was distributed under an open-source license that is
[compatible][wiki-compatibility] with the [Apache 2.0
license](https://github.com/zulip/zulip/blob/main/LICENSE). If it was not, this
work cannot be contributed to Zulip, with or without modification.
[wiki-compatibility]: https://en.wikipedia.org/wiki/License_compatibility#Compatibility_of_FOSS_licenses
If you have verified that the work is OK to use, you will need to provide
appropriate attribution in the [`docs/THIRDPARTY`
file](https://github.com/zulip/zulip/blob/main/docs/THIRDPARTY) as part of your
PR. Please refer to the [`debian/copyright` file
documentation](https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/)
for a detailed description (including examples) of how to correctly describe the
copyright and licensing information in your PR.
If you are not sure about the licensing or attribution for your work, please
include the full details of your open questions in the description for your PR.

View File

@@ -0,0 +1,390 @@
# Presenting visual changes
If your pull request makes visual changes, or includes refactoring that might
cause visual changes, you must include screenshots demonstrating the impact of
your changes in the description for your pull request.
**Always make sure the screenshots in the PR description capture the _current_
state of the PR.** To avoid confusion, delete outdated screenshots from the
description. If reviewers need to see multiple variants of the UI to make some
decision, include those variants in the comments.
## What to capture
Always include screenshots of _all_ the UI components and states affected by
your PR. For example, a PR that adds a new dropdown setting would need
screenshots to demonstrate:
- What the setting looks like in the settings UI (with some surrounding context).
- The open dropdown.
- The disabled version of the setting with its accompanying tooltip that would
be shown to users who aren't allowed to modify the setting.
- Visual impact of using each value of the setting (if any).
- Updated help center documentation (if any); see
[note](#presenting-documentation-changes) below.
If you're using standard components, there's no need to go overboard with
screenshots:
- Show the Before state if it provides helpful context (e.g., if you're changing
text on a banner), but otherwise you can skip them (e.g., if you're adding a
setting).
- There's usually no need to show light and dark theme screenshots, or
screenshots at different font sizes.
- There's usually no need to show the keyboard selection UI.
However, if your pull request makes any CSS changes, you'll need to thoroughly
demonstrate its effects. You will need to **capture precise screenshots**
demonstrating the differences between the Before and After states, as described
[below](#capturing-precise-screenshots).
Precise screenshots are necessary not only to document your intended
changes, but also to demonstrate that there are **no unintended side-effects**
or visual regressions. In fact, PRs that refactor templates or CSS often need to
include screenshots to explicitly demonstrate that there are no visual changes.
:::{important}
Wherever possible, use still screenshots rather than videos.
:::
Static screenshots are much easier to review than screencast videos. Use a video
only when necessary to demonstrate an interaction, and only to supplement still
screenshots. Always include screenshots for any aspects of your changes which
can be seen on a still screenshot. See
[below](#capturing-and-presenting-short-videos) for how to capture reviewable videos.
For updates or changes to CSS class rules, it's a good practice
to include the results of a [`git grep`][git-grep] search for
the class name(s) to confirm that you've tested and captured screenshots
of all the impacted areas of the UI or Zulip documentation.
```console
$ git grep '.example-class-name' web/templates/ templates/
templates/corporate/...
templates/zerver/...
web/templates/...
```
Never include screenshots of your code or the GitHub UI, which reviewers can
easily see directly.
## What are precise Before/After screenshots?
Precise Before/After screenshots have two essential qualities:
1. **The state of the UI should be identical between screenshots.**
For example, a screenshot of the message feed should have messages scrolled to the
same spot, the focus ring should be around the same message, etc. The goal is to
highlight the differences your PR introduces, and not include any unintended noise in
the screenshots from things that just happen to be different.
1. **The screenshots must have the exact same pixel dimensions.** If the Before
screenshot is 800px by 600px, the After screenshot should be too. This is
to make sure that there's a pixel-to-pixel correspondence of everything
you've captured onscreen.
## Why bother with precise Before/After screenshots?
Capturing precise screenshots serves two primary purposes:
1. For you as a contributor, **checking your own screenshots** will help you to
catch any regressions on your own, prior to submitting your PR. It'll also
help you point out changes or shifts for reviewers to consider, which may
require some design discussion.
2. For reviewers, checking screenshots is a quick way to **verify** that a PR
does what's expected, and provide **feedback** on visual changes without
pulling down the PR.
## Capturing precise screenshots
This section describes different techniques for producing pixel-precise
screen captures. To master these techniques, you'll likely need to spend some time
working with your capture tools of choice, whether they're part of your browser or
operating system, or a third-party screen capture tool or browser plugin.
### Using Git to get required states
Git is, of course, your friend for setting up the UI state for Before and After
screenshots: the Before shot will typically be of the `main` branch updated from
upstream, while the After shot will be of your PR's working branch. Take the time
to rebase your working branch over the latest `main`, too, before capturing your
screenshots.
Sometimes you may be asked to present alternative looks to your PR in tandem
with a discussion [#design](https://chat.zulip.org/#topics/channel/101-design)
channel in the Zulip development community, in which case you'll need to walk
through different commits on your branch—or make judicious use of `git stash`
and `git stash pop`.
### Capturing precise screenshots with your browser
The easiest cross-platform way of capturing screenshots of your PR's changes
is to use your browser. Both Chrome and Firefox have built-in screenshot capabilities,
so it's worth your time to explore how those work. Firefox's capabilities are neatly
tied to its responsive design view, which means you can very precisely size the viewport
to highlight the changes in your PR. (And if you're not used to developing in Firefox,
this can be a convenient way to check your work in a different browser, too.)
For example, it's easy to capture a mobile-scale viewport in Firefox like this:
| In responsive mode for capture | Resulting screenshot |
| ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| ![Firefox in responsive design mode](/images/firefox-rwd-capture-mobile.png) | ![Mobile-scale capture from Firefox](/images/firefox-mobile-scale-350x600.png) |
For another example, if you're making changes to the left sidebar, you'll want to open
the viewport wider, until the left sidebar is showing:
![Firefox in opened wider to show sidebar](/images/firefox-rwd-capture-medium.png)
The great thing about capturing screenshots in your browser is that it is very easy to ensure that you meet both criteria for precise screenshots: a UI in the same state for
the Before and After shots, and screenshots that are the same exact dimensions—easily verified by the values you set on the width and height of the viewport.
Additionally, if you need to demonstrate states like `:hover` or `:active` on an element,
you can use your browser's developer tools to emulate that state for you, without your
needing to fiddle with the keyboard or mouse.
### Capturing precise screenshots with native OS tools
Most of the time, browser-captured screenshots are ideal. Screens are generally
high-enough resolution that your reviewers (and you) can quickly recognize any
changes just by comparing the full-size screenshots.
However, if you really do need to illustrate a change in closer detail, it can be helpful
to use your operating system's native screen-capture tools. See if your OS allows
you to specify a box of fixed dimensions that you can use to repeatedly capture the same
area of the screen.
For example, perhaps there's something very subtle about the channel list that a PR needs
to highlight:
![Fixed region capture using OS tools](/images/os-fixed-capture-box.png)
Note that [a fixed, reusable capture box is different from a freehand capture](#freehand-versus-fixed-screenshots),
because the OS enables you to call up the same fixed-size box for repeated screenshots
of the same region of the screen, helping you to maintain pixel precision in the
Before and After shots. Just be careful not to move your browser window around between
shots.
### Capturing precise screenshots with other software
If you find that your operating system or browser's tools are insufficient for capturing
the screenshots that you need, you might want to explore [third-party software](#screenshot-and-gif-software). Just keep
in mind the two qualities your screenshots need to maintain: identical UI state, and
pixel-precise dimensions between Before and After shots.
### Freehand versus fixed screenshots
It may be tempting to freehand your screenshots, perhaps by using your operating
system's screen-capture utility that allows freehand dragging of a capture area.
The two freehand-captured images below represent Before and After states. Can you
spot any changes to the UI? How about if you open each image in a separate tab in
your browser? (Typically a reviewer will open up the full-size images in separate
tabs in order to more easily compare them.)
| Before | After |
| --------------------------------------------------------------- | ------------------------------------------------------------- |
| ![Freehand screenshot, before](/images/freehand-cap-before.png) | ![Freehand screenshot, after](/images/freehand-cap-after.png) |
Here's an animated GIF approximating a comparison of the full-size images:
![Comparing freehand screenshots](/images/freehand-capture-compare.gif)
Compare those to this set of screenshots. These are the same Before and After
states as captured in the freehand shots above, but these have been captured using
a fixed box offered by an operating system's native screen-capture utility:
| Before | After |
| --------------------------------------------------------- | ------------------------------------------------------- |
| ![Fixed screenshot, before](/images/fixed-cap-before.png) | ![Fixed screenshot, after](/images/fixed-cap-after.png) |
Now see if you can catch the change between the Before and After images in this GIF:
![Comparing fixed screenshots](/images/fixed-capture-compare.gif)
Those screenshots make it obvious that the space between the Zulip logo and the top
of the message area has been reduced. Without precise screenshots, that change
would've been nearly impossible to detect.
### Providing sufficient UI context
The images above might have been intended to show close details of the Zulip logo
and message area. But the contributor could have also just used their browser
(Firefox, in this case) to capture more of the viewport:
| Before | After |
| ----------------------------------------------------------------- | --------------------------------------------------------------- |
| ![Browser screenshot, before](/images/browser-capture-before.png) | ![Browser screenshot, after](/images/browser-capture-after.png) |
Even if your work is targeted at a specific element, detailed screenshots are not
always the best choice. CSS adjustments are notorious for having unintended consequences,
so it's often a smart choice to show as much of the UI as you can.
As with the fixed-box screenshots above, having pixel-precise screenshots
where the UI is in an identical state and there isn't a bunch of unintended movement
or other noise, the browser captures above make catching the space shift much easier.
## Capturing and presenting short videos
Still screenshots are almost always superior to videos. They are easier to compare, and
enable reviewers to focus more precisely on the changes your PR introduces.
If you absolutely must show off a brief interaction on your PR, see whether your operating
system will allow you to again set a fixed box for capturing video of a region of your
screen.
Be sure to edit your video down to the shortest length possible. And rather
than post the video—whose format may not be suitable for the web or accessible to all
reviewers—use a video-to-GIF service like [ezgif.com](https://ezgif.com/video-to-gif)
to create a looping animation showing off the interaction.
Here, for an example, is a short looping animation from [an actual PR](https://github.com/zulip/zulip/pull/35969)
that modified some interactions on the compose box:
![Animation showing compose box](/images/general-chat-after.gif)
It's worth noting here that [the full PR](https://github.com/zulip/zulip/pull/35969)
included plenty of static screenshots in addition to the GIFs showing off interactivity.
Finally, make sure a person watching your video can see what you're typing, or where on
the screen you're tapping or clicking. Use the "show touches" or "include the mouse
pointer" feature if your screen-recording software supports it. To show keyboard
interactions, e.g., using a [keyboard shortcut](https://zulip.com/help/keyboard-shortcuts),
you can use a [keypress visualizer](#keypress-visualizers-by-platform) while recording.
## Presenting screenshots on your pull request
Now that you've got all these screenshots, how do you present them in the
description for your PR?
### Using tables for Before/After comparisons
For presenting Before and After states, use GitHub's table syntax to render
them side-by-side. Reviewers can open the full-size image from GitHub for quick
and easy comparison:
```
### Descriptive header for images:
| Before | After |
| --- | --- |
| ![image-before](uploaded-file-information) | ![image-after](uploaded-file-information)
```
To quickly insert these tables, consider
[creating a GitHub Saved Reply](https://docs.github.com/en/get-started/writing-on-github/working-with-saved-replies/creating-a-saved-reply).
### Making screenshots collapsible
When including numerous screenshots or screencasts, consider grouping them
in details/summary tags to reduce visual clutter and the scroll length of
pull-request descriptions and comments. This is especially useful when you
have several screenshots or screencasts to include in your PR description
or follow-up comments, as you can put groups of related images in separate
details/summary tags.
Do think about your reviewers' comfort when using more than one set of
details/summary tags, as it is generally much easier to scroll past a
bunch of screenshots than it is to open numerous collapsed details/summary
tags.
```
<details>
<summary>Descriptive summary of image group</summary>
| Before | After |
| --- | --- |
| ![image-before](uploaded-file-information) | ![image-after](uploaded-file-information) |
| ![image-2-before](uploaded-file-information) | ![image-2-after](uploaded-file-information) |
</details>
```
### Presenting documentation changes
If you've updated existing documentation in your pull request,
include a link to the current documentation above the screenshot
of the updates. That way a reviewer can quickly compare the current
documentation while reviewing your changes.
```
[Current documentation](link-to-current-documentation-page)
![image-after](uploaded-file-information)
```
[git-grep]: https://git-scm.com/docs/git-grep
[screenshots-gifs]: ../contributing/presenting-visual-changes.md#screenshot-and-gif-software
[zulip-dev-community]: https://chat.zulip.org
[link-to-message]: https://zulip.com/help/link-to-a-message-or-conversation#get-a-link-to-a-specific-message
[dev-community-linkifiers]: https://zulip.com/development-community/#linking-to-github-issues-and-pull-requests
## Screenshot and GIF software
You can check out the following tools for capturing screenshots and videos/GIFs.
### Screenshot tools by platform
#### Browser
- [Firefox screenshots](https://support.mozilla.org/en-US/kb/take-screenshots-firefox) without any plugins
- [Chrome screenshots](https://developer.chrome.com/docs/devtools/device-mode#screenshot) without any plugins
- [LightShot Screenshot](https://app.prntscr.com/en/index.html) (Chrome, Firefox, IE & Opera)
- [Chrome Capture](https://chrome.google.com/webstore/detail/chrome-capture-screenshot/ggaabchcecdbomdcnbahdfddfikjmphe?hl=en)
#### macOS
- [Take a screenshot on Mac](https://support.apple.com/en-us/102646)
- [LightShot Screenshot](https://app.prntscr.com/en/index.html)
- [Gyazo](https://gyazo.com/en)
#### Windows
- [Use Snipping Tool to capture screenshots](https://support.microsoft.com/en-us/windows/use-snipping-tool-to-capture-screenshots-00246869-1843-655f-f220-97299b865f6b)
- [LightShot Screenshot](https://app.prntscr.com/en/index.html)
- [Gyazo](https://gyazo.com/en)
- [ScreenToGif](https://www.screentogif.com/)
#### Linux
- [GNOME Screenshots and screencasts](https://help.gnome.org/gnome-help/screen-shot-record.html)
- [Spectacle by KDE](https://apps.kde.org/spectacle/)
### GIF tools by platform
#### Browser
- [GIPHY](https://giphy.com)
- [Chrome Capture](https://chrome.google.com/webstore/detail/chrome-capture/ggaabchcecdbomdcnbahdfddfikjmphe?hl=en)
(Tip: Use `Alt`+`I` to interact with the page while recording)
#### macOS
- [QuickTime](https://support.apple.com/en-in/HT201066)
- [GIPHY](https://giphy.com/apps/giphycapture)
- [Zight](https://zight.com)
- [Kap](https://getkap.co)
- [Gifski](https://sindresorhus.com/gifski)
- [Gyazo GIF](https://gyazo.com/en)
#### Windows
- [ScreenToGif](https://www.screentogif.com)
- [Gyazo GIF](https://gyazo.com/en)
#### Linux
- [Peek](https://github.com/phw/peek)
- [SilentCast](https://github.com/colinkeenan/silentcast)
### Keypress visualizers by platform
#### macOS
- [KeyCastr](https://github.com/keycastr/keycastr)
#### Windows
- [YetAnotherKeyDisplayer(YAKD)](https://github.com/Jagailo/YetAnotherKeyDisplayer)
#### Linux
- [hibiki](https://github.com/linuxmobile/hibiki), for Wayland.
- [screenkey](https://gitlab.com/screenkey/screenkey), for X11.

View File

@@ -0,0 +1,157 @@
# Reporting bugs
There are several ways to report bugs (or possible bugs) you encounter in Zulip:
- If you have a concrete bug report with steps to reproduce the behavior, [file an
issue](#filing-a-github-issue) in the appropriate GitHub repository.
- If you are not sure whether the issue you encountered is a bug, or how to
reproduce it, [start a
conversation](#starting-a-conversation-about-a-possible-bug) in the Zulip
development community.
- To report a possible security issue, contact Zulip's security team at
[security@zulip.com](mailto:security@zulip.com). _Do not_ report security issues
publicly (in GitHub or in the Zulip development community). We create a CVE for
every security issue in our released software.
- If reporting a bug requires sharing private details about your
organization, email [support@zulip.com](mailto:support@zulip.com).
No matter where you report the bug, please follow the instructions below for
what to include in a bug report.
## What to include in a bug report
1. **Describe** what you were expecting to see, what you saw instead, and steps
that may help others reproduce the surprising behavior you experienced.
Include screenshots and/or screen captures (see
[recommended tools](../contributing/presenting-visual-changes.md#screenshot-and-gif-software))
if they help communicate what you are describing, but avoid posting long videos.
1. **Indicate the [version](https://zulip.com/help/view-zulip-version)** of the
Zulip app where you encountered the bug. It may also be helpful to note your
operating system, whether you are using the web app or the desktop app, and
your browser if using the web app.
## Filing a GitHub issue
Filing a GitHub issue works best when:
- You are confident that the behavior you encountered is a bug, not some quirk
of how a feature works that may turn out to be intentional.
- You can describe clearly what you were expecting to see, and what you saw instead.
- You can provide steps for someone else to reproduce the issue you encountered.
This is important for developers to be able to fix the bug, and test that
their fix worked.
If all of the above accurately describe your situation, please file an issue!
Otherwise, we recommend [starting a
conversation](#starting-a-conversation-about-a-possible-bug) in the Zulip
development community so that the problem you encountered can be discussed
interactively.
Steps and best practices for filing a GitHub issue:
1. Report the issue in the **appropriate [Zulip
repository](https://github.com/zulip)**. The most commonly used repositories
are:
- [zulip/zulip](https://github.com/zulip/zulip/issues) for issues with the
Zulip web app or server. A good default if you aren't sure which repository
to use.
- [zulip/zulip-flutter](https://github.com/zulip/zulip-flutter/issues) for
issues with the mobile apps.
- [zulip/zulip-desktop](https://github.com/zulip/zulip-desktop/issues) for
issues that are specific to the Zulip desktop app, and therefore _do not_
occur in the web app.
- [zulip/zulip-terminal](https://github.com/zulip/zulip-terminal/issues) for
issues with the terminal app.
2. Do a **quick search** of the repository to see if your issue has already
been filed. If it has, you can add a comment if that seems helpful.
3. If you are aware of a related discussion in the Zulip development community,
please **cross-link** between the issue and the discussion thread. [Link to a
specific
message](https://zulip.com/help/link-to-a-message-or-conversation#get-a-link-to-a-specific-message)
in the discussion thread, as message links will still work even if the topic is
renamed or resolved.
To encourage prompt attention and discussion for a bug report you have filed,
you can send a message in the Zulip development community with the key points
from your report. Be sure to [link to the GitHub
issue](https://zulip.com/development-community/#linking-to-github-issues-and-pull-requests).
See the following section for advice on where and how to start the conversation.
## Starting a conversation about a possible bug
If you are not sure whether the issue you encountered is a bug, or how to
reproduce it, we highly recommend reporting it in the [Zulip development
community](https://zulip.com/development-community/). It's the best place to
interactively discuss your problem.
Steps and best practices for starting a conversation:
1. [**Join** the Zulip development
community](https://zulip.com/development-community/) if you don't already
have an account.
2. Pick an **appropriate channel** to report your issue:
- [#issues](https://chat.zulip.org/#narrow/channel/9-issues) for issues with
the Zulip web app or server. Use this channel if you aren't sure which
channel is most appropriate.
- [#mobile](https://chat.zulip.org/#narrow/channel/48-mobile) for issues with
the mobile apps.
- [#desktop](https://chat.zulip.org/#narrow/channel/16-desktop) for issues
that are specific to the Zulip desktop app, and therefore _do not_
occur in the web app.
- [#zulip-terminal](https://chat.zulip.org/#narrow/channel/206-zulip-terminal)
for issues with the terminal app.
- [#production
help](https://chat.zulip.org/#narrow/channel/31-production-help) for issues
related to self-hosting Zulip. See the [troubleshooting
guide](../production/troubleshooting.md) for additional details.
3. **[Start a new topic](https://zulip.com/help/introduction-to-topics#how-to-start-a-new-topic)**
for discussing your issue, using a brief summary of the issue as the name of
the topic.
If you aren't sure where to post or how to name your topic, don't worry!
Moderators can always rename the topic, or move the thread to another channel.
Once a possible bug is reported, members of the development community will jump
in to discuss whether the report constitutes a bug, how to reproduce it, and how
it can be resolved. The initial reporter can help by monitoring the discussion
and replying to any follow-up questions. If the report is determined to be a
reproducible bug, a GitHub issue will be filed to keep track of it (see below).
## Managing bug reports
This section describes our process for managing bugs. All community members are
encouraged to help make sure this process runs smoothly, whether or not they
originally reported the bug.
Whenever a bug is tracked in GitHub and also discussed in the development
community, be sure to cross-link between the issue and the conversation. [Link
to a specific
message](https://zulip.com/help/link-to-a-message-or-conversation#get-a-link-to-a-specific-message)
in the discussion thread, as message links will still work even if the topic is
renamed or resolved.
- If you encounter a definite bug with a clear reproducer and significant user
impact, it is best to both file a GitHub issue and immediately start a
discussion in the development community. This helps us address important
issues as quickly as possible.
- For minor bugs (e.g., a visual glitch in a settings menu for very long channel
names), filing a GitHub issue is sufficient.
- If a potential bug discussed in the development community is confirmed to be
an actual, reproducible bug, anyone can help out by filing a GitHub issue to
track it:
- In some cases, especially if we're planning to fix the issue right away, the
GitHub issue description can simply quote and link to a message from the
discussion in the development community -- no need to stress over making it
perfect.
- [Use Zulipbot](../contributing/zulipbot-usage.md) to add the appropriate
labels, including “bug” and at least one area label; leave a comment on
the issue if you don't know what area labels to use.
- You can add the “help wanted” label (and claim the issue if you like) if
that is appropriate based on the discussion. Note that sometimes we won't
mark a reproducible bug as “help wanted” for various reasons. For example,
we might want a core contributor to take it on, or the fix might be planned
as part of a larger project.
- Don't forget to cross-link between the issue and the discussion.
- If a bug report in GitHub is not sufficiently clear, Zulip maintainers will
often encourage the reporter to discuss it interactively in the development
community.

View File

@@ -0,0 +1 @@
../../SECURITY.md

View File

@@ -0,0 +1,135 @@
# Pull request review process
Pull requests submitted to Zulip go through a rigorous review process, which is
designed to ensure that we are building a high-quality product with a
maintainable codebase. This page describes the stages of review your pull
request may go through, and offers guidance on how you can help keep your pull
request moving along.
## Labels for managing the stages of pull request review
In the Zulip server/web app repository
([`zulip/zulip`](https://github.com/zulip/zulip/)), we use GitHub labels to help
everyone understand where a pull request is in the review process. These labels
are noted below, alongside their corresponding pull-request stage. Each label is
removed by the reviewer for that stage when they have no more feedback on the PR
and consider it ready for the next stage of review.
Sometimes, a label may also be removed because significant changes by
the contributor are required before the PR ready to be reviewed again. In that
case, the contributor should post a comment mentioning the reviewer when the
changes have been completed, unless the reviewer requested some other action.
## Stages of a pull request review
This section describes the stages of the pull request review process. Each stage
may require several rounds of iteration. Don't feel daunted! Not every PR will
require all the stages described, and the process often goes quite quickly for
smaller changes that are clearly explained.
1. **Product review.** Oftentimes, seeing an initial implementation will make it
clear that the product design for a feature needs to be revised, or that
additional changes are needed. The reviewer may therefore ask you to amend or
change the implementation. Some changes may be blockers for getting the PR
merged, while others may be improvements that can happen afterwards. Feel
free to ask if it's unclear which type of feedback you're getting.
(Follow-ups can be a great next issue to work on!)
Your PR might be assigned the [product
review](https://github.com/zulip/zulip/pulls?q=is%3Aopen+is%3Apr+label%3A%22product+review%22)
label at this stage, or later in the review process as questions come up. You
can also add this label yourself if appropriate. If doing so, be sure to
clearly outline the product questions that need to be addressed.
2. **QA.** If your PR makes user-facing changes, it may get a round of testing
without reference to the code. You will get feedback on any user-facing bugs
in the implementation. To minimize the number of review round-trips, make
sure to [thoroughly test](../contributing/code-reviewing.md#manual-testing)
your own PR prior to asking for review.
Your PR might be assigned the [QA
needed](https://github.com/zulip/zulip/pulls?q=is%3Aopen+is%3Apr+label%3A%22QA+needed%22)
label at this stage, or later on if re-testing is required.
3. **Initial code review.** All PRs will go through one or more rounds of code
review. Your code may initially be [reviewed by other
contributors](../contributing/code-reviewing.md). This helps us make good use
of project maintainers' time, and helps you make progress on the PR by
getting quick feedback. A project maintainer may leave a comment asking
someone with expertise in the area you're working on to review your work.
4. **Maintainer code review.** In this phase, a Zulip maintainer will do a
thorough review of your proposed code changes. Your PR may be assigned the
[maintainer
review](https://github.com/zulip/zulip/pulls?q=is%3Aopen+is%3Apr+label%3A%22maintainer+review%22)
label at this stage.
5. **Documentation review.** If your PR includes documentation changes, those
changes will require review. This generally happens fairly late in the review
process, once the UI and the code are unlikely to undergo major changes.
Maintainers may indicate that a PR is ready for documentation review by
adding a [help center
review](https://github.com/zulip/zulip/pulls?q=is%3Aopen+is%3Apr+label%3A%22help+center+review%22)
and/or [api docs
review](https://github.com/zulip/zulip/pulls?q=is%3Aopen+is%3Apr+label%3A%22api+docs+review%22)
label, and mentioning a documentation maintainer in the comments.
6. **Integration review**. This is the final round of the review process,
generally done by `@timabbott` for server and web app PRs. A maintainer will
usually assign the [integration
review](https://github.com/zulip/zulip/pulls?q=is%3Aopen+is%3Apr+label%3A%22integration+review%22)
label when the PR is ready for this phase.
## How to help move the review process forward
If there are no comments on your PR for a week after you submit it, you can
check again to make sure that it's ready for review, and then post a quick
comment to remind Zulip's maintainers to take a look at your work. Consider also
[asking for a
review](../contributing/code-reviewing.md#asking-for-a-code-review) in the Zulip
development community.
After that, the key to keeping your review moving through the review process is to:
- Address _all_ the feedback to the best of your ability.
- Make it clear when the requested changes have been made
and you believe it's time for another look.
- Make it as easy as possible to review the changes you made.
In order to do this, when you believe you have addressed the previous round of
feedback on your PR as best you can, post a comment asking reviewers to take
another look. Your comment should make it easy to understand what has been done
and what remains by:
- Summarizing the changes made since the last review you received. Be clear
about which issues you've resolved (and how!).
- Highlighting remaining questions or decisions, with links to any relevant
threads in the [Zulip development
community](https://zulip.com/development-community/). It should be clear which
feedback you _haven't_ addressed yet.
- Providing updated screenshots and information on manual testing if
appropriate.
The easier it is to review your work, the more likely you are to receive quick
feedback.
## Follow-ups
Sometimes reviewers will comment on "follow-ups" to your pull request. A
follow-up is something that can be done separately from the changes in the
current pull request, because it's tangential to the current changes, or would
be the next task to do once the current changes are completed.
You should prioritize completing the current pull request over working on
follow-ups. However, you are expected to manage follow-ups to your work:
1. If possible, it's best to complete follow-ups as soon as you are done with
the current pull request. That way, both you and reviewers have the context
for the changes fresh in mind.
1. If you don't expect to have time to complete a follow-up soon (or aren't sure
if you will), please file an issue to track it. Include a description of the
required changes, and a link to the comment where the follow-up was
discussed. You can copy-paste the issue description from the prior
discussion, but be sure that what you write makes sense without needing to
refer to the original thread.

View File

@@ -0,0 +1,168 @@
# Submitting a pull request
A pull request (PR) is a presentation of your proposed changes to Zulip. Your aim
should be to explain your changes as clearly as possible. This will help
reviewers evaluate whether the proposed changes are correct, and address any
open questions. Clear communication helps the whole Zulip project move more
quickly by saving maintainers time when they review your code. It will also make
a big difference for getting your work integrated without delay.
You will go through the following steps to prepare your work for review. Each
step is described in detail below, with links to additional resources:
1. Write your code [with clarity in mind](#write-clear-code).
1. [Organize your proposed changes](#organize-your-proposed-changes) into a
series of commits that tell the story of how the codebase will change.
1. [Explain your changes](#explain-your-changes) in the description for your
pull request, including
[screenshots](../contributing/presenting-visual-changes.md) for visual changes.
1. Carefully [review your own work](#review-your-own-work).
1. [Submit your pull request](#submit-your-pull-request-for-review) for review.
To learn more about putting together pull requests maintainers will love to
review, check out [this FOSDEM
talk](https://fosdem.org/2026/schedule/event/L7ERNP-prs-maintainers-will-love/)
by a Zulip maintainer.
See the [pull request review process](../contributing/review-process.md) guide
for a detailed overview of what happens once your pull request is submitted.
## Write clear code
When you write code, you should make sure that you understand _why it works_ as
intended. This is the foundation for being able to explain your proposed changes
to others.
Zulip’s coding philosophy is to focus relentlessly on making the codebase easy
to understand and difficult to make dangerous mistakes. Our linters, tests, code
style guidelines, [testing philosophy](../testing/philosophy.md), [commit
discipline](../contributing/commit-discipline.md), this documentation, and our
attention to detail in [code review](../contributing/review-process.md) are all
important elements of this strategy. Following these guidelines is essential if
you'd like your work to be merged into the project.
If any part of your contribution is from someone else (code snippets, images,
sounds, or any other copyrightable work, modified or unmodified), be sure to
review the instructions on how to [properly attribute](./licensing.md) the work.
## Organize your proposed changes
The changes you submit will be organized into a series of commits. A PR might
contain a single commit, or a dozen or more, depending on the changes being
made.
Commits help you tell the story of how each change you are proposing is
necessary or helpful. If you were presenting your changes, a commit might be a
slide in your presentation. As a rough guideline, a good commit usually has less
than 100 lines of code changes. If you can see a way to split a commit into
different pieces of meaning, you should split it.
Keep in mind that you are presenting your final work product, _not_ the path you
took to get there. You should never have a commit that can be described as
fixing a mistake in an earlier commit in the same PR; use `git rebase -i` to fix
the mistake in the original commit.
See the [commit discipline guide](../contributing/commit-discipline.md) for more
details on how to structure your commits, and guidelines on how to write good
commit messages. Your pull request can only be reviewed once you've followed
these guidelines to the best of your ability. This makes it much easier for
reviewers to understand your work and identify any problems.
Ideally, when reviewing a pull request for a complex project, Zulip's
maintainers should be able to verify and merge the first few commits, and leave
comments on the rest. It is by far the most efficient way to do collaborative
development, since one is constantly making progress, we keep branches small,
and reviewers don't end up repeatedly going over the earlier parts of a pull
request.
## Explain your changes
By the time you are submitting your pull request, you should already have put a
lot of thought into how to organize and present your proposed changes. In the
description for your pull request, you will:
- Provide an overview of your changes.
- Note any differences from prior plans (e.g., from the description of the issue you
are solving).
- Call out any open questions, concerns, or decisions you are uncertain about.
The review process will go a lot more smoothly if points of uncertainty are
explicitly laid out.
- Include screenshots for all visual changes, so that they can be reviewed
without running your code. Be sure to follow our
[guide on presenting visual changes](../contributing/presenting-visual-changes.md).
If you have a question about a specific part of your code that you expect to be
resolved during the review process, put it in a PR comment attached to a
relevant part of the changes.
Take advantage of [GitHub's formatting][github-syntax] to make your pull request
description and comments easy to read.
[github-syntax]: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax
### Discussions in the development community
Any questions for which broader feedback or visibility is helpful are discussed
in the [Zulip development community](https://zulip.com/development-community/).
If there has been a conversation in the [Zulip development
community][zulip-dev-community] about the changes you've made or the issue your
pull request addresses, please cross-link between your pull request and those
conversations in both directions. This provides helpful context for maintainers
and reviewers. Specifically, it's best to link from your pull request [to a
specific message][link-to-message], as these links will still work even if the
topic of the conversation is renamed, moved or resolved.
Once you've created a pull request on GitHub, you can use one of the [custom
linkifiers][dev-community-linkifiers] in the development community to easily
link to your pull request from the relevant conversation.
[zulip-dev-community]: https://chat.zulip.org
[link-to-message]: https://zulip.com/help/link-to-a-message-or-conversation#get-a-link-to-a-specific-message
[dev-community-linkifiers]: https://zulip.com/development-community/#linking-to-github-issues-and-pull-requests
## Review your own work
Before requesting a review for your pull request, follow our [review
guide](./code-reviewing.md#reviewing-your-own-code) to carefully review and test
your own work. You can often find things you missed by taking a step back to
look over your work before asking others to do so. Catching mistakes yourself
will help your PRs be merged faster, and reviewers will appreciate the quality
and professionalism of your work.
The pull request template in the `zulip/zulip` repository has a checklist of
reminders for points you need to cover in your review. Make sure that all the
relevant items on the self-review checklist have been addressed, and check them
off on the list.
## Submit your pull request for review
If you are new to Git, see our guide on [making a pull
request](../git/pull-requests.md) for detailed technical instructions on how to
submit a pull request.
When submitting your PR, you will need to make sure that the pull request passes
all CI tests. You can sometimes request initial feedback if there are open
questions that will impact how you update the tests. But in general,
maintainers will wait for your PR to pass tests before reviewing your work.
If your PR was not ready for review when you first posted it (e.g., because it
was failing tests, or you weren't done working through the self-review
checklist), notify maintainers when you'd like them to take a look by posting a
clear comment on the main GitHub thread for your PR with details on any changes
from the original version; this is very helpful for any maintainers who already
read the draft PR.
## Draft pull requests
If it helps your workflow, you can submit your pull request marked as
a [draft][github-help-draft-pr] while you're still working on it. When ready for
review:
1. Make sure your PR is no longer marked as a [draft][github-help-draft-pr], and
doesn't have "WIP" in the title.
1. Post a quick "Ready for review!" comment on the main GitHub thread for your
PR.
[github-help-draft-pr]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests

View File

@@ -0,0 +1,111 @@
# Suggesting features and improvements
If you have ideas for how to make Zulip better, we'd love to hear from you! Many
improvements start with a user's suggestion. The best way to suggest a feature
or an improvement is by starting a conversation in the [Zulip development
community](https://zulip.com/development-community/). It's a great way to engage
interactively with members of the community, and explore how best to improve
Zulip for you and other users.
Usually, if the discussion leads to a concrete proposal, Zulip's product team
will follow up by filing a GitHub issue to track the idea. Many conversations do
not immediately lead to a GitHub issue, and that's OK! Sometimes the time is not
right to pin down a plan, or more ideas need to come in before a great proposal
emerges. Regardless of whether a discussion results in immediate action, we
appreciate the time everyone takes to make suggestions and brainstorm ideas.
## What to include in your proposal
- Describe your idea. It's absolutely fine to bring up a problem without
suggesting a concrete solution.
- Provide context on how the change you are proposing would help you or your
organization. It is often helpful to describe how you are using Zulip (e.g.,
"I work at a small startup", or "I'm teaching a class"). This lets us combine
our Zulip expertise with your requirements to come up with a great design for
a feature.
- If you are aware of a related issue in GitHub or a prior conversation in the
development community, please include a link.
## Starting a conversation about a suggested feature or improvement
Steps and best practices for starting a conversation:
1. [**Join** the Zulip development
community](https://zulip.com/development-community/) if you don't already
have an account.
2. Pick an **appropriate channel** to discuss your idea:
- [#feedback](https://chat.zulip.org/#narrow/channel/137-feedback) for suggestions for
the Zulip web app or server. Use this channel if you aren't sure which channel is
most appropriate.
- [#mobile](https://chat.zulip.org/#narrow/channel/48-mobile) for suggestions
for the mobile apps.
- [#desktop](https://chat.zulip.org/#narrow/channel/16-desktop) for suggestions
that are specific to the Zulip desktop app.
- [#zulip-terminal](https://chat.zulip.org/#narrow/channel/206-zulip-terminal)
for suggestions for the terminal app.
- [#production
help](https://chat.zulip.org/#narrow/channel/31-production-help) for suggestions
related to self-hosting Zulip.
3. **[Start a new topic](https://zulip.com/help/introduction-to-topics#how-to-start-a-new-topic)**
for discussing your suggestions, using a brief summary of your idea as the
name of the topic.
If you aren't sure where to post or how to name your topic, don't worry!
Moderators can always rename the topic, or move the thread to another channel.
Members of the development community will jump in to discuss your idea. You can
help by participating in the discussion, including replying to any follow-up
questions, and helping develop the proposal. The discussion may conclude with an
issue being filed in GitHub to track the plan that was developed.
## Filing a GitHub issue
Filing a GitHub issue can be effective when you have a very specific proposal
for a feature or improvement. Steps and best practices for filing an issue:
1. File the issue in the **appropriate [Zulip
repository](https://github.com/zulip)**. The most commonly used repositories
are:
- [zulip/zulip](https://github.com/zulip/zulip/issues) for suggestions for the
Zulip web app or server. A good default if you aren't sure which repository
to use.
- [zulip/zulip-flutter](https://github.com/zulip/zulip-flutter/issues) for
suggestions for the mobile apps.
- [zulip/zulip-desktop](https://github.com/zulip/zulip-desktop/issues) for
suggestions that are specific to the Zulip desktop app.
- [zulip/zulip-terminal](https://github.com/zulip/zulip-terminal/issues) for
suggestions for the terminal app.
2. Do a **quick search** of the repository to see if there is already a similar
request. If there is, add a comment explaining why you would also appreciate
the proposed change, and make any additional suggestions you might have. Do
not file a new issue.
3. If you are aware of a related discussion in the Zulip development community,
please **cross-link** between the issue and the discussion thread. [Link to a
specific
message](https://zulip.com/help/link-to-a-message-or-conversation#get-a-link-to-a-specific-message)
in the discussion thread, as message links will still work even if the topic is
renamed or resolved.
## Evaluation and onboarding feedback
If you have been involved in the decision to use (or not use!) Zulip, or are
currently considering it, we'd love to hear about it. You can contact us
publicly in the [#feedback](https://chat.zulip.org/#narrow/channel/137-feedback)
channel in the [Zulip development
community](https://zulip.com/development-community/), or privately at
[feedback@zulip.com](mailto:feedback@zulip.com).
Here are some questions we're especially interested in:
- **Who you are**: Tell us a bit about your organization. What does it do? How many
people are involved?
- **Evaluation**: What is the process by which your organization chose or will
choose a team chat product?
- **Pros and cons**: What are the pros and cons of Zulip for your organization,
and the pros and cons of other products you are evaluating?
- **Features**: What are the features that are most important for your
organization? In the best-case scenario, what would your chat solution do
for you?
- **Onboarding**: If you remember, what were your impressions during your first
few minutes of using Zulip? What did you notice, and how did you feel? Was
there anything that stood out to you as confusing, or unexpected, or great?

View File

@@ -0,0 +1,94 @@
# Using zulipbot
Zulip uses [@zulipbot](https://github.com/zulipbot), a GitHub workflow bot
deployed on all Zulip repositories, to handle issues and pull requests in our
repositories in order to create a better workflow for Zulip contributors.
Its purpose is to work around various limitations in GitHub's
permissions and notifications systems to make it possible to have a
much more democratic workflow for our contributors. It allows anyone
to self-assign or label an issue, not just the core contributors
trusted with full write access to the repository (which is the only
model GitHub supports).
## Usage
- **Claim an issue** — Comment `@zulipbot claim` on the issue you want
to claim; **@zulipbot** will assign you to the issue and label the issue as
**in progress**.
- If you're a new contributor, **@zulipbot** will give you read-only
collaborator access to the repository and leave a welcome message on the
issue you claimed.
- You can also claim an issue that you've opened by including
`@zulipbot claim` in the body of your issue.
- If you accidentally claim an issue you didn't want to claim, comment
`@zulipbot abandon` to abandon an issue.
- **Label your issues** — Add appropriate labels to issues that you opened by
including `@zulipbot add` in an issue comment or the body of your issue
followed by the desired labels enclosed within double quotes (`""`).
- For example, to add the **bug** and **help wanted** labels to your
issue, comment or include `@zulipbot add "bug" "help wanted"` in the
issue body.
- You'll receive an error message if you try to add any labels to your issue
that don't exist in your repository.
- If you accidentally added the wrong labels, you can remove them by commenting
`@zulipbot remove` followed by the desired labels enclosed with double quotes
(`""`).
- **Find unclaimed issues** — Use the [GitHub search
feature](https://help.github.com/en/articles/using-search-to-filter-issues-and-pull-requests)
to find unclaimed issues by adding one of the following filters to your search:
- `-label: "in progress"` (excludes issues labeled with the **in progress** label)
- `no:assignee` (shows issues without assignees)
Issues labeled with the **in progress** label and/or assigned to other users have
already been claimed.
- **Collaborate in area label teams** — Receive notifications on
issues and pull requests within your fields of expertise on the
[Zulip server repository](https://github.com/zulip/zulip) by joining
the Zulip server
[area label teams](https://github.com/orgs/zulip/teams?utf8=✓&query=Server)
(Note: this link only works for members of the Zulip organization;
we'll happily add you if you're interested). These teams correspond
to the repository's
[area labels](https://github.com/zulip/zulip/labels), although some
teams are associated with multiple labels; for example, the **area:
message-editing** and **area: message view** labels are both related
to the
[Server message view](https://github.com/orgs/zulip/teams/server-message-view)
team. Feel free to join as many area label teams as you'd like!
After your request to join an area label team is approved, you'll receive
notifications for any issues labeled with the team's corresponding area
label as well as any pull requests that reference issues labeled with your
team's area label.
- **Track inactive claimed issues** — If a claimed issue has not been updated
for a week, **@zulipbot** will post a comment on the inactive issue to ask the
assignee(s) if they are still working on the issue.
If you see this comment on an issue you claimed, you should post a comment
on the issue to notify **@zulipbot** that you're still working on it.
If **@zulipbot** does not receive a response from the assignee within 3 days
of an inactive issue prompt, **@zulipbot** will automatically remove the
issue's current assignee(s) and the "in progress" label to allow others to
work on an inactive issue.
### Contributing
If you wish to help develop and contribute to **@zulipbot**, check out the
[zulip/zulipbot](https://github.com/zulip/zulipbot) repository on GitHub and read
the project's [contributing
guidelines](https://github.com/zulip/zulipbot/blob/main/.github/CONTRIBUTING.md#contributing) for
more information.