---
version: 2.1
executors:
  med: # 2cpu, 4G ram
    docker:
      - image: circleci/node:10
    resource_class: medium
    working_directory: ~/project

  med_py:
    docker:
      - image: circleci/python:3.8
    resource_class: medium
    working_directory: ~/project

  release: # 1cpu, 2G ram
    docker:
      - image: cibuilds/github:0.13.0
    resource_class: small
    working_directory: ~/project

commands:
  prepare:
    description: "Prepare"
    steps:
      - checkout
      - restore_cache:
          name: Restore cached dependencies
          keys:
            - deps-{{ checksum "package.json" }}-{{ .Branch }}-{{ .Revision }}
            - deps-{{ checksum "package.json" }}
            - deps-

jobs:
  dependencies:
    executor: med
    steps:
      - prepare
      - run:
          name: Install Dependencies
          command: |
            yarn install
      - save_cache:
          name: Caching dependencies
          key: deps-{{ checksum "package.json" }}-{{ .Branch }}-{{ .Revision }}
          paths:
            - node_modules
      - persist_to_workspace:
          root: ~/project
          paths:
            - ./

  build_contracts:
    executor: med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: Build Contracts
          command: |
            yarn run build:contracts
      - persist_to_workspace:
          root: ~/project
          paths:
            - ./

  build_app:
    executor: med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: Build app
          command: |
            yarn run build:app
      - persist_to_workspace:
          root: ~/project
          paths:
            - ./

  build_deployment_app:
    executor: med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: Build app
          command: |
            yarn run build:app
          environment:
            GENERATE_SOURCEMAP: false
      - run:
          name: Bundle
          working_directory: build
          command: |
            mkdir -p ../distribution
            tar -czvf ../distribution/permissioning-smart-contracts-$(git describe).tar.gz *
            zip -R ../distribution/permissionin-smart-contracts-$(git describe).zip *
      - persist_to_workspace:
          root: ./
          paths:
            - distribution/
            - build/
      - store_artifacts:
          name: Distributions
          path: distribution/
          when: always

  lint_contracts:
    executor: med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: Lint
          command: |
            yarn run lint:contracts

  lint_app:
    executor: med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: Lint
          command: |
            yarn run lint:app

  # Run vulnerability detection with MythX 
  run_mythx:
    executor: med_py
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: Install MythX CLI
          command: pip install mythx-cli
      - run:
          name: Analyze with MythX
          command: mythx analyze
  
  test_contracts:
    executor: med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: Test Contracts
          command: |
            yarn run test:contracts
            mkdir -p test-results/contracts
            mv test-results/test-contract-results.xml test-results/contracts/results.xml
      - store_test_results:
          path: test-results
      - run:
          name: Collect Contract Coverage
          command: |
            yarn run coverage:contracts
            ./node_modules/.bin/istanbul report
      - store_artifacts:
          path: coverage
      - store_artifacts:
          path: coverage.json

  test_app:
    executor: med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: Test app
          command: |
            yarn run test:app:ci
            mkdir -p test-results/app
            mv junit.xml test-results/app/results.xml
      - store_test_results:
          path: test-results


  build_docker:
    executor: med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - setup_remote_docker
      - run:
          name: Build Docker
          command: |
            VERSION=$(git describe)
            docker build -t pegasyseng/permissioning-smart-contracts-dapp:${VERSION} -f docker/Dockerfile .

  publish_docker:
    executor: med
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - setup_remote_docker
      - run:
          name: Publish Docker
          command: |
            VERSION=$(git describe)
            docker login --username "${DOCKER_USER}" --password "${DOCKER_PASSWORD}"
            docker push  pegasyseng/permissioning-smart-contracts-dapp:${VERSION}

  release:
    executor: release
    steps:
      - prepare
      - attach_workspace:
          at: ~/project
      - run:
          name: Publish Release on Github
          command: |
            VERSION=$(git describe)
            ghr \
              -t ${GITHUB_RELEASE_TOKEN} \
              -u ${CIRCLE_PROJECT_USERNAME} \
              -r ${CIRCLE_PROJECT_REPONAME} \
              -c ${CIRCLE_SHA1} \
              ${CIRCLE_TAG} \
              ./distribution/

workflows:
  version: 2
  default:
    jobs:
      - dependencies:
          filters:
            tags:
              only:
                - /.*/
      - build_contracts:
          requires:
            - dependencies
          filters:
            tags:
              only:
                - /.*/
      - lint_contracts:
          requires:
            - build_contracts
          filters:
            tags:
              only:
                - /.*/
      - test_contracts:
          requires:
            - build_contracts
          filters:
            tags:
              only:
                - /.*/
      - run_mythx:
          requires:
            - build_contracts
          filters:
            branches:
              only:
                - main
            tags:
              only:
                - /.*/
      - test_app:
          requires:
            - build_contracts
          filters:
            tags:
              only:
                - /.*/
      - lint_app:
          requires:
            - build_contracts
          filters:
            tags:
              only:
                - /.*/
      - build_app:
          requires:
            - test_app
          filters:
            tags:
              ignore:
                - /.*/
      - build_deployment_app:
          requires:
            - test_app
          filters:
            branches:
              ignore:
                - /.*/
            tags:
              only:
                - /.*/
      - build_docker:
          requires:
            - build_deployment_app
          filters:
            branches:
              ignore:
                - /.*/
            tags:
              only:
                - /.*/
      - publish_docker:
          requires:
            - build_docker
            - lint_app
            - test_contracts
            - lint_contracts
          filters:
            branches:
              ignore:
                - /.*/
            tags:
              only:
                - /.*/
      - release:
          requires:
            - build_deployment_app
            - lint_app
            - test_contracts
            - lint_contracts
          filters:
            branches:
              ignore:
                - /.*/
            tags:
              only:
                - /.*/
