version: 2.1

# How to test the Linux jobs:
#   - Install CircleCI local CLI: https://circleci.com/docs/2.0/local-cli/
#   - circleci config process .circleci/config.yml > gen.yml && circleci local execute -c gen.yml --job binary_linux_wheel_py3.8
#     - Replace binary_linux_wheel_py3.8 with the name of the job you want to test.
#       Job names are 'name:' key.

executors:
  windows-cpu:
    machine:
      resource_class: windows.xlarge
      image: windows-server-2019-vs2019:stable
      shell: bash.exe

  windows-gpu:
    machine:
      resource_class: windows.gpu.nvidia.medium
      image: windows-server-2019-nvidia:stable
      shell: bash.exe

commands:
  generate_cache_key:
    description: "Generates a cache key file that changes daily"
    steps:
      - run:
          name: Generate cache key
          command: echo "$(date +"%Y-%m-%d")" > .cachekey
  designate_upload_channel:
    description: "inserts the correct upload channel into ${BASH_ENV}"
    steps:
      - run:
          name: adding UPLOAD_CHANNEL to BASH_ENV
          command: |
            our_upload_channel=nightly
            # On tags upload to test instead
            if [[ -n "${CIRCLE_TAG}" ]] || [[ ${CIRCLE_BRANCH} =~ release/* ]]; then
              our_upload_channel=test
            fi
            echo "export UPLOAD_CHANNEL=${our_upload_channel}" >> ${BASH_ENV}
  load_conda_channel_flags:
    description: "Determines whether we need extra conda channels"
    steps:
      - run:
          name: Adding CONDA_CHANNEL_FLAGS to BASH_ENV
          command: |
              CONDA_CHANNEL_FLAGS=""
              # formerly used to add conda-forge flags for Python 3.9, reserving the mechanism for future python upgrades
  windows_install_cuda:
    description: "Install desired CUDA version on Windows runners"
    steps:
      - run:
          name: Install CUDA
          command: |
              packaging/windows/internal/cuda_install.bat

binary_common: &binary_common
  parameters:
    # Edit these defaults to do a release
    build_version:
      description: "version number of release binary; by default, build a nightly"
      type: string
      default: ""
    pytorch_version:
      description: "PyTorch version to build against; by default, use a nightly"
      type: string
      default: ""
    # Don't edit these
    python_version:
      description: "Python version to build against (e.g., 3.8)"
      type: string
    cuda_version:
      description: "CUDA version to build against (e.g., cpu, cu101)"
      type: string
      default: "cpu"
    wheel_docker_image:
      description: "Wheel only: what docker image to use"
      type: string
      default: "pytorch/manylinux-cuda116"
    conda_docker_image:
      description: "Conda only: what docker image to use"
      type: string
      default: "pytorch/conda-builder:cuda116"
  environment: &environment
    PYTHON_VERSION: << parameters.python_version >>
    BUILD_VERSION: << parameters.build_version >>
    PYTORCH_VERSION: << parameters.pytorch_version >>
    CU_VERSION: << parameters.cuda_version >>
    MACOSX_DEPLOYMENT_TARGET: 10.9

smoke_test_common: &smoke_test_common
  <<: *binary_common
  docker:
    - image: pytorch/torchaudio_unittest_base:smoke_test-20220425
  resource_class: large

jobs:
  circleci_consistency:
    docker:
      - image: cimg/python:3.8
    steps:
      - checkout
      - run:
          command: |
            pip install --user --progress-bar off jinja2 pyyaml
            python .circleci/regenerate.py
            git diff --exit-code || (echo ".circleci/config.yml not in sync with config.yml.in! Run .circleci/regenerate.py to update config"; exit 1)

  lint_python_and_config:
    docker:
      - image: circleci/python:3.8
    steps:
      - checkout
      - run:
          name: Install pre-commit
          command: pip install --user --progress-bar off pre-commit
      - run:
          name: Install pre-commit hooks
          command: pre-commit install-hooks
      - run:
          name: Lint Python code and config files
          command: pre-commit run --all-files
      - run:
          name: Required lint modifications
          when: always
          command: git --no-pager diff --color=always

  download_third_parties:
    docker:
      - image: "pytorch/torchaudio_unittest_base:manylinux"
    resource_class: small
    steps:
      - checkout
      - generate_cache_key
      - restore_cache:
          {% raw %}
          keys:
            - tp-nix-v2-{{ checksum ".cachekey" }}
          {% endraw %}
      - run:
          command: |
              mkdir -p third_party/archives/
              wget --no-clobber --directory-prefix=third_party/archives/ $(awk '/URL /{print $2}' third_party/*/CMakeLists.txt)
      - save_cache:
          {% raw %}
          key: tp-nix-v2-{{ checksum ".cachekey" }}
          {% endraw %}
          paths:
            - third_party/archives
      - persist_to_workspace:
          root: third_party
          paths:
            - archives

  build_ffmpeg_linux:
    <<: *binary_common
    docker:
      - image: << parameters.wheel_docker_image >>
    resource_class: 2xlarge+
    steps:
      - checkout
      - generate_cache_key
      - restore_cache:
          {% raw %}
          keys:
            - ffmpeg-linux-v0-{{ checksum ".cachekey" }}
          {% endraw %}
      - run:
          command: |
            export FFMPEG_ROOT=${PWD}/third_party/ffmpeg
            if [[ ! -d ${FFMPEG_ROOT} ]]; then
                packaging/ffmpeg/build.sh
            fi
      - save_cache:
          {% raw %}
          key: ffmpeg-linux-v0-{{ checksum ".cachekey" }}
          {% endraw %}
          paths:
            - third_party/ffmpeg
      - persist_to_workspace:
          root: third_party
          paths:
            - ffmpeg

  build_ffmpeg_macos:
    <<: *binary_common
    macos:
      xcode: "14.0"
    steps:
      - checkout
      - generate_cache_key
      - restore_cache:
          {% raw %}
          keys:
            - ffmpeg-macos-v0-{{ checksum ".cachekey" }}
          {% endraw %}
      - run:
          command: |
            export FFMPEG_ROOT=${PWD}/third_party/ffmpeg
            if [[ ! -d ${FFMPEG_ROOT} ]]; then
                packaging/ffmpeg/build.sh
            fi
      - save_cache:
          {% raw %}
          key: ffmpeg-macos-v0-{{ checksum ".cachekey" }}
          {% endraw %}
          paths:
            - third_party/ffmpeg
      - persist_to_workspace:
          root: third_party
          paths:
            - ffmpeg

  build_ffmpeg_windows:
    <<: *binary_common
    machine:
      resource_class: windows.xlarge
      image: windows-server-2019-vs2019:stable
      # Note:
      # Unlike other Windows job, this job uses cmd.exe as shell because
      # we need to invoke bash.exe from msys2 in ffmpeg build process, and doing so
      # from different installation of bash.exe (the one from the VM) cause issue
      shell: cmd.exe
    steps:
      - checkout
      - run: date /t > .cachekey
      - restore_cache:
          {% raw %}
          keys:
            - ffmpeg-windows-{{ checksum ".cachekey" }}
          {% endraw %}
      - run: packaging\ffmpeg\build.bat
      - save_cache:
          {% raw %}
          key: ffmpeg-windows-{{ checksum ".cachekey" }}
          {% endraw %}
          paths:
            - third_party/ffmpeg
      - persist_to_workspace:
          root: third_party
          paths:
            - ffmpeg

  binary_linux_wheel:
    <<: *binary_common
    docker:
      - image: << parameters.wheel_docker_image >>
    resource_class: 2xlarge+
    steps:
      - checkout
      - attach_workspace:
          at: third_party
      - run:
          command: |
            export FFMPEG_ROOT=${PWD}/third_party/ffmpeg
            packaging/build_wheel.sh
          environment:
            USE_FFMPEG: true
      - store_artifacts:
          path: dist
      - persist_to_workspace:
          root: dist
          paths:
            - "*"

  binary_linux_conda:
    <<: *binary_common
    docker:
      - image: "<< parameters.conda_docker_image >>"
    resource_class: 2xlarge+
    steps:
      - checkout
      - load_conda_channel_flags
      - attach_workspace:
          at: third_party
      - run:
          name: Build conda packages
          no_output_timeout: 30m
          command: |
            export FFMPEG_ROOT=${PWD}/third_party/ffmpeg
            packaging/build_conda.sh
          environment:
            USE_FFMPEG: true
      - store_artifacts:
          path: /opt/conda/conda-bld/linux-64
      - persist_to_workspace:
          root: /opt/conda
          paths:
            - "conda-bld/*"

  binary_macos_wheel:
    <<: *binary_common
    macos:
      xcode: "14.0"
    steps:
      - checkout
      - load_conda_channel_flags
      - attach_workspace:
          at: third_party
      - run:
          # Cannot easily deduplicate this as source'ing activate
          # will set environment variables which we need to propagate
          # to build_wheel.sh
          command: |
            curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
            sh conda.sh -b
            source $HOME/miniconda3/bin/activate
            export FFMPEG_ROOT="${PWD}/third_party/ffmpeg"
            packaging/build_wheel.sh
          environment:
            USE_FFMPEG: true
            USE_OPENMP: false
      - store_artifacts:
          path: dist
      - persist_to_workspace:
          root: dist
          paths:
            - "*"

  binary_macos_conda:
    <<: *binary_common
    macos:
      xcode: "14.0"
    steps:
      - checkout
      - load_conda_channel_flags
      - attach_workspace:
          at: third_party
      - run:
          command: |
            curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
            sh conda.sh -b
            source $HOME/miniconda3/bin/activate
            conda install -yq conda-build
            export FFMPEG_ROOT="${PWD}/third_party/ffmpeg"
            packaging/build_conda.sh
          environment:
            USE_FFMPEG: true
            USE_OPENMP: false
      - store_artifacts:
          path: /Users/distiller/miniconda3/conda-bld/osx-64
      - persist_to_workspace:
          root: /Users/distiller/miniconda3
          paths:
            - "conda-bld/*"

  binary_windows_wheel:
    <<: *binary_common
    executor:
      name: windows-cpu
    steps:
      - checkout
      - load_conda_channel_flags
      - windows_install_cuda
      - attach_workspace:
          at: third_party
      - run:
          name: Build wheel packages
          no_output_timeout: 30m
          command: |
            set -ex
            eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')"
            conda activate base
            export FFMPEG_ROOT="${PWD}/third_party/ffmpeg"
            bash packaging/build_wheel.sh
          environment:
            USE_FFMPEG: true
      - store_artifacts:
          path: dist
      - persist_to_workspace:
          root: dist
          paths:
            - "*"

  binary_windows_conda:
    <<: *binary_common
    executor:
      name: windows-cpu
    steps:
      - checkout
      - load_conda_channel_flags
      - windows_install_cuda
      - attach_workspace:
          at: third_party
      - run:
          name: Build conda packages
          no_output_timeout: 30m
          command: |
            set -ex
            eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')"
            conda activate base
            conda install -yq conda-build "conda-package-handling!=1.5.0"
            export FFMPEG_ROOT="${PWD}/third_party/ffmpeg"
            bash packaging/build_conda.sh
          environment:
            USE_FFMPEG: true
      - store_artifacts:
          path: C:/tools/miniconda3/conda-bld/win-64
      - persist_to_workspace:
          root: C:/tools/miniconda3
          paths:
            - "conda-bld/*"

  # Requires org-member context
  binary_conda_upload:
    docker:
      - image: continuumio/miniconda
    steps:
      - attach_workspace:
          at: ~/workspace
      - designate_upload_channel
      - run:
          command: |
            # Prevent credential from leaking
            conda install -yq anaconda-client
            set -x
            anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/conda-bld/*/*.tar.bz2 -u "pytorch-${UPLOAD_CHANNEL}" --label main --no-progress --force

  # Requires org-member context
  binary_wheel_upload:
    parameters:
      subfolder:
        description: "What whl subfolder to upload to, e.g., blank or cu100/ (trailing slash is important)"
        type: string
    docker:
      - image: cimg/python:3.8
    steps:
      - attach_workspace:
          at: ~/workspace
      - checkout
      - designate_upload_channel
      - run:
          command: |
            pip install --user awscli
            export PATH="$HOME/.local/bin:$PATH"
            # Prevent credential from leaking
            set +x
            export AWS_ACCESS_KEY_ID="${PYTORCH_BINARY_AWS_ACCESS_KEY_ID}"
            export AWS_SECRET_ACCESS_KEY="${PYTORCH_BINARY_AWS_SECRET_ACCESS_KEY}"
            set -x
            for pkg in ~/workspace/*.whl; do
              aws s3 cp "$pkg" "s3://pytorch/whl/${UPLOAD_CHANNEL}/<< parameters.subfolder >>" --acl public-read
            done

  smoke_test_linux_conda:
    <<: *smoke_test_common
    steps:
      - attach_workspace:
          at: ~/workspace
      - designate_upload_channel
      - load_conda_channel_flags
      - run:
          name: install binaries
          no_output_timeout: 30m
          command: |
            set -x
            source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION}
            conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch cpuonly
            conda install -v -y -c file://$HOME/workspace/conda-bld torchaudio
      - checkout
      - run:
          name: smoke test
          command: |
            source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION}
            conda install 'ffmpeg<5'
            ./test/smoke_test/run_smoke_test.sh

  smoke_test_linux_conda_gpu:
    <<: *smoke_test_common
    steps:
      - attach_workspace:
          at: ~/workspace
      - designate_upload_channel
      - load_conda_channel_flags
      - run:
          name: install binaries
          no_output_timeout: 30m
          command: |
            set -x
            source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION}
            if [[ "$CU_VERSION" == cu116 || "$CU_VERSION" == cu117 || "$CU_VERSION" == cu118 ]]; then
              conda install -v -y -c pytorch-${UPLOAD_CHANNEL} -c nvidia pytorch pytorch-cuda=${CU_VERSION:2:2}.${CU_VERSION:4}
            else
              conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch cudatoolkit=${CU_VERSION:2:2}.${CU_VERSION:4}
            fi
            conda install -v -y -c file://$HOME/workspace/conda-bld torchaudio
      - checkout
      - run:
          name: smoke test
          command: |
            source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION}
            conda install 'ffmpeg<5'
            ./test/smoke_test/run_smoke_test.sh

  smoke_test_linux_pip:
    <<: *smoke_test_common
    steps:
      - attach_workspace:
          at: ~/workspace
      - designate_upload_channel
      - load_conda_channel_flags
      - run:
          name: install binaries
          no_output_timeout: 30m
          command: |
            set -x
            source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION}
            pip install $(ls ~/workspace/torchaudio*.whl) -f "https://download.pytorch.org/whl/${UPLOAD_CHANNEL}/${CU_VERSION}/torch_${UPLOAD_CHANNEL}.html"
      - checkout
      - run:
          name: smoke test
          command: |
            source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION}
            export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${HOME}/workspace/ffmpeg/lib"
            ./test/smoke_test/run_smoke_test.sh

  smoke_test_windows_conda:
    <<: *binary_common
    executor:
      name: windows-cpu
    steps:
      - attach_workspace:
          at: ~/workspace
      - designate_upload_channel
      - load_conda_channel_flags
      - run:
          name: install binaries
          no_output_timeout: 30m
          command: |
            set -x
            eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')"
            conda update -y conda
            conda env remove -n python${PYTHON_VERSION} || true
            conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION}
            conda activate python${PYTHON_VERSION}
            if [[ "${PYTHON_VERSION}" == "3.11" ]]; then
              export CONDA_CHANNEL_FLAGS=" -c malfet"
            fi
            conda install -v -y ${CONDA_CHANNEL_FLAGS:-} -c pytorch-${UPLOAD_CHANNEL} pytorch cpuonly
            conda install -v -y $(ls ~/workspace/conda-bld/win-64/torchaudio*.tar.bz2)
      - checkout
      - run:
          name: smoke test
          command: |
            eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')"
            conda activate python${PYTHON_VERSION}
            if [[ "${PYTHON_VERSION}" == "3.11" ]]; then
              conda install -c conda-forge ffmpeg=4.4.2
            else
              conda install 'ffmpeg<5'
            fi
            ./test/smoke_test/run_smoke_test.sh

  smoke_test_windows_conda_gpu:
    <<: *binary_common
    executor:
      name: windows-gpu
    steps:
      - checkout
      - attach_workspace:
          at: ~/workspace
      - designate_upload_channel
      - load_conda_channel_flags
      - windows_install_cuda
      - run:
          name: Update CUDA driver
          command: packaging/windows/internal/driver_update.bat
      - run:
          name: install binaries
          no_output_timeout: 30m
          command: |
            set -x
            eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')"
            conda update -y conda
            conda env remove -n python${PYTHON_VERSION} || true
            conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION}
            conda activate python${PYTHON_VERSION}
            # Include numpy and cudatoolkit in the install conda-forge chanell is used for cudatoolkit
            if [[ "${PYTHON_VERSION}" == "3.11" ]]; then
              export CONDA_CHANNEL_FLAGS=" -c malfet"
            fi

            if [[ "$CU_VERSION" == cu116 || "$CU_VERSION" == cu117 || "$CU_VERSION" == cu118 ]]; then
              conda install -v -y ${CONDA_CHANNEL_FLAGS:-} -c pytorch-${UPLOAD_CHANNEL} -c nvidia pytorch numpy ffmpeg pytorch-cuda=${CU_VERSION:2:2}.${CU_VERSION:4}
            else
              conda install -v -y ${CONDA_CHANNEL_FLAGS:-} -c pytorch-${UPLOAD_CHANNEL} pytorch numpy ffmpeg cudatoolkit=${CU_VERSION:2:2}.${CU_VERSION:4}
            fi
            # Install from torchaudio file
            conda install -v -y $(ls ~/workspace/conda-bld/win-64/torchaudio*.tar.bz2)
      - run:
          name: smoke test
          command: |
            eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')"
            conda activate python${PYTHON_VERSION}
            # Install sound backend
            pip install PySoundFile
            ./test/smoke_test/run_smoke_test.sh

  smoke_test_windows_pip:
    <<: *binary_common
    executor:
      name: windows-cpu
    steps:
      - attach_workspace:
          at: ~/workspace
      - designate_upload_channel
      - load_conda_channel_flags
      - run:
          name: install binaries
          no_output_timeout: 30m
          command: |
            set -x
            eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')"
            conda update -y conda
            conda env remove -n python${PYTHON_VERSION} || true
            conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION}
            conda activate python${PYTHON_VERSION}
            pip install $(ls ~/workspace/torchaudio*.whl) -f "https://download.pytorch.org/whl/${UPLOAD_CHANNEL}/${CU_VERSION}/torch_${UPLOAD_CHANNEL}.html"
      - checkout
      - run:
          name: smoke test
          command: |
            eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')"
            conda activate python${PYTHON_VERSION}
            # Hack to load FFmpeg libraries
            # Note: Depending on Python version, they search different paths.
            # For 3.9, copying them in CWD works.
            cp ~/workspace/ffmpeg/bin/* test/smoke_test/
            # For 3.8 and 3.10, they must be in the same directory as the entrypoint lib
            cp ~/workspace/ffmpeg/bin/* /C/tools/miniconda3/envs/python${PYTHON_VERSION}/lib/site-packages/torchaudio/lib/
            ./test/smoke_test/run_smoke_test.sh

  unittest_linux_cpu:
    <<: *binary_common
    docker:
      - image: pytorch/torchaudio_unittest_base:manylinux-20210121
    resource_class: 2xlarge+
    steps:
      - checkout
      - attach_workspace:
          at: third_party
      - designate_upload_channel
      - load_conda_channel_flags
      - run:
          name: Setup
          command: .circleci/unittest/linux/scripts/setup_env.sh
      - run:
          name: Install torchaudio
          command: .circleci/unittest/linux/scripts/install.sh
          environment:
              USE_FFMPEG: true
      - run:
          name: Run tests
          command: .circleci/unittest/linux/scripts/run_test.sh
          environment:
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CUDA: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_HW_ACCEL: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_ON_PYTHON_310: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_AUDIO_OUT_DEVICE: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_MACOS: true
      - store_test_results:
          path: test-results
      - store_artifacts:
          path: test/htmlcov

  unittest_linux_gpu:
    <<: *binary_common
    machine:
      image: ubuntu-2004-cuda-11.4:202110-01
    resource_class: gpu.nvidia.medium
    environment:
      <<: *environment
      CUDA_VERSION: 11.7
      image_name: pytorch/torchaudio_unittest_base:manylinux-cuda10.2-cudnn8-20210623
    steps:
      - checkout
      - attach_workspace:
          at: third_party
      - designate_upload_channel
      - load_conda_channel_flags
      - run:
          name: Pull Docker image
          command: docker pull --quiet "${image_name}"
      - run:
          name: Setup
          command: docker run -t --gpus all -e PYTHON_VERSION -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh
      - run:
          name: Install torchaudio
          command: docker run -t --gpus all -e UPLOAD_CHANNEL -e CONDA_CHANNEL_FLAGS -e CUDA_VERSION -e USE_FFMPEG=1 -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/install.sh
      - run:
          name: Run tests
          environment:
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_HW_ACCEL: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_ON_PYTHON_310: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_CUDA_SMALL_MEMORY: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_MACOS: true
          command: |
            docker run -t --gpus all -v $PWD:$PWD -w $PWD -e "CI=${CI}" -e TORCHAUDIO_TEST_ALLOW_SKIP_IF_ON_PYTHON_310 -e TORCHAUDIO_TEST_ALLOW_SKIP_IF_CUDA_SMALL_MEMORY -e TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_MACOS -e TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_HW_ACCEL "${image_name}" .circleci/unittest/linux/scripts/run_test.sh
      - store_test_results:
          path: test-results
      - store_artifacts:
          path: test/htmlcov

  unittest_windows_cpu:
    <<: *binary_common
    executor:
      name: windows-cpu
    steps:
      - checkout
      - designate_upload_channel
      - load_conda_channel_flags
      - run:
          name: Setup
          command: .circleci/unittest/windows/scripts/setup_env.sh
      - run:
          name: Install torchaudio
          command: .circleci/unittest/windows/scripts/install.sh
          environment:
              USE_FFMPEG: true
      - run:
          name: Run tests
          command: .circleci/unittest/windows/scripts/run_test.sh
          environment:
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_APPLY_CMVN_SLIDING: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_FBANK_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_KALDI_PITCH_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_MFCC_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_SPECTROGRAM_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_SOX: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CUDA: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_HW_ACCEL: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_KALDI: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_SOX: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_ON_PYTHON_310: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_MOD_sentencepiece: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_AUDIO_OUT_DEVICE: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_MACOS: true
      - store_test_results:
          path: test-results
      - store_artifacts:
          path: test/htmlcov

  unittest_windows_gpu:
    <<: *binary_common
    executor:
      name: windows-gpu
    environment:
      <<: *environment
      CUDA_VERSION: "11.7"
    steps:
      - checkout
      - designate_upload_channel
      - load_conda_channel_flags
      - run:
          name: Setup
          command: .circleci/unittest/windows/scripts/setup_env.sh
      - run:
          name: Install CUDA
          command: packaging/windows/internal/cuda_install.bat
      - run:
          name: Update CUDA driver
          command: packaging/windows/internal/driver_update.bat
      - run:
          name: Install torchaudio
          command: .circleci/unittest/windows/scripts/install.sh
          environment:
              USE_FFMPEG: true
      - run:
          name: Run tests
          command: .circleci/unittest/windows/scripts/run_test.sh
          environment:
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_APPLY_CMVN_SLIDING: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_FBANK_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_KALDI_PITCH_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_MFCC_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_SPECTROGRAM_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_SOX: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_KALDI: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_SOX: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_ON_PYTHON_310: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_MOD_sentencepiece: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_CUDA_SMALL_MEMORY: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_AUDIO_OUT_DEVICE: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_MACOS: true
      - store_test_results:
          path: test-results
      - store_artifacts:
          path: test/htmlcov

  unittest_macos_cpu:
    <<: *binary_common
    macos:
      xcode: "14.0"
    resource_class: large
    steps:
      - checkout
      - load_conda_channel_flags
      - attach_workspace:
          at: third_party
      - designate_upload_channel
      - run:
          name: Setup
          command: .circleci/unittest/linux/scripts/setup_env.sh
      - run:
          name: Install torchaudio
          command: .circleci/unittest/linux/scripts/install.sh
          environment:
              USE_FFMPEG: true
              USE_OPENMP: false
      - run:
          name: Run tests
          command: .circleci/unittest/linux/scripts/run_test.sh
          environment:
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_APPLY_CMVN_SLIDING: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_FBANK_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_KALDI_PITCH_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_MFCC_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CMD_COMPUTE_SPECTROGRAM_FEATS: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_CUDA: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_HW_ACCEL: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_QUANTIZATION: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_ON_PYTHON_310: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_MOD_sentencepiece: true
              TORCHAUDIO_TEST_ALLOW_SKIP_IF_NO_AUDIO_OUT_DEVICE: true
      - store_test_results:
          path: test-results
      - store_artifacts:
          path: test/htmlcov

  stylecheck:
    <<: *binary_common
    docker:
      - image: "pytorch/torchaudio_unittest_base:manylinux"
    resource_class: medium
    steps:
      - checkout
      - designate_upload_channel
      - load_conda_channel_flags
      - run:
          name: Setup
          command: .circleci/unittest/linux/scripts/setup_env.sh
      - run:
          name: Run style check
          command: .circleci/unittest/linux/scripts/run_style_checks.sh

  build_docs:
    <<: *smoke_test_common
    resource_class: 2xlarge+
    steps:
      - attach_workspace:
          at: ~/workspace
      - checkout
      - designate_upload_channel
      - load_conda_channel_flags
      - run:
          name: Install packages
          command: |
            set -x
            source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION}
            if [[ "$CU_VERSION" == cu116 || "$CU_VERSION" == cu117 || "$CU_VERSION" == cu118 ]]; then
              conda install -v -y -c pytorch-${UPLOAD_CHANNEL} -c nvidia pytorch pytorch-cuda=${CU_VERSION:2:2}.${CU_VERSION:4}
            else
              conda install -v -y -c pytorch-${UPLOAD_CHANNEL} pytorch cudatoolkit=${CU_VERSION:2:2}.${CU_VERSION:4}
            fi
            conda install -v -y -c file://$HOME/workspace/conda-bld torchaudio
            # gxx_linux-64 is for installing pesq library that depends on cython
            conda install -y pandoc 'ffmpeg<5' gxx_linux-64 git make
            conda install -y -c conda-forge doxygen
            pip install --progress-bar off -r docs/requirements.txt -r docs/requirements-tutorials.txt
      - run:
          name: Build docs
          command: |
            source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION}
            cd docs
            make 'SPHINXOPTS=-W' html
            cd build
            tar -czf artifact.tar.gz html
            mv artifact.tar.gz html
          environment:
            BUILD_GALLERY: 1
            TORCH_SHOW_CPP_STACKTRACES: 1
          no_output_timeout: 60m
      - persist_to_workspace:
          root: ./
          paths:
            - "*"
      - store_artifacts:
          path: ./docs/build/html
          destination: docs

  upload_docs:
    <<: *binary_common
    docker:
      - image: "pytorch/manylinux-cuda100"
    resource_class: 2xlarge+
    steps:
      - attach_workspace:
          at: ~/workspace
      - run:
          name: Generate netrc
          command: |
            # set credentials for https pushing
            # requires the org-member context
            cat > ~/.netrc \<<DONE
              machine github.com
              login pytorchbot
              password ${GITHUB_PYTORCHBOT_TOKEN}
            DONE
      - run:
          name: Upload docs
          command: |
            # Don't use "checkout" step since it uses ssh, which cannot git push
            # https://circleci.com/docs/2.0/configuration-reference/#checkout
            set -ex
            # turn v1.12.0rc3 into 1.12.0
            tag=$(echo $CIRCLE_TAG | sed -e 's/v*\([0-9.]*\).*/\1/')
            target=${tag:-main}
            ~/workspace/.circleci/build_docs/commit_docs.sh ~/workspace $target

  docstring_parameters_sync:
    <<: *binary_common
    docker:
      - image: cimg/python:3.8
    steps:
      - checkout
      - run:
          name: Check parameters docstring sync
          command: |
            pip install --user pydocstyle
            pydocstyle torchaudio

workflows:
  lint:
    jobs:
      - lint_python_and_config
  build:
    jobs:
      - circleci_consistency
      {{ build_workflows() }}
  unittest:
    jobs:
      {{ unittest_workflows() }}
  nightly:
    jobs:
      - circleci_consistency:
          filters:
            branches:
              only: nightly
      {{ build_workflows(prefix="nightly_", filter_branch="nightly", upload=True) }}
