Skip to content

Commit

Permalink
Merge pull request #58 from wolfv/rattler-build-check
Browse files Browse the repository at this point in the history
feat: solvability implementation for rattler-build
  • Loading branch information
beckermr authored Sep 23, 2024
2 parents 35b9955 + 0df0679 commit a32add4
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 3 deletions.
29 changes: 26 additions & 3 deletions conda_forge_feedstock_check_solvable/check_solvable.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import conda_forge_feedstock_check_solvable.utils
from conda_forge_feedstock_check_solvable.mamba_solver import mamba_solver_factory
from conda_forge_feedstock_check_solvable.rattler_build import invoke_rattler_build
from conda_forge_feedstock_check_solvable.rattler_solver import rattler_solver_factory
from conda_forge_feedstock_check_solvable.utils import (
MAX_GLIBC_MINOR,
Expand Down Expand Up @@ -132,7 +133,12 @@ def _is_recipe_solvable(
print_warning(errors[-1])
return False, errors, {}

if not os.path.exists(os.path.join(feedstock_dir, "recipe", "meta.yaml")):
meta_exists = os.path.exists(os.path.join(feedstock_dir, "recipe", "meta.yaml"))
recipe_exists = os.path.exists(
os.path.join(feedstock_dir, "recipe", "recipe.yaml")
)

if not (meta_exists or recipe_exists):
errors.append(
"No `recipe/meta.yaml` file found! This issue is quite weird and "
"someone should investigate!",
Expand Down Expand Up @@ -187,8 +193,8 @@ def _is_recipe_solvable(


def _is_recipe_solvable_on_platform(
recipe_dir,
cbc_path,
recipe_dir: str,
cbc_path: str,
platform,
arch,
build_platform_arch=None,
Expand Down Expand Up @@ -258,6 +264,23 @@ def _is_recipe_solvable_on_platform(

timeout_timer.raise_for_timeout()

if os.path.exists(os.path.join(recipe_dir, "recipe.yaml")):
# this is a rattler-build recipe so we can invoke rattler-build with
# the new `cbc`.
solvable, errors = invoke_rattler_build(
recipe_dir,
channels=channel_sources,
build_platform=f"{platform}-{arch}",
host_platform=f"{platform}-{arch}",
variants=cbc,
)

if errors:
print_warning("Rattler build errors: %s", errors)
errors = [f"Rattler build errors: {errors}"]

return solvable, errors

# now we render the meta.yaml into an actual recipe
metas = conda_build_api_render(
recipe_dir,
Expand Down
63 changes: 63 additions & 0 deletions conda_forge_feedstock_check_solvable/rattler_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import subprocess
import tempfile

import yaml

from conda_forge_feedstock_check_solvable.utils import print_debug
from conda_forge_feedstock_check_solvable.virtual_packages import (
virtual_package_repodata,
)


def run_rattler_build(command):
try:
# Run the command and capture output
print_debug("Running: ", " ".join(command))
result = subprocess.run(
" ".join(command), shell=True, check=False, capture_output=True, text=True
)

# Get the status code
status_code = result.returncode

# Get stdout and stderr
stdout = result.stdout.strip()
stderr = result.stderr.strip()

return status_code, stdout, stderr
except Exception as e:
return -1, "", str(e)


def invoke_rattler_build(
recipe_dir: str, channels, build_platform, host_platform, variants
) -> (bool, str):
# this is OK since there is an lru cache
virtual_package_repo_url = virtual_package_repodata()
# create a temporary file and dump the variants as YAML

with tempfile.NamedTemporaryFile(mode="w", delete=False) as variants_file:
yaml.dump(variants, variants_file)
variants_file.flush()

channels_args = []
for c in channels:
channels_args.extend(["-c", c])

channels_args.extend(["-c", virtual_package_repo_url])

args = (
["rattler-build", "build", "--recipe", recipe_dir]
+ channels_args
+ ["--target-platform", host_platform]
+ ["--build-platform", build_platform]
+ ["-m", variants_file.name]
+ ["--render-only", "--with-solve"]
)

status, out, err = run_rattler_build(args)

if status == 0:
return True, ""
else:
return False, out + err
33 changes: 33 additions & 0 deletions tests/test_check_solvable.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,3 +572,36 @@ def test_pillow_solvable(tmp_path, solver):
pprint.pprint(solvable_by_variant)
assert solvable, pprint.pformat(errors)
assert any("python3.10" in k for k in solvable_by_variant)


def test_jolt_physics_rattler(tmp_path):
"""test the new recipe format"""
feedstock_dir = clone_and_checkout_repo(
tmp_path,
"https://github.com/conda-forge/jolt-physics-feedstock",
ref="main",
)
solvable, errors, solvable_by_variant = is_recipe_solvable(
feedstock_dir,
solver="rattler",
verbosity=VERB,
timeout=None,
fail_fast=True,
)
pprint.pprint(solvable_by_variant)
assert solvable, pprint.pformat(errors)


def test_v1_unsolvable(tmp_path):
"""test an unsolvable recipe in the new format"""
feedstock_dir = os.path.join(os.path.dirname(__file__), "v1-unsolvable-feedstock")
solvable, errors, _ = is_recipe_solvable(
feedstock_dir,
solver="rattler",
verbosity=VERB,
timeout=None,
fail_fast=True,
)
assert solvable is False

print(errors[0])
4 changes: 4 additions & 0 deletions tests/v1-unsolvable-feedstock/.ci_support/osx_arm64_.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
python:
- 100
channel_sources:
- conda-forge
7 changes: 7 additions & 0 deletions tests/v1-unsolvable-feedstock/recipe/recipe.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package:
name: v1-unsolvable
version: "0.1"

requirements:
build:
- python

0 comments on commit a32add4

Please sign in to comment.