[Python / Conda / Github Actions] conda で requirement.txt に記載されたパッケージインストールし、GitHub Actions で自動テストを行いたい時

# 概要

タイトルの通りです。
結構大変だったので、共有したいと思います。

# Dependencies

item|version
--|--
python|3.10.x
package manager|miniforge 24.3.0-0
test library|pytest 8.0.0


# ディレクトリ構造 (参考)

こんな感じのディレクトリ構造にしているよ。

```bash
./<APP_ROOT>
    ├── environments/
    │    └── python-env/
    │   　    └── requirements.txt
    ├── src/
    └── tests/
```

ローカルマシンでは、 `conda install -c conda-forge --yes --file environments/python-env/requirements.txt` を実行して、python モジュールをインストールしている。
それを踏まえて、以下のように workflows ファイルを作成している。

# ソースコード

全体は以下のようにしたところ、テストが通過した。

```yaml:.github/workflows/pytest.yml
name: Pytest

on:
  push:

jobs:
  pytest:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      # ここで conda を用意 (自分の場合は miniforge と conda-forge チャンネルを利用)
      - uses: conda-incubator/setup-miniconda@v3
        with:
          auto-activate-base: true
          # NOTE: ここは true じゃないと動かないっぽい
          activate-environment: true
          channels: conda-forge
          miniforge-version: 24.3.0-0
          python-version: "3.10"
          show-channel-urls: true
          # NOTE: ここは false じゃないと動かないっぽい
          use-only-tar-bz2: false

      - name: Install dependencies
        shell: bash -l {0}
        run: conda install -c conda-forge --yes --file environments/python-env/requirements.txt

      - name: pytest
        # Refer to: https://stackoverflow.com/questions/63593086/pytest-not-found-when-running-from-a-conda-environment-in-github-actions
        shell: bash -l {0}
        run: pytest --tb=line ./tests/
        env:
          PYTHONPATH: src

```

## ポイント

### 1. `uses: conda-incubator/setup-miniconda@v3`

最初は `uses: goanpeca/setup-miniconda@v1` を利用していたのだけれど、その際は以下のようなエラーが発生していた。

```bash
# Setup environment variables...
################################

Add "/usr/share/miniconda/condabin" to PATH
Error: Unable to process command '::add-path::/usr/share/miniconda/condabin' successfully.
Error: The `add-path` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/
/usr/share/miniconda/condabin/conda config --add pkgs_dirs /home/runner/conda_pkgs_dir
Error: Unable to process command '::set-env name=CONDA_PKGS_DIR::/home/runner/conda_pkgs_dir' successfully.
Error: The `set-env` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/
```

`goanpeca/setup-miniconda` はもう古いらしい。以下の GitHub issue に書かれていた。

> SOLUTION: Simply update your goanpeca/setup-miniconda@v1 hook to conda-incubator/setup-miniconda@v2 and the error should go away.
>
> https://github.com/conda-incubator/setup-miniconda/issues/101


### 2. `activate-environment: true`

最初は、 `activate-environment: ""` にしていたのだけれど、その場合は以下のようなエラーが発生した。

> `Error: 'python-version: 3.10' requires 'activate-environment: true'`

### 3. `use-only-tar-bz2: false`

最初は `use-only-tar-bz2: true` にしていたのだけど、その時は以下のようなエラーが発生していた。

```bash
PackagesNotFoundError: The following packages are not available from current channels:

  - seaborn==0.13.1
  - pytest-cov==5.0.0
  - pytest==8.0.0

  ...

  - mamba[version='>=1.5.8']

Current channels:

  - https://conda.anaconda.org/conda-forge
  - defaults

To search for alternate channels that may provide the conda package you're
looking for, navigate to

    https://anaconda.org

and use the search bar at the top of the page.
Note: 'use_only_tar_bz2' is enabled. This might be omitting some
packages from the index. Set this option to 'false' and retry.
```

どうやら、 `'use_only_tar_bz2'` が true だと、いくつかのパッケージがインストールできなくなってしまうらしい。


### 4. `channel-priority: flexible` (もしくはセットしない)

最初は `channel-priority: strict` にしていたのだけれど、その時は以下のようなエラーが発生した。

```bash
LibMambaUnsatisfiableError: Encountered problems while solving:
  - nothing provides requested seaborn 0.13.1
  - nothing provides requested pytest-cov 5.0.0
  - nothing provides requested pytest 8.0.0

  ...

  - package numpy-1.26.4-py39heeff2f4_0 is excluded by strict repo priority
  - package tqdm-4.66.2-py39h2f386ee_0 is excluded by strict repo priority
  - package conda-24.7.1-py39h06a4308_0 is excluded by strict repo priority
```

`strict` だと、色々なパッケージがインストールできないらしい。

ただ、 [`use-only-tar-bz2: true` でないとpythonライブラリのキャッシュが効かないっぽい](https://github.com/conda-incubator/setup-miniconda?tab=readme-ov-file#caching)ので、そこはちょっとつらみ( ˘ω˘)


### 5. `shell: bash -l {0}`

パッケージインストール (`conda install`) の step と、 pytest を実行する step の双方において、 `shell: bash -l {0}` を設定しないと、 `pytest` のコマンドが `not found` になってしまうので注意。

`shell: bash -l {0}` を設定していないときは、以下のようなエラーが発生していた。

> `pytest: command not found`
>
> https://stackoverflow.com/questions/63593086/pytest-not-found-when-running-from-a-conda-environment-in-github-actions


### 6. 各パッケージのバージョン

conda (miniforge) のバージョンと、 conda でインストールするライブラリのバージョンはよく確認しよう。
開発環境でインストールできていたとしても、 GitHub Actions 上で異なるバージョンが利用されていたりすることがあり、その場合はpythonパッケージインストールに失敗しがちになる。


### 7. requirements.txt に日本語は書かない (OS が windows の場合)

実行環境 (OS や platform) が Windows の場合は、たとえコメント文であろうと、 `requirements.txt` に日本語があるだけでこんなエラーになる。

```bash:error
Run conda install -c conda-forge --yes --file environments/python-env/requirements.txt

CondaError: Error reading file, file should be a text file containing packages 
conda create --help for details

Error: Process completed with exit code 1.
```

日本語 (マルチバイト文字) は徹底排除！


# References

## setup-miniconda の公式 document

https://github.com/conda-incubator/setup-miniconda?tab=readme-ov-file#conda-incubatorsetup-miniconda

## StackOverflow

https://stackoverflow.com/questions/63593086/pytest-not-found-when-running-from-a-conda-environment-in-github-actions

`shell: bash -l {0}` の必要性はここで把握した。