Skip to content

Commit

Permalink
Merge branch 'develop' into basic-func-search
Browse files Browse the repository at this point in the history
  • Loading branch information
darkwing authored Sep 5, 2024
2 parents 9246c5a + 2455440 commit efe5da8
Show file tree
Hide file tree
Showing 2,058 changed files with 125,404 additions and 48,855 deletions.
615 changes: 280 additions & 335 deletions .circleci/config.yml

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions .circleci/scripts/enable-vnc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash

# This script is based on the documentation from CircleCI, which does not work as written
# https://circleci.com/docs/browser-testing/#interacting-with-the-browser-over-vnc

set -e
set -u
set -o pipefail
set -x

cd "${HOME}/project"

# Install a VNC server
readonly LOCK_FILE="installed.lock"
if [ ! -f "${LOCK_FILE}" ]; then
sudo apt update
sudo apt install -y x11vnc

touch "${LOCK_FILE}"
fi

# Start VNC server
if ! pgrep x11vnc > /dev/null; then
x11vnc -display "$DISPLAY" -bg -forever -nopw -quiet -listen localhost -xkb -rfbport 5901 -passwd password
fi
136 changes: 136 additions & 0 deletions .circleci/scripts/git-diff-develop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { hasProperty } from '@metamask/utils';
import { exec as execCallback } from 'child_process';
import fs from 'fs';
import path from 'path';
import { promisify } from 'util';

const exec = promisify(execCallback);

const MAIN_BRANCH = 'develop';

/**
* Get the target branch for the given pull request.
*
* @returns The name of the branch targeted by the PR.
*/
async function getBaseRef(): Promise<string | null> {
if (!process.env.CIRCLE_PULL_REQUEST) {
return null;
}

// We're referencing the CIRCLE_PULL_REQUEST environment variable within the script rather than
// passing it in because this makes it easier to use Bash parameter expansion to extract the
// PR number from the URL.
const result = await exec(`gh pr view --json baseRefName "\${CIRCLE_PULL_REQUEST##*/}" --jq '.baseRefName'`);
const baseRef = result.stdout.trim();
return baseRef;
}

/**
* Fetches the git repository with a specified depth.
*
* @param depth - The depth to use for the fetch command.
* @returns True if the fetch is successful, otherwise false.
*/
async function fetchWithDepth(depth: number): Promise<boolean> {
try {
await exec(`git fetch --depth ${depth} origin develop`);
await exec(`git fetch --depth ${depth} origin ${process.env.CIRCLE_BRANCH}`);
return true;
} catch (error: unknown) {
console.error(`Failed to fetch with depth ${depth}:`, error);
return false;
}
}

/**
* Attempts to fetch the necessary commits until the merge base is found.
* It tries different fetch depths and performs a full fetch if needed.
*
* @throws If an unexpected error occurs during the execution of git commands.
*/
async function fetchUntilMergeBaseFound() {
const depths = [1, 10, 100];
for (const depth of depths) {
console.log(`Attempting git diff with depth ${depth}...`);
await fetchWithDepth(depth);

try {
await exec(`git merge-base origin/HEAD HEAD`);
return;
} catch (error: unknown) {
if (
error instanceof Error &&
hasProperty(error, 'code') &&
error.code === 1
) {
console.error(`Error 'no merge base' encountered with depth ${depth}. Incrementing depth...`);
} else {
throw error;
}
}
}
await exec(`git fetch --unshallow origin develop`);
}

/**
* Performs a git diff command to get the list of files changed between the current branch and the origin.
* It first ensures that the necessary commits are fetched until the merge base is found.
*
* @returns The output of the git diff command, listing the changed files.
* @throws If unable to get the diff after fetching the merge base or if an unexpected error occurs.
*/
async function gitDiff(): Promise<string> {
await fetchUntilMergeBaseFound();
const { stdout: diffResult } = await exec(`git diff --name-only origin/HEAD...${process.env.CIRCLE_BRANCH}`);
if (!diffResult) {
throw new Error('Unable to get diff after full checkout.');
}
return diffResult;
}

/**
* Stores the output of git diff to a file.
*
* @returns Returns a promise that resolves when the git diff output is successfully stored.
*/
async function storeGitDiffOutput() {
try {
// Create the directory
// This is done first because our CirleCI config requires that this directory is present,
// even if we want to skip this step.
const outputDir = 'changed-files';
fs.mkdirSync(outputDir, { recursive: true });

console.log(`Determining whether this run is for a PR targetting ${MAIN_BRANCH}`)
if (!process.env.CIRCLE_PULL_REQUEST) {
console.log("Not a PR, skipping git diff");
return;
}

const baseRef = await getBaseRef();
if (baseRef === null) {
console.log("Not a PR, skipping git diff");
return;
} else if (baseRef !== MAIN_BRANCH) {
console.log(`This is for a PR targeting '${baseRef}', skipping git diff`);
return;
}

console.log("Attempting to get git diff...");
const diffOutput = await gitDiff();
console.log(diffOutput);

// Store the output of git diff
const outputPath = path.resolve(outputDir, 'changed-files.txt');
fs.writeFileSync(outputPath, diffOutput.trim());

console.log(`Git diff results saved to ${outputPath}`);
process.exit(0);
} catch (error: any) {
console.error('An error occurred:', error.message);
process.exit(1);
}
}

storeGitDiffOutput();
2 changes: 1 addition & 1 deletion .circleci/scripts/release-create-gh-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ then
install_github_cli

printf '%s\n' 'Creating GitHub Release'
release_body="$(awk -v version="${tag##v}" -f .circleci/scripts/show-changelog.awk CHANGELOG.md)"
release_body="$(awk -v version="[${tag##v}]" -f .circleci/scripts/show-changelog.awk CHANGELOG.md)"
hub release create \
--attach builds/metamask-chrome-*.zip \
--attach builds-mv2/metamask-firefox-*.zip \
Expand Down
21 changes: 21 additions & 0 deletions .circleci/scripts/test-run-e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,25 @@ then
exit 1
fi

# Skip running e2e tests if we're doing "Rerun job with SSH" and we're not on the first node
if netstat -tnlp | grep -q 'circleci-agent' && [ "$CIRCLE_NODE_INDEX" -ne 0 ]
then
printf '"Rerun job with SSH" and not on the first node, shutting down\n'
circleci-agent step halt
exit 1
fi

# Run the actual test command from the parameters
timeout 20m "$@" --retries 1

# Error code 124 means the command timed out
if [ $? -eq 124 ]
then
# Once deleted, if someone tries to "Rerun failed tests" the result will be
# "Error: can not rerun failed tests: no failed tests could be found"
echo 'Timeout error, deleting the test results'
rm -rf test/test-results/e2e
exit 124
fi

exit 0
31 changes: 31 additions & 0 deletions .circleci/scripts/validate-locales-only.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const { readChangedFiles } = require('../../test/e2e/changedFilesUtil.js');

/**
* Verifies that all changed files are in the /_locales/ directory.
* Fails the build if any changed files are outside of the /_locales/ directory.
* Fails if no changed files are detected.
*/
async function validateLocalesOnlyChangedFiles() {
const changedFiles = await readChangedFiles();
if (!changedFiles || changedFiles.length === 0) {
console.error('Failure: No changed files detected.');
process.exit(1);
}
const invalidFiles = changedFiles.filter(
(file) => !file.startsWith('app/_locales/'),
);
if (invalidFiles.length > 0) {
console.error(
'Failure: Changed files must be in the /_locales/ directory.\n Changed Files:',
changedFiles,
'\n Invalid Files:',
invalidFiles,
);
process.exit(1);
} else {
console.log('Passed validation');
process.exit(0);
}
}

validateLocalesOnlyChangedFiles();
19 changes: 17 additions & 2 deletions .depcheckrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ ignores:
- 'wait-on'
- 'tsx' # used in .devcontainer
- 'prettier-eslint' # used by the Prettier ESLint VSCode extension
# development tool
- 'nyc'
# storybook
- '@storybook/cli'
- '@storybook/core'
Expand All @@ -60,6 +58,23 @@ ignores:
- 'resolve-url-loader'
# jest environments
- 'jest-environment-jsdom'
# webpack
- '@pmmmwh/react-refresh-webpack-plugin' # dev tool
- 'webpack-dev-server' # dev tool
- 'html-bundler-webpack-plugin' # build tool
- 'postcss-loader' # build tool
- '@swc/helpers' # build tool
- browserslist # build tool
- 'buffer' # polyfill
- 'crypto-browserify' # polyfill
- 'process' # polyfill
- 'stream-http' # polyfill
- 'rimraf' # misc: install helper
- 'json-schema-to-ts' # misc: typescript helper
- 'https-browserify' # polyfill
- 'path-browserify' # polyfill
- 'nyc' # coverage
- 'core-js-pure' # polyfills
# babel
- '@babel/plugin-transform-logical-assignment-operators'
# trezor
Expand Down
5 changes: 2 additions & 3 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
],
"settings": {
"editor.formatOnSave": true,
"git.autofetch": true,
"git.ignoreRebaseWarning": true,
"git.rebaseWhenSync": true,
"gitlens.showWelcomeOnInstall": false
Expand Down Expand Up @@ -48,13 +47,13 @@
}
},

"postAttachCommand": "/usr/local/share/desktop-init.sh && git pull --rebase; yarn download-builds",
"postAttachCommand": "/usr/local/share/desktop-init.sh && git pull; yarn download-builds",

// This is a working Infura key, but it's on the Free Plan and has very limited requests per second
// If you want to use your own INFURA_PROJECT_ID, follow the instructions in README.md
"postCreateCommand": "if [ -z \"$INFURA_PROJECT_ID\" ]; then echo 'INFURA_PROJECT_ID=3d110a0fce9e49b08d2ee584e19a05ba' > .metamaskrc; fi",

"runArgs": ["--shm-size=1g"],

"updateContentCommand": "sudo .devcontainer/install.sh && yarn --immutable && yarn tsx .devcontainer/setup-browsers.ts && echo 'export DISPLAY=:1' >> ~/.bashrc"
"updateContentCommand": "sudo .devcontainer/install.sh && corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 yarn --immutable && yarn tsx .devcontainer/setup-browsers.ts && echo 'export DISPLAY=:1' >> ~/.bashrc"
}
6 changes: 5 additions & 1 deletion .devcontainer/download-builds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ async function getBuilds(branch: string, jobNames: string[]) {

const artifacts = await response.json();

if (!artifacts || artifacts.length === 0) {
if (
!artifacts ||
artifacts.length === 0 ||
artifacts.message === 'Not Found'
) {
return [];
}

Expand Down
38 changes: 11 additions & 27 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ module.exports = {
'development/**/*.js',
'test/e2e/**/*.js',
'test/helpers/*.js',
'test/lib/wait-until-called.js',
'test/run-unit-tests.js',
'test/merge-coverage.js',
],
extends: [
path.resolve(__dirname, '.eslintrc.base.js'),
Expand Down Expand Up @@ -94,8 +92,6 @@ module.exports = {
'test/stub/**/*.js',
'test/unit-global/**/*.js',
],
// TODO: Convert these files to modern JS
excludedFiles: ['test/lib/wait-until-called.js'],
extends: [
path.resolve(__dirname, '.eslintrc.base.js'),
path.resolve(__dirname, '.eslintrc.node.js'),
Expand Down Expand Up @@ -261,26 +257,7 @@ module.exports = {
* Mocha library.
*/
{
files: [
'**/*.test.js',
'test/lib/wait-until-called.js',
'test/e2e/**/*.spec.js',
],
excludedFiles: [
'app/scripts/controllers/app-state.test.js',
'app/scripts/controllers/mmi-controller.test.js',
'app/scripts/controllers/permissions/**/*.test.js',
'app/scripts/controllers/preferences.test.js',
'app/scripts/lib/**/*.test.js',
'app/scripts/metamask-controller.test.js',
'app/scripts/migrations/*.test.js',
'app/scripts/platforms/*.test.js',
'development/**/*.test.js',
'shared/**/*.test.js',
'ui/**/*.test.js',
'ui/__mocks__/*.js',
'test/e2e/helpers.test.js',
],
files: ['test/e2e/**/*.spec.js'],
extends: ['@metamask/eslint-config-mocha'],
rules: {
// In Mocha tests, it is common to use `this` to store values or do
Expand All @@ -293,13 +270,21 @@ module.exports = {
* Jest tests
*
* These are files that make use of globals and syntax introduced by the
* Jest library. The files in this section should match the Mocha excludedFiles section.
* Jest library.
* TODO: This list of files is incomplete, and should be replaced with globs that match the
* Jest config.
*/
{
files: [
'**/__snapshots__/*.snap',
'app/scripts/controllers/app-state.test.js',
'app/scripts/controllers/mmi-controller.test.ts',
'app/scripts/metamask-controller.actions.test.js',
'app/scripts/detect-multiple-instances.test.js',
'app/scripts/controllers/bridge.test.ts',
'app/scripts/controllers/swaps/**/*.test.js',
'app/scripts/controllers/swaps/**/*.test.ts',
'app/scripts/controllers/metametrics.test.js',
'app/scripts/controllers/permissions/**/*.test.js',
'app/scripts/controllers/preferences.test.js',
'app/scripts/lib/**/*.test.js',
Expand All @@ -314,6 +299,7 @@ module.exports = {
'test/jest/*.js',
'test/lib/timer-helpers.js',
'test/e2e/helpers.test.js',
'test/unit-global/*.test.js',
'ui/**/*.test.js',
'ui/__mocks__/*.js',
'shared/lib/error-utils.test.js',
Expand Down Expand Up @@ -382,8 +368,6 @@ module.exports = {
'development/**/*.js',
'test/e2e/benchmark.js',
'test/helpers/setup-helper.js',
'test/run-unit-tests.js',
'test/merge-coverage.js',
],
rules: {
'node/no-process-exit': 'off',
Expand Down
Loading

0 comments on commit efe5da8

Please sign in to comment.