Skip to content

Commit dceca8a

Browse files
release: 7.67.0 (#26310)
# 🚀 v7.67.0 Testing & Release Quality Process Hi Team, As part of our new **MetaMask Release Quality Process**, here’s a quick overview of the key processes, testing strategies, and milestones to ensure a smooth and high-quality deployment. --- ## 📋 Key Processes ### Testing Strategy - **Developer Teams:** Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows. - **QA Team:** Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing. - **Customer Success Team:** Validate new functionalities and provide feedback to support release monitoring. ### GitHub Signoff - Each team must **sign off on the Release Candidate (RC)** via GitHub by the end of the validation timeline (**Tuesday EOD PT**). - Ensure all tests outlined in the Testing Plan are executed, and any identified issues are addressed. ### Issue Resolution - **Resolve all Release Blockers** (Sev0 and Sev1) by **Tuesday EOD PT**. - For unresolved blockers, PRs may be reverted, or feature flags disabled to maintain release quality and timelines. ### Cherry-Picking Criteria - Only **critical fixes** meeting outlined criteria will be cherry-picked. - Developers must ensure these fixes are thoroughly reviewed, tested, and merged by **Tuesday EOD PT**. --- ## 🗓️ Timeline and Milestones 1. **Today (Friday):** Begin Release Candidate validation. 2. **Tuesday EOD PT:** Finalize RC with all fixes and cherry-picks. 3. **Wednesday:** Buffer day for final checks. 4. **Thursday:** Submit release to app stores and begin rollout to 1% of users. 5. **Monday:** Scale deployment to 10%. 6. **Tuesday:** Full rollout to 100%. --- ## ✅ Signoff Checklist Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion: # Team sign-off checklist - [x] Accounts Framework - [x] Assets - [x] BE Trade - [x] Bots Team - [x] Card - [x] Confirmations - [x] Core Platform - [x] Design System - [x] Earn - [x] Engagement - [x] Mobile Platform - [x] Mobile UX - [x] Networks - [x] Onboarding - [x] Perps - [x] Predict - [x] Product Safety - [x] Ramp - [x] Rewards - [x] Social & AI - [x] Swaps and Bridge - [x] Wallet Integrations This process is a major step forward in ensuring release stability and quality. Let’s stay aligned and make this release a success! 🚀 Feel free to reach out if you have questions or need clarification. Many thanks in advance # Reference - Testing plan sheet - https://docs.google.com/spreadsheets/d/1tsoodlAlyvEUpkkcNcbZ4PM9HuC9cEM80RZeoVv5OCQ/edit?gid=404070372#gid=404070372 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it changes GitHub Actions build/test workflows (artifact handling, sharding/coverage merge, BrowserStack tunnel behavior) and updates several Yarn patches that affect controller/metrics/runtime behavior. Failures are most likely in CI stability, artifact publishing, or analytics payload shape rather than end-user security. > > **Overview** > **Release 7.67.0** with version bumps (Android `versionName`/`versionCode`, `package.json` version) and cleanup of deprecated Storybook “temp” header components. > > Build/CI workflows are reworked: `build.yml` adds iOS environment setup, standardizes artifact renaming via `scripts/rename-artifacts.js`, and uploads iOS/Android outputs as artifacts; `ci.yml` shards component-view tests (`cv-test`) and merges coverage into a single HTML report, updating downstream job dependencies. > > E2E/performance automation is extended for *mm-connect* on BrowserStack (local tunnel handling, longer readiness wait, new test command, and clearer artifact naming), with updated concurrency/permissions. Tooling updates include a Perps-specific ESLint “Core-alignment” override (adds `promise` plugin and stricter rules), expanded Ramp CODEOWNERS patterns, a new WalletConnect v2 verify context type stored in `wc2Metadata`, and updated Yarn patches for assets/bridge controllers and Appwright behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit b1c3e3e. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
2 parents 624b19f + 0c23991 commit dceca8a

1,273 files changed

Lines changed: 80650 additions & 33092 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cursor/BUGBOT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ Use the rules in the [e2e-testing-guidelines](rules/e2e-testing-guidelines.mdc)
2626

2727
- **ALWAYS** load and reference [component-view-testing](rules/component-view-testing.mdc)
2828
- Verify test file naming pattern: `**/*.view.test.{ts,tsx,js,jsx}`
29-
- Check for proper use of presets and renderers from `app/util/test/component-view/`
29+
- Check for proper use of presets and renderers from `tests/component-view/`
3030

3131
Use the rules in the [component-view-testing](rules/component-view-testing.mdc) to enforce the test quality and bug detection.

.cursor/rules/component-view-testing.mdc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
description: Mobile component-view testing rules (project-wide). Engine-only mocks, state-driven tests, presets/renderers, deterministicFiat, AAA, execution.
33
globs:
44
- "**/*.view.test.{ts,tsx,js,jsx}"
5-
- "app/util/test/component-view/**"
6-
alwaysApply: false
5+
- "tests/component-view/**"
6+
alwaysApply: true
77
---
88

99
## Component-view Testing (Project-wide)
@@ -28,15 +28,16 @@ Follow these rules for all component view tests. Nested, component-specific rule
2828
- AAA pattern with blank lines between sections.
2929
- Action-oriented names (no "should").
3030
- One behavior per test; robust assertions over brittle formatting.
31+
- **No fake timers**: Do not use `jest.useFakeTimers()`, `jest.advanceTimersByTime()`, or `jest.useRealTimers()` in component view tests; use `waitFor(..., { timeout })` or real delays instead (fake timers conflict with `waitFor` and can cause flakiness).
3132

3233
- **Execution**
3334
- Prefer `--coverage=false` during iteration for speed.
3435
- Use yarn only (no npm/npx).
3536

3637
- **References**
3738
- Component-view framework guide: `docs/readme/component-view-testing.md`
38-
- Detailed rules: `app/util/test/component-view/COMPONENT_VIEW_TEST_RULES.md`
39+
- Detailed rules: `tests/component-view/COMPONENT_VIEW_TEST_RULES.md`
3940
- Cursor authoring rules: [Cursor Context Rules](https://cursor.com/docs/context/rules)
4041

4142
@docs/readme/component-view-testing.md
42-
@app/util/test/component-view/COMPONENT_VIEW_TEST_RULES.md
43+
@tests/component-view/COMPONENT_VIEW_TEST_RULES.md

.e2e.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ export TEST_SRP_2=
2727
export TEST_SRP_3=
2828
export BROWSERSTACK_USERNAME=
2929
export BROWSERSTACK_ACCESS_KEY=
30+
# Set BROWSERSTACK_LOCAL=true when using run-appwright:mm-connect-android-bs-local (BrowserStack Local tunnel)
31+
# BROWSERSTACK_LOCAL=true
3032
export SEEDLESS_ONBOARDING_ENABLED=
3133
export SOLANA_MODAL_ENABLED=
3234

.eslintrc.js

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module.exports = {
1616
plugins: [
1717
'@typescript-eslint',
1818
'@metamask/design-tokens',
19+
'promise',
1920
'react-compiler',
2021
'tailwindcss',
2122
],
@@ -174,6 +175,201 @@ module.exports = {
174175
],
175176
},
176177
},
178+
// ── Perps controller Core-alignment override ──
179+
// Enforces the same ESLint rules that Core's @metamask/eslint-config
180+
// applies to packages/perps-controller so that code written in mobile
181+
// passes Core's linter after a straight copy.
182+
//
183+
// Plugin differences from Core:
184+
// - mobile uses `import` (eslint-plugin-import); Core uses `import-x`
185+
// (eslint-plugin-import-x). Rules are identical; `--fix` in Core
186+
// handles any formatting delta.
187+
//
188+
// See docs/perps/perps-core-sync.md for the full sync workflow.
189+
{
190+
files: ['app/controllers/perps/**/*.{ts,tsx}'],
191+
excludedFiles: ['**/*.test.ts', '**/*.test.tsx'],
192+
rules: {
193+
// === Existing rule ===
194+
'@typescript-eslint/consistent-type-definitions': ['error', 'type'],
195+
196+
// === Core base rules (from @metamask/eslint-config) ===
197+
'no-restricted-syntax': [
198+
'error',
199+
{
200+
selector: 'TSParameterProperty',
201+
message:
202+
'Prefer explicit property declaration and assignment in constructor.',
203+
},
204+
{
205+
selector: "MethodDefinition[accessibility='private']",
206+
message:
207+
'Use ES private class fields (#field) instead of TypeScript private keyword.',
208+
},
209+
{
210+
selector: "PropertyDefinition[accessibility='private']",
211+
message:
212+
'Use ES private class fields (#field) instead of TypeScript private keyword.',
213+
},
214+
],
215+
'id-denylist': [
216+
'error',
217+
'buf',
218+
'cat',
219+
'err',
220+
'cb',
221+
'cfg',
222+
'hex',
223+
'int',
224+
'msg',
225+
'num',
226+
'opt',
227+
'sig',
228+
],
229+
'id-length': [
230+
'error',
231+
{
232+
min: 2,
233+
exceptionPatterns: ['_', 'a', 'b', 'i', 'j', 'k'],
234+
properties: 'never',
235+
},
236+
],
237+
'no-negated-condition': 'error',
238+
'no-eq-null': 'error',
239+
'no-nested-ternary': 'error',
240+
'no-plusplus': ['error', { allowForLoopAfterthoughts: true }],
241+
'require-unicode-regexp': 'error',
242+
'consistent-return': 'error',
243+
'prefer-template': 'error',
244+
'prefer-destructuring': [
245+
'error',
246+
{
247+
VariableDeclarator: { array: false, object: true },
248+
AssignmentExpression: { array: false, object: false },
249+
},
250+
{ enforceForRenamedProperties: false },
251+
],
252+
'no-implicit-coercion': 'error',
253+
'no-param-reassign': 'error',
254+
'no-duplicate-imports': 'off',
255+
curly: ['error', 'all'],
256+
'no-void': 'error',
257+
258+
// === TypeScript type-aware rules ===
259+
'no-shadow': 'off',
260+
'@typescript-eslint/no-shadow': ['error', { builtinGlobals: true }],
261+
'@typescript-eslint/prefer-nullish-coalescing': 'error',
262+
'@typescript-eslint/prefer-readonly': 'error',
263+
'@typescript-eslint/explicit-function-return-type': 'error',
264+
'@typescript-eslint/naming-convention': [
265+
'error',
266+
{
267+
selector: 'default',
268+
format: ['camelCase'],
269+
leadingUnderscore: 'allow',
270+
trailingUnderscore: 'forbid',
271+
},
272+
{
273+
selector: 'enumMember',
274+
format: ['PascalCase'],
275+
},
276+
{
277+
selector: 'import',
278+
format: ['camelCase', 'PascalCase', 'snake_case', 'UPPER_CASE'],
279+
},
280+
{
281+
selector: 'interface',
282+
format: ['PascalCase'],
283+
custom: {
284+
regex: '^I[A-Z]',
285+
match: false,
286+
},
287+
},
288+
{
289+
selector: 'objectLiteralMethod',
290+
format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
291+
},
292+
{
293+
selector: 'objectLiteralProperty',
294+
format: null,
295+
},
296+
{
297+
selector: 'typeLike',
298+
format: ['PascalCase'],
299+
},
300+
{
301+
selector: 'typeParameter',
302+
format: ['PascalCase'],
303+
custom: { regex: '^.{3,}', match: true },
304+
},
305+
{
306+
selector: 'variable',
307+
format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
308+
leadingUnderscore: 'allow',
309+
},
310+
{
311+
selector: 'parameter',
312+
format: ['camelCase', 'PascalCase'],
313+
leadingUnderscore: 'allow',
314+
},
315+
{
316+
selector: [
317+
'classProperty',
318+
'objectLiteralProperty',
319+
'typeProperty',
320+
'classMethod',
321+
'objectLiteralMethod',
322+
'typeMethod',
323+
'accessor',
324+
'enumMember',
325+
],
326+
format: null,
327+
modifiers: ['requiresQuotes'],
328+
},
329+
],
330+
'@typescript-eslint/consistent-type-exports': 'error',
331+
'@typescript-eslint/no-floating-promises': 'error',
332+
'@typescript-eslint/restrict-template-expressions': 'error',
333+
334+
// === Import rules (using 'import' plugin, not 'import-x') ===
335+
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
336+
'import/no-named-as-default': 'error',
337+
'import/order': [
338+
'error',
339+
{
340+
groups: [
341+
['builtin', 'external'],
342+
['internal', 'parent', 'sibling', 'index'],
343+
],
344+
alphabetize: { order: 'asc', caseInsensitive: true },
345+
'newlines-between': 'always',
346+
},
347+
],
348+
349+
// === JSDoc rules ===
350+
'jsdoc/check-alignment': 'error',
351+
'jsdoc/tag-lines': ['error', 'any', { startLines: 1 }],
352+
'jsdoc/check-param-names': 'error',
353+
'jsdoc/require-param': 'error',
354+
'jsdoc/require-param-description': 'error',
355+
'jsdoc/require-returns': 'error',
356+
'jsdoc/require-returns-description': 'error',
357+
358+
// === Promise rules (eslint-plugin-promise) ===
359+
'promise/always-return': 'error',
360+
'promise/no-nesting': 'error',
361+
'promise/no-callback-in-promise': 'error',
362+
'promise/param-names': 'error',
363+
},
364+
},
365+
{
366+
// Perps test files use top-level type imports (import type + import from same module),
367+
// which conflicts with the global no-duplicate-imports rule.
368+
files: ['app/controllers/perps/**/*.test.{ts,tsx}'],
369+
rules: {
370+
'no-duplicate-imports': 'off',
371+
},
372+
},
177373
{
178374
files: ['app/**/*.{ts,tsx}'],
179375
excludedFiles: ['app/controllers/perps/**/*.{ts,tsx}'],

.github/CODEOWNERS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ app/core/Engine/controllers/ramps-controller @MetaMask/ramp
6565
app/core/Engine/messengers/ramps-controller-messenger @MetaMask/ramp
6666
app/core/Engine/messengers/ramps-service-messenger @MetaMask/ramp
6767
app/selectors/rampsController @MetaMask/ramp
68+
**/Ramp/** @MetaMask/ramp
69+
**/ramp/** @MetaMask/ramp
70+
**/ramps/** @MetaMask/ramp
6871

6972
# Card Team
7073
app/components/UI/Card/ @MetaMask/card
@@ -218,6 +221,7 @@ app/components/Views/Settings @MetaMask/mobile-core-ux
218221
app/components/Views/TermsAndConditions @MetaMask/mobile-core-ux
219222
app/components/Views/MultichainTransactionsView @MetaMask/mobile-core-ux
220223
app/components/Views/UnifiedTransactionsView @MetaMask/mobile-core-ux
224+
app/components/Views/AccountsMenu @MetaMask/mobile-core-ux
221225
app/components/UI/MultichainTransactionListItem @MetaMask/mobile-core-ux
222226
app/components/UI/TransactionActionModal @MetaMask/mobile-core-ux
223227
app/components/UI/TransactionElement @MetaMask/mobile-core-ux

0 commit comments

Comments
 (0)