Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion docs/processes/breaking-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ For dependent packages located in `core`, you may get type errors immediately th

For other projects that live outside of `core`, you can use the following process to verify the effects:

1. Create a [preview build](./testing-changes-in-other-projects.md#testing-changes-to-packages-with-preview-builds) for your package.
1. Create a [preview build](./preview-builds.md) for your package.
2. Open draft PRs in the dependent projects.
3. In each draft PR, upgrade your package to the preview build.
4. Test the project, particularly the functionality that makes use of your package.
Expand Down
41 changes: 41 additions & 0 deletions docs/processes/local-builds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Using local builds

If you are unable to use [preview builds](./preview-builds.md) for testing, you can always build a package locally and link it to a project.

1. First, build the monorepo by running `yarn build`.

2. In the project, open `package.json` and locate the entry in `dependencies` for the package you want to test.

3. Replace the version range in the right-hand side of the entry to point to the local build:

```json
"@metamask/<PACKAGE_NAME>@<VERSION_RANGE>": "file:<PATH_TO_CORE>/packages/<PACKAGE_NAME>"
```

where:

- `PACKAGE_NAME` is the name of your package
- `VERSION_RANGE` is the version range of your package being used in production, usually starting with `^`
- `PATH_TO_MONOREPO` is the local path to the clone of this monorepo

4. Run `yarn install`. (Note that due to the use of Yarn's `file:` protocol, you'll need to repeat this step each time you update the package in the monorepo.)

> **Example:**
>
> Given:
>
> - You have changes to `@metamask/controller-utils` you want to test
> - `@metamask/controller-utils` is listed at `^1.1.4`
> - You've cloned this repo next to the project
>
> In this case, you would go to `dependencies` and replace the line:
>
> ```json
> "@metamask/controller-utils": "^1.1.4"
> ```
>
> with:
>
> ```json
> "@metamask/controller-utils@^1.1.4": "file:../core/packages/controller-utils"
> ```
204 changes: 204 additions & 0 deletions docs/processes/preview-builds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
# Publishing and using preview builds

Preview builds are pre-production versions of packages. Unlike [local builds](./local-builds.md), they are published to NPM (albeit under a separate NPM namespace) and can therefore be treated the same way as production releases in CI. Because of this, we recommend using preview builds for testing.

Generally, when working with preview builds, you will follow this process:

1. Create a branch in your clone of this repo
2. Work on changes to your package(s)
3. [Publish preview builds](#publishing-preview-builds)
4. Switch to the project and [configure it to use the new preview builds](#using-preview-builds)
5. Repeat steps 2-4 as necessary

## Publishing preview builds

To publish preview builds:

1. Create a pull request with the changes to your package(s).
2. Post a comment on the pull request with the text `@metamaskbot publish-previews`. The `publish-preview` GitHub action will kick off to generate and publish preview builds for all packages in the monorepo.
3. After a few minutes, you will see a new comment that lists the newly published packages along with their versions.

<details><summary><b>Publishing preview builds as an independent contributor</b></summary>
<br/>
Note that the steps above will only work if you are a member of the MetaMask engineering team on GitHub. If you are not, you'll need to follow some different steps:

1. First, you'll need access to an NPM organization under which the preview builds will be published. If you have not already done so, you can either [create a new organization](https://www.npmjs.com/org/create) or [convert your existing username into an organization](https://www.npmjs.com/org/upgrade).
2. Open the `package.json` for each package that you want to publish, and change the NPM scope in the package's name from `@metamask` to reflect your NPM organization.
3. Run the following command to create and publish preview builds for all packages in the monorepo (replacing `NPM_ORG` as appropriate):

```bash
yarn prepare-preview-builds "@<NPM_ORG>" "$(git rev-parse --short HEAD)"
yarn build
yarn publish-previews
```

You will see a list of the newly published packages along with their versions.
</details>

## Using preview builds

To simulate production as best as possible, there are different instructions for using preview builds depending on whether the changes to a package you are testing are breaking or non-breaking.

### Testing non-breaking changes to a package

If you have made non-breaking changes to the package you want to test, and therefore plan on bumping the _minor_ or _patch_ part of that package's version, follow these steps:

1. In the project, open `package.json` and locate the entry in `dependencies` for the package. Take note of the major part of the version.

2. Run `yarn why @metamask/<PACKAGE_NAME>`, replacing `PACKAGE_NAME` as appropriate. You will see output like this:

```
├─ @metamask/parent-controller-1@npm:93.1.0
│ └─ @metamask/my-controller@npm:12.1.1 (via npm:^12.1.1)
├─ @metamask/parent-controller-2@npm:94.1.0
│ └─ @metamask/my-controller@npm:12.1.1 (via npm:^12.1.1)
├─ @metamask/parent-controller-3@npm:94.1.0 [abc9d]
│ └─ @metamask/my-controller@npm:12.1.1 [57677] (via npm:^12.1.1 [15228])
...
└─ metamask@workspace:.
└─ @metamask/my-controller@npm:12.1.1 [57677] (via npm:^12.1.0 [abc9d])
```

Take note of all the version ranges that match the major version you saw earlier (here, we are looking for all version ranges that start with `^12`).

3. Back in `package.json`, locate the section responsible for resolution overrides (or create one if it doesn't exist). If you're using Yarn, this is `resolutions`; if you're using NPM or any other package manager, this is `overrides`.

4. For each version range, add a new entry that looks like this:

```json
"@metamask/<PACKAGE_NAME>@<VERSION_RANGE>": "npm:@<NPM_ORG>/<PACKAGE_NAME>@<PREVIEW_VERSION>"
```

where:

- `PACKAGE_NAME` is the name of your package
- `VERSION_RANGE` is one of the version ranges you noted in step 2
- `NPM_ORG` is the NPM scope that the preview build is published under (note: this is _not_ `@metamask`)
- `PREVIEW_VERSION` is the version string of the preview build (note: this should _not_ start with `^`)

5. Run `yarn install` to apply the changes.

6. Run `yarn why @metamask/<PACKAGE_NAME>` again to confirm that all of the instances of the package you saw when you ran this command earlier are now using your preview build.

> **Example:**
>
> - You have non-breaking changes to `@metamask/controller-utils` you want to test
> - You're in a MetaMask client repo
> - `@metamask/controller-utils` is listed at `^1.1.4`, and `yarn why` reveals that `^1.0.1` and `^1.1.3` are also being used as version ranges in the dependency tree
> - You want to use the preview version `1.1.4-preview-e2df9b4`
>
> In this case, you would go to `resolutions` and add these lines:
>
> ```json
> "@metamask/controller-utils@^1.0.1": "npm:@metamask-previews/[email protected]",
> "@metamask/controller-utils@^1.1.3": "npm:@metamask-previews/[email protected]",
> "@metamask/controller-utils@^1.1.4": "npm:@metamask-previews/[email protected]",
> ```

### Testing breaking changes to a package

If you have made breaking changes to the package you want to test, and therefore plan on bumping the _major_ part of that package's version, follow these steps:

1. In the project, open `package.json`, and:

- Note the name of the package.
- Locate the section responsible for resolution overrides (or create one if it doesn't exist). If you're using Yarn, this is `resolutions`; if you're using NPM or any other package manager, this is `overrides`.

2. Add a new entry that looks like this:

```json
"<ROOT_PACKAGE_NAME>@workspace:./@metamask/<PACKAGE_NAME>": "npm:@<NPM_ORG>/<PACKAGE_NAME>@<PREVIEW_VERSION>"
```

where:

- `ROOT_PACKAGE_NAME` is the value of the `name` field at the top of `package.json`
- `NPM_ORG` is the NPM scope that the preview build is published under (note: this is _not_ `@metamask`)
- `PACKAGE_NAME` is the name of your package
- `PREVIEW_VERSION` is the version string of the preview build (note: this should _not_ start with `^`)

3. Run `yarn install` to apply the changes.

> **Example:**
>
> - You have breaking changes to `@metamask/network-controller` you want to test
> - You're in a MetaMask client repo
> - The `name` in `package.json` is "metamask"
> - `@metamask/network-controller` is listed at `^12.4.9`
> - You want to use the preview version `12.4.9-preview-e2df9b4`
>
> In this case, you would go to `resolutions` and add this line:
>
> ```json
> "metamask@workspace:./@metamask/network-controller@^12.4.9": "npm:@metamask-previews/[email protected]",
> ```

### Using a preview build for a patched package

When you go to add a resolution for a package you want to test following steps in either of the sections above, you may find that the package is patched. An entry for a patched dependency looks like this:

```json
"@metamask/<PACKAGE_NAME>": "patch:@metamask/<PACKAGE_NAME>@npm:<ESCAPED_VERSION_RANGE>#~/.yarn/patches/<PATCH_NAME>.patch"
```

where:

- `PACKAGE_NAME` is the name of the package.
- `ESCAPED_VERSION_RANGE` is the version range, but where characters like `^` are escaped (for instance, `^` will appear as `%3A`).
- `PATCH_NAME` is the filename for a patch. It is usually dash-separated, starts with the package name, and ends with the commit ID from which the patch was created.

You will need to ensure that you keep the patch when you use a preview build for the package. To do this:

1. Look for the escaped version range on the right-hand side of the dependency entry and mentally parse it to determine the underlying version range that the patch is being applied to.

2. When you add a resolution, target that version range on the left-hand side as if the patch were not there, and reuse the same `patch:` identifier on the right side, but replace the package name and version string accordingly.

- Note: Sometimes, for a patched dependency, the patch is present in not only as a dependency entry but also a resolution entry. If a resolution entry already exists, you'll want to replace it (but _only_ if you are making non-breaking changes, otherwise you'll want to add a new resolution).

> **Example 1 (non-breaking changes):**
>
> - You have non-breaking changes to `@metamask/controller-utils` you want to test
> - You're in a MetaMask client repo
> - `@metamask/controller-utils` is listed at `^1.1.4`, and `yarn why` reveals that `^1.0.1` and `^1.1.3` are also being used as version ranges in the dependency tree
> - The dependency entry looks like this:
> ```json
> "@metamask/controller-utils": "patch:@metamask/controller-utils@npm%3A1.1.4#~/.yarn/patches/@metamask-controller-utils-npm-1.1.4-cccac388c7.patch"
> ```
> - A resolution entry also exists which looks like this:
> ```json
> "@metamask/controller-utils@npm:^1.1.4": "patch:@metamask/controller-utils@npm%3A1.1.4#~/.yarn/patches/@metamask-controller-utils-npm-1.1.4-cccac388c7.patch"
> ```
> - You want to use the preview version `1.1.4-preview-e2df9b4`
>
> In this case, you would go to `resolutions`, _remove_ the existing entry, and add these new entries:
>
> ```json
> "@metamask/controller-utils@^1.0.1": "patch:@metamask-previews/controller-utils@npm%3A1.1.4-preview-e2df9b4#~/.yarn/patches/@metamask-controller-utils-npm-1.1.4-cccac388c7.patch"
> "@metamask/controller-utils@^1.1.3": "patch:@metamask-previews/controller-utils@npm%3A1.1.4-preview-e2df9b4#~/.yarn/patches/@metamask-controller-utils-npm-1.1.4-cccac388c7.patch"
> "@metamask/controller-utils@^1.1.4": "patch:@metamask-previews/controller-utils@npm%3A1.1.4-preview-e2df9b4#~/.yarn/patches/@metamask-controller-utils-npm-1.1.4-cccac388c7.patch"
> ```

> **Example 2 (breaking changes):**
>
> - You have breaking changes to `@metamask/network-controller` you want to test
> - You're in a MetaMask client repo
> - The `name` in `package.json` is "metamask"
> - `@metamask/network-controller` is listed at `^12.4.9`
> - The dependency entry looks like this:
> ```json
> "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A12.4.9#~/.yarn/patches/@metamask-network-controller-npm-12.4.9-cccac388c7.patch"
> ```
> - A resolution entry also exists which looks like this:
> ```json
> "@metamask/network-controller@npm:^12.4.9": "patch:@metamask/network-controller@npm%3A12.4.9#~/.yarn/patches/@metamask-network-controller-npm-12.4.9-cccac388c7.patch"
> ```
> - You want to use the preview version `12.4.9-preview-e2df9b4`
>
> In this case, you would go to `resolutions` and leave the existing one there, but _add_ a new one:
>
> ```json
> "metamask@workspace:./@metamask/network-controller@^12.4.9": "patch:@metamask-previews/network-controller@npm%3A12.4.9-preview-e2df9b4#~/.yarn/patches/@metamask-network-controller-npm-12.4.9-cccac388c7.patch"
> ```
95 changes: 4 additions & 91 deletions docs/processes/testing-changes-in-other-projects.md
Original file line number Diff line number Diff line change
@@ -1,95 +1,8 @@
# Testing changes to packages in other projects

If you have a project that depends on a package in this monorepo, you may want to load those changes into the project without having to create a whole new monorepo release. How you do this depends on your use case.
Often it is useful to test in-progress changes to one or more packages in the context of a project before releasing them (particularly when making [breaking changes](./breaking-changes.md)).

### Testing changes to packages locally
There are two ways to do this:

If you're developing your project locally and want to test changes to a package, you can follow these steps:

1. First, you must build the monorepo, by running `yarn build`.
2. Next, you need to connect the package to your project by overriding the resolution logic in your package manager to replace the published version of the package with the local version.

1. Open `package.json` in the project and locate the dependency entry for the package.
2. Locate the section responsible for resolution overrides (or create it if it doesn't exist). If you're using Yarn, this is `resolutions`; if you're using NPM or any other package manager, this is `overrides`.
3. Add a line to this section that mirrors the dependency entry on the left-hand side and points to the local path on the right-hand side:

```
"@metamask/<PACKAGE_NAME>@<PUBLISHED_VERSION_RANGE>": "file:<PATH_TO_CORE>/packages/<PACKAGE_NAME>"
```

> **Example:**
>
> - If your project uses Yarn, `@metamask/controller-utils` is listed in dependencies at `^1.1.4`, and your clone of the `core` repo is at the same level as your project, add the following to `resolutions`:
>
> ```
> "@metamask/controller-utils@^1.1.4": "file:../core/packages/controller-utils"
> ```

4. Run `yarn install`.

3. Due to the use of Yarn's `file:` protocol, if you update the package in the monorepo, then you'll need to run `yarn install` in the project again.

### Testing changes to packages with preview builds

If you want to test changes to a package where it would be unwieldy or impossible to use a local version, such as on CI, you can publish a preview build and configure your project to use it.

#### Publishing preview builds as a MetaMask contributor

If you're a member of the MetaMask organization, you can create preview builds based on a pull request by following these steps:

1. Post a comment on the pull request with the text `@metamaskbot publish-preview`. This starts the `publish-preview` GitHub action, which will create preview builds for all packages in the monorepo.
2. After a few minutes, the action should complete and you will see a new comment that lists the newly published packages along with their versions.

Note two things about each package:

- The name is scoped to `@metamask-previews` instead of `@metamask`.
- The ID of the last commit in the branch is appended to the version, e.g. `1.2.3-preview-e2df9b4` instead of `1.2.3`.

Now you can [use these preview builds in your project](#using-preview-builds).

If you make more changes to a package, follow step 2 again, making sure to update the reference to the package in your project's `package.json` to use the newly published preview version.

#### Publishing preview builds as an independent contributor

If you've forked this repository, you can create preview builds based on a branch by following these steps:

1. First, since an NPM scope is used to host preview build releases, you'll need access to one. If you do not, you can either [create a new organization](https://www.npmjs.com/org/create) or [convert your existing username into an organization](https://www.npmjs.com/org/upgrade).

2. Once you've done this, open the `package.json` for each package that you want to publish and change the scope in the name from `@metamask` to `@<NPM_ORG>`, replacing `NPM_ORG` with your NPM organization.

3. Next, run the following command to create and publish the preview builds (again, replacing `NPM_ORG` as appropriate):

```
yarn prepare-preview-builds "@<NPM_ORG>" "$(git rev-parse --short HEAD)" && yarn build && yarn publish-previews
```

You should be able to see the published version of each package in the output. Note two things:

- The name is scoped to the NPM organization you entered instead of `@metamask`.
- The ID of the last commit in the branch is appended to the version, e.g. `1.2.3-preview-e2df9b4` instead of `1.2.3`.

Now you can [use these preview builds in your project](#using-preview-builds).

If you make more changes to a package, follow step 3 again, making sure to update the reference to the package in your project's `package.json` to use the newly published preview version.

#### Using preview builds

To use a preview build for a package within a project, you need to override the resolution logic for your package manager so that the "production" version of that package is replaced with the preview version. Here's how you do that:

1. Open `package.json` in the project and locate the dependency entry for the core package for which you want to use a preview build.
2. Locate the section responsible for resolution overrides (or create it if it doesn't exist). If you're using Yarn, this is `resolutions`; if you're using NPM or any other package manager, this is `overrides`.
3. Add a line to this section that mirrors the dependency entry on the left-hand side and points to the preview version on the right-hand side:

```
"@metamask/<PACKAGE_NAME>@<PRODUCTION_VERSION_RANGE>": "npm:@<NPM_ORG>/<PACKAGE_NAME>@<PREVIEW_VERSION>"
```

> **Example:**
>
> - If your project uses Yarn, `@metamask/controller-utils` is listed in dependencies at `^1.1.4`, and you want to use the preview version `1.2.3-preview-e2df9b4`, add the following to `resolutions`:
>
> ```
> "@metamask/controller-utils@^1.1.4": "npm:@metamask-previews/[email protected]"
> ```

4. Run `yarn install`.
- [Preview builds](./preview-builds.md) _(recommended)_
- [Local builds](./local-builds.md)
2 changes: 1 addition & 1 deletion scripts/generate-preview-build-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async function main(): Promise<void> {
}

const previewBuildMessage = `
Preview builds have been published. [See these instructions](https://github.com/MetaMask/core/blob/main/docs/processes/testing-changes-in-other-projects.md#testing-changes-to-packages-with-preview-builds) for more information about preview builds.
Preview builds have been published. [See these instructions](https://github.com/MetaMask/core/blob/main/docs/processes/preview-builds.md) for more information about preview builds.

<details>

Expand Down
Loading