# Contributing to `dstack` We appreciate your interest in contributing to `dstack`! This document will help you get up to speed with `dstack` codebase and guide you through the contribution process. ## Who can contribute We'd be happy to see your contribution if you are a `dstack` user, a partner integrating with `dstack`, or any other person genuinely interested in `dstack`. ## Using AI assistance You may use AI assistance when contributing to `dstack`. However, we expect you, the human contributor, to initiate and validate the contribution, ensuring it meets the same standard as something you'd write by hand. Contributions made entirely without a human in the loop (e.g., PRs filed by an autonomous agent against open issues) are discouraged and will be declined. ## Accepted changes * Bug fixes that address a bug you've hit while using `dstack`. Include steps to reproduce in the linked issue or the PR. * New features that improve `dstack` for you. Before submitting a feature PR, please describe your use case and proposal in a GitHub issue to discuss it with the core team. * Minor fixes such as typos. * [Examples](examples). Existing open issues are typically picked up by the core team — please only contribute to one if it actually affects how you use `dstack`. ## Set up your development environment Follow [contributing/DEVELOPMENT.md](contributing/DEVELOPMENT.md). ## Learn dstack internals If you make a non-trivial change to `dstack`, we recommend you learn about `dstack` internals. A good place to start is [contributing/ARCHITECTURE.md](contributing/ARCHITECTURE.md). ## Make a PR 1. Look for an [existing issue](https://github.com/dstackai/dstack/issues) or create a [new one](https://github.com/dstackai/dstack/issues/new/choose). 2. Fork the repo. 3. Commit your changes. 4. Open a PR. [Link the PR to the issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) (if you are solving one). ### Before pushing your changes We use [`ruff`](https://docs.astral.sh/ruff/) to format Python code and to sort Python imports. Before committing your changes, run: 1. `uv run ruff check --fix` 2. `uv run ruff format` > There are also helper pre-commits installed for [`ruff`](https://docs.astral.sh/ruff/integrations/#pre-commit) that make commits fail if the code is not formatted or the imports are not sorted. They also change the code as required so that you can review the changes and commit again. ### Run tests It's recommended to run tests locally before running them in CI. To run Python tests, first ensure you've install dev dependencies as described in [contributing/DEVELOPMENT.md](contributing/DEVELOPMENT.md). Then you can do: ```shell uv run pytest src/tests ``` (Optionally) Some tests are skipped by default because they need extra setup. Enable them with these flags: * `--runpostgres` – run the tests against Postgres in addition to SQLite. Requires Docker. * `--rundocker` – run the tests that use Docker containers. Requires Docker. * `--runui` – run the tests of the bundled frontend. Requires the frontend build in `src/dstack/_internal/server/statics`. * `--runall` – all of the above. ```shell uv run pytest src/tests --runall ``` Alternatively, you can run tests via [tox](https://tox.wiki/) inside an isolated environment ensuring that the `dstack` package itself is built correctly and all requirements are specified and correct. tox and [just](https://just.systems/) must be already installed. * Run tests in the default environment: ```shell just tox::test-default ``` The Python version of the default environment is configured via the `.python-version` file in the repo root directory. Note, the same file [is used by uv](https://docs.astral.sh/uv/concepts/python-versions/#python-version-files). * Run tests against all currently supported Python versions: ```shell just tox::test-supported ``` * Run tests in the _current_ environment: ```shell just tox::test-current ``` It saves about 30-60 seconds at the cost of Python environment isolation (defeating the core purpose of tox) — no packages are built or installed, and, as a consequence, all dependencies must be already installed, but, unlike the plain pytest command, the process environment variables are still isolated. It's possible to pass pytest arguments after the `--` separator (the arguments _before_ the separator are `tox run` arguments): ```shell just tox::test-default -- -vvv --last-failed ``` ## Add a new backend If you'd like to integrate a new cloud provider to `dstack`, follow [contributing/BACKENDS.md](contributing/BACKENDS.md). ## What's next You can find more subject-focused guides in the [contributing](contributing/) directory. If you have any questions, you can always get help in our [Discord](https://discord.gg/u8SmfwPpMd) community.