Skip to main content

An extremely fast Python linter and code formatter, written in Rust.

Project description

Ruff

Ruff image image image Actions status Discord

Docs | Playground

An extremely fast Python linter and code formatter, written in Rust.

Shows a bar chart with benchmark results.

Linting the CPython codebase from scratch.

  • ⚡️ 10-100x faster than existing linters (like Flake8) and formatters (like Black)
  • 🐍 Installable via pip
  • 🛠️ pyproject.toml support
  • 🤝 Python 3.13 compatibility
  • ⚖️ Drop-in parity with Flake8, isort, and Black
  • 📦 Built-in caching, to avoid re-analyzing unchanged files
  • 🔧 Fix support, for automatic error correction (e.g., automatically remove unused imports)
  • 📏 Over 800 built-in rules, with native re-implementations of popular Flake8 plugins, like flake8-bugbear
  • ⌨️ First-party editor integrations for VS Code and more
  • 🌎 Monorepo-friendly, with hierarchical and cascading configuration

Ruff aims to be orders of magnitude faster than alternative tools while integrating more functionality behind a single, common interface.

Ruff can be used to replace Flake8 (plus dozens of plugins), Black, isort, pydocstyle, pyupgrade, autoflake, and more, all while executing tens or hundreds of times faster than any individual tool.

Ruff is extremely actively developed and used in major open-source projects like:

...and many more.

Ruff is backed by Astral. Read the launch post, or the original project announcement.

Testimonials

Sebastián Ramírez, creator of FastAPI:

Ruff is so fast that sometimes I add an intentional bug in the code just to confirm it's actually running and checking the code.

Nick Schrock, founder of Elementl, co-creator of GraphQL:

Why is Ruff a gamechanger? Primarily because it is nearly 1000x faster. Literally. Not a typo. On our largest module (dagster itself, 250k LOC) pylint takes about 2.5 minutes, parallelized across 4 cores on my M1. Running ruff against our entire codebase takes .4 seconds.

Bryan Van de Ven, co-creator of Bokeh, original author of Conda:

Ruff is ~150-200x faster than flake8 on my machine, scanning the whole repo takes ~0.2s instead of ~20s. This is an enormous quality of life improvement for local dev. It's fast enough that I added it as an actual commit hook, which is terrific.

Timothy Crosley, creator of isort:

Just switched my first project to Ruff. Only one downside so far: it's so fast I couldn't believe it was working till I intentionally introduced some errors.

Tim Abbott, lead developer of Zulip:

This is just ridiculously fast... ruff is amazing.

Table of Contents

For more, see the documentation.

  1. Getting Started
  2. Configuration
  3. Rules
  4. Contributing
  5. Support
  6. Acknowledgements
  7. Who's Using Ruff?
  8. License

Getting Started

For more, see the documentation.

Installation

Ruff is available as ruff on PyPI.

Invoke Ruff directly with uvx:

uvx ruff check   # Lint all files in the current directory.
uvx ruff format  # Format all files in the current directory.

Or install Ruff with uv (recommended), pip, or pipx:

# With uv.
uv tool install ruff@latest  # Install Ruff globally.
uv add --dev ruff            # Or add Ruff to your project.

# With pip.
pip install ruff

# With pipx.
pipx install ruff

Starting with version 0.5.0, Ruff can be installed with our standalone installers:

# On macOS and Linux.
curl -LsSf https://astral.sh/ruff/install.sh | sh

# On Windows.
powershell -c "irm https://astral.sh/ruff/install.ps1 | iex"

# For a specific version.
curl -LsSf https://astral.sh/ruff/0.12.5/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.12.5/install.ps1 | iex"

You can also install Ruff via Homebrew, Conda, and with a variety of other package managers.

Usage

To run Ruff as a linter, try any of the following:

ruff check                          # Lint all files in the current directory (and any subdirectories).
ruff check path/to/code/            # Lint all files in `/path/to/code` (and any subdirectories).
ruff check path/to/code/*.py        # Lint all `.py` files in `/path/to/code`.
ruff check path/to/code/to/file.py  # Lint `file.py`.
ruff check @arguments.txt           # Lint using an input file, treating its contents as newline-delimited command-line arguments.

Or, to run Ruff as a formatter:

ruff format                          # Format all files in the current directory (and any subdirectories).
ruff format path/to/code/            # Format all files in `/path/to/code` (and any subdirectories).
ruff format path/to/code/*.py        # Format all `.py` files in `/path/to/code`.
ruff format path/to/code/to/file.py  # Format `file.py`.
ruff format @arguments.txt           # Format using an input file, treating its contents as newline-delimited command-line arguments.

Ruff can also be used as a pre-commit hook via ruff-pre-commit:

- repo: https://github.com/astral-sh/ruff-pre-commit
  # Ruff version.
  rev: v0.12.5
  hooks:
    # Run the linter.
    - id: ruff-check
      args: [ --fix ]
    # Run the formatter.
    - id: ruff-format

Ruff can also be used as a VS Code extension or with various other editors.

Ruff can also be used as a GitHub Action via ruff-action:

name: Ruff
on: [ push, pull_request ]
jobs:
  ruff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/ruff-action@v3

Configuration

Ruff can be configured through a pyproject.toml, ruff.toml, or .ruff.toml file (see: Configuration, or Settings for a complete list of all configuration options).

If left unspecified, Ruff's default configuration is equivalent to the following ruff.toml file:

# Exclude a variety of commonly ignored directories.
exclude = [
    ".bzr",
    ".direnv",
    ".eggs",
    ".git",
    ".git-rewrite",
    ".hg",
    ".ipynb_checkpoints",
    ".mypy_cache",
    ".nox",
    ".pants.d",
    ".pyenv",
    ".pytest_cache",
    ".pytype",
    ".ruff_cache",
    ".svn",
    ".tox",
    ".venv",
    ".vscode",
    "__pypackages__",
    "_build",
    "buck-out",
    "build",
    "dist",
    "node_modules",
    "site-packages",
    "venv",
]

# Same as Black.
line-length = 88
indent-width = 4

# Assume Python 3.9
target-version = "py39"

[lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
select = ["E4", "E7", "E9", "F"]
ignore = []

# Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []

# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

[format]
# Like Black, use double quotes for strings.
quote-style = "double"

# Like Black, indent with spaces, rather than tabs.
indent-style = "space"

# Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false

# Like Black, automatically detect the appropriate line ending.
line-ending = "auto"

Note that, in a pyproject.toml, each section header should be prefixed with tool.ruff. For example, [lint] should be replaced with [tool.ruff.lint].

Some configuration options can be provided via dedicated command-line arguments, such as those related to rule enablement and disablement, file discovery, and logging level:

ruff check --select F401 --select F403 --quiet

The remaining configuration options can be provided through a catch-all --config argument:

ruff check --config "lint.per-file-ignores = {'some_file.py' = ['F841']}"

To opt in to the latest lint rules, formatter style changes, interface updates, and more, enable preview mode by setting preview = true in your configuration file or passing --preview on the command line. Preview mode enables a collection of unstable features that may change prior to stabilization.

See ruff help for more on Ruff's top-level commands, or ruff help check and ruff help format for more on the linting and formatting commands, respectively.

Rules

Ruff supports over 800 lint rules, many of which are inspired by popular tools like Flake8, isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in Rust as a first-party feature.

By default, Ruff enables Flake8's F rules, along with a subset of the E rules, omitting any stylistic rules that overlap with the use of a formatter, like ruff format or Black.

If you're just getting started with Ruff, the default rule set is a great place to start: it catches a wide variety of common errors (like unused imports) with zero configuration.

Beyond the defaults, Ruff re-implements some of the most popular Flake8 plugins and related code quality tools, including:

For a complete enumeration of the supported rules, see Rules.

Contributing

Contributions are welcome and highly appreciated. To get started, check out the contributing guidelines.

You can also join us on Discord.

Support

Having trouble? Check out the existing issues on GitHub, or feel free to open a new one.

You can also ask for help on Discord.

Acknowledgements

Ruff's linter draws on both the APIs and implementation details of many other tools in the Python ecosystem, especially Flake8, Pyflakes, pycodestyle, pydocstyle, pyupgrade, and isort.

In some cases, Ruff includes a "direct" Rust port of the corresponding tool. We're grateful to the maintainers of these tools for their work, and for all the value they've provided to the Python community.

Ruff's formatter is built on a fork of Rome's rome_formatter, and again draws on both API and implementation details from Rome, Prettier, and Black.

Ruff's import resolver is based on the import resolution algorithm from Pyright.

Ruff is also influenced by a number of tools outside the Python ecosystem, like Clippy and ESLint.

Ruff is the beneficiary of a large number of contributors.

Ruff is released under the MIT license.

Who's Using Ruff?

Ruff is used by a number of major open-source projects and companies, including:

Show Your Support

If you're using Ruff, consider adding the Ruff badge to your project's README.md:

[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)

...or README.rst:

.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
    :target: https://github.com/astral-sh/ruff
    :alt: Ruff

...or, as HTML:

<a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff" style="max-width:100%;"></a>

License

This repository is licensed under the MIT License

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ruff-0.12.5.tar.gz (5.2 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ruff-0.12.5-py3-none-win_arm64.whl (12.0 MB view details)

Uploaded Python 3Windows ARM64

ruff-0.12.5-py3-none-win_amd64.whl (12.9 MB view details)

Uploaded Python 3Windows x86-64

ruff-0.12.5-py3-none-win32.whl (11.8 MB view details)

Uploaded Python 3Windows x86

ruff-0.12.5-py3-none-musllinux_1_2_x86_64.whl (13.0 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

ruff-0.12.5-py3-none-musllinux_1_2_i686.whl (12.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ i686

ruff-0.12.5-py3-none-musllinux_1_2_armv7l.whl (11.6 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARMv7l

ruff-0.12.5-py3-none-musllinux_1_2_aarch64.whl (11.8 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

ruff-0.12.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.9 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

ruff-0.12.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl (12.7 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ s390x

ruff-0.12.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (13.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64le

ruff-0.12.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl (14.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64

ruff-0.12.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl (13.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ i686

ruff-0.12.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (11.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARMv7l

ruff-0.12.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (12.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

ruff-0.12.5-py3-none-macosx_11_0_arm64.whl (11.7 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

ruff-0.12.5-py3-none-macosx_10_12_x86_64.whl (12.5 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

ruff-0.12.5-py3-none-linux_armv6l.whl (11.8 MB view details)

Uploaded Python 3

File details

Details for the file ruff-0.12.5.tar.gz.

File metadata

  • Download URL: ruff-0.12.5.tar.gz
  • Upload date:
  • Size: 5.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.8.2

File hashes

Hashes for ruff-0.12.5.tar.gz
Algorithm Hash digest
SHA256 b209db6102b66f13625940b7f8c7d0f18e20039bb7f6101fbdac935c9612057e
MD5 94d3243dff55af17a61e4255e4afe8df
BLAKE2b-256 30cd01015eb5034605fd98d829c5839ec2c6b4582b479707f7c1c2af861e8258

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-win_arm64.whl.

File metadata

  • Download URL: ruff-0.12.5-py3-none-win_arm64.whl
  • Upload date:
  • Size: 12.0 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.8.2

File hashes

Hashes for ruff-0.12.5-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 48cdbfc633de2c5c37d9f090ba3b352d1576b0015bfc3bc98eaf230275b7e805
MD5 6287bc41955539a1fcfe47993c208eca
BLAKE2b-256 00dbc376b0661c24cf770cb8815268190668ec1330eba8374a126ceef8c72d55

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-win_amd64.whl.

File metadata

  • Download URL: ruff-0.12.5-py3-none-win_amd64.whl
  • Upload date:
  • Size: 12.9 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.8.2

File hashes

Hashes for ruff-0.12.5-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 ae0d90cf5f49466c954991b9d8b953bd093c32c27608e409ae3564c63c5306a5
MD5 84cf3f7a0bc79828a1ae529a0c61f74c
BLAKE2b-256 bc0fab16e8259493137598b9149734fec2e06fdeda9837e6f634f5c4e35916da

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-win32.whl.

File metadata

  • Download URL: ruff-0.12.5-py3-none-win32.whl
  • Upload date:
  • Size: 11.8 MB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.8.2

File hashes

Hashes for ruff-0.12.5-py3-none-win32.whl
Algorithm Hash digest
SHA256 dfeb2627c459b0b78ca2bbdc38dd11cc9a0a88bf91db982058b26ce41714ffa9
MD5 713aece0f06bb6cc247eaa0a0c3b7122
BLAKE2b-256 3eb9053d6445dc7544fb6594785056d8ece61daae7214859ada4a152ad56b6e0

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 5a655a0a0d396f0f072faafc18ebd59adde8ca85fb848dc1b0d9f024b9c4d3bb
MD5 27d49665ccc468214c8c1e0d8d4f7752
BLAKE2b-256 3404b6b00383cf2f48e8e78e14eb258942fdf2a9bf0287fbf5cdd398b749193a

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 46699f73c2b5b137b9dc0fc1a190b43e35b008b398c6066ea1350cce6326adcb
MD5 d0b2247ce5053a552eaf729c1334cadb
BLAKE2b-256 c26791c71d27205871737cae11025ee2b098f512104e26ffd8656fd93d0ada0a

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-musllinux_1_2_armv7l.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 a5a4c7830dadd3d8c39b1cc85386e2c1e62344f20766be6f173c22fb5f72f293
MD5 d93d130948c63e5af7568d5d00e6e903
BLAKE2b-256 52757356af30a14584981cabfefcf6106dea98cec9a7af4acb5daaf4b114845f

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 c5076aa0e61e30f848846f0265c873c249d4b558105b221be1828f9f79903dc5
MD5 bb7aed42b07e4ada941c00fa2b4b5025
BLAKE2b-256 ebd368bc5e7ab96c94b3589d1789f2dd6dd4b27b263310019529ac9be1e8f31b

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2c47dea6ae39421851685141ba9734767f960113d51e83fd7bb9958d5be8763a
MD5 8c46a2c2cce8aafbcdb5bd2665dc5975
BLAKE2b-256 24ff96058f6506aac0fbc0d0fc0d60b0d0bd746240a0594657a2d94ad28033ba

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 8dbbf9f25dfb501f4237ae7501d6364b76a01341c6f1b2cd6764fe449124bb2a
MD5 2df6751bd87d8077567c4a9d1680fb7d
BLAKE2b-256 62e31c98c566fe6809a0c83751d825a03727f242cdbe0d142c9e292725585521

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 ca972c80f7ebcfd8af75a0f18b17c42d9f1ef203d163669150453f50ca98ab7b
MD5 b5ad2115dff132375281f860abe447d1
BLAKE2b-256 bdd1ef6b19622009ba8386fdb792c0743f709cf917b0b2f1400589cbe4739a33

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl
Algorithm Hash digest
SHA256 c7da4129016ae26c32dfcbd5b671fe652b5ab7fc40095d80dcff78175e7eddd4
MD5 43718b7eced71bb3752d9d558eca4b1c
BLAKE2b-256 6b5868a5be2c8e5590ecdad922b2bcd5583af19ba648f7648f95c51c3c1eca81

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 f1504fea81461cf4841778b3ef0a078757602a3b3ea4b008feb1308cb3f23e08
MD5 e79068d758c94196ea4734512d435f86
BLAKE2b-256 d8c9c2ccb3b8cbb5661ffda6925f81a13edbb786e623876141b04919d1128370

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 8b13489c3dc50de5e2d40110c0cce371e00186b880842e245186ca862bf9a1ac
MD5 262565c456bb55c5d29cb4b8f41fbf96
BLAKE2b-256 25bfcd07e8f6a3a6ec746c62556b4c4b79eeb9b0328b362bb8431b7b8afd3856

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 73b4cae449597e7195a49eb1cdca89fd9fbb16140c7579899e87f4c85bf82f73
MD5 0ee48f35b2e202d777390f65b7d6b0d4
BLAKE2b-256 a116cf372d2ebe91e4eb5b82a2275c3acfa879e0566a7ac94d331ea37b765ac8

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 962775ed5b27c7aa3fdc0d8f4d4433deae7659ef99ea20f783d666e77338b8cf
MD5 4c0205e7c1b401d3efcc4eab5402172e
BLAKE2b-256 c5dec6bec1dce5ead9f9e6a946ea15e8d698c35f19edc508289d70a577921b30

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 d1ab65e7d8152f519e7dea4de892317c9da7a108da1c56b6a3c1d5e7cf4c5e9a
MD5 2e279c49e2bb39e282c54bf3a8771de1
BLAKE2b-256 f8fcc6b65cd0e7fbe60f17e7ad619dca796aa49fbca34bb9bea5f8faf1ec2643

See more details on using hashes here.

File details

Details for the file ruff-0.12.5-py3-none-linux_armv6l.whl.

File metadata

File hashes

Hashes for ruff-0.12.5-py3-none-linux_armv6l.whl
Algorithm Hash digest
SHA256 1de2c887e9dec6cb31fcb9948299de5b2db38144e66403b9660c9548a67abd92
MD5 e0fbc143c3741fb22b33bc63d827dc04
BLAKE2b-256 d4dead2f68f0798ff15dd8c0bcc2889558970d9a685b3249565a937cd820ad34

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page