Repository: conda-forge/conda-smithy

Issue:
Remote-ci-setup handling cannot handle constraints anymore (since conda-smithy 3.26)
It seems that https://github.com/conda-forge/conda-smithy/commit/4a5ac16fc18281dd8e5922c13b333d31b50dd73f broke handling of `remote_ci_setup` setups that use constraints. For example, for compiler-rt, we need to use:
```yaml
remote_ci_setup:
  - conda-forge-ci-setup=3
  - py-lief<0.12
```

This will not rerender anymore with the newest conda-smithy (I tried various quoting and indentation patterns) -- from what I can tell this is due to
https://github.com/conda-forge/conda-smithy/blob/8ffa0d8f73e69dbcfe19c97c92b05e77187cad6a/conda_smithy/configure_feedstock.py#L2039-L2041
using `.name` unconditionally.

This has effectively made compiler-rt un-rerenderable (except with manual fixes), because we cannot remove the py-lief pin, since https://github.com/conda/conda-build/issues/4787 was only fixed in conda-build 3.26, which we still cannot pull into our CI due to https://github.com/conda-forge/boa-feedstock/issues/75. For a sample CI failure without the pin, see https://github.com/conda-forge/compiler-rt-feedstock/pull/83.

CC @jaimergp 

<details>
<summary>stacktrace</summary>

### Note the unbalanced quotes!

```
(builder) C:\Users\[...]\dev\conda-forge\compiler-rt-feedstock>conda smithy rerender
INFO:conda_smithy.configure_feedstock:Downloading conda-forge-pinning-2023.09.26.03.46.41
INFO:conda_smithy.configure_feedstock:Extracting conda-forge-pinning to C:\Users\[...]\AppData\Local\Temp\tmpjn62ot_j
Traceback (most recent call last):
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\version.py", line 43, in __call__
    return cls._cache_[arg]
KeyError: '<0.12"'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\version.py", line 43, in __call__
    return cls._cache_[arg]
KeyError: '0.12"'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\[...]\.conda\envs\builder\Scripts\conda-smithy-script.py", line 9, in <module>
    sys.exit(main())
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda_smithy\cli.py", line 669, in main
    args.subcommand_func(args)
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda_smithy\cli.py", line 485, in __call__
    self._call(args, tmpdir)
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda_smithy\cli.py", line 490, in _call
    configure_feedstock.main(
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda_smithy\configure_feedstock.py", line 2357, in main
    config = _load_forge_config(forge_dir, exclusive_config_file, forge_yml)
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda_smithy\configure_feedstock.py", line 2039, in _load_forge_config
    config["remote_ci_setup_names"] = [
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda_smithy\configure_feedstock.py", line 2040, in <listcomp>
    MatchSpec(pkg).name for pkg in config["remote_ci_setup"]
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\match_spec.py", line 55, in __call__
    return super().__call__(**parsed)
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\match_spec.py", line 179, in __init__
    self._match_components = self._build_components(**kwargs)
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\match_spec.py", line 414, in _build_components
    return frozendict(_make_component(key, value) for key, value in kwargs.items())
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\_vendor\frozendict\__init__.py", line 21, in __init__
    self._dict = self.dict_cls(*args, **kwargs)
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\match_spec.py", line 414, in <genexpr>
    return frozendict(_make_component(key, value) for key, value in kwargs.items())
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\match_spec.py", line 428, in _make_component
    matcher = _implementors[field_name](value)
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\version.py", line 45, in __call__
    val = cls._cache_[arg] = super().__call__(arg)
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\version.py", line 516, in __init__
    vspec_str, matcher, is_exact = self.get_matcher(vspec)
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\version.py", line 570, in get_matcher
    self.matcher_vo = VersionOrder(vo_str)
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\version.py", line 45, in __call__
    val = cls._cache_[arg] = super().__call__(arg)
  File "C:\Users\[...]\.conda\envs\builder\lib\site-packages\conda\models\version.py", line 171, in __init__
    raise InvalidVersionSpec(vstr, "invalid character(s)")
conda.exceptions.InvalidVersionSpec: Invalid version '0.12"': invalid character(s)
```

</details>


Discussion:
Sorry about that. I added the 'names only' variant because `conda update` only allows name-only specs. `mamba` seems to accept constrained specs too, but I assumed it was an oversight, not an intentional feature. Is this on Windows only?
> Sorry about that. I added the 'names only' variant because `conda update` only allows name-only specs. `mamba` seems to accept constrained specs too, but I assumed it was an oversight, not an intentional feature.

Constraining infrastructure deps like lief seems to be the primary (and I believe motivating) use case of `remote_ci_setup` to me, so I don't think we can ignore it.

> Is this on Windows only?

It was supported on all platforms, but in any case, the current issue (basically https://github.com/conda/conda-build/issues/4787) only occurs on osx, so that's where we'd mainly need it.
I'll put a PR later today with a fix.
In the meantime, I am curious: does `conda_install_tool: conda` + `conda_solver: libmamba` + `conda_build_tool: conda-build` in `conda-forge.yml` sort the issue?
I have a [PR](https://github.com/conda-forge/compiler-rt-feedstock/pull/83) for testing this, feel free to push there - I'm logging off for today 🙃 
If it manages to pull in conda-build 3.26, it will be fixed (one of the successful runs in that PR was in the brief period where we had boa builds that were compatible with 3.26, before they were marked broken)

Resolving patch:
diff --git a/conda_smithy/configure_feedstock.py b/conda_smithy/configure_feedstock.py
--- a/conda_smithy/configure_feedstock.py
+++ b/conda_smithy/configure_feedstock.py
@@ -2037,7 +2037,8 @@ def _load_forge_config(forge_dir, exclusive_config_file, forge_yml=None):
         config["remote_ci_setup"]
     )
     config["remote_ci_setup_names"] = [
-        MatchSpec(pkg).name for pkg in config["remote_ci_setup"]
+        MatchSpec(pkg.strip('"').strip("'")).name
+        for pkg in config["remote_ci_setup"]
     ]
 
     # Older conda-smithy versions supported this with only one


Test patch:
diff --git a/tests/test_configure_feedstock.py b/tests/test_configure_feedstock.py
--- a/tests/test_configure_feedstock.py
+++ b/tests/test_configure_feedstock.py
@@ -907,3 +907,22 @@ def test_conda_build_tools(config_yaml):
 
     with pytest.raises(AssertionError):
         assert load_forge_config()
+
+
+def test_remote_ci_setup(config_yaml):
+    load_forge_config = lambda: cnfgr_fdstk._load_forge_config(  # noqa
+        config_yaml,
+        exclusive_config_file=os.path.join(
+            config_yaml, "recipe", "default_config.yaml"
+        ),
+    )
+    cfg = load_forge_config()
+    with open(os.path.join(config_yaml, "conda-forge.yml"), "a+") as fp:
+        fp.write("remote_ci_setup: ['conda-forge-ci-setup=3', 'py-lief<0.12']")
+    cfg = load_forge_config()
+    # pylief was quoted due to <
+    assert cfg["remote_ci_setup"] == [
+        "conda-forge-ci-setup=3",
+        '"py-lief<0.12"',
+    ]
+    assert cfg["remote_ci_setup_names"] == ["conda-forge-ci-setup", "py-lief"]