version: 2.1

orbs:
  win: circleci/windows@4.0.0

workflows:
  version: 2
  ci:
    jobs:
      - test-cli
      #  - test-gui
      - build-win64:
          requires:
            - test-cli
            # - test-gui
      # - build-win32:
      #     requires:
      #       - test-cli
      #       # - test-gui
      # - build-macos:
      #     requires:
      #       - test-cli
      #       # - test-gui

jobs:
  test-cli:
    docker:
      - image: cimg/python:3.9
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: |
            sudo apt-get update
            sudo apt-get -y install tor obfs4proxy
      - restore_cache:
          key: test-cli-poetry-deps-{{ .Environment.CACHE_VERSION }}-{{ checksum "~/project/cli/poetry.lock" }}
      - run:
          name: Install poetry dependencies
          command: |
            cd ~/project/cli
            poetry install
      - save_cache:
          key: test-cli-poetry-deps-{{ .Environment.CACHE_VERSION }}-{{ checksum "~/project/cli/poetry.lock" }}
          paths:
            - /home/circleci/.cache/pypoetry/virtualenvs
      - run:
          name: Run tests
          command: |
            cd ~/project/cli
            poetry run pytest -v ./tests
            poetry run onionshare-cli --local-only ./tests --auto-stop-timer 2
            poetry run onionshare-cli --local-only --receive --auto-stop-timer 2
            poetry run onionshare-cli --local-only --website ../docs --auto-stop-timer 2
            poetry run onionshare-cli --local-only --chat --auto-stop-timer 2

  test-gui:
    docker:
      - image: cimg/python:3.9
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: |
            sudo apt-get update
            sudo apt-get install -y tor obfs4proxy gcc python3-dev python3-pyside2.qtcore python3-pyside2.qtwidgets python3-pyside2.qtgui
            sudo apt-get install -y xvfb x11-utils libxkbcommon-x11-0 libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev libxcb-render-util0 libxcb-icccm4 libxcb-keysyms1 libxcb-image0
      - restore_cache:
          key: test-desktop-poetry-deps-{{ checksum "~/project/desktop/poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Install poetry dependencies
          command: |
            cd ~/project/desktop
            poetry install
      - save_cache:
          key: test-desktop-poetry-deps-{{ checksum "~/project/desktop/poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - /home/circleci/.cache/pypoetry/virtualenvs
      - run:
          name: Run tests
          command: |
            cd ~/project/desktop
            QT_DEBUG_PLUGINS=1 xvfb-run poetry run pytest -v ./tests/test_gui_*.py

  build-win64:
    executor:
      name: win/default
      shell: powershell.exe
    environment:
      # NOTE: make sure to change when upgrading libevent
      LIBEVENT_TAG: "release-2.1.12-stable"
      # NOTE: make sure to change when upgrading tor
      TOR_TAG: "tor-0.4.7.7"
    steps:
      - checkout

      - restore_cache:
          # NOTE: make sure to change when upgrading tor
          key: "build-win64-tor-0.4.7.7-{{ .Environment.CACHE_VERSION }}"

      # Install cygwin and required packages
      - run:
          name: Install cygwin and required packages (for building tor)
          shell: bash.exe --login -eo pipefail
          command: |
            if [[ -d "/c/Users/circleci/build/tor" ]]; then
              echo "libevent and tor already compiled, skipping"
              exit 0
            fi

            curl -o setup-x86_64.exe https://cygwin.com/setup-x86_64.exe
            curl -o setup-x86_64.exe.sig https://cygwin.com/setup-x86_64.exe.sig
            curl -o pubring.asc https://cygwin.com/key/pubring.asc

            gpg --import pubring.asc
            gpg --verify setup-x86_64.exe.sig setup-x86_64.exe
            if [ $? -ne 0 ]; then
              echo "cygwin signature doesn't verify"
              exit -1
            fi

            ./setup-x86_64.exe -q -s https://mirrors.kernel.org/sourceware/cygwin/ -P libssl-devel,libevent-devel,git,gcc-core,make,autoconf,automake,libtool,gnupg

      # # Build libevent
      # - run:
      #     name: Build libevent
      #     shell: C:\\cygwin64\\bin\\bash.exe --login -eo pipefail
      #     command: |
      #       if [[ -d "/cygdrive/c/Users/circleci/build/libevent" ]]; then
      #         echo "libevent already compiled, skipping"
      #         exit 0
      #       fi

      #       mkdir -p /cygdrive/c/Users/circleci/src
      #       mkdir -p /cygdrive/c/Users/circleci/build

      #       # Get source
      #       curl "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x9e3ac83a27974b84d1b3401db86086848ef8686d" | gpg --import
      #       cd /cygdrive/c/Users/circleci/src
      #       git clone https://github.com/libevent/libevent.git
      #       cd libevent
      #       git tag -v $LIBEVENT_TAG
      #       if [ $? -ne 0 ]; then
      #         echo "libevent tag doesn't verify"
      #         exit -1
      #       fi
      #       git checkout $LIBEVENT_TAG

      #       # Build
      #       ./autogen.sh
      #       ./configure \
      #         --prefix=/opt/libevent-build \
      #         --with-pic
      #       make -j$(nproc)
      #       make install
      #       cp -r /opt/libevent-build /cygdrive/c/Users/circleci/build/libevent
      # - save_cache:
      #     # NOTE: make sure to change when upgrading libevent
      #     key: "build-win64-libevent-2.1.12-{{ .Environment.CACHE_VERSION }}"
      #     paths:
      #       - C:\Users\circleci\build\libevent

      # Build tor
      - run:
          name: Build tor
          shell: C:\\cygwin64\\bin\\bash.exe --login -eo pipefail
          command: |
            if [[ -d "/cygdrive/c/Users/circleci/build/tor" ]]; then
              echo "tor already compiled, skipping"
              exit 0
            fi

            mkdir -p /cygdrive/c/Users/circleci/src
            mkdir -p /cygdrive/c/Users/circleci/build

            # Get source
            curl https://keys.openpgp.org/vks/v1/by-fingerprint/B74417EDDF22AC9F9E90F49142E86A2A11F48D36 | gpg --import
            cd /cygdrive/c/Users/circleci/src
            git clone https://git.torproject.org/tor.git
            cd tor
            git tag -v $TOR_TAG
            if [ $? -ne 0 ]; then
              echo "tor tag doesn't verify"
              exit -1
            fi
            git checkout $TOR_TAG

            # Build
            ./autogen.sh
            ./configure \
              --prefix=/opt/tor-build \
              --disable-asciidoc
            make -j$(nproc)
            make install
            cp -r /opt/tor-build /cygdrive/c/Users/circleci/build/tor
      - save_cache:
          # NOTE: make sure to change when upgrading tor
          key: "build-win64-tor-0.4.7.7-{{ .Environment.CACHE_VERSION }}"
          paths:
            - C:\Users\circleci\build\tor

      # # Install python
      # - run:
      #     name: Install Python 3.9.12
      #     command: |
      #       choco install python3 --version=3.9.12

      # # Install poetry
      # - run:
      #     name: Install poetry
      #     command: (Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python -

      # # Install poetry dependencies
      # - restore_cache:
      #     key: build-win64-desktop-poetry-deps-{{ checksum "C:\Users\circleci\project\desktop\poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
      # - run:
      #     name: Install poetry dependencies
      #     command: |
      #       cd C:\Users\circleci\project\desktop
      #       poetry install
      # - save_cache:
      #     key: build-win64-desktop-poetry-deps-{{ checksum "C:\Users\circleci\project\desktop\poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
      #     paths:
      #       - C:\Users\circleci\AppData\Local\pypoetry\Cache\virtualenvs

      # - restore_cache:
      #     key: download-tor-win32-0.4.7.7
      # - run:
      #     name: Download tor (Windows Expert Bundle)
      #     command: |
      #       mkdir ~\Downloads\tor
      #       cd ~\Downloads\tor
      #       $URL = "https://www.torproject.org/dist/torbrowser/11.0.13/tor-win32-0.4.7.7.zip"
      #       $Filename = "tor-win32-0.4.7.7.zip"
      #       $ExpectedHash = "6af0088460d61a5e60971aea94562a3bed2fb597da6b8ac77948a5f6424dfa29"
      #       Invoke-WebRequest -Uri $URL -OutFile $Filename
      #       $FileHash = Get-FileHash $Filename
      #       if($FileHash.Hash -ne $ExpectedHash) { throw "Invalid hash" }
      #       mkdir ~\Downloads\tor\tor-win32
      #       Expand-Archive -LiteralPath tor-win32-0.4.7.7.zip -DestinationPath ~\Downloads\tor\tor-win32
      # - save_cache:
      #     key: download-tor-win32-0.4.7.7
      #     paths:
      #       - ~\Downloads\tor\tor-win32
      # - run:
      #     name: Copy tor binary into app
      #     command: cp ~\Downloads\tor\tor-win32\* ~\project\desktop\onionshare\resources\tor
      # - restore_cache:
      #     key: build-win64-obfs4proxy-v0.0.13
      # - run:
      #     name: Build obfs4proxy
      #     command: |
      #       mkdir ~\Downloads\obfs4proxy
      #       cd Downloads\obfs4proxy
      #       git clone https://gitlab.com/yawning/obfs4
      #       cd obfs4
      #       git checkout obfs4proxy-0.0.13
      #       go build .\obfs4proxy
      #       Move-Item -Path .\obfs4proxy.exe -Destination ~\project\desktop\onionshare\resources\tor\Tor\obfs4proxy.exe
      # - save_cache:
      #     key: build-win64-obfs4proxy-v0.0.13
      #     paths:
      #       - ~\project\desktop\onionshare\resources\tor\Tor\obfs4proxy.exe
      # - restore_cache:
      #     key: build-win64-snowflake-v2.1.0
      # - run:
      #     name: Build snowflake-client
      #     command: |
      #       go install git.torproject.org/pluggable-transports/snowflake.git/client@v2.1.0
      #       Move-Item -Path ~\go\bin\client.exe -Destination ~\project\desktop\onionshare\resources\tor\Tor\snowflake-client.exe
      # - save_cache:
      #     key: build-win64-snowflake-v2.1.0
      #     paths:
      #       - ~\project\desktop\onionshare\resources\tor\Tor\snowflake-client.exe
      # - restore_cache:
      #     key: build-win64-meek-v0.37.0
      # - run:
      #     name: Build meek-client
      #     command: |
      #       go install git.torproject.org/pluggable-transports/meek.git/meek-client@v0.37.0
      #       Move-Item -Path ~\go\bin\meek-client.exe -Destination ~\project\desktop\onionshare\resources\tor\Tor\meek-client.exe
      # - save_cache:
      #     key: build-win64-meek-v0.37.0
      #     paths:
      #       - ~\project\desktop\onionshare\resources\tor\Tor\meek-client.exe
      # - run:
      #     name: Build OnionShare
      #     command: |
      #       cd ~\project\desktop
      #       poetry run python .\setup-freeze.py build
      #       poetry run python .\scripts\build-windows.py cleanup-build
      # - run:
      #     name: Compress
      #     command: |
      #       mv ~\project\desktop\build\exe.win-amd64-3.9\ ~\onionshare-win64
      #       Compress-Archive -LiteralPath ~\onionshare-win64 -DestinationPath ~\onionshare-win64.zip
      # - store_artifacts:
      #     path: ~\onionshare-win64.zip

  build-win32:
    executor:
      name: win/default
      shell: powershell.exe
    steps:
      - checkout
      - run:
          name: Install Python 3.9.12 (32-bit)
          command: |
            choco install python3 --params "/InstallDir32:C:\Python-32bit" --version=3.9.12
      - run:
          name: Install golang (32-bit)
          command: |
            cd ~\Downloads
            Invoke-WebRequest -Uri https://go.dev/dl/go1.18.windows-386.msi -OutFile go1.18.windows-386.msi
            msiexec.exe /i go1.18.windows-386.msi /quiet /L*V go-install.log
      - run:
          name: Install poetry (32-bit)
          command: C:\Python-32bit\Scripts\pip install poetry
      - run:
          name: Install poetry dependencies
          command: |
            cd ~\project\desktop
            C:\Python-32bit\Scripts\poetry install
      - restore_cache:
          key: download-tor-win32-0.4.7.7
      - run:
          name: Download tor (Windows Expert Bundle)
          command: |
            mkdir ~\Downloads\tor
            cd ~\Downloads\tor
            $URL = "https://www.torproject.org/dist/torbrowser/11.0.13/tor-win32-0.4.7.7.zip"
            $Filename = "tor-win32-0.4.7.7.zip"
            $ExpectedHash = "6af0088460d61a5e60971aea94562a3bed2fb597da6b8ac77948a5f6424dfa29"
            Invoke-WebRequest -Uri $URL -OutFile $Filename
            $FileHash = Get-FileHash $Filename
            if($FileHash.Hash -ne $ExpectedHash) { throw "Invalid hash" }
            mkdir ~\Downloads\tor\tor-win32
            Expand-Archive -LiteralPath tor-win32-0.4.7.7.zip -DestinationPath ~\Downloads\tor\tor-win32
      - save_cache:
          key: download-tor-win32-0.4.7.7
          paths:
            - ~\Downloads\tor\tor-win32
      - run:
          name: Copy tor binary into app
          command: cp ~\Downloads\tor\tor-win32\* ~\project\desktop\onionshare\resources\tor
      - restore_cache:
          key: build-win32-obfs4proxy-v0.0.13
      - run:
          name: Build obfs4proxy
          command: |
            mkdir ~\Downloads\obfs4proxy
            cd Downloads\obfs4proxy
            git clone https://gitlab.com/yawning/obfs4
            git checkout obfs4proxy-0.0.13
            cd obfs4
            "C:\\Program Files (x86)\\Go\\bin\\go" build .\obfs4proxy
            Move-Item -Path .\obfs4proxy.exe -Destination ~\project\desktop\onionshare\resources\tor\Tor\obfs4proxy.exe
      - save_cache:
          key: build-win32-obfs4proxy-v0.0.13
          paths:
            - ~\project\desktop\onionshare\resources\tor\Tor\obfs4proxy.exe
      - restore_cache:
          key: build-win32-snowflake-v2.1.0
      - run:
          name: Build snowflake-client
          command: |
            "C:\\Program Files (x86)\\Go\\bin\\go" install git.torproject.org/pluggable-transports/snowflake.git/client@v2.1.0
            Move-Item -Path ~\go\bin\client.exe -Destination ~\project\desktop\onionshare\resources\tor\Tor\snowflake-client.exe
      - save_cache:
          key: build-win32-snowflake-v2.1.0
          paths:
            - ~\project\desktop\onionshare\resources\tor\Tor\snowflake-client.exe
      - restore_cache:
          key: build-win32-meek-v0.37.0
      - run:
          name: Build meek-client
          command: |
            "C:\\Program Files (x86)\\Go\\bin\\go" install git.torproject.org/pluggable-transports/meek.git/meek-client@v0.37.0
            Move-Item -Path ~\go\bin\meek-client.exe -Destination ~\project\desktop\onionshare\resources\tor\Tor\meek-client.exe
      - save_cache:
          key: build-win32-meek-v0.37.0
          paths:
            - ~\project\desktop\onionshare\resources\tor\Tor\meek-client.exe
      - run:
          name: Build OnionShare
          command: |
            cd ~\project\desktop
            C:\Python-32bit\Scripts\poetry run python .\setup-freeze.py build
            C:\Python-32bit\Scripts\poetry run python .\scripts\build-windows.py cleanup-build
      - run:
          name: Compress
          command: |
            mv ~\project\desktop\build\exe.win32-3.9\ ~\onionshare-win32
            Compress-Archive -LiteralPath ~\onionshare-win32 -DestinationPath ~\onionshare-win32.zip
      - store_artifacts:
          path: ~\onionshare-win32.zip

  build-macos:
    macos:
      xcode: 12.5.1
    environment:
      BINARY_DIR: /Users/distiller/bin
    steps:
      - checkout
      - run:
          name: Install Homebrew dependencies
          command: |
            brew install wget
            brew install go
      - restore_cache:
          key: build-libevent-2.1.12-tor-0.4.6.10
      - run:
          name: Build libevent and tor
          command: |
            mkdir -p $BINARY_DIR/tor
            # Download and verify libevent
            cd ~/Downloads
            URL=https://github.com/libevent/libevent/releases/download/release-2.1.12-stable/libevent-2.1.12-stable.tar.gz
            FILENAME=libevent-2.1.12-stable.tar.gz
            EXPECTED_SHA256=92e6de1be9ec176428fd2367677e61ceffc2ee1cb119035037a27d346b0403bb
            wget $URL
            SHA256=$(shasum -a 256 $FILENAME | cut -d" " -f1)
            if [ "$SHA256" != "$EXPECTED_SHA256" ]; then echo "Failed" && exit -1; fi
            tar -xvf $FILENAME
            # Build libevent
            cd libevent-2.1.12-stable
            ./configure --disable-openssl --prefix=$BINARY_DIR/tor
            make
            make install
            # Download and verify tor
            cd ~/Downloads
            URL=https://dist.torproject.org/tor-0.4.6.10.tar.gz
            FILENAME=tor-0.4.6.10.tar.gz
            EXPECTED_SHA256=94ccd60e04e558f33be73032bc84ea241660f92f58cfb88789bda6893739e31c
            wget $URL
            SHA256=$(shasum -a 256 $FILENAME | cut -d" " -f1)
            if [ "$SHA256" != "$EXPECTED_SHA256" ]; then echo "Failed" && exit -1; fi
            tar -xvf $FILENAME
            # Build tor
            cd tor-0.4.6.10
            ./configure --prefix=$BINARY_DIR/tor
            make
            make install
      - save_cache:
          key: build-libevent-2.1.12-tor-0.4.6.10
          paths:
            - /Users/distiller/bin/tor
      - restore_cache:
          key: build-macos-obfs4proxy-v0.0.13
      - run:
          name: Build obfs4proxy
          command: |
            # Get source code
            mkdir ~/Downloads/obfs4proxy
            cd ~/Downloads/obfs4proxy
            git clone https://gitlab.com/yawning/obfs4
            cd obfs4
            git checkout obfs4proxy-0.0.13
            # Build
            go build -o $BINARY_DIR/obfs4proxy ./obfs4proxy
      - save_cache:
          key: build-macos-obfs4proxy-v0.0.13
          paths:
            - /Users/distiller/bin/obfs4proxy
      - restore_cache:
          key: build-macos-snowflake-v2.1.0
      - run:
          name: Build snowflake-client
          command: |
            # Get source code
            mkdir ~/Downloads/snowflake-client
            cd ~/Downloads/snowflake-client
            git clone https://git.torproject.org/pluggable-transports/snowflake.git
            cd snowflake
            git checkout v2.1.0
            # Build
            go build -o $BINARY_DIR/snowflake-client ./client
      - save_cache:
          key: build-macos-snowflake-v2.1.0
          paths:
            - /Users/distiller/bin/snowflake-client
      - restore_cache:
          key: build-macos-meek-v0.37.0
      - run:
          name: Build meek-client
          command: |
            # Get source code
            mkdir ~/Downloads/meek-client
            cd ~/Downloads/meek-client
            git clone https://git.torproject.org/pluggable-transports/meek.git
            cd meek
            git checkout v0.37.0
            # Build
            go build -o $BINARY_DIR/meek-client ./meek-client
      - save_cache:
          key: build-macos-meek-v0.37.0
          paths:
            - /Users/distiller/bin/meek-client
      - run:
          name: Copy binaries into app
          command: |
            export DEST=~\project\desktop\onionshare\resources\tor
            cp $BINARY_DIR/tor/bin/tor $DEST
            cp $BINARY_DIR/tor/lib/libevent-2.1.7.dylib $DEST
            cp $BINARY_DIR/tor/share/tor/geoip* $DEST
            cp $BINARY_DIR/obfs4proxy $DEST
            cp $BINARY_DIR/snowflake-client $DEST
            cp $BINARY_DIR/meek-client $DEST
      - run:
          name: Install Python 3.9.12
          command: |
            wget https://www.python.org/ftp/python/3.9.12/python-3.9.12-macosx10.9.pkg -O ~/Downloads/python.pkg
            sudo installer -pkg ~/Downloads/python.pkg -target /
      - run:
          name: Install poetry
          command: |
            pip3 install poetry
            ln -s /Library/Frameworks/Python.framework/Versions/3.9/bin/poetry /usr/local/bin
      - run:
          name: Install poetry dependencies
          command: |
            cd ~/project/desktop
            poetry install
      - run:
          name: Build OnionShare
          command: |
            cd ~/project/desktop
            poetry run python ./setup-freeze.py build
            poetry run python ./setup-freeze.py bdist_mac
            poetry run python ./scripts/build-macos.py cleanup-build
      - run:
          name: Compress
          command: |
            cd ~/project/desktop/build
            zip -r ~/onionshare-macos.zip OnionShare.app
      - store_artifacts:
          path: ~/onionshare-macos.zip