version: 2.1

executors:
  node:
    parameters:
      browsers:
        type: boolean
        default: false
    docker:
      - image: circleci/node:latest<<# parameters.browsers >>-browsers<</ parameters.browsers >>
    working_directory: ~/project
    environment:
      NODE_ENV: test
      NODE_OPTIONS: --max_old_space_size=4096

commands:
  attach-project:
    steps:
      - checkout
      - attach_workspace:
          at: ~/project
  store-test-results:
    steps:
      - store_test_results:
          path: reports/junit
  release:
    steps:
      - attach-project
      - run:
          name: release
          command: |
            if [ -z "$COMMIT_MSG" ]; then
              COMMIT_MSG=$(git --no-pager log --pretty=full -n1 $CIRCLE_SHA1)
            fi
            if echo "$COMMIT_MSG" | grep -o "\[release\]"; then
              echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
              echo "//registry.yarnpkg.com/:_authToken=$NPM_TOKEN" >> ~/.npmrc
              yarn lerna version --yes --no-git-tag-version --no-push
              PACKAGE_SUFFIX=edge yarn build
              if [ "$CIRCLE_BRANCH" = "next" ]; then tag="--tag next"; fi
              ./scripts/workspace-run npm publish $tag -q
            else
              echo "Release phase is skipped."
            fi

release_branches: &release_branches
  branches:
    only:
      - dev
      - next

jobs:
  # --------------------------------------------------------------------------
  # Phase 1: Setup
  # --------------------------------------------------------------------------
  setup:
    executor: node
    steps:
      # Checkout repository
      - checkout

      # Restore cache
      - restore_cache:
          key: lock-{{ checksum "yarn.lock" }}

      # Install dependencies
      - run:
          name: Install Dependencies
          command: yarn --frozen-lockfile --non-interactive

      # Save cache
      - save_cache:
          key: lock-{{ checksum "yarn.lock" }}
          paths:
            - node_modules
            - packages/*/node_modules
            - distributions/*/node_modules

      # Persist workspace
      - persist_to_workspace:
          root: ~/project
          paths:
            - node_modules
            - packages/*/node_modules
            - distributions/*/node_modules
            - packages/*/dist

  # --------------------------------------------------------------------------
  # Phase 2: Lint + Audit + Build Nuxt and fixtures
  # --------------------------------------------------------------------------
  lint:
    executor: node
    steps:
      - attach-project
      - run:
          name: Lint
          command: yarn test:lint

  audit:
    executor: node
    steps:
      - attach-project
      - run:
          name: Security Audit
          command: yarn audit || true

  build:
    executor: node
    steps:
      - attach-project
      - run:
          name: Build Fixtures
          command: yarn test:fixtures -i --coverage && yarn coverage -F fixtures
          environment:
            JEST_JUNIT_OUTPUT_NAME: fixtures.xml
      - store-test-results
      - persist_to_workspace:
          root: ~/project
          paths:
            - test/fixtures

  lint-app:
    executor: node
    steps:
      - attach-project
      - run:
          name: Lint vue-app templates
          command: yarn lint:app

  # --------------------------------------------------------------------------
  # Phase 3: Unit and E2E tests
  # --------------------------------------------------------------------------
  test-unit:
    executor: node
    steps:
      - attach-project
      - run:
          name: Unit Tests
          command: yarn test:unit -w=2 --coverage && yarn coverage -F unit
          environment:
            JEST_JUNIT_OUTPUT_NAME: unit.xml
      - store-test-results

  test-e2e:
    executor:
      name: node
      browsers: true
    steps:
      - attach-project
      - run:
          name: Download Chromium
          command: |
            cd /opt
            sudo wget https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/641430/chrome-linux.zip
            sudo unzip chrome-linux.zip
            sudo ln -s `pwd`/chrome-linux/chrome /bin/chromium
      - run:
          name: E2E Tests
          command: CHROME_PATH=/bin/chromium yarn test:e2e && yarn coverage -F e2e
          environment:
            JEST_JUNIT_OUTPUT_NAME: e2e.xml
      - store-test-results

  # --------------------------------------------------------------------------
  # Phase 4: Release (dev branch only)
  # --------------------------------------------------------------------------
  release-commit:
    executor: node
    steps:
      - release

  release-nightly:
    executor: node
    steps:
      - release
    environment:
        COMMIT_MSG: '[release]'

# Workflow definition
workflows:
  version: 2

  # Build and test after each commit
  # Manually release on release branches
  commit:
    jobs:
      - setup
      - lint:       { requires: [setup] }
      - audit:      { requires: [setup] }
      - build:      { requires: [setup] }
      - lint-app:   { requires: [build] }
      - test-unit:  { requires: [build] }
      - test-e2e:   { requires: [build] }
      - release-commit:
          requires: [build, lint, lint-app, audit, test-unit, test-e2e]
          filters:
            <<: *release_branches

  # Release nightly builds on release branches
  nightly:
    jobs:
      - setup
      - lint:       { requires: [setup] }
      - audit:      { requires: [setup] }
      - build:      { requires: [setup] }
      - lint-app:   { requires: [build] }
      - test-unit:  { requires: [build] }
      - test-e2e:   { requires: [build] }
      - release-nightly:
          requires: [build, lint, lint-app, audit, test-unit, test-e2e]
    triggers:
      - schedule:
          cron: "0 0 * * *"
          filters:
            <<: *release_branches