Skip to content

Commit 6850973

Browse files
feat: Update RemoteFeatureFlag controller version to latest (#38584)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> This PR aims to update `RemoteFeatureFlagController` version to latest. As `clientVersion` is introduced as new breaking change, PR also includes base version of the app while initialising the controller. As this is not a user facing feature - no changelog needed. Related core PR: MetaMask/core#7277 [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/38584?quickstart=1) ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: Extension part of MetaMask/core#7285 ## **Manual testing steps** N/A ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [X] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [X] I’ve included tests if applicable - [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Upgrades the remote feature flag controller to v3 and begins sending the app’s base SemVer as `clientVersion`, adding a helper and tests and updating LavaMoat policies. > > - **Controllers**: > - Pass `clientVersion: getBaseSemVerVersion()` when initializing `RemoteFeatureFlagController` in `app/scripts/controller-init/remote-feature-flag-controller-init.ts`. > - **Feature Flags**: > - Add `getBaseSemVerVersion` in `shared/lib/feature-flags/version-gating.ts` to return base SemVer; include comprehensive unit tests. > - **Tests**: > - Update `remote-feature-flag-controller-init.test.ts` to expect `clientVersion`. > - **Security/Policies**: > - LavaMoat policies: allow `@metamask/utils` for `@metamask/remote-feature-flag-controller` across build variants. > - **Dependencies**: > - Bump `@metamask/remote-feature-flag-controller` to `^3.0.0`; update lockfile. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 7c17943. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: MetaMask Bot <[email protected]>
1 parent fa3b248 commit 6850973

File tree

11 files changed

+85
-3
lines changed

11 files changed

+85
-3
lines changed

app/scripts/controller-init/remote-feature-flag-controller-init.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ describe('RemoteFeatureFlagControllerInit', () => {
118118
fetchInterval: expect.any(Number),
119119
getMetaMetricsId: expect.any(Function),
120120
clientConfigApiService: expect.any(ClientConfigApiService),
121+
clientVersion: expect.any(String),
121122
});
122123
});
123124
});

app/scripts/controller-init/remote-feature-flag-controller-init.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
} from '@metamask/remote-feature-flag-controller';
99
import { ENVIRONMENT } from '../../../development/build/constants';
1010
import { previousValueComparator } from '../lib/util';
11+
import { getBaseSemVerVersion } from '../../../shared/lib/feature-flags/version-gating';
1112
import { ControllerInitFunction } from './types';
1213
import {
1314
RemoteFeatureFlagControllerInitMessenger,
@@ -89,6 +90,7 @@ export const RemoteFeatureFlagControllerInit: ControllerInitFunction<
8990
disabled: getIsDisabled(),
9091
getMetaMetricsId: () =>
9192
initMessenger.call('MetaMetricsController:getMetaMetricsId'),
93+
clientVersion: getBaseSemVerVersion(),
9294
clientConfigApiService: new ClientConfigApiService({
9395
fetch: globalThis.fetch.bind(globalThis),
9496
config: {

lavamoat/browserify/beta/policy.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2023,6 +2023,7 @@
20232023
"packages": {
20242024
"@metamask/base-controller": true,
20252025
"@metamask/controller-utils": true,
2026+
"@metamask/utils": true,
20262027
"uuid": true
20272028
}
20282029
},

lavamoat/browserify/experimental/policy.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2023,6 +2023,7 @@
20232023
"packages": {
20242024
"@metamask/base-controller": true,
20252025
"@metamask/controller-utils": true,
2026+
"@metamask/utils": true,
20262027
"uuid": true
20272028
}
20282029
},

lavamoat/browserify/flask/policy.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2023,6 +2023,7 @@
20232023
"packages": {
20242024
"@metamask/base-controller": true,
20252025
"@metamask/controller-utils": true,
2026+
"@metamask/utils": true,
20262027
"uuid": true
20272028
}
20282029
},

lavamoat/browserify/main/policy.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2023,6 +2023,7 @@
20232023
"packages": {
20242024
"@metamask/base-controller": true,
20252025
"@metamask/controller-utils": true,
2026+
"@metamask/utils": true,
20262027
"uuid": true
20272028
}
20282029
},

lavamoat/webpack/mv2/policy.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,7 @@
19521952
"packages": {
19531953
"@metamask/base-controller": true,
19541954
"@metamask/controller-utils": true,
1955+
"@metamask/utils": true,
19551956
"uuid": true
19561957
}
19571958
},

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@
356356
"@metamask/profile-sync-controller": "^26.0.0",
357357
"@metamask/providers": "^22.1.1",
358358
"@metamask/rate-limit-controller": "^7.0.0",
359-
"@metamask/remote-feature-flag-controller": "^2.0.0",
359+
"@metamask/remote-feature-flag-controller": "^3.0.0",
360360
"@metamask/rpc-errors": "^7.0.0",
361361
"@metamask/safe-event-emitter": "^3.1.1",
362362
"@metamask/scure-bip39": "^2.0.3",

shared/lib/feature-flags/version-gating.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import semver from 'semver';
22
import {
3+
getBaseSemVerVersion,
34
hasMinimumRequiredVersion,
45
validatedVersionGatedFeatureFlag,
56
VersionGatedFeatureFlag,
@@ -265,4 +266,49 @@ describe('version-gating', () => {
265266
});
266267
});
267268
});
269+
270+
describe('getBaseSemVerVersion', () => {
271+
const semverParseMock = semver.parse as jest.MockedFunction<
272+
typeof semver.parse
273+
>;
274+
275+
it('returns base version from package.json version', () => {
276+
semverParseMock.mockReturnValue({
277+
major: 12,
278+
minor: 5,
279+
patch: 0,
280+
} as semver.SemVer);
281+
282+
expect(getBaseSemVerVersion()).toBe('12.5.0');
283+
expect(semverParseMock).toHaveBeenCalledWith('12.5.0');
284+
});
285+
286+
it('strips prerelease tag when parsing version', () => {
287+
semverParseMock.mockReturnValue({
288+
major: 13,
289+
minor: 13,
290+
patch: 0,
291+
prerelease: ['experimental', 0],
292+
} as unknown as semver.SemVer);
293+
294+
expect(getBaseSemVerVersion()).toBe('13.13.0');
295+
});
296+
297+
it('strips build metadata when parsing version', () => {
298+
semverParseMock.mockReturnValue({
299+
major: 1,
300+
minor: 0,
301+
patch: 0,
302+
build: ['build', '123'],
303+
} as unknown as semver.SemVer);
304+
305+
expect(getBaseSemVerVersion()).toBe('1.0.0');
306+
});
307+
308+
it('returns unknown when semver.parse returns null', () => {
309+
semverParseMock.mockReturnValue(null);
310+
311+
expect(getBaseSemVerVersion()).toBe('unknown');
312+
});
313+
});
268314
});

shared/lib/feature-flags/version-gating.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@ export type VersionGatedFeatureFlag = {
88

99
const APP_VERSION = packageJson.version;
1010

11+
/**
12+
* Extracts the base 3-part SemVer version (major.minor.patch) from the package.json version.
13+
* Strips any prerelease or build metadata suffixes
14+
*
15+
* @returns The base version string (e.g., '13.13.0' or '13.2.3'), or 'unknown' if parsing fails
16+
*/
17+
export const getBaseSemVerVersion = (): string => {
18+
const parsed = semver.parse(APP_VERSION);
19+
if (!parsed) {
20+
return 'unknown';
21+
}
22+
23+
return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
24+
};
25+
1126
export const hasMinimumRequiredVersion = (
1227
minRequiredVersion?: string | null,
1328
) => {

0 commit comments

Comments
 (0)