Skip to content

Commit 0265117

Browse files
committed
Merge branch 'main' into jl/eip-5792-middleware-3-0-0
2 parents f56ff68 + da19bad commit 0265117

1,469 files changed

Lines changed: 69116 additions & 53069 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.

.depcheckrc.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,18 @@ ignores:
139139

140140
# Used in Yarn plugin for preview builds
141141
- '@yarnpkg/core'
142+
143+
# Babel plugins referenced in babel.config.js by their short name (without
144+
# the `babel-plugin-` prefix). Babel resolves them correctly at build time
145+
# but depcheck doesn't recognize the indirect reference. See babel.config.js
146+
# line 65 comment for details.
147+
- 'babel-plugin-react-compiler' # used as 'react-compiler' (line 68)
148+
- 'babel-plugin-transform-inline-environment-variables' # used as 'transform-inline-environment-variables' (line 81)
149+
- 'babel-plugin-transform-remove-console' # used as 'transform-remove-console' (line 166, production env)
150+
151+
# Listed as a direct dep in package.json but no longer referenced in
152+
# babel.config.js (we use babel-preset-expo) or anywhere in our source.
153+
# It's still available transitively via babel-preset-expo + Metro, so
154+
# removing the direct declaration should be a no-op — left for a follow-up
155+
# cleanup once the RN 0.81 upgrade has settled to avoid surprises.
156+
- '@react-native/babel-preset'

.eslintrc.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,33 @@ module.exports = {
385385
],
386386
},
387387
},
388+
{
389+
files: ['**/*.test.{js,ts,tsx,jsx}', '**/*.spec.{js,ts,tsx,jsx}'],
390+
plugins: ['jest'],
391+
rules: {
392+
// Prevent new file-based snapshots. Inline snapshots (toMatchInlineSnapshot)
393+
// are still allowed as they keep assertions co-located with the test.
394+
'jest/no-restricted-matchers': [
395+
'error',
396+
{
397+
toMatchSnapshot:
398+
'Use toMatchInlineSnapshot() or an explicit assertion instead. File-based snapshots are being phased out.',
399+
},
400+
],
401+
},
402+
},
403+
{
404+
// Matches CODEOWNERS `**/snaps/**` and `**/Snaps/**` (@MetaMask/core-platform).
405+
// ESLint cannot read CODEOWNERS.
406+
files: [
407+
'**/snaps/**/*.{test,spec}.{js,ts,tsx,jsx}',
408+
'**/Snaps/**/*.{test,spec}.{js,ts,tsx,jsx}',
409+
],
410+
plugins: ['jest'],
411+
rules: {
412+
'jest/no-restricted-matchers': 'off',
413+
},
414+
},
388415
// ── Perps controller Core-alignment override ──
389416
// Enforces the same ESLint rules that Core's @metamask/eslint-config
390417
// applies to packages/perps-controller so that code written in mobile

.github/CODEOWNERS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,12 @@ app/components/UI/TemplateRenderer @MetaMask/confirmations @MetaMask/core-plat
158158
app/components/UI/Stake @MetaMask/earn
159159
app/core/Engine/controllers/earn-controller @MetaMask/earn
160160
app/core/Engine/messengers/earn-controller-messenger @MetaMask/earn
161+
app/core/Engine/controllers/chomp-api-service-init* @MetaMask/earn
162+
app/core/Engine/controllers/money-account-upgrade-controller-init* @MetaMask/earn
163+
app/core/Engine/messengers/chomp-api-service-messenger* @MetaMask/earn
164+
app/core/Engine/messengers/money-account-upgrade-controller-messenger* @MetaMask/earn
161165
app/selectors/earnController @MetaMask/earn
166+
app/selectors/featureFlagController/chompApi/ @MetaMask/earn
162167
**/Earn/** @MetaMask/earn
163168
**/earn/** @MetaMask/earn
164169
**/Money/** @MetaMask/earn
@@ -358,6 +363,7 @@ tests/websocket/ @MetaMask/qa
358363
.github/workflows/run-performance-e2e.yml @MetaMask/qa
359364
.github/workflows/run-performance-e2e-experimental.yml @MetaMask/qa
360365
.github/workflows/run-performance-e2e-release.yml @MetaMask/qa
366+
.github/workflows/run-system-tests.yml @MetaMask/qa
361367
.github/scripts/e2e-*.mjs @MetaMask/qa
362368
.github/scripts/collect-qa-stats.mjs @MetaMask/qa
363369
.github/scripts/generate-regression-slack-summary.mjs @MetaMask/qa

.github/actionlint.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ self-hosted-runner:
1515
- "ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg"
1616
- "ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-xl"
1717
- "low-priority"
18+
# Namespace runner profile labels (INFRA-3592). Format: namespace-profile-<profile-name>.
19+
- "namespace-profile-metamask-ci-linux"
20+
- "namespace-profile-metamask-android-build"
21+
- "namespace-profile-metamask-ios-build"
22+
- "namespace-profile-metamask-ios-e2e"
1823

1924
# Configuration variables in array of strings defined in your repository or
2025
# organization. `null` means disabling configuration variables check.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: 'Check force-builds override'
2+
description: >-
3+
Detects whether the current workflow run should bypass native build reuse
4+
(both the GHA cache and the cross-run artifact lookup) and always compile
5+
fresh. The override is honored on `pull_request` events via a `force-builds`
6+
label OR a `[force-builds]` token in the head commit message. It is
7+
intentionally ignored on `merge_group` and `push` events so the merge queue
8+
always uses hash-verified reuse.
9+
10+
inputs:
11+
github-token:
12+
description: >-
13+
GitHub token with `pull-requests: read` (for label lookup) and
14+
`contents: read` (to fetch the head commit message via the REST API).
15+
required: true
16+
label-name:
17+
description: 'PR label that, when present, forces fresh builds'
18+
required: false
19+
default: 'force-builds'
20+
commit-tag:
21+
description: 'Case-sensitive substring in the head commit message that forces fresh builds'
22+
required: false
23+
default: '[force-builds]'
24+
25+
outputs:
26+
force:
27+
description: "'true' when fresh builds should be forced, otherwise 'false'"
28+
value: ${{ steps.compute.outputs.force }}
29+
30+
runs:
31+
using: 'composite'
32+
steps:
33+
- name: Compute force-builds flag
34+
id: compute
35+
shell: bash
36+
env:
37+
GH_TOKEN: ${{ inputs.github-token }}
38+
LABEL_NAME: ${{ inputs.label-name }}
39+
COMMIT_TAG: ${{ inputs.commit-tag }}
40+
EVENT_NAME: ${{ github.event_name }}
41+
HEAD_COMMIT_HASH: ${{ github.event.pull_request.head.sha }}
42+
PR_NUMBER: ${{ github.event.pull_request.number }}
43+
REPOSITORY: ${{ github.repository }}
44+
run: |
45+
FORCE="false"
46+
47+
if [[ "$EVENT_NAME" != "pull_request" ]]; then
48+
echo "Event is $EVENT_NAME; force-builds override is ignored outside pull_request events."
49+
echo "force=$FORCE" >> "$GITHUB_OUTPUT"
50+
exit 0
51+
fi
52+
53+
# Commit-message tag.
54+
COMMIT_MESSAGE=""
55+
if COMMIT_MESSAGE=$(gh api \
56+
"repos/$REPOSITORY/commits/$HEAD_COMMIT_HASH" \
57+
--jq '.commit.message' 2>/dev/null); then
58+
if printf '%s' "$COMMIT_MESSAGE" \
59+
| grep --fixed-strings --quiet "$COMMIT_TAG"; then
60+
echo "-> force=true because '$COMMIT_TAG' was found in commit message of $HEAD_COMMIT_HASH"
61+
FORCE="true"
62+
fi
63+
else
64+
echo "::warning::Failed to fetch commit message for $HEAD_COMMIT_HASH via GitHub API; commit-tag force-builds check skipped for this run (the '$LABEL_NAME' label path still works)."
65+
fi
66+
67+
# PR label
68+
if [[ -n "$PR_NUMBER" ]]; then
69+
if gh pr view "$PR_NUMBER" --repo "$REPOSITORY" \
70+
--json labels --jq '.labels[].name' \
71+
| grep --fixed-strings --line-regexp --quiet "$LABEL_NAME"; then
72+
echo "-> force=true because '$LABEL_NAME' label is applied to PR #$PR_NUMBER"
73+
FORCE="true"
74+
fi
75+
fi
76+
77+
if [[ "$FORCE" == "false" ]]; then
78+
echo "No force-builds override active."
79+
fi
80+
81+
echo "force=$FORCE" >> "$GITHUB_OUTPUT"
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
name: CI Status Gate
2+
description: Evaluate required CI job results and fail on unexpected skips or failed jobs.
3+
4+
inputs:
5+
needs-json:
6+
description: JSON representation of the calling job's needs context.
7+
required: true
8+
requirement-context-json:
9+
description: JSON representation of get-requirements outputs.
10+
required: true
11+
e2e-job-regex:
12+
description: Regex matching E2E build/test jobs whose skipped result is allowed. Failed or cancelled E2E jobs still fail.
13+
required: false
14+
default: '^e2e-'
15+
event-name:
16+
description: GitHub event name for the current workflow run.
17+
required: true
18+
is-fork:
19+
description: Whether the current pull request originates from a fork. When true, skipped jobs are treated as allowed skips.
20+
required: false
21+
default: 'false'
22+
23+
runs:
24+
using: composite
25+
steps:
26+
- name: Evaluate CI status
27+
shell: bash
28+
env:
29+
NEEDS_JSON: ${{ inputs.needs-json }}
30+
REQUIREMENT_CONTEXT_JSON: ${{ inputs.requirement-context-json }}
31+
E2E_JOB_REGEX: ${{ inputs.e2e-job-regex }}
32+
EVENT_NAME: ${{ inputs.event-name }}
33+
IS_FORK: ${{ inputs.is-fork }}
34+
run: |
35+
set -euo pipefail
36+
37+
get_requirement() {
38+
local key="$1"
39+
jq -nr --arg key "$key" 'env.REQUIREMENT_CONTEXT_JSON | fromjson | .[$key] // "false"'
40+
}
41+
42+
sanitize_markdown_cell() {
43+
local value="$1"
44+
value="${value//$'\n'/ }"
45+
value="${value//|/\\|}"
46+
printf '%s' "$value"
47+
}
48+
49+
add_summary_row() {
50+
local job_name result decision reason
51+
job_name="$(sanitize_markdown_cell "$1")"
52+
result="$(sanitize_markdown_cell "$2")"
53+
decision="$(sanitize_markdown_cell "$3")"
54+
reason="$(sanitize_markdown_cell "$4")"
55+
56+
printf '| `%s` | `%s` | %s | %s |\n' \
57+
"$job_name" "$result" "$decision" "$reason" >> "$summary_file"
58+
}
59+
60+
mark_failure() {
61+
local message="$1"
62+
failed="true"
63+
echo "::error::$message"
64+
}
65+
66+
validate_json_type() {
67+
local variable_name="$1"
68+
local expected_type="$2"
69+
70+
if ! jq -en --arg variable_name "$variable_name" --arg expected_type "$expected_type" \
71+
'(env[$variable_name] | fromjson | type) == $expected_type' >/dev/null 2>&1; then
72+
echo "::error::$variable_name is not a valid JSON $expected_type"
73+
exit 1
74+
fi
75+
}
76+
77+
require_requirement_key() {
78+
local key="$1"
79+
80+
if ! jq -en --arg key "$key" \
81+
'env.REQUIREMENT_CONTEXT_JSON | fromjson | .[$key] != null' >/dev/null 2>&1; then
82+
echo "::error::REQUIREMENT_CONTEXT_JSON is missing or null for required key: $key"
83+
exit 1
84+
fi
85+
}
86+
87+
validate_json_type NEEDS_JSON object
88+
validate_json_type REQUIREMENT_CONTEXT_JSON object
89+
90+
for required_key in skip_everything block_merge_for_e2e_readiness; do
91+
require_requirement_key "$required_key"
92+
done
93+
94+
skip_everything="$(get_requirement skip_everything)"
95+
block_merge_for_e2e_readiness="$(get_requirement block_merge_for_e2e_readiness)"
96+
97+
if [[ "$block_merge_for_e2e_readiness" == "true" ]]; then
98+
echo "::error::The 'pr-not-ready-for-e2e' label is still applied. Remove it to trigger E2E tests before merging."
99+
exit 1
100+
fi
101+
102+
if [[ "$skip_everything" == "true" ]]; then
103+
echo "skip_everything=true; treating all jobs as passed"
104+
exit 0
105+
fi
106+
107+
failed="false"
108+
summary_file="$(mktemp)"
109+
trap 'if [[ -n "${GITHUB_STEP_SUMMARY:-}" && -f "$summary_file" ]]; then cat "$summary_file" >> "$GITHUB_STEP_SUMMARY"; fi; rm -f "$summary_file"' EXIT
110+
job_count=0
111+
112+
{
113+
echo "### CI Status Gate"
114+
echo
115+
echo "| Job | Result | Decision | Reason |"
116+
echo "| --- | --- | --- | --- |"
117+
} >> "$summary_file"
118+
119+
while IFS=$'\t' read -r job_name result; do
120+
job_count=$((job_count + 1))
121+
122+
case "$result" in
123+
success)
124+
add_summary_row "$job_name" "$result" "pass" "job succeeded"
125+
;;
126+
failure|cancelled)
127+
mark_failure "$job_name finished with result: $result"
128+
add_summary_row "$job_name" "$result" "fail" "job did not complete successfully"
129+
;;
130+
skipped)
131+
if [[ "$job_name" =~ $E2E_JOB_REGEX ]]; then
132+
add_summary_row "$job_name" "$result" "pass" "skipped E2E jobs are allowed"
133+
elif [[ "$EVENT_NAME" == "merge_group" ]]; then
134+
add_summary_row "$job_name" "$result" "pass" "merge queue skip is allowed"
135+
elif [[ "$IS_FORK" == "true" ]]; then
136+
add_summary_row "$job_name" "$result" "pass" "fork-only skip is allowed"
137+
else
138+
mark_failure "$job_name was skipped unexpectedly"
139+
add_summary_row "$job_name" "$result" "fail" "skip was not expected"
140+
fi
141+
;;
142+
*)
143+
mark_failure "$job_name has unknown result: $result"
144+
add_summary_row "$job_name" "$result" "fail" "job result is unknown"
145+
;;
146+
esac
147+
done < <(jq -nr 'env.NEEDS_JSON | fromjson | to_entries[] | [.key, (.value.result // "")] | @tsv')
148+
149+
if [[ "$job_count" -eq 0 ]]; then
150+
echo "::error::NEEDS_JSON does not contain any jobs"
151+
exit 1
152+
fi
153+
154+
if [[ "$failed" == "true" ]]; then
155+
exit 1
156+
fi
157+
158+
echo "All required jobs passed"

0 commit comments

Comments
 (0)