cool-easter-32542
07/11/2025, 6:41 PMmacos-13 is closing down
The macOS 13 hosted runner image is closing down, following our N-1 OS support policy. This process will begin September 1, 2025, and the image will be fully retired on November 14, 2025. We recommend updating workflows to use macos-14 or macos-15.pantsbuild/pants
cool-easter-32542
07/11/2025, 11:30 PMpants --keep-sandboxes=always test projects/test_foo.py:tests -- -l
16:25:31.92 [INFO] Preserving local process execution dir /Users/jordan/git/pants.d/tmp/pants-sandbox-4DThMk for Run Pytest for projects/test_foo.py:tests
16:25:35.94 [INFO] Completed: Scheduling: Run Pytest for projects/test_foo.py:tests
16:25:35.94 [ERROR] Completed: Run Pytest - projects/test_foo.py:tests - failed (exit code 1).
============================= test session starts ==============================
platform darwin -- Python 3.11.11, pytest-7.4.4, pluggy-1.6.0
rootdir: /Users/jordan/git/pants.d/tmp/pants-sandbox-4DThMk
configfile: pytest.ini
plugins: asyncio-0.23.8, docker-3.2.3, xdist-3.7.0, cov-6.2.1, mock-3.14.1, opentelemetry-1.1.0, hypothesis-6.127.9
asyncio: mode=Mode.AUTO
collected 1 item
projects/test_foo.py F [100%]
=================================== FAILURES ===================================
___________________________________ test_foo ___________________________________
def test_foo():
print(os.getcwd())
extra = f"{os.getcwd()}/extra"
print(extra)
assert os.getcwd() in extra
> assert False, "this was actually successful"
E AssertionError: this was actually successful
E assert False
extra = '/Users/jordan/git/pants.dextra'
projects/test_foo.py:8: AssertionError
----------------------------- Captured stdout call -----------------------------
/Users/jordan/git/pants.d/tmp/pants-sandbox-4DThMk
/Users/jordan/git/pants.dextra
- generated xml file: /Users/jordan/git/pants.dprojects.test_foo.py.tests.xml -
=========================== short test summary info ============================
FAILED projects/test_foo.py::test_foo - AssertionError: this was actually successful
============================== 1 failed in 0.13s ===============================
✕ projects/test_foo.py:tests failed in 3.92s.
Note that:
• /tmp/pants-sandbox-4DThMk
is successfully printed in the terminal output: the first line in the capture output is /Users/jordan/git/pants.d/tmp/pants-sandbox-4DThMk
• /tmp/pants-sandbox-4DThMk/
is stripped from everywhere it should appear: the second line in the capture output is /Users/jordan/git/pants.dextra
, which is not a real path.
When re-running the __run.sh
script in the sandbox, all the terminal output is correct:
/Users/jordan/git/pants.d/tmp/pants-sandbox-4DThMk/__run.sh
================================================= test session starts ==================================================
platform darwin -- Python 3.11.11, pytest-7.4.4, pluggy-1.6.0
rootdir: /Users/jordan/git/pants.d/tmp/pants-sandbox-4DThMk
configfile: pytest.ini
plugins: asyncio-0.23.8, docker-3.2.3, xdist-3.7.0, cov-6.2.1, mock-3.14.1, opentelemetry-1.1.0, hypothesis-6.127.9
asyncio: mode=Mode.AUTO
collected 1 item
projects/test_foo.py F [100%]
======================================================= FAILURES =======================================================
_______________________________________________________ test_foo _______________________________________________________
def test_foo():
print(os.getcwd())
extra = f"{os.getcwd()}/extra"
print(extra)
assert os.getcwd() in extra
> assert False, "this was actually successful"
E AssertionError: this was actually successful
E assert False
extra = '/Users/jordan/git/pants.d/tmp/pants-sandbox-4DThMk/extra'
projects/test_foo.py:8: AssertionError
------------------------------------------------- Captured stdout call -------------------------------------------------
/Users/jordan/git/pants.d/tmp/pants-sandbox-4DThMk
/Users/jordan/git/pants.d/tmp/pants-sandbox-4DThMk/extra
--- generated xml file: /Users/jordan/git/pants.d/tmp/pants-sandbox-4DThMk/projects.test_foo.py.tests.xml ----
=============================================== short test summary info ================================================
FAILED projects/test_foo.py::test_foo - AssertionError: this was actually successful
================================================== 1 failed in 0.05s ===================================================
pantsbuild/pantscool-easter-32542
07/13/2025, 8:30 PMin_scope_types
on `@union`s.
Instead, we could derive the in-scope types from the signature of a polymorphic rule.
# Background
## Polymorphic Dispatch
Polymorphic rules allow dispatch based on runtime types of members of a union.
In the old call-by-type world, this meant that, given:
@union
class Base:
...
class Member1:
...
class Member2:
...
@rule
async def rule1(input: Member1) -> Result:
...
@rule
async def rule2(input: Member2) -> Result:
...
and the following union rule registrations:
UnionRule(Base, Member1),
UnionRule(Base, Member2),
Then await Get(Result, Base, input)
would dispatch to either rule1
or rule2
, depending on the type of input
. Note that Member1
and Member2
do not have to be Python subtypes of Base
, but it is very common that they are.
## In-scope Types
Unlike regular function dispatch, `@rule`s can consume `Param`s available at the callsite, even if not provided explicitly. For example, given
@rule
async def do_something(input: Input, other: Other) -> Result:
...
Then await Get(Result, Input, input)
will invoke do_something(...)
with the Other
argument provided from callsite context (e.g., if it was a parameter of the calling rule, or if some other rule can create it from parameters available to do_something(...)
.
This complicates matters for polymorphic dispatch, since we need the relevant polymorphic rules to have stable APIs, so that the caller knows which params to provide to `@rule`s it may not know about in advance.
This stability is achieved via the in_scope_types
argument to the @union
decorator:
@union(in_scope_types=[Other])
class Base:
...
This is a contract that polymorphic dispatch will provide the union member, and instances of each of the in_scope_types
, as params to the callees.
# Polymorphic Call-by-name
We are currently ]migrating](#21065) the codebase from call-by-type to call-by-name. Polymorphic call-by-name is implemented via a base @rule
tagged as polymorphic:
@rule(polymorphic=True)
async def base_rule(input: Base) -> Result:
...
So that a call await base_rule(**implicitly({input: Base}))
dispatches according to the runtime type of input
.
# Proposed Idiom
Once we are entirely call-by-name, we might consider the following changes, to make Pants rule graph polymorphism follow a more natural idiom:
1. Use subtyping instead of UnionRule
registration. Today it is already very common for union members to also be Python subclasses of the union type. So we might as well require it, and consult the MRO instead of explicitly registering unions.
2. Use the `base_rule`'s signature as the stable extension API, instead of in_scope_types
. For example, given
@rule(polymorphic=True)
async def base_rule(input: Base, other: Other) -> Result:
...
we can infer that Base
and Other
are the params that will be made available to the polymorphic variants.
This has the added advantage of being a property of the base rule, and not of the union itself, so that different rules that are polymorphic on the same type can have different in-scope types.
This change will require the `base_rule`'s definition to be available where in_scope_types
are currently consumed, which may require some plumbing.
pantsbuild/pantscool-easter-32542
07/14/2025, 1:19 AM21:16:12.68 [DEBUG] Launching 1 roots (poll=true).
every second to the .pants.d/workdir/pants.log
file which is just adding no new information. Ideally, pantsd would not be writing that message and filling up the log unnecessarily. This seems to happen after I ran a Pants command with -ldebug
.
This is with Pants 2.27.0.
pantsbuild/pantscool-easter-32542
07/14/2025, 6:00 PMbuildx
to build a docker image, you may have multiple buildx drivers configured on your system where you want to choose one for pants to use.
Describe the solution you'd like
I'd like
• a global configuration for the docker subsystem (overridable in a docker_image configuration) that allows for selecting the buildx driver by name
• this is used to set the --builder
argument used in the docker buildx build
command that pants launches (see https://docs.docker.com/reference/cli/docker/buildx/#builder)
Describe alternatives you've considered
The only alternatives I am aware of include
1. Setting the buildx driver outside of pants configuration by setting the default with https://docs.docker.com/reference/cli/docker/buildx/use/
2. Setting BUILDX_BUILDER=<your driver of choice>
environment variable as a [docker.env_vars]
Additional context
• This builds on the work started in #15199
• See more context in this thread: https://pantsbuild.slack.com/archives/C046T6T9U/p1751926012583459
pantsbuild/pantscool-easter-32542
07/15/2025, 6:32 AMrun
command.
Describe the solution you'd like
extra_run_args
field on docker_image
target, akin to the extra_build_args
.
Describe alternatives you've considered
CLI mess
Additional context
N/A
pantsbuild/pantscool-easter-32542
07/15/2025, 12:39 PMcool-easter-32542
07/15/2025, 6:53 PMengine
crate is both the primary crate in Pants and also the root of the Rust workspace. I'd like to reorganize the Rust sources to break that conjunction.
src/rust
would become the new workspace root. All crates one level below engine
would be moved to src/rust
. For example, src/rust/engine/process_execution
becomes src/rust/process_execution
. The crates underneath process_execution
(like src/rust/engine/process_execution/remote
) would still live under src/rust/process_execution
since they are arguably thematically related.
src/rust/engine/Cargo.toml
would be split into the workspace-specific part and the engine
-specific part. Currently, it serves dual purposes.
Benefits:
1. Easier to understand engine
since its top-level directory is not polluted with every other crate.
2. The workspace Cargo.toml
will be separate from the engine
Cargo.toml
. It will make it easier for readers to reason about the workspace and engine
.
pantsbuild/pantscool-easter-32542
07/21/2025, 1:41 PMdocker build .
), there are no issues.
Pants version
2.27
OS
Ubuntu 22.04
Additional info
BUILD
docker_image(
name="docker",
)
python_requirements(
name="reqs",
source="pyproject.toml",
)
```
pants --print-stacktrace -ldebug package myproject:docker
[2025-07-21T133209Z DEBUG pantsd] Looking for pantsd metadata in /home/user/IdeaProjects/analytics/.pants.d/pids as specified by [GLOBAL] pants_subprocessdir = .pants.d/pids via Default.
[2025-07-21T133209Z DEBUG pantsd] Parsed port 41109 from /home/user/IdeaProjects/analytics/.pants.d/pids/278be61e79f6/pantsd/socket.
163210.17 [DEBUG] acquiring lock: <pants.pantsd.lock.OwnerPrintingInterProcessFileLock object at 0x7aa9a76bfc10>
163210.17 [DEBUG] terminating pantsd
163210.17 [DEBUG] sending signal 15 to pid 64400
163210.27 [DEBUG] successfully terminated pid 64400
163210.27 [DEBUG] purging metadata directory: /home/user/IdeaProjects/analytics/.pants.d/pids/278be61e79f6/pantsd
163210.27 [DEBUG] Launching pantsd
163210.27 [DEBUG] purging metadata directory: /home/user/IdeaProjects/analytics/.pants.d/pids/278be61e79f6/pantsd
163210.28 [DEBUG] pantsd command is: PANTS_DAEMON_ENTRYPOINT=pants.pantsd.pants_daemon:launch_new_pantsd_instance PYTHONPATH=/home/user/.cache/nce/5c54a0c25255df2afb0525da856d49eb81b48cff0e32a9c868f77a296af24319/bindings/venvs/2.27.0/bin/home/user/.cache/nce/4dd2c710a828c8cfff384e0549141016a563a5e153d2819a7225ccc05a1a17c7/cpython 3.11.13+20250612 x86 64 unknown linux gnu install only.tar.gz/python/lib/python311.zip/home/user/.cache/nce/4dd2c710a828c8cfff384e0549141016a563a5e153d2819a7225ccc05a1a17c7/cpython-3.11.13+20250612-x86_64-unknown-linux-gnu-install_only.tar.gz/python/lib/python3.11/home/user/.cache/nce/4dd2c710a828c8cfff384e0549141016a563a5e153d2819a7225ccc05a1a17c7/cpython 3.11.13+20250612 x86 64 unknown linux gnu install only.tar.gz/python/lib/python3.11/lib dynload/home/user/.cache/nce/5c54a0c25255df2afb0525da856d49eb81b48cff0e32a9c868f77a296af24319/bindings/venvs/2.27.0/lib/python3.11/site-packages /home/user/.cache/nce/5c54a0c25255df2afb0525da856d49eb81b48cff0e32a9c868f77a296af24319/bindings/venvs/2.27.0/bin/python3.11 /home/user/.cache/nce/5c54a0c25255df2afb0525da856d49eb81b48cff0e32a9c868f77a296af24319/bindings/venvs/2.27.0/bin/pants --print-stacktrace -ldebug package myproject:docker
163212.68 [DEBUG] pantsd is running at pid 66871, pailgun port is 34489
163212.68 [DEBUG] releasing lock: <pants.pantsd.lock.OwnerPrintingInterProcessFileLock object at 0x7aa9a76bfc10>
163212.68 [DEBUG] Connecting to pantsd on port 34489
163212.68 [DEBUG] Connecting to pantsd on port 34489 attempt 1/3
163212.68 [DEBUG] Connected to pantsd
163212.68 [DEBUG] work dir: /home/user/IdeaProjects/analytics
163212.68 [DEBUG] Found BuildRoot("/home/user/IdeaProjects/analytics") starting search from /home/user/IdeaProjects/analytics.
163212.69 [DEBUG] Launching 1 roots (poll=false).
163212.69 [DEBUG] Found BuildRoot("/home/user/IdeaProjects/analytics") starting search from /home/user/IdeaProjects/analytics.
163212.70 [DEBUG] computed 1 nodes in 0.009718 seconds. there are 10 total nodes.
163212.70 [DEBUG] Launching 1 roots (poll=false).
163212.70 [DEBUG] computed 1 nodes in 0.000305 seconds. there are 14 total nodes.
163212.83 [DEBUG] Found BuildRoot("/home/user/IdeaProjects/analytics") starting search from /home/user/IdeaProjects/analytics.
163212.84 [INFO] Initializing scheduler...
163212.86 [DEBUG] File handle limit is: 1048576
163212.87 [DEBUG] No sandboxer configured.
163212.87 [DEBUG] Initializing Nailgun pool for 32 processes...
163212.87 [DEBUG] Using [cache::CommandRunner { inner: bounded::CommandRunner { inner: SwitchedCommandRunner { .. }, .. }, .. }, cache::CommandRunner { inner: bounded::CommandRunner { inner: SwitchedCommandRunner { .. }, .. }, .. }] for process execution.
163212.87 [DEBUG] Rule graph: building...
163212.87 [DEBUG] Rule graph: validating rule IDs...
163212.87 [DEBUG] Rule graph: building initial polymorphic graph...
163213.16 [DEBUG] Rule graph: labelling live variables...
163213.23 [DEBUG] Rule graph: monomophizing graph...
163214.36 [DEBUG] Rule graph: pruning edges...
163214.40 [DEBUG] Rule graph: finalizing...
163214.41 [DEBUG] Rule graph: built in 1.539s
163214.41 [DEBUG] Changes to /home/user/.cache/nce/5c54a0c25255df2afb0525da856d49eb81b48cff0e32a9c868f77a296af24319/bindings/venvs/2.27.0/bin, outside of the buildroot, will not be invalidated.
163214.41 [DEBUG] Changes to /home/user/.cache/nce/5c54a0c25255df2afb0525da856d49eb81b48cff0e32a9c868f77a296af24319/bindings/venvs/2.27.0/bin, outside of the buildroot, will not be invalidated.
163214.41 [DEBUG] Changes to /home/user/.cache/nce/4dd2c710a828c8cfff384e0549141016a563a5e153d2819a7225ccc05a1a17c7/cpython-3.11.13+20250612-x86_64-unknown-linux-gnu-install_only.tar.gz/python/lib/python311.zip, outside of the buildroot, will not be invalidated.
163214.41 [DEBUG] Changes to /home/user/.cache/nce/4dd2c710a828c8cfff384e0549141016a563a5e153d2819a7225ccc05a1a17c7/cpython-3.11.13+20250612-x86_64-unknown-linux-gnu-install_only.tar.gz/python/lib/python3.11, outside of the buildroot, will not be invalidated.
163214.41 [DEBUG] Changes to /home/user/.cache/nce/4dd2c710a828c8cfff384e0549141016a563a5e153d2819a7225ccc05a1a17c7/cpython-3.11.13+20250612-x86_64-unknown-linux-gnu-install_only.tar.gz/python/lib/python3.11/lib-dynload, outside of the buildroot, will not be invalidated.
163214.41 [DEBUG] Changes to /home/user/.cache/nce/5c54a0c25255df2afb0525da856d49eb81b48cff0e32a9c868f77a296af24319/bindings/venvs/2.27.0/lib/python3.11/site-packages, outside of the buildroot, will not be invalidated.
163214.41 [DEBUG] setting up service <pants.pantsd.service.scheduler_service.SchedulerService object at 0x7aadc7f48c10>
163214.41 [DEBUG] setting up service <pants.pantsd.service.store_gc_service.StoreGCService object at 0x7aada59161d0>
163214.41 [DEBUG] starting service <pants.pantsd.service.scheduler_service.SchedulerService object at 0x7aadc7f48c10>
163214.41 [DEBUG] starting service <pants.pantsd.service.store_gc_service.StoreGCService object at 0x7aada59161d0>
163214.41 [INFO] Scheduler initialized.
163214.41 [DEBUG] Launching 1 roots (poll=false).
163214.42 [DEBUG] computed 1 nodes in 0.000233 seconds. there are 14 total nodes.
163214.42 [DEBUG] Launching 1 roots (poll=false).
163214.42 [DEBUG] computed 1 nodes in 0.000109 seconds. there are 14 total nodes.
163214.46 [DEBUG] specs are: Specs(includes=RawSpecs(description_of_origin='CLI arguments', address_literals=(AddressLiteralSpec(path_component='myproject', target_component='docker', generated_component=None, parameters=FrozenDict({})),), file_literals=(), file_globs=(), dir_literals=(), dir_globs=(), recursive_globs=(), ancestor_globs=(), unmatched_glob_behavior=<GlobMatchErrorBehavior.error: 'error'>, filter_by_global_options=True, from_change_detection=False), ignores=RawSpecs(description_of_origin='CLI arguments', address_literals=(), file_literals=(), file_globs=(), dir_literals=(), dir_globs=(), recursive_globs=(), ancestor_globs=(), unmatched_glob_behavior=<GlobMatchErrorBehavior.error: 'error'>, filter_by_global_options=False, from_change_detection=False))
163214.46 [DEBUG] changed_options are: ChangedOptions(since=None, diffspec=None, dependents=<DependentsOption.NONE: 'none'>)
163214.46 [DEBUG] Launching 1 roots (poll=false).
163214.46 [DEBUG] Found BuildRoot("/home/user/IdeaProjects/analytics") starting search from /home/user/IdeaProjects/analytics.
163214.47 [DEBUG] computed 1 nodes in 0.010404 seconds. there are 17 total nodes.
163214.47 [DEBUG] Launching 1 roots (poll=false).
163214.47 [DEBUG] computed 1 nodes in 0.00044…
pantsbuild/pantscool-easter-32542
07/21/2025, 10:25 PMKUBERNETES_SERVICE_[HOST|PORT|PORT_HTTPS]
env_vars to the [docker] backend config of pants.toml
• consider explicitly setting buildx driver and namespace in the same env_vars config, like BUILDX_BUILDER=<your k8s buildx driver name>
, BUILDKIT_NAMESPACE=<your namespace>
• on the docker_image
target, set output={"type": "registry"}
• don't run pants publish
on that target because pants package
will upload to the registry
### Premise
The ability of pants to optimally build docker images with pex files is pretty compelling (see this blog). This is made even better with buildx support in the pants docker backend, which enables multi-platform docker image builds.
Normally, with docker desktop installed, pants package
and pants publish
of a dockerimage target using buildx "just works". package
will build the image and store it locally, publish
can push it up to a registry.
However, I recently hit an issue moving the pants commands that worked on my laptop to a (Gitlab) CI job had some tricky failures to overcome.
### More about the CI environment
For our CI jobs, our workers run a Docker image that has the docker CLI installed. There have long been security concerns and complications running docker in docker (dind). For that reason, the team in charge of CI infrastructure at my company does not have a docker daemon running on the CI container (no socket). Instead, there's a kubernetes cluster of BuildKit workers available for building the images triggered by a docker buildx build
command.
On my laptop, I have the following build backend
% docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
default docker
\_ default \_ default running v0.23.2 linux/amd64 (+2), linux/arm64, linux/ppc64le, linux/s390x, (2 more)
desktop-linux* docker
\_ desktop-linux \_ desktop-linux running v0.23.2 linux/amd64 (+2), linux/arm64, linux/ppc64le, linux/s390x, (2 more)
In CI, we instead have
docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
ci* kubernetes
\_ buildkit-platform-amd64 \_ kubernetes:///ci?deployment=buildkit-platform-amd64&kubeconfig= running v0.21.1 linux/amd64 (+4), linux/386
\_ buildkit-platform-arm64 \_ kubernetes:///ci?deployment=buildkit-platform-arm64&kubeconfig= running v0.21.1 linux/arm64, linux/arm (+2)
default error
Cannot load builder default: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Notice "default" status is "error" and that last line... there's no default docker daemon
### Overcoming pants package
failure 1 – "cannot determine Kubernetes namespace"
On buildx version v0.19.2 I got
ERROR: no valid drivers found: cannot determine Kubernetes namespace, specify manually: invalid configuration: no configuration has been provided, try setting KUBERNETES_MASTER environment variable
And on the older buildx v0.11.1 I got
ERROR: no valid drivers found: cannot determine Kubernetes namespace, specify manually: stat /root/.kube/config: no such file or directory
There's no kubeconfig file because the CI worker pod is in-cluster, which means it should get its namespace and cluster information from the kubernetes server. To get this to work for docker buildx build
launched by pants, I had to pass the KUBERNETES_SERVICE_HOST
and KUBERNETES_SERVICE_PORT
environment vars to the docker backend's env_vars. With that info exposed, the docker buildx build
executed by pants was able to pull the info it needed to use the ci
buildx kubernetes driver.
### Overcoming pants package
failure 2 - "failed to copy to tar"
Next,pants package <docker_image target>
almost succeeded in building the image, but failed with the following error:
#7 ERROR: failed to copy to tar: rpc error: code = Unknown desc = io: read/write on closed pipe
Inspecting with pants -ldebug
, we see that pants is running the following command
/usr/bin/docker buildx build \
--platform=linux/amd64 \
--output=type=docker \
--pull=False \
--file ...
type=docker
cannot work as an output type for remote docker builds when there's no local docker engine running that can save the image. The solution was to set --output=type=registry
on the docker_image.
❗ This means there's no need for a pants publish
step: pants publish
pushes up an image from the local engine to a registry, but the output of pants package
on the docker_image target already was that registry.
### Putting it all together (working in pants v2.27.0)
pants.[ci.]toml
[docker]
use_buildx = true
env_vars = [
"BUILDX_BUILDER=ci",
"BUILDKIT_NAMESPACE=buildkit-platform",
"DOCKER_CONFIG=%(homedir)s/.docker",
"KUBERNETES_SERVICE_HOST",
"KUBERNETES_SERVICE_PORT",
"KUBERNETES_SERVICE_PORT_HTTPS",
...
]
build_verbose = true
BUILD target
docker_image(
output={"type": "registry"},
...
pantsbuild/pantscool-easter-32542
07/23/2025, 1:48 PM7.0.1
.
• There are lots of feature additions and bug improvements between pytest 7.0.1
and 8.4.1
. At least in my case, many of the desired features translate to much broader pytest configuration control centralized in my codebase's pyproject.toml
.
• Moving to pytest 8.x would also mitigate a number of deprecation warnings that stem from older versions of pytest (see related issue thread here for one such example impacting us at the moment).
## Solution Description
• Bump the default version of pytest to 8.x
.
## Alternatives Considered
• Modify the pytest version in our project. Not totally opposed to this, but I wanted to see if there's any reason not to bump the version at the source.
pantsbuild/pantscool-easter-32542
07/25/2025, 2:41 PMAbstract{Lint/Fmt/Fix}Request
, and subclasses of those for each tool, plus a .Batch
nested class that is distinct for each enclosing class (via a @distinct_union_type_per_subclass
annotation). And then there are also {Lint/Fix}{Targets/Files}Request
which are also subclasses of the Abstract{Lint/Fmt/Fix}Request
types, and these are mixed in odd ways. And then there are also is_fixer
and is_formatter
booleans on those types. It's a lot.
pantsbuild/pantscool-easter-32542
07/25/2025, 6:12 PMpackage
goal
233029.03 [DEBUG] computed 1 nodes in 29.739843 seconds. there are 14019 total nodes.
233029.03 [ERROR] 1 Exception encountered:
Engine traceback:
in root
..
in pants.core.goals.package.package_asset
package
goal
Traceback (most recent call last):
File "/Users/chenwuhao/Library/Caches/nce/0bb9722222f003de9629623179038ecab5b6bd747796b95272e1d271dba00578/bindings/venvs/2.20.0a0/lib/python3.9/site-packages/pants/core/goals/package.py", line 165, in package_asset
packages = await MultiGet(
File "/Users/chenwuhao/Library/Caches/nce/0bb9722222f003de9629623179038ecab5b6bd747796b95272e1d271dba00578/bindings/venvs/2.20.0a0/lib/python3.9/site-packages/pants/engine/internals/selectors.py", line 376, in MultiGet
return await _MultiGet(tuple(__arg0))
File "/Users/chenwuhao/Library/Caches/nce/0bb9722222f003de9629623179038ecab5b6bd747796b95272e1d271dba00578/bindings/venvs/2.20.0a0/lib/python3.9/site-packages/pants/engine/internals/selectors.py", line 174, in await
result = yield self.gets
File "/Users/chenwuhao/Library/Caches/nce/0bb9722222f003de9629623179038ecab5b6bd747796b95272e1d271dba00578/bindings/venvs/2.20.0a0/lib/python3.9/site-packages/pants/core/goals/package.py", line 116, in environment_aware_package
package = await Get(
File "/Users/chenwuhao/Library/Caches/nce/0bb9722222f003de9629623179038ecab5b6bd747796b95272e1d271dba00578/bindings/venvs/2.20.0a0/lib/python3.9/site-packages/pants/engine/internals/selectors.py", line 124, in await
result = yield self
File "/Users/chenwuhao/Library/Caches/nce/0bb9722222f003de9629623179038ecab5b6bd747796b95272e1d271dba00578/bindings/venvs/2.20.0a0/lib/python3.9/site-packages/pants/backend/docker/goals/package_image.py", line 470, in build_docker_image
raise ProcessExecutionFailure(
pants.engine.process.ProcessExecutionFailure: Process 'Building docker image europe-west2-docker.pkg.dev/spacedevice/spacedevice-dev/executor/img:latest' failed with exit code 125.
stdout:
stderr:
unknown flag: --output
See 'docker --help'.
Usage: docker [OPTIONS] COMMAND
A self-sufficient runtime for containers
Common Commands:
run Create and run a new container from an image
exec Execute a command in a running container
ps List containers
build Build an image from a Dockerfile
pull Download an image from a registry
push Upload an image to a registry
images List images
login Log in to a registry
logout Log out from a registry
search Search Docker Hub for images
version Show the Docker version information
info Display system-wide information
Management Commands:
builder Manage builds
container Manage containers
context Manage contexts
image Manage images
manifest Manage Docker image manifests and manifest lists
network Manage networks
plugin Manage plugins
system Manage Docker
trust Manage trust on Docker images
volume Manage volumes
Swarm Commands:
swarm Manage Swarm
Commands:
attach Attach local standard input, output, and error streams to a running container
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
events Get real time events from the server
export Export a container's filesystem as a tar archive
history Show the history of an image
import Import the contents from a tarball to create a filesystem image
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
save Save one or more images to a tar archive (streamed to STDOUT by default)
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
wait Block until one or more containers stop, then print their exit codes
Global Options:
--config string Location of client config files (default ".docker")
-c, --context string Name of the context to use to connect to the
daemon (overrides DOCKER_HOST env var and
default context set with "docker context use")
-D, --debug Enable debug mode
-H, --host list Daemon socket to connect to
-l, --log-level string Set the logging level ("debug", "info",
"warn", "error", "fatal") (default "info")
--tls Use TLS; implied by --tlsverify
--tlscacert string Trust certs signed only by this CA (default
".docker/ca.pem")
--tlscert string Path to TLS certificate file (default
".docker/cert.pem")
--tlskey string …
pantsbuild/pantscool-easter-32542
07/25/2025, 6:12 PMpants package ::
:
[ERROR] 1 Exception encountered:
Engine traceback:
in `package` goal
DockerBuildContextError: Undefined value for build arg on the <redacted>:app target: The Docker environment variable 'GITHUB_SHA' is undefined. You may provide a value for this variable either in `[docker].env_vars` or in Pants's own environment.
If you did not intend to inherit the value for this build arg from the environment, provide a default value with the option `[docker].build_args` or in the `extra_build_args` field on the target definition. Alternatively, you may also provide a default value on the `ARG` instruction directly in the `Dockerfile`.
Pants version
2.15.0
OS
Mac OS M1 Max
pantsbuild/pantscool-easter-32542
07/25/2025, 6:12 PMlocal_environment(
name="local-environment",
subprocess_environment_env_vars=env_vars_devcontainer(),
)
where th subprocesse environment variables are defined in my macros.py. Furthermode I added this environment to my pants.toml:
[environments-preview.names]
local = "//:local-environment"
In my local environment I defined an environment variable, let's call it ENV_VAR=true. I want this environment variable to have a different value for tests, so I add
[test]
extra_env_vars = ["ENV_VAR=false"]
in the pants.toml but that is somehow ignored by pants. ENV_VAR is still on true, when I run pants test
Pants version
Which version of Pants are you using?
2.16.0rc5
OS
Are you encountering the bug on MacOS, Linux, or both?
Linux
Additional info
Add any other information about the problem here, such as attachments or links to gists, if relevant.
pantsbuild/pantscool-easter-32542
07/25/2025, 6:12 PMenvironments
breaks the docker build process in CI/CD and complains that the DOCKER_HOST
is in the wrong place.
---
We have a docker_image
that depends on a pex_binary
BUILD
pex_binary(
name = "bin",
dependencies = [
":lib",
],
execution_mode = "venv",
include_tools = True,
layout = "packed",
)
docker_image(
name = "docker",
dependencies = [
":docker_resources",
":bin",
],
image_tags = ["{build_args.PANTS_DISTRIBUTION_VERSION}"],
)
Due to some wheel compatibility issues, we cannot build this pex_binary
(and subsequent docker_image
) on our Macs, it only works up in CI/CD (self-hosted GitHub Actions runners) where the machine is linux_x86
.
To resolve this issue for ourselves locally, we enabled the environments
feature
BUILD
local_environment(
name="local_linux_x86",
description="Localhost x86 Linux Environment",
compatible_platforms=["linux_x86_64"],
fallback_environment="docker_x86",
)
docker_environment(
name="local_docker_x86",
description="Dockerized x86 Linux Environment",
platform="linux_x86_64",
image="python:3.8.16",
)
And we attached the environment to the pex_binary
BUILD
pex_binary(
name = "bin",
dependencies = [
":lib",
],
execution_mode = "venv",
include_tools = True,
layout = "packed",
environment = "local_linux_x86",
)
The idea here is that the pex_binary
needs to be built on a linux_x86_64
platform and when that platform isn't available locally it should just use the docker_environment
.
This solution is working for us locally, but when we run it up in CI/CD it no longer works. Here is the issue that we're seeing in CI/CD:
Log Output
15:54:05.51 [DEBUG] Starting: Scheduling: Building docker image ***.<http://dkr.ecr.us-east-1.amazonaws.com/moz-batch-job:16.0.0-beta.1|dkr.ecr.us-east-1.amazonaws.com/moz-batch-job:16.0.0-beta.1>
15:54:05.54 [DEBUG] Starting: acquire_command_runner_slot
15:54:19.81 [DEBUG] Completed: setup_sandbox
15:54:19.86 [DEBUG] spawned local process as Some(1133) for Process { argv: ["/usr/bin/docker", "build", "--pull=False", "--tag", "***.<http://dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:latest|dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:latest>", "--tag", "***.<http://dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:16.0.0-beta.1|dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:16.0.0-beta.1>", "--build-arg", "PANTS_DISTRIBUTION_VERSION", "--file", "services/moz-helper-services/Dockerfile", "."], env: {"PANTS_DISTRIBUTION_VERSION": "16.0.0-beta.1", "PATH": "/tmp/pants-sandbox-q6Zu6z/.shims/bin", "__UPSTREAM_IMAGE_IDS": ""}, working_directory: None, input_digests: InputDigests { complete: DirectoryDigest { digest: Digest { hash: Fingerprint<2c4455e78a6e491e19a07eca09e00a2fc9d026b6e428026680cb253cbbf4d541>, size_bytes: 264 }, tree: "Some(..)" }, nailgun: DirectoryDigest { digest: Digest { hash: Fingerprint<e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855>, size_bytes: 0 }, tree: "Some(..)" }, input_files: DirectoryDigest { digest: Digest { hash: Fingerprint<79b1e31b408edaf0ecb646a2deaf492f0d62436d46c7e020659821ef142b3191>, size_bytes: 184 }, tree: "Some(..)" }, immutable_inputs: {RelativePath(".shims"): DirectoryDigest { digest: Digest { hash: Fingerprint<e6c1927a092ff6beaa1fa4f372248c975cb51869b1c28245cb0281ebc6816ecb>, size_bytes: 78 }, tree: "Some(..)" }}, use_nailgun: {} }, output_files: {}, output_directories: {}, timeout: None, execution_slot_variable: None, concurrency_available: 0, description: "Building docker image ***.<http://dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:latest|dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:latest> +1 additional tag.", level: Info, append_only_caches: {}, jdk_home: None, platform: Linux_x86_64, cache_scope: PerSession, execution_strategy: Local, remote_cache_speculation_delay: 0ns }
15:54:19.89 [INFO] Completed: Building docker image ***.<http://dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:latest|dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:latest> +1 additional tag.
15:54:19.89 [DEBUG] Completed: Scheduling: Building docker image ***.<http://dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:latest|dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:latest> +1 additional tag.
15:54:19.89 [DEBUG] Completed: acquire_command_runner_slot
15:54:19.89 [DEBUG] Running Building docker image ***.<http://dkr.ecr.us-east-1.amazonaws.com/moz-result-processor:16.0.0-beta.1|dkr.ecr.us-east-1.amazonaws.com/moz-result-processor:16.0.0-beta.1> under semaphore with concurrency id: 1, and concurrency: 1
15:54:19.89 [INFO] Starting: Building docker image ***.<http://dkr.ecr.us-east-1.amazonaws.com/moz-result-processor:16.0.0-beta.1|dkr.ecr.us-east-1.amazonaws.com/moz-result-processor:16.0.0-beta.1>
15:54:19.89 [DEBUG] Starting: setup_sandbox
15:54:19.89 [WARN] Docker build failed for `docker_image` services/moz-helper-services:docker. The services/moz-helper-services/Dockerfile has `COPY` instructions for source files that may not have been found in the Docker build context.
However there are possible matches. Please review the following list of suggested renames:
* services.moz-helper-services/bin.pex => services/moz-helper-services
15:54:19.90 [DEBUG] Completed: `publish` goal
15:54:19.90 [DEBUG] computed 1 nodes in 44.638043 seconds. there are 13299 total nodes.
15:54:19.90 [ERROR] 1 Exception encountered:
Engine traceback:
in select
..
in pants.core.goals.publish.run_publish
`publish` goal
in pants.core.goals.publish.package_for_publish
..
in pants.core.goals.package.environment_aware_package
..
in pants.backend.docker.goals.package_image.build_docker_image
..
Traceback (most recent call last):
File "/home/runner/.cache/pants/setup/bootstrap-Linux-x86_64/2.15.1rc2_py38/lib/python3.8/site-packages/pants/engine/internals/selectors.py", line 593, in native_engine_generator_send
res = func.send(arg)
File "/home/runner/.cache/pants/setup/bootstrap-Linux-x86_64/2.15.1rc2_py38/lib/python3.8/site-packages/pants/backend/docker/goals/package_image.py", line 309, in build_docker_image
raise ProcessExecutionFailure(
pants.engine.process.ProcessExecutionFailure: Process 'Building docker image ***.<http://dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:latest|dkr.ecr.us-east-1.amazonaws.com/moz-helper-services:latest> +1 additional tag.' failed with exit code 1.
stdout:
stderr:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
As far as I can tell, enabling the environments
feature confuses pants
about where the DOCKER_HOST
should be (our GitHub runners have DOCKER_HOST
set to unix:///run/docker/docker.sock
instead of the default unix:///var/run/docker.sock
). We pass this environment variable down in our pants.toml
file though:
pants.toml
[docker]
env_vars = [
"DOCKER_CONFIG=%(homedir)s/.docker",
"DOCKER_DEFAULT_PLATFORM=linux/amd64",
"HOME",
"USER",
"PATH",
# used by action-runner-controller dind
"DOCKER_CERT_PATH",
"DOCKER_HOST",
"DOCKER_TLS_VERIFY",
]
tools = [
"dirname",
"readlink",
"python3",
# These may be necessary if using Pyenv-installed Python.
"cut",
"sed",
"bash",
"sh",
]
default_repository = "{directory}"
build_args = ["PANTS_DISTRIBUTION_VERSION"]
For solutions to this we've tried upgrading to pants==2.15.1rc2
, removing the local_environment
completely and just using the docker_environment
, and also using pants.ci.toml
to override which environment to use, and even hardcoding the DOCKER_HOST
env var inside of pants.ci.toml
.
All of this worked within CI/CD when we specify no environments at all, but doesn't work locally. However it works lo…
pantsbuild/pantscool-easter-32542
08/01/2025, 8:32 AMcelery
in the following) to the example-django
repository causes ./pants check
to fail with the following error:
ModuleNotFoundError: No module named 'celery'
See the slack discussion: https://app.slack.com/client/T046T6T8L/C046T6T9U/thread/C046T6T9U-1661627014.305049
Pants version
2.12.0
OS
Linux
Additional info
The root cause is that the mypy_django_plugin
needs to load the Django models at the start, which it cannot do without the dependencies installed in the mypy virtual environment.
Adding celery
to extra_requirements
under [mypy]
in pants.toml
removes this error, but this seems to be a hack. In my actual repo, I would need to add around fifty requirements here, which would be difficult to maintain.
Excerpt from the slack discussion:
[Screenshot from 2022-09-01 13-10-45](https://user-images.githubusercontent.com/7020472/187844053-ea672538-e8ca-49d3-abf8-26fe7ab9fb99.png)▾
cool-easter-32542
08/03/2025, 9:34 PMRUN --mount=type=cache,target=/tmp/pex-cache,sharing=locked ...
I'm hoping to wrap all this up into a few macros or some kind of assistance so every time a team member adds a new image we don't have to go through the back-and-forth of discovering poor build times and fixing them.
I tried using adhoc_tool
to inject the commands, but no matter how I spell the dependencies or sources, I can't get it to accept the generated Dockerfile.
I think the simplest thing (although I don't understand the finer points of pants backends) might be to add an experimental_wrap_as_dockerfile
target.
I see there's some prior discussion, but as far as I can find there's not been a resolution:
• #17926
• #17877
• #13360
Thank you!
Kevin
pantsbuild/pantscool-easter-32542
08/08/2025, 6:49 PMyaml
comment strings, will break Pants dependency inference. An example in the wild is the official Airflow Helm chart, e.g. this template: https://github.com/apache/airflow/blob/main/chart/templates/jobs/create-user-job.yaml
These "manifest" files end up only containing yaml
comment lines. E.g. for the above example we will end up with (when the "create user job" is disabled):
################################
## Airflow Create User Job
#################################
which hikaru
cannot parse (key error looking for apiVersion
), and the k8s_parser
will fail.
Fix proposed here: #22565
pantsbuild/pantscool-easter-32542
08/15/2025, 1:20 PMrm -rf .pants.d
. This stickiness is even persisting across CI runs, which I'm guessing has to do with the way pantsbuild/actions/init-pants@v4-scie-pants
sets up Pants.
Pants version
2.19.1
OS
Both my intel mac and the intel linux our CI runs on.
Additional info
Add any other information about the problem here, such as attachments or links to gists, if relevant.
pantsbuild/pantscool-easter-32542
08/15/2025, 1:33 PMinterpreter_constraints
and resolve
fields. Resolves themselves also have interpreter constraints set in pants.toml
. By default, the interpreter_constraints
on Python targets defaults to the [python].interpreter_constraints
field in pants.toml
. However, if you have multiple resolves with different interpreter constraints, you now have to set the interpreter constraints on each Python source file to be a subset of the constraints of its resolve.
Describe the solution you'd like
There should be an option in the Python subsystem to allow Python targets with a resolves
field to fall back to the interpreter constraints of their resolve instead of the global constraints.
Describe alternatives you've considered
I use a macro to make the resolve constraints and source file constraints match today, but this means constraints must be updated and match in multiple spots instead of just having pants.toml
as the single source of truth.
pantsbuild/pantscool-easter-32542
08/16/2025, 1:06 PM__defaults__(
{
"docker_image": dict(
image_tags=[
"{pants.hash}",
env("BRANCH_NAME"),
env("COMMIT_SHA"),
env("TIMESTAMP"), # e.g., "main-20240116-123456"
],
),
}
)
# base/BUILD
docker_image(name="image", source="Dockerfile")
# app/BUILD
docker_image(name="image", source="Dockerfile")
# app/Dockerfile
FROM base:image
# ... rest of dockerfile
### What Happens
1. When building app:image, Pants builds the upstream base:image first
2. The base:image is packaged as a BuiltPackage which includes metadata
containing all the image tags
3. This metadata (including the timestamp) becomes part of the package
digest
4. The package digest is included in the build context snapshot for
app:image
5. Since the timestamp changes on every build, the hash for app:image
changes even if nothing else has changed
### Impact
• Broken caching: Images are rebuilt unnecessarily because the hash
changes on every run
• Circular dependency with {pants.hash}: The hash depends on tags, but
{pants.hash} tag depends on the hash
• CI/CD inefficiency: Builds take longer and use more resources due to
unnecessary rebuilds
• Inconsistent image tags: The {pants.hash} value changes even when the
actual image content hasn't changed
### Reproduction Steps
1. Create two Docker targets where one depends on the other
2. Configure image_tags with dynamic values (e.g., using env() with
timestamps)
3. Run pants package //app:image multiple times
4. Observe that the hash changes each time (visible in the {pants.hash}
tag value)
### Expected Behavior
The hash should remain stable when:
• No source files have changed
• No dependencies have changed
• No build configuration has changed
The image_tags field should not affect the hash calculation because
tags are metadata about how to publish the image, not part of the image
content itself.
### Actual Behavior
The hash changes on every build when upstream Docker images have
dynamic tags, even when nothing else has changed.
Environment
• Pants version: 2.26.1 (and likely affects earlier/later versions)
• Occurs when using Docker image dependencies with dynamic tags
Describe the bug
A clear and concise description of the bug.
Pants version
Which version of Pants are you using?
OS
Are you encountering the bug on MacOS, Linux, or both?
Additional info
Add any other information about the problem here, such as attachments or links to gists, if relevant.
pantsbuild/pantscool-easter-32542
08/19/2025, 2:24 PMIntrinsicError: Failed to make named cache(s) for local execution: "Failed to create parent directory for named cache in Docker container:\nstdout:\n\nstderr:\nmkdir: cannot create directory ‘/pants-named-caches/python_build_standalone’: Permission denied\n\n"
The ephemeral container pants creates to build this pex using the ubi9 image shows the pants-immuatble-inputs and pants-sandbox are owned by 'default' and pants-named-caches is owned by root.
If I put the container in debug mode and chmod 775 pants-named-caches, the pex_binary build works fine.
I'm not sure what image this person was using, but it looks like there have been a few people running into this in slack: https://pantsbuild.slack.com/archives/C046T6T9U/p1687899481825509
pantsbuild/pantscool-easter-32542
08/20/2025, 8:39 PMgenerate-lockfiles
goal
ProcessExecutionFailure: Process 'Parse re/dac/ted/go.mod' failed with exit code 2.
stdout:
stderr:
go: unknown GOEXPERIMENT coverageredesign
Use --keep-sandboxes=on_failure
to preserve the process chroot for inspection.
My shell environment does not set GOEXPERIMENT; this appears to come from Pants’ Go backend. This worked with Go 1.24, but breaks with Go 1.25 because the coverageredesign experiment was removed from the toolchain:
• Tracking issue to remove the experiment: golang/go#55953
• Tracking issue to remove `GOEXPERIMENT=coverageredesign`: golang/go#57943
Expected behavior: Pants should not inject unsupported GOEXPERIMENT values. For Go ≥ 1.23 (and definitely in 1.25), coverageredesign is no longer a valid experiment and causes go to error out.
Pants version
2.25.1
OS
MacOS
Additional info
Workaround: roll back to go v1.24
pantsbuild/pantscool-easter-32542
08/21/2025, 9:29 AMjdk="temurin:21.0.8"
, then pants check
on java_sources
target hangs. It seems stuck at compilation. It works with Java 11 or 17
Pants version
2.27
OS
Linux
Additional info
Add any other information about the problem here, such as attachments or links to gists, if relevant.
pantsbuild/pantscool-easter-32542
08/21/2025, 2:14 PM-r
option to pex lock create
, the option is respected.
Pants version
2.27
OS
Both
pantsbuild/pantsquaint-telephone-89068
09/01/2025, 12:10 PMextra_build_args
in Docker image targets. When users try to pass target addresses as build arguments, Pants fails to resolve them to the actual built Docker image tags, causing build failures.
## Reproducing the Issue
Demo available in https://github.com/ademariag/pants-demo-bugs/tree/main/docker_args_test
This directory demonstrates the problem with a concrete example. The following configuration currently fails:
BUILD file:
docker_image(
name="base",
source="Dockerfile.base", # FROM ubuntu
)
docker_image(
name="base2",
source="Dockerfile.base2", # FROM alpine
)
docker_image(
name="main",
source="Dockerfile",
extra_build_args=[
"BASE_IMAGE=:base2" # Target reference - would not resolve properly
]
)
Dockerfile:
ARG BASE_IMAGE=:base
FROM ${BASE_IMAGE}
RUN echo "using ${BASE_IMAGE}"
The BASE_IMAGE=:base2
argument is not being resolved to the actual Docker image tag of the built :base2
target, causing the FROM ${BASE_IMAGE}
instruction to fail.
## Expected Behavior
The target reference :base2
in the extra_build_args
should be resolved to the actual Docker image tag produced by building the :base
target (e.g., sha256:abc123...
or a tagged name), allowing the Dockerfile's FROM ${BASE_IMAGE}
instruction to work correctly.
This would enable powerful Docker image composition patterns where one Docker image can reference another Pants-built Docker image as its base image through build arguments.
## Current Error
When running:
pants package docker_args_test:main
The build fails because ${BASE_IMAGE}
resolves to the literal string :base
instead of the actual built Docker image identifier, causing Docker's FROM
instruction to fail with an invalid image reference.
## Impact
This limitation prevents users from:
• Creating hierarchical Docker image dependencies within Pants
• Dynamically selecting base images through build arguments
• Composing complex Docker build pipelines where images depend on other Pants-built images
## Workaround
Currently, users must hardcode image tags or use external tooling to pass the correct image references, defeating the purpose of Pants' dependency management for Docker images.
Pants version
pants_version = "2.26.1"
OS
Linux
Additional info
Add any other information about the problem here, such as attachments or links to gists, if relevant.
pantsbuild/pantsquaint-telephone-89068
09/03/2025, 6:10 PMquaint-telephone-89068
09/04/2025, 6:51 AMquaint-telephone-89068
09/04/2025, 10:27 AM