defaults: &defaults
  working_directory: /tmp/material-ui
  docker:
    - image: circleci/node:9.10
# CircleCI has disabled the cache across forks for security reasons.
# Following their official statement, it was a quick solution, they
# are working on providing this feature back with appropriate security measures.
# restore_repo: &restore_repo
#   restore_cache:
#     key: v1-repo-{{ .Branch }}-{{ .Revision }}
install_js: &install_js
  run:
    name: Install js dependencies
    command: |
      yarn config set yarn-offline-mirror ~/.cache/npm-packages-offline-cache/v1
      yarn
restore_yarn_cache: &restore_yarn_cache
  restore_cache:
    key: v1-yarn-sha-{{ checksum "yarn.lock" }}
restore_yarn_offline_mirror: &restore_yarn_offline_mirror
  restore_cache:
    key: v1-npm-packages-offline-cache
version: 2
jobs:
  checkout:
    <<: *defaults
    steps:
      - checkout
      - *restore_yarn_offline_mirror
      - *restore_yarn_cache
      - run:
          name: Check versions and env
          command: |
            yarn --version
            node --version
            docker --version
            docker-compose --version
            env
            yarn cache dir
      - *install_js
      - run:
          name: Should not have any git not staged
          command: git diff --exit-code
      - save_cache:
          key: v1-yarn-sha-{{ checksum "yarn.lock" }}
          paths:
            - ~/.cache/yarn/v1
      - save_cache:
          key: v1-npm-packages-offline-cache
          paths:
            - ~/.cache/npm-packages-offline-cache/v1
  test_unit:
    <<: *defaults
    steps:
      - checkout
      - *restore_yarn_offline_mirror
      - *restore_yarn_cache
      - *install_js
      - run:
          name: Export changed files
          command: |
            # changed files on this branch
            # `git diff --name-only master` but since the checkout used reset --hard
            # we need to parse the revs for the actual master
            echo 'export CHANGED_FILES=$(git diff --name-only $(git rev-parse origin/master)...)' >> $BASH_ENV
      - run:
          name: Check if yarn prettier was run
          command: |
            # if we use an empty string as a pattern grep will match everything
            if [ -z "$CHANGED_FILES" ]; then
              echo "no changes"
            else
              # Files that should have been formatted while working on this branch
              # CircleCI does not support interpolation when setting environment variables
              echo 'export FORMATTED_FILES=$(yarn --silent prettier:files | grep "$CHANGED_FILES")' >> $BASH_ENV
              source $BASH_ENV

              if [ -z "$FORMATTED_FILES" ]; then
                echo "no files for prettier were changed"
              else
                yarn prettier:ci $FORMATTED_FILES
              fi
            fi
      - run:
          name: Lint
          command: yarn lint
      - run:
          name: Lint JSON
          command: yarn jsonlint
      - run:
          name: Tests TypeScript definitions
          command: yarn typescript
      - run:
          name: Tests fake browser
          command: yarn test:coverage
      - run:
          name: Check coverage generated
          command: |
            if ! [[ -s coverage/lcov.info ]]
            then
              exit 1
            fi
      - run:
          name: Coverage
          command: bash <(curl -s https://codecov.io/bash) -Z
  test_material-ui-x:
    <<: *defaults
    steps:
      - checkout
      - *restore_yarn_offline_mirror
      - *restore_yarn_cache
      - *install_js
      - run:
          name: material-ui-icons
          command: |
            # latest commit
            LATEST_COMMIT=$(git rev-parse HEAD)

            # latest commit where packages/material-ui-icons was changed
            FOLDER_COMMIT=$(git log -1 --format=format:%H --full-diff packages/material-ui-icons)

            if [ $FOLDER_COMMIT = $LATEST_COMMIT ]; then
              echo "changes, let's run the tests"
              cd packages/material-ui-icons && yarn test
            else
              echo "no changes"
            fi
      - run:
          name: material-ui-codemod
          command: |
            # latest commit
            LATEST_COMMIT=$(git rev-parse HEAD)

            # latest commit where packages/material-ui-codemod was changed
            FOLDER_COMMIT=$(git log -1 --format=format:%H --full-diff packages/material-ui-codemod)

            if [ $FOLDER_COMMIT = $LATEST_COMMIT ]; then
              echo "changes, let's run the tests"
              cd packages/material-ui-codemod && yarn test
            else
              echo "no changes"
            fi
      - run:
          name: material-ui-lab
          command: |
            # latest commit
            LATEST_COMMIT=$(git rev-parse HEAD)

            # latest commit where packages/material-ui-lab was changed
            FOLDER_COMMIT=$(git log -1 --format=format:%H --full-diff packages/material-ui-lab)

            if [ $FOLDER_COMMIT = $LATEST_COMMIT ]; then
              echo "changes, let's run the tests"
              cd packages/material-ui-lab && yarn test
            else
              echo "no changes"
            fi
      - run:
          name: eslint-plugin-material-ui
          command: |
            # latest commit
            LATEST_COMMIT=$(git rev-parse HEAD)

            # latest commit where packages/eslint-plugin-material-ui was changed
            FOLDER_COMMIT=$(git log -1 --format=format:%H --full-diff packages/eslint-plugin-material-ui)

            if [ $FOLDER_COMMIT = $LATEST_COMMIT ]; then
              echo "changes, let's run the tests"
              cd packages/eslint-plugin-material-ui && yarn test
            else
              echo "no changes"
            fi
  test_build:
    <<: *defaults
    # This isn't user facing code.
    # Let's take advantage of the most up to date node version.
    docker:
      - image: circleci/node:9.10
    steps:
      - checkout
      - *restore_yarn_offline_mirror
      - *restore_yarn_cache
      - *install_js
      - run:
          name: Can we generate the material-ui build?
          command: cd packages/material-ui && yarn build
      - run:
          name: Can we build the docs?
          command: yarn docs:build
      - run:
          name: Is the size acceptable?
          command: yarn size
  test_browser:
    <<: *defaults
    steps:
      - checkout
      - *restore_yarn_offline_mirror
      - *restore_yarn_cache
      - *install_js
      - run:
          name: Can we generate the documentation?
          command: yarn docs:api
      - run:
          name: "`yarn docs:api` changes commited?"
          command: git diff --exit-code
      - run:
          name: Install dependencies for Chrome Headless
          # From https://github.com/GoogleChrome/puppeteer/blob/811415bc8c47f7882375629b57b3fe186ad61ed4/docs/troubleshooting.md#chrome-headless-doesnt-launch
          command: |
            sudo apt-get update
            sudo apt-get install -y gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
      - run:
          name: Tests real browsers
          command: yarn test:karma
  test_regressions:
    <<: *defaults
    docker:
      - image: circleci/node:9.10
      - image: selenium/standalone-chrome:3.11.0
    steps:
      - checkout
      - *restore_yarn_offline_mirror
      - *restore_yarn_cache
      - *install_js
      - run:
          name: Visual regression tests
          command: |
            DOCKER_TEST_URL=http://$(ip addr show lo | grep "inet\b" | awk '{print $2}' | cut -d/ -f1):3090 yarn test:regressions
            yarn argos
workflows:
  version: 2
  pipeline:
    jobs:
      - checkout
      - test_unit:
          requires:
            - checkout
      - test_material-ui-x:
          requires:
            - checkout
      - test_browser:
          requires:
            - checkout
      - test_build:
          requires:
            - checkout
      - test_regressions:
          requires:
            - test_material-ui-x
            - test_unit
            - test_browser
            - test_build
