version: 2.1

executors:
  linux:
    machine:
      image: ubuntu-2004:202101-01
  macos:
    macos:
      xcode: 13.4.1

jobs:
  build:
    docker:
      - image: zokrates/env:latest
    resource_class: large
    steps:
      - checkout
      - run:
          name: Version information
          command: rustc --version; cargo --version; rustup --version
      - setup-sccache
      - restore-sccache-cache
      - run:
          name: Build
          command: RUSTFLAGS="-D warnings" ./build.sh
      - save-sccache-cache
  test:
    docker:
      - image: zokrates/env:latest
    resource_class: xlarge
    steps:
      - checkout
      - run:
          name: Version information
          command: rustc --version; cargo --version; rustup --version
      - setup-sccache
      - restore-sccache-cache
      - run:
          name: Check format
          command: cargo fmt --all -- --check
      - run:
          name: Run clippy
          no_output_timeout: 1h
          command: cargo clippy -j 4 -- -D warnings
      - run:
          name: Run tests
          no_output_timeout: 1h
          command: RUSTFLAGS="-D warnings" ./test.sh
      - save-sccache-cache
  wasm_test:
    docker:
      - image: zokrates/env:latest
    resource_class: large
    steps:
      - checkout
      - run:
          name: Version information
          command: rustc --version; cargo --version; rustup --version
      - setup-sccache
      - restore-sccache-cache
      - run:
          name: Test on firefox
          command: |
            cd zokrates_test
            wasm-pack test --firefox --headless
      - save-sccache-cache
  integration_test:
    docker:
      - image: zokrates/env:latest
      - image: trufflesuite/ganache-cli:next
    resource_class: large
    steps:
      - checkout
      - run:
          name: Version information
          command: rustc --version; cargo --version; rustup --version
      - setup-sccache
      - restore-sccache-cache
      - run:
          name: Install foundry
          command: ./scripts/install_foundry.sh
      - run:
          name: Run integration tests
          no_output_timeout: "30m"
          command: RUSTFLAGS="-D warnings" ./integration_test.sh
      - save-sccache-cache
  deploy:
    docker:
      - image: cimg/python:3.8-node
    resource_class: large
    steps:
      - checkout
      - setup_remote_docker:
          docker_layer_caching: true
      - run:
          name: Release
          no_output_timeout: "1h"
          command: ./scripts/release.sh
  zokrates_js_build:
    docker:
      - image: zokrates/env:latest
    resource_class: xlarge
    working_directory: ~/project/zokrates_js
    steps:
      - checkout:
          path: ~/project
      - setup-sccache
      - restore-sccache-cache
      - run:
          name: Build
          no_output_timeout: "30m"
          command: npm ci && npm run build:dev && npm pack --dry-run
      - save-sccache-cache
  zokrates_js_test:
    docker:
      - image: zokrates/env:latest
    resource_class: xlarge
    working_directory: ~/project/zokrates_js
    steps:
      - checkout:
          path: ~/project
      - setup-sccache
      - restore-sccache-cache
      - run:
          name: Install headless chrome dependencies
          command: |
            apt-get update && apt-get install -yq \
            ca-certificates fonts-liberation libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 \
            libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 \
            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 lsb-release wget xdg-utils
      - run:
          name: Run tests
          no_output_timeout: "30m"
          command: npm ci && npm run test
      - save-sccache-cache
  cross_build:
    parameters:
      os:
        type: executor
      target:
        type: string
      add-target:
        type: boolean
        default: false
      build-with:
        type: string
        default: cross
    executor: << parameters.os >>
    steps:
      - checkout
      - when:
         condition: << parameters.add-target >>
         steps:
           - run: rustup target add << parameters.target >>
      - run:
          name: Build
          no_output_timeout: "1h"
          command: RUSTFLAGS="--remap-path-prefix=$PWD=" << parameters.build-with >> build --package zokrates_cli --target << parameters.target >> --release
      - tar_artifacts:
          target: << parameters.target >>
  publish_artifacts:
    docker:
      - image: circleci/golang
    steps:
      - attach_workspace:
          at: /tmp/artifacts
      - run:
          name: "Publish artifacts on GitHub"
          command: |
            go install github.com/github-release/github-release@latest
            find /tmp/artifacts -type f -name *.tar.gz -exec basename {} \; | xargs -I {} github-release upload \
              -s ${GH_TOKEN} \
              -u ${CIRCLE_PROJECT_USERNAME} \
              -r ${CIRCLE_PROJECT_REPONAME} \
              -t ${CIRCLE_TAG} \
              -n "{}" \
              -f /tmp/artifacts/{}

commands:
  setup-sccache:
    steps:
      - run:
          name: Install sccache
          command: |
            apt-get install -y pkg-config libssl-dev
            curl -o- -sSLf https://github.com/mozilla/sccache/releases/download/0.2.14/sccache-0.2.14-x86_64-unknown-linux-musl.tar.gz | tar xzf -
            mv sccache-0.2.14-x86_64-unknown-linux-musl/sccache /usr/local/cargo/bin/sccache
            echo 'export "RUSTC_WRAPPER"="sccache"' >> $BASH_ENV
            echo 'export "SCCACHE_CACHE_SIZE"="1G"' >> $BASH_ENV
  restore-sccache-cache:
    steps:
      - restore_cache:
          name: Restore sccache cache
          key: sccache-cache-stable-{{ arch }}-{{ .Environment.CIRCLE_JOB }}
  save-sccache-cache:
    steps:
      - save_cache:
          name: Save sccache cache
          # We use {{ epoch }} to always upload a fresh cache:
          # Of course, restore_cache will not find this exact key,
          # but it will fall back to the closest key (aka the most recent).
          # See https://discuss.circleci.com/t/add-mechanism-to-update-existing-cache-key/9014/13
          key: sccache-cache-stable-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ epoch }}
          paths:
            - "~/.cache/sccache"
  install_rust:
    steps:
      - run:
          name: Install Rust
          command: |
            curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
            source $HOME/.cargo/env
  install_cross:
    steps:
      - run:
          name: Install cross
          command: cargo install cross --git https://github.com/cross-rs/cross
  tar_artifacts:
    parameters:
      target:
        type: string
    steps:
      - run:
          name: Store build artifacts
          command: |
            mkdir -p /tmp/artifacts
            find target/<< parameters.target >>/release -maxdepth 1 -type f | grep -E "zokrates(\.exe)?$" | xargs -I {} cp {} /tmp/artifacts/
            cp -r zokrates_stdlib/stdlib /tmp/artifacts/
            cd /tmp/artifacts
            tar czf zokrates-${CIRCLE_TAG}-<< parameters.target >>.tar.gz *
            ls | grep -v *.tar.gz | xargs rm -rf
      - store_artifacts:
          path: /tmp/artifacts
      - persist_to_workspace:
          root: /tmp/artifacts
          paths:
            - zokrates-*-<< parameters.target >>.tar.gz

tag-only: &tag-only
  filters:
    branches:
      ignore: /.*/
    tags:
      only: /^\d+\.\d+\.\d+$/

workflows:
  build-test-and-deploy:
    jobs:
      - build
      - test
      - wasm_test
      - integration_test
      - zokrates_js_build
      - zokrates_js_test
      - cross_build:
          <<: *tag-only
          pre-steps:
            - install_rust
            - install_cross
          matrix:
            alias: cross-build-linux
            parameters:
              os:
                - linux
              target:
                - aarch64-unknown-linux-gnu
                - arm-unknown-linux-gnueabi
                - x86_64-unknown-linux-gnu
                - x86_64-pc-windows-gnu
      - cross_build:
          <<: *tag-only
          pre-steps:
            - install_rust
          build-with: cargo
          matrix:
            alias: cross-build-macos
            parameters:
              os:
                - macos
              target:
                - x86_64-apple-darwin
      - cross_build:
         <<: *tag-only
         pre-steps:
           - install_rust
         build-with: SDKROOT=$(xcrun -sdk macosx12.3 --show-sdk-path) MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx12.3 --show-sdk-platform-version) cargo
         add-target: true
         matrix:
           alias: cross-build-apple-silicon
           parameters:
             os:
               - macos
             target:
               - aarch64-apple-darwin
      - publish_artifacts:
          <<: *tag-only
          requires:
            - cross-build-linux
            - cross-build-macos
            - cross-build-apple-silicon
      - deploy:
          filters:
            branches:
              only:
                - deploy
          requires:
            - build
            - test
            - wasm_test
            - integration_test
            - zokrates_js_build
            - zokrates_js_test
