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

pantsbuild / pants / 20147226056

11 Dec 2025 08:58PM UTC coverage: 78.827% (-1.5%) from 80.293%
20147226056

push

github

web-flow
Forwarded the `style` and `complete-platform` args from pants.toml to PEX (#22910)

## Context

After Apple switched to the `arm64` architecture, some package
publishers stopped releasing `x86_64` variants of their packages for
`darwin`. As a result, generating a universal lockfile now fails because
no single package version is compatible with both `x86_64` and `arm64`
on `darwin`.

The solution is to use the `--style` and `--complete-platform` flags
with PEX. For example:
```
pex3 lock create \
    --style strict \
    --complete-platform 3rdparty/platforms/manylinux_2_28_aarch64.json \
    --complete-platform 3rdparty/platforms/macosx_26_0_arm64.json \
    -r 3rdparty/python/requirements_pyarrow.txt \
    -o python-pyarrow.lock
```

See the Slack discussion here:
https://pantsbuild.slack.com/archives/C046T6T9U/p1760098582461759

## Reproduction

* `BUILD`
```
python_requirement(
    name="awswrangler",
    requirements=["awswrangler==3.12.1"],
    resolve="awswrangler",
)
```
* Run `pants generate-lockfiles --resolve=awswrangler` on macOS with an
`arm64` CPU
```
pip: ERROR: Cannot install awswrangler==3.12.1 because these package versions have conflicting dependencies.
pip: ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts
pip:  
pip:  The conflict is caused by:
pip:      awswrangler 3.12.1 depends on pyarrow<18.0.0 and >=8.0.0; sys_platform == "darwin" and platform_machine == "x86_64"
pip:      awswrangler 3.12.1 depends on pyarrow<21.0.0 and >=18.0.0; sys_platform != "darwin" or platform_machine != "x86_64"
pip:  
pip:  Additionally, some packages in these conflicts have no matching distributions available for your environment:
pip:      pyarrow
pip:  
pip:  To fix this you could try to:
pip:  1. loosen the range of package versions you've specified
pip:  2. remove package versions to allow pip to attempt to solve the dependency conflict
```

## Implementation
... (continued)

77 of 100 new or added lines in 6 files covered. (77.0%)

868 existing lines in 42 files now uncovered.

74471 of 94474 relevant lines covered (78.83%)

3.18 hits per line

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

0.0
/src/python/pants/backend/helm/lint/trivy/rules.py
1
# Copyright 2024 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
UNCOV
3
from abc import ABCMeta
×
UNCOV
4
from dataclasses import dataclass
×
UNCOV
5
from typing import Any
×
6

UNCOV
7
from pants.backend.helm.subsystems.post_renderer import setup_post_renderer_launcher
×
UNCOV
8
from pants.backend.helm.target_types import (
×
9
    HelmChartFieldSet,
10
    HelmChartTarget,
11
    HelmDeploymentFieldSet,
12
    HelmDeploymentTarget,
13
)
UNCOV
14
from pants.backend.helm.util_rules.post_renderer import HelmDeploymentPostRendererRequest
×
UNCOV
15
from pants.backend.helm.util_rules.renderer import (
×
16
    HelmDeploymentCmd,
17
    HelmDeploymentRequest,
18
    RenderedHelmFiles,
19
    RenderHelmChartRequest,
20
    render_helm_chart,
21
    run_renderer,
22
)
UNCOV
23
from pants.backend.tools.trivy.rules import RunTrivyRequest, run_trivy
×
UNCOV
24
from pants.backend.tools.trivy.subsystem import SkipTrivyField, Trivy
×
UNCOV
25
from pants.core.goals.lint import LintResult, LintTargetsRequest
×
UNCOV
26
from pants.core.util_rules.partitions import PartitionerType
×
UNCOV
27
from pants.engine.process import FallibleProcessResult
×
UNCOV
28
from pants.engine.rules import collect_rules, implicitly, rule
×
UNCOV
29
from pants.engine.target import FieldSet, Target
×
UNCOV
30
from pants.util.logging import LogLevel
×
31

32

UNCOV
33
class TrivyLintHelmRequest(LintTargetsRequest, metaclass=ABCMeta):
×
UNCOV
34
    tool_subsystem = Trivy  # type: ignore[assignment]
×
35

36

UNCOV
37
@dataclass(frozen=True)
×
UNCOV
38
class TrivyHelmFieldSet(FieldSet, metaclass=ABCMeta):
×
UNCOV
39
    @classmethod
×
UNCOV
40
    def opt_out(cls, tgt: Target) -> bool:
×
41
        return tgt.get(SkipTrivyField).value
×
42

43

UNCOV
44
@dataclass(frozen=True)
×
UNCOV
45
class RunTrivyOnHelmRequest:
×
UNCOV
46
    field_set: TrivyHelmFieldSet
×
UNCOV
47
    rendered_files: RenderedHelmFiles
×
48

49

UNCOV
50
@rule
×
UNCOV
51
async def run_trivy_on_helm(
×
52
    request: RunTrivyOnHelmRequest,
53
) -> FallibleProcessResult:
54
    """Run Trivy on Helm files, either a rendered Helm chart from a `helm_deployment` or a chart
55
    rendered from its defaults from a `helm_chart`"""
56

57
    r = await run_trivy(
×
58
        RunTrivyRequest(
59
            command="config",
60
            scanners=(),
61
            command_args=tuple(),
62
            target=".",  # the charts are rendered to the local directory
63
            input_digest=request.rendered_files.snapshot.digest,
64
            description=f"Run Trivy on Helm files for {request.field_set.address}",
65
        ),
66
        **implicitly(),
67
    )
68

69
    return r
×
70

71

UNCOV
72
@dataclass(frozen=True)
×
UNCOV
73
class TrivyLintHelmDeploymentFieldSet(HelmDeploymentFieldSet, TrivyHelmFieldSet):
×
UNCOV
74
    pass
×
75

76

UNCOV
77
class TrivyLintHelmDeploymentRequest(TrivyLintHelmRequest):
×
UNCOV
78
    field_set_type = TrivyLintHelmDeploymentFieldSet
×
UNCOV
79
    tool_subsystem = Trivy
×
UNCOV
80
    partitioner_type = PartitionerType.DEFAULT_ONE_PARTITION_PER_INPUT
×
81

82

UNCOV
83
@rule(desc="Lint Helm deployment with Trivy", level=LogLevel.DEBUG)
×
UNCOV
84
async def run_trivy_on_helm_deployment(
×
85
    request: TrivyLintHelmDeploymentRequest.Batch[TrivyLintHelmDeploymentFieldSet, Any],
86
) -> LintResult:
87
    assert len(request.elements) == 1, "not single element in partition"  # "Do we need to?"
×
88
    [field_set] = request.elements
×
89

90
    post_renderer = await setup_post_renderer_launcher(
×
91
        **implicitly(HelmDeploymentPostRendererRequest(field_set))
92
    )
93
    rendered_files = await run_renderer(
×
94
        **implicitly(
95
            HelmDeploymentRequest(
96
                field_set,
97
                cmd=HelmDeploymentCmd.RENDER,
98
                post_renderer=post_renderer,
99
                description=f"Evaluating Helm deployment files for {field_set.address}",
100
            )
101
        )
102
    )
103

104
    r = await run_trivy_on_helm(RunTrivyOnHelmRequest(field_set, rendered_files))
×
105

106
    return LintResult.create(request, r)
×
107

108

UNCOV
109
@dataclass(frozen=True)
×
UNCOV
110
class TrivyLintHelmChartFieldSet(HelmChartFieldSet, TrivyHelmFieldSet):
×
UNCOV
111
    pass
×
112

113

UNCOV
114
class TrivyLintHelmChartRequest(TrivyLintHelmRequest):
×
UNCOV
115
    field_set_type = TrivyLintHelmChartFieldSet
×
UNCOV
116
    tool_subsystem = Trivy
×
UNCOV
117
    partitioner_type = PartitionerType.DEFAULT_ONE_PARTITION_PER_INPUT
×
118

119

UNCOV
120
@rule(desc="Lint Helm chart with Trivy", level=LogLevel.DEBUG)
×
UNCOV
121
async def run_trivy_on_helm_chart(
×
122
    request: TrivyLintHelmChartRequest.Batch[TrivyLintHelmChartFieldSet, Any],
123
) -> LintResult:
124
    assert len(request.elements) == 1, "not single element in partition"  # "Do we need to?"
×
125
    [field_set] = request.elements
×
126

127
    rendered_files: RenderedHelmFiles = await render_helm_chart(RenderHelmChartRequest(field_set))
×
128
    r = await run_trivy_on_helm(RunTrivyOnHelmRequest(field_set, rendered_files))
×
129

130
    return LintResult.create(request, r)
×
131

132

UNCOV
133
def rules():
×
UNCOV
134
    return (
×
135
        *collect_rules(),
136
        *TrivyLintHelmDeploymentRequest.rules(),
137
        *TrivyLintHelmChartRequest.rules(),
138
        HelmDeploymentTarget.register_plugin_field(SkipTrivyField),
139
        HelmChartTarget.register_plugin_field(SkipTrivyField),
140
    )
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