Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEW: Migrate NVIDIA redist feedstocks to use cf-nvidia-tools #3580

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
7 changes: 6 additions & 1 deletion conda_forge_tick/make_migrators.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
remove_key_for_hashmap,
)
from conda_forge_tick.migrators import (
AddNVIDIATools,
ArchRebuild,
Build2HostMigrator,
CondaForgeYAMLCleanup,
Expand Down Expand Up @@ -797,7 +798,11 @@
gx: nx.DiGraph,
dry_run: bool = False,
) -> MutableSequence[Migrator]:
migrators: List[Migrator] = []
migrators: List[Migrator] = [

Check warning on line 801 in conda_forge_tick/make_migrators.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/make_migrators.py#L801

Added line #L801 was not covered by tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should append this migrator to the list after the noarch python migrator. There are some conventions in the code about where each kind of migrator goes in the list.

AddNVIDIATools(
check_solvable=False,
),
]

add_arch_migrate(migrators, gx)

Expand Down
1 change: 1 addition & 0 deletions conda_forge_tick/migrators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@
from .version import Version
from .xz_to_liblzma_devel import XzLibLzmaDevelMigrator
from .noarch_python_min import NoarchPythonMinMigrator
from .nvtools import AddNVIDIATools
from .round_trip import YAMLRoundTrip
243 changes: 243 additions & 0 deletions conda_forge_tick/migrators/nvtools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
import copy
import logging
import os.path
from typing import Any

from conda_forge_tick.contexts import ClonedFeedstockContext
from conda_forge_tick.migrators_types import AttrsTypedDict, MigrationUidTypedDict
from conda_forge_tick.utils import (
get_bot_run_url,
yaml_safe_dump,
yaml_safe_load,
)

from .core import Migrator


def _file_contains(filename: str, string: str) -> bool:
"""Return whether the given file contains the given string."""
with open(filename) as f:
return string in f.read()

Check warning on line 20 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L19-L20

Added lines #L19 - L20 were not covered by tests


def _insert_subsection(
filename: str,
section: str,
subsection: str,
new_item: str,
) -> None:
"""Append a new item onto the end of the section.subsection of a recipe."""
# Strategy: Read the file as a list of strings. Split the file in half at the end of the
# section.subsection section. Append the new_item to the first half. Combine the two
# file halves. Write the file back to disk.
first_half: list[str] = []
second_half: list[str] = []
break_located: bool = False
section_found: bool = False
subsection_found: bool = False
with open(filename) as f:
for line in f:
if break_located:
second_half.append(line)

Check warning on line 41 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L33-L41

Added lines #L33 - L41 were not covered by tests
else:
if line.startswith(section):
section_found = True
elif section_found and line.lstrip().startswith(subsection):
subsection_found = True
elif section_found and subsection_found:
if line.lstrip().startswith("-"):

Check warning on line 48 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L43-L48

Added lines #L43 - L48 were not covered by tests
# Inside section.subsection elements start with "-". We assume there
# is at least one item under section.subsection already.
first_half.append(line)
continue

Check warning on line 52 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L51-L52

Added lines #L51 - L52 were not covered by tests
else:
break_located = True
second_half.append(line)
continue
first_half.append(line)

Check warning on line 57 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L54-L57

Added lines #L54 - L57 were not covered by tests

if not break_located:

Check warning on line 59 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L59

Added line #L59 was not covered by tests
# Don't overwrite file if we didn't find section.subsection
return

Check warning on line 61 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L61

Added line #L61 was not covered by tests

with open(filename, "w") as f:
f.writelines(first_half + [new_item] + second_half)

Check warning on line 64 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L63-L64

Added lines #L63 - L64 were not covered by tests


class AddNVIDIATools(Migrator):
"""Add the cf-nvidia-tools package to NVIDIA redist feedstocks.

In order to ensure that NVIDIA's redistributed binaries (redists) are being packaged
correctly, NVIDIA has created a package containing a collection of tools to perform
common actions for NVIDIA recipes.

At this time, the package may be used to check Linux binaries for their minimum glibc
requirement in order to ensure that the correct metadata is being used in the conda
package.

This migrator will attempt to add this glibc check to all feedstocks which download any
artifacts from https://developer.download.nvidia.com. The check involves adding
"cf-nvidia-tools" to the top-level build requirements and something like:

```bash
check-glibc "$PREFIX"/lib/*.so.* "$PREFIX"/bin/*
```

to the build script after the package artifacts have been installed.

> [!NOTE]
> A human needs to verify that the glob expression is checking all of the correct
> artifacts!

> [!NOTE]
> If the recipe does not have a top-level requirements.build section, it should be
> refactored so that the top-level package does not share a name with one of the
> outputs. i.e. The top-level package name should be something like "libcufoo-split".

More information about cf-nvidia-tools is available in the feedstock's
[README](https://github.com/conda-forge/cf-nvidia-tools-feedstock/tree/main/recipe).

Please ping carterbox for questions.
"""

name = "NVIDIA Tools Migrator"

rerender = True

max_solver_attempts = 3

migrator_version = 0

allow_empty_commits = False

allowed_schema_versions = [0]

def filter(self, attrs: "AttrsTypedDict", not_bad_str_start: str = "") -> bool:
"""If true don't act upon node

Parameters
----------
attrs : dict
The node attributes
not_bad_str_start : str, optional
If the 'bad' notice starts with the string then it is not
to be excluded. For example, rebuild migrations don't need
to worry about if the upstream can be fetched. Defaults to ``''``

Returns
-------
bool :
True if node is to be skipped
"""
return (

Check warning on line 132 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L132

Added line #L132 was not covered by tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the filter method always needs calls to super and to check the schema version. Check some of the other migrators for examples.

attrs["archived"]
or "https://developer.download.nvidia.com" not in attrs["source"]["url"]
)

def migrate(
self, recipe_dir: str, attrs: AttrsTypedDict, **kwargs: Any
) -> MigrationUidTypedDict:
"""Perform the migration, updating the ``meta.yaml``

Parameters
----------
recipe_dir : str
The directory of the recipe
attrs : dict
The node attributes

Returns
-------
namedtuple or bool:
If namedtuple continue with PR, if False scrap local folder
"""
# STEP 0: Bump the build number
self.set_build_number(os.path.join(recipe_dir, "meta.yaml"))

Check warning on line 155 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L155

Added line #L155 was not covered by tests

# STEP 1: Add cf-nvidia-tools to build requirements
meta = os.path.join(recipe_dir, "meta.yaml")
if _file_contains(meta, "cf-nvidia-tools"):
logging.debug("cf-nvidia-tools already in meta.yaml; not adding again.")

Check warning on line 160 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L158-L160

Added lines #L158 - L160 were not covered by tests
else:
_insert_subsection(

Check warning on line 162 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L162

Added line #L162 was not covered by tests
meta,
"requirements",
"build",
" - cf-nvidia-tools 1 # [linux]\n",
)
logging.debug("cf-nvidia-tools added to meta.yaml.")

Check warning on line 168 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L168

Added line #L168 was not covered by tests

# STEP 2: Add check-glibc to the build script
build = os.path.join(recipe_dir, "build.sh")
if os.path.isfile(build):
if _file_contains(build, "check-glibc"):
logging.debug(

Check warning on line 174 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L171-L174

Added lines #L171 - L174 were not covered by tests
"build.sh already contains check-glibc; not adding again."
)
else:
with open(build, "a") as file:
file.write(

Check warning on line 179 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L178-L179

Added lines #L178 - L179 were not covered by tests
'\ncheck-glibc "$PREFIX"/lib*/*.so.* "$PREFIX"/bin/* "$PREFIX"/targets/*/lib*/*.so.* "$PREFIX"/targets/*/bin/*\n'
)
logging.debug("Added check-glibc to build.sh")

Check warning on line 182 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L182

Added line #L182 was not covered by tests
else:
if _file_contains(meta, "check-glibc"):
logging.debug(

Check warning on line 185 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L184-L185

Added lines #L184 - L185 were not covered by tests
"meta.yaml already contains check-glibc; not adding again."
)
else:
_insert_subsection(

Check warning on line 189 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L189

Added line #L189 was not covered by tests
meta,
"build",
"script",
' - check-glibc "$PREFIX"/lib*/*.so.* "$PREFIX"/bin/* "$PREFIX"/targets/*/lib*/*.so.* "$PREFIX"/targets/*/bin/* # [linux]\n',
)
logging.debug("Added check-glibc to meta.yaml")

Check warning on line 195 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L195

Added line #L195 was not covered by tests

# STEP 3: Remove os_version keys from conda-forge.yml
config = os.path.join(recipe_dir, "..", "conda-forge.yml")
with open(config) as f:
y = yaml_safe_load(f)
y_orig = copy.deepcopy(y)
y.pop("os_version", None)
if y_orig != y:
with open(config, "w") as f:
yaml_safe_dump(y, f)

Check warning on line 205 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L198-L205

Added lines #L198 - L205 were not covered by tests
Comment on lines +197 to +205
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we are dropping the os_version specification of the Docker image to use?

Wonder if it makes to add/confirm {{ stdlib("c") }} is used and c_stdlib_version is set correctly

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It's not necessary to force use an old container.

The tool fails if c_stdlib_version is not set, so indirectly this is already checked?


return self.migrator_uid(attrs)

Check warning on line 207 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L207

Added line #L207 was not covered by tests

def pr_body(
self, feedstock_ctx: ClonedFeedstockContext, add_label_text=True
) -> str:
"""Create a PR message body

Returns
-------
body: str
The body of the PR message
:param feedstock_ctx:
"""
body = f"{AddNVIDIATools.__doc__}\n\n"

Check warning on line 220 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L220

Added line #L220 was not covered by tests

if add_label_text:
body += (

Check warning on line 223 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L222-L223

Added lines #L222 - L223 were not covered by tests
"If this PR was opened in error or needs to be updated please add "
"the `bot-rerun` label to this PR. The bot will close this PR and "
"schedule another one. If you do not have permissions to add this "
"label, you can use the phrase "
"<code>@<space/>conda-forge-admin, please rerun bot</code> "
"in a PR comment to have the `conda-forge-admin` add it for you.\n\n"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wonder if we should add some text on how to handle issues or ask for help in resolving

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please look at line 113. The description directs users (us) to ping me for questions.

)

body += (

Check warning on line 232 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L232

Added line #L232 was not covered by tests
"<sub>"
"This PR was created by the [regro-cf-autotick-bot](https://github.com/regro/cf-scripts). "
"The **regro-cf-autotick-bot** is a service to automatically "
"track the dependency graph, migrate packages, and "
"propose package version updates for conda-forge. "
"Feel free to drop us a line if there are any "
"[issues](https://github.com/regro/cf-scripts/issues)! "
+ f"This PR was generated by {get_bot_run_url()} - please use this URL for debugging."
+ "</sub>"
)
return body

Check warning on line 243 in conda_forge_tick/migrators/nvtools.py

View check run for this annotation

Codecov / codecov/patch

conda_forge_tick/migrators/nvtools.py#L243

Added line #L243 was not covered by tests