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

migrations guidelines #96

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This is a living repository — nothing is set in stone! If you're member of Met
- [Contributor Code of Conduct](https://github.com/MetaMask/.github/blob/main/CODE_OF_CONDUCT.md)
- [Engineering Principles](./docs/engineering-principles.md)
- [JavaScript Guidelines](./docs/javascript.md)
- [Migrations Best Practices](./docs/migrations-guidelines.md)
- [Performance Tracing Guidelines](./docs/performance-tracing.md)
- [Pull Requests Guide](./docs/pull-requests.md)
- [React Guidelines](./docs/react.md)
Expand Down
62 changes: 62 additions & 0 deletions docs/migrations-guidelines.md
tommasini marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Migration and Testing Guidelines

## Overview

This document outlines best practices and guidelines for writing migration scripts and their corresponding test cases.

The focus is on ensuring data integrity, handling errors gracefully, and maintaining consistency across our applications versions.

We always look for improvement, if you see anything that could be improved, please open a PR against this guidelines.

You can also check an example of a migration on MetaMask mobile app [here](https://github.com/MetaMask/metamask-mobile/blob/1855bd674e33bb0ece06fb6d8f09a4e5df46a108/app/store/migrations/044.ts#L1)

## Migration Guidelines

1. **State Integrity Checks**:

Validates the state's structure and types before migration, using specific functions to ensure data meets expectations. Halts migration if inconsistencies are detected, preventing data corruption.

- State's on migrations are type `unknown`, it's crucial to validate state integrity before proceeding, we only migrate when structure and types meets our expectations,
- Validate the state and its nested properties using functions like `isObject` and `hasProperty` from `@metamask/utils`,
- Prevent data corruption by halting the migration on any inconsistencies and logging errors.

2. **Error Handling**:

Logs detailed errors and halts the migration if potential data corruption is identified, ensuring issues are addressed before proceeding.

- Log errors with `captureException` from Sentry, which is crucial for diagnosing issues post-migration,
- Ensure that error messages are descriptive: include the migration number and a clear description of the issue,
- If an exception is detected, indicating potential data corruption, halt the migration process and return the intial state,

3. **Return State**:

Completes the migration by returning the state, modified or not, ensuring a seamless transition to subsequent migrations.

- Always return the state at the end of the migration function, whether it was modified or not,
- Returning the state ensures that the migration process completes and the state is passed to the next migrations.

## Testing Guidelines
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we add something to look at the oldest widely adopted version to generate the first set of state for testing?


1. **Initial State Setup**:

- Create an initial state that reflects possible real-world scenarios, including edge cases,
- if needed, create multiple initial states and use them each in a test for this specific case,

2. **Invalid State Scenarios**:

- Test how the migration handles invalid states, including null values, incorrect types, and missing properties,
- Ensure that the migration logs the appropriate errors without modifying and corrupting the state.

3. **Error Assertions**:

- Verify that errors are logged correctly for invalid states or unexpected conditions,

4. **Ensure State Immutability**:

- Always use deep cloning on the old state before passing it to the migration function in tests. For example, use `cloneDeep` from `lodash`.
- Deep cloning preserves the integrity of your test data across different test cases.
- Ensures the original state object is not mutated during the migration process.
- guarantees that each test case runs on an correct, clean copy of the state.
- Never mutate the state directly as this can:
- lead to hard-to-track bugs and false positives or negatives test results.
- start subsequent tests with the original state as intended.
Loading