version: 2.1 executors: node-browsers: docker: - image: circleci/node:16-browsers node-browsers-medium-plus: docker: - image: circleci/node:16-browsers resource_class: medium+ environment: NODE_OPTIONS: --max_old_space_size=2048 shellcheck: docker: - image: koalaman/shellcheck-alpine@sha256:dfaf08fab58c158549d3be64fb101c626abc5f16f341b569092577ae207db199 orbs: gh: circleci/github-cli@2.0 codecov: codecov/codecov@3.2.2 workflows: test_and_release: jobs: - create_release_pull_request: requires: - prep-deps filters: branches: only: - /^Version-v(\d+)[.](\d+)[.](\d+)/ - prep-deps - test-deps-audit: requires: - prep-deps - test-deps-depcheck: requires: - prep-deps - test-yarn-dedupe: requires: - prep-deps - validate-lavamoat-config: filters: branches: only: - /^Version-v(\d+)[.](\d+)[.](\d+)|master/ requires: - prep-deps - prep-build: requires: - prep-deps - prep-build-beta: requires: - prep-deps - prep-build-flask: requires: - prep-deps - prep-build-test: requires: - prep-deps - prep-build-test-mv3: requires: - prep-deps - prep-build-test-flask: requires: - prep-deps - prep-build-storybook: requires: - prep-deps - prep-build-ts-migration-dashboard: requires: - prep-deps - test-lint: requires: - prep-deps - test-lint-shellcheck - test-lint-lockfile: requires: - prep-deps - test-lint-changelog: requires: - prep-deps - test-e2e-chrome: requires: - prep-build-test - test-e2e-firefox: requires: - prep-build-test - test-e2e-chrome-snaps: requires: - prep-build-test-flask - test-e2e-firefox-snaps: requires: - prep-build-test-flask - test-e2e-chrome-mv3: requires: - prep-build-test-mv3 - test-unit-mocha: requires: - prep-deps - test-unit-jest-main: requires: - prep-deps - test-unit-jest-development: requires: - prep-deps - upload-and-validate-coverage: requires: - test-unit-jest-main - test-unit-jest-development - test-unit-mocha - test-unit-global: requires: - prep-deps - validate-source-maps: requires: - prep-build - validate-source-maps-beta: requires: - prep-build-beta - validate-source-maps-flask: requires: - prep-build-flask - test-mozilla-lint: requires: - prep-deps - prep-build - test-mozilla-lint-beta: requires: - prep-deps - prep-build-beta - test-mozilla-lint-flask: requires: - prep-deps - prep-build-flask - all-tests-pass: requires: - validate-lavamoat-config - test-lint - test-lint-shellcheck - test-lint-lockfile - test-lint-changelog - test-unit-jest-main - test-unit-jest-development - test-unit-global - test-unit-mocha - upload-and-validate-coverage - validate-source-maps - validate-source-maps-beta - validate-source-maps-flask - test-mozilla-lint - test-mozilla-lint-beta - test-mozilla-lint-flask - test-e2e-chrome - test-e2e-firefox - test-e2e-chrome-snaps - test-e2e-firefox-snaps - benchmark: requires: - prep-build-test - user-actions-benchmark: requires: - prep-build-test - stats-module-load-init: requires: - prep-build-test-mv3 - job-publish-prerelease: requires: - prep-deps - prep-build - prep-build-beta - prep-build-flask - prep-build-storybook - prep-build-ts-migration-dashboard - prep-build-test-mv3 - benchmark - user-actions-benchmark - stats-module-load-init - all-tests-pass - job-publish-release: filters: branches: only: master requires: - prep-deps - prep-build - prep-build-flask - all-tests-pass - job-publish-storybook: filters: branches: only: develop requires: - prep-build-storybook - job-publish-ts-migration-dashboard: filters: branches: only: develop requires: - prep-build-ts-migration-dashboard jobs: create_release_pull_request: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: Bump manifest version command: .circleci/scripts/release-bump-manifest-version.sh - run: name: Update changelog command: yarn update-changelog --rc - run: name: Commit changes command: .circleci/scripts/release-commit-version-bump.sh - run: name: Create GitHub Pull Request for version command: .circleci/scripts/release-create-release-pr.sh prep-deps: executor: node-browsers steps: - checkout - restore_cache: keys: # First try to get the specific cache for the checksum of the yarn.lock file. # This cache key lookup will fail if the lock file is modified and a cache # has not yet been persisted for the new checksum. - dependency-cache-v1-{{ checksum "yarn.lock" }} # To prevent having to do a full install of every node_module when # dependencies change, restore from the last known cache of any # branch/checksum, the install step will remove cached items that are no longer # required and add the new dependencies, and the cache will be persisted. - dependency-cache-v1- - gh/install - run: name: Set IS_DRAFT environment variable command: | PR_NUMBER="${CIRCLE_PULL_REQUEST##*/}" if [ -n "$PR_NUMBER" ] then echo "IS_DRAFT=$(gh pr view --json isDraft --jq '.isDraft' "$PR_NUMBER")" >> "$BASH_ENV" source "$BASH_ENV" else echo "Not a PR; skipping" fi - run: name: Setup registry config for using package previews on draft PRs command: | if [[ $IS_DRAFT == 'true' ]] then printf '%s\n\n%s' '@metamask:registry=https://npm.pkg.github.com' "//npm.pkg.github.com/:_authToken=${GITHUB_PACKAGE_READ_TOKEN}" > .npmrc else echo "Not draft; skipping GitHub registry setup" fi - run: name: Install deps command: | .circleci/scripts/deps-install.sh - save_cache: key: dependency-cache-v1-{{ checksum "yarn.lock" }} paths: - .yarn/cache - persist_to_workspace: root: . paths: - node_modules - build-artifacts validate-lavamoat-config: executor: node-browsers-medium-plus steps: - checkout - attach_workspace: at: . - run: name: Validate allow-scripts config command: | .circleci/scripts/validate-allow-scripts.sh - run: name: Validate LavaMoat policy command: | .circleci/scripts/validate-lavamoat-policy.sh prep-build: executor: node-browsers-medium-plus steps: - checkout - attach_workspace: at: . - when: condition: not: matches: pattern: /^master$/ value: << pipeline.git.branch >> steps: - run: name: build:dist command: yarn build dist - when: condition: matches: pattern: /^master$/ value: << pipeline.git.branch >> steps: - run: name: build:prod command: yarn build prod - run: name: build:debug command: find dist/ -type f -exec md5sum {} \; | sort -k 2 - persist_to_workspace: root: . paths: - dist - builds prep-build-beta: executor: node-browsers-medium-plus steps: - checkout - attach_workspace: at: . - when: condition: not: matches: pattern: /^master$/ value: << pipeline.git.branch >> steps: - run: name: build:dist command: yarn build --build-type beta dist - when: condition: matches: pattern: /^master$/ value: << pipeline.git.branch >> steps: - run: name: build:prod command: yarn build --build-type beta prod - run: name: build:debug command: find dist/ -type f -exec md5sum {} \; | sort -k 2 - run: name: Move beta build to 'dist-beta' to avoid conflict with production build command: mv ./dist ./dist-beta - run: name: Move beta zips to 'builds-beta' to avoid conflict with production build command: mv ./builds ./builds-beta - persist_to_workspace: root: . paths: - dist-beta - builds-beta prep-build-flask: executor: node-browsers-medium-plus steps: - checkout - attach_workspace: at: . - when: condition: not: matches: pattern: /^master$/ value: << pipeline.git.branch >> steps: - run: name: build:dist command: yarn build --build-type flask dist - when: condition: matches: pattern: /^master$/ value: << pipeline.git.branch >> steps: - run: name: build:prod command: yarn build --build-type flask prod - run: name: build:debug command: find dist/ -type f -exec md5sum {} \; | sort -k 2 - run: name: Move flask build to 'dist-flask' to avoid conflict with production build command: mv ./dist ./dist-flask - run: name: Move flask zips to 'builds-flask' to avoid conflict with production build command: mv ./builds ./builds-flask - persist_to_workspace: root: . paths: - dist-flask - builds-flask prep-build-test-flask: executor: node-browsers-medium-plus steps: - checkout - attach_workspace: at: . - run: name: Build extension for testing command: yarn build:test:flask - run: name: Move test build to 'dist-test' to avoid conflict with production build command: mv ./dist ./dist-test-flask - run: name: Move test zips to 'builds-test' to avoid conflict with production build command: mv ./builds ./builds-test-flask - persist_to_workspace: root: . paths: - dist-test-flask - builds-test-flask prep-build-test-mv3: executor: node-browsers-medium-plus steps: - checkout - attach_workspace: at: . - run: name: Build extension in mv3 for testing command: yarn build:test:mv3 - run: name: Move test build to 'dist-test' to avoid conflict with production build command: mv ./dist ./dist-test-mv3 - run: name: Move test zips to 'builds-test' to avoid conflict with production build command: mv ./builds ./builds-test-mv3 - persist_to_workspace: root: . paths: - dist-test-mv3 - builds-test-mv3 prep-build-test: executor: node-browsers-medium-plus steps: - checkout - attach_workspace: at: . - run: name: Build extension for testing command: yarn build:test - run: name: Move test build to 'dist-test' to avoid conflict with production build command: mv ./dist ./dist-test - run: name: Move test zips to 'builds-test' to avoid conflict with production build command: mv ./builds ./builds-test - persist_to_workspace: root: . paths: - dist-test - builds-test prep-build-storybook: executor: node-browsers-medium-plus steps: - checkout - attach_workspace: at: . - run: name: Build Storybook command: yarn storybook:build - persist_to_workspace: root: . paths: - storybook-build prep-build-ts-migration-dashboard: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: Build TypeScript migration dashboard command: yarn ts-migration:dashboard:build - persist_to_workspace: root: . paths: - development/ts-migration-dashboard/build test-yarn-dedupe: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: Detect yarn lock deduplications command: yarn dedupe --check test-lint: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: Lint command: yarn lint - run: name: Verify locales command: yarn verify-locales --quiet test-lint-shellcheck: executor: shellcheck steps: - checkout - run: apk add --no-cache bash jq yarn - run: name: ShellCheck Lint command: ./development/shellcheck.sh test-lint-lockfile: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: lockfile-lint command: yarn lint:lockfile test-lint-changelog: executor: node-browsers steps: - checkout - attach_workspace: at: . - when: condition: not: matches: pattern: /^Version-v(\d+)[.](\d+)[.](\d+)$/ value: << pipeline.git.branch >> steps: - run: name: Validate changelog command: yarn lint:changelog - when: condition: matches: pattern: /^Version-v(\d+)[.](\d+)[.](\d+)$/ value: << pipeline.git.branch >> steps: - run: name: Validate release candidate changelog command: yarn lint:changelog:rc test-deps-audit: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: yarn audit command: .circleci/scripts/yarn-audit.sh test-deps-depcheck: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: depcheck command: yarn depcheck test-e2e-chrome: executor: node-browsers parallelism: 8 steps: - checkout - run: name: Re-Install Chrome command: ./.circleci/scripts/chrome-install.sh - attach_workspace: at: . - run: name: Move test build to dist command: mv ./dist-test ./dist - run: name: Move test zips to builds command: mv ./builds-test ./builds - run: name: test:e2e:chrome command: | if .circleci/scripts/test-run-e2e.sh then yarn test:e2e:chrome --retries 2 fi no_output_timeout: 20m - store_artifacts: path: test-artifacts destination: test-artifacts test-e2e-chrome-mv3: executor: node-browsers parallelism: 8 steps: - checkout - run: name: Re-Install Chrome command: ./.circleci/scripts/chrome-install.sh - attach_workspace: at: . - run: name: Move test build to dist command: mv ./dist-test-mv3 ./dist - run: name: Move test zips to builds command: mv ./builds-test-mv3 ./builds - run: name: test:e2e:chrome command: | if .circleci/scripts/test-run-e2e.sh then yarn test:e2e:chrome --retries 2 --mv3 || echo "Temporarily suppressing MV3 e2e test failures" fi no_output_timeout: 20m - store_artifacts: path: test-artifacts destination: test-artifacts test-e2e-firefox-snaps: executor: node-browsers parallelism: 2 steps: - checkout - run: name: Install Firefox command: ./.circleci/scripts/firefox-install.sh - attach_workspace: at: . - run: name: Move test build to dist command: mv ./dist-test-flask ./dist - run: name: Move test zips to builds command: mv ./builds-test-flask ./builds - run: name: test:e2e:firefox:snaps command: | if .circleci/scripts/test-run-e2e.sh then yarn test:e2e:firefox:snaps --retries 2 fi no_output_timeout: 20m - store_artifacts: path: test-artifacts destination: test-artifacts test-e2e-chrome-snaps: executor: node-browsers parallelism: 2 steps: - checkout - run: name: Re-Install Chrome command: ./.circleci/scripts/chrome-install.sh - attach_workspace: at: . - run: name: Move test build to dist command: mv ./dist-test-flask ./dist - run: name: Move test zips to builds command: mv ./builds-test-flask ./builds - run: name: test:e2e:chrome:snaps command: | if .circleci/scripts/test-run-e2e.sh then yarn test:e2e:chrome:snaps --retries 2 fi no_output_timeout: 20m - store_artifacts: path: test-artifacts destination: test-artifacts test-e2e-firefox: executor: node-browsers-medium-plus parallelism: 8 steps: - checkout - run: name: Install Firefox command: ./.circleci/scripts/firefox-install.sh - attach_workspace: at: . - run: name: Move test build to dist command: mv ./dist-test ./dist - run: name: Move test zips to builds command: mv ./builds-test ./builds - run: name: test:e2e:firefox command: | if .circleci/scripts/test-run-e2e.sh then yarn test:e2e:firefox --retries 2 fi no_output_timeout: 20m - store_artifacts: path: test-artifacts destination: test-artifacts benchmark: executor: node-browsers-medium-plus steps: - checkout - run: name: Re-Install Chrome command: ./.circleci/scripts/chrome-install.sh - attach_workspace: at: . - run: name: Move test build to dist command: mv ./dist-test ./dist - run: name: Move test zips to builds command: mv ./builds-test ./builds - run: name: Run page load benchmark command: yarn benchmark:chrome --out test-artifacts/chrome/benchmark/pageload.json --retries 2 - store_artifacts: path: test-artifacts destination: test-artifacts - persist_to_workspace: root: . paths: - test-artifacts user-actions-benchmark: executor: node-browsers-medium-plus steps: - checkout - run: name: Re-Install Chrome command: ./.circleci/scripts/chrome-install.sh - attach_workspace: at: . - run: name: Move test build to dist command: mv ./dist-test ./dist - run: name: Move test zips to builds command: mv ./builds-test ./builds - run: name: Run page load benchmark command: yarn user-actions-benchmark:chrome --out test-artifacts/chrome/benchmark/user_actions.json --retries 2 - store_artifacts: path: test-artifacts destination: test-artifacts - persist_to_workspace: root: . paths: - test-artifacts stats-module-load-init: executor: node-browsers-medium-plus steps: - checkout - run: name: Re-Install Chrome command: ./.circleci/scripts/chrome-install.sh - attach_workspace: at: . - run: name: Move test build to dist command: mv ./dist-test-mv3 ./dist - run: name: Move test zips to builds command: mv ./builds-test-mv3 ./builds - run: name: Run page load benchmark command: | mkdir -p test-artifacts/chrome/mv3 cp -R development/charts/flamegraph test-artifacts/chrome/mv3/initialisation cp -R development/charts/flamegraph/chart test-artifacts/chrome/mv3/initialisation/background cp -R development/charts/flamegraph/chart test-artifacts/chrome/mv3/initialisation/ui cp -R development/charts/table test-artifacts/chrome/mv3/load_time - run: name: Run page load benchmark command: yarn mv3:stats:chrome --out test-artifacts/chrome/mv3 - run: name: Install jq command: sudo apt install jq -y - run: name: Record bundle size at commit command: ./.circleci/scripts/bundle-stats-commit.sh - store_artifacts: path: test-artifacts destination: test-artifacts - persist_to_workspace: root: . paths: - test-artifacts job-publish-prerelease: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: build:source-map-explorer command: ./development/source-map-explorer.sh - store_artifacts: path: dist/sourcemaps destination: builds/sourcemaps - store_artifacts: path: dist-beta/sourcemaps destination: builds-beta/sourcemaps - store_artifacts: path: dist-flask/sourcemaps destination: builds-flask/sourcemaps - store_artifacts: path: builds destination: builds - store_artifacts: path: builds-beta destination: builds-beta - store_artifacts: path: builds-flask destination: builds-flask - store_artifacts: path: coverage destination: coverage - store_artifacts: path: test-artifacts destination: test-artifacts # important: generate lavamoat viz AFTER uploading builds as artifacts # Temporarily disabled until we can update to a version of `sesify` with # this fix included: https://github.com/LavaMoat/LavaMoat/pull/121 - run: name: build:lavamoat-viz command: ./.circleci/scripts/create-lavamoat-viz.sh - store_artifacts: path: build-artifacts destination: build-artifacts - store_artifacts: path: storybook-build destination: storybook - store_artifacts: path: development/ts-migration-dashboard/build destination: ts-migration-dashboard - run: name: Set branch parent commit env var command: | echo "export PARENT_COMMIT=$(git merge-base origin/HEAD HEAD)" >> $BASH_ENV source $BASH_ENV - run: name: build:announce command: ./development/metamaskbot-build-announce.js job-publish-release: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: Publish main release to Sentry command: yarn sentry:publish - run: name: Publish Flask release to Sentry command: yarn sentry:publish --build-type flask - run: name: Create GitHub release command: | .circleci/scripts/release-create-gh-release.sh job-publish-storybook: executor: node-browsers steps: - add_ssh_keys: fingerprints: - '3d:49:29:f4:b2:e8:ea:af:d1:32:eb:2a:fc:15:85:d8' - checkout - attach_workspace: at: . - run: name: storybook:deploy command: | git remote add storybook git@github.com:MetaMask/metamask-storybook.git yarn storybook:deploy job-publish-ts-migration-dashboard: executor: node-browsers steps: - add_ssh_keys: fingerprints: - '8b:21:e3:20:7c:c9:db:82:74:2d:86:d6:11:a7:2f:49' - checkout - attach_workspace: at: . - run: name: ts-migration-dashboard:deploy command: | git remote add ts-migration-dashboard git@github.com:MetaMask/metamask-extension-ts-migration-dashboard.git git config user.name "MetaMask Bot" git config user.email metamaskbot@users.noreply.github.com yarn ts-migration:dashboard:deploy test-unit-mocha: executor: node-browsers-medium-plus steps: - checkout - attach_workspace: at: . - run: name: test:coverage:mocha command: yarn test:coverage:mocha - persist_to_workspace: root: . paths: - .nyc_output - coverage test-unit-jest-development: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: jest development unit tests command: yarn test:coverage:jest:dev - persist_to_workspace: root: . paths: - coverage - store_test_results: path: test/test-results/junit.xml test-unit-jest-main: executor: node-browsers-medium-plus parallelism: 12 steps: - checkout - attach_workspace: at: . - run: name: test:coverage:jest command: yarn test:coverage:jest - persist_to_workspace: root: . paths: - coverage - store_test_results: path: test/test-results/junit.xml upload-and-validate-coverage: executor: node-browsers steps: - checkout - attach_workspace: at: . - codecov/upload - run: name: test:coverage:validate command: yarn test:coverage:validate - persist_to_workspace: root: . paths: - coverage test-unit-global: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: test:unit:global command: yarn test:unit:global validate-source-maps: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: Validate source maps command: yarn validate-source-maps validate-source-maps-beta: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: Move beta build to dist command: mv ./dist-beta ./dist - run: name: Move beta zips to builds command: mv ./builds-beta ./builds - run: name: Validate source maps command: yarn validate-source-maps validate-source-maps-flask: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: Move flask build to dist command: mv ./dist-flask ./dist - run: name: Move flask zips to builds command: mv ./builds-flask ./builds - run: name: Validate source maps command: yarn validate-source-maps test-mozilla-lint: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: test:mozilla-lint command: NODE_OPTIONS=--max_old_space_size=3072 yarn mozilla-lint test-mozilla-lint-beta: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: Move beta build to dist command: mv ./dist-beta ./dist - run: name: Move beta zips to builds command: mv ./builds-beta ./builds - run: name: test:mozilla-lint command: NODE_OPTIONS=--max_old_space_size=3072 yarn mozilla-lint test-mozilla-lint-flask: executor: node-browsers steps: - checkout - attach_workspace: at: . - run: name: Move flask build to dist command: mv ./dist-flask ./dist - run: name: Move flask zips to builds command: mv ./builds-flask ./builds - run: name: test:mozilla-lint command: NODE_OPTIONS=--max_old_space_size=3072 yarn mozilla-lint all-tests-pass: executor: node-browsers steps: - run: name: All Tests Passed command: echo 'weew - everything passed!'