Skip to content

nfpm: add get_package_field_sets_for_nfpm_content_file_deps rule#22863

Merged
cognifloyd merged 2 commits intomainfrom
cognifloyd/nfpm-contents_util
Nov 6, 2025
Merged

nfpm: add get_package_field_sets_for_nfpm_content_file_deps rule#22863
cognifloyd merged 2 commits intomainfrom
cognifloyd/nfpm-contents_util

Conversation

@cognifloyd
Copy link
Member

@cognifloyd cognifloyd commented Nov 6, 2025

This extends then pants.backend.experimental.nfpm backend's plugin API with a new utility rule: get_package_field_sets_for_nfpm_content_file_deps.

This should be useful for anyone implementing a rule for this nfpm backend plugin hook (a polymorphic rule), especially when injecting package requirements based on the system package's contents:

  • inject_nfpm_package_fields(InjectNfpmPackageFieldsRequest) -> InjectedNfpmPackageFields

@cognifloyd cognifloyd marked this pull request as ready for review November 6, 2025 15:46
Comment on lines +45 to +47
#### nFPM backend

Added a new rule to help in-repo plugins implement the `inject_nfpm_package_fields(InjectNfpmPackageFieldsRequest) -> InjectedNfpmPackageFields` polymorphic rule. The `get_package_field_sets_for_nfpm_content_file_deps` rule (in the `pants.backend.nfpm.util_rules.contents` module) collects selected `PackageFieldSet`s from the contents of an `nfpm_*_package` so that the packages can be analyzed to inject things like package requirements.
Copy link
Member Author

@cognifloyd cognifloyd Nov 6, 2025

Choose a reason for hiding this comment

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

I debated labeling this PR with release-notes:not-required [CI] PR doesn't require mention in release notes
I decided to add this release notes entry because the plugin API was originally included in the release notes and it is a separate rule meant for use in in-repo/external plugins.

It will also be used in pants in a rule that should be added in #22861 (or a PR that gets split off of that one), but it is separate so that I can reuse this tested rule in in-repo/external plugins as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think when in doubt, put it in the notes, so this is great.

("rpm",),
),
)
def test_get_package_field_sets_for_nfpm_content_file_deps(rule_runner: RuleRunner, packager: str):
Copy link
Member Author

Choose a reason for hiding this comment

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

I copied a bunch of this from the other tests in this directory. The tests are not as DRY as I would like, but moving the rule_runner.write_files calls to a fixture in conftest.py could make the tests harder to follow. Sharing logic across tests is not always straightforward.



def rules():
def rules() -> Iterable[Rule | UnionRule]:
Copy link
Member Author

@cognifloyd cognifloyd Nov 6, 2025

Choose a reason for hiding this comment

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

This added typehint is not strictly required by this PR. It's a minor consistency improvement (+4 -2 lines), and I'm already editing this file (+2 lines), so I included it here.

@benjyw
Copy link
Contributor

benjyw commented Nov 6, 2025

I would edit the PR description to remove the "This was cherry-picked from #22861" bit because that PR hasn't merged yet (and may or may not) so we won't want it in the commit description.

Comment on lines +45 to +47
#### nFPM backend

Added a new rule to help in-repo plugins implement the `inject_nfpm_package_fields(InjectNfpmPackageFieldsRequest) -> InjectedNfpmPackageFields` polymorphic rule. The `get_package_field_sets_for_nfpm_content_file_deps` rule (in the `pants.backend.nfpm.util_rules.contents` module) collects selected `PackageFieldSet`s from the contents of an `nfpm_*_package` so that the packages can be analyzed to inject things like package requirements.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think when in doubt, put it in the notes, so this is great.

@cognifloyd
Copy link
Member Author

cognifloyd commented Nov 6, 2025

@cognifloyd cognifloyd merged commit 1de0801 into main Nov 6, 2025
28 checks passed
@cognifloyd cognifloyd deleted the cognifloyd/nfpm-contents_util branch November 6, 2025 20:36
cognifloyd added a commit that referenced this pull request Nov 20, 2025
…22899)

## PR Series Overview

This is the second in a series of PRs that introduces a new backend:
`pants.backend.npm.native_libs`
Initially, the backend will be available as:
`pants.backend.experimental.nfpm.native_libs`

I proposed this new backend (originally named `bindeps`) in discussion
#22396.

This backend will inspect ELF bin/lib files (like `lib*.so`) in packaged
contents (for this PR series, only in `pex_binary` targets) to identify
package dependency metadata and inject that metadata on the relevant
`nfpm_deb_package` or `nfpm_rpm_package` targets. Effectively, it will
provide an approximation of these native packager features:
- `rpm`: `rpmdeps` + `elfdeps`
- `deb`: `dh_shlibdeps` + `dpkg-shlibdeps` (These substitute
`${shlibs:Depends}` in debian control files have)

### Goal: Host-agnostic package builds

This pants backend is designed to be host-agnostic, like
[nFPM](https://nfpm.goreleaser.com/).

Native packaging tools are often restricted to a single release of a
single distro. Unlike native package builders, this new pants backend
does not use any of those distro-specific or distro-release-specific
utilities or local package databases. This new backend should be able to
run (help with building deb and rpm packages) anywhere that pants can
run (MacOS, rpm linux distros, deb linux distros, other linux distros,
docker, ...).

### Previous PRs in series

- #22873

## PR Overview

This PR adds rules in `nfpm.native_libs` to add package dependency
metadata to `nfpm_rpm_package`. The 2 new rules are:

- `inject_native_libs_dependencies_in_package_fields`:

    - An implementation of the polymorphic rule `inject_nfpm_package_fields`.
      This rule is low priority (`priority = 2`) so that in-repo plugins can
      override/augment what it injects. (See #22864)

    - Rule logic overview:
        - find any pex_binaries that will be packaged in an `nfpm_rpm_package`
          (using utility introduced in #22863)
        - Run new `rpm_depends_from_pex` rule (see below)
        - Inject identified SONAMEs in `nfpm_rpm_package` dependency fields
          (rpm accepts raw SONAMEs in these fields, so the SONAME does not need to
          be translated to a package name when building the package).
            - The `requires` field gets SONAMEs required by ELF binaries or
              libraries in the package contents
            - The `provides` field gets SONAMEs provided by ELF libraries in the
              package contents

    - How the rule outputs are used: The package dependency fields (like
      `requires` and `provides`) will be used when generating the config
      passed to `nFPM` so that `nFPM` includes the package dependency metadata
      in the built rpm package.

- `rpm_depends_from_pex`:
    - runs `elfdeps_analyze_pex` on a pex (added in #22873)
    - returns only the ELF metadata that can be injected in
      `nfpm_rpm_package` fields.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants