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

pantsbuild / pants / 25443604553

06 May 2026 03:05PM UTC coverage: 92.879% (-0.04%) from 92.915%
25443604553

push

github

web-flow
[pants_ng] Scaffolding for a pants_ng mode. (#23319)

In this mode the command line is parsed as an
NG invocation, and dispatched appropriately.

Of course at the moment there are no
implementations to dispatch to. That will follow.

This does expose a new option, `pants_ng` to users. 
There is a big warning not to set it, but we're not trying
to hide that we're working on a new thing, so I am
comfortable with this.

25 of 76 new or added lines in 9 files covered. (32.89%)

1294 existing lines in 76 files now uncovered.

92234 of 99306 relevant lines covered (92.88%)

4.05 hits per line

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

100.0
/src/python/pants/backend/javascript/goals/lockfile.py
1
# Copyright 2023 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
UNCOV
3
from __future__ import annotations
1✔
4

UNCOV
5
import os.path
1✔
UNCOV
6
from collections.abc import Iterable
1✔
UNCOV
7
from dataclasses import dataclass
1✔
8

UNCOV
9
from pants.backend.javascript import nodejs_project_environment
1✔
UNCOV
10
from pants.backend.javascript.nodejs_project import AllNodeJSProjects, NodeJSProject
1✔
UNCOV
11
from pants.backend.javascript.nodejs_project_environment import (
1✔
12
    NodeJsProjectEnvironment,
13
    NodeJsProjectEnvironmentProcess,
14
)
UNCOV
15
from pants.backend.javascript.package_json import PackageJsonTarget
1✔
UNCOV
16
from pants.backend.javascript.resolve import NodeJSProjectResolves
1✔
UNCOV
17
from pants.backend.javascript.subsystems.nodejs import UserChosenNodeJSResolveAliases
1✔
UNCOV
18
from pants.core.goals.generate_lockfiles import (
1✔
19
    GenerateLockfile,
20
    GenerateLockfileResult,
21
    KnownUserResolveNames,
22
    KnownUserResolveNamesRequest,
23
    RequestedUserResolveNames,
24
    UserGenerateLockfiles,
25
)
UNCOV
26
from pants.core.goals.tailor import TailorGoal
1✔
UNCOV
27
from pants.engine.internals.native_engine import AddPrefix
1✔
UNCOV
28
from pants.engine.intrinsics import add_prefix
1✔
UNCOV
29
from pants.engine.process import fallible_to_exec_result_or_raise
1✔
UNCOV
30
from pants.engine.rules import Rule, collect_rules, implicitly, rule
1✔
UNCOV
31
from pants.engine.unions import UnionRule
1✔
UNCOV
32
from pants.util.docutil import bin_name
1✔
UNCOV
33
from pants.util.ordered_set import FrozenOrderedSet
1✔
UNCOV
34
from pants.util.strutil import pluralize, softwrap
1✔
35

36

UNCOV
37
@dataclass(frozen=True)
1✔
UNCOV
38
class GeneratePackageLockJsonFile(GenerateLockfile):
1✔
UNCOV
39
    project: NodeJSProject
1✔
40

41

UNCOV
42
class KnownPackageJsonUserResolveNamesRequest(KnownUserResolveNamesRequest):
1✔
UNCOV
43
    pass
1✔
44

45

UNCOV
46
class RequestedPackageJsonUserResolveNames(RequestedUserResolveNames):
1✔
UNCOV
47
    pass
1✔
48

49

UNCOV
50
@rule
1✔
UNCOV
51
async def determine_package_json_user_resolves(
1✔
52
    _: KnownPackageJsonUserResolveNamesRequest,
53
    all_projects: AllNodeJSProjects,
54
    user_chosen_resolves: UserChosenNodeJSResolveAliases,
55
) -> KnownUserResolveNames:
UNCOV
56
    names = FrozenOrderedSet(
1✔
57
        user_chosen_resolves.get(
58
            os.path.join(project.root_dir, project.lockfile_name), project.default_resolve_name
59
        )
60
        for project in all_projects
61
    )
UNCOV
62
    unmatched_aliases = set(user_chosen_resolves.values()).difference(names)
1✔
UNCOV
63
    if unmatched_aliases:
1✔
UNCOV
64
        projects = pluralize(len(unmatched_aliases), "project", include_count=False)
1✔
UNCOV
65
        lockfiles = ", ".join(
1✔
66
            lockfile
67
            for lockfile, alias in user_chosen_resolves.items()
68
            if alias in unmatched_aliases
69
        )
UNCOV
70
        paths = pluralize(len(unmatched_aliases), "path", include_count=False)
1✔
UNCOV
71
        raise ValueError(
1✔
72
            softwrap(
73
                f"""
74
                No nodejs {projects} could be found for {lockfiles}, but
75
                some are configured under [nodejs].resolves.
76

77
                Ensure that a package.json file you intend to manage with pants has
78
                a corresponding BUILD file containing a `{PackageJsonTarget.alias}` target
79
                by running `{bin_name()} {TailorGoal.name} ::`.
80

81
                Also confirm that {lockfiles} would be generated by your
82
                chosen nodejs package manager at the specified {paths}.
83
                """
84
            )
85
        )
86

UNCOV
87
    return KnownUserResolveNames(
1✔
88
        names=tuple(names),
89
        option_name="[nodejs].resolves",
90
        requested_resolve_names_cls=RequestedPackageJsonUserResolveNames,
91
    )
92

93

UNCOV
94
@rule
1✔
UNCOV
95
async def setup_user_lockfile_requests(
1✔
96
    resolves: NodeJSProjectResolves,
97
    requested: RequestedPackageJsonUserResolveNames,
98
) -> UserGenerateLockfiles:
UNCOV
99
    return UserGenerateLockfiles(
1✔
100
        GeneratePackageLockJsonFile(
101
            resolve_name=name,
102
            lockfile_dest=os.path.join(resolves[name].root_dir, resolves[name].lockfile_name),
103
            diff=False,
104
            project=resolves[name],
105
        )
106
        for name in requested
107
    )
108

109

UNCOV
110
@rule
1✔
UNCOV
111
async def generate_lockfile_from_package_jsons(
1✔
112
    request: GeneratePackageLockJsonFile,
113
) -> GenerateLockfileResult:
UNCOV
114
    result = await fallible_to_exec_result_or_raise(
1✔
115
        **implicitly(
116
            NodeJsProjectEnvironmentProcess(
117
                env=NodeJsProjectEnvironment.from_root(request.project),
118
                args=request.project.generate_lockfile_args,
119
                description=f"generate {request.project.lockfile_name} for '{request.resolve_name}'.",
120
                output_files=(request.project.lockfile_name,),
121
            )
122
        )
123
    )
UNCOV
124
    output_digest = await add_prefix(AddPrefix(result.output_digest, request.project.root_dir))
1✔
UNCOV
125
    return GenerateLockfileResult(output_digest, request.resolve_name, request.lockfile_dest)
1✔
126

127

UNCOV
128
def rules() -> Iterable[Rule | UnionRule]:
1✔
UNCOV
129
    return (
1✔
130
        *collect_rules(),
131
        *nodejs_project_environment.rules(),
132
        UnionRule(GenerateLockfile, GeneratePackageLockJsonFile),
133
        UnionRule(KnownUserResolveNamesRequest, KnownPackageJsonUserResolveNamesRequest),
134
        UnionRule(RequestedUserResolveNames, RequestedPackageJsonUserResolveNames),
135
    )
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