docs: Do a general update pass on OpenAPI developer docs.

This commit is contained in:
Tim Abbott 2020-06-20 19:03:51 -07:00
parent 318bc0ca1e
commit 0542c60466
2 changed files with 75 additions and 50 deletions

View File

@ -1,10 +1,28 @@
# Documenting REST API endpoints
This document explains the system for documenting [Zulip's REST
API](https://zulip.com/api/rest). This documentation is an
essential resource both for users and the developers of Zulip's mobile
and terminal apps. We carefully designed a system for both displaying
it and helping ensure it stays up to date as Zulip's API changes.
API](https://zulip.com/api/rest).
Zulip's API documentation is an essential resource both for users and
for the developers of Zulip's mobile and terminal apps. Our vision is
for the documentation to be sufficiently good that developers of
Zulip's apps should never need to look at the server's implementation
to answer questions about the API's semantics.
To achieve these goals, Zulip leverages the popular OpenAPI format as
the data source to ensure that Zulip's API documentation is correct
and remains so as Zulip's API evolves.
In particular, the top goal for this system is that all mistakes in
verifiable content (i.e. not the English explanations) should cause
the Zulip test suite to fail. This is incredibly important, because
once you notice one error in API documentation, you no longer trust it
to be correct, which ends up wasting the time of its users.
Since it's very difficult to not make little mistakes when writing any
code of untested code, the only good solution to this is a way to test
the documentation. We found dozens of errors in the process of adding
the validation Zulip has today.
Our API documentation is defined by a few sets of files:
@ -14,7 +32,9 @@ Our API documentation is defined by a few sets of files:
* The top-level templates live under `templates/zerver/api/*`, and are
written using the markdown framework that powers our [user
docs](../documentation/user.md), with some special extensions for
rendering nice code blocks and example responses.
rendering nice code blocks and example responses. We expect to
eventually remove most of these files where it is possible to
fully generate the documentation from the OpenAPI files.
* The text for the Python examples comes from a test suite for the
Python API documentation (`zerver/openapi/python_examples.py`; run via
`tools/test-api`). The `generate_code_example` macro will magically
@ -22,9 +42,20 @@ Our API documentation is defined by a few sets of files:
This structure ensures that Zulip's API documentation is robust to a
wide range of possible typos and other bugs in the API
documentation.
* The JavaScript examples are similarly generated and tested using
`zerver/openapi/javascript_examples.js`.
* The cURL examples are generated and tested using
`zerver/openapi/curl_param_value_generators.py`.
* The REST API index
(`templates/zerver/help/include/rest-endpoints.md`) in the broader
/api left sidebar (`templates/zerver/api/sidebar_index.md`).
* We have an extensive set of tests designed to validate that the data
in this file is correct, `zerver/tests/test_openapi.py` compares
every endpoint's accepted parameters in `views` code with those
declared in `zulip.yaml`. And [backend test
suite](../testing/testing-with-django.md) and checks that every API
response served during our extensive backend test suite matches one
the declared OpenAPI schema for that endpoint.
This first section is focused on explaining how the API documentation
system is put together; when actually documenting an endpoint, you'll
@ -52,16 +83,13 @@ The rest of this guide describes how each of these sections works.
### Description
At the top of any REST endpoint documentation page, you'll want to
explain what the endpoint does in clear English. Include
notes on how to use it correctly or what it's good or bad for, with
Displayed at the top of any REST endpoint documentation page, this
should explain what the endpoint does in clear English. Include
details on how to use it correctly or what it's good or bad for, with
links to any alternative endpoints the user might want to consider.
These sections should almost always contain a link to the
documentation of the relevant feature in `/help/`.
We plan to migrate to storing this description content in the
`description` field in `zerver/openapi/zulip.yaml`; currently, the
`description` section in `zulip.yaml` is not used for anything.
These sections should often contain a link to the documentation of the
relevant feature in `/help/`.
### Usage examples
@ -89,12 +117,7 @@ writes a Markdown file block that looks something like this:
{end_tabs}
```
For JavaScript and `curl` examples, we just have the example right
there in the markdown file. It is **critical** that these examples be
tested manually by copy-pasting the result; it is very easy and very
embarrassing to have typos result in incorrect documentation.
Additionally, JavaScript examples should conform to the coding style
and structure of [Zulip's existing JavaScript examples][javascript-examples].
#### Writing Python examples
For the Python examples, you'll write the example in
`zerver/openapi/python_examples.py`, and it'll be run and verified
@ -141,10 +164,10 @@ substitute it in place of
`{generate_code_example(python)|/messages/render:post|example}`
wherever that string appears in the API documentation.
### Arguments
### Parameters
We have a separate Markdown extension to document the arguments that
an API endpoint expects. You'll see this in files like
We have a separate Markdown extension to document the parameters that
an API endpoint supports. You'll see this in files like
`templates/zerver/api/render-message.md` via the following Markdown
directive (implemented in
`zerver/lib/bugdown/api_arguments_table_generator.py`):
@ -194,11 +217,15 @@ above.
that endpoint in `zerver/views/`, and inspect its arguments
declared using `REQ`.
You can check your formatting using two helpful tools.
You can check your formatting using these helpful tools.
* `tools/check-openapi` will verify the syntax of `zerver/openapi/zulip.yaml`.
* `tools/test-backend zerver/tests/test_openapi.py`; this test compares
your documentation against the code and can find many common
mistakes in how arguments are declared.
* `test-backend`: The full Zulip backend test suite will fail if
any actual API responses generated by the tests don't match your
defined OpenAPI schema. Use `test-backend --rerun` for a fast
edit/refresh cycle when debugging.
[rest-api-tutorial]: ../tutorials/writing-views.html#writing-api-rest-endpoints
@ -269,15 +296,11 @@ it? There's several major benefits to this system:
of manual management.
* Every Zulip server can host correct API documentation for its
version, with the key variables (like the Zulip server URL) already
pre-susbtituted for the user.
pre-sustituted for the user.
* We're able to share implementation language and visual styling with
our Helper Center, which is especially useful for the extensive
our Help Center, which is especially useful for the extensive
non-REST API documentation pages (e.g. our bot framework).
* Open source systems for displaying OpenAPI documentation (such as
Swagger) have poor UI, whereas Cloud systems that accept OpenAPI
data, like readme.io, make the above things much more difficult to
manage.
Using the standard OpenAPI format gives us flexibility, though; if the
state of third-party tools improves, we don't need to redo most of the
actual documentation work in order to migrate tools.
Using the standard OpenAPI format gives us flexibility, though; if we
later choose to migrate to third-party tools, we don't need to redo
the actual documentation work in order to migrate tools.

View File

@ -1,27 +1,31 @@
# OpenAPI configuration
The [OpenAPI](https://swagger.io/specification/) (formerly known as
Swagger) specification is a standardized way to describe how an API
functions. This description then can then be used by any tool that
supports the standard.
[OpenAPI][openapi-spec] is a popular format for describing an API. An
OpenAPI file can be used by various tools to generate documentation
for the API or even basic client-side bindings for dozens of
programming languages.
Zulip uses the Swagger spec to generate an API reference from the
`zulip.yaml` file. This page is a basic introduction to the format of
this file and how to add content to it.
Zulip's API is described in `zerver/openapi/zulip.yaml`. Our aim is
for that file to fully describe every endpoint in the Zulip API, and
for the Zulip test suite to fail should the API every change without a
corresponding adjustment to the documentation. In particular,
essentially all content in Zulip's [REST API
documentation](../documentation/api.md) is generated from our OpenAPI
file.
In a Swagger file, every configuration section is an object. Objects
may contain other objects, or reference objects defined
In an OpenAPI Swagger file, every configuration section is an object.
Objects may contain other objects, or reference objects defined
elsewhere. Larger API specifications may be split into multiple
files. There are more types of objects than mentioned here, you can
find the complete details at
[Swagger/OpenAPI specification page](https://swagger.io/specification/).
files. See the [OpenAPI specification][openapi-spec].
[openapi-spec]: https://swagger.io/docs/specification/about/
This library isn't in production use yet, but it is our current plan
for how Zulip's API documentation will work.
## Working with the `zulip.yaml` file
A Swagger specification file has three general parts: information and
An OpenAPI specification file has three general parts: information and
configuration, endpoint definitions, and object schemas referenced by
other objects (as an alternative to defining everything inline.)
References can either specify an individual object, using `$ref:`, or
@ -173,14 +177,12 @@ correct.
* A single `|` (pipe) character begins a multi-line description on the
next line. Single spaced lines (one newline at the end of each) are
joined. Use an extra blank line for a paragraph break.
joined. Use an extra blank line for a paragraph break. We prefer
to use this format for all descriptions because it doesn't require
extra effort to expand.
### Examples:
```
Description: This is a single line description.
```
```
Description: |
This description has multiple lines.