Skip to content

Add external reader support in pkl-gradle#1067

Closed
HT154 wants to merge 2 commits into
apple:mainfrom
HT154:gradle-external-readers
Closed

Add external reader support in pkl-gradle#1067
HT154 wants to merge 2 commits into
apple:mainfrom
HT154:gradle-external-readers

Conversation

@HT154
Copy link
Copy Markdown
Contributor

@HT154 HT154 commented May 11, 2025

Test on [windows] please

Comment thread pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java Outdated
@HT154 HT154 force-pushed the gradle-external-readers branch from 498201d to fc0567e Compare May 11, 2025 06:19
Comment thread pkl-gradle/src/main/java/org/pkl/gradle/spec/BasePklSpec.java Outdated
@HT154 HT154 force-pushed the gradle-external-readers branch from fc0567e to a18074d Compare May 12, 2025 20:35
@bioball
Copy link
Copy Markdown
Member

bioball commented May 12, 2025

@HT154 can we add some test coverage for this?

I think this would involve moving TestExternalReaderProcess to pkl-commons-test, and adding a corresponding test to org.pkl.gradle.EvaluatorsTest.

Hint: the Groovy syntax for maps is [key: value].
External readers would look something like:

externalModuleReaders = ["foo": new org.pkl.gradle.ExternalReader("bar")]

@HT154 HT154 force-pushed the gradle-external-readers branch 5 times, most recently from e6b911e to f6d3224 Compare May 19, 2025 02:51
Comment thread pkl-gradle/src/main/java/org/pkl/gradle/ExternalReader.java Outdated
Comment thread pkl-gradle/src/main/java/org/pkl/gradle/spec/BasePklSpec.java Outdated
Comment on lines +148 to +154
@Nested
@Optional
public abstract MapProperty<String, ExternalReader> getExternalModuleReaders();

@Nested
@Optional
public abstract MapProperty<String, ExternalReader> getExternalResourceReaders();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be marked as @Input properties, not @Nested. The @Nested annotation in Gradle is used to make Gradle process values of a map property as beans. All @Nested properties are treated as @Input, so it will work as is, but semantically values of this map are just data carriers without any annotations which do not require further processing, so I think that @Input would be more appropriate here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @netvl! Do you know of any documentation that covers these subtleties? I wasn't able to find anything when I searched.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all described in Gradle docs, but it may be hard to find, especially since Gradle docs constantly evolve. Most of it comes with experience with writing plugins and sifting through tons of github tickets in the Gradle repo :)
On this particular thing, I believe, the description is here: https://docs.gradle.org/current/userguide/incremental_build.html#sec:task_input_output_annotations

@HT154 HT154 force-pushed the gradle-external-readers branch 2 times, most recently from 818061b to 5b2a4c8 Compare July 23, 2025 18:18
Comment thread pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java
@HT154 HT154 force-pushed the gradle-external-readers branch from 5b2a4c8 to a1565c2 Compare August 14, 2025 21:16
Copy link
Copy Markdown
Contributor

@netvl netvl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@HT154
Copy link
Copy Markdown
Contributor Author

HT154 commented Aug 20, 2025

It looks like this hangs right now for reasons I'm not understanding. It's intermittent on *nix systems and seemingly consistent on Windows (but I don't have a system to test that locally). Will likely need a hand debugging this.

@HT154 HT154 force-pushed the gradle-external-readers branch from a1565c2 to cbff681 Compare November 30, 2025 23:21
@HT154 HT154 force-pushed the gradle-external-readers branch from cbff681 to 30972cc Compare November 30, 2025 23:23
@HT154 HT154 closed this Apr 20, 2026
@HT154 HT154 deleted the gradle-external-readers branch April 20, 2026 17:20
netvl added a commit to netvl/pkl that referenced this pull request May 11, 2026
This PR adds support for configuring external module and resource readers in the Gradle plugin, for all tasks which may need it.

Currently, no external readers are passed to the CliBaseOptions instance which is constructed by every task. Therefore, the only way external readers can be used with Gradle is via PklProject definitions, which sometimes may be limiting. After this change, it will be possible to configure external readers for any tasks, including those which operate on individual modules and not the entire projects.

I'm using NamedDomainObjectContainer to store reader definitions. The name of each reader's definition is passed through into the CLI classes as the map key. Therefore, you can define an external reader like this:

```kotlin
val myPklTask by pkl.operationKind.creating {
    val foo by externalModuleReaders.creating {
        executable = "external-executable"
        arguments = listOf("--bar", "baz")
    }
}
```

and then use `foo` as the URI schema in the Pkl code:

```pkl
import "foo:a/b/c"
```

Properties of each external reader spec are defined as proper properties and are propagated as input dependencies to the task, so the caching and task dependency resolution behaves as expected.

I completely forgot that apple#1067 exists and reimplemented this from scratch. But my approach to the interface is slightly different and more in line with Gradle recommendations, IMO, and I really need this functionality so I intend to see this through. As in that PR, there are no tests which validate the actual invocation of the external command because creating one requires writing a command which does msgpack, which I'm unsure of how to do properly within this project.
netvl added a commit to netvl/pkl that referenced this pull request May 11, 2026
This PR adds support for configuring external module and resource readers in the Gradle plugin, for all tasks which may need it.

Currently, no external readers are passed to the CliBaseOptions instance which is constructed by every task. Therefore, the only way external readers can be used with Gradle is via PklProject definitions, which sometimes may be limiting. After this change, it will be possible to configure external readers for any tasks, including those which operate on individual modules and not the entire projects.

I'm using NamedDomainObjectContainer to store reader definitions. The name of each reader's definition is passed through into the CLI classes as the map key. Therefore, you can define an external reader like this:

```kotlin
val myPklTask by pkl.operationKind.creating {
    val foo by externalModuleReaders.creating {
        executable = "external-executable"
        arguments = listOf("--bar", "baz")
    }
}
```

and then use `foo` as the URI schema in the Pkl code:

```pkl
import "foo:a/b/c"
```

Properties of each external reader spec are defined as proper properties and are propagated as input dependencies to the task, so the caching and task dependency resolution behaves as expected.

I completely forgot that apple#1067 exists and reimplemented this from scratch. But my approach to the interface is slightly different and more in line with Gradle recommendations, IMO, and I really need this functionality so I intend to see this through. As in that PR, there are no tests which validate the actual invocation of the external command because creating one requires writing a command which does msgpack, which I'm unsure of how to do properly within this project.
netvl added a commit to netvl/pkl that referenced this pull request May 11, 2026
This PR adds support for configuring external module and resource readers in the Gradle plugin, for all tasks which may need it.

Currently, no external readers are passed to the CliBaseOptions instance which is constructed by every task. Therefore, the only way external readers can be used with Gradle is via PklProject definitions, which sometimes may be limiting. After this change, it will be possible to configure external readers for any tasks, including those which operate on individual modules and not the entire projects.

I'm using NamedDomainObjectContainer to store reader definitions. The name of each reader's definition is passed through into the CLI classes as the map key. Therefore, you can define an external reader like this:

```kotlin
val myPklTask by pkl.operationKind.creating {
    val foo by externalModuleReaders.creating {
        executable = "external-executable"
        arguments = listOf("--bar", "baz")
    }
}
```

and then use `foo` as the URI schema in the Pkl code:

```pkl
import "foo:a/b/c"
```

Properties of each external reader spec are defined as proper properties and are propagated as input dependencies to the task, so the caching and task dependency resolution behaves as expected.

I completely forgot that apple#1067 exists and reimplemented this from scratch. But my approach to the interface is slightly different and more in line with Gradle recommendations, IMO, and I really need this functionality so I intend to see this through. As in that PR, there are no tests which validate the actual invocation of the external command because creating one requires writing a command which does msgpack, which I'm unsure of how to do properly within this project.
netvl added a commit to netvl/pkl that referenced this pull request May 11, 2026
This PR adds support for configuring external module and resource readers in the Gradle plugin, for all tasks which may need it.

Currently, no external readers are passed to the CliBaseOptions instance which is constructed by every task. Therefore, the only way external readers can be used with Gradle is via PklProject definitions, which sometimes may be limiting. After this change, it will be possible to configure external readers for any tasks, including those which operate on individual modules and not the entire projects.

I'm using NamedDomainObjectContainer to store reader definitions. The name of each reader's definition is passed through into the CLI classes as the map key. Therefore, you can define an external reader like this:

```kotlin
val myPklTask by pkl.operationKind.creating {
    val foo by externalModuleReaders.creating {
        executable = "external-executable"
        arguments = listOf("--bar", "baz")
    }
}
```

and then use `foo` as the URI schema in the Pkl code:

```pkl
import "foo:a/b/c"
```

Properties of each external reader spec are defined as proper properties and are propagated as input dependencies to the task, so the caching and task dependency resolution behaves as expected.

I completely forgot that apple#1067 exists and reimplemented this from scratch. But my approach to the interface is slightly different and more in line with Gradle recommendations, IMO, and I really need this functionality so I intend to see this through. As in that PR, there are no tests which validate the actual invocation of the external command because creating one requires writing a command which does msgpack, which I'm unsure of how to do properly within this project.
netvl added a commit to netvl/pkl that referenced this pull request May 13, 2026
This PR adds support for configuring external module and resource readers in the Gradle plugin, for all tasks which may need it.

Currently, no external readers are passed to the CliBaseOptions instance which is constructed by every task. Therefore, the only way external readers can be used with Gradle is via PklProject definitions, which sometimes may be limiting. After this change, it will be possible to configure external readers for any tasks, including those which operate on individual modules and not the entire projects.

I'm using NamedDomainObjectContainer to store reader definitions. The name of each reader's definition is passed through into the CLI classes as the map key. Therefore, you can define an external reader like this:

```kotlin
val myPklTask by pkl.operationKind.creating {
    val foo by externalModuleReaders.creating {
        executable = "external-executable"
        arguments = listOf("--bar", "baz")
    }
}
```

and then use `foo` as the URI schema in the Pkl code:

```pkl
import "foo:a/b/c"
```

Properties of each external reader spec are defined as proper properties and are propagated as input dependencies to the task, so the caching and task dependency resolution behaves as expected.

I completely forgot that apple#1067 exists and reimplemented this from scratch. But my approach to the interface is slightly different and more in line with Gradle recommendations, IMO, and I really need this functionality so I intend to see this through. As in that PR, there are no tests which validate the actual invocation of the external command because creating one requires writing a command which does msgpack, which I'm unsure of how to do properly within this project.
netvl added a commit to netvl/pkl that referenced this pull request May 14, 2026
This PR adds support for configuring external module and resource readers in the Gradle plugin, for all tasks which may need it.

Currently, no external readers are passed to the CliBaseOptions instance which is constructed by every task. Therefore, the only way external readers can be used with Gradle is via PklProject definitions, which sometimes may be limiting. After this change, it will be possible to configure external readers for any tasks, including those which operate on individual modules and not the entire projects.

I'm using NamedDomainObjectContainer to store reader definitions. The name of each reader's definition is passed through into the CLI classes as the map key. Therefore, you can define an external reader like this:

```kotlin
val myPklTask by pkl.operationKind.creating {
    val foo by externalModuleReaders.creating {
        executable = "external-executable"
        arguments = listOf("--bar", "baz")
    }
}
```

and then use `foo` as the URI schema in the Pkl code:

```pkl
import "foo:a/b/c"
```

Properties of each external reader spec are defined as proper properties and are propagated as input dependencies to the task, so the caching and task dependency resolution behaves as expected.

I completely forgot that apple#1067 exists and reimplemented this from scratch. But my approach to the interface is slightly different and more in line with Gradle recommendations, IMO, and I really need this functionality so I intend to see this through. As in that PR, there are no tests which validate the actual invocation of the external command because creating one requires writing a command which does msgpack, which I'm unsure of how to do properly within this project.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants