---

version: 2.1
orbs:
  shellcheck: circleci/shellcheck@2.2.2 # brew install shellcheck stopped working so using this
  macos: circleci/macos@2

aliases:
  - &important-branches
    filters:
      branches:
        only:
          - master
          - /^version\-bump\-.*/
  # common - cache
  - &cache_restore_git
    restore_cache:
      name: cache | restore git
      keys:
        - src-v1-{{ arch }}-{{ .Branch }}-{{ .Revision }}
        - src-v1-{{ arch }}-{{ .Branch }}-
        - src-v1-{{ arch }}
  - &cache_save_git
    save_cache:
      name: cache | save git
      key: src-v1-{{ arch }}-{{ .Branch }}-{{ .Revision }}
      paths:
        - ".git"

  - &cache_restore_bundler
    restore_cache:
      name: cache | restore bundle
      key: v3-gems-{{ arch }}-<< parameters.ruby_version >>-{{ checksum "Gemfile.lock" }}
  - &cache_save_bundler
    save_cache:
      name: cache | store bundle
      key: v3-gems-{{ arch }}-<< parameters.ruby_version >>-{{ checksum "Gemfile.lock" }}
      paths:
        - ".bundle"

  - &cache_restore_rubocop
    restore_cache:
      name: cache | restore rubocop
      keys:
        - v1-rubocop-{{ arch }}-{{ epoch }}
        - v1-rubocop-{{ arch }}-
  - &cache_save_rubocop
    save_cache:
      name: cache | store rubocop
      key: v1-rubocop-{{ arch }}-{{ epoch }}
      paths:
        - "~/.cache/rubocop_cache"

  - &bundle_install
    run:
      name: bundle install
      command: |
        gem install bundler -v $(cat Gemfile.lock | tail -1 | tr -d " ")
        bundle config set --local path .bundle
        bundle check || bundle install --jobs=4 --retry=3

jobs:
  tests_macos: &tests_macos_base
    description: 'Execute tests on macOS with given Xcode and Ruby version'
    macos:
      xcode: << parameters.xcode_version >>
    parameters:
      xcode_version:
        type: string
      ruby_version:
        type: string
      ruby_opt:
        type: string
        default: ''
    environment:
      CIRCLE_TEST_REPORTS: '~/test-reports'
      LC_ALL: 'en_US.UTF-8'
      LANG: 'en_US.UTF-8'
    shell: '/bin/bash --login -eo pipefail'
    steps:
      - *cache_restore_git
      - checkout
      - *cache_save_git
      - *cache_restore_bundler
      - macos/switch-ruby:
          version: << parameters.ruby_version >>
      - run:
          name: debug | ruby version
          command: |
            ruby -v
      - run:
          name: Setup Build
          command: |
            mkdir -p ~/test-reports
      - *bundle_install
      - *cache_save_bundler
      - run:
          name: Check PR Metadata
          command: bundle exec danger || echo "danger failed"
      - *cache_restore_rubocop
      - run:
          name: bundle exec fastlane execute_tests
          command: |
            bundle exec fastlane snapshot reset_simulators --force
            RUBYOPT=<< parameters.ruby_opt >> bundle exec fastlane execute_tests
      - *cache_save_rubocop
      - run:
          name: Check compatibility with Ruby 3.0
          command: |
            touch ~/test-reports/ruby_warnings.txt
            ! cat ~/test-reports/ruby_warnings.txt | grep -E "warning:\s.*(deprecated).*$" && echo "No deprecation message found."
            ! cat ~/test-reports/ruby_warnings.txt | grep -E "warning:\s.*(obsolete).*$" && echo "No obsolete message found."
      - store_test_results:
          path: ~/test-reports
      - store_artifacts:
          path: ~/test-reports/rspec
          destination: test-reports
      - store_artifacts:
          path: ~/test-reports/ruby_warnings.txt
          destination: ruby_warnings.txt
      - run:
          name: Post Test Results to GitHub
          command: bundle exec danger || echo "danger failed"
          when: always  # Run this even when tests fail

  tests_ubuntu:
    parameters:
      image:
        type: string
      ruby_version: # Used when restoring/saving bundler cache
        type: string
    environment:
      CIRCLE_TEST_REPORTS: '~/test-reports'
      LC_ALL: 'C.UTF-8'
      LANG: 'C.UTF-8'
      FASTLANE_ITUNES_TRANSPORTER_PATH: .bundle
    docker:
      - image: << parameters.image >>
    steps:
      - *cache_restore_git
      - checkout
      - *cache_save_git
      - *cache_restore_bundler
      - run:
          name: Setup Build
          command: |
            mkdir -p ~/test-reports
      - *bundle_install
      - *cache_save_bundler
      - run:
          name: Check PR Metadata
          command: bundle exec danger || echo "danger failed"
      - *cache_restore_rubocop
      - run: bundle exec fastlane execute_tests
      - *cache_save_rubocop
      - store_test_results:
          path: ~/test-reports
      - store_artifacts:
          path: ~/test-reports/rspec
          destination: test-reports
      - store_artifacts:
          path: ~/test-reports/ruby_warnings.txt
          destination: ruby_warnings.txt
      - run:
          name: Post Test Results to GitHub
          command: bundle exec danger || echo "danger failed"
          when: always  # Run this even when tests fail

  validate_fastlane_swift_generation:
    <<: *tests_macos_base
    steps:
      - *cache_restore_git
      - checkout
      - *cache_save_git
      - *cache_restore_bundler
      - macos/switch-ruby:
          version: << parameters.ruby_version >>
      - *bundle_install
      - *cache_save_bundler
      - run:
          name: debug | brew version
          command: |
            brew -v
      - run:
          name: brew update if needed # temporary solution for this https://discuss.circleci.com/t/macos-image-users-homebrew-brownout-2021-04-26/39872/2
          command: |
            # if the version is not 3.x.x, try brew update
            ruby -e 'exit(1) if `brew -v` =~ /2\.\d+\.\d+/' ||\
            brew update || \
            # if brew update fails due to shallow clone, try unshallowing and then brew update again
            git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow && \
            brew update
      - run: bundle exec fastlane generate_swift_api

  validate_documentation:
    parameters:
      image:
        type: string
      ruby_version: # Used when restoring/saving bundler cache
        type: string
    docker:
      - image: << parameters.image >>
    steps:
      - *cache_restore_git
      - checkout
      - *cache_save_git
      - *cache_restore_bundler

      - run:
          name: Setup Build
          command: |
            gem update --system
      - *bundle_install
      - *cache_save_bundler

      - run: bundle exec fastlane validate_docs

  lint_source_code:
    parameters:
      image:
        type: string
      ruby_version: # Used when restoring/saving bundler cache
        type: string
    docker:
      - image: << parameters.image >>
    steps:
      - *cache_restore_git
      - checkout
      - *cache_save_git
      - *cache_restore_bundler
      - *bundle_install
      - *cache_save_bundler

      - run: bundle exec fastlane lint_source

  modules_load_up_tests:
    parameters:
      image:
        type: string
    environment:
      LC_ALL: C.UTF-8
      LANG: C.UTF-8
    docker:
      - image: << parameters.image >>
    shell: /bin/bash --login -eo pipefail
    steps:
      - *cache_restore_git
      - checkout
      - *cache_save_git

      - run:
          name: Setup Build
          # Build gem from fastlane.gemspec and install locally
          command: |
            gem install $(echo $(gem build fastlane.gemspec) | sed 's/.*File: //')

      - run: /bin/bash ./test_modules/run_tests.sh

workflows:
  version: 2
  "Run Tests & Checks": # Name of the workflow, which ends up displayed on GitHub's PR Check
    jobs:
      - tests_macos:
          name: 'Execute tests on macOS (Xcode 12.5.1, Ruby 2.6)'
          xcode_version: '12.5.1'
          ruby_version: '2.6.6'
          <<: *important-branches
      - tests_macos:
          name: 'Execute tests on macOS (Xcode 12.5.1, Ruby 2.7)'
          xcode_version: '12.5.1'
          ruby_version: '2.7.3'
          ruby_opt: -W:deprecated
          <<: *important-branches
      - tests_macos:
          name: 'Execute tests on macOS (Xcode 13.4.1, Ruby 3.0)'
          xcode_version: '13.4.1'
          ruby_version: '3.0.4'
          ruby_opt: -W:deprecated
          <<: *important-branches
      - tests_macos:
          name: 'Execute tests on macOS (Xcode 13.4.1, Ruby 3.1)'
          xcode_version: '13.4.1'
          ruby_version: '3.1.2'
          ruby_opt: -W:deprecated
      - tests_macos:
          name: 'Execute tests on macOS (Xcode 14.3.1, Ruby 3.1)'
          xcode_version: '14.3.1'
          ruby_version: '3.1
          ruby_opt: -W:deprecated
      - tests_macos:
          name: 'Execute tests on macOS (Xcode 15.0.1, Ruby 3.1)'
          xcode_version: '15.0.1'
          ruby_version: '3.1'
          ruby_opt: -W:deprecated
      - tests_macos:
          name: 'Execute tests on macOS (Xcode 13.4.1, Ruby 3.1)'
          xcode_version: '13.4.1'
          ruby_version: '3.1'
          ruby_opt: -W:deprecated
      - tests_macos:
          name: 'Execute tests on macOS (Xcode 14.3.1, Ruby 3.2)'
          xcode_version: '14.3.1'
          ruby_version: '3.2'
          ruby_opt: -W:deprecated
      - tests_macos:
          name: 'Execute tests on macOS (Xcode 15.0.1, Ruby 3.2)'
          xcode_version: '15.0.1'
          ruby_version: '3.2'
          ruby_opt: -W:deprecated
      - tests_ubuntu:
          name: 'Execute tests on Ubuntu'
          image: 'fastlanetools/ci:0.3.0'
          ruby_version: '2.6'
      - validate_fastlane_swift_generation:
          name: 'Validate Fastlane.swift generation'
          xcode_version: '12.5.1'
          ruby_version: '2.7'
      - validate_documentation:
          name: 'Validate Documentation'
          image: 'cimg/ruby:3.2.2'
          ruby_version: '3.2'
      - lint_source_code:
          name: 'Lint source code'
          image: 'cimg/ruby:2.6'
          ruby_version: '2.6'
      - modules_load_up_tests:
          name: 'Modules load up tests'
          image: 'cimg/ruby:2.6'
