I want to create a custom pants goal that packages...
# plugins
q
I want to create a custom pants goal that packages the relavant targets and then publishes them to an artifactory. I am not using
publish
because it does not support pexes. Ideally, I want to run the goal like this:
pants publish-pex :: --repo=repo1
There are a couple things that I am facing an issue with: 1. How do I filter out the relevant targets? Do I have to use
.has_field()
or can I check if it is a specific type of target like a
pex_binary
target? 2. How do I run the
package
goal before my own goal? Because if the targets have not been packaged, I want to run that and then upload the artifact to an artifactory 3. How do I provide cmd line args to my goal? Do I have to use
Options
? 4. Right now, I need to run a
Process
that executes a command to upload the artifact in JFrog artifactory. In that command, I can't use a relative path like
dist/abc/abc.pex
. I have to use an absolute path to it. I tried to give an
input_digest
to the
Process
command but that still doesn't work with relative paths.
w
Have you read the section on the website about writing plugins, and the tutorials? I think that should cover some of your questions above https://www.pantsbuild.org/2.21/docs/writing-plugins/overview
Also, reviewing similar plugins in the main repo would be a good next step
q
Yes I have done both. In the website, I was only able to find examples for filtering based on fields and not the particular target itself (example). As for running other goals before/after running my own custom goal, I didn't find anything in the docs for that. So I looked at the source code for the
publish
and
package
goals. They both run this command which I believe packages the artifacts: https://github.com/pantsbuild/pants/blob/3f1793623c56e7bf1e498495530757603a55250b/src/python/pants/core/goals/publish.py#L219 As for the other questions, I wasn't able to the necessary information for them
h
Why not augment the existing
publish
goal to act on
pex_binary
targets, rather than creating a new goal?
q
I had asked this question before as well. I think we need to use
UnionRules
for this? But the docs contains very little information about this. I was trying to create it but wasn't sure how to proceed with it. Also the issue with extending the
publish
goal is, it uses twine to upload whereas to upload pexes, I am using JFrog since twine cannot do it. So I will need to pass extra config options to the goal which would be confusing if it runs for both pexes and wheels
h
Yes, this is where unions come in. The generic
publish
goal (src/python/pants/core/goals/publish.py) doesn’t use Twine, the implementation for
python_distribution
(src/python/pants/backend/python/goals/publish.py) does. So you would need to add your own implementation for
pex_binary
.
So, you can follow the
python_distribution
example. E.g., you would subclass
PublishFieldSet
.
And
PublishRequest
There is an explanation at the top of src/python/pants/core/goals/publish.py
q
yes I saw this in the comments in the
publish
goal code. I am just new to writing pants goals so I was wondering if there were other examples of this where goals are extended? Also, in the
publish
and
package
goals, It doesn't take
Targets
as an argument to the
goal_rule
Instead, it runs this:
Copy code
target_roots_to_package_field_sets, target_roots_to_publish_field_sets = await MultiGet(
        Get(
            TargetRootsToFieldSets,
            TargetRootsToFieldSetsRequest(
                PackageFieldSet,
                goal_description="",
                # Don't warn/error here because it's already covered by `PublishFieldSet`.
                no_applicable_targets_behavior=NoApplicableTargetsBehavior.ignore,
            ),
        ),
        Get(
            TargetRootsToFieldSets,
            TargetRootsToFieldSetsRequest(
                PublishFieldSet,
                goal_description="the `publish` goal",
                no_applicable_targets_behavior=NoApplicableTargetsBehavior.warn,
            ),
        ),
    )
How does that work when we give target addresses when we run the goal like
pants package ::
? I thought (according to the docs) that to use target addresses like
::
we need to take
Targets
as an input to the
goal_rule
function?
h
Many goals are extended in similar ways, including
lint
,
test
and so on.
publish
itself is, if you look at
git grep PublishFieldSet
That
TargetRootsToFieldSets
thing is the magic of the engine at work
This rule is automatically invoked to satisfy that
Get
, and its missing parameters, including the command line
Specs
, are filled in for you by the engine.
It’s dependency injection on steroids
q
Oh I see. But you mentioned that I would need to create one for
pex_binary
and the one for
python_distribution
already exists? Could you point me to where exactly that is so I can use it as a reference?
h
I already did… look at src/python/pants/backend/python/goals/publish.py, and specifically the registration at the end
q
are you talking about
package_for_publish()
? Where is it specific to
python_distribution
?
c
This line here, states that this field set is for targets with a "PythonRepositoriesField" field: https://github.com/pantsbuild/pants/blob/63e8b7b2743a01f69ace373ac0527950691144fa/src/python/pants/backend/python/goals/publish.py#L63 which is registered as a plugin field on the
python_distribution
target here: https://github.com/pantsbuild/pants/blob/63e8b7b2743a01f69ace373ac0527950691144fa/src/python/pants/backend/python/goals/publish.py#L217 That's how this becomes publish goal for python dists
... and I acknowledge the lack of documentation for more advanced Plugin API usage. These tasks are still learned by internalizing the pants sources, unfortunately.