• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 19015773527

02 Nov 2025 05:33PM UTC coverage: 17.872% (-62.4%) from 80.3%
19015773527

Pull #22816

github

web-flow
Merge a12d75757 into 6c024e162
Pull Request #22816: Update Pants internal Python to 3.14

4 of 5 new or added lines in 3 files covered. (80.0%)

28452 existing lines in 683 files now uncovered.

9831 of 55007 relevant lines covered (17.87%)

0.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/python/pants/backend/nfpm/rules.py
1
# Copyright 2023 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

UNCOV
4
from __future__ import annotations
×
5

UNCOV
6
from dataclasses import dataclass
×
7

UNCOV
8
from pants.backend.nfpm.field_sets import (
×
9
    NfpmApkPackageFieldSet,
10
    NfpmArchlinuxPackageFieldSet,
11
    NfpmDebPackageFieldSet,
12
    NfpmPackageFieldSet,
13
    NfpmRpmPackageFieldSet,
14
)
UNCOV
15
from pants.backend.nfpm.field_sets import rules as field_sets_rules
×
UNCOV
16
from pants.backend.nfpm.subsystem import NfpmSubsystem
×
UNCOV
17
from pants.backend.nfpm.util_rules.generate_config import (
×
18
    NfpmPackageConfigRequest,
19
    generate_nfpm_yaml,
20
)
UNCOV
21
from pants.backend.nfpm.util_rules.generate_config import rules as generate_config_rules
×
UNCOV
22
from pants.backend.nfpm.util_rules.inject_config import rules as inject_config_rules
×
UNCOV
23
from pants.backend.nfpm.util_rules.sandbox import (
×
24
    NfpmContentSandboxRequest,
25
    populate_nfpm_content_sandbox,
26
)
UNCOV
27
from pants.backend.nfpm.util_rules.sandbox import rules as sandbox_rules
×
UNCOV
28
from pants.core.goals import package
×
UNCOV
29
from pants.core.goals.package import BuiltPackage, BuiltPackageArtifact
×
UNCOV
30
from pants.core.util_rules.external_tool import download_external_tool
×
UNCOV
31
from pants.engine.fs import CreateDigest, Directory, MergeDigests
×
UNCOV
32
from pants.engine.internals.native_engine import AddPrefix, RemovePrefix
×
UNCOV
33
from pants.engine.internals.selectors import concurrently
×
UNCOV
34
from pants.engine.intrinsics import create_digest, digest_to_snapshot, merge_digests, remove_prefix
×
UNCOV
35
from pants.engine.platform import Platform
×
UNCOV
36
from pants.engine.process import Process, execute_process_or_raise
×
UNCOV
37
from pants.engine.rules import collect_rules, implicitly, rule
×
UNCOV
38
from pants.util.logging import LogLevel
×
39

40

UNCOV
41
@dataclass(frozen=True)
×
UNCOV
42
class BuiltNfpmPackageArtifact(BuiltPackageArtifact):
×
UNCOV
43
    packager: str = ""
×
44

UNCOV
45
    @classmethod
×
UNCOV
46
    def create(cls, relpath: str, packager: str) -> BuiltNfpmPackageArtifact:
×
47
        return cls(
×
48
            relpath=relpath,
49
            packager=packager,
50
            extra_log_lines=(f"Built {packager} package with nFPM: {relpath}",),
51
        )
52

53

UNCOV
54
@dataclass(frozen=True)
×
UNCOV
55
class NfpmPackageRequest:
×
UNCOV
56
    field_set: NfpmPackageFieldSet
×
57

58

UNCOV
59
@rule(level=LogLevel.INFO)
×
UNCOV
60
async def package_nfpm_package(
×
61
    request: NfpmPackageRequest,
62
    nfpm_subsystem: NfpmSubsystem,
63
    platform: Platform,
64
) -> BuiltPackage:
65
    output_dir = "__out"
×
66

67
    field_set = request.field_set
×
68

69
    nfpm_content_sandbox = await populate_nfpm_content_sandbox(
×
70
        NfpmContentSandboxRequest(field_set), **implicitly()
71
    )
72

73
    nfpm_config, downloaded_tool, output_dir_digest = await concurrently(
×
74
        generate_nfpm_yaml(
75
            NfpmPackageConfigRequest(field_set, nfpm_content_sandbox.digest), **implicitly()
76
        ),
77
        download_external_tool(nfpm_subsystem.get_request(platform)),
78
        create_digest(CreateDigest([Directory(output_dir)])),
79
    )
80

81
    sandbox_digest = await merge_digests(
×
82
        MergeDigests(
83
            (
84
                nfpm_content_sandbox.digest,
85
                nfpm_config.digest,
86
                downloaded_tool.digest,
87
                output_dir_digest,
88
            )
89
        )
90
    )
91

92
    result = await execute_process_or_raise(
×
93
        **implicitly(
94
            Process(
95
                argv=(
96
                    downloaded_tool.exe,
97
                    "package",  # or "pkg" or "p"
98
                    # use default config file: nfpm.yaml
99
                    "--packager",  # or "-p"
100
                    field_set.packager,
101
                    "--target",  # or "-t"
102
                    output_dir,
103
                ),
104
                description=f"Creating {field_set.packager} package with nFPM: {field_set.address}",
105
                input_digest=sandbox_digest,
106
                output_directories=(output_dir,),
107
            )
108
        ),
109
    )
110

111
    # The final directory that should contain the package artifact.
112
    # The package artifact itself will use the conventional filename generated by nFPM.
113
    output_path = field_set.output_path.value_or_default(file_ending=None)
×
114

115
    stripped_digest = await remove_prefix(RemovePrefix(result.output_digest, output_dir))
×
116
    final_snapshot = await digest_to_snapshot(**implicitly(AddPrefix(stripped_digest, output_path)))
×
117

118
    # nFPM creates only 1 file (any signature gets embedded in the package file).
119
    assert len(final_snapshot.files) == 1
×
120
    conventional_file_name = final_snapshot.files[0]
×
121

122
    return BuiltPackage(
×
123
        final_snapshot.digest,
124
        artifacts=(BuiltNfpmPackageArtifact.create(conventional_file_name, field_set.packager),),
125
    )
126

127

UNCOV
128
@rule
×
UNCOV
129
async def package_nfpm_apk_package(field_set: NfpmApkPackageFieldSet) -> BuiltPackage:
×
130
    built_package: BuiltPackage = await package_nfpm_package(
×
131
        NfpmPackageRequest(field_set), **implicitly()
132
    )
133
    return built_package
×
134

135

UNCOV
136
@rule
×
UNCOV
137
async def package_nfpm_archlinux_package(field_set: NfpmArchlinuxPackageFieldSet) -> BuiltPackage:
×
138
    built_package: BuiltPackage = await package_nfpm_package(
×
139
        NfpmPackageRequest(field_set), **implicitly()
140
    )
141
    return built_package
×
142

143

UNCOV
144
@rule
×
UNCOV
145
async def package_nfpm_deb_package(field_set: NfpmDebPackageFieldSet) -> BuiltPackage:
×
146
    built_package: BuiltPackage = await package_nfpm_package(
×
147
        NfpmPackageRequest(field_set), **implicitly()
148
    )
149
    return built_package
×
150

151

UNCOV
152
@rule
×
UNCOV
153
async def package_nfpm_rpm_package(field_set: NfpmRpmPackageFieldSet) -> BuiltPackage:
×
154
    built_package: BuiltPackage = await package_nfpm_package(
×
155
        NfpmPackageRequest(field_set), **implicitly()
156
    )
157
    return built_package
×
158

159

UNCOV
160
def rules():
×
UNCOV
161
    return [
×
162
        *package.rules(),
163
        *field_sets_rules(),
164
        *inject_config_rules(),
165
        *generate_config_rules(),
166
        *sandbox_rules(),
167
        *collect_rules(),
168
    ]
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc