Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ For example:

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them
- [ ] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/internal-snaps/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking changes](https://github.com/MetaMask/internal-snaps/tree/main/docs/processes/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

This monorepo hosts MetaMask's first-party Snaps along with shared tooling and infrastructure for building, testing, and releasing them.

## Contributing

See the [Contributor Documentation](./docs/README.md) for help on:

- Setting up your development environment
- Working with the monorepo
- Testing changes in clients
- Issuing new releases
- Creating a new package

## Installation/Usage

Each snap in this repository has its own README with installation and usage instructions. See `packages/` for more.
Expand Down
26 changes: 26 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Contributor Documentation

Hi! Welcome to the contributor documentation for the `internal-snaps` monorepo.

## Getting started

- [Setting up your development environment](./getting-started/setting-up-your-environment.md)
- [Codeownership](./getting-started/codeownership.md)

## Processes

- [Performing operations across the monorepo](./processes/general-monorepo-operations.md)
- [Writing and running tests](./processes/testing.md)
- [Linting and formatting](./processes/linting-and-formatting.md)
- [Updating changelogs](./processes/updating-changelogs.md)
- [Creating pull requests](./processes/creating-pull-requests.md)
- [Releasing changes](./processes/releasing.md)
- [Preparing and releasing breaking changes](./processes/breaking-changes.md)
- [Testing changes to packages in other projects](./processes/testing-changes-in-other-projects.md)
- [Building packages](./processes/building.md)
- [Adding new packages to the monorepo](./processes/adding-new-packages.md)
- [Migrating external snaps to the monorepo](./processes/snap-migration-process-guide.md)

## Code guidelines

- [General MetaMask code guidelines](https://github.com/MetaMask/contributor-docs)
5 changes: 5 additions & 0 deletions docs/getting-started/codeownership.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Understanding codeowners

Although maintenance of this repository is superintended by the Networks team, the responsibility of maintenance is expected to be shared among multiple teams at MetaMask. The exact allocation is governed by the [`CODEOWNERS`](../../.github/CODEOWNERS) file.

\*\*If your team is listed as a codeowner for a package, you may change, approve pull requests, and create releases. Alternatively, if you feel that your team should be granted codeownership over a specific package, you can submit a pull request to change `CODEOWNERS`.
7 changes: 7 additions & 0 deletions docs/getting-started/setting-up-your-environment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Setting up your development environment

1. Install the current LTS version of [Node](https://nodejs.org).
- If you are using [NVM](https://github.com/creationix/nvm#installation) (recommended), running `nvm install` will install the latest version, and running `nvm use` will automatically choose the right Node version for you.
2. Run `corepack enable` to install [Yarn](https://yarnpkg.com) via [Corepack](https://github.com/nodejs/corepack?tab=readme-ov-file#how-to-install).
- If you have Yarn installed globally via Homebrew or NPM, you'll need to uninstall it before running this command.
3. Run `yarn install` to install dependencies and run any required post-install scripts.
29 changes: 29 additions & 0 deletions docs/processes/adding-new-packages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Adding new packages to the monorepo

> [!NOTE]
> If you're migrating an existing package to the monorepo, please see [the package migration documentation](./package-migration-process-guide.md). You may be able to make use of `create-package` when migrating your package, but there's a lot more to it.

Manually creating a new monorepo package can be a tedious, even frustrating process. To alleviate that problem, we have created a CLI that automates most of the job for us, creatively titled [`create-package`](../../scripts/create-package/). To create a new monorepo package, follow these steps:

1. Create a new package using `yarn create-package`.
- Use the `--help` flag for usage information.
- Once this is done, you can find a package with your chosen name in `/packages`.
2. Make sure your license is correct.
- By default, `create-package` gives your package an MIT license.
- If your desired license is _not_ MIT, then you must update your `LICENSE` file and the `license` field of `package.json`.
3. Update `.github/CODEOWNERS` to assign a team as the owner of the new package.
4. Add your dependencies.
- Do this as normal using `yarn`.
- Remember, if you are adding other monorepo packages as dependents, don't forget to add them to the `references` array in your package's `tsconfig.json` and `tsconfig.build.json`.

And that's it!

### Contributing to `create-package`

Along with this documentation, `create-package` is intended to be the source of truth for the process of adding new packages to the monorepo. Consequently, to change that process, you will want to change `create-package`.

The `create-package` directory contains a [template package](../../scripts/create-package/package-template/). The CLI is not aware of the contents of the template, only that its files have [placeholder values](../../scripts/create-package/constants.ts). When a new package is created, the template files are read from disk, the placeholder values are replaced with real ones, and the updated files are added to a new directory in `/packages`. To modify the template package:

- If you need to add or modify any files or folders, just go ahead and make your changes in [`/scripts/create-package/package-template`](../../scripts/create-package/package-template/). The CLI will read whatever's in that directory and write it to disk.
- If you need to add or modify any placeholders, make sure that your desired values are added to both the relevant file(s) and [`/scripts/create-package/constants.ts`](../../scripts/create-package/constants.ts). Then, update the implementation of the CLI accordingly.
- As with placeholders, updating the monorepo files that the CLI interacts with begins by updating [`/scripts/create-package/constants.ts`](../../scripts/create-package/constants.ts).
76 changes: 76 additions & 0 deletions docs/processes/breaking-changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Preparing and releasing breaking changes

When developing packages, it is always important to be intentional about the impact that changes have on projects which use those packages. However, special consideration must be given to breaking changes.

This guide provides best practices for documenting, preparing, releasing, and adapting to breaking changes within `internal-snaps` and in other projects.

## What is a breaking change?

A change to a package is "breaking" if upgrading a project to a version containing the change would require modifications to source code or configuration in order to avoid user- or developer-facing problems (an inability to use or build the project, a loss of functionality, etc.).

There are many kinds of breaking changes. Here are some examples:

- Removals
- Removing a method from a class
- Removing an export from a package (including a type export)
- Functional changes that require code changes or change expectations
- Changing the number of required arguments for a function or method
- Throwing a new error in a function or method
- Changing a function or method so that it no longer fires an event
- Breaking changes to types
- Adding external actions or events to a messenger type
- Narrowing the type of an argument in a function or method
- Changing the number of required properties in an object type
- Narrowing the type of a property in an object type
- Changing the number of type parameters for a type
- Making any other change listed [here](https://www.semver-ts.org/formal-spec/2-breaking-changes.html)
- Bumping the minimum supported Node.js version of a package
- Upgrading a dependency referenced in published code to a version that causes any of the above

## Introducing breaking changes safely

Before merging a PR that introduces breaking changes, it is important to ensure that they are accounted for among projects.

### 1. Document breaking changes

To inform other maintainers now and in the future, make sure that breaking changes are documented in the changelog:

1. Be explicit in your changelog entries about which classes, functions, types, etc. are affected.
2. Prefix entries with `**BREAKING:**`.
3. If relevant, provide details on how consuming code can adapt to the changes safely.
4. Move entries for breaking changes above all other kinds of changes within the same section.

<!-- Provide exmaples later when you have some git history. Uncomment below section. -->

<!-- For example:

```markdown

``` -->

### 2. Audit dependents

When you release your changes, which codebases will be affected?

Using the changelog as a guide, locate all of the places across MetaMask that use the affected classes, functions, types, etc.:

- To find dependents of your package within `internal-snaps`, look in the package's `package.json`, or simply search across the repo.
- To find dependents of your package across MetaMask, do a search on GitHub for import statements or, better, usages of the affected symbols.

### 3. Prepare upgrade PRs for dependents

Finally, how will dependent projects need to adapt to your breaking changes?

For dependent packages located in `internal-snaps`, you may get type errors immediately that you will have to fix in the same PR that introduces the breaking changes. Otherwise, create new PRs to migrate existing code.

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

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.
5. If you see compile-time or runtime errors, make changes to the project as necessary.
6. If you discover new breaking changes in your package that you haven't yet listed in the changelog, go back and [document them](#1-document-breaking-changes).
7. Once you've done this for all projects, check off the "I've followed the process for releasing breaking changes" item in the checklist at the bottom of your PR.

This process serves as a check to help you understand the full impact of your changes. It will also save you time after you make a new release, because you can reuse the draft PRs later to complete upgrades.
6 changes: 6 additions & 0 deletions docs/processes/building.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Building packages

Built files show up in the `dist/` directory in each package. These are the files which will ultimately be published to NPM.

- Run `yarn build` to build all packages in the monorepo.
- Run `yarn workspace <workspaceName> run build` to build a single package.
8 changes: 8 additions & 0 deletions docs/processes/creating-pull-requests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Creating pull requests

When submitting a pull request for this repo, take some a bit of extra time to fill out its description. Use the provided template as a guide, paying particular attention to the **Explanation** section. This section is intended for you to explain the purpose and scope of your changes and share knowledge that other engineers might not be able to see from reading the PR alone. Some questions you should seek to answer are:

- What is the motivator for these changes? What need are the changes satisfying? Is there a ticket you can share or can you provide some more context for people who might not be familiar with the domain?
- Are there any changes in particular whose purpose might not be obvious or whose implementation might be difficult to decipher? How do they work?
- If your primary goal was to update one package but you found you had to update another one along the way, why did you do so?
- If you had to upgrade a dependency, why did you do so?
11 changes: 11 additions & 0 deletions docs/processes/general-monorepo-operations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Performing operations across the monorepo

This repository relies on Yarn's [workspaces feature](https://yarnpkg.com/features/workspaces) to provide a way to work with packages individually and collectively. Refer to the documentation for the following Yarn commands for usage instructions:

- [`yarn workspace`](https://yarnpkg.com/cli/workspace)
- [`yarn workspaces foreach`](https://yarnpkg.com/cli/workspaces/foreach)

> **Note**
>
> - `workspaceName` in the Yarn documentation is the `name` field within a package's `package.json`, e.g., `@metamask/bitcoin-wallet-snap`.
> - `commandName` in the Yarn documentation is any sub-command that the `yarn` executable would usually take. Pay special attention to the difference between `run` vs `exec`. If you want to run a package script, you would use `run`, e.g., `yarn workspace @metamask/bitcoin-wallet-snap run changelog:validate`; but if you want to run _any_ shell command, you'd use `exec`, e.g. `yarn workspace @metamask/bitcoin-wallet-snap exec cat package.json | jq '.version'`.
8 changes: 8 additions & 0 deletions docs/processes/linting-and-formatting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Linting and formatting code

[ESLint](https://eslint.org) v9 (via [MetaMask's shared ESLint configurations](https://github.com/MetaMask/eslint-config)) is used to check for code quality issues, and [Oxfmt](https://oxc.rs/docs/guide/usage/formatter.html) is used to format files.

If you need to customize the behavior of ESLint, see `eslint.config.mjs` in the root.

- Run `yarn lint` to lint all files and show possible violations across the monorepo.
- Run `yarn lint:fix` to fix any automatically fixable violations.
40 changes: 40 additions & 0 deletions docs/processes/local-builds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 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/bitcoin-wallet-snap` you want to test
> - `@metamask/bitcoin-wallet-snap` is listed at `^1.15.2`
> - You've cloned this repo next to the project
>
> In this case, you would go to `dependencies` and replace the line:
>
> ```json
> "@metamask/bitcoin-wallet-snap": "^1.15.2"
> ```
>
> with:
>
> ```json
> "@metamask/bitcoin-wallet-snap@^1.15.2": "file:../internal-snaps/packages/bitcoin-wallet-snap"
> ```
Loading
Loading