-
Notifications
You must be signed in to change notification settings - Fork 233
Description
NOTE: This proposal has been partially succeeded by a proposal with a proper workspace file. See https://docs.google.com/document/d/1UEEAGdWIgVf0X7o8WPQCPmL4LSzaGCfJTM0pURoDLfE/edit?resourcekey=0-c5CMaOoc_pg3ZwJKMAM0og . We probably want to support resolution: external
as well as resolution: workspace
for cases such as the dart sdk where the package-config is not created by pub.
This issue suggests a simple mechanism in the pub client for better supporting a shared resolution between the packages of a mono-repo. Namely adding
resolution: external
to a pubspec.yaml to indicate that pub should not treat it as a root package.
The main parts of this proposal does not contain much support in the pub client for how to manage multiple packages together in a single project. We instead suggest pushing more advanced support to external tools such as package:mono_repo
or package:melos
.
Motivation
Mono-repositories are repositories with tightly related packages that are often developed and released together.
The dart team is maintaining a number of mono-repos Eg:
dart-lang/test
google/protobuf.dart
dart-lang/ecosystem
Another special case of mono-repos is the dart SDK where a common resolution is used, but not maintained by pub, even though many of the subpackages have a pubspec.yaml
, and some are published to pub.dev individually...
Externally we know of several customers using mono-repositories.
When developing in a mono-repo it is often desirable to use a shared version resolution for ensuring consistent behavior.
By having a shared resolution, tools such as the analyzer can also share context between analyzing each package, with big potential memory savings.
Some packages are in a mono-repo for organizational purposes, and might not want to share the same resolution (and would not benefit from this proposal). One such repo could be: flutter/packages.
Some tutorials are split in multiple "chapters" each with a single pubspec.yaml
, and the analyzer has been known to choke on those because they each have a separate context. They could perhaps benefit from this proposal (if developing the pubspec.yaml
is not part of the tutorial).
Existing support for mono-repositories
There exists tooling to support handling of mono-repos, such as mono_repo.dart and melos. These tools can help running the same command for all sub-projects
They, however, don't allow a shared resolution between the packages. These could be updated to allow for generating a shared root pubspec.yaml
.
Proposed mechanism
A new section in pubspec.yaml
would mark a pubspec that it should not be used for a "local resolution", but instead rely on the Dart VM's mechanism for searching parent directories for a .dart_tool/package_config.json
containing a resolution to use.
name: test
environment:
sdk: ^3.1.0
dependencies:
...
resolution: external
-
Given this,
dart pub get
would not generate adart_tool/package_config.json
file in the same directory. Instead it could either (still open):- Report an error: "This package is not intended for direct resolution"
- Look for a
pubspec.yaml
in parent directories and resolve that instead. - Do nothing.
-
dart run
anddart test
needs to ignorepubspec.yaml
s withresolution: external
when resolving packages.
dart pub publish
should however consider thispubspec.yaml
when doing validations.
We could create a lint discouraging from havingdev_dependencies
anddependency_overrides
in apubspec.yaml
withresolution: external
.
Creating a mono-repo
Now to create a mono-repo, one would create a "root" pubspec.yaml
with dependency_overrides
with path-dependencies on all the sub-projects.
name: my_mono_repo_root
publish_to: none
environment:
sdk: ^3.0.0
dev_dependencies:
build_runner: ^2.0.0
dependency_overrides:
pkg1:
path: pkgs/pkg1
pkg2:
path: pkgs/pkg2
All dev_dependencies
should be collected in the root pubspec.yaml
, and thus shared between the subprojects.
Running dart pub get
in this root-directory will create a shared pubspec.lock
(that can be checked into source control if desired) and a shared dart_tool/package_config.json
for consumption by the Dart VM and analyzer.
-
We now rely on the
dart run
resolution mechanism to look up through parent directories for finding thedart_tool/package_config.json
file, and providing the package resolution. This should enabledart test
to still work from the sub-project folder (we need to test that this works). -
One could think of mechanisms for "linking" the sub-projects into the root-project, such that they could be operated on as a whole (eg. when doing upgrades). We propose to (at least as a first step) leave such functionality out of the pub client, and for example
The Dart SDK
In the Dart SDK we can mark all the in-sdk-repo packages as resolution: external
.
There will not (at least for now) be a root pubspec.yaml
, but we will instead rely on the current alternative tooling to generate a shared dart_tool/package_config.json
.
Open questions:
- Do we need a way to mark the sub-dependencies as special, such that Pub knows how to update them in sync? Or are
dependency_overrides
good enough?- We could add this later if there's a high demand
- We could also autodetect overridden path-dependencies from the root-package and handle them special.
- We need to figure out how
build_runner
would work in such a setup. Can each sub-project contain its ownbuild.yaml
? - How does this affect
dart pub add
? Can you add to a sub-package, and should that resolve together with other packages? - Should
dart pub add --dev
find the rootpubspec.yaml
? - How does this affect
dart pub upgrade --major-versions
? Is there a way to upgrade all thepubspec.yaml
's of a project in sync? (Could perhaps be added later)
We might need a way to force resolution of the single package, e.g. for deployment of a sub-package. (Could we piggy back on dart pub get --enforce-lockfile
- then we should have called it dart pub get --deploy
😐)
Potential downsides
- Relying on
dependencies_overrides
can cause some issues-
Dependency constraints among sub-projects are not checked.
When publishing you might have constraints not matching sibling dependenciesThis can to some extent be helped by doing a sub-package-only resolution in
dart pub publish
.
-
- Diamonds where you depend on other packages on pub.dev, and these packages also depends on another package in your mono-repository
- These are rather rare - perhaps we don't need strong support for those.
- cycles with other packages on pub.dev
- These are rather rare - perhaps we don't need to support those.
- Mono-repository root
pubspec.yaml
might be missing thedependency_override
that should include a child.- Could we warn against this?