# vim:ts=2:sw=2:et
# --------------------------------------------------------------------------
#   Prefixes used in order to keep CircleCI workflow overview more readable:
#     - b: build
#     - t: test
#     - ubu: ubuntu
#     - ems: Emscripten
version: 2.1
parameters:
  ubuntu-2004-docker-image:
    type: string
    # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004-8
    default: "solbuildpackpusher/solidity-buildpack-deps@sha256:9c3cdfc1d573d1ca3edacd892590a9a83487a1f746a6ca2093d7e009818c5179"
  ubuntu-2004-clang-docker-image:
    type: string
    # solbuildpackpusher/solidity-buildpack-deps:ubuntu2004.clang-8
    default: "solbuildpackpusher/solidity-buildpack-deps@sha256:61232feea23c8c57e82cf5fae890f8b86bbec353cdc04f2fcba383ca589e1d8b"
  ubuntu-1604-clang-ossfuzz-docker-image:
    type: string
    # solbuildpackpusher/solidity-buildpack-deps:ubuntu1604.clang.ossfuzz-13
    default: "solbuildpackpusher/solidity-buildpack-deps@sha256:c26a7ffc9fc243a4ec3105b9dc1edcdd964ad0e9665c83172b7ebda74bbf3021"
  emscripten-docker-image:
    type: string
    # solbuildpackpusher/solidity-buildpack-deps:emscripten-6
    default: "solbuildpackpusher/solidity-buildpack-deps@sha256:092da5817bc032c91a806b4f73db2a1a31e5cc4c066d94d43eedd9f365df7154"
  evm-version:
    type: string
    default: london

orbs:
  win: circleci/windows@2.2.0

defaults:

  # --------------------------------------------------------------------------
  # Build Templates

  - setup_prerelease_commit_hash: &setup_prerelease_commit_hash
      name: Store commit hash and prerelease
      command: |
        if [ "$CIRCLE_BRANCH" = release -o -n "$CIRCLE_TAG" ]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi
        echo -n "$CIRCLE_SHA1" > commit_hash.txt

  - run_build: &run_build
      name: Build
      command: scripts/ci/build.sh

  - run_build_ossfuzz: &run_build_ossfuzz
      name: Build_ossfuzz
      command: scripts/ci/build_ossfuzz.sh

  - run_proofs: &run_proofs
      name: Correctness proofs for optimization rules
      command: scripts/run_proofs.sh

  - run_soltest: &run_soltest
      name: soltest
      no_output_timeout: 30m
      command: ./.circleci/soltest.sh

  - run_soltest_all: &run_soltest_all
      name: soltest_all
      no_output_timeout: 30m
      command: ./.circleci/soltest_all.sh

  - run_cmdline_tests: &run_cmdline_tests
      name: command line tests
      no_output_timeout: 30m
      command: ./test/cmdlineTests.sh

  - run_docs_pragma_min_version: &run_docs_pragma_min_version
      name: docs pragma version check
      command: ./scripts/docs_version_pragma_check.sh

  # --------------------------------------------------------------------------
  # Artifacts Templates

  # the whole build directory
  - artifacts_build_dir: &artifacts_build_dir
      root: build
      paths:
        - "*"

  # compiled solc executable target
  - artifacts_solc: &artifacts_solc
      path: build/solc/solc
      destination: solc

  # windows artifacts
  - artifact_solc_windows: &artifact_solc_windows
      path: upload/

  # compiled tool executable target
  - artifacts_tools: &artifacts_tools
      path: build/tools/solidity-upgrade
      destination: solidity-upgrade

  # compiled executable targets
  - artifacts_executables: &artifacts_executables
      root: build
      paths:
        - solc/solc
        - test/soltest
        - test/tools/solfuzzer

  # compiled OSSFUZZ targets
  - artifacts_executables_ossfuzz: &artifacts_executables_ossfuzz
      root: build
      paths:
        - test/tools/ossfuzz/abiv2_proto_ossfuzz
        - test/tools/ossfuzz/abiv2_isabelle_ossfuzz
        - test/tools/ossfuzz/const_opt_ossfuzz
        - test/tools/ossfuzz/solc_mutator_ossfuzz
        - test/tools/ossfuzz/solc_ossfuzz
        - test/tools/ossfuzz/stack_reuse_codegen_ossfuzz
        - test/tools/ossfuzz/strictasm_assembly_ossfuzz
        - test/tools/ossfuzz/strictasm_diff_ossfuzz
        - test/tools/ossfuzz/strictasm_opt_ossfuzz
        - test/tools/ossfuzz/yul_proto_diff_ossfuzz
        - test/tools/ossfuzz/yul_proto_diff_custom_mutate_ossfuzz
        - test/tools/ossfuzz/yul_proto_ossfuzz
        - test/tools/ossfuzz/sol_proto_ossfuzz

  # test result output directory
  - artifacts_test_results: &artifacts_test_results
      path: test_results/
      destination: test_results/

  # --------------------------------------------------------------------------
  # Tests Templates

  # store_test_results helper
  - store_test_results: &store_test_results
      path: test_results/

  - steps_soltest: &steps_soltest
      steps:
        - checkout
        - attach_workspace:
            at: build
        - run: *run_soltest
        - store_test_results: *store_test_results
        - store_artifacts: *artifacts_test_results

  - steps_soltest_all: &steps_soltest_all
      steps:
        - checkout
        - attach_workspace:
            at: build
        - run: *run_soltest_all
        - store_test_results: *store_test_results
        - store_artifacts: *artifacts_test_results

  - steps_cmdline_tests: &steps_cmdline_tests
      steps:
        - checkout
        - attach_workspace:
            at: build
        - run: *run_cmdline_tests
        - store_test_results: *store_test_results
        - store_artifacts: *artifacts_test_results

  - test_ubuntu1604_clang: &test_ubuntu1604_clang
      docker:
        - image: << pipeline.parameters.ubuntu-1604-clang-ossfuzz-docker-image >>
      <<: *steps_soltest

  - test_ubuntu2004_clang: &test_ubuntu2004_clang
      docker:
        - image: << pipeline.parameters.ubuntu-2004-clang-docker-image >>
      <<: *steps_soltest

  - test_ubuntu2004: &test_ubuntu2004
      docker:
        - image: << pipeline.parameters.ubuntu-2004-docker-image >>
      parallelism: 6
      <<: *steps_soltest_all

  - test_asan: &test_asan
      <<: *test_ubuntu2004
      <<: *steps_soltest

  - test_ubuntu2004_clang_cli: &test_ubuntu2004_clang_cli
      docker:
        - image: << pipeline.parameters.ubuntu-2004-clang-docker-image >>
      <<: *steps_cmdline_tests

  # --------------------------------------------------------------------------
  # Workflow Templates

  - workflow_trigger_on_tags: &workflow_trigger_on_tags
      filters:
        tags:
          only: /.*/

  - workflow_ubuntu2004: &workflow_ubuntu2004
      <<: *workflow_trigger_on_tags
      requires:
        - b_ubu

  - workflow_ubuntu1604_clang: &workflow_ubuntu1604_clang
      <<: *workflow_trigger_on_tags
      requires:
        - b_ubu_ossfuzz

  - workflow_ubuntu2004_clang: &workflow_ubuntu2004_clang
      <<: *workflow_trigger_on_tags
      requires:
        - b_ubu_clang

  - workflow_ubuntu2004_release: &workflow_ubuntu2004_release
      <<: *workflow_trigger_on_tags
      requires:
        - b_ubu_release

  - workflow_archlinux: &workflow_archlinux
      <<: *workflow_trigger_on_tags
      requires:
        - b_archlinux

  - workflow_ubuntu2004_codecov: &workflow_ubuntu2004_codecov
      <<: *workflow_trigger_on_tags
      requires:
        - b_ubu_codecov

  - workflow_osx: &workflow_osx
      <<: *workflow_trigger_on_tags
      requires:
        - b_osx

  - workflow_ubuntu2004_asan: &workflow_ubuntu2004_asan
      <<: *workflow_trigger_on_tags
      requires:
        - b_ubu_asan

  - workflow_ubuntu2004_asan_clang: &workflow_ubuntu2004_asan_clang
      <<: *workflow_trigger_on_tags
      requires:
        - b_ubu_asan_clang

  - workflow_ubuntu2004_ubsan_clang: &workflow_ubuntu2004_ubsan_clang
      <<: *workflow_trigger_on_tags
      requires:
        - b_ubu_ubsan_clang

  - workflow_emscripten: &workflow_emscripten
      <<: *workflow_trigger_on_tags
      requires:
        - b_ems

  - workflow_ubuntu1604_ossfuzz: &workflow_ubuntu1604_ossfuzz
      <<: *workflow_trigger_on_tags
      requires:
        - b_ubu_ossfuzz

  - workflow_win: &workflow_win
      <<: *workflow_trigger_on_tags
      requires:
        - b_win

  - workflow_win_release: &workflow_win_release
      <<: *workflow_trigger_on_tags
      requires:
        - b_win_release

  # --------------------------------------------------------------------------
  # Notification Templates
  - gitter_notify_failure: &gitter_notify_failure
      name: Gitter notify failure
      command: >-
        curl -X POST -i
        -i -H "Content-Type: application/json"
        -H "Accept: application/json"
        -H "Authorization: Bearer $GITTER_API_TOKEN" "https://api.gitter.im/v1/rooms/$GITTER_NOTIFY_ROOM_ID/chatMessages"
        -d '{"text":" ❌ Nightly job **'$CIRCLE_JOB'** failed on **'$CIRCLE_BRANCH'**. Please see '$CIRCLE_BUILD_URL' for details."}'
      when: on_fail

  - gitter_notify_success: &gitter_notify_success
      name: Gitter notify success
      command: >-
        curl -X POST -i
        -i -H "Content-Type: application/json"
        -H "Accept: application/json"
        -H "Authorization: Bearer $GITTER_API_TOKEN" "https://api.gitter.im/v1/rooms/$GITTER_NOTIFY_ROOM_ID/chatMessages"
        -d '{"text":" ✅ Nightly job **'$CIRCLE_JOB'** succeeded on **'$CIRCLE_BRANCH'**. Please see '$CIRCLE_BUILD_URL' for details."}'
      when: on_success

# -----------------------------------------------------------------------------------------------
jobs:

  chk_spelling:
    docker:
      - image: circleci/python:3.6
    environment:
      TERM: xterm
    steps:
      - checkout
      - attach_workspace:
          at: build
      - run:
          name: Install dependencies
          command: |
            pip install --user codespell
      - run:
          name: Check spelling
          command: ~/.local/bin/codespell -S "*.enc,.git,Dockerfile*" -I ./scripts/codespell_whitelist.txt

  chk_docs_examples:
    docker:
      - image: circleci/node
    environment:
      TERM: xterm
    steps:
      - checkout
      - attach_workspace:
          at: build
      - run:
          name: JS deps
          command: sudo npm install -g solhint
      - run:
          name: Test Docs examples
          command: ./test/docsCodeStyle.sh

  chk_coding_style:
    docker:
      - image: buildpack-deps:focal
    steps:
      - checkout
      - run:
          name: Install shellcheck
          command: apt -q update && apt install -y shellcheck
      - run:
          name: Check for C++ coding style
          command: ./scripts/check_style.sh
      - run:
          name: checking shell scripts
          command: ./scripts/chk_shellscripts/chk_shellscripts.sh
      - run:
          name: Check for broken symlinks
          command: ./scripts/check_symlinks.sh

  chk_errorcodes:
    docker:
      - image: circleci/python:3.6
    steps:
      - checkout
      - run:
          name: Check for error codes
          command: ./scripts/error_codes.py --check

  chk_pylint:
    docker:
      - image: buildpack-deps:focal
    steps:
      - checkout
      - run:
          name: Install pip
          command: apt -q update && apt install -y python3-pip
      - run:
          name: Install pylint
          command: python3 -m pip install pylint z3-solver pygments-lexer-solidity parsec tabulate
          # also z3-solver, parsec and tabulate to make sure pylint knows about this module, pygments-lexer-solidity for docs
      - run:
          name: Linting Python Scripts
          command: ./scripts/pylint_all.py

  chk_antlr_grammar:
    docker:
      - image: buildpack-deps:focal
    steps:
      - checkout
      - run:
          name: Install Java
          command: apt -q update && apt install -y openjdk-16-jdk
      - run:
          name: Run tests
          command: ./scripts/test_antlr_grammar.sh

  chk_buglist:
    docker:
      - image: circleci/node
    environment:
      TERM: xterm
    steps:
      - checkout
      - run:
          name: JS deps
          command: |
            npm install download
            npm install JSONPath
            npm install mktemp
      - run:
          name: Test buglist
          command: ./test/buglistTests.js

  chk_proofs:
    docker:
      - image: buildpack-deps:latest
    environment:
      TERM: xterm
    steps:
      - checkout
      - run:
          name: Z3 python deps
          command: |
            apt-get -qq update
            apt-get -qy install python3-pip
            pip3 install --user z3-solver
      - run: *run_proofs

  chk_docs_pragma_min_version:
    docker:
      - image: << pipeline.parameters.ubuntu-2004-docker-image >>
    environment:
      TERM: xterm
    steps:
      - checkout
      - run: *run_docs_pragma_min_version

  t_pyscripts_ubu:
    docker:
      - image: << pipeline.parameters.ubuntu-2004-docker-image >>
    steps:
      - checkout
      - run:
          name: Python unit tests
          command: python3 test/pyscriptTests.py

  t_pyscripts_win:
    executor:
      name: win/default
      shell: powershell.exe
    steps:
      - run: git config --global core.autocrlf false
      - checkout
      - run:
          name: Python unit tests
          command: python.exe test/pyscriptTests.py

  b_ubu: &b_ubu
    resource_class: xlarge
    docker:
      - image: << pipeline.parameters.ubuntu-2004-docker-image >>
    environment:
      MAKEFLAGS: -j 10
    steps:
      - checkout
      - run: *run_build
      - store_artifacts: *artifacts_solc
      - store_artifacts: *artifacts_tools
      - persist_to_workspace: *artifacts_executables

  # x64 ASAN build, for testing for memory related bugs
  b_ubu_asan: &b_ubu_asan
    <<: *b_ubu
    environment:
      CMAKE_OPTIONS: -DSANITIZE=address
      MAKEFLAGS: -j 10
      CMAKE_BUILD_TYPE: Release
    steps:
      - checkout
      - run: *run_build
      - store_artifacts: *artifacts_solc
      - persist_to_workspace: *artifacts_executables

  b_ubu_clang: &b_ubu_clang
    resource_class: xlarge
    docker:
      - image: << pipeline.parameters.ubuntu-2004-clang-docker-image >>
    environment:
      CC: clang
      CXX: clang++
      MAKEFLAGS: -j 10
    steps:
      - checkout
      - run: *run_build
      - store_artifacts: *artifacts_solc
      - persist_to_workspace: *artifacts_executables

  b_ubu_asan_clang: &b_ubu_asan_clang
    docker:
      - image: << pipeline.parameters.ubuntu-2004-clang-docker-image >>
    environment:
      CC: clang
      CXX: clang++
      CMAKE_OPTIONS: -DSANITIZE=address
      MAKEFLAGS: -j 3
    steps:
      - checkout
      - run: *run_build
      - store_artifacts: *artifacts_solc
      - persist_to_workspace: *artifacts_executables

  b_ubu_ubsan_clang: &b_ubu_ubsan_clang
    docker:
      - image: << pipeline.parameters.ubuntu-2004-clang-docker-image >>
    environment:
      CC: clang
      CXX: clang++
      CMAKE_OPTIONS: -DSANITIZE=undefined
      MAKEFLAGS: -j 3
    steps:
      - checkout
      - run: *run_build
      - run: *gitter_notify_failure
      - store_artifacts: *artifacts_solc
      - persist_to_workspace: *artifacts_executables

  b_ubu_release: &b_ubu_release
    <<: *b_ubu
    environment:
      FORCE_RELEASE: ON
      MAKEFLAGS: -j 10

  b_ubu_static:
    <<: *b_ubu
    environment:
      MAKEFLAGS: -j 10
      CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON
    steps:
      - checkout
      - run: *run_build
      - run:
          name: strip binary
          command: strip build/solc/solc
      - store_artifacts: *artifacts_solc

  b_ubu_codecov:
    <<: *b_ubu
    environment:
      COVERAGE: ON
      CMAKE_BUILD_TYPE: Debug
      MAKEFLAGS: -j 10
    steps:
      - checkout
      - run: *run_build
      - persist_to_workspace: *artifacts_executables

  t_ubu_codecov:
    <<: *test_ubuntu2004
    environment:
      EVM: << pipeline.parameters.evm-version >>
      OPTIMIZE: 1
    steps:
      - checkout
      - attach_workspace:
          at: build
      - run:
          name: "soltest: Syntax Tests"
          command: build/test/soltest -t 'syntaxTest*' -- --testpath test
      - run:
          name: "Code Coverage: Syntax Tests"
          command: codecov --flags syntax --gcov-root build
      - run: *run_soltest
      - run:
          name: "Coverage: All"
          command: codecov --flags all --gcov-root build
      - store_artifacts: *artifacts_test_results

  # Builds in C++20 mode and uses debug build in order to speed up.
  # Do *NOT* store any artifacts or workspace as we don't run tests on this build.
  b_ubu_cxx20:
    <<: *b_ubu
    environment:
      CMAKE_BUILD_TYPE: Debug
      CMAKE_OPTIONS: -DCMAKE_CXX_STANDARD=20 -DUSE_CVC4=OFF
      MAKEFLAGS: -j 10
    steps:
      - checkout
      - run: *run_build

  b_ubu_ossfuzz: &b_ubu_ossfuzz
    docker:
      - image: << pipeline.parameters.ubuntu-1604-clang-ossfuzz-docker-image >>
    environment:
      CC: clang
      CXX: clang++
      TERM: xterm
      MAKEFLAGS: -j 3
    steps:
      - checkout
      - run: *setup_prerelease_commit_hash
      - run: *run_build_ossfuzz
      - persist_to_workspace: *artifacts_executables_ossfuzz

  t_ubu_ossfuzz: &t_ubu_ossfuzz
    <<: *test_ubuntu1604_clang
    steps:
      - checkout
      - attach_workspace:
          at: build
      - run:
          name: Regression tests
          command: |
            git clone https://github.com/ethereum/solidity-fuzzing-corpus /tmp/solidity-fuzzing-corpus
            mkdir -p test_results
            scripts/regressions.py -o test_results
      - run: *gitter_notify_failure
      - run: *gitter_notify_success
      - store_test_results: *store_test_results
      - store_artifacts: *artifacts_test_results

  b_archlinux:
    docker:
      - image: archlinux:base
    environment:
      TERM: xterm
      MAKEFLAGS: -j 3
    steps:
      - run:
          name: Install build dependencies
          command: |
            pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake z3 cvc4 git openssh tar
      - checkout
      - run: *run_build
      - store_artifacts: *artifacts_solc
      - persist_to_workspace: *artifacts_executables

  b_osx:
    macos:
      xcode: "11.0.0"
    environment:
      TERM: xterm
      CMAKE_BUILD_TYPE: Release
      MAKEFLAGS: -j 5
    steps:
      - checkout
      - restore_cache:
          keys:
            - dependencies-osx-{{ checksum ".circleci/osx_install_dependencies.sh" }}
      # DO NOT EDIT between here and save_cache, but rather edit ./circleci/osx_install_dependencies.sh
      # WARNING! If you do edit anything here instead, remember to invalidate the cache manually.
      - run:
          name: Install build dependencies
          command: ./.circleci/osx_install_dependencies.sh
      - save_cache:
          key: dependencies-osx-{{ checksum ".circleci/osx_install_dependencies.sh" }}
          paths:
            - /usr/local/bin
            - /usr/local/sbin
            - /usr/local/lib
            - /usr/local/include
            - /usr/local/Cellar
            - /usr/local/Homebrew
      - run: *run_build
      - store_artifacts: *artifacts_solc
      - store_artifacts: *artifacts_tools
      - persist_to_workspace:
          root: .
          paths:
            - build/solc/solc
            - build/test/soltest
            - build/test/tools/solfuzzer

  t_osx_soltest:
    macos:
      xcode: "11.0.0"
    environment:
      EVM: << pipeline.parameters.evm-version >>
      OPTIMIZE: 0
      TERM: xterm
    steps:
      - checkout
      - restore_cache:
          keys:
            - dependencies-osx-{{ checksum ".circleci/osx_install_dependencies.sh" }}
      - attach_workspace:
          at: .
      - run: *run_soltest
      - store_test_results: *store_test_results
      - store_artifacts: *artifacts_test_results

  t_osx_cli:
    macos:
      xcode: "11.0.0"
    environment:
      TERM: xterm
    steps:
      - checkout
      - restore_cache:
          keys:
            - dependencies-osx-{{ checksum ".circleci/osx_install_dependencies.sh" }}
      - attach_workspace:
          at: .
      - run: *run_cmdline_tests
      - store_artifacts: *artifacts_test_results

  b_ems:
    resource_class: xlarge
    docker:
      - image: << pipeline.parameters.emscripten-docker-image >>
    environment:
      MAKEFLAGS: -j 10
      TERM: xterm
    steps:
      - checkout
      - run:
          name: Build
          command: |
            scripts/ci/build_emscripten.sh
      - store_artifacts:
          path: emscripten_build/libsolc/soljson.js
          destination: soljson.js
      - run: mkdir -p workspace
      - run: cp emscripten_build/libsolc/soljson.js workspace/soljson.js
      - run: scripts/get_version.sh > workspace/version.txt
      - persist_to_workspace:
          root: workspace
          paths:
            - soljson.js
            - version.txt

  b_docs:
    docker:
      - image: << pipeline.parameters.ubuntu-2004-docker-image >>
    steps:
      - checkout
      - run: *setup_prerelease_commit_hash
      - run:
          name: Build documentation
          command: ./scripts/docs.sh
      - store_artifacts:
          path: docs/_build/html/
          destination: docs-html

  t_ubu_soltest: &t_ubu_soltest
    <<: *test_ubuntu2004

  t_archlinux_soltest: &t_archlinux_soltest
      docker:
        - image: archlinux:base
      environment:
        EVM: << pipeline.parameters.evm-version >>
        OPTIMIZE: 0
        TERM: xterm
        # For Archlinux we do not have prebuilt docker images and we would need to build evmone from source,
        # thus we forgo semantics tests to speed things up.
        SOLTEST_FLAGS: --no-semantic-tests
      steps:
        - run:
            name: Install runtime dependencies
            command: |
              pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake z3 cvc4 git openssh tar
        - when:
            condition: true
            <<: *steps_soltest

  t_ubu_soltest_enforce_yul: &t_ubu_soltest_enforce_yul
    docker:
      - image: << pipeline.parameters.ubuntu-2004-docker-image >>
    environment:
      EVM: << pipeline.parameters.evm-version >>
      SOLTEST_FLAGS: --enforce-via-yul
      OPTIMIZE: 0
      TERM: xterm
    <<: *steps_soltest


  t_ubu_clang_soltest: &t_ubu_clang_soltest
    <<: *test_ubuntu2004_clang
    environment:
      EVM: << pipeline.parameters.evm-version >>
      OPTIMIZE: 0

  t_ubu_release_soltest: &t_ubu_release_soltest
    <<: *t_ubu_soltest

  t_ubu_cli: &t_ubu_cli
    docker:
      - image: << pipeline.parameters.ubuntu-2004-docker-image >>
    environment:
      TERM: xterm
    <<: *steps_cmdline_tests

  t_ubu_release_cli: &t_ubu_release_cli
    <<: *t_ubu_cli

  t_ubu_asan_cli:
    <<: *t_ubu_cli
    environment:
      TERM: xterm
      ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2
    <<: *steps_cmdline_tests

  t_ubu_asan:
    <<: *test_asan
    environment:
      EVM: << pipeline.parameters.evm-version >>
      OPTIMIZE: 0
      SOLTEST_FLAGS: --no-smt
      ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2

  t_ubu_asan_clang:
    <<: *test_ubuntu2004_clang
    environment:
      EVM: << pipeline.parameters.evm-version >>
      OPTIMIZE: 0
      SOLTEST_FLAGS: --no-smt
      ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2

  t_ubu_ubsan_clang:
    environment:
      EVM: << pipeline.parameters.evm-version >>
    docker:
      - image: << pipeline.parameters.ubuntu-2004-clang-docker-image >>
    steps:
      - when:
          condition: true
          <<: *steps_soltest
      - run: *gitter_notify_failure

  t_ubu_ubsan_clang_cli:
    docker:
      - image: << pipeline.parameters.ubuntu-2004-clang-docker-image >>
    steps:
      - when:
          condition: true
          <<: *steps_cmdline_tests
      - run: *gitter_notify_failure

  t_ems_solcjs:
    docker:
      - image: << pipeline.parameters.ubuntu-2004-docker-image >>
    environment:
      TERM: xterm
    steps:
      - checkout
      - attach_workspace:
          at: /tmp/workspace
      - run:
          name: Install test dependencies
          command: |
            apt-get update
            apt-get install -qqy --no-install-recommends nodejs npm
      - run:
          name: Test solcjs
          no_output_timeout: 30m
          command: |
            node --version
            npm --version
            test/externalTests/solc-js/solc-js.sh /tmp/workspace/soljson.js $(cat /tmp/workspace/version.txt)

  t_ems_ext:
    parameters:
      project:
        type: string
      compile_only:
        type: integer
        default: 0
      nodejs_version:
        type: integer
        default: 14
      gitter_notify:
        type: boolean
        default: no
    docker:
      - image: circleci/node:<<parameters.nodejs_version>>
    environment:
      TERM: xterm
      COMPILE_ONLY: <<parameters.compile_only>>
    steps:
      - checkout
      - attach_workspace:
          at: /tmp/workspace
      - run:
          name: Install dependencies
          command: |
            # lsof is used by Colony in its stop-blockchain-client.sh script
            sudo apt-get -qy install lsof
      - run:
          name: External <<parameters.project>> tests
          command: |
            test/externalTests/<<parameters.project>>.sh /tmp/workspace/soljson.js
      - when:
          condition: <<parameters.gitter_notify>>
          steps:
            - run: *gitter_notify_failure
            - run: *gitter_notify_success

  b_win: &b_win
    executor:
      name: win/default
      shell: powershell.exe
    steps:
      # NOTE: Not disabling git's core.autocrlf here because we want to build using the typical Windows config.
      - checkout
      - restore_cache:
          keys:
            - dependencies-win-{{ checksum "scripts/install_deps.ps1" }}
      # DO NOT EDIT between here and save_cache, but rather edit .\scripts\install_deps.ps1
      # WARNING! If you do edit anything here instead, remember to invalidate the cache manually.
      - run:
          name: "Installing dependencies"
          command: .\scripts\install_deps.ps1
      - save_cache:
          key: dependencies-win-{{ checksum "scripts/install_deps.ps1" }}
          paths:
            - .\deps
      - run:
          name: "Building solidity"
          command: .circleci/build_win.ps1
      - run:
          name: "Run solc.exe to make sure build was successful."
          command: .\build\solc\Release\solc.exe --version
      - store_artifacts: *artifact_solc_windows
      - persist_to_workspace:
          root: build
          paths:
            - .\solc\*\solc.exe
            - .\test\*\soltest.exe

  b_win_release:
    <<: *b_win
    environment:
      FORCE_RELEASE: ON

  t_win: &t_win
    executor:
      name: win/default
      shell: powershell.exe
    steps:
      # NOTE: Git's default core.autocrlf is fine for running soltest. We get additional coverage
      # for files using CRLF that way.
      - checkout
      - attach_workspace:
          at: build
      - run:
          name: "Install evmone"
          command: scripts/install_evmone.ps1
      - run:
          name: "Run soltest"
          command: .circleci/soltest.ps1
      - store_test_results: *store_test_results
      - store_artifacts: *artifacts_test_results

  t_win_release:
    <<: *t_win

  b_bytecode_ubu:
    docker:
      - image: << pipeline.parameters.ubuntu-2004-docker-image >>
    steps:
      - checkout
      - attach_workspace:
          at: build
      - run: mkdir test-cases/
      - run: cd test-cases && ../scripts/isolate_tests.py ../test/
      - run: cd test-cases && ../scripts/bytecodecompare/prepare_report.py ../build/solc/solc --interface standard-json --report-file ../bytecode-report-ubuntu-json.txt
      - run: cd test-cases && ../scripts/bytecodecompare/prepare_report.py ../build/solc/solc --interface cli --report-file ../bytecode-report-ubuntu-cli.txt
      - store_artifacts:
          path: bytecode-report-ubuntu-json.txt
      - store_artifacts:
          path: bytecode-report-ubuntu-cli.txt
      - persist_to_workspace:
          root: .
          paths:
            - bytecode-report-ubuntu-json.txt
            - bytecode-report-ubuntu-cli.txt

  b_bytecode_osx:
    macos:
      xcode: "11.0.0"
    environment:
      TERM: xterm
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run: mkdir test-cases/
      - run: cd test-cases && ../scripts/isolate_tests.py ../test/
      - run: cd test-cases && ../scripts/bytecodecompare/prepare_report.py ../build/solc/solc --interface standard-json --report-file ../bytecode-report-osx-json.txt
      - run: cd test-cases && ../scripts/bytecodecompare/prepare_report.py ../build/solc/solc --interface cli --report-file ../bytecode-report-osx-cli.txt
      - store_artifacts:
          path: bytecode-report-osx-json.txt
      - store_artifacts:
          path: bytecode-report-osx-cli.txt
      - persist_to_workspace:
          root: .
          paths:
            - bytecode-report-osx-json.txt
            - bytecode-report-osx-cli.txt

  b_bytecode_win:
    executor:
      name: win/default
      shell: cmd.exe
    steps:
      # NOTE: For bytecode generation we need the input files to be byte-for-byte identical on all
      # platforms so line ending conversions must absolutely be disabled.
      - run: git config --global core.autocrlf false
      - checkout
      - attach_workspace:
          at: build
      - run: mkdir test-cases\
      - run: cd test-cases\ && python ..\scripts\isolate_tests.py ..\test\
      - run: cd test-cases\ && python ..\scripts\bytecodecompare\prepare_report.py ..\build\solc\Release\solc.exe --interface standard-json --report-file ..\bytecode-report-windows-json.txt
      - run: cd test-cases\ && python ..\scripts\bytecodecompare\prepare_report.py ..\build\solc\Release\solc.exe --interface cli --report-file ..\bytecode-report-windows-cli.txt
      - store_artifacts:
          path: bytecode-report-windows-json.txt
      - store_artifacts:
          path: bytecode-report-windows-cli.txt
      - persist_to_workspace:
          root: .
          paths:
            - bytecode-report-windows-json.txt
            - bytecode-report-windows-cli.txt

  b_bytecode_ems:
    docker:
      - image: circleci/node:16
    environment:
      SOLC_EMSCRIPTEN: "On"
    steps:
      - checkout
      - attach_workspace:
          at: emscripten_build/libsolc
      - run: scripts/bytecodecompare/storebytecode.sh && mv -v report.txt bytecode-report-emscripten.txt
      - store_artifacts:
          path: bytecode-report-emscripten.txt
      - persist_to_workspace:
          root: .
          paths:
            - bytecode-report-emscripten.txt

  t_bytecode_compare:
    docker:
      - image: << pipeline.parameters.ubuntu-2004-docker-image >>
    environment:
      REPORT_FILES: |
        bytecode-report-emscripten.txt
        bytecode-report-ubuntu-json.txt
        bytecode-report-ubuntu-cli.txt
        bytecode-report-osx-json.txt
        bytecode-report-osx-cli.txt
        bytecode-report-windows-json.txt
        bytecode-report-windows-cli.txt
    steps:
      - attach_workspace:
          at: .
      - run:
          name: Compare reports
          command: diff --brief --report-identical-files --from-file $REPORT_FILES
      - run:
          name: Print diff
          when: on_fail
          command: diff --unified=0 --report-identical-files --from-file $REPORT_FILES | head --lines 50
      - run:
          name: Install zip
          when: on_fail
          command: |
            apt update --quiet
            apt install zip --assume-yes
      - run:
          name: Bundle reports into a single package
          when: on_fail
          command: zip all-bytecode-reports.zip $REPORT_FILES
      - store_artifacts:
          # NOTE: store_artifacts does not support the 'when' attribute.
          # Fortunately when the artifact does not exist it just says "No artifact files found" and ignores it.
          path: all-bytecode-reports.zip

workflows:
  version: 2

  main:
    jobs:
      # basic checks
      - chk_spelling: *workflow_trigger_on_tags
      - chk_coding_style: *workflow_trigger_on_tags
      # DISABLED FOR 0.6.0 - chk_docs_examples: *workflow_trigger_on_tags
      - chk_buglist: *workflow_trigger_on_tags
      - chk_proofs: *workflow_trigger_on_tags
      - chk_pylint: *workflow_trigger_on_tags
      - chk_errorcodes: *workflow_trigger_on_tags
      - chk_antlr_grammar: *workflow_trigger_on_tags
      - chk_docs_pragma_min_version: *workflow_trigger_on_tags
      - t_pyscripts_ubu: *workflow_trigger_on_tags
      - t_pyscripts_win: *workflow_trigger_on_tags

      # build-only
      - b_docs: *workflow_trigger_on_tags
      - b_ubu_cxx20: *workflow_trigger_on_tags
      - b_ubu_ossfuzz: *workflow_trigger_on_tags

      # OS/X build and tests
      - b_osx: *workflow_trigger_on_tags
      - t_osx_cli: *workflow_osx
      - t_osx_soltest: *workflow_osx

      # ArchLinux build and tests
      - b_archlinux: *workflow_trigger_on_tags
      - t_archlinux_soltest: *workflow_archlinux

      # Static build
      - b_ubu_static: *workflow_trigger_on_tags

      # Ubuntu build and tests
      - b_ubu: *workflow_trigger_on_tags
      - t_ubu_cli: *workflow_ubuntu2004
      - t_ubu_soltest: *workflow_ubuntu2004
      - t_ubu_soltest_enforce_yul: *workflow_ubuntu2004
      - b_ubu_clang: *workflow_trigger_on_tags
      - t_ubu_clang_soltest: *workflow_ubuntu2004_clang

      # Ubuntu fake release build and tests
      - b_ubu_release: *workflow_trigger_on_tags
      - t_ubu_release_cli: *workflow_ubuntu2004_release
      - t_ubu_release_soltest: *workflow_ubuntu2004_release

      # Emscripten build and tests that take 15 minutes or less
      - b_ems: *workflow_trigger_on_tags
      - t_ems_solcjs: *workflow_emscripten

      - t_ems_ext:
          <<: *workflow_emscripten
          name: t_ems_compile_ext_colony
          project: colony
          compile_only: 1
      - t_ems_ext:
          <<: *workflow_emscripten
          name: t_ems_compile_ext_gnosis
          project: gnosis
          compile_only: 1
      - t_ems_ext:
          <<: *workflow_emscripten
          name: t_ems_compile_ext_gnosis_v2
          project: gnosis-v2
          compile_only: 1
      - t_ems_ext:
          <<: *workflow_emscripten
          name: t_ems_compile_ext_zeppelin
          project: zeppelin
          compile_only: 1
      - t_ems_ext:
          <<: *workflow_emscripten
          name: t_ems_compile_ext_ens
          project: ens
          compile_only: 1
          # NOTE: One of the dependencies (fsevents) fails to build its native extension on node.js 12+.
          nodejs_version: 10

      # FIXME: Gnosis tests are pretty flaky right now. They often fail on CircleCI due to random ProviderError
      # and there are also other less frequent problems. See https://github.com/gnosis/safe-contracts/issues/216.
      #- t_ems_ext:
      #    <<: *workflow_emscripten
      #    name: t_ems_test_ext_gnosis
      #    project: gnosis
      #    # NOTE: Tests do not start on node.js 14 ("ganache-cli exited early with code 1").
      #    nodejs_version: 12
      - t_ems_ext:
          <<: *workflow_emscripten
          name: t_ems_test_ext_gnosis_v2
          project: gnosis-v2
          # NOTE: Tests do not start on node.js 14 ("ganache-cli exited early with code 1").
          nodejs_version: 12
      - t_ems_ext:
          <<: *workflow_emscripten
          name: t_ems_test_ext_zeppelin
          project: zeppelin
      - t_ems_ext:
          <<: *workflow_emscripten
          name: t_ems_test_ext_ens
          project: ens
          # NOTE: One of the dependencies (fsevents) fails to build its native extension on node.js 12+.
          nodejs_version: 10

      # Windows build and tests
      - b_win: *workflow_trigger_on_tags
      - b_win_release: *workflow_trigger_on_tags
      - t_win: *workflow_win
      - t_win_release: *workflow_win_release

      # Bytecode comparison:
      - b_bytecode_ubu:
          requires:
            - b_ubu
      - b_bytecode_win:
          requires:
            - b_win
      - b_bytecode_osx:
          requires:
            - b_osx
      - b_bytecode_ems:
          requires:
            - b_ems
      - t_bytecode_compare:
          requires:
            - b_bytecode_ubu
            - b_bytecode_win
            - b_bytecode_osx
            - b_bytecode_ems

  nightly:

    triggers:
      - schedule:
          cron: "0 0 * * *"
          filters:
            branches:
              only:
                - develop

    jobs:
      # OSSFUZZ builds and (regression) tests
      - b_ubu_ossfuzz: *workflow_trigger_on_tags
      - t_ubu_ossfuzz: *workflow_ubuntu1604_ossfuzz

      # Code Coverage enabled build and tests
      - b_ubu_codecov: *workflow_trigger_on_tags
      - t_ubu_codecov: *workflow_ubuntu2004_codecov

      # ASan build and tests
      - b_ubu_asan: *workflow_trigger_on_tags
      - b_ubu_asan_clang: *workflow_trigger_on_tags
      - t_ubu_asan: *workflow_ubuntu2004_asan
      - t_ubu_asan_clang: *workflow_ubuntu2004_asan_clang
      - t_ubu_asan_cli: *workflow_ubuntu2004_asan

      # UBSan build and tests
      - b_ubu_ubsan_clang: *workflow_trigger_on_tags
      - t_ubu_ubsan_clang: *workflow_ubuntu2004_ubsan_clang
      - t_ubu_ubsan_clang_cli: *workflow_ubuntu2004_ubsan_clang

      # Emscripten build and tests that take more than 15 minutes to execute
      - b_ems: *workflow_trigger_on_tags
      - t_ems_ext:
          <<: *workflow_emscripten
          name: t_ems_test_ext_colony
          project: colony
          gitter_notify: yes
