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
            pip install --upgrade pip poetry
      - 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
            pip install --upgrade pip poetry
      - 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
    steps:
      - checkout

      - run:
          name: Install Python 3.9.13 (64-bit)
          command: |
            cd ~\Downloads
            Invoke-WebRequest -Uri https://www.python.org/ftp/python/3.9.13/python-3.9.13-amd64.exe -OutFile python-3.9.13-amd64.exe
            .\python-3.9.13-amd64.exe /quiet InstallAllUsers=1 TargetDir=C:\Python39
            while($true) {
              if ((Test-Path -Path C:\Python39\python.exe) -eq $True) {
                Write-Output "Python is installed"
                break
              } else {
                Write-Output "Waiting for Python to finish installing ..."
                Start-Sleep -Seconds 2
              }
            }

      - run:
          name: Install poetry
          command: C:\Python39\python -m pip install poetry

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

      - restore_cache:
          key: get-tor-win64-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Get tor binaries from Tor Browser (64-bit)
          command: |
            cd desktop
            C:\Python39\Scripts\poetry run python .\scripts\get-tor.py win64
      - save_cache:
          key: get-tor-win64-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - C:\Users\circleci\project\desktop\build\tor

      - restore_cache:
          key: build-win64-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.ps1" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Build obfs4proxy
          command: |
            if ((Test-Path -Path 'C:\Users\circleci\project\desktop\onionshare\resources\tor\obfs4proxy.exe') -eq $True) {
              Write-Output "obfs4proxy already built"
            } else {
              cd C:\Users\circleci\project\desktop
              .\scripts\build-pt-obfs4proxy.ps1
            }
      - save_cache:
          key: build-win64-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.ps1" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - C:\Users\circleci\project\desktop\onionshare\resources\tor\obfs4proxy.exe

      - restore_cache:
          key: build-win64-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.ps1" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Build snowflake-client
          command: |
            if ((Test-Path -Path 'C:\Users\circleci\project\desktop\onionshare\resources\tor\snowflake-client.exe') -eq $True) {
              Write-Output "snowflake already built"
            } else {
              cd C:\Users\circleci\project\desktop
              .\scripts\build-pt-snowflake.ps1
            }
      - save_cache:
          key: build-win64-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.ps1" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - C:\Users\circleci\project\desktop\onionshare\resources\tor\snowflake-client.exe

      - restore_cache:
          key: build-win64-meek-{{ checksum "~/project/desktop/scripts/build-pt-meek.ps1" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Build meek-client
          command: |
            if ((Test-Path -Path 'C:\Users\circleci\project\desktop\onionshare\resources\tor\meek-client.exe') -eq $True) {
              Write-Output "snowflake already built"
            } else {
              cd C:\Users\circleci\project\desktop
              .\scripts\build-pt-meek.ps1
            }
      - save_cache:
          key: build-win64-meek-{{ checksum "~/project/desktop/scripts/build-pt-meek.ps1" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - C:\Users\circleci\project\desktop\onionshare\resources\tor\meek-client.exe

      - run:
          name: Build OnionShare
          command: |
            cd ~\project\desktop
            C:\Python39\Scripts\poetry run python .\setup-freeze.py build
            C:\Python39\Scripts\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.13 (32-bit)
          command: |
            cd ~\Downloads
            Invoke-WebRequest -Uri https://www.python.org/ftp/python/3.9.13/python-3.9.13.exe -OutFile python-3.9.13.exe
            .\python-3.9.13.exe /quiet InstallAllUsers=1 TargetDir=C:\Python39
            while($true) {
              if ((Test-Path -Path C:\Python39\python.exe) -eq $True) {
                Write-Output "Python is installed"
                break
              } else {
                Write-Output "Waiting for Python to finish installing ..."
                Start-Sleep -Seconds 2
              }
            }

      - run:
          name: Install poetry
          command: C:\Python39\python -m pip install poetry

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

      - restore_cache:
          key: get-tor-win32-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Get tor binaries from Tor Browser (32-bit)
          command: |
            cd desktop
            C:\Python39\Scripts\poetry run python .\scripts\get-tor.py win32
      - save_cache:
          key: get-tor-win32-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - C:\Users\circleci\project\desktop\build\tor

      - 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

      - restore_cache:
          key: build-win32-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.ps1" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Build obfs4proxy
          command: |
            if ((Test-Path -Path C:\Users\circleci\project\desktop\onionshare\resources\tor\obfs4proxy.exe) -eq $True) {
              Write-Output "obfs4proxy already built"
            } else {
              $env:PATH = "C:\Program Files (x86)\Go\bin\go;$env:PATH"
              cd C:\Users\circleci\project\desktop
              .\scripts\build-pt-obfs4proxy.ps1
            }
      - save_cache:
          key: build-win32-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.ps1" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - C:\Users\circleci\project\desktop\onionshare\resources\tor\obfs4proxy.exe

      - restore_cache:
          key: build-win32-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.ps1" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Build snowflake-client
          command: |
            if ((Test-Path -Path C:\Users\circleci\project\desktop\onionshare\resources\tor\snowflake-client.exe) -eq $True) {
              Write-Output "snowflake already built"
            } else {
              $env:PATH = "C:\Program Files (x86)\Go\bin\go;$env:PATH"
              cd C:\Users\circleci\project\desktop
              .\scripts\build-pt-snowflake.ps1
            }
      - save_cache:
          key: build-win32-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.ps1" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - C:\Users\circleci\project\desktop\onionshare\resources\tor\snowflake-client.exe

      - restore_cache:
          key: build-win32-meek-{{ checksum "~/project/desktop/scripts/build-pt-meek.ps1" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Build meek-client
          command: |
            if ((Test-Path -Path C:\Users\circleci\project\desktop\onionshare\resources\tor\meek-client.exe) -eq $True) {
              Write-Output "snowflake already built"
            } else {
              $env:PATH = "C:\Program Files (x86)\Go\bin\go;$env:PATH"
              cd C:\Users\circleci\project\desktop
              .\scripts\build-pt-meek.ps1
            }
      - save_cache:
          key: build-win32-meek-{{ checksum "~/project/desktop/scripts/build-pt-meek.ps1" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - C:\Users\circleci\project\desktop\onionshare\resources\tor\meek-client.exe

      - run:
          name: Build OnionShare
          command: |
            cd ~\project\desktop
            C:\Python39\Scripts\poetry run python .\setup-freeze.py build
            C:\Python39\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 Go 1.18.3
          command: |
            curl -L https://go.dev/dl/go1.18.3.darwin-amd64.pkg --output ~/Downloads/go.pkg
            sudo installer -pkg ~/Downloads/go.pkg -target /

      - run:
          name: Install Python 3.9.13
          command: |
            curl -L https://www.python.org/ftp/python/3.9.13/python-3.9.13-macosx10.9.pkg --output ~/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

      - restore_cache:
          key: build-macos-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: build-macos-desktop-poetry-deps-{{ checksum "~/project/desktop/poetry.lock" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - /Users/distiller/Library/Caches/pypoetry/virtualenvs

      - restore_cache:
          key: get-tor-macos-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Get tor binaries from Tor Browser
          command: |
            cd desktop
            poetry run python ./scripts/get-tor.py macos
      - save_cache:
          key: get-tor-macos-{{ checksum "desktop/scripts/get-tor.py" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - ~/project/desktop/build/tor

      - restore_cache:
          key: build-macos-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.sh" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Build obfs4proxy
          command: |
            if [[ -f "/Users/distiller/project/desktop/onionshare/resources/tor/obfs4proxy" ]]; then
              echo "obfs4proxy already built"
            else
              cd /Users/distiller/project/desktop
              ./scripts/build-pt-obfs4proxy.sh
            fi
      - save_cache:
          key: build-macos-obfs4proxy-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.sh" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - /Users/distiller/project/desktop/onionshare/resources/tor/obfs4proxy

      - restore_cache:
          key: build-macos-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.sh" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Build snowflake
          command: |
            if [[ -f "/Users/distiller/project/desktop/onionshare/resources/tor/snowflake-client" ]]; then
              echo "snowflake already built"
            else
              cd /Users/distiller/project/desktop
              ./scripts/build-pt-snowflake.sh
            fi
      - save_cache:
          key: build-macos-snowflake-{{ checksum "~/project/desktop/scripts/build-pt-snowflake.sh" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - ~/project/desktop/onionshare/resources/tor/snowflake-client

      - restore_cache:
          key: build-macos-meek-{{ checksum "~/project/desktop/scripts/build-pt-obfs4proxy.sh" }}-{{ .Environment.CACHE_VERSION }}
      - run:
          name: Build meek
          command: |
            if [[ -f "/Users/distiller/project/desktop/onionshare/resources/tor/meek-client" ]]; then
              echo "meek already built"
            else
              cd /Users/distiller/project/desktop
              ./scripts/build-pt-meek.sh
            fi
      - save_cache:
          key: build-macos-meek-{{ checksum "~/project/desktop/scripts/build-pt-meek.sh" }}-{{ .Environment.CACHE_VERSION }}
          paths:
            - ~/project/desktop/onionshare/resources/tor/meek-client

      - 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
            tar -czvf ~/onionshare-macos.tar.gz OnionShare.app

      - store_artifacts:
          path: ~/onionshare-macos.tar.gz