Skip to content

Commit

Permalink
Begin migration to explicitly scoped environments (#17155)
Browse files Browse the repository at this point in the history
As described in #17129: we would like `@goal_rule`s to eventually make their own decisions about which environments to use, generally by consuming targets to do so, but possibly also by pinning themselves to other environments via configuration.

This change builds on #17179, and introduces a migration from `Goal.environment_migrated = {False => True}`. All graph-introspection goals consume only the APIs which are pinned to the local environment by #17179, and so are trivially migrated here. Other goals trigger a deprecation warning like the following:
```
DEPRECATED: Not setting `Goal.environment_migrated=True` for `Goal` `generate-lockfiles` is scheduled to be removed in version 2.17.0.dev0.

See https://www.pantsbuild.org/v2.15/docs/plugin-upgrade-guide
```

Before calling #17129 done, we will migrate all internal goals to `Goal.environment_migrated=True`.

[ci skip-rust]
[ci skip-build-wheels]
  • Loading branch information
stuhood authored Oct 11, 2022
1 parent 31e3e10 commit 0b6eee2
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,40 @@ updatedAt: "2022-07-25T20:02:17.695Z"
2.15
----

### `EnvironmentName` is now required to run processes, get environment variables, etc

In order to support the new [environments](doc:environments) feature, an `EnvironmentName` parameter
is now required in order to:
* Run a `Process`
* Get environment variables
* Inspect the current `Platform`

Some deprecations are in place to reduce the burden on `@rule` authors:

#### `Goal.environment_migrated`

The `Goal` class has an `environment_migrated` property, which controls whether an `EnvironmentName` is automatically injected when a `@goal_rule` runs. When `environment_migrated=False` (the default), the `QueryRule` that is installed for a `@goal_rule` will include an `EnvironmentName`.

To migrate a `Goal`, set `environment_migrated=True`, select an `EnvironmentName` to use for (different portions of) your `Goal`, and then provide the `EnvironmentName` to the relevant callsites. In general, `Goal`s should use `EnvironmentNameRequest` to get `EnvironmentName`s for the targets that they will be operating on.
```python
Get(
EnvironmentName,
EnvironmentNameRequest,
EnvironmentNameRequest.from_field_set(field_set),
)
```
If rather than using the environment configured by a target your `Goal` should always be pinned to run in the local environment, you can instead request the `ChosenLocalEnvironmentName` and use its content as the `EnvironmentName`.

Then, the `EnvironmentName` should be used at `Get` callsites which require an environment:
```python
Get(TestResult, {field_set: TestFieldSet, environment_name: EnvironmentName})
```
The multi-parameter `Get` syntax provides the value transitively, and so will need to be used in many `Get` callsites in `@goal_rule`s which transitively run processes, consume the platform, etc. One exception is that (most of) the APIs provided by `pants.engine.target` are pinned to running in the `__local__` environment, and so do not require an `EnvironmentName` to use.

#### `RuleRunner.inherent_environment`

To reduce the number of changes necessary in tests, the `RuleRunner.inherent_environment` argument defaults to injecting an `EnvironmentName` when running `@rule`s in tests.

### `platform` kwarg for `Process` deprecated

Previously, we assumed processes were platform-agnostic, i.e. they had identical output on all
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class ListAndDieForTestingSubsystem(GoalSubsystem):

class ListAndDieForTesting(Goal):
subsystem_cls = ListAndDieForTestingSubsystem
environment_migrated = True


@goal_rule
Expand Down
1 change: 1 addition & 0 deletions src/python/pants/backend/project_info/dependees.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class DependeesSubsystem(LineOriented, GoalSubsystem):

class DependeesGoal(Goal):
subsystem_cls = DependeesSubsystem
environment_migrated = True


@goal_rule
Expand Down
1 change: 1 addition & 0 deletions src/python/pants/backend/project_info/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class DependenciesSubsystem(LineOriented, GoalSubsystem):

class Dependencies(Goal):
subsystem_cls = DependenciesSubsystem
environment_migrated = True


@goal_rule
Expand Down
1 change: 1 addition & 0 deletions src/python/pants/backend/project_info/filter_targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ def warn_deprecated_target_type(tgt_type: type[Target]) -> None:

class FilterGoal(Goal):
subsystem_cls = FilterSubsystem
environment_migrated = True


@goal_rule
Expand Down
1 change: 1 addition & 0 deletions src/python/pants/backend/project_info/list_roots.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class RootsSubsystem(LineOriented, GoalSubsystem):

class Roots(Goal):
subsystem_cls = RootsSubsystem
environment_migrated = True


@goal_rule
Expand Down
1 change: 1 addition & 0 deletions src/python/pants/backend/project_info/list_targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class ListSubsystem(LineOriented, GoalSubsystem):

class List(Goal):
subsystem_cls = ListSubsystem
environment_migrated = True


@goal_rule
Expand Down
1 change: 1 addition & 0 deletions src/python/pants/backend/project_info/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class PathsSubsystem(Outputting, GoalSubsystem):

class PathsGoal(Goal):
subsystem_cls = PathsSubsystem
environment_migrated = True


def find_paths_breadth_first(
Expand Down
21 changes: 21 additions & 0 deletions src/python/pants/engine/goal.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@

from typing_extensions import final

from pants.base.deprecated import deprecated_conditional
from pants.engine.unions import UnionMembership
from pants.option.option_types import StrOption
from pants.option.scope import ScopeInfo
from pants.option.subsystem import Subsystem
from pants.util.docutil import doc_url
from pants.util.meta import classproperty

if TYPE_CHECKING:
Expand Down Expand Up @@ -82,6 +84,25 @@ class List(Goal):
exit_code: int
subsystem_cls: ClassVar[Type[GoalSubsystem]]

f"""Indicates that a Goal has been migrated to compute EnvironmentNames to build targets in.
All goals in `pantsbuild/pants` should be migrated before the 2.15.x branch is cut, but end
user goals have until `2.17.0.dev0` to migrate.
See {doc_url('plugin-upgrade-guide')}.
"""
environment_migrated: ClassVar[bool] = False

@classmethod
def _get_environment_migrated(cls) -> bool:
deprecated_conditional(
lambda: not cls.environment_migrated,
"2.17.0.dev0",
f"Not setting `Goal.environment_migrated=True` for `Goal` `{cls.name}`",
hint=f"See {doc_url('plugin-upgrade-guide')}\n",
)
return cls.environment_migrated

@final
@classproperty
def name(cls) -> str:
Expand Down
16 changes: 12 additions & 4 deletions src/python/pants/init/engine_initializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import logging
from dataclasses import dataclass
from pathlib import Path
from typing import Any, ClassVar, Iterable, cast
from typing import Any, ClassVar, Iterable, Mapping, cast

from pants.base.build_environment import get_buildroot
from pants.base.build_root import BuildRoot
Expand Down Expand Up @@ -157,8 +157,8 @@ class GoalMappingError(Exception):
"""Raised when a goal cannot be mapped to an @rule."""

@staticmethod
def _make_goal_map_from_rules(rules):
goal_map = {}
def _make_goal_map_from_rules(rules) -> Mapping[str, type[Goal]]:
goal_map: dict[str, type[Goal]] = {}
for r in rules:
output_type = getattr(r, "output_type", None)
if not output_type or not issubclass(output_type, Goal):
Expand Down Expand Up @@ -286,12 +286,20 @@ def build_root_singleton() -> BuildRoot:
)
)

environment_migrated_goal_param_types = [
t for t in GraphSession.goal_param_types if t != EnvironmentName
]
rules = FrozenOrderedSet(
(
*rules,
# Install queries for each Goal.
*(
QueryRule(goal_type, GraphSession.goal_param_types)
QueryRule(
goal_type,
environment_migrated_goal_param_types
if goal_type._get_environment_migrated()
else GraphSession.goal_param_types,
)
for goal_type in goal_map.values()
),
# Install queries for each request/response pair used by the BSP support.
Expand Down

0 comments on commit 0b6eee2

Please sign in to comment.