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-desktop:
          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-nft:
          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-e2e-chrome-nft:
          requires:
            - prep-build-test-nft
      - test-e2e-firefox-nft:
          requires:
            - prep-build-test-nft
      - 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
      - test-storybook:
          requires:
            - prep-deps
            - prep-build-storybook
      - validate-source-maps:
          requires:
            - prep-build
      - validate-source-maps-beta:
          requires:
            - prep-build-beta
      - validate-source-maps-desktop:
          requires:
            - prep-build-desktop
      - 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-desktop:
          requires:
            - prep-deps
            - prep-build-desktop
      - 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-desktop
            - validate-source-maps-flask
            - test-mozilla-lint
            - test-mozilla-lint-beta
            - test-mozilla-lint-desktop
            - test-mozilla-lint-flask
            - test-e2e-chrome
            - test-e2e-firefox
            - test-e2e-chrome-snaps
            - test-e2e-firefox-snaps
            - test-storybook
      - 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-desktop
            - prep-build-flask
            - prep-build-storybook
            - prep-build-ts-migration-dashboard
            - prep-build-test-mv3
            - prep-build-test-nft
            - 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-desktop
            - 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-desktop:
    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 desktop dist
      - when:
          condition:
            matches:
              pattern: /^master$/
              value: << pipeline.git.branch >>
          steps:
            - run:
                name: build:prod
                command: yarn build --build-type desktop prod
      - run:
          name: build:debug
          command: find dist/ -type f -exec md5sum {} \; | sort -k 2
      - run:
          name: Move desktop build to 'dist-desktop' to avoid conflict with production build
          command: mv ./dist ./dist-desktop
      - run:
          name: Move desktop zips to 'builds-desktop' to avoid conflict with production build
          command: mv ./builds ./builds-desktop
      - persist_to_workspace:
          root: .
          paths:
            - dist-desktop
            - builds-desktop

  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-nft:
    executor: node-browsers-medium-plus
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: Build extension with nft's enabled for testing
          command: yarn build:test:nft
      - run:
          name: Move test build to 'dist-test-nft' to avoid conflict with production build
          command: mv ./dist ./dist-test-nft
      - run:
          name: Move test zips to 'builds-test-nft' to avoid conflict with production build
          command: mv ./builds ./builds-test-nft
      - persist_to_workspace:
          root: .
          paths:
            - dist-test-nft
            - builds-test-nft

  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/final

  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-storybook:
    executor: node-browsers-medium-plus
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: Install Playwright browsers
          command: yarn exec playwright install
      - run:
          name: Test Storybook
          command: yarn test-storybook:ci

  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
      - run:
          name: Merge JUnit report
          command: |
            if [ "$(ls -A test/test-results/e2e)" ]; then
              yarn test:e2e:report
            fi
      - store_artifacts:
          path: test-artifacts
          destination: test-artifacts
      - store_test_results:
          path: test/test-results/e2e.xml

  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-chrome-nft:
    executor: node-browsers
    parallelism: 1
    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-nft ./dist
      - run:
          name: Move test zips to builds
          command: mv ./builds-test-nft ./builds
      - run:
          name: test:e2e:chrome
          command: |
            if .circleci/scripts/test-run-e2e.sh
            then
              yarn test:e2e:chrome:nft --retries 2
            fi
          no_output_timeout: 20m
      - run:
          name: Merge JUnit report
          command: |
            if [ "$(ls -A test/test-results/e2e)" ]; then
              yarn test:e2e:report
            fi
      - store_artifacts:
          path: test-artifacts
          destination: test-artifacts
      - store_test_results:
          path: test/test-results/e2e.xml

  test-e2e-firefox-nft:
    executor: node-browsers
    parallelism: 1
    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-nft ./dist
      - run:
          name: Move test zips to builds
          command: mv ./builds-test-nft ./builds
      - run:
          name: test:e2e:firefox
          command: |
            if .circleci/scripts/test-run-e2e.sh
            then
              yarn test:e2e:firefox:nft --retries 2
            fi
          no_output_timeout: 20m
      - run:
          name: Merge JUnit report
          command: |
            if [ "$(ls -A test/test-results/e2e)" ]; then
              yarn test:e2e:report
            fi
      - store_artifacts:
          path: test-artifacts
          destination: test-artifacts
      - store_test_results:
          path: test/test-results/e2e.xml
          
  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
      - run:
          name: Merge JUnit report
          command: |
            if [ "$(ls -A test/test-results/e2e)" ]; then
              yarn test:e2e:report
            fi
      - store_artifacts:
          path: test-artifacts
          destination: test-artifacts
      - store_test_results:
          path: test/test-results/e2e.xml

  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
      - run:
          name: Merge JUnit report
          command: |
            if [ "$(ls -A test/test-results/e2e)" ]; then
              yarn test:e2e:report
            fi
      - store_artifacts:
          path: test-artifacts
          destination: test-artifacts
      - store_test_results:
          path: test/test-results/e2e.xml

  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
      - run:
          name: Merge JUnit report
          command: |
            if [ "$(ls -A test/test-results/e2e)" ]; then
              yarn test:e2e:report
            fi
      - store_artifacts:
          path: test-artifacts
          destination: test-artifacts
      - store_test_results:
          path: test/test-results/e2e.xml

  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/final
          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-desktop:
    executor: node-browsers
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: Move desktop build to dist
          command: mv ./dist-desktop ./dist
      - run:
          name: Move desktop zips to builds
          command: mv ./builds-desktop ./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-desktop:
    executor: node-browsers
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: Move desktop build to dist
          command: mv ./dist-desktop ./dist
      - run:
          name: Move desktop zips to builds
          command: mv ./builds-desktop ./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!'