Skip to content
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

feat!: Migrate to use the Pub workspaces feature #816

Merged
merged 8 commits into from
Jan 7, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
docs: Update docs to reflect 7.0.0
spydon committed Jan 6, 2025
commit 24f1560ed1d8ba8834c81a7b673ed58d08f2fbac
60 changes: 27 additions & 33 deletions docs/commands/bootstrap.mdx
Original file line number Diff line number Diff line change
@@ -7,48 +7,43 @@ description: Learn more about the `bootstrap` command in Melos.

<Info>Supports all [Melos filtering](/filters) flags.</Info>

This command initializes the workspace, links local packages together and
installs remaining package dependencies.
This command initializes the workspace and installs remaining package
dependencies.

```bash
melos bootstrap
# or
melos bs
```

Bootstrapping has two primary functions:
Bootstrapping has three primary functions:

1. Installing all package dependencies (internally using `pub get`).
2. Locally linking any packages together via path dependency overrides _without
having to edit your pubspec.yaml_.
2. Syncing shared dependencies between packages.
3. Running any bootstrap lifecycle scripts.

## Why is bootstrapping required?

In normal projects, packages can be linked by providing a `path` within the
`pubspec.yaml`. This works for small projects however presents a problem at
scale. Packages cannot be published with a locally defined path, meaning once
you're ready to publish your packages you'll need to manually update all the
packages `pubspec.yaml` files with the versions. If your packages are also
tightly coupled (dependencies of each other), you'll also have to manually check
which versions should be updated. Even with a few of packages this can become a
long and error-prone task.

Melos solves this problem by overriding local files which the Dart analyzer uses
to read packages from. If a local package exists (defined in the `melos.yaml`
file) and a different local package has it listed as a dependency, it will be
linked regardless of whether a version has been specified.
After the [Pub Workspaces feature](https://dart.dev/tools/pub/workspaces) was
introduced in Dart 3.6.0, it is no longer strictly necessary to run `melos
bootstrap`, since all the packages are already linked together. However, there
are still some benefits to running `melos bootstrap`, because you need to run
`pub get` in each package to initialize the workspace, and `melos bootstrap`
will do that for you.
Comment on lines +27 to +32

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because you need to run pub get in each package to initialize the workspace

@spydon I've just been running dart pub get in any folder (in a non-Melos workspace) and it initializes the whole workspace. That makes sense to me because the packages have a shared resolution.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you're correct!
I read the instructions here sloppily: https://dart.dev/tools/pub/workspaces

You need to run dart pub get once for each package.

But that section is of course about if you aren't using the pub workspaces feature.

Copy link

@Levi-Lesches Levi-Lesches Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might not a matter of interpretation but this paragraphs reads to me as:

Once you start using Pub Workspaces, you don't need to run melos bootstrap, but it's still convenient since it will run dart pub get in each sub-package for you

(It does say "each package in the _workspace" too!)

It would probably help to re-word this paragraph to specifically discuss how Melos and melos bootstrap play with the Workspaces feature. In general I had a hard time finding a list of what Melos can do that workspaces cannot (eg, specify that Melos can publish all sub-packages while pub cannot, but other pub commands do work recursively)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed it up here: #822

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed you second comment!
Yeah, I guess that we should clarify that on the intro page of the docs, is it something you'd like to PR? :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I don't actually know the details of melos -- that's why I came here, was hoping to find such a list!


### Benefits

- All local packages in the repository can be interlinked by Melos to point to
their local directories rather than 'remote' _without pubspec.yaml
modifications_.
Why would I want to use a monorepo?

- All local packages in the repository can be interlinked to point to their
local directories rather than 'remote' _without pubspec.yaml modifications_.
- **Example Scenario**: In a repository, package `A` depends on package `B`.
Both packages `A` & `B` exist in the monorepo. However, if you `pub get`
inside package `A`, `pub` will retrieve package `B` from the pub.dev
registry as it's unaware of `B` existing locally. However, with Melos, it's
aware that package `B` exists locally too, so it will generate the various
pub files to point to a relative path in the local repository.
registry as it's unaware of `B` existing locally. However, with Melos and
pub workspaces, it's aware that package `B` exists locally too, so it will
generate the various pub files to point to a relative path in the local
repository.
- If you wanted to use pub you could of course define a dependency override
in the pubspec of package `A` that sets a path for package `B` but, then
you'd have to do this manually every time and then manually remove it
@@ -86,20 +81,19 @@ melos bootstrap --diff="main"

## Bootstrap flags

- The `--no-example` flag is used to exclude flutter package's example's dependencies
(https://github.com/dart-lang/pub/pull/3856)
- The `--no-example` flag is used to exclude flutter package's example's
dependencies (https://github.com/dart-lang/pub/pull/3856)
- This will run `pub get` with the `--no-example` flag.
- The `--enforce-lockfile` flag is used to enforce versions from `.lock` files.
- Ensure .lock files exist, as failure may occur if they're not checked in.
- The `--no-enforce-lockfile` flag is used to disregard versions from `.lock` files if
`enforce-lockfile` is configured in the `melos.yaml` file.
- The `--skip-linking` flag is used to skip the local linking of workspace packages.
- The `--offline` flag is used to only resolve dependencies from the local cache by running
`pub get` with the `--offline` flag.
- The `--no-enforce-lockfile` flag is used to disregard versions from `.lock`
files if `enforce-lockfile` is configured in the `melos.yaml` file.
- The `--offline` flag is used to only resolve dependencies from the local
cache by running `pub get` with the `--offline` flag.


In addition to the above flags, the `melos bootstrap` command supports a few different flags that
can be defined in your `melos.yaml` file.
In addition to the above flags, the `melos bootstrap` command supports a few
different configurations that can be defined in your `melos.yaml` file.


### Shared dependencies
72 changes: 39 additions & 33 deletions docs/getting-started.mdx
Original file line number Diff line number Diff line change
@@ -8,6 +8,12 @@
Melos requires a few one-off steps to be completed before you can start using
it.

## Pub Workspaces

First start by reading the short Pub Workspaces guide for how to get your
monorepo ready to be used with Melos and Pub Workspaces, the guide can be
found on the [Dart website](https://dart.dev/tools/pub/workspaces).

## Installation

Install Melos as a
@@ -59,11 +65,18 @@

```yaml
name: my_project

publish_to: none
environment:
sdk: '>=3.0.0 <4.0.0'
sdk: ^3.6.0
workspace:
- packages/helper
- packages/client_package
- packages/server_package
```

Where `packages/helper`, `packages/client_package` and `packages/server_package`
are the paths to the packages in your workspace.

The corresponding `pubspec.lock` file should also be committed. Make sure to
exclude it from the `.gitignore` file.

@@ -73,6 +86,18 @@
dart pub add melos --dev
```

### Configure your packages

Next, in all your packages `pubspec.yaml` files, add the
`resolution: workspace` field:

```yaml
name: my_package
resolution: workspace

...
```

### Configure the workspace

Next create a `melos.yaml` file at the repository root. Within the `melos.yaml`
@@ -90,43 +115,23 @@
project. Each path can be defined using the
[glob](https://docs.python.org/3/library/glob.html) pattern expansion format.

Melos generates `pubspec_overrides.yaml` files to link local packages for
development. Typically these files should be ignored by git. To ignore these
files, add the following to your `.gitignore` file:

```
pubspec_overrides.yaml
```

## Bootstrapping

Once installed & setup, Melos needs to be bootstrapped. Bootstrapping has 2
primary roles:
Once installed & setup, Melos needs to be bootstrapped. Bootstrapping has
three primary functions:

1. Installing all package dependencies (internally using `pub get`).
2. Locally linking any packages together.
2. Syncing shared dependencies between packages.
3. Running any bootstrap lifecycle scripts.

Bootstrap your project by running the following command:
Bootstrap your project by running the following command:

```bash
melos bootstrap
```

### Why do I need to bootstrap?

In normal projects, packages can be linked by providing a `path` within the
`pubspec.yaml`. This works for small projects however presents a problem at
scale. Packages cannot be published with a locally defined path, meaning once
you're ready to publish your packages you'll need to manually update all the
packages `pubspec.yaml` files with the versions. If your packages are also
tightly coupled (dependencies of each other), you'll also have to manually check
which versions should be updated. Even with a few packages this can become a
long and error-prone task.

Melos solves this problem by overriding local files which the Dart analyzer uses
to read packages from. If a local package exists (defined in the `melos.yaml`
file) and a different local package has it listed as a dependency, it will be
linked regardless of whether a version has been specified.
If you wonder why bootrapping is needed you can read more about it in the
[Bootstrap section](/commands/bootstrap).

## Next steps

@@ -146,15 +151,16 @@
- packages/**

scripts:
analyze:
exec: dart analyze .
generate:
run: melos exec -c 1 --depends-on build_runner -- dart run build_runner build
```

Then execute the command by running `melos run analyze`.
Then execute the command by running `melos generate`.

If you're looking for some inspiration as to what scripts can help with, check
out the
[FlutterFire repository](https://github.com/firebase/flutterfire/blob/master/melos.yaml).
[FlutterFire repository](https://github.com/firebase/flutterfire/blob/master/melos.yaml)

Check warning on line 162 in docs/getting-started.mdx

In Solidarity / Inclusive Language

Match Found

Please consider an alternative to `master`. Possibilities include: `primary`, `main`, `leader`, `active`, `writer`
Raw output
/master/gi
or the [Flame repository](https://github.com/flame-engine/flame/blob/main/melos.yaml).

If you are using VS Code, there is an [extension](/ide-support#vs-code)
available, to integrate Melos with VS Code.
35 changes: 35 additions & 0 deletions docs/guides/migrations.mdx
Original file line number Diff line number Diff line change
@@ -5,6 +5,41 @@ description: How to migrate between major versions of Melos.

# Migrations

## 6.x.x to 7.x.x

Since the [pub workspaces](https://dart.dev/tools/pub/workspaces) feature has
been released, Melos has been updated to rely on that instead of creating
`pubspec_overrides.yaml` files and thus some migration is needed.

The main difference is that you now have to add `resolution: workspace` to all
of your packages' `pubspec.yaml` files and add a list of all your packages to
the root `pubspec.yaml` file, similar to this:

Package `pubspec.yaml` file:
```yaml
name: my_package
environment:
sdk: ^3.6.0
resolution: workspace
```

Workspace root `pubspec.yaml` file:
```yaml
name: my_workspace
publish_to: none
environment:
sdk: ^3.6.0
workspace:
- packages/helper
- packages/client_package
- packages/server_package
dev_dependencies:
melos: ^7.0.0
```

> [!NOTE]
> You have to use Dart SDK 3.6.0 or newer to use pub workspaces.

## 3.0.0 to 4.0.0

### `--no-git-tag-version` behavior change
3 changes: 2 additions & 1 deletion docs/index.mdx
Original file line number Diff line number Diff line change
@@ -30,7 +30,8 @@ other. Features include:
- Listing of local packages & their dependencies.

Melos also works great on CI/CD environments to help automate complex tasks and
challenges.
challenges. If you're using GitHub you can check out the
[Melos GitHub Action](https://github.com/bluefireteam/melos-action).

## Projects using Melos

9 changes: 9 additions & 0 deletions packages/melos/README.md
Original file line number Diff line number Diff line change
@@ -44,6 +44,15 @@ The main difference is that you now have to add `resolution: workspace` to all
of your packages' `pubspec.yaml` files and add a list of all your packages to
the root `pubspec.yaml` file, similar to this:

Package `pubspec.yaml` file:
```yaml
name: my_package
environment:
sdk: ^3.6.0
resolution: workspace
```

Workspace root `pubspec.yaml` file:
```yaml
name: my_workspace
publish_to: none