Pin dependencies version in CI with lock files with a bot that auto-updates the lockfiles

### Motivation

- avoid CI breakage due to dependencies updates (recent examples: setuptools update, pytest7 update, coverage 6.3 update, very likely others ...)
- avoid painful debugging when a breakage happens to figure out what is the cause of the problem and generally end up after some time that a dependency has changed
- avoid breaking everyone PRs which is confusing for contributers

### Ideas for implementation

- have environment.yml files for each build rather than versions defined in azure/Circle .yml (for the build using build, we can either use  poetry or conda-lock is supposed to support pip section in the environment.yml although I have not managed to get it to work yet)
- have a script using [conda-lock](https://github.com/conda-incubator/conda-lock) to regenerates conda lock files for each build based on their environment.yml
- have a bot that runs this script updates the lock files and creates a PR, it seems like using an approach using GH action like  Hypothesis does could work:
  https://github.com/HypothesisWorks/hypothesis/commit/c96bbc86efbaa46a78bbb075a36869734dde76b9.
- Have this PR merged if CI passes
- only one PR opened at a time to avoid generating many PRs with the same diff. If there is already an open PR (based on a github label for example), push -f  to the PR branch

### Where to start

I'll probably try out this idea on one build first (e.g. one using conda-forge) to test it out, see how that works, and go from there.

cc @thomasjpfan in case you have some thoughs about this or you have already started working on something similar

### Rejected alternatives

In an ideal workd we would "just" use Dependabot but [it can spam forks](https://github.com/dependabot/dependabot-core/issues/2804) with PRs. Numpy has given up on it see for example [this](https://twitter.com/ralfgommers/status/1457023221841149955)

COMMENT:
> I guess if we don't use lock files we would need to write a custom script, which does not seem that straightforward to me.

If the lock files make it easier for updating then I am okay with lock files. I did a little testing with how `conda-lock` works for updating. (Note that `--update` was added in https://github.com/conda-incubator/conda-lock/pull/124 so one needs to install from source.) 

A possible workflow with lock files is to start with environment file that pins we care about, and minimum dependencies for everything else:

```yaml
name: test-environment
channels:
  - conda-forge
dependencies:
  - numpy=1.15.0
  - pytest>=5.0.1
```

We use this env file to generate the lock file and always use the lock-file in CI. A dependency updater bot will generate a new lock file and only create a PR if one of the direct dependencies are updated. (There cuold be many PRs if we update the lock file for indirect dependencies.) BTW we need to run `--update`  multiple times since it only works one package at a time.

<details><summary><b>Alternative solution with pinning environment.yml</b>

</summary>

Assuming a starting `environment.yml` with everything pinned

```yaml
name: test-environment
channels:
  - conda-forge
dependencies:
  - pytest=6.2.4
```

and running the following to create the lock file:

```bash
conda-lock -f environment.yml -p linux-64
```

To get `conda-lock --update pytest -p linux-64` to work, I removed the pin in `environment.yml`, to generate a new lock file. To actually generate a new `environment.yml`, I think we need to parse the lock file, get the new versions, and generate the `environment.yml` ourselves.

</details>

### Other solutions

1. hypothesis wraps [pip-tools](https://github.com/HypothesisWorks/hypothesis/blob/da699996b08e2be1c646071de2d61ca724e7d31e/tooling/src/hypothesistooling/__main__.py#L245-L261) and uses that to update a `requirements.txt` directly. (They use `requirements.txt` like a lock file)
2. Custom script that reads `environment.yml` and checks for direct dependencies we wish to update and generate a new `environment.yml` if any of them were updated. I know `pypi` has a [rest api](https://warehouse.pypa.io/api-reference/json.html) for package metadata and for conda we can use... `conda search pytest  --json`. There could be edge case with indirect dependencies that lock files help with, but I do not think it happens too often.

Labels: Build / CI