Skip to content

chore: switch to monorepo, move realtime inside #1190

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

o-santi
Copy link
Contributor

@o-santi o-santi commented Aug 4, 2025

What kind of change does this PR introduce?

This PR contains the first change in the monorepo switch, by moving realtime into this repository, and deprecating https://github.com/supabase/realtime-py (which I intend to do later). This requires restructuring this repository's files in order to leverage uv workspaces, as explained in #1186.

The changes can be summarized by the following tree diagram:

.
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── MAINTAINERS.md
├── README.md
├── docs
│   └── ...
├── release-please-config.json
├── flake.lock                  <- mostly copied from realtime-py
├── flake.nix                   <- mostly copied from realtime-py
├── justfile                    <- new
├── pyproject.toml              <- virtual workspace root
├── src                         <- new packages directory
│   ├── realtime                <- inlined from supabase/realtime-py
│   │   ├── README.md           <- inlined from supabase/realtime-py
│   │   ├── infra               <- inlined from supabase/realtime-py
│   │   │   └── ...
│   │   ├── mod.just            <- new
│   │   ├── pyproject.toml      <- inlined from supabase/realtime-py
│   │   ├── src                 <- inlined from supabase/realtime-py
│   │   │   └── realtime        <- inlined from supabase/realtime-py
│   │   │       ├── __init__.py
│   │   │       └── ...
│   │   └── tests               <- inlined from supabase/realtime-py
│   │       └── ...
│   └── supabase                <- moved to sub package
│       ├── README.md           <- moved to sub package
│       ├── mod.just            <- new
│       ├── pyproject.toml      <- supabase-py library root
│       ├── src                 <- moved to sub package
│       │   └── supabase        <- moved to sub package
│       │       ├── __init__.py <- moved to sub package
│       │       └── ...
│       └── tests               <- moved to sub package
│           └── ...
├── test.ps1
└── uv.lock

Reasoning

File structuring

uv broadly expects python "packages" to be either libraries or applications; and for workspaces, it expects them to be structured as N libraries, whose directory need to be specified in uv.workspace.members, and 1 application, located in ./src/{appname}. This means that projects in the root of the repository are generally interpreted as describing the application, but given that this repository shouldn't have no application, I decided to move most of the roots pyproject.toml into src/supabase, and use it as a workspace library entry by listing it in members. uv generally calls these "virtual workspaces" but I couldn't find much documentation around them anywhere.

Package specific dependencies and commands

uv already handles package specific dependencies by leveraging uv --exact --package {package} {cmd} ..., so no additional care is required besides calling the command correctly. In order to make running these more streamlined, and to share/compose them into bigger ones (for instance, to run the same commands locally and in CI), I think it makes sense to rely on a command runner. I outlined the following broad requirements in order to decide which tool to use:

  1. All python packages resolution should be done by uv, including test/dev time dependencies (by using dependency-groups). This is to ensure that we are not specifying tests differently to run locally vs in CI.
  2. Each package should be able to cleanly state its commands locally, and there should be a way to compose these from outside, without worrying with issues such as names clashing or environment leaks. A use case for this is that realtime requires certain docker instances to be up before running pytest, while supabase does not. On the flip side, supabase relies on unasync-cli to generate the _sync, with adhoc sed commands, while realtime does not use any of it - I don't think we want to keep this behavior in the future, but I do not intend to change it now.
  3. It should be easy to install, should not add any performance overhead over running the commands manually, should work out of the box with the local setup and should be supported by all major platforms we use.

I decided to give just a try. It can be summarized as a make successor, that aims to be a command runner instead of a build system. By being a command runner, it does not suffer from issues that Makefiles suffer, like that targets may be interpreted as files, and thus need to be marked as PHONY sometimes, and has niceties such as aliases, readable errors, recipe arguments, invoking from anywhere (not only from the workspace root).

just also allows for structuring the files as namespaced modules, which helps to avoid hackier solutions to name collisions, like prepending every command with the package name. With this, each package can declare its commands for testing, linting and publishing inside src/{packge}/mod.just, that is then imported as a module inside the justfile in the root of the workspace. This allows us to define targets like just test by composing each of the packages' test, without any additional coordination.

mod supabase "src/supabase/mod.just"
mod realtime "src/realtime/mod.just"

test: realtime::test && supabase::test

Alternatives

I believe that trying to use Makefiles to the same effect would result in a big spaghetti mess of commands, which is why I sought for a different tool. just was the best tool I found that was also minimalistic and not an entire build system, but I'd love some more suggestions for monorepo related tooling, specially those that generally fit those guidelines. For the record, I considered the following tools:

  • tox / nox: requires dependencies to be installed by their bespoke system, which would require duplicating a lot of version requirements in different places
  • invoke: requires an outside python installation with invoke, which would require one to use uv to run it in the first place.
  • pants: bespoke entire build system, does not integrate with uv.

o-santi added 5 commits August 1, 2025 17:15
I've decided to stick with `just` for command management, as they
provide a module structure that's very favorable for monorepos.

each package is going to be stored at `src/{package}`, with its own
`pyproject.toml` and `mod.just` files, for defining relevant commands,
tests, lints, and so on.

the main `justfile` in the workspace root then serves as the
coordinator, calling all the subfiles in order to create commands to
run in the CI and pre-commit.
make `supabase-py` a sub package, and make the workspace root a
virtual workspace that contains no "main package". this is in order to
have more homogeneity around the packages, as before the `supabase-py`
was treated specially (pyproject in the root instead of in `src/supabase`).
@silentworks
Copy link
Contributor

silentworks commented Aug 5, 2025

Great work and explanations here @o-santi. I really like the direction this is going but I think we need to ensure #1166 happens before this PR get's merged in. We would need to make at least two more releases with the current setup first before migration to this setup. Otherwise we will still be releasing two versions of the auth and functions packages.

@o-santi
Copy link
Contributor Author

o-santi commented Aug 5, 2025

Of course, I just wanted to get some comments and suggestions before moving forward with this. In talking with @olirice, we came to the conclusion that it might make sense to leave the command runner part out of the PR for now, and after all the sub packages are merged in, we can try to find the best way to do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants