-
-
Notifications
You must be signed in to change notification settings - Fork 636
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ci skip-rust] [ci skip-build-wheels]
- Loading branch information
Showing
7 changed files
with
200 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
--- | ||
title: "Environments: Cross-Platform or Remote Builds" | ||
slug: "environments" | ||
hidden: false | ||
createdAt: "2022-10-03T21:39:51.235Z" | ||
updatedAt: "2022-10-03T21:39:51.235Z" | ||
--- | ||
Environments | ||
============ | ||
|
||
By default, Pants will execute all sandboxed build work directly on localhost. But defining and using additional "environments" for particular targets allows Pants to transparently execute some or all of your build either: | ||
1. locally in Docker (_TODO: link?)_ containers | ||
2. remotely via [remote execution](doc:remote-execution) | ||
3. locally, but with a non-default set of environment variables and settings (such as for cross-building) | ||
|
||
## Defining environments | ||
|
||
Environments are defined using environment targets: | ||
|
||
* [`local_environment`](doc:reference-local_environment) - Runs without containerization on localhost (which is also the default if no environment targets are defined). | ||
* [`docker_environment`](doc:reference-docker_environment) - Runs in a cached container using the specified Docker image. | ||
* [`remote_environment`](doc:reference-remote_environment) - Runs in a remote worker via [remote execution](doc:remote-execution) (possibly with containerization, depending on the server implementation). | ||
|
||
Environment targets are given short, descriptive names using the [`[environments.names]` option](doc:reference-environments#names) (usually defined in `pants.toml`) for consuming targets to use to refer from them in `BUILD` files. That might look like a `pants.toml` section and `BUILD` file (at the root of the repository in this case) containing: | ||
|
||
```toml | ||
[environments.names] | ||
linux = "//:local_linux" | ||
linux_docker = "//:local_busybox" | ||
``` | ||
|
||
```python | ||
local_environment( | ||
name="local_linux", | ||
compatible_platforms=["linux_x86_64"], | ||
fallback_environment="local_busybox", | ||
.. | ||
) | ||
|
||
docker_environment( | ||
name="local_busybox", | ||
platform="linux_x86_64", | ||
image="busybox:latest@sha256-abcd123...", | ||
.. | ||
) | ||
``` | ||
|
||
### Environment-aware options | ||
|
||
Environment targets have fields (target arguments) which correspond to options which are marked "environment-aware" (_TODO: align naming_). When an option is environment-aware, the value of the option that will be used in an environment can be overridden by setting the corresponding field value on the environment target for that environment. If an environment target does not set a value, it defaults to the value which is set globally via options values. | ||
|
||
For example, the [`[python-bootstrap].search_path` option](doc:reference-python-bootstrap#search_path) is environment-aware, which is indicated in its help (_TODO: ensure these are marked in the generated help_). It can be overridden for a particular environment by a corresponding environment target field, such as [the one on `local_environment`](doc:reference-local_environment#codepython_bootstrap_search_pathcode). | ||
|
||
> 👍 See an option which should be environment-aware, but isn't? | ||
> | ||
> Environments are a new concept: if you see an option value which should be marked environment-aware but isn't, please definitely [file an issue](https://github.com/pantsbuild/pants/issues/new/choose)! | ||
## Consuming environments | ||
|
||
To declare which environment they should build with, many (_TODO: mark more_) target types (but particularly "root" targets like tests or binaries) have an `environment=` field: for example, [`python_tests(environment=..)`](doc:reference-python_tests#codeenvironmentcode). | ||
|
||
The `environment=` field may either: | ||
1. refer to an environment by name | ||
2. use the special `__local__` environment, which resolves to any matching `local_environment` (see "Environment matching" below) | ||
|
||
Test targets additionally have a `runtime_environment=` field (_TODO: see workflow below, and implement_) which defaults to the value of the target's `environment=` field, but which can be set explicitly to indicate that a test should execute in a different environment than it was built in. This can be used to enable cross-building (where a test is built on one platform, but executed on another), or to explicitly provide tools or running services at test runtime which would not otherwise be available. | ||
|
||
> 🚧 Environment compatibility | ||
> | ||
> Currently, there is no static validation that a target's environment is compatible with its dependencies' environments -- only the implicit validation of the goals that you run successfully against those targets (`check`, `lint`, `test`, `package`, etc). | ||
> | ||
> As we gain more experience with how environments are used in the wild, it's possible that more static validation can be added: your feedback would be very welcome! | ||
### Setting the environment on many targets at once | ||
|
||
To use an environment everywhere in your repository (or only within a particular subdirectory, or with a particular target | ||
type), you can use the [`__defaults__` builtin](doc:targets#field-default-values). For example, to use an environment named `my_default_environment` globally by default, you would add the following to a `BUILD` file at the root of the repository: | ||
```python | ||
__defaults__(all=dict(environment="my_default_environment")) | ||
``` | ||
... and individual targets could override the default as needed. | ||
|
||
### Environment matching | ||
|
||
A single environment name may end up referring to different environment targets on different physical machines, or with different global settings applied: this is known as environment "matching". | ||
|
||
* `local_environment` targets will match if their `compatible_platforms=` field matches localhost's platform. | ||
* `docker_environment` targets will match [if Docker is enabled](doc:reference-global#docker_execution), and if their `platform=` field is compatible with localhost's platform. | ||
* `remote_environment` targets will match [if Remote execution is enabled](doc:reference-global#remote_execution). | ||
|
||
It a particular environment target _doesn't_ match, it can configure a `fallback_environment=` which will be attempted next. This allows for forming preference chains which are referred to by whichever environment name is at the head of the chain. | ||
|
||
For example: a chain like "prefer remote execution if enabled, but fall back to local execution if the platform matches, otherwise use docker" might be configured via the targets: | ||
```python | ||
remote_environment( | ||
name="remote", | ||
fallback_environment="local", | ||
.. | ||
) | ||
|
||
local_environment( | ||
name="local", | ||
compatible_platforms=["linux_x86_64"], | ||
fallback_environment="docker", | ||
) | ||
|
||
docker_environment( | ||
name="docker", | ||
.. | ||
) | ||
``` | ||
|
||
In future versions, environment targets will gain additional predicates to control whether they match (for example: `local_environment` will likely gain a predicate that looks for the presence of an environment variable _TODO: open ticket_). But in the meantime, it's possible to override which environments are matched for particular use cases by overriding their configured names: see the "Toggle use of an environment" workflow below for an example. | ||
|
||
## Example workflows | ||
|
||
### Enabling remote execution globally | ||
|
||
`remote_environment` targets match unless the [`--remote-execution`](doc:reference-global#remote_execution) option is disabled. So to cause a particular environment name to use remote execution whenever it is enabled, you could define environment targets which tried remote execution first, and then fell back to local execution: | ||
|
||
```python | ||
remote_environment( | ||
name="remote_busybox", | ||
platform="linux_x86_64", | ||
extra_platform_properties={"container-image=busybox:latest"}, | ||
fallback_environment="local", | ||
) | ||
|
||
local_environment( | ||
name="local", | ||
compatible_platforms=[...], | ||
) | ||
``` | ||
|
||
You'd then give your `remote_environment` target an unassuming name like "default": | ||
```toml | ||
[environments.names] | ||
default = "//:remote_busybox" | ||
local = "//:local" | ||
``` | ||
... and use that environment by default with all targets. Users or consumers like CI could then toggle whether remote execution was used by (un)setting `--remote-execution`. | ||
|
||
_TODO: No speculation in `2.15.x`: it is definitely necessary for using remote execution locally, but it might not be necessary for CI use-cases._ | ||
|
||
### Execute a test in Docker, while natively cross-building it | ||
|
||
_TODO: Give an example of using `environment=` vs `runtime_environment=` to use docker only for test execution, but not for building of thirdparty dependencies by using PEX to cross-build. This will require exposing options out of PEX to override (?) the target platform. But figuring out how that doesn't break `check` is an open question._ | ||
|
||
### Toggle use of an environment for some consumers | ||
|
||
As mentioned above in "Environment matching", environment targets "match" based on their field values and global options. But if two environment targets would be ambiguous in some cases, or if you'd otherwise like to control what a particular environment name means (in CI, for example), you can override an environment name via options. | ||
|
||
For example: if you'd like to use a particular `macOS` environment target locally, but override it for a particular use case in CI, you'd start by defining two `local_environment` targets which would usually match ambiguously: | ||
|
||
```python | ||
local_environment( | ||
name="macos_laptop", | ||
compatible_platforms=["macos_x86_64"], | ||
) | ||
|
||
local_environment( | ||
name="macos_ci", | ||
compatible_platforms=["macos_x86_64"], | ||
) | ||
``` | ||
|
||
... and then assign one of them a (generic) environment name in `pants.toml`: | ||
```toml | ||
[environments.names] | ||
macos = "//:macos_laptop" | ||
... | ||
``` | ||
|
||
You could then _override_ that name definition in `pants.ci.toml` (note the use of the `.add` suffix, in order to preserve any other named environments): | ||
```toml | ||
[environments.names.add] | ||
macos = "//:macos_ci" | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters