Compare commits

...

46 Commits

Author SHA1 Message Date
Daniel Chao a1eea47b3f Restore @ThreadSafe and @Immutable annotations (#1613) 2026-05-22 15:58:09 -07:00
dependabot[bot] 648f9143bf Bump io.leangen.geantyref:geantyref from 1.3.16 to 2.0.1 (#1566)
Bumps [io.leangen.geantyref:geantyref](https://github.com/leangen/geantyref) from 1.3.16 to 2.0.1.
- [Release notes](https://github.com/leangen/geantyref/releases)
- [Commits](leangen/geantyref@geantyref-v1.3.16...geantyref-v2.0.1)

---
updated-dependencies:
- dependency-name: io.leangen.geantyref:geantyref
  dependency-version: 2.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-22 15:54:27 -07:00
Daniel Chao 95bcd6a463 Remove jsr305; switch GuardedBy to com.google.errorprone (#1611)
- Remove single usage of @immutable without replacement
- Remove HttpClient's usages of @threadsafe without replacement
- Replace javax.annotation.concurrent.GuardedBy
  with com.google.errorprone.annotations.concurrent.GuardedBy

Also:
- Remove redundant final modifiers from members of a final class

---------

Co-authored-by: odenix <self@odenix.org>
2026-05-22 14:15:18 -07:00
Daniel Chao a800072441 Fix native build (#1610)
Fix native executable build; there was a missing truffle boundary
2026-05-22 11:50:40 -07:00
Daniel Chao b070d56741 Remove public modifier on LazyHttpClient and RequestRewritingClient (#1609)
This introduces a test helper to expose configured HTTP settings, and
makes the underlying classes package-private again.
2026-05-22 10:17:26 -07:00
Daniel Chao da4dd4c4f8 Make codegen default to jspecify NonNull annotations (#1607)
With JSpecify now a dependency of pkl-config-java, this moves the
non-null annotation to jspecify's.
This makes it simpler for users to do nullness checks, as tooling
already understands JSpecify nullness annotations.
2026-05-21 21:12:15 -07:00
Daniel Chao 8e2e5e4ba8 Improve HTTP headers logic (#1584)
* Relax forbidden headers constraints
  - remove restriction on browser-related headers
- allow any glob pattern (no need to end with `/` or `*`, because glob
patterns already require users to explicitly declare prefix matches if
that's the intention)
* Replace `List<Pair<, ...>>`; use `Map<String, ...>` instead
* Use glob pattern strings as an API throughout, instead of `Pattern`
(e.g. in `HttpClientBuilder`)
* Add HTTP headers to message passing API
* Add HTTP headers to executor API (introduces `ExecutorSpiOptions4`)
* Add tests for Gradle, CLI, and pkl-executor invocations
* Improve documentation
* Add `isGlobPattern` API to class `String` for in-language validation
of http headers
* Behavior change: make sure explicitly configured `User-Agent` in
`HttpClientBuilder` can be shadowed by headers (allows users to set
`--http-header "**=User-Agent: My User Agent"` and for this to be the
only user agent).

CC @kyokuping
2026-05-21 20:07:06 -07:00
Daniel Chao 87ea28260b Configure IntelliJ to respect @LateInit annotations (#1606)
IntelliJ can understand that some annotations on fields mean that they
are implicitly initialized, which means we don't get the "field XXX is
not initialized" warning for `@LateInit` fields.

This setting, unfortunately, is recorded into `.idea/misc.xml`, which
contains a bunch of arbitrary stuff that we don't want to check into
source control

This adds some logic to touch up that file to mark `@LateInit` as
implicitly initialized fields, so we don't get any editor warnings.

Also, suppress some warnings.
2026-05-21 14:34:11 -07:00
odenix 3dc93cbd4a pkl-core: Migrate nullness to JSpecify (#1601)
Replace pkl-core's local nullness annotations with JSpecify annotations.
Enable NullAway checking for pkl-core packages except org.pkl.core.ast
and org.pkl.core.stdlib.

Notable code changes:
- Add a dedicated late-init constructor to VmTyped
- Move VmExceptionBuilder's fallback message derivation from withCause()
to build()
- Split VmException rendering between builder-provided messages and
string-backed messages
- Initialize MessageTransport handlers with default throwing handlers
- Update JSON helper collection types to allow nullable values JSON
arrays and objects can contain JSON null,
so the Java Map/List element types need to model nullable elements
explicitly
- Make public command transform APIs accept nullable transformed values 
   Command transforms can produce null for optional/default handling,
so the BiFunction and options-map element types now model that
explicitly
- Make ExecutorSpiException accept nullable message and cause 
Existing call sites can pass nullable causes from Throwable.getCause()
- Remove JSR-305 semantics from `@LateInit`
   JSpecify does not support the same type-qualifier-nickname pattern,
so `@LateInit` is now documentation plus a NullAway
constructor-initialization exemption

Out of scope:
- NullAway checking of org.pkl.core.ast and org.pkl.core.stdlib
- IntelliJ warnings related to `@LateInit` fields
- Removing the JSR-305 dependency, since concurrency annotations are
still in use
2026-05-21 13:57:20 -07:00
dependabot[bot] 63ef60f3c4 Bump slf4j from 2.0.17 to 2.0.18 (#1605)
Bumps `slf4j` from 2.0.17 to 2.0.18.

Updates `org.slf4j:slf4j-api` from 2.0.17 to 2.0.18

Updates `org.slf4j:slf4j-simple` from 2.0.17 to 2.0.18

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-api
  dependency-version: 2.0.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.slf4j:slf4j-simple
  dependency-version: 2.0.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 09:56:49 -07:00
dependabot[bot] f10b235002 Bump gradle-wrapper from 9.5.0 to 9.5.1 (#1604) 2026-05-21 09:46:41 -07:00
Daniel Chao 1e33179ecc Update codestyles (#1602)
IntelliJ keeps touching this file; these settings must be obsolete.
2026-05-21 08:18:29 -07:00
Daniel Chao 1733a4c6e7 Fix: docsite-info is an optional input (#1598) 2026-05-19 15:20:02 -07:00
odenix dc9003d0f1 pkl-config-java: Refine nullness handling in Config and JavaType (#1544)
Motivation:
Config.as() causes nullness warnings when its result is intentionally assigned
to a non-null variable

Changes:

* Introduce Config.asNullable(Class<T>), asNullable(JavaType<T>), and
  asNullable(Type) to explicitly opt into nullable values
* Keep the signatures of Config.as(Class<T>) and Config.as(JavaType<T>)
  unchanged from 0.31 by adding @NullUnmarked
  * This gives users time to migrate from as() to asNullable() where appropriate
  * Avoids introducing new spurious warnings
* Change `<T> T Config.as(Type)` to `<T extends @nullable Object> T Config.as(Type)`
  * This overload is typically used by reflective code such as
    pkl-config-kotlin's Config.to() rather than directly by user code
* Clarify that JavaType<T> represents a non-null top-level type whose type arguments may be nullable
  * Restricting <T> to non-null keeps method signatures understandable for humans and tools
  * Enables full symmetry between Class<T> and JavaType<T> overloads in Config and JavaType
  * Enables future non-null runtime checks in both Config.as() overloads
* Simplify construction of `JavaType`s with nullable type arguments
  * Add ofNullable() variants for most factory methods, e.g., JavaType.listOfNullable()
* Overhaul Javadoc of Config and JavaType

Result:

* Clear separation between accessing nullable and non-null values
* Config.as() is used for the common non-null case
* Config.as() can perform non-null runtime checks in a future release (breaking change)
* More ergonomic construction of types with nullable type arguments
* More detailed and consistent documentation
2026-05-19 12:27:59 -07:00
Daniel Chao e34c3e8c4f Test reporter fixes (#1597)
* Fix error message when an invalid test reporter is supplied in Gradle
* Fix Gradle property name in docs
* Fix Gradle property name in tasks
* Introduce `TestReporter.default`, and use it in places where default
is applied
* Remove calls to `convention()`; this is not required because the input
is optional anyways.
2026-05-19 11:32:51 -07:00
Islon Scherer 3fbcd463e0 Introduce "minimal" test reporter (#1563) 2026-05-19 17:20:26 +02:00
odenix 566c42f44d pkl-doc: Support single-package docsite mode (#1592)
When a docsite has only one package name and no DocsiteInfo.overview,
treat it like Javadoc's single-module output: redirect the top-level
index to the package page and omit the site-title breadcrumb segment
from generated pages.

Add src/test/files/SinglePackageTest fixtures to cover multiple package
versions, redirect behavior, breadcrumb behavior, and unchanged site
structure.

Also:
- Shut down Executor used in test.
- Declare expected output fixtures of DocGenerator as test inputs, not
outputs.
- Fix IntelliJ warning by using a Set for the right-hand side of
collection subtraction.
2026-05-15 18:38:24 -07:00
Daniel Chao a7a64acbac Improve handling of evaling dependency notation URIs (#1595) 2026-05-15 15:51:09 -07:00
Daniel Chao 3ad1cb3645 Ensure local dependency matches PklProject.dep.json version (#1594)
The version of local project dependencies should _always_ exactly match
up with what's declared in a PklProject.deps.json; any package in the
transitive dependency tree should always be delcaring the same import
too.

Closes #1591
2026-05-15 11:48:57 -07:00
Vladimir Matveev 2fe565a0f2 Added support for external readers in Gradle plugins (#1578)
Adds support for configuring external module and resource readers in the Gradle plugin
2026-05-14 11:18:22 -07:00
odenix 1b6e89c971 pkl-doc: Fix/improve Executor handling in DocGenerator (#1590)
run() now creates and closes a default Executor per call. This is fine
because there is no good reason to call this method multiple times.

run(Executor) now lets callers provide their own Executor, which is
customary for a well-behaved library.

Also: Fix IntelliJ warning by calling toSet()

Closes #1583
2026-05-14 11:02:23 -07:00
dependabot[bot] 6171dbde28 Bump org.msgpack:msgpack-core from 0.9.11 to 0.9.12 (#1587) 2026-05-14 08:51:52 -07:00
dependabot[bot] 99b29ef3c7 Bump github/codeql-action from 4.35.2 to 4.35.4 (#1586) 2026-05-14 08:49:18 -07:00
dependabot[bot] c428f7abd0 Bump com.palantir.javapoet:javapoet from 0.14.0 to 0.15.0 (#1588) 2026-05-14 08:48:29 -07:00
dependabot[bot] 366b51bd21 Bump nu.validator:validator from 26.4.16 to 26.5.7 (#1589) 2026-05-14 08:47:25 -07:00
Jeaeun Kim 14085c18bb Add support for customizing HTTP headers (#1196)
This PR adds support for custom HTTP headers, introducing a
`--http-header` CLI flag to accept `key=value` pairs. These headers can
also be specified within the `setting.pkl` file.

Closes #633

SPICE: https://github.com/apple/pkl-evolution/pull/24

---------

Co-authored-by: Jen Basch <jbasch94@gmail.com>
Co-authored-by: Islon Scherer <islonscherer@gmail.com>
2026-05-12 13:53:59 -07:00
Jen Basch fe58405220 Improve some doc comments in pkl:Command (#1582) 2026-05-12 13:53:15 -07:00
Vladimir Matveev bac8b47ba8 Add resource readers from service providers in CLI (#1581)
This omission, in particular, prevents Gradle plugins (which rely on CLI
classes) from adding custom resource readers via the service loading
mechanism. This change seems benign, especially since this is already
done for module key factories.
2026-05-11 16:54:36 -07:00
Jen Basch 713fbc5043 Add missing javadoc for org.pkl.core.CommandSpec (#1577) 2026-05-08 20:29:05 -07:00
Daniel Chao 38733e5781 Fix parsing of dependency notation URIs (#1570)
Fixes a thrown exception when path segments contain characters that
aren't URI safe (e.g. `import "@foo/bar baz.pkl"`).

Closes #1545
2026-05-07 13:00:52 -07:00
dependabot[bot] 8ff03cfac0 Bump gradle-wrapper from 9.4.1 to 9.5.0 (#1575)
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.4.1 to
9.5.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/gradle/gradle/releases">gradle-wrapper's
releases</a>.</em></p>
<blockquote>
<h2>9.5.0</h2>
<p>The Gradle team is excited to announce Gradle 9.5.0.</p>
<p>Here are the highlights of this release:</p>
<ul>
<li>Task provenance in reports and failure messages</li>
<li>Type-safe accessors for precompiled Kotlin Settings plugins</li>
</ul>
<p><a href="https://docs.gradle.org/9.5.0/release-notes.html">Read the
Release Notes</a></p>
<p>We would like to thank the following community members for their
contributions to this release of Gradle:
<a href="https://github.com/atm1020">atm1020</a>,
<a href="https://github.com/mataha">mataha</a>,
<a href="https://github.com/aSemy">Adam</a>,
<a href="https://github.com/kelemen">Attila Kelemen</a>,
<a href="https://github.com/britter">Benedikt Ritter</a>,
<a href="https://github.com/Vampire">Björn Kautler</a>,
<a href="https://github.com/budindepunk">Caro Silva Rode</a>,
<a href="https://github.com/chanani">CHANHAN</a>,
<a href="https://github.com/DmitryNez">Dmitry Nezavitin</a>,
<a href="https://github.com/Juneezee">Eng Zer Jun</a>,
<a href="https://github.com/KugelLibelle">KugelLibelle</a>,
<a href="https://github.com/vmadalin">Madalin Valceleanu</a>,
<a href="https://github.com/quijote">Markus Gaisbauer</a>,
<a href="https://github.com/koppor">Oliver Kopp</a>,
<a href="https://github.com/hfhbd">Philip Wedemann</a>,
<a href="https://github.com/ploober">ploober</a>,
<a href="https://github.com/rpalcolea">Roberto Perez Alcolea</a>,
<a href="https://github.com/R0h1tAnand">Rohit Anand</a>,
<a href="https://github.com/Suvrat1629">Suvrat Acharya</a>,
<a href="https://github.com/usv240">Ujwal Suresh Vanjare</a>,
<a href="https://github.com/urdak">Victor Merkulov</a></p>
<h2>Upgrade instructions</h2>
<p>Switch your build to use Gradle 9.5.0 by updating your wrapper:</p>
<pre><code>./gradlew wrapper --gradle-version=9.5.0 &amp;&amp; ./gradlew
wrapper
</code></pre>
<p>See the Gradle <a
href="https://docs.gradle.org/9.5.0/userguide/upgrading_version_9.html">9.x
upgrade guide</a> to learn about deprecations, breaking changes and
other considerations when upgrading.</p>
<p>For Java, Groovy, Kotlin and Android compatibility, see the <a
href="https://docs.gradle.org/9.5.0/userguide/compatibility.html">full
compatibility notes</a>.</p>
<h2>Reporting problems</h2>
<p>If you find a problem with this release, please file a bug on <a
href="https://github.com/gradle/gradle/issues">GitHub Issues</a>
adhering to our issue guidelines.
If you're not sure you're encountering a bug, please use the <a
href="https://discuss.gradle.org/c/help-discuss">forum</a>.</p>
<p>We hope you will build happiness with Gradle, and we look forward to
your feedback via <a href="https://twitter.com/gradle">Twitter</a> or on
<a href="https://github.com/gradle">GitHub</a>.</p>
<h2>9.5.0 RC4</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/gradle/gradle/commit/3fe117d68f3907790f3809f121aa36303a9151f8"><code>3fe117d</code></a>
Update jdks.yaml (<a
href="https://redirect.github.com/gradle/gradle/issues/37703">#37703</a>)</li>
<li><a
href="https://github.com/gradle/gradle/commit/33d145af6fbe7cf7c9d84646b6d7f32fea91d5e2"><code>33d145a</code></a>
Update jdks.yaml</li>
<li><a
href="https://github.com/gradle/gradle/commit/f7a05d1ed48442eb5da4d6e2b6593da55cdec1da"><code>f7a05d1</code></a>
Update Gradle wrapper to version 9.5.0-rc-4 (<a
href="https://redirect.github.com/gradle/gradle/issues/37654">#37654</a>)</li>
<li><a
href="https://github.com/gradle/gradle/commit/266facdcbcb0b4c60120cc118eaf0f652bfcdfe5"><code>266facd</code></a>
Update Gradle wrapper to version 9.5.0-rc-4</li>
<li><a
href="https://github.com/gradle/gradle/commit/0ad6dd8e143455707e444aa7e3d38327a3366513"><code>0ad6dd8</code></a>
Suppress OSC taskbar reset on plain/piped stdout (<a
href="https://redirect.github.com/gradle/gradle/issues/37646">#37646</a>)</li>
<li><a
href="https://github.com/gradle/gradle/commit/966025d5850d46c9158a2f25e4096222277ecf57"><code>966025d</code></a>
Suppress OSC taskbar reset on plain/piped stdout</li>
<li><a
href="https://github.com/gradle/gradle/commit/e7455734449e422accebf44cf7b31bf93e3a770c"><code>e745573</code></a>
Polish IP docs (<a
href="https://redirect.github.com/gradle/gradle/issues/37642">#37642</a>)</li>
<li><a
href="https://github.com/gradle/gradle/commit/d5cfd079acd2c8f1182edd6ec23dbab571132d0a"><code>d5cfd07</code></a>
Ensure BuildOperationQueue will progress without extra leases (<a
href="https://redirect.github.com/gradle/gradle/issues/37629">#37629</a>)</li>
<li><a
href="https://github.com/gradle/gradle/commit/acdf0c36fa13ba09a7ff5b51f79b9af4b1a097ee"><code>acdf0c3</code></a>
Ensure BuildOperationQueue will progress without extra leases</li>
<li><a
href="https://github.com/gradle/gradle/commit/f7d0e4f6f7896426a8b24091388e4c252b62faef"><code>f7d0e4f</code></a>
Rename anchor</li>
<li>Additional commits viewable in <a
href="https://github.com/gradle/gradle/compare/v9.4.1...v9.5.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=gradle-wrapper&package-manager=gradle&previous-version=9.4.1&new-version=9.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 12:28:59 -07:00
dependabot[bot] be8366a975 Bump jline from 4.0.12 to 4.0.14 (#1574)
Bumps `jline` from 4.0.12 to 4.0.14.

Updates `org.jline:jline-reader` from 4.0.12 to 4.0.14
- [Release notes](https://github.com/jline/jline3/releases)
- [Commits](jline/jline3@4.0.12...4.0.14)

Updates `org.jline:jline-terminal` from 4.0.12 to 4.0.14
- [Release notes](https://github.com/jline/jline3/releases)
- [Commits](jline/jline3@4.0.12...4.0.14)

Updates `org.jline:jline-terminal-jni` from 4.0.12 to 4.0.14
- [Release notes](https://github.com/jline/jline3/releases)
- [Commits](jline/jline3@4.0.12...4.0.14)

---
updated-dependencies:
- dependency-name: org.jline:jline-reader
  dependency-version: 4.0.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jline:jline-terminal
  dependency-version: 4.0.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jline:jline-terminal-jni
  dependency-version: 4.0.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-07 11:17:45 -07:00
Jen Basch 8a4821c4e7 Power assertions: change source section check to an assert (#1572) 2026-05-04 13:53:40 -07:00
Jen Basch b7ba6a8649 Fix pkl:test fact power assertions when member source section is unavailable (#1571)
Power assertions only work when the source section is available. If it
is unavailable, power assertions throw a ParserError (unexpected EOF on
an empty input) when re-parsing the expression for presentation.
2026-05-04 12:25:15 -07:00
dependabot[bot] 9c1a9cb4f8 Bump kotlinToolchain from 2.3.20 to 2.3.21 (#1567)
Updates `org.jetbrains.kotlin:kotlin-gradle-plugin` from 2.3.20 to 2.3.21
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](JetBrains/kotlin@v2.3.20...v2.3.21)

Updates `org.jetbrains.kotlin.plugin.serialization` from 2.3.20 to 2.3.21
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](JetBrains/kotlin@v2.3.20...v2.3.21)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-gradle-plugin
  dependency-version: 2.3.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jetbrains.kotlin.plugin.serialization
  dependency-version: 2.3.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-30 08:31:46 -07:00
dependabot[bot] 5d4bac8f61 Bump com.uber.nullaway:nullaway from 0.13.2 to 0.13.4 (#1568)
Bumps [com.uber.nullaway:nullaway](https://github.com/uber/NullAway) from 0.13.2 to 0.13.4.
- [Release notes](https://github.com/uber/NullAway/releases)
- [Changelog](https://github.com/uber/NullAway/blob/master/CHANGELOG.md)
- [Commits](uber/NullAway@v0.13.2...v0.13.4)

---
updated-dependencies:
- dependency-name: com.uber.nullaway:nullaway
  dependency-version: 0.13.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-30 08:31:14 -07:00
Daniel Chao 4a25320995 Fix import/read verification when encountering glob wildcards (#1559)
Fixes an issue where the import verifier can possibly throw when
packaging on Windows due to `*` being an invalid filename.
2026-04-29 20:20:49 -07:00
Vladimir Matveev df063f17f3 Added pkg module key factory and resource reader to project loading (#1547)
This change allows `PklProject` files, usually loaded via the `Project`
static methods, to have references to external packages via `package://`
URIs.

This is helpful for centralizing and sharing common package
configuration via packages.
2026-04-29 16:45:14 -07:00
Kushal Pisavadia d3a3a14aaa Fix CRLF handling in line continuation escapes (#1564) 2026-04-29 13:53:55 -07:00
Daniel Chao 39c01c24ba Add another commit to ignore revs file (#1561)
Add commit from https://github.com/apple/pkl/pull/1560
2026-04-25 11:58:55 -07:00
Daniel Chao 2b3603b544 Reformat Kotlin code (#1560)
ktfmt has much improved how it formats Kotlin code. Unfortunately, this
means that whenever we touch a single line in a Kotlin file, we get a
_lot_ more changes thanks to ratcheting now picking up this file for
formatting.

This PR just reformats every single Kotlin file so we don't have to deal
with this churn in future PRs that touch Kotlin code.
2026-04-25 06:14:44 -07:00
Daniel Chao c4f56bf20d Fix setting DEBUG_ARGS (#1558)
Looks like context variable `runner` isn't available on the job level
`env`. It's available on the step level `env` though.
2026-04-24 19:34:08 -07:00
Daniel Chao 87b15f7a70 Only set --stacktrace --info if verbose logging is enabled (#1557)
This is a quality-of-life improvement; make our build logs more easy to
read through for the default case.

If we need more information, we can click on the "Enable debug logging"
checkbox when re-running a job, which then populates the `runner.debug`
context variable.
2026-04-24 15:28:57 -07:00
Daniel Chao e07ff96de8 Switch CodeQL to use PklCI API (#1555) 2026-04-23 11:28:16 -07:00
dependabot[bot] 88a56198a8 Bump nu.validator:validator from 26.4.2 to 26.4.16 (#1550)
Bumps [nu.validator:validator](https://github.com/validator/validator) from 26.4.2 to 26.4.16.
- [Release notes](https://github.com/validator/validator/releases)
- [Commits](https://github.com/validator/validator/commits/26.4.16)

---
updated-dependencies:
- dependency-name: nu.validator:validator
  dependency-version: 26.4.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-23 11:19:19 -07:00
dependabot[bot] de22705add Bump com.google.errorprone:error_prone_core from 2.48.0 to 2.49.0 (#1552)
Bumps [com.google.errorprone:error_prone_core](https://github.com/google/error-prone) from 2.48.0 to 2.49.0.
- [Release notes](https://github.com/google/error-prone/releases)
- [Commits](google/error-prone@v2.48.0...v2.49.0)

---
updated-dependencies:
- dependency-name: com.google.errorprone:error_prone_core
  dependency-version: 2.49.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-23 10:14:28 -07:00
495 changed files with 11663 additions and 4348 deletions
+2
View File
@@ -1,2 +1,4 @@
# Auto-format Kotlin code # Auto-format Kotlin code
816cd483c8adf4c04e14236c173a1dc6bd2579ea 816cd483c8adf4c04e14236c173a1dc6bd2579ea
# Format Kotlin code again
2b3603b544bae2ad87374b65afaf8ac018216261
+1 -1
View File
@@ -2,7 +2,7 @@ amends "pkl:Project"
dependencies { dependencies {
["pkl.impl.ghactions"] { ["pkl.impl.ghactions"] {
uri = "package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@1.6.0" uri = "package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@1.7.0"
} }
["gha"] { ["gha"] {
uri = "package://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1.4.0" uri = "package://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1.4.0"
+8 -8
View File
@@ -3,16 +3,16 @@
"resolvedDependencies": { "resolvedDependencies": {
"package://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1": { "package://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1": {
"type": "remote", "type": "remote",
"uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1.4.0", "uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1.6.0",
"checksums": { "checksums": {
"sha256": "e0b9a9f71071d6101e9d764c069b2ec4a597d5315cb6e4c265b3f0d90c2b482c" "sha256": "10e27d63df4a4520d8a9375962406ca5ffe74f396bd3cb1c19b1f8358505010a"
} }
}, },
"package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@1": { "package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@1": {
"type": "remote", "type": "remote",
"uri": "projectpackage://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@1.6.0", "uri": "projectpackage://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@1.7.0",
"checksums": { "checksums": {
"sha256": "fbc3c456ea468a0fe6baa9b3d30167259ac04e721a41a10fe82d2970026f0b1d" "sha256": "962cdba703b50e86ecfda1a1345bf58caa7b4839dd090eae6120024d862793d0"
} }
}, },
"package://pkg.pkl-lang.org/pkl-pantry/pkl.experimental.deepToTyped@1": { "package://pkg.pkl-lang.org/pkl-pantry/pkl.experimental.deepToTyped@1": {
@@ -24,16 +24,16 @@
}, },
"package://pkg.pkl-lang.org/pkl-pantry/pkl.github.dependabotManagedActions@1": { "package://pkg.pkl-lang.org/pkl-pantry/pkl.github.dependabotManagedActions@1": {
"type": "remote", "type": "remote",
"uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/pkl.github.dependabotManagedActions@1.1.0", "uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/pkl.github.dependabotManagedActions@1.1.3",
"checksums": { "checksums": {
"sha256": "025fac778f2c5f75c8229fa4ec0f49ebdb99a61affe9aae489fefd8fccd92faa" "sha256": "521feb6f5ff12075ebad0758799fe7ec2675d231a0e0f5456694c8d4822a8171"
} }
}, },
"package://pkg.pkl-lang.org/pkl-pantry/com.github.dependabot@1": { "package://pkg.pkl-lang.org/pkl-pantry/com.github.dependabot@1": {
"type": "remote", "type": "remote",
"uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/com.github.dependabot@1.0.1", "uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/com.github.dependabot@1.0.3",
"checksums": { "checksums": {
"sha256": "0a4fe9b0983716ec49fb060b9e5e83f8c365eb899d517123b43134416a9574b6" "sha256": "a8934d84ffd11992d7baf6acfd97bae31d6112fa8add5cc8b5b4a722ce5b9ffc"
} }
} }
} }
-67
View File
@@ -1,67 +0,0 @@
amends "@gha/Workflow.pkl"
import "@gha/catalog.pkl"
on {
push {
branches {
"main"
}
}
pull_request {}
schedule {
// Run at 01:38 on Saturday
new { cron = "38 1 * * 6" }
}
}
local class CodeQLScan {
language: String
`build-mode`: String
}
local scans: Listing<CodeQLScan> = new {
new {
language = "actions"
`build-mode` = "none"
}
new {
language = "java-kotlin"
`build-mode` = "autobuild"
}
new {
language = "javascript-typescript"
`build-mode` = "none"
}
}
jobs {
for (scan in scans) {
["analyze-\(scan.language)"] {
name = "Analyze (\(scan.language))"
`runs-on` = "ubuntu-latest"
permissions {
`security-events` = "write"
}
steps {
catalog.`actions/checkout@v6`
new {
name = "Initialize CodeQL"
uses = "github/codeql-action/init@v4"
with {
["languages"] = scan.language
["build-mode"] = scan.`build-mode`
}
}
new {
name = "Perform CodeQL Analysis"
uses = "github/codeql-action/analyze@v4"
with {
["category"] = "/language:\(scan.language)"
}
}
}
}
}
}
+11 -4
View File
@@ -9,7 +9,6 @@ import "jobs/GithubRelease.pkl"
import "jobs/GradleJob.pkl" import "jobs/GradleJob.pkl"
import "jobs/PklJob.pkl" import "jobs/PklJob.pkl"
import "jobs/SimpleGradleJob.pkl" import "jobs/SimpleGradleJob.pkl"
import "codeql.pkl"
triggerDocsBuild = "both" triggerDocsBuild = "both"
@@ -241,7 +240,15 @@ dependabot {
} }
} }
workflows { codeql {
// add codeql workflow to set of workflows scans {
["workflows/codeql.yml"] = codeql new {
language = "java-kotlin"
buildMode = "autobuild"
}
new {
language = "javascript-typescript"
buildMode = "none"
}
}
} }
+16 -2
View File
@@ -3,6 +3,7 @@ abstract module GradleJob
extends "PklJob.pkl" extends "PklJob.pkl"
import "@gha/Workflow.pkl" import "@gha/Workflow.pkl"
import "@gha/context.pkl"
import "@pkl.impl.ghactions/catalog.pkl" import "@pkl.impl.ghactions/catalog.pkl"
/// Whether this is a release build or not. /// Whether this is a release build or not.
@@ -29,8 +30,7 @@ fetchDepth: Int?
fixed gradleArgs = fixed gradleArgs =
new Listing { new Listing {
"--info" "$DEBUG_ARGS"
"--stacktrace"
"--no-daemon" "--no-daemon"
"-DpklMultiJdkTesting=true" "-DpklMultiJdkTesting=true"
when (isRelease) { when (isRelease) {
@@ -97,6 +97,20 @@ fixed job {
} }
} }
} }
new {
name = "Set DEBUG_ARGS env var"
env {
["RUNNER_DEBUG"] = context.runner.debug
}
shell = "bash"
// language=bash
run =
"""
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
"""
}
...module.steps ...module.steps
} }
} }
+2 -2
View File
@@ -31,9 +31,9 @@ jobs:
- name: dawidd6/action-download-artifact@v11 - name: dawidd6/action-download-artifact@v11
uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11 uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11
- name: github/codeql-action/analyze@v4 - name: github/codeql-action/analyze@v4
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4 uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
- name: github/codeql-action/init@v4 - name: github/codeql-action/init@v4
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4 uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
- name: gradle/actions/dependency-submission@v6 - name: gradle/actions/dependency-submission@v6
uses: gradle/actions/dependency-submission@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6 uses: gradle/actions/dependency-submission@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6
- name: gradle/actions/setup-gradle@v5 - name: gradle/actions/setup-gradle@v5
+153 -17
View File
@@ -30,9 +30,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -63,9 +71,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -94,9 +110,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: bench:jmh - name: bench:jmh
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true bench:jmh
gradle-compatibility: gradle-compatibility:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
@@ -113,9 +137,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: :pkl-gradle:build :pkl-gradle:compatibilityTestReleases - name: :pkl-gradle:build :pkl-gradle:compatibilityTestReleases
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true :pkl-gradle:build :pkl-gradle:compatibilityTestReleases run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true :pkl-gradle:build :pkl-gradle:compatibilityTestReleases
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -145,12 +177,20 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false persist-credentials: false
- name: gradle build java executables - name: gradle build java executables
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:build pkl-cli:build pkl-codegen-java:build pkl-codegen-kotlin:build run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:build pkl-cli:build pkl-codegen-java:build pkl-codegen-kotlin:build
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -187,9 +227,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -225,11 +273,19 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -268,9 +324,17 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -306,11 +370,19 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -346,6 +418,14 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -421,7 +501,7 @@ jobs:
echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH" echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -456,9 +536,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -495,9 +583,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -533,11 +629,19 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -576,9 +680,17 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -614,11 +726,19 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -654,6 +774,14 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -729,7 +857,7 @@ jobs:
echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH" echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -764,9 +892,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
+10 -11
View File
@@ -1,11 +1,13 @@
# Generated from Workflow.pkl. DO NOT EDIT. # Generated from Workflow.pkl. DO NOT EDIT.
'on': 'on':
pull_request: {} pull_request:
branches:
- main
push: push:
branches: branches:
- main - main
schedule: schedule:
- cron: 38 1 * * 6 - cron: 29 17 * * 4
jobs: jobs:
analyze-actions: analyze-actions:
name: Analyze (actions) name: Analyze (actions)
@@ -16,13 +18,12 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false persist-credentials: false
- name: Initialize CodeQL - uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with: with:
languages: actions languages: actions
build-mode: none build-mode: none
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4 uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
with: with:
category: /language:actions category: /language:actions
analyze-java-kotlin: analyze-java-kotlin:
@@ -34,13 +35,12 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false persist-credentials: false
- name: Initialize CodeQL - uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with: with:
languages: java-kotlin languages: java-kotlin
build-mode: autobuild build-mode: autobuild
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4 uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
with: with:
category: /language:java-kotlin category: /language:java-kotlin
analyze-javascript-typescript: analyze-javascript-typescript:
@@ -52,12 +52,11 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false persist-credentials: false
- name: Initialize CodeQL - uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with: with:
languages: javascript-typescript languages: javascript-typescript
build-mode: none build-mode: none
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4 uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
with: with:
category: /language:javascript-typescript category: /language:javascript-typescript
+162 -18
View File
@@ -28,9 +28,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -61,9 +69,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -92,9 +108,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: bench:jmh - name: bench:jmh
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true bench:jmh
gradle-compatibility: gradle-compatibility:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
@@ -111,9 +135,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: :pkl-gradle:build :pkl-gradle:compatibilityTestReleases - name: :pkl-gradle:build :pkl-gradle:compatibilityTestReleases
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true :pkl-gradle:build :pkl-gradle:compatibilityTestReleases run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true :pkl-gradle:build :pkl-gradle:compatibilityTestReleases
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -143,12 +175,20 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false persist-credentials: false
- name: gradle build java executables - name: gradle build java executables
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:build pkl-cli:build pkl-codegen-java:build pkl-codegen-kotlin:build run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:build pkl-cli:build pkl-codegen-java:build pkl-codegen-kotlin:build
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -185,9 +225,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -223,11 +271,19 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -266,9 +322,17 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -304,11 +368,19 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -344,6 +416,14 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -419,7 +499,7 @@ jobs:
echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH" echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -454,9 +534,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -493,9 +581,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -531,11 +627,19 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -574,9 +678,17 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -612,11 +724,19 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -652,6 +772,14 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -727,7 +855,7 @@ jobs:
echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH" echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -762,9 +890,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -817,6 +953,14 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false persist-credentials: false
@@ -830,7 +974,7 @@ jobs:
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.ORG_GRADLE_PROJECT_SIGNINGPASSWORD }} ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.ORG_GRADLE_PROJECT_SIGNINGPASSWORD }}
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPEPASSWORD }} ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPEPASSWORD }}
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPEUSERNAME }} ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPEUSERNAME }}
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true --no-parallel publishToSonatype run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true --no-parallel publishToSonatype
dependency-submission: dependency-submission:
permissions: permissions:
contents: write contents: write
+126 -14
View File
@@ -24,9 +24,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -59,9 +67,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -94,9 +110,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -134,11 +158,19 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -178,9 +210,17 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -218,11 +258,19 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -260,6 +308,14 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -335,7 +391,7 @@ jobs:
echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH" echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -372,9 +428,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -412,9 +476,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -452,11 +524,19 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -496,9 +576,17 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -536,11 +624,19 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -578,6 +674,14 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -653,7 +757,7 @@ jobs:
echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH" echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -690,9 +794,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
+153 -17
View File
@@ -28,9 +28,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -61,9 +69,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -92,9 +108,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: bench:jmh - name: bench:jmh
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true bench:jmh
gradle-compatibility: gradle-compatibility:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
@@ -111,9 +135,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: :pkl-gradle:build :pkl-gradle:compatibilityTestReleases - name: :pkl-gradle:build :pkl-gradle:compatibilityTestReleases
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true :pkl-gradle:build :pkl-gradle:compatibilityTestReleases run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true :pkl-gradle:build :pkl-gradle:compatibilityTestReleases
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -143,12 +175,20 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false persist-credentials: false
- name: gradle build java executables - name: gradle build java executables
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:build pkl-cli:build pkl-codegen-java:build pkl-codegen-kotlin:build run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:build pkl-cli:build pkl-codegen-java:build pkl-codegen-kotlin:build
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -185,9 +225,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -223,11 +271,19 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -266,9 +322,17 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -304,11 +368,19 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -344,6 +416,14 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -419,7 +499,7 @@ jobs:
echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH" echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -454,9 +534,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -493,9 +581,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -531,11 +627,19 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -574,9 +678,17 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -612,11 +724,19 @@ jobs:
architecture: aarch64 architecture: aarch64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -652,6 +772,14 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -727,7 +855,7 @@ jobs:
echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH" echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -762,9 +890,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
+162 -18
View File
@@ -28,9 +28,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -61,9 +69,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -92,9 +108,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: bench:jmh - name: bench:jmh
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true bench:jmh
gradle-compatibility: gradle-compatibility:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
@@ -111,9 +135,17 @@ jobs:
architecture: x64 architecture: x64
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {} with: {}
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: :pkl-gradle:build :pkl-gradle:compatibilityTestReleases - name: :pkl-gradle:build :pkl-gradle:compatibilityTestReleases
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true :pkl-gradle:build :pkl-gradle:compatibilityTestReleases run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true :pkl-gradle:build :pkl-gradle:compatibilityTestReleases
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
@@ -144,12 +176,20 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false persist-credentials: false
- name: gradle build java executables - name: gradle build java executables
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:build pkl-cli:build pkl-codegen-java:build pkl-codegen-kotlin:build run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:build pkl-cli:build pkl-codegen-java:build pkl-codegen-kotlin:build
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -187,9 +227,17 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -226,11 +274,19 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -270,9 +326,17 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -309,11 +373,19 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -350,6 +422,14 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -425,7 +505,7 @@ jobs:
echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH" echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.musl=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.musl=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -461,9 +541,17 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -501,9 +589,17 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.targetArch=amd64 "-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh" pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -540,11 +636,19 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -584,9 +688,17 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -623,11 +735,19 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Fix git ownership - name: Fix git ownership
run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE" run: git status || git config --system --add safe.directory "$GITHUB_WORKSPACE"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -664,6 +784,14 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -739,7 +867,7 @@ jobs:
echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH" echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH"
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.musl=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.musl=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -775,9 +903,17 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
@@ -831,6 +967,14 @@ jobs:
- uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: with:
cache-disabled: true cache-disabled: true
- name: Set DEBUG_ARGS env var
env:
RUNNER_DEBUG: ${{ runner.debug }}
shell: bash
run: |-
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
fi
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false persist-credentials: false
@@ -844,7 +988,7 @@ jobs:
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.ORG_GRADLE_PROJECT_SIGNINGPASSWORD }} ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.ORG_GRADLE_PROJECT_SIGNINGPASSWORD }}
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPEPASSWORD }} ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPEPASSWORD }}
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPEUSERNAME }} ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPEUSERNAME }}
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true publishToSonatype closeAndReleaseSonatypeStagingRepository run: ./gradlew $DEBUG_ARGS --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true publishToSonatype closeAndReleaseSonatypeStagingRepository
github-release: github-release:
needs: deploy-release needs: deploy-release
permissions: permissions:
-10
View File
@@ -10,16 +10,6 @@
<option name="INSERT_INNER_CLASS_IMPORTS" value="true" /> <option name="INSERT_INNER_CLASS_IMPORTS" value="true" />
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" /> <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" /> <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" />
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value />
</option>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="" withSubpackages="true" static="true" />
<emptyLine />
<package name="" withSubpackages="true" static="false" />
</value>
</option>
<option name="RIGHT_MARGIN" value="100" /> <option name="RIGHT_MARGIN" value="100" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" /> <option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" /> <option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
@@ -0,0 +1,76 @@
/*
* Copyright © 2026 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import groovy.util.Node
import groovy.xml.XmlParser
import groovy.xml.XmlUtil
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
abstract class ConfigureLateInitAnnotation : DefaultTask() {
private val miscXmlFile = project.rootProject.file(".idea/misc.xml")
init {
inputs.file(miscXmlFile)
outputs.file(miscXmlFile)
}
@TaskAction
fun run() {
val annotationName = "org.pkl.core.util.LateInit"
if (!miscXmlFile.exists()) {
miscXmlFile.writeText(
"""
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
</project>
"""
.trimIndent()
.trim()
)
}
val root = XmlParser().parse(miscXmlFile)
fun Node.childNodes() = children().filterIsInstance<Node>()
var entryPointsManager =
root.childNodes().find {
it.name() == "component" && it.attribute("name") == "EntryPointsManager"
}
if (entryPointsManager == null) {
entryPointsManager = root.appendNode("component", mapOf("name" to "EntryPointsManager"))
}
var writeAnnotations = entryPointsManager.childNodes().find { it.name() == "writeAnnotations" }
if (writeAnnotations == null) {
writeAnnotations = entryPointsManager.appendNode("writeAnnotations")
}
val alreadyExists =
writeAnnotations.childNodes().any {
it.name() == "writeAnnotation" && it.attribute("name") == annotationName
}
if (!alreadyExists) {
writeAnnotations.appendNode("writeAnnotation", mapOf("name" to annotationName))
miscXmlFile.writeText(XmlUtil.serialize(root))
logger.lifecycle("Updated .idea/misc.xml")
} else {
logger.info("$annotationName is already configured in .idea/misc.xml")
}
}
}
@@ -44,7 +44,6 @@ kotlin {
freeCompilerArgs.addAll( freeCompilerArgs.addAll(
"-jvm-default=no-compatibility", // was: -Xjvm-default=all "-jvm-default=no-compatibility", // was: -Xjvm-default=all
"-Xjdk-release=${buildInfo.jvmTarget}", "-Xjdk-release=${buildInfo.jvmTarget}",
"-Xjsr305=strict",
) )
} }
} }
+4
View File
@@ -17,6 +17,7 @@
import org.jetbrains.gradle.ext.ActionDelegationConfig import org.jetbrains.gradle.ext.ActionDelegationConfig
import org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM import org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM
import org.jetbrains.gradle.ext.ProjectSettings import org.jetbrains.gradle.ext.ProjectSettings
import org.jetbrains.gradle.ext.taskTriggers
plugins { plugins {
id("pklAllProjects") id("pklAllProjects")
@@ -36,6 +37,8 @@ nexusPublishing {
} }
} }
val configureLateInitAnnotation by tasks.registering(ConfigureLateInitAnnotation::class)
idea { idea {
project { project {
this as ExtensionAware this as ExtensionAware
@@ -45,6 +48,7 @@ idea {
delegateBuildRunToGradle = true delegateBuildRunToGradle = true
testRunner = PLATFORM testRunner = PLATFORM
} }
taskTriggers.afterSync(configureLateInitAnnotation)
} }
} }
} }
@@ -210,6 +210,11 @@ class Http {
/// ///
/// Each rewrite must start with `http://` or `https://`, and must end with `/`. /// Each rewrite must start with `http://` or `https://`, and must end with `/`.
rewrites: Mapping<String, String>? rewrites: Mapping<String, String>?
/// HTTP headers.
/// Each entry key is a glob pattern that is matched against outbound request URLs.
/// Each value is a map of headers that is added to the matching request.
headers: Mapping<String, Mapping<String, Listing<String>>>?
} }
/// Settings that control how Pkl talks to HTTP proxies. /// Settings that control how Pkl talks to HTTP proxies.
+1 -1
View File
@@ -198,7 +198,7 @@ For Spring Boot applications, and for users of `pkl-config-java` compiling the g
.--non-null-annotation .--non-null-annotation
[%collapsible] [%collapsible]
==== ====
Default: `org.pkl.config.java.mapper.NonNull` + Default: `org.jspecify.annotations.NonNull` +
Fully qualified name of the annotation type to use for annotating non-null types. + Fully qualified name of the annotation type to use for annotating non-null types. +
The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)` The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)`
or the generated code may not compile. or the generated code may not compile.
@@ -5059,8 +5059,6 @@ in the context of that module.
[[glob-patterns]] [[glob-patterns]]
=== Glob Patterns === Glob Patterns
Resources and modules may be imported at the same time by globbing with the <<globbed-imports>> and <<globbed-reads>> features.
Pkl's glob patterns mostly follow the rules described by link:{uri-glob-7}[glob(7)], with the following differences: Pkl's glob patterns mostly follow the rules described by link:{uri-glob-7}[glob(7)], with the following differences:
* `*` includes names that start with a dot (`.`). * `*` includes names that start with a dot (`.`).
+17
View File
@@ -546,6 +546,15 @@ When enabled, test failures will show intermediate values in the assertion expre
Use `--no-power-assertions` to disable this feature if you prefer simpler output. Use `--no-power-assertions` to disable this feature if you prefer simpler output.
==== ====
[[test-reporter]]
.--test-reporter
[%collapsible]
====
Default: `spec` +
Example: `--test-reporter minimal` +
Which test reporter to use for CLI output. Possible values are `spec` and `minimal`.
====
This command also takes <<common-options, common options>>. This command also takes <<common-options, common options>>.
[[command-run]] [[command-run]]
@@ -667,6 +676,14 @@ Force generation of expected examples. +
The old expected files will be deleted if present. The old expected files will be deleted if present.
==== ====
.--test-reporter
[%collapsible]
====
Default: `spec` +
Example: `--test-reporter minimal` +
Which test reporter to use for CLI output. Possible values are `spec` and `minimal`.
====
This command also takes <<common-options,common options>>. This command also takes <<common-options,common options>>.
[[command-project-resolve]] [[command-project-resolve]]
@@ -158,6 +158,23 @@ This option is commonly used to enable package mirroring.
The above example will rewrite URL `\https://pkg.pkl-lang.org/pkl-k8s/k8s@1.0.0` to `\https://my.internal.mirror/pkl-k8s/k8s@1.0.0`. The above example will rewrite URL `\https://pkg.pkl-lang.org/pkl-k8s/k8s@1.0.0` to `\https://my.internal.mirror/pkl-k8s/k8s@1.0.0`.
==== ====
.--http-header
[%collapsible]
====
Default: (none) +
Example: `**=User-Agent: My User Agent` +
Additional headers to add to outbound HTTP requests.
The syntax is `<glob pattern>=<header name>:<header value>`, and any whitespace after the leading colon is trimmed.
The glob pattern is used to match against the URLs of outbound HTTP calls, and the value is the header name and value to add.
In the case of multiple matches, every header is added.
To describe a prefix match, the `\\**` wildcard should be added to the pattern.
For example, `https?://example.com/**` matches against every request to host `example.com`.
====
.--trace-mode .--trace-mode
[%collapsible] [%collapsible]
==== ====
+1 -1
View File
@@ -204,7 +204,7 @@ Download links:
The Pkldoc tool is offered as Gradle plugin, Java library, and CLI. The Pkldoc tool is offered as Gradle plugin, Java library, and CLI.
It can generate documentation either for modules directly, or generate documentation for _package uris_. It can generate documentation either for modules directly, or generate documentation for _package uris_.
The tool requires an argument of a module named _docsite-info.pkl_, that amends link:{uri-DocsiteInfo}[pkl.DocsiteInfo]. The tool accepts an optional argument of a module named _docsite-info.pkl_, that amends link:{uri-DocsiteInfo}[pkl.DocsiteInfo].
[discrete] [discrete]
==== Generating documentation for modules directly ==== Generating documentation for modules directly
+18 -1
View File
@@ -322,6 +322,15 @@ Default: `false` +
Whether to ignore expected example files and generate them again. Whether to ignore expected example files and generate them again.
==== ====
[[test-reporter]]
.testReporter: Property<String>
[%collapsible]
====
Default: `"spec"` +
Example: `reporter = "minimal"` +
Which test reporter to use for CLI output. Possible values are `"spec"` and `"minimal"`.
====
[[power-assertions-test]] [[power-assertions-test]]
.powerAssertions: Property<Boolean> .powerAssertions: Property<Boolean>
[%collapsible] [%collapsible]
@@ -414,7 +423,7 @@ For Spring Boot applications, and for users of `pkl-config-java` compiling the g
.nonNullAnnotation: Property<String> .nonNullAnnotation: Property<String>
[%collapsible] [%collapsible]
==== ====
Default: `"org.pkl.config.java.mapper.NonNull"` + Default: `"org.jspecify.annotations.NonNull"` +
Example: `nonNullAnnotation = "org.project.MyAnnotation"` + Example: `nonNullAnnotation = "org.project.MyAnnotation"` +
Fully qualified name of the annotation type to use for annotating non-null types. + Fully qualified name of the annotation type to use for annotating non-null types. +
The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)` The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)`
@@ -677,6 +686,14 @@ Default: `false` +
Whether to ignore expected example files and generate them again. Whether to ignore expected example files and generate them again.
==== ====
.testReporter: Property<String>
[%collapsible]
====
Default: `"spec"` +
Example: `reporter = "minimal"` +
Which test reporter to use for CLI output. Possible values are `"spec"` and `"minimal"`.
====
Common properties: Common properties:
include::../partials/gradle-common-properties.adoc[] include::../partials/gradle-common-properties.adoc[]
@@ -119,6 +119,19 @@ This option is commonly used to enable package mirroring.
The above example will rewrite URL `\https://pkg.pkl-lang.org/pkl-k8s/k8s@1.0.0` to `\https://my.internal.mirror/pkl-k8s/k8s@1.0.0`. The above example will rewrite URL `\https://pkg.pkl-lang.org/pkl-k8s/k8s@1.0.0` to `\https://my.internal.mirror/pkl-k8s/k8s@1.0.0`.
==== ====
.httpHeaders: MapProperty<String, Map<String, List<String>>>
[%collapsible]
====
Default: `null` +
Example: `httpHeaders = ["**": ["User-Agent": ["My User Agent"]]]` +
Additional headers to add to outbound HTTP requests.
The key is a glob pattern that is used to match against the URLs of outbound HTTP calls, and the value is the header name and values to add.
Each header value becomes its own HTTP header.
To describe a prefix match, the `\\**` wildcard should be added to the pattern.
For example, `https?://example.com/**` matches against every request to host `example.com`.
====
.powerAssertions: Property<Boolean> .powerAssertions: Property<Boolean>
[%collapsible] [%collapsible]
==== ====
@@ -37,6 +37,10 @@ The following APIs have been removed without replacement.
* `org.pkl.config.java.Config#makeConfig` (pr:https://github.com/apple/pkl/pull/1531[]) * `org.pkl.config.java.Config#makeConfig` (pr:https://github.com/apple/pkl/pull/1531[])
The following APIs have been deprecated for removal.
* `org.pkl.config.java.mapper.NonNull` (https://github.com/apple/pkl/pull/1607[#1607]).
.XXX .XXX
[%collapsible] [%collapsible]
==== ====
+113 -101
View File
@@ -1,3 +1,22 @@
/*
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.nio.file.Files
import kotlin.io.path.isDirectory
import kotlin.io.path.isRegularFile
import kotlin.io.path.useDirectoryEntries
import org.junit.platform.commons.annotation.Testable import org.junit.platform.commons.annotation.Testable
import org.junit.platform.engine.* import org.junit.platform.engine.*
import org.junit.platform.engine.TestDescriptor.Type import org.junit.platform.engine.TestDescriptor.Type
@@ -16,23 +35,18 @@ import org.pkl.core.Loggers
import org.pkl.core.SecurityManagers import org.pkl.core.SecurityManagers
import org.pkl.core.StackFrameTransformers import org.pkl.core.StackFrameTransformers
import org.pkl.core.evaluatorSettings.TraceMode import org.pkl.core.evaluatorSettings.TraceMode
import org.pkl.core.http.HttpClient
import org.pkl.core.module.ModuleKeyFactories import org.pkl.core.module.ModuleKeyFactories
import org.pkl.core.repl.ReplRequest import org.pkl.core.repl.ReplRequest
import org.pkl.core.repl.ReplResponse import org.pkl.core.repl.ReplResponse
import org.pkl.core.repl.ReplServer import org.pkl.core.repl.ReplServer
import org.pkl.core.resource.ResourceReaders
import org.pkl.core.util.IoUtils import org.pkl.core.util.IoUtils
import org.pkl.core.http.HttpClient
import org.pkl.parser.Parser import org.pkl.parser.Parser
import org.pkl.parser.ParserError import org.pkl.parser.ParserError
import org.pkl.parser.syntax.ClassProperty import org.pkl.parser.syntax.ClassProperty
import org.pkl.core.resource.ResourceReaders
import java.nio.file.Files
import kotlin.io.path.isDirectory
import kotlin.io.path.isRegularFile
import kotlin.io.path.useDirectoryEntries
@Testable @Testable class DocSnippetTests
class DocSnippetTests
class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.ExecutionContext>() { class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.ExecutionContext>() {
private val projectDir = rootProjectDir.resolve("docs") private val projectDir = rootProjectDir.resolve("docs")
@@ -41,7 +55,8 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
private companion object { private companion object {
val headingRegex = Regex("""(?u)^\s*(=++)\s*(.+)""") val headingRegex = Regex("""(?u)^\s*(=++)\s*(.+)""")
val collapsibleBlockRegex = Regex("""(?u)^\s*\[%collapsible""") val collapsibleBlockRegex = Regex("""(?u)^\s*\[%collapsible""")
val codeBlockRegex = Regex("""(?u)^\s*\[source(?:%(tested|parsed)(%error)?)?(?:,\{?([a-zA-Z-_]+)}?)?""") val codeBlockRegex =
Regex("""(?u)^\s*\[source(?:%(tested|parsed)(%error)?)?(?:,\{?([a-zA-Z-_]+)}?)?""")
val codeBlockNameRegex = Regex("""(?u)^\s*\.(.+)""") val codeBlockNameRegex = Regex("""(?u)^\s*\.(.+)""")
val codeBlockDelimiterRegex = Regex("""(?u)^\s*----""") val codeBlockDelimiterRegex = Regex("""(?u)^\s*----""")
val graphicsRegex = Regex("\\[small]#.+#") val graphicsRegex = Regex("\\[small]#.+#")
@@ -51,7 +66,7 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
override fun discover( override fun discover(
discoveryRequest: EngineDiscoveryRequest, discoveryRequest: EngineDiscoveryRequest,
uniqueId: UniqueId uniqueId: UniqueId,
): TestDescriptor { ): TestDescriptor {
val packageSelectors = discoveryRequest.getSelectorsByType(PackageSelector::class.java) val packageSelectors = discoveryRequest.getSelectorsByType(PackageSelector::class.java)
val classSelectors = discoveryRequest.getSelectorsByType(ClassSelector::class.java) val classSelectors = discoveryRequest.getSelectorsByType(ClassSelector::class.java)
@@ -62,12 +77,14 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
val packageName = testClass.`package`.name val packageName = testClass.`package`.name
val className = testClass.name val className = testClass.name
if (methodSelectors.isEmpty() if (
&& (packageSelectors.isEmpty() || packageSelectors.any { it.packageName == packageName }) methodSelectors.isEmpty() &&
&& (classSelectors.isEmpty() || classSelectors.any { it.className == className }) (packageSelectors.isEmpty() || packageSelectors.any { it.packageName == packageName }) &&
(classSelectors.isEmpty() || classSelectors.any { it.className == className })
) { ) {
val rootDescriptor = Descriptor.Path(uniqueId, docsDir.fileName.toString(), ClassSource.from(testClass), docsDir) val rootDescriptor =
Descriptor.Path(uniqueId, docsDir.fileName.toString(), ClassSource.from(testClass), docsDir)
doDiscover(rootDescriptor, uniqueIdSelectors) doDiscover(rootDescriptor, uniqueIdSelectors)
return rootDescriptor return rootDescriptor
} }
@@ -77,36 +94,34 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
} }
override fun createExecutionContext(request: ExecutionRequest): ExecutionContext { override fun createExecutionContext(request: ExecutionRequest): ExecutionContext {
val replServer = ReplServer( val replServer =
SecurityManagers.defaultManager, ReplServer(
HttpClient.dummyClient(), SecurityManagers.defaultManager,
Loggers.stdErr(), HttpClient.dummyClient(),
listOf( Loggers.stdErr(),
ModuleKeyFactories.standardLibrary, listOf(
ModuleKeyFactories.classPath(DocSnippetTests::class.java.classLoader), ModuleKeyFactories.standardLibrary,
ModuleKeyFactories.file ModuleKeyFactories.classPath(DocSnippetTests::class.java.classLoader),
), ModuleKeyFactories.file,
listOf( ),
ResourceReaders.environmentVariable(), listOf(ResourceReaders.environmentVariable(), ResourceReaders.externalProperty()),
ResourceReaders.externalProperty() System.getenv(),
), emptyMap(),
System.getenv(), null,
emptyMap(), null,
null, null,
null, IoUtils.getCurrentWorkingDir(),
null, StackFrameTransformers.defaultTransformer,
IoUtils.getCurrentWorkingDir(), false,
StackFrameTransformers.defaultTransformer, TraceMode.COMPACT,
false, )
TraceMode.COMPACT,
)
return ExecutionContext(replServer) return ExecutionContext(replServer)
} }
private fun doDiscover(rootDescriptor: TestDescriptor, selectors: List<UniqueIdSelector>) { private fun doDiscover(rootDescriptor: TestDescriptor, selectors: List<UniqueIdSelector>) {
fun isMatch(other: UniqueId) = selectors.isEmpty() || selectors.any { fun isMatch(other: UniqueId) =
it.uniqueId.hasPrefix(other) || other.hasPrefix(it.uniqueId) selectors.isEmpty() ||
} selectors.any { it.uniqueId.hasPrefix(other) || other.hasPrefix(it.uniqueId) }
docsDir.useDirectoryEntries { docsDirEntries -> docsDir.useDirectoryEntries { docsDirEntries ->
for (docsDirEntry in docsDirEntries) { for (docsDirEntry in docsDirEntries) {
@@ -116,12 +131,13 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
val docsDirEntryId = rootDescriptor.uniqueId.append("dir", docsDirEntryName) val docsDirEntryId = rootDescriptor.uniqueId.append("dir", docsDirEntryName)
if (!isMatch(docsDirEntryId)) continue if (!isMatch(docsDirEntryId)) continue
val docsDirEntryDescriptor = Descriptor.Path( val docsDirEntryDescriptor =
docsDirEntryId, Descriptor.Path(
docsDirEntryName, docsDirEntryId,
DirectorySource.from(docsDirEntry.toFile()), docsDirEntryName,
docsDirEntry DirectorySource.from(docsDirEntry.toFile()),
) docsDirEntry,
)
rootDescriptor.addChild(docsDirEntryDescriptor) rootDescriptor.addChild(docsDirEntryDescriptor)
val pagesDir = docsDirEntry.resolve("pages") val pagesDir = docsDirEntry.resolve("pages")
@@ -131,17 +147,20 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
for (pagesDirEntry in pagesDirEntries) { for (pagesDirEntry in pagesDirEntries) {
val pagesDirEntryName = pagesDirEntry.fileName.toString() val pagesDirEntryName = pagesDirEntry.fileName.toString()
val pagesDirEntryId = docsDirEntryId.append("file", pagesDirEntryName) val pagesDirEntryId = docsDirEntryId.append("file", pagesDirEntryName)
if (!pagesDirEntry.isRegularFile() || if (
!pagesDirEntryName.endsWith(".adoc") || !pagesDirEntry.isRegularFile() ||
!isMatch(pagesDirEntryId) !pagesDirEntryName.endsWith(".adoc") ||
) continue !isMatch(pagesDirEntryId)
val pagesDirEntryDescriptor = Descriptor.Path(
pagesDirEntryId,
pagesDirEntryName,
FileSource.from(pagesDirEntry.toFile()),
pagesDirEntry
) )
continue
val pagesDirEntryDescriptor =
Descriptor.Path(
pagesDirEntryId,
pagesDirEntryName,
FileSource.from(pagesDirEntry.toFile()),
pagesDirEntry,
)
docsDirEntryDescriptor.addChild(pagesDirEntryDescriptor) docsDirEntryDescriptor.addChild(pagesDirEntryDescriptor)
parseAsciidoc(pagesDirEntryDescriptor, selectors) parseAsciidoc(pagesDirEntryDescriptor, selectors)
@@ -174,17 +193,15 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
} }
val parent = sections.firstOrNull() ?: docDescriptor val parent = sections.firstOrNull() ?: docDescriptor
val normalizedTitle = title val normalizedTitle =
.replace("<code>", "") title.replace("<code>", "").replace("</code>", "").replace(graphicsRegex, "").trim()
.replace("</code>", "") val childSection =
.replace(graphicsRegex, "") Descriptor.Section(
.trim() parent.uniqueId.append("section", normalizedTitle),
val childSection = Descriptor.Section( normalizedTitle,
parent.uniqueId.append("section", normalizedTitle), FileSource.from(docDescriptor.path.toFile(), FilePosition.from(lineNum)),
normalizedTitle, newLevel,
FileSource.from(docDescriptor.path.toFile(), FilePosition.from(lineNum)), )
newLevel
)
sections.addFirst(childSection) sections.addFirst(childSection)
parent.addChild(childSection) parent.addChild(childSection)
@@ -217,7 +234,8 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
codeBlockNum += 1 codeBlockNum += 1
val (testMode, error, language) = codeBlockMatch.destructured val (testMode, error, language) = codeBlockMatch.destructured
if (testMode.isNotEmpty()) { if (testMode.isNotEmpty()) {
val blockName = codeBlockNameRegex.find(prevLine)?.groupValues?.get(1) ?: "snippet$codeBlockNum" val blockName =
codeBlockNameRegex.find(prevLine)?.groupValues?.get(1) ?: "snippet$codeBlockNum"
while (linesIterator.hasNext()) { while (linesIterator.hasNext()) {
advance() advance()
val startDelimiterMatch = codeBlockDelimiterRegex.find(line) val startDelimiterMatch = codeBlockDelimiterRegex.find(line)
@@ -236,10 +254,13 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
snippetId, snippetId,
blockName, blockName,
language, language,
FileSource.from(docDescriptor.path.toFile(), FilePosition.from(jumpToLineNum)), FileSource.from(
docDescriptor.path.toFile(),
FilePosition.from(jumpToLineNum),
),
builder.toString(), builder.toString(),
testMode == "parsed", testMode == "parsed",
error.isNotEmpty() error.isNotEmpty(),
) )
) )
} }
@@ -261,28 +282,21 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
} }
} }
private sealed class Descriptor( private sealed class Descriptor(uniqueId: UniqueId, displayName: String, source: TestSource) :
uniqueId: UniqueId, AbstractTestDescriptor(uniqueId, displayName, source), Node<ExecutionContext> {
displayName: String,
source: TestSource
) : AbstractTestDescriptor(uniqueId, displayName, source), Node<ExecutionContext> {
class Path( class Path(
uniqueId: UniqueId, uniqueId: UniqueId,
displayName: String, displayName: String,
source: TestSource, source: TestSource,
val path: java.nio.file.Path val path: java.nio.file.Path,
) : Descriptor(uniqueId, displayName, source) { ) : Descriptor(uniqueId, displayName, source) {
override fun getType() = Type.CONTAINER override fun getType() = Type.CONTAINER
} }
class Section( class Section(uniqueId: UniqueId, displayName: String, source: TestSource, val level: Int) :
uniqueId: UniqueId, Descriptor(uniqueId, displayName, source) {
displayName: String,
source: TestSource,
val level: Int
) : Descriptor(uniqueId, displayName, source) {
override fun getType() = Type.CONTAINER override fun getType() = Type.CONTAINER
@@ -299,7 +313,7 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
source: TestSource, source: TestSource,
private val code: String, private val code: String,
private val parseOnly: Boolean, private val parseOnly: Boolean,
private val expectError: Boolean private val expectError: Boolean,
) : Descriptor(uniqueId, displayName, source) { ) : Descriptor(uniqueId, displayName, source) {
override fun getType() = Type.TEST override fun getType() = Type.TEST
@@ -308,11 +322,14 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
when (language) { when (language) {
"pkl" -> Parser().parseModule(code) "pkl" -> Parser().parseModule(code)
"pkl-expr" -> Parser().parseExpressionInput(code) "pkl-expr" -> Parser().parseExpressionInput(code)
else -> throw(Exception("Unrecognized language: $language")) else -> throw (Exception("Unrecognized language: $language"))
} }
} }
override fun execute(context: ExecutionContext, executor: DynamicTestExecutor): ExecutionContext { override fun execute(
context: ExecutionContext,
executor: DynamicTestExecutor,
): ExecutionContext {
if (parseOnly) { if (parseOnly) {
try { try {
parsed parsed
@@ -328,12 +345,7 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
} }
context.replServer.handleRequest( context.replServer.handleRequest(
ReplRequest.Eval( ReplRequest.Eval("snippet", code, !expectError, !expectError)
"snippet",
code,
!expectError,
!expectError
)
) )
val properties = parsed.children()?.filterIsInstance<ClassProperty>() ?: emptyList() val properties = parsed.children()?.filterIsInstance<ClassProperty>() ?: emptyList()
@@ -342,21 +354,21 @@ class DocSnippetTestsEngine : HierarchicalTestEngine<DocSnippetTestsEngine.Execu
// force each property // force each property
for (prop in properties) { for (prop in properties) {
responses.addAll(context.replServer.handleRequest( responses.addAll(
ReplRequest.Eval( context.replServer.handleRequest(
"snippet", ReplRequest.Eval("snippet", prop.name.value, false, true)
prop.name.value,
false,
true
) )
)) )
} }
if (expectError) { if (expectError) {
if (responses.dropLast(1).any { it !is ReplResponse.EvalSuccess } || if (
responses.last() !is ReplResponse.EvalError) { responses.dropLast(1).any { it !is ReplResponse.EvalSuccess } ||
responses.last() !is ReplResponse.EvalError
) {
throw AssertionError( throw AssertionError(
"Expected %error snippet to fail at the end, but got the following REPL responses:\n\n" + "Expected %error snippet to fail at the end, but got the following REPL responses:\n\n" +
responses.joinToString("\n\n") { it.message }) responses.joinToString("\n\n") { it.message }
)
} }
return context return context
+10 -11
View File
@@ -5,9 +5,9 @@ checksumPlugin = "1.4.0"
clikt = "5.0.3" clikt = "5.0.3"
commonMark = "0.28.0" commonMark = "0.28.0"
downloadTaskPlugin = "5.7.0" downloadTaskPlugin = "5.7.0"
errorProne = "2.48.0" errorProne = "2.49.0"
errorPronePlugin = "5.1.0" errorPronePlugin = "5.1.0"
geantyref = "1.3.16" geantyref = "2.0.1"
#noinspection UnusedVersionCatalogEntry #noinspection UnusedVersionCatalogEntry
googleJavaFormat = "1.35.0" googleJavaFormat = "1.35.0"
# 25.0.2 no longer supports macos-x64 # 25.0.2 no longer supports macos-x64
@@ -29,21 +29,20 @@ graalVmSha256-windows-x64 = "fde83c5ceec2c75560c747ccd9f314f90e4cf5c5287416e67c4
#noinspection UnusedVersionCatalogEntry #noinspection UnusedVersionCatalogEntry
graalVmSha256-windows-aarch64 = "unavailable" graalVmSha256-windows-aarch64 = "unavailable"
ideaExtPlugin = "1.4.1" ideaExtPlugin = "1.4.1"
javaPoet = "0.14.0" javaPoet = "0.15.0"
javaxInject = "1" javaxInject = "1"
jimfs = "1.3.1" jimfs = "1.3.1"
jline = "4.0.12" jline = "4.0.14"
jmh = "1.37" jmh = "1.37"
jmhPlugin = "0.7.3" jmhPlugin = "0.7.3"
jspecify = "1.0.0" jspecify = "1.0.0"
jsr305 = "3.0.2"
junit = "6.0.3" junit = "6.0.3"
# 1.7+ generates much more verbose code # 1.7+ generates much more verbose code
kotlinPoet = "1.6.0" kotlinPoet = "1.6.0"
kotlinStdLib = "2.2.21" kotlinStdLib = "2.2.21"
#noinspection UnusedVersionCatalogEntry #noinspection UnusedVersionCatalogEntry
kotlinTarget = "2.2" kotlinTarget = "2.2"
kotlinToolchain = "2.3.20" kotlinToolchain = "2.3.21"
kotlinxHtml = "0.12.0" kotlinxHtml = "0.12.0"
# 1.9.0 is the last version compatible with Kotlin 2.2 # 1.9.0 is the last version compatible with Kotlin 2.2
kotlinxSerialization = "1.9.0" kotlinxSerialization = "1.9.0"
@@ -53,14 +52,14 @@ ktfmt = "0.62"
# replaces nuValidator's log4j dependency # replaces nuValidator's log4j dependency
# 2.17.1 is the last version compatible with nuValidator # 2.17.1 is the last version compatible with nuValidator
log4j = "2.17.1" log4j = "2.17.1"
msgpack = "0.9.11" msgpack = "0.9.12"
nexusPublishPlugin = "2.0.0" nexusPublishPlugin = "2.0.0"
nullaway = "0.13.2" nullaway = "0.13.4"
nullawayPlugin = "3.0.0" nullawayPlugin = "3.0.0"
nuValidator = "26.4.2" nuValidator = "26.5.7"
paguro = "3.10.3" paguro = "3.10.3"
shadowPlugin = "9.4.1" shadowPlugin = "9.4.1"
slf4j = "2.0.17" slf4j = "2.0.18"
snakeYaml = "3.0.1" snakeYaml = "3.0.1"
spotlessPlugin = "8.4.0" spotlessPlugin = "8.4.0"
wiremock = "3.13.2" wiremock = "3.13.2"
@@ -74,6 +73,7 @@ commonMarkTables = { group = "org.commonmark", name = "commonmark-ext-gfm-tables
downloadTaskPlugin = { group = "de.undercouch", name = "gradle-download-task", version.ref = "downloadTaskPlugin" } downloadTaskPlugin = { group = "de.undercouch", name = "gradle-download-task", version.ref = "downloadTaskPlugin" }
#noinspection UnusedVersionCatalogEntry #noinspection UnusedVersionCatalogEntry
errorProne = { group = "com.google.errorprone", name = "error_prone_core", version.ref = "errorProne" } errorProne = { group = "com.google.errorprone", name = "error_prone_core", version.ref = "errorProne" }
errorProneAnnotations = { group = "com.google.errorprone", name = "error_prone_annotations", version.ref = "errorProne" }
errorPronePlugin = { group = "net.ltgt.gradle", name = "gradle-errorprone-plugin", version.ref = "errorPronePlugin" } errorPronePlugin = { group = "net.ltgt.gradle", name = "gradle-errorprone-plugin", version.ref = "errorPronePlugin" }
geantyref = { group = "io.leangen.geantyref", name = "geantyref", version.ref = "geantyref" } geantyref = { group = "io.leangen.geantyref", name = "geantyref", version.ref = "geantyref" }
graalCompiler = { group = "org.graalvm.compiler", name = "compiler", version.ref = "graalVm" } graalCompiler = { group = "org.graalvm.compiler", name = "compiler", version.ref = "graalVm" }
@@ -87,7 +87,6 @@ jlineTerminal = { group = "org.jline", name = "jline-terminal", version.ref = "j
jlineTerminalJni = { group = "org.jline", name = "jline-terminal-jni", version.ref = "jline" } jlineTerminalJni = { group = "org.jline", name = "jline-terminal-jni", version.ref = "jline" }
#noinspection UnusedVersionCatalogEntry #noinspection UnusedVersionCatalogEntry
jspecify = { group = "org.jspecify", name = "jspecify", version.ref = "jspecify" } jspecify = { group = "org.jspecify", name = "jspecify", version.ref = "jspecify" }
jsr305 = { group = "com.google.code.findbugs", name = "jsr305", version.ref = "jsr305" }
junitApi = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit" } junitApi = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit" }
junitEngine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit" } junitEngine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit" }
junitParams = { group = "org.junit.jupiter", name = "junit-jupiter-params", version.ref = "junit" } junitParams = { group = "org.junit.jupiter", name = "junit-jupiter-params", version.ref = "junit" }
Binary file not shown.
+4 -2
View File
@@ -1,8 +1,10 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionSha256Sum=2ab2958f2a1e51120c326cad6f385153bb11ee93b3c216c5fccebfdfbb7ec6cb distributionSha256Sum=bafc141b619ad6350fd975fc903156dd5c151998cc8b058e8c1044ab5f7b031f
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
networkTimeout=10000 networkTimeout=10000
retries=0
retryBackOffMs=500
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
Vendored
+1 -1
View File
@@ -57,7 +57,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
Vendored
+10 -21
View File
@@ -23,8 +23,8 @@
@rem @rem
@rem ########################################################################## @rem ##########################################################################
@rem Set local scope for the variables with windows NT shell @rem Set local scope for the variables, and ensure extensions are enabled
if "%OS%"=="Windows_NT" setlocal setlocal EnableExtensions
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=. if "%DIRNAME%"=="" set DIRNAME=.
@@ -51,7 +51,7 @@ echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2 echo location of your Java installation. 1>&2
goto fail "%COMSPEC%" /c exit 1
:findJavaFromJavaHome :findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
@@ -65,7 +65,7 @@ echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2 echo location of your Java installation. 1>&2
goto fail "%COMSPEC%" /c exit 1
:execute :execute
@rem Setup the command line @rem Setup the command line
@@ -73,21 +73,10 @@ goto fail
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* @rem endlocal doesn't take effect until after the line is parsed and variables are expanded
@rem which allows us to clear the local environment before executing the java command
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
:end :exitWithErrorLevel
@rem End local scope for the variables with windows NT shell @rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
if %ERRORLEVEL% equ 0 goto mainEnd "%COMSPEC%" /c exit %ERRORLEVEL%
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@@ -67,7 +67,7 @@ constructor(
val evaluator = builder.build() val evaluator = builder.build()
evaluator.use { evaluator.use {
evaluator.evaluateCommand( evaluator.evaluateCommand(
uri(resolvedSourceModules.first()), uri(options.normalizedSourceModules.first()),
reservedFlagNames, reservedFlagNames,
reservedFlagShortNames, reservedFlagShortNames,
) { spec -> ) { spec ->
@@ -115,7 +115,7 @@ constructor(
// used just to resolve the `%{moduleName}` placeholder // used just to resolve the `%{moduleName}` placeholder
val moduleResolver = ModuleResolver(moduleKeyFactories(ModulePathResolver.empty())) val moduleResolver = ModuleResolver(moduleKeyFactories(ModulePathResolver.empty()))
return resolvedSourceModules.associateWith { uri -> return options.base.normalizedSourceModules.associateWith { uri ->
val moduleDir: String? = val moduleDir: String? =
IoUtils.toPath(uri)?.let { IoUtils.toPath(uri)?.let {
IoUtils.relativize(it.parent, workingDir).toString().ifEmpty { "." } IoUtils.relativize(it.parent, workingDir).toString().ifEmpty { "." }
@@ -191,7 +191,7 @@ constructor(
} }
} else { } else {
var outputWritten = false var outputWritten = false
for (moduleUri in resolvedSourceModules) { for (moduleUri in options.base.normalizedSourceModules) {
val moduleSource = toModuleSource(moduleUri, inputStream) val moduleSource = toModuleSource(moduleUri, inputStream)
if (options.expression != null) { if (options.expression != null) {
val output = evaluator.evaluateExpressionString(moduleSource, options.expression) val output = evaluator.evaluateExpressionString(moduleSource, options.expression)
@@ -44,19 +44,19 @@ constructor(
private val sourceModule = private val sourceModule =
ModuleSource.text( ModuleSource.text(
""" """
import "pkl:analyze" import "pkl:analyze"
local importStrings = read*("prop:pkl.analyzeImports.**").toMap().values.toSet() local importStrings = read*("prop:pkl.analyzeImports.**").toMap().values.toSet()
output { output {
value = analyze.importGraph(importStrings) value = analyze.importGraph(importStrings)
renderer { renderer {
converters { converters {
[Map] = (it) -> it.toMapping() [Map] = (it) -> it.toMapping()
[Set] = (it) -> it.toListing() [Set] = (it) -> it.toListing()
}
} }
} }
}
""" """
.trimIndent() .trimIndent()
) )
@@ -66,7 +66,7 @@ constructor(
try { try {
return builder return builder
.apply { .apply {
for ((idx, sourceModule) in resolvedSourceModules.withIndex()) { for ((idx, sourceModule) in options.base.normalizedSourceModules.withIndex()) {
addExternalProperty("pkl.analyzeImports.$idx", sourceModule.toString()) addExternalProperty("pkl.analyzeImports.$idx", sourceModule.toString())
} }
} }
@@ -15,6 +15,7 @@
*/ */
package org.pkl.cli package org.pkl.cli
import java.io.StringWriter
import java.io.Writer import java.io.Writer
import org.pkl.commons.cli.* import org.pkl.commons.cli.*
import org.pkl.core.Closeables import org.pkl.core.Closeables
@@ -22,8 +23,9 @@ import org.pkl.core.EvaluatorBuilder
import org.pkl.core.ModuleSource.uri import org.pkl.core.ModuleSource.uri
import org.pkl.core.PklException import org.pkl.core.PklException
import org.pkl.core.TestResults import org.pkl.core.TestResults
import org.pkl.core.stdlib.test.report.JUnitReport import org.pkl.core.stdlib.test.report.JUnitReporter
import org.pkl.core.stdlib.test.report.SimpleReport import org.pkl.core.stdlib.test.report.MinimalReporter
import org.pkl.core.stdlib.test.report.SpecReporter
import org.pkl.core.util.ErrorMessages import org.pkl.core.util.ErrorMessages
class CliTestRunner class CliTestRunner
@@ -47,7 +49,7 @@ constructor(
private fun evalTest(builder: EvaluatorBuilder) { private fun evalTest(builder: EvaluatorBuilder) {
val sources = val sources =
resolvedSourceModules.ifEmpty { project?.tests?.map { it.toUri() } } options.normalizedSourceModules.ifEmpty { project?.tests?.map { it.toUri() } }
?: ?:
// keep in sync with error message thrown by clikt // keep in sync with error message thrown by clikt
throw CliException( throw CliException(
@@ -55,7 +57,7 @@ constructor(
Usage: pkl test [<options>] <modules>... Usage: pkl test [<options>] <modules>...
Error: missing argument <modules> Error: missing argument <modules>
""" """
.trimIndent() .trimIndent()
) )
@@ -64,13 +66,15 @@ constructor(
var failed = false var failed = false
var isExampleWrittenFailure = true var isExampleWrittenFailure = true
val moduleNames = mutableSetOf<String>() val moduleNames = mutableSetOf<String>()
val reporter = SimpleReport(useColor) val reporter =
when (testOptions.reporter) {
TestReporter.SPEC -> SpecReporter(useColor)
TestReporter.MINIMAL -> MinimalReporter(useColor)
}
val allTestResults = mutableListOf<TestResults>() val allTestResults = mutableListOf<TestResults>()
val junitDir = testOptions.junitDir val junitDir = testOptions.junitDir
if (junitDir != null) { junitDir?.toFile()?.mkdirs()
junitDir.toFile().mkdirs()
}
for ((idx, moduleUri) in sources.withIndex()) { for ((idx, moduleUri) in sources.withIndex()) {
try { try {
@@ -80,8 +84,11 @@ constructor(
failed = results.failed() failed = results.failed()
isExampleWrittenFailure = results.isExampleWrittenFailure.and(isExampleWrittenFailure) isExampleWrittenFailure = results.isExampleWrittenFailure.and(isExampleWrittenFailure)
} }
reporter.report(results, consoleWriter) val tmpWriter = StringWriter()
if (sources.size > 1 && idx != sources.size - 1) { reporter.report(results, tmpWriter)
val report = tmpWriter.toString()
consoleWriter.write(report)
if (report.isNotEmpty() && sources.size > 1 && idx != sources.size - 1) {
consoleWriter.append('\n') consoleWriter.append('\n')
} }
consoleWriter.flush() consoleWriter.flush()
@@ -101,7 +108,7 @@ constructor(
moduleNames += moduleName moduleNames += moduleName
if (!testOptions.junitAggregateReports) { if (!testOptions.junitAggregateReports) {
JUnitReport().reportToPath(results, junitDir.resolve(moduleName)) JUnitReporter().reportToPath(results, junitDir.resolve(moduleName))
} }
} }
} catch (ex: Exception) { } catch (ex: Exception) {
@@ -119,7 +126,7 @@ constructor(
} }
if (testOptions.junitAggregateReports && junitDir != null) { if (testOptions.junitAggregateReports && junitDir != null) {
val fileName = "${testOptions.junitAggregateSuiteName}.xml" val fileName = "${testOptions.junitAggregateSuiteName}.xml"
JUnitReport(testOptions.junitAggregateSuiteName) JUnitReporter(testOptions.junitAggregateSuiteName)
.summarizeToPath(allTestResults, junitDir.resolve(fileName)) .summarizeToPath(allTestResults, junitDir.resolve(fileName))
} }
consoleWriter.append('\n') consoleWriter.append('\n')
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ internal object ReplMessages {
* Incomplete input will be continued on the next line. * Incomplete input will be continued on the next line.
* Multi-line programs can be copy-pasted into the REPL. * Multi-line programs can be copy-pasted into the REPL.
""" """
.trimIndent() .trimIndent()
val examples: String = val examples: String =
@@ -44,13 +44,13 @@ import org.pkl.commons.writeString
class CliCommandRunnerTest { class CliCommandRunnerTest {
private val renderOptions = private val renderOptions =
""" """
extends "pkl:Command" extends "pkl:Command"
options: Options options: Options
output { output {
value = options value = options
} }
""" """
.trimIndent() .trimIndent()
@@ -104,10 +104,10 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
foo: String foo: String
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -125,48 +125,48 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
`number-as-int`: Number `number-as-int`: Number
`number-as-float`: Number `number-as-float`: Number
`number-nullable`: Number? `number-nullable`: Number?
`number-default`: Number = 100.0 `number-default`: Number = 100.0
`number-default-overridden`: Number = 100.0 `number-default-overridden`: Number = 100.0
float: Float float: Float
`float-without-decimals`: Float `float-without-decimals`: Float
`float-nullable`: Float? `float-nullable`: Float?
`float-default`: Float = 100.0 `float-default`: Float = 100.0
`float-default-overridden`: Float = 100.0 `float-default-overridden`: Float = 100.0
int: Int int: Int
`int-nullable`: Int? `int-nullable`: Int?
`int-default`: Int = 100 `int-default`: Int = 100
`int-default-overridden`: Int = 100 `int-default-overridden`: Int = 100
int8: Int8 int8: Int8
int16: Int16 int16: Int16
int32: Int32 int32: Int32
uint: UInt uint: UInt
uint8: UInt8 uint8: UInt8
uint16: UInt16 uint16: UInt16
uint32: UInt32 uint32: UInt32
boolean: Boolean boolean: Boolean
`boolean-nullable`: Boolean? `boolean-nullable`: Boolean?
`boolean-default`: Boolean = true `boolean-default`: Boolean = true
`boolean-default-overridden`: Boolean = false `boolean-default-overridden`: Boolean = false
string: String string: String
`string-nullable`: String? `string-nullable`: String?
`string-default`: String = "default" `string-default`: String = "default"
`string-default-overridden`: String = "default" `string-default-overridden`: String = "default"
char: Char char: Char
`char-nullable`: Char? `char-nullable`: Char?
`char-default`: Char = "a" `char-default`: Char = "a"
`char-default-overridden`: Char = "b" `char-default-overridden`: Char = "b"
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -245,45 +245,45 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Argument @Argument
`number-as-int`: Number `number-as-int`: Number
@Argument @Argument
`number-as-float`: Number `number-as-float`: Number
@Argument @Argument
float: Float float: Float
@Argument @Argument
`float-without-decimals`: Float `float-without-decimals`: Float
@Argument @Argument
int: Int int: Int
@Argument @Argument
int8: Int8 int8: Int8
@Argument @Argument
int16: Int16 int16: Int16
@Argument @Argument
int32: Int32 int32: Int32
@Argument @Argument
uint: UInt uint: UInt
@Argument @Argument
uint8: UInt8 uint8: UInt8
@Argument @Argument
uint16: UInt16 uint16: UInt16
@Argument @Argument
uint32: UInt32 uint32: UInt32
@Argument @Argument
boolean: Boolean boolean: Boolean
@Argument @Argument
string: String string: String
@Argument @Argument
char: Char char: Char
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -338,21 +338,21 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
typealias MyEnum = "d" | "e" | *"f" typealias MyEnum = "d" | "e" | *"f"
class Options { class Options {
enum: "a" | "b" | "c" enum: "a" | "b" | "c"
`enum-default`: "a" | *"b" | "c" `enum-default`: "a" | *"b" | "c"
`enum-explicit-default`: "a" | "b" | "c" = "c" `enum-explicit-default`: "a" | "b" | "c" = "c"
`enum-alias-default`: MyEnum `enum-alias-default`: MyEnum
`enum-alias-explicit-default`: MyEnum = "e" `enum-alias-explicit-default`: MyEnum = "e"
`enum-alias-default-overridden`: MyEnum `enum-alias-default-overridden`: MyEnum
`enum-single`: "x" `enum-single`: "x"
`enum-single-nullable`: "x"? `enum-single-nullable`: "x"?
`enum-single-explicit-default`: "x" = "x" `enum-single-explicit-default`: "x" = "x"
`enum-single-overridden`: "x" `enum-single-overridden`: "x"
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -386,16 +386,16 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
typealias MyEnum = "d" | "e" | *"f" typealias MyEnum = "d" | "e" | *"f"
class Options { class Options {
@Argument @Argument
enum: "a" | "b" | "c" enum: "a" | "b" | "c"
@Argument @Argument
`enum-default`: "a" | *"b" | "c" `enum-default`: "a" | *"b" | "c"
@Argument @Argument
`enum-alias-default`: MyEnum `enum-alias-default`: MyEnum
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -419,18 +419,18 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
list: List<Number> list: List<Number>
`list-nullable`: List<Number>? `list-nullable`: List<Number>?
`list-default`: List<Number> = List(1, 2, 300.0) `list-default`: List<Number> = List(1, 2, 300.0)
set: Set<Number> set: Set<Number>
`set-nullable`: Set<Number>? `set-nullable`: Set<Number>?
`set-default`: Set<Number> = Set(1, 2, 300.0, 2) `set-default`: Set<Number> = Set(1, 2, 300.0, 2)
`enum-list`: List<"a" | "b" | *"c"> `enum-list`: List<"a" | "b" | *"c">
`enum-set`: Set<"a" | "b" | *"c"> `enum-set`: Set<"a" | "b" | *"c">
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -477,11 +477,11 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Argument @Argument
list: List<Number> list: List<Number>
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -500,11 +500,11 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Argument @Argument
set: Set<Number> set: Set<Number>
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output2 = val output2 =
@@ -523,11 +523,11 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Argument @Argument
listing: Listing<Number> listing: Listing<Number>
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output3 = val output3 =
@@ -554,11 +554,11 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Argument @Argument
map: Map<Number, Number> map: Map<Number, Number>
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -577,11 +577,11 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Argument @Argument
mapping: Mapping<Number, Number> mapping: Mapping<Number, Number>
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output2 = val output2 =
@@ -603,11 +603,11 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Argument @Argument
pair: Pair<Number, Number> pair: Pair<Number, Number>
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output3 = runToStdout(CliBaseOptions(sourceModules = listOf(moduleUri3)), listOf("1=0.0")) val output3 = runToStdout(CliBaseOptions(sourceModules = listOf(moduleUri3)), listOf("1=0.0"))
@@ -628,15 +628,15 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
typealias MyEnum = "a" | "b" | *"c" typealias MyEnum = "a" | "b" | *"c"
class Options { class Options {
map: Map<Char, Number> map: Map<Char, Number>
`map-nullable`: Map<Char, Number>? `map-nullable`: Map<Char, Number>?
`map-default`: Map<Char, Number> = Map("x", 123, "y", 456.789) `map-default`: Map<Char, Number> = Map("x", 123, "y", 456.789)
`enum-map`: Map<MyEnum, MyEnum> `enum-map`: Map<MyEnum, MyEnum>
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -664,15 +664,15 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
typealias MyEnum = "a" | "b" | *"c" typealias MyEnum = "a" | "b" | *"c"
class Options { class Options {
mapping: Mapping<Char, Number> mapping: Mapping<Char, Number>
`mapping-nullable`: Mapping<Char, Number>? `mapping-nullable`: Mapping<Char, Number>?
`mapping-default`: Mapping<Char, Number> = new { ["x"] = 123; ["y"] = 456.789 } `mapping-default`: Mapping<Char, Number> = new { ["x"] = 123; ["y"] = 456.789 }
`enum-mapping`: Mapping<MyEnum, MyEnum> `enum-mapping`: Mapping<MyEnum, MyEnum>
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -709,15 +709,15 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
typealias MyEnum = "a" | "b" | *"c" typealias MyEnum = "a" | "b" | *"c"
class Options { class Options {
pair: Pair<Char, Number> pair: Pair<Char, Number>
`pair-nullable`: Pair<Char, Number>? `pair-nullable`: Pair<Char, Number>?
`pair-default`: Pair<Char, Number> = Pair("x", 123) `pair-default`: Pair<Char, Number> = Pair("x", 123)
`enum-pair`: Pair<MyEnum, MyEnum> `enum-pair`: Pair<MyEnum, MyEnum>
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -745,17 +745,17 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Argument { convert = module.convertDuration } @Argument { convert = module.convertDuration }
a: Duration a: Duration
@Argument { convert = module.convertDuration } @Argument { convert = module.convertDuration }
b: Duration b: Duration
@Argument { convert = module.convertDuration } @Argument { convert = module.convertDuration }
c: Duration c: Duration
@Argument { convert = module.convertDuration } @Argument { convert = module.convertDuration }
d: Duration d: Duration
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -783,17 +783,17 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Argument { convert = module.convertDataSize } @Argument { convert = module.convertDataSize }
a: DataSize a: DataSize
@Argument { convert = module.convertDataSize } @Argument { convert = module.convertDataSize }
b: DataSize b: DataSize
@Argument { convert = module.convertDataSize } @Argument { convert = module.convertDataSize }
c: DataSize c: DataSize
@Argument { convert = module.convertDataSize } @Argument { convert = module.convertDataSize }
d: DataSize d: DataSize
} }
""" """
.trimIndent(), .trimIndent(),
) )
val output = val output =
@@ -820,23 +820,23 @@ class CliCommandRunnerTest {
writePklFile( writePklFile(
"cmd.pkl", "cmd.pkl",
""" """
extends "pkl:Command" extends "pkl:Command"
options: Options options: Options
output { output {
value = (options) { value = (options) {
fromImport { fromImport {
baz = true // assert that imported modules are not forced baz = true // assert that imported modules are not forced
}
} }
} }
}
class Options { class Options {
@Argument { convert = (it) -> new Import{ uri = it } } @Argument { convert = (it) -> new Import{ uri = it } }
fromImport: Module fromImport: Module
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -844,10 +844,10 @@ class CliCommandRunnerTest {
writePklFile( writePklFile(
"import.pkl", "import.pkl",
""" """
foo = 1 foo = 1
bar = "baz" bar = "baz"
baz: Boolean baz: Boolean
""" """
.trimIndent(), .trimIndent(),
) )
@@ -873,26 +873,26 @@ class CliCommandRunnerTest {
writePklFile( writePklFile(
"cmd.pkl", "cmd.pkl",
""" """
extends "pkl:Command" extends "pkl:Command"
options: Options options: Options
output { output {
value = (options) { value = (options) {
fromImport { fromImport {
baz = true // assert that imported modules are not forced baz = true // assert that imported modules are not forced
}
} }
} }
}
class Options { class Options {
@Flag { @Flag {
convert = (it) -> new Import{ uri = it } convert = (it) -> new Import{ uri = it }
transformAll = (values) -> values.firstOrNull ?? new Import { uri = "./default.pkl" } transformAll = (values) -> values.firstOrNull ?? new Import { uri = "./default.pkl" }
}
fromImport: Module
} }
fromImport: Module """
}
"""
.trimIndent(), .trimIndent(),
) )
@@ -900,10 +900,10 @@ class CliCommandRunnerTest {
writePklFile( writePklFile(
"default.pkl", "default.pkl",
""" """
foo = 1 foo = 1
bar = "baz" bar = "baz"
baz: Boolean baz: Boolean
""" """
.trimIndent(), .trimIndent(),
) )
@@ -932,26 +932,26 @@ class CliCommandRunnerTest {
writePklFile( writePklFile(
"cmd.pkl", "cmd.pkl",
""" """
extends "pkl:Command" extends "pkl:Command"
import "base.pkl" import "base.pkl"
options: Options options: Options
output { output {
value = (options) { value = (options) {
fromGlobImport { fromGlobImport {
[[true]] { [[true]] {
baz = true // assert that imported modules are not forced baz = true // assert that imported modules are not forced
}
} }
} }
} }
}
class Options { class Options {
@Argument { convert = (it) -> new Import { uri = it; glob = true }; multiple = false } @Argument { convert = (it) -> new Import { uri = it; glob = true }; multiple = false }
fromGlobImport: Mapping<String, base> fromGlobImport: Mapping<String, base>
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -959,10 +959,10 @@ class CliCommandRunnerTest {
writePklFile( writePklFile(
"base.pkl", "base.pkl",
""" """
foo: Int foo: Int
bar: String bar: String
baz: Boolean baz: Boolean
""" """
.trimIndent(), .trimIndent(),
) )
writePklFile( writePklFile(
@@ -971,7 +971,7 @@ class CliCommandRunnerTest {
amends "base.pkl" amends "base.pkl"
foo = 1 foo = 1
bar = "baz" bar = "baz"
""" """
.trimIndent(), .trimIndent(),
) )
writePklFile( writePklFile(
@@ -980,7 +980,7 @@ class CliCommandRunnerTest {
amends "base.pkl" amends "base.pkl"
foo = 2 foo = 2
bar = "qux" bar = "qux"
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1019,11 +1019,11 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Argument { convert = (it) -> throw("oops!") } @Argument { convert = (it) -> throw("oops!") }
foo: String foo: String
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1041,11 +1041,11 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Argument { convert = (it) -> it.noSuchMethod() } @Argument { convert = (it) -> it.noSuchMethod() }
foo: String foo: String
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1063,12 +1063,12 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
const function overflow(it) = overflow(it) const function overflow(it) = overflow(it)
class Options { class Options {
@Argument { convert = (it) -> overflow(it) } @Argument { convert = (it) -> overflow(it) }
foo: String foo: String
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1086,19 +1086,19 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@BooleanFlag @BooleanFlag
`bool-true`: Boolean `bool-true`: Boolean
@BooleanFlag @BooleanFlag
`bool-false`: Boolean `bool-false`: Boolean
@BooleanFlag @BooleanFlag
`bool-nullable`: Boolean? `bool-nullable`: Boolean?
@BooleanFlag @BooleanFlag
`bool-default-true`: Boolean = true `bool-default-true`: Boolean = true
@BooleanFlag @BooleanFlag
`bool-default-false`: Boolean = false `bool-default-false`: Boolean = false
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1128,11 +1128,11 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@BooleanFlag @BooleanFlag
foo: String foo: String
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1151,25 +1151,25 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@CountedFlag { shortName = "a" } @CountedFlag { shortName = "a" }
int: Int int: Int
@CountedFlag { shortName = "b" } @CountedFlag { shortName = "b" }
int8: Int8 int8: Int8
@CountedFlag { shortName = "c" } @CountedFlag { shortName = "c" }
int16: Int16 int16: Int16
@CountedFlag { shortName = "d" } @CountedFlag { shortName = "d" }
int32: Int32 int32: Int32
@CountedFlag { shortName = "x" } @CountedFlag { shortName = "x" }
uint: UInt uint: UInt
@CountedFlag { shortName = "y" } @CountedFlag { shortName = "y" }
uint8: UInt8 uint8: UInt8
@CountedFlag { shortName = "g" } @CountedFlag { shortName = "g" }
uint16: UInt16 uint16: UInt16
@CountedFlag { shortName = "i" } @CountedFlag { shortName = "i" }
uint32: UInt32 uint32: UInt32
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1202,14 +1202,14 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
@Flag { @Flag {
multiple = true multiple = true
transformAll = (values) -> values.fold(0, (res, acc) -> res + acc) transformAll = (values) -> values.fold(0, (res, acc) -> res + acc)
} }
foo: Int foo: Int
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1235,21 +1235,21 @@ class CliCommandRunnerTest {
"cmd.pkl", "cmd.pkl",
renderOptions + renderOptions +
""" """
class Options { class Options {
none: String? none: String?
enum: *"a" | "b" | "c" enum: *"a" | "b" | "c"
@Flag { completionCandidates = "paths" } @Flag { completionCandidates = "paths" }
path: String? path: String?
@Flag { completionCandidates { "foo"; "bar"; "baz" } } @Flag { completionCandidates { "foo"; "bar"; "baz" } }
explicit: String? explicit: String?
@Argument @Argument
enumArg: *"a" | "b" | "c" enumArg: *"a" | "b" | "c"
@Argument { completionCandidates = "paths" } @Argument { completionCandidates = "paths" }
pathArg: String pathArg: String
@Argument { completionCandidates { "foo"; "bar"; "baz" } } @Argument { completionCandidates { "foo"; "bar"; "baz" } }
explicitArg: String explicitArg: String
} }
""" """
.trimIndent(), .trimIndent(),
) )
val exc = val exc =
@@ -58,7 +58,7 @@ class CliEvaluatorTest {
name = "pigeon" name = "pigeon"
age = 20 + 10 age = 20 + 10
} }
""" """
.trimIndent() .trimIndent()
private val packageServer = PackageServer() private val packageServer = PackageServer()
@@ -243,12 +243,12 @@ person:
.resolve("test2.pkl") .resolve("test2.pkl")
.writeString( .writeString(
""" """
amends "test.pkl" amends "test.pkl"
person { person {
name = "barn owl" name = "barn owl"
} }
""" """
.trimIndent() .trimIndent()
) )
@@ -739,7 +739,7 @@ result = someLib.x
} }
} }
} }
""" """
.trimIndent(), .trimIndent(),
) )
) )
@@ -815,31 +815,31 @@ result = someLib.x
writePklFile( writePklFile(
"test0.pkl", "test0.pkl",
""" """
output { output {
files { files {
["foo.pcf"] { ["foo.pcf"] {
value = new Dynamic { value = new Dynamic {
["bar"] = "baz" ["bar"] = "baz"
}
} }
} }
} }
} """
"""
.trimIndent(), .trimIndent(),
), ),
writePklFile( writePklFile(
"test1.pkl", "test1.pkl",
""" """
output { output {
files { files {
["bar.pcf"] { ["bar.pcf"] {
value = new Dynamic { value = new Dynamic {
["bar"] = "baz" ["bar"] = "baz"
}
} }
} }
} }
} """
"""
.trimIndent(), .trimIndent(),
), ),
) )
@@ -860,27 +860,27 @@ result = someLib.x
writePklFile( writePklFile(
"bar.pkl", "bar.pkl",
""" """
output { output {
files { files {
["foo.pcf"] { ["foo.pcf"] {
text = "myBar" text = "myBar"
}
} }
} }
} """
"""
.trimIndent(), .trimIndent(),
), ),
writePklFile( writePklFile(
"foo.pkl", "foo.pkl",
""" """
output { output {
files { files {
["foo.pcf"] { ["foo.pcf"] {
text = "myFoo" text = "myFoo"
}
} }
} }
} """
"""
.trimIndent(), .trimIndent(),
), ),
) )
@@ -918,7 +918,7 @@ result = someLib.x
} }
} }
} }
""" """
.trimIndent(), .trimIndent(),
) )
val options = val options =
@@ -949,7 +949,7 @@ result = someLib.x
} }
} }
} }
""" """
.trimIndent(), .trimIndent(),
) )
val options = val options =
@@ -970,23 +970,23 @@ result = someLib.x
writePklFile( writePklFile(
"test1.pkl", "test1.pkl",
""" """
output { output {
files { files {
["."] { text = "bar" } ["."] { text = "bar" }
}
} }
} """
"""
.trimIndent(), .trimIndent(),
), ),
writePklFile( writePklFile(
"test2.pkl", "test2.pkl",
""" """
output { output {
files { files {
["myDir"] { text = "bar" } ["myDir"] { text = "bar" }
}
} }
} """
"""
.trimIndent(), .trimIndent(),
), ),
) )
@@ -1009,23 +1009,23 @@ result = someLib.x
writePklFile( writePklFile(
"test1.pkl", "test1.pkl",
""" """
output { output {
files { files {
["foo.txt"] { text = "bar" } ["foo.txt"] { text = "bar" }
}
} }
} """
"""
.trimIndent(), .trimIndent(),
), ),
writePklFile( writePklFile(
"test2.pkl", "test2.pkl",
""" """
output { output {
files { files {
["foo.txt"] { text = "bar" } ["foo.txt"] { text = "bar" }
}
} }
} """
"""
.trimIndent(), .trimIndent(),
), ),
) )
@@ -1045,13 +1045,13 @@ result = someLib.x
writePklFile( writePklFile(
"test.pkl", "test.pkl",
""" """
output { output {
files { files {
["foo.txt"] { text = "bar" } ["foo.txt"] { text = "bar" }
["./foo.txt"] { text = "bar" } ["./foo.txt"] { text = "bar" }
}
} }
} """
"""
.trimIndent(), .trimIndent(),
) )
val options = val options =
@@ -1071,12 +1071,12 @@ result = someLib.x
writePklFile( writePklFile(
"test.pkl", "test.pkl",
""" """
output { output {
files { files {
["foo:bar"] { text = "bar" } ["foo:bar"] { text = "bar" }
}
} }
} """
"""
.trimIndent(), .trimIndent(),
) )
@@ -1096,12 +1096,12 @@ result = someLib.x
writePklFile( writePklFile(
"test.pkl", "test.pkl",
""" """
output { output {
files { files {
["foo\\bar"] { text = "bar" } ["foo\\bar"] { text = "bar" }
}
} }
} """
"""
.trimIndent(), .trimIndent(),
) )
@@ -1120,10 +1120,10 @@ result = someLib.x
writePklFile( writePklFile(
"test.pkl", "test.pkl",
""" """
foo { foo {
bar = 1 bar = 1
} }
""" """
.trimIndent(), .trimIndent(),
) )
val options = val options =
@@ -1136,8 +1136,8 @@ result = someLib.x
assertThat(buffer.toString(StandardCharsets.UTF_8)) assertThat(buffer.toString(StandardCharsets.UTF_8))
.isEqualTo( .isEqualTo(
""" """
new Dynamic { bar = 1 } new Dynamic { bar = 1 }
""" """
.trimIndent() .trimIndent()
) )
} }
@@ -1148,13 +1148,13 @@ result = someLib.x
writePklFile( writePklFile(
"test.pkl", "test.pkl",
""" """
class Person { class Person {
name: String name: String
function toString() = "Person(\(name))" function toString() = "Person(\(name))"
} }
person: Person = new { name = "Frodo" } person: Person = new { name = "Frodo" }
""" """
.trimIndent(), .trimIndent(),
) )
val options = val options =
@@ -1173,10 +1173,10 @@ result = someLib.x
writePklFile( writePklFile(
"test.pkl", "test.pkl",
""" """
person { person {
friend { name = "Bilbo" } friend { name = "Bilbo" }
} }
""" """
.trimIndent(), .trimIndent(),
) )
val options = val options =
@@ -1196,8 +1196,8 @@ result = someLib.x
writePklFile( writePklFile(
"test.pkl", "test.pkl",
""" """
res = 1 res = 1
""" """
.trimIndent(), .trimIndent(),
) )
writePklFile( writePklFile(
@@ -1206,7 +1206,7 @@ result = someLib.x
amends "pkl:Project" amends "pkl:Project"
package = throw("invalid project package") package = throw("invalid project package")
""" """
.trimIndent(), .trimIndent(),
) )
val options = val options =
@@ -1225,8 +1225,8 @@ result = someLib.x
writePklFile( writePklFile(
"test.pkl", "test.pkl",
""" """
res = read*("env:**") res = read*("env:**")
""" """
.trimIndent(), .trimIndent(),
) )
writePklFile( writePklFile(
@@ -1241,7 +1241,7 @@ result = someLib.x
["bar"] = "bar" ["bar"] = "bar"
} }
} }
""" """
.trimIndent(), .trimIndent(),
) )
val options = val options =
@@ -1251,12 +1251,12 @@ result = someLib.x
assertThat(buffer.toString(StandardCharsets.UTF_8)) assertThat(buffer.toString(StandardCharsets.UTF_8))
.isEqualTo( .isEqualTo(
""" """
res { res {
["env:bar"] = "bar" ["env:bar"] = "bar"
["env:foo"] = "foo" ["env:foo"] = "foo"
} }
""" """
.trimIndent() .trimIndent()
) )
} }
@@ -1353,10 +1353,10 @@ result = someLib.x
writePklFile( writePklFile(
"test.pkl", "test.pkl",
""" """
import "package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl" import "package://localhost:0/birds@0.5.0#/catalog/Swallow.pkl"
res = Swallow res = Swallow
""" """
.trimIndent(), .trimIndent(),
) )
val buffer = ByteArrayOutputStream() val buffer = ByteArrayOutputStream()
@@ -1375,14 +1375,14 @@ result = someLib.x
assertThat(buffer.toString(StandardCharsets.UTF_8)) assertThat(buffer.toString(StandardCharsets.UTF_8))
.isEqualTo( .isEqualTo(
""" """
res { res {
name = "Swallow" name = "Swallow"
favoriteFruit { favoriteFruit {
name = "Apple" name = "Apple"
}
} }
}
""" """
.trimIndent() .trimIndent()
) )
assertThat(tempDir.resolve("package-2")).doesNotExist() assertThat(tempDir.resolve("package-2")).doesNotExist()
@@ -1481,13 +1481,13 @@ result = someLib.x
assertThat(output) assertThat(output)
.isEqualTo( .isEqualTo(
""" """
name = "Ostrich" name = "Ostrich"
favoriteFruit { favoriteFruit {
name = "Orange" name = "Orange"
} }
""" """
.trimIndent() .trimIndent()
) )
verify(getRequestedFor(urlEqualTo("birds@0.5.0"))) verify(getRequestedFor(urlEqualTo("birds@0.5.0")))
@@ -1590,13 +1590,13 @@ result = someLib.x
homeDir.writeFile( homeDir.writeFile(
"settings.pkl", "settings.pkl",
""" """
amends "pkl:settings" amends "pkl:settings"
http { http {
proxy { proxy {
address = "http://invalid.proxy.address" address = "http://invalid.proxy.address"
}
} }
}
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1614,6 +1614,24 @@ result = someLib.x
assertThat(output).isEqualTo("result = 1\n") assertThat(output).isEqualTo("result = 1\n")
} }
@Test
fun `eval configured http headers`(wwRuntimeInfo: WireMockRuntimeInfo) {
stubFor(get(anyUrl()).willReturn(ok("result = 1")))
val file = URI("${wwRuntimeInfo.httpBaseUrl}/foo.pkl")
val output =
evalToConsole(
CliEvaluatorOptions(
CliBaseOptions(
sourceModules = listOf(file),
httpHeaders = mapOf("**" to mapOf("X-Foo" to listOf("Foo"))),
allowedModules =
listOf(Pattern.compile("http:"), Pattern.compile("file:"), Pattern.compile("pkl:")),
)
)
)
verify(getRequestedFor(urlEqualTo("/foo.pkl")).withHeader("X-Foo", equalTo("Foo")))
}
@Test @Test
fun `eval file with non-ASCII name`() { fun `eval file with non-ASCII name`() {
val tempDirUri = tempDir.toUri() val tempDirUri = tempDir.toUri()
@@ -1677,26 +1695,26 @@ result = someLib.x
writePklFile( writePklFile(
"test.pkl", "test.pkl",
""" """
pigeon { pigeon {
name = "Pigeon" name = "Pigeon"
diet = "Seeds" diet = "Seeds"
} }
parrot { parrot {
name = "Parrot" name = "Parrot"
diet = "Seeds" diet = "Seeds"
} }
output { output {
files { files {
["pigeon.json"] { ["pigeon.json"] {
value = pigeon value = pigeon
renderer = new JsonRenderer {} renderer = new JsonRenderer {}
} }
["birds/parrot.yaml"] { ["birds/parrot.yaml"] {
value = parrot value = parrot
renderer = new YamlRenderer {} renderer = new YamlRenderer {}
}
} }
} }
}
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1713,10 +1731,10 @@ result = someLib.x
realOutputDir.resolve("pigeon.json"), realOutputDir.resolve("pigeon.json"),
"pigeon.json", "pigeon.json",
""" """
{ {
"name": "Pigeon", "name": "Pigeon",
"diet": "Seeds" "diet": "Seeds"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1725,8 +1743,8 @@ result = someLib.x
realOutputDir.resolve("birds/parrot.yaml"), realOutputDir.resolve("birds/parrot.yaml"),
"parrot.yaml", "parrot.yaml",
""" """
name: Parrot name: Parrot
diet: Seeds diet: Seeds
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1735,10 +1753,10 @@ result = someLib.x
symlinkOutputDir.resolve("pigeon.json"), symlinkOutputDir.resolve("pigeon.json"),
"pigeon.json", "pigeon.json",
""" """
{ {
"name": "Pigeon", "name": "Pigeon",
"diet": "Seeds" "diet": "Seeds"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1747,13 +1765,39 @@ result = someLib.x
symlinkOutputDir.resolve("birds/parrot.yaml"), symlinkOutputDir.resolve("birds/parrot.yaml"),
"parrot.yaml", "parrot.yaml",
""" """
name: Parrot name: Parrot
diet: Seeds diet: Seeds
""" """
.trimIndent(), .trimIndent(),
) )
} }
@Test
fun `eval dependency notation source`(@TempDir tempDir: Path) {
PackageServer.populateCacheDir(tempDir)
val projectPath =
FileTestUtils.rootProjectDir.resolve(
"pkl-commons-cli/src/main/resources/org/pkl/commons/cli/project1/"
)
val options =
CliEvaluatorOptions(
CliBaseOptions(
sourceModules = listOf(URI("@fruit/catalog/apple.pkl")),
projectDir = projectPath,
moduleCacheDir = tempDir,
)
)
val output = evalToConsole(options)
assertThat(output)
.isEqualTo(
"""
name = "Apple 🍎"
"""
.trimIndent()
)
}
private fun evalModuleThatImportsPackage(certsFile: Path?, testPort: Int = -1) { private fun evalModuleThatImportsPackage(certsFile: Path?, testPort: Int = -1) {
val moduleUri = val moduleUri =
writePklFile( writePklFile(
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -74,7 +74,7 @@ class CliMainTest {
value = x value = x
renderer = new JsonRenderer {} renderer = new JsonRenderer {}
} }
""" """
.trimIndent() .trimIndent()
val inputFile = tempDir.resolve("test.pkl").writeString(code).toString() val inputFile = tempDir.resolve("test.pkl").writeString(code).toString()
val outputFile = makeSymdir(tempDir, "out", "linkOut").resolve("test.pkl").toString() val outputFile = makeSymdir(tempDir, "out", "linkOut").resolve("test.pkl").toString()
@@ -169,4 +169,60 @@ class CliMainTest {
link.createSymbolicLinkPointingTo(dir) link.createSymbolicLinkPointingTo(dir)
return link return link
} }
@Test
fun `invalid http header glob pattern`() {
val ex =
assertThrows<BadParameterValue> {
rootCmd.parse(arrayOf("eval", "--http-header", "foo{{}}=bar:baz", "myModule.pkl"))
}
assertThat(ex.message)
.contains("Sub-patterns cannot be nested. To fix, remove or escape the inner `{` character.")
}
@Test
fun `forbidden http header name`() {
val ex =
assertThrows<BadParameterValue> {
rootCmd.parse(arrayOf("eval", "--http-header", "**=Connection: baz", "myModule.pkl"))
}
assertThat(ex.message).contains("HTTP header `Connection` is a reserved header")
}
@Test
fun `bad http header value`() {
val ex =
assertThrows<BadParameterValue> {
rootCmd.parse(arrayOf("eval", "--http-header", "**=X-Foo:🙃", "myModule.pkl"))
}
assertThat(ex.message).contains("HTTP header value `🙃` has invalid syntax")
}
@Test
fun `multiple headers`() {
val cmd = RootCommand()
cmd.parse(
arrayOf(
"eval",
"--http-header",
"**=X-Foo:Foo",
"--http-header",
"**=X-Foo:Foo2",
"--http-header",
"**=X-Bar:Bar",
"--http-header",
"https://example.com/**=X-Qux:Qux",
"pkl:base",
)
)
val evalCmd = cmd.registeredSubcommands().filterIsInstance<EvalCommand>().first()
assertThat(evalCmd.baseOptions.httpHeaders)
.isEqualTo(
mapOf(
"**" to mapOf("X-Foo" to listOf("Foo", "Foo2"), "X-Bar" to listOf("Bar")),
"https://example.com/**" to mapOf("X-Qux" to listOf("Qux")),
)
)
}
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -74,7 +74,7 @@ class CliPackageDownloaderTest {
evaluatorSettings { evaluatorSettings {
moduleCacheDir = ".my-cache" moduleCacheDir = ".my-cache"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -210,7 +210,7 @@ class CliPackageDownloaderTest {
Exception when making request `GET https://bogus.domain/notAPackage@1.0.0`: Exception when making request `GET https://bogus.domain/notAPackage@1.0.0`:
Error connecting to host `bogus.domain`. Error connecting to host `bogus.domain`.
""" """
.trimIndent() .trimIndent()
) )
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -85,8 +85,8 @@ class CliProjectPackagerTest {
.resolve("PklProject") .resolve("PklProject")
.writeString( .writeString(
""" """
amends "pkl:Project" amends "pkl:Project"
""" """
.trimIndent() .trimIndent()
) )
val packager = val packager =
@@ -114,7 +114,7 @@ class CliProjectPackagerTest {
1 == 2 1 == 2
} }
} }
""" """
.trimIndent(), .trimIndent(),
) )
tempDir.writeFile( tempDir.writeFile(
@@ -129,7 +129,7 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
apiTests { "myTest.pkl" } apiTests { "myTest.pkl" }
} }
""" """
.trimIndent(), .trimIndent(),
) )
val buffer = StringWriter() val buffer = StringWriter()
@@ -160,7 +160,7 @@ class CliProjectPackagerTest {
1 == 1 1 == 1
} }
} }
""" """
.trimIndent() .trimIndent()
) )
tempDir tempDir
@@ -176,7 +176,7 @@ class CliProjectPackagerTest {
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
apiTests { "myTest.pkl" } apiTests { "myTest.pkl" }
} }
""" """
.trimIndent() .trimIndent()
) )
val buffer = StringWriter() val buffer = StringWriter()
@@ -209,7 +209,7 @@ class CliProjectPackagerTest {
new Bird { name = "Finch"; favoriteFruit { name = "Tangerine" } } new Bird { name = "Finch"; favoriteFruit { name = "Tangerine" } }
} }
} }
""" """
.trimIndent() .trimIndent()
) )
projectDir projectDir
@@ -227,7 +227,7 @@ class CliProjectPackagerTest {
} }
} }
""" """
.trimIndent() .trimIndent()
) )
projectDir projectDir
@@ -249,7 +249,7 @@ class CliProjectPackagerTest {
uri = "package://localhost:0/birds@0.5.0" uri = "package://localhost:0/birds@0.5.0"
} }
} }
""" """
.trimIndent() .trimIndent()
) )
projectDir projectDir
@@ -300,7 +300,7 @@ class CliProjectPackagerTest {
module foo module foo
name: String name: String
""" """
.trimIndent(), .trimIndent(),
) )
@@ -311,7 +311,7 @@ class CliProjectPackagerTest {
foo foo
bar bar
baz baz
""" """
.trimIndent(), .trimIndent(),
) )
@@ -327,7 +327,7 @@ class CliProjectPackagerTest {
baseUri = "package://example.com/mypackage" baseUri = "package://example.com/mypackage"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
""" """
.trimIndent() .trimIndent()
) )
val packager = val packager =
@@ -348,18 +348,18 @@ class CliProjectPackagerTest {
assertThat(expectedMetadata) assertThat(expectedMetadata)
.hasContent( .hasContent(
""" """
{ {
"name": "mypackage", "name": "mypackage",
"packageUri": "package://example.com/mypackage@1.0.0", "packageUri": "package://example.com/mypackage@1.0.0",
"version": "1.0.0", "version": "1.0.0",
"packageZipUrl": "https://foo.com", "packageZipUrl": "https://foo.com",
"packageZipChecksums": { "packageZipChecksums": {
"sha256": "e83b67722ea17ba41717ce6e99ae8ee02d66df6294bd319ce403075b1071c3e0" "sha256": "e83b67722ea17ba41717ce6e99ae8ee02d66df6294bd319ce403075b1071c3e0"
}, },
"dependencies": {}, "dependencies": {},
"authors": [] "authors": []
} }
""" """
.trimIndent() .trimIndent()
) )
assertThat(expectedArchive).exists() assertThat(expectedArchive).exists()
@@ -395,21 +395,21 @@ class CliProjectPackagerTest {
tempDir.writeFile( tempDir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "mypackage" name = "mypackage"
version = "1.0.0" version = "1.0.0"
baseUri = "package://example.com/mypackage" baseUri = "package://example.com/mypackage"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
exclude { exclude {
"*.bin" "*.bin"
"child/main.pkl" "child/main.pkl"
"*.test.pkl" "*.test.pkl"
"examples/Ex1.pkl" "examples/Ex1.pkl"
"tests/**" "tests/**"
}
} }
}
""" """
.trimIndent(), .trimIndent(),
) )
@@ -444,21 +444,21 @@ class CliProjectPackagerTest {
projectDir.writeFile( projectDir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "mypackage" name = "mypackage"
version = "1.0.0" version = "1.0.0"
baseUri = "package://example.com/mypackage" baseUri = "package://example.com/mypackage"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
dependencies { dependencies {
["birds"] { ["birds"] {
uri = "package://localhost:0/birds@0.5.0" uri = "package://localhost:0/birds@0.5.0"
}
["project2"] = import("../project2/PklProject")
} }
["project2"] = import("../project2/PklProject")
}
""" """
.trimIndent(), .trimIndent(),
) )
@@ -489,24 +489,24 @@ class CliProjectPackagerTest {
project2Dir.writeFile( project2Dir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "project2" name = "project2"
baseUri = "package://localhost:0/project2" baseUri = "package://localhost:0/project2"
version = "5.0.0" version = "5.0.0"
packageZipUrl = "https://foo.com/project2.zip" packageZipUrl = "https://foo.com/project2.zip"
} }
""" """
.trimIndent(), .trimIndent(),
) )
project2Dir.writeFile( project2Dir.writeFile(
"PklProject.deps.json", "PklProject.deps.json",
""" """
{ {
"schemaVersion": 1, "schemaVersion": 1,
"resolvedDependencies": {} "resolvedDependencies": {}
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -557,18 +557,18 @@ class CliProjectPackagerTest {
assertThat(project2Metadata.readString()) assertThat(project2Metadata.readString())
.isEqualTo( .isEqualTo(
""" """
{ {
"name": "project2", "name": "project2",
"packageUri": "package://localhost:0/project2@5.0.0", "packageUri": "package://localhost:0/project2@5.0.0",
"version": "5.0.0", "version": "5.0.0",
"packageZipUrl": "https://foo.com/project2.zip", "packageZipUrl": "https://foo.com/project2.zip",
"packageZipChecksums": { "packageZipChecksums": {
"sha256": "8739c76e681f900923b900c9df0ef75cf421d39cabb54650c4b9ad19b6a76d85" "sha256": "8739c76e681f900923b900c9df0ef75cf421d39cabb54650c4b9ad19b6a76d85"
}, },
"dependencies": {}, "dependencies": {},
"authors": [] "authors": []
} }
""" """
.trimIndent() .trimIndent()
) )
} }
@@ -582,44 +582,44 @@ class CliProjectPackagerTest {
projectDir.writeFile( projectDir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "mypackage" name = "mypackage"
version = "1.0.0" version = "1.0.0"
baseUri = "package://example.com/mypackage" baseUri = "package://example.com/mypackage"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
dependencies { dependencies {
["birds"] { ["birds"] {
uri = "package://localhost:0/birds@0.5.0" uri = "package://localhost:0/birds@0.5.0"
}
["project2"] = import("../project2/PklProject")
} }
["project2"] = import("../project2/PklProject")
}
""" """
.trimIndent(), .trimIndent(),
) )
projectDir.writeFile( projectDir.writeFile(
"PklProject.deps.json", "PklProject.deps.json",
""" """
{ {
"schemaVersion": 1, "schemaVersion": 1,
"resolvedDependencies": { "resolvedDependencies": {
"package://localhost:0/birds@0": { "package://localhost:0/birds@0": {
"type": "remote", "type": "remote",
"uri": "projectpackage://localhost:0/birds@0.5.0", "uri": "projectpackage://localhost:0/birds@0.5.0",
"checksums": { "checksums": {
"sha256": "0a5ad2dc13f06f73f96ba94e8d01d48252bc934e2de71a837620ca0fef8a7453" "sha256": "0a5ad2dc13f06f73f96ba94e8d01d48252bc934e2de71a837620ca0fef8a7453"
}
},
"package://localhost:0/project2@5": {
"type": "local",
"uri": "projectpackage://localhost:0/project2@5.0.0",
"path": "../project2"
} }
},
"package://localhost:0/project2@5": {
"type": "local",
"uri": "projectpackage://localhost:0/project2@5.0.0",
"path": "../project2"
} }
} }
}
""" """
.trimIndent(), .trimIndent(),
) )
@@ -627,24 +627,24 @@ class CliProjectPackagerTest {
project2Dir.writeFile( project2Dir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "project2" name = "project2"
baseUri = "package://localhost:0/project2" baseUri = "package://localhost:0/project2"
version = "5.0.0" version = "5.0.0"
packageZipUrl = "https://foo.com/project2.zip" packageZipUrl = "https://foo.com/project2.zip"
} }
""" """
.trimIndent(), .trimIndent(),
) )
project2Dir.writeFile( project2Dir.writeFile(
"PklProject.deps.json", "PklProject.deps.json",
""" """
{ {
"schemaVersion": 1, "schemaVersion": 1,
"resolvedDependencies": {} "resolvedDependencies": {}
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -667,23 +667,23 @@ class CliProjectPackagerTest {
tempDir.writeFile( tempDir.writeFile(
"main.pkl", "main.pkl",
""" """
import "../foo.pkl" import "../foo.pkl"
res = foo res = foo
""" """
.trimIndent(), .trimIndent(),
) )
tempDir.writeFile( tempDir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "mypackage" name = "mypackage"
version = "1.0.0" version = "1.0.0"
baseUri = "package://example.com/mypackage" baseUri = "package://example.com/mypackage"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -702,12 +702,12 @@ class CliProjectPackagerTest {
assertThat(e.message) assertThat(e.message)
.startsWith( .startsWith(
""" """
Pkl Error Pkl Error
Path `../foo.pkl` includes path segments that are outside the project root directory. Path `../foo.pkl` includes path segments that are outside the project root directory.
1 | import "../foo.pkl" 1 | import "../foo.pkl"
^^^^^^^^^^^^ ^^^^^^^^^^^^
""" """
.trimIndent() .trimIndent()
) )
} }
@@ -730,14 +730,14 @@ class CliProjectPackagerTest {
tempDir.writeFile( tempDir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "mypackage" name = "mypackage"
version = "1.0.0" version = "1.0.0"
baseUri = "package://example.com/mypackage" baseUri = "package://example.com/mypackage"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -763,6 +763,43 @@ class CliProjectPackagerTest {
) )
} }
@Test
fun `import path verification with glob imports`(@TempDir tempDir: Path) {
tempDir.writeFile(
"main.pkl",
"""
import* "**.pkl" as foo
res = foo
"""
.trimIndent(),
)
tempDir.writeFile(
"PklProject",
"""
amends "pkl:Project"
package {
name = "mypackage"
version = "1.0.0"
baseUri = "package://example.com/mypackage"
packageZipUrl = "https://foo.com"
}
"""
.trimIndent(),
)
CliProjectPackager(
CliBaseOptions(workingDir = tempDir),
listOf(tempDir),
CliTestOptions(),
".out/%{name}@%{version}",
skipPublishCheck = true,
consoleWriter = StringWriter(),
)
.run()
}
@Test @Test
@DisabledOnOs(OS.WINDOWS) @DisabledOnOs(OS.WINDOWS)
fun `import path verification -- absolute read from root dir`(@TempDir tempDir: Path) { fun `import path verification -- absolute read from root dir`(@TempDir tempDir: Path) {
@@ -776,14 +813,14 @@ class CliProjectPackagerTest {
tempDir.writeFile( tempDir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "mypackage" name = "mypackage"
version = "1.0.0" version = "1.0.0"
baseUri = "package://example.com/mypackage" baseUri = "package://example.com/mypackage"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -814,21 +851,21 @@ class CliProjectPackagerTest {
tempDir.writeFile( tempDir.writeFile(
"foo/bar.pkl", "foo/bar.pkl",
""" """
import "baz.pkl" import "baz.pkl"
""" """
.trimIndent(), .trimIndent(),
) )
tempDir.writeFile( tempDir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "mypackage" name = "mypackage"
version = "1.0.0" version = "1.0.0"
baseUri = "package://example.com/mypackage" baseUri = "package://example.com/mypackage"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -849,14 +886,14 @@ class CliProjectPackagerTest {
tempDir.writeFile( tempDir.writeFile(
"project1/PklProject", "project1/PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "project1" name = "project1"
version = "1.0.0" version = "1.0.0"
baseUri = "package://example.com/project1" baseUri = "package://example.com/project1"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -864,14 +901,14 @@ class CliProjectPackagerTest {
tempDir.writeFile( tempDir.writeFile(
"project2/PklProject", "project2/PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "project2" name = "project2"
version = "2.0.0" version = "2.0.0"
baseUri = "package://example.com/project2" baseUri = "package://example.com/project2"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -914,14 +951,14 @@ class CliProjectPackagerTest {
"project/PklProject", "project/PklProject",
// intentionally conflict with localhost:0/birds@0.5.0 from our test fixtures // intentionally conflict with localhost:0/birds@0.5.0 from our test fixtures
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "birds" name = "birds"
version = "0.5.0" version = "0.5.0"
baseUri = "package://localhost:0/birds" baseUri = "package://localhost:0/birds"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -959,14 +996,14 @@ class CliProjectPackagerTest {
tempDir.writeFile( tempDir.writeFile(
"project/PklProject", "project/PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "mangos" name = "mangos"
version = "1.0.0" version = "1.0.0"
baseUri = "package://localhost:0/mangos" baseUri = "package://localhost:0/mangos"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1015,7 +1052,7 @@ class CliProjectPackagerTest {
baseUri = "package://example.com/mypackage" baseUri = "package://example.com/mypackage"
packageZipUrl = "https://foo.com" packageZipUrl = "https://foo.com"
} }
""" """
.trimIndent() .trimIndent()
) )
val packager = val packager =
@@ -1033,53 +1070,53 @@ class CliProjectPackagerTest {
assertThat(expectedMetadata) assertThat(expectedMetadata)
.hasContent( .hasContent(
""" """
{ {
"name": "mypackage", "name": "mypackage",
"packageUri": "package://example.com/mypackage@1.0.0", "packageUri": "package://example.com/mypackage@1.0.0",
"version": "1.0.0", "version": "1.0.0",
"packageZipUrl": "https://foo.com", "packageZipUrl": "https://foo.com",
"packageZipChecksums": { "packageZipChecksums": {
"sha256": "8739c76e681f900923b900c9df0ef75cf421d39cabb54650c4b9ad19b6a76d85" "sha256": "8739c76e681f900923b900c9df0ef75cf421d39cabb54650c4b9ad19b6a76d85"
},
"dependencies": {},
"authors": [],
"annotations": [
{
"type": "PObject",
"classInfo": {
"moduleName": "pkl.base",
"class": "Unlisted",
"moduleUri": "pkl:base"
},
"properties": {}
}, },
{ "dependencies": {},
"type": "PObject", "authors": [],
"classInfo": { "annotations": [
"moduleName": "pkl.base", {
"class": "Deprecated", "type": "PObject",
"moduleUri": "pkl:base" "classInfo": {
"moduleName": "pkl.base",
"class": "Unlisted",
"moduleUri": "pkl:base"
},
"properties": {}
}, },
"properties": { {
"since": "0.26.1", "type": "PObject",
"message": "do not use", "classInfo": {
"replaceWith": null "moduleName": "pkl.base",
} "class": "Deprecated",
}, "moduleUri": "pkl:base"
{ },
"type": "PObject", "properties": {
"classInfo": { "since": "0.26.1",
"moduleName": "pkl.base", "message": "do not use",
"class": "ModuleInfo", "replaceWith": null
"moduleUri": "pkl:base" }
}, },
"properties": { {
"minPklVersion": "0.26.0" "type": "PObject",
"classInfo": {
"moduleName": "pkl.base",
"class": "ModuleInfo",
"moduleUri": "pkl:base"
},
"properties": {
"minPklVersion": "0.26.0"
}
} }
} ]
] }
} """
"""
.trimIndent() .trimIndent()
) )
} }
@@ -74,13 +74,13 @@ class CliProjectResolverTest {
tempDir.writeFile( tempDir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
dependencies { dependencies {
["birds"] { ["birds"] {
uri = "package://localhost:0/birds@0.5.0" uri = "package://localhost:0/birds@0.5.0"
}
} }
}
""" """
.trimIndent(), .trimIndent(),
) )
@@ -129,13 +129,13 @@ class CliProjectResolverTest {
tempDir.writeFile( tempDir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
dependencies { dependencies {
["birds"] { ["birds"] {
uri = "package://localhost:0/birds@0.5.0" uri = "package://localhost:0/birds@0.5.0"
}
} }
}
""" """
.trimIndent(), .trimIndent(),
) )
@@ -185,35 +185,35 @@ class CliProjectResolverTest {
projectDir.writeFile( projectDir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
dependencies { dependencies {
["birds"] { ["birds"] {
uri = "package://localhost:0/birds@0.5.0" uri = "package://localhost:0/birds@0.5.0"
}
["project2"] = import("../project2/PklProject")
} }
["project2"] = import("../project2/PklProject")
}
""" """
.trimIndent(), .trimIndent(),
) )
projectDir.writeFile( projectDir.writeFile(
"../project2/PklProject", "../project2/PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "project2" name = "project2"
baseUri = "package://localhost:0/package2" baseUri = "package://localhost:0/package2"
version = "5.0.0" version = "5.0.0"
packageZipUrl = "https://foo.com/package2.zip" packageZipUrl = "https://foo.com/package2.zip"
} }
dependencies { dependencies {
["fruit"] { ["fruit"] {
uri = "package://localhost:0/fruit@1.0.5" uri = "package://localhost:0/fruit@1.0.5"
}
["project3"] = import("../project3/PklProject")
} }
["project3"] = import("../project3/PklProject")
}
""" """
.trimIndent(), .trimIndent(),
) )
@@ -221,20 +221,20 @@ class CliProjectResolverTest {
projectDir.writeFile( projectDir.writeFile(
"../project3/PklProject", "../project3/PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "project3" name = "project3"
baseUri = "package://localhost:0/package3" baseUri = "package://localhost:0/package3"
version = "5.0.0" version = "5.0.0"
packageZipUrl = "https://foo.com/package3.zip" packageZipUrl = "https://foo.com/package3.zip"
} }
dependencies { dependencies {
["fruit"] { ["fruit"] {
uri = "package://localhost:0/fruit@1.1.0" uri = "package://localhost:0/fruit@1.1.0"
}
} }
}
""" """
.trimIndent(), .trimIndent(),
) )
@@ -293,28 +293,28 @@ class CliProjectResolverTest {
projectDir.writeFile( projectDir.writeFile(
"PklProject", "PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
dependencies { dependencies {
["birds"] { ["birds"] {
uri = "package://localhost:0/birds@0.5.0" uri = "package://localhost:0/birds@0.5.0"
}
["fruit"] = import("../fruit/PklProject")
} }
["fruit"] = import("../fruit/PklProject")
}
""" """
.trimIndent(), .trimIndent(),
) )
projectDir.writeFile( projectDir.writeFile(
"../fruit/PklProject", "../fruit/PklProject",
""" """
amends "pkl:Project" amends "pkl:Project"
package { package {
name = "fruit" name = "fruit"
baseUri = "package://localhost:0/fruit" baseUri = "package://localhost:0/fruit"
version = "1.0.0" version = "1.0.0"
packageZipUrl = "https://foo.com/fruit.zip" packageZipUrl = "https://foo.com/fruit.zip"
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -375,7 +375,7 @@ class CliProjectResolverTest {
uri = "package://localhost:0/birds@0.5.0" uri = "package://localhost:0/birds@0.5.0"
} }
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -389,7 +389,7 @@ class CliProjectResolverTest {
uri = "package://localhost:0/fruit@1.1.0" uri = "package://localhost:0/fruit@1.1.0"
} }
} }
""" """
.trimIndent(), .trimIndent(),
) )
@@ -469,14 +469,14 @@ class CliProjectResolverTest {
.resolve("PklProject") .resolve("PklProject")
.writeString( .writeString(
""" """
amends "pkl:Project" amends "pkl:Project"
dependencies { dependencies {
["birds"] { ["birds"] {
uri = "package://localhost:0/birds@0.5.0" uri = "package://localhost:0/birds@0.5.0"
}
} }
} """
"""
.trimIndent() .trimIndent()
) )
// coerce an IOException by making this a directory // coerce an IOException by making this a directory
@@ -47,7 +47,7 @@ class CliTestRunnerTest {
3 == 3 3 == 3
} }
} }
""" """
.trimIndent() .trimIndent()
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val out = StringWriter() val out = StringWriter()
@@ -65,13 +65,13 @@ class CliTestRunnerTest {
assertThat(out.toString().stripFileAndLines(tempDir)) assertThat(out.toString().stripFileAndLines(tempDir))
.isEqualTo( .isEqualTo(
""" """
module test module test
facts facts
succeed succeed
100.0% tests pass [1 passed], 100.0% asserts pass [2 passed] 100.0% tests pass [1 passed], 100.0% asserts pass [2 passed]
""" """
.trimIndent() .trimIndent()
) )
assertThat(err.toString()).isEqualTo("") assertThat(err.toString()).isEqualTo("")
@@ -89,7 +89,7 @@ class CliTestRunnerTest {
1 == 5 1 == 5
} }
} }
""" """
.trimIndent() .trimIndent()
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val out = StringWriter() val out = StringWriter()
@@ -136,7 +136,7 @@ class CliTestRunnerTest {
throw("uh oh") throw("uh oh")
} }
} }
""" """
.trimIndent() .trimIndent()
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val out = StringWriter() val out = StringWriter()
@@ -154,19 +154,19 @@ class CliTestRunnerTest {
assertThat(out.toString().stripFileAndLines(tempDir)) assertThat(out.toString().stripFileAndLines(tempDir))
.isEqualToNormalizingNewlines( .isEqualToNormalizingNewlines(
""" """
module test module test
facts facts
fail fail
Pkl Error Pkl Error
uh oh uh oh
5 | throw("uh oh") 5 | throw("uh oh")
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
at test#facts["fail"][#1] (/tempDir/test.pkl, line xx) at test#facts["fail"][#1] (/tempDir/test.pkl, line xx)
0.0% tests pass [1/1 failed], 0.0% asserts pass [1/1 failed] 0.0% tests pass [1/1 failed], 0.0% asserts pass [1/1 failed]
""" """
.trimIndent() .trimIndent()
) )
assertThat(err.toString()).isEqualTo("") assertThat(err.toString()).isEqualTo("")
@@ -183,7 +183,7 @@ class CliTestRunnerTest {
throw("uh oh") throw("uh oh")
} }
} }
""" """
.trimIndent() .trimIndent()
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val out = StringWriter() val out = StringWriter()
@@ -201,19 +201,19 @@ class CliTestRunnerTest {
assertThat(out.toString().stripFileAndLines(tempDir)) assertThat(out.toString().stripFileAndLines(tempDir))
.isEqualTo( .isEqualTo(
""" """
module test module test
examples examples
fail fail
Pkl Error Pkl Error
uh oh uh oh
5 | throw("uh oh") 5 | throw("uh oh")
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
at test#examples["fail"][#1] (/tempDir/test.pkl, line xx) at test#examples["fail"][#1] (/tempDir/test.pkl, line xx)
0.0% tests pass [1/1 failed], 0.0% asserts pass [1/1 failed] 0.0% tests pass [1/1 failed], 0.0% asserts pass [1/1 failed]
""" """
.trimIndent() .trimIndent()
) )
assertThat(err.toString()).isEqualTo("") assertThat(err.toString()).isEqualTo("")
@@ -232,19 +232,19 @@ class CliTestRunnerTest {
throw("uh oh") throw("uh oh")
} }
} }
""" """
.trimIndent() .trimIndent()
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
tempDir tempDir
.resolve("test.pkl-expected.pcf") .resolve("test.pkl-expected.pcf")
.writeString( .writeString(
""" """
examples { examples {
["fail"] { ["fail"] {
"never compared to" "never compared to"
}
} }
} """
"""
.trimIndent() .trimIndent()
) )
val out = StringWriter() val out = StringWriter()
@@ -262,19 +262,19 @@ class CliTestRunnerTest {
assertThat(out.toString().stripFileAndLines(tempDir)) assertThat(out.toString().stripFileAndLines(tempDir))
.isEqualToNormalizingNewlines( .isEqualToNormalizingNewlines(
""" """
module test module test
examples examples
fail fail
Pkl Error Pkl Error
uh oh uh oh
5 | throw("uh oh") 5 | throw("uh oh")
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
at test#examples["fail"][#1] (/tempDir/test.pkl, line xx) at test#examples["fail"][#1] (/tempDir/test.pkl, line xx)
0.0% tests pass [1/1 failed], 0.0% asserts pass [1/1 failed] 0.0% tests pass [1/1 failed], 0.0% asserts pass [1/1 failed]
""" """
.trimIndent() .trimIndent()
) )
assertThat(err.toString()).isEqualTo("") assertThat(err.toString()).isEqualTo("")
@@ -296,7 +296,7 @@ class CliTestRunnerTest {
5 == 9 5 == 9
} }
} }
""" """
.trimIndent() .trimIndent()
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val noopWriter = noopWriter() val noopWriter = noopWriter()
@@ -314,19 +314,19 @@ class CliTestRunnerTest {
assertThat(junitReport) assertThat(junitReport)
.isEqualTo( .isEqualTo(
""" """
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuite name="test" tests="2" failures="1"> <testsuite name="test" tests="2" failures="1">
<testcase classname="test.facts" name="foo"></testcase> <testcase classname="test.facts" name="foo"></testcase>
<testcase classname="test.facts" name="bar"> <testcase classname="test.facts" name="bar">
<failure message="Fact Failure">5 == 9 (/tempDir/test.pkl, line xx) <failure message="Fact Failure">5 == 9 (/tempDir/test.pkl, line xx)
false</failure> false</failure>
</testcase> </testcase>
<system-err><![CDATA[9 = 9 <system-err><![CDATA[9 = 9
]]></system-err> ]]></system-err>
</testsuite> </testsuite>
""" """
.trimIndent() .trimIndent()
) )
} }
@@ -346,7 +346,7 @@ class CliTestRunnerTest {
throw("uh oh") throw("uh oh")
} }
} }
""" """
.trimIndent() .trimIndent()
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val noopWriter = noopWriter() val noopWriter = noopWriter()
@@ -364,23 +364,23 @@ class CliTestRunnerTest {
assertThat(junitReport) assertThat(junitReport)
.isEqualTo( .isEqualTo(
""" """
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuite name="test" tests="2" failures="1"> <testsuite name="test" tests="2" failures="1">
<testcase classname="test.facts" name="foo"></testcase> <testcase classname="test.facts" name="foo"></testcase>
<testcase classname="test.facts" name="fail"> <testcase classname="test.facts" name="fail">
<error message="uh oh"> Pkl Error <error message="uh oh"> Pkl Error
uh oh uh oh
9 | throw(&quot;uh oh&quot;) 9 | throw(&quot;uh oh&quot;)
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
at test#facts[&quot;fail&quot;][#1] (/tempDir/test.pkl, line xx) at test#facts[&quot;fail&quot;][#1] (/tempDir/test.pkl, line xx)
</error> </error>
</testcase> </testcase>
<system-err><![CDATA[9 = 9 <system-err><![CDATA[9 = 9
]]></system-err> ]]></system-err>
</testsuite> </testsuite>
""" """
.trimIndent() .trimIndent()
) )
} }
@@ -398,7 +398,7 @@ class CliTestRunnerTest {
1 == 1 1 == 1
} }
} }
""" """
.trimIndent() .trimIndent()
val bar = val bar =
@@ -412,7 +412,7 @@ class CliTestRunnerTest {
1 == 1 1 == 1
} }
} }
""" """
.trimIndent() .trimIndent()
val input = tempDir.resolve("test.pkl").writeString(foo).toString() val input = tempDir.resolve("test.pkl").writeString(foo).toString()
val input2 = tempDir.resolve("test.pkl").writeString(bar).toString() val input2 = tempDir.resolve("test.pkl").writeString(bar).toString()
@@ -438,7 +438,7 @@ class CliTestRunnerTest {
true true
} }
} }
""" """
.trimIndent() .trimIndent()
val code2 = val code2 =
@@ -450,7 +450,7 @@ class CliTestRunnerTest {
true true
} }
} }
""" """
.trimIndent() .trimIndent()
val input1 = tempDir.resolve("test1.pkl").writeString(code1).toString() val input1 = tempDir.resolve("test1.pkl").writeString(code1).toString()
val input2 = tempDir.resolve("test2.pkl").writeString(code2).toString() val input2 = tempDir.resolve("test2.pkl").writeString(code2).toString()
@@ -482,7 +482,7 @@ class CliTestRunnerTest {
5 == 9 5 == 9
} }
} }
""" """
.trimIndent() .trimIndent()
val code2 = val code2 =
@@ -500,7 +500,7 @@ class CliTestRunnerTest {
true true
} }
} }
""" """
.trimIndent() .trimIndent()
val input1 = tempDir.resolve("test1.pkl").writeString(code1).toString() val input1 = tempDir.resolve("test1.pkl").writeString(code1).toString()
val input2 = tempDir.resolve("test2.pkl").writeString(code2).toString() val input2 = tempDir.resolve("test2.pkl").writeString(code2).toString()
@@ -547,7 +547,7 @@ class CliTestRunnerTest {
</testsuite> </testsuite>
</testsuites> </testsuites>
""" """
.trimIndent() .trimIndent()
) )
} }
@@ -563,7 +563,7 @@ class CliTestRunnerTest {
true true
} }
} }
""" """
.trimIndent() .trimIndent()
val code2 = val code2 =
@@ -575,7 +575,7 @@ class CliTestRunnerTest {
true true
} }
} }
""" """
.trimIndent() .trimIndent()
val input1 = tempDir.resolve("test1.pkl").writeString(code1).toString() val input1 = tempDir.resolve("test1.pkl").writeString(code1).toString()
val input2 = tempDir.resolve("test2.pkl").writeString(code2).toString() val input2 = tempDir.resolve("test2.pkl").writeString(code2).toString()
@@ -620,19 +620,19 @@ class CliTestRunnerTest {
2 2
} }
} }
""" """
.trimIndent() .trimIndent()
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
tempDir tempDir
.resolve("test.pkl-expected.pcf") .resolve("test.pkl-expected.pcf")
.writeString( .writeString(
""" """
examples { examples {
["nums"] { ["nums"] {
1 1
}
} }
} """
"""
.trimIndent() .trimIndent()
) )
val out = StringWriter() val out = StringWriter()
@@ -676,7 +676,7 @@ class CliTestRunnerTest {
2 2
} }
} }
""" """
.trimIndent() .trimIndent()
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val out = StringWriter() val out = StringWriter()
@@ -694,13 +694,13 @@ class CliTestRunnerTest {
assertThat(out.toString()) assertThat(out.toString())
.isEqualTo( .isEqualTo(
""" """
module test module test
examples examples
nums nums
1 examples written 1 examples written
""" """
.trimIndent() .trimIndent()
) )
} }
@@ -738,13 +738,13 @@ class CliTestRunnerTest {
assertThat(out.toString().stripFileAndLines(tempDir)) assertThat(out.toString().stripFileAndLines(tempDir))
.isEqualTo( .isEqualTo(
""" """
module test module test
facts facts
localeTest localeTest
100.0% tests pass [1 passed], 100.0% asserts pass [1 passed] 100.0% tests pass [1 passed], 100.0% asserts pass [1 passed]
""" """
.trimIndent() .trimIndent()
) )
assertThat(err.toString()).isEqualTo("") assertThat(err.toString()).isEqualTo("")
@@ -31,7 +31,7 @@ class CliJavaCodeGenerator(private val options: CliJavaCodeGeneratorOptions) :
val builder = evaluatorBuilder() val builder = evaluatorBuilder()
try { try {
builder.build().use { evaluator -> builder.build().use { evaluator ->
for (moduleUri in resolvedSourceModules) { for (moduleUri in options.base.normalizedSourceModules) {
val schema = evaluator.evaluateSchema(ModuleSource.uri(moduleUri)) val schema = evaluator.evaluateSchema(ModuleSource.uri(moduleUri))
val codeGenerator = JavaCodeGenerator(schema, options.toJavaCodeGeneratorOptions()) val codeGenerator = JavaCodeGenerator(schema, options.toJavaCodeGeneratorOptions())
try { try {
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("unused") @file:Suppress("unused", "CanConvertToMultiDollarString")
package org.pkl.codegen.java package org.pkl.codegen.java
@@ -172,7 +172,7 @@ class JavaCodeGenerator(
val annotation = codegenOptions.nonNullAnnotation val annotation = codegenOptions.nonNullAnnotation
val className = val className =
if (annotation == null) { if (annotation == null) {
ClassName.get("org.pkl.config.java.mapper", "NonNull") ClassName.get("org.jspecify.annotations", "NonNull")
} else { } else {
toClassName(annotation) toClassName(annotation)
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -102,10 +102,10 @@ class PklJavaCodegenCommand : ModulesCommand(name = "pkl-codegen-java", helpLink
names = arrayOf("--non-null-annotation"), names = arrayOf("--non-null-annotation"),
help = help =
""" """
Fully qualified name of the annotation type to use for annotating non-null types. Fully qualified name of the annotation type to use for annotating non-null types.
The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)` The specified annotation type must be annotated with `@java.lang.annotation.Target(ElementType.TYPE_USE)`
or the generated code may not compile. or the generated code may not compile.
""" """
.trimIndent(), .trimIndent(),
) )
@@ -122,10 +122,10 @@ class PklJavaCodegenCommand : ModulesCommand(name = "pkl-codegen-java", helpLink
metavar = "old_name=new_name", metavar = "old_name=new_name",
help = help =
""" """
Replace a prefix in the names of the generated Java classes (repeatable). Replace a prefix in the names of the generated Java classes (repeatable).
By default, the names of generated classes are derived from the Pkl module names. By default, the names of generated classes are derived from the Pkl module names.
With this option, you can override or modify the default names, renaming entire With this option, you can override or modify the default names, renaming entire
classes or just their packages. classes or just their packages.
""" """
.trimIndent(), .trimIndent(),
) )
File diff suppressed because it is too large Load Diff
@@ -5,8 +5,8 @@ import java.lang.Override;
import java.lang.String; import java.lang.String;
import java.lang.StringBuilder; import java.lang.StringBuilder;
import java.util.Objects; import java.util.Objects;
import org.jspecify.annotations.NonNull;
import org.pkl.config.java.mapper.Named; import org.pkl.config.java.mapper.Named;
import org.pkl.config.java.mapper.NonNull;
import org.pkl.core.DataSize; import org.pkl.core.DataSize;
import org.pkl.core.Duration; import org.pkl.core.Duration;
@@ -5,8 +5,8 @@ import java.lang.Override;
import java.lang.String; import java.lang.String;
import java.lang.StringBuilder; import java.lang.StringBuilder;
import java.util.Objects; import java.util.Objects;
import org.jspecify.annotations.NonNull;
import org.pkl.config.java.mapper.Named; import org.pkl.config.java.mapper.Named;
import org.pkl.config.java.mapper.NonNull;
import org.pkl.core.Duration; import org.pkl.core.Duration;
public final class Mod { public final class Mod {
@@ -5,8 +5,8 @@ import java.lang.Override;
import java.lang.String; import java.lang.String;
import java.lang.StringBuilder; import java.lang.StringBuilder;
import java.util.Objects; import java.util.Objects;
import org.jspecify.annotations.NonNull;
import org.pkl.config.java.mapper.Named; import org.pkl.config.java.mapper.Named;
import org.pkl.config.java.mapper.NonNull;
/** /**
* module comment. * module comment.
@@ -11,8 +11,8 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.jspecify.annotations.NonNull;
import org.pkl.config.java.mapper.Named; import org.pkl.config.java.mapper.Named;
import org.pkl.config.java.mapper.NonNull;
import org.pkl.core.DataSize; import org.pkl.core.DataSize;
import org.pkl.core.DataSizeUnit; import org.pkl.core.DataSizeUnit;
import org.pkl.core.Duration; import org.pkl.core.Duration;
@@ -32,7 +32,7 @@ class CliKotlinCodeGenerator(private val options: CliKotlinCodeGeneratorOptions)
try { try {
builder.build().use { evaluator -> builder.build().use { evaluator ->
for (moduleUri in resolvedSourceModules) { for (moduleUri in options.base.normalizedSourceModules) {
val schema = evaluator.evaluateSchema(ModuleSource.uri(moduleUri)) val schema = evaluator.evaluateSchema(ModuleSource.uri(moduleUri))
val codeGenerator = KotlinCodeGenerator(schema, options.toKotlinCodeGeneratorOptions()) val codeGenerator = KotlinCodeGenerator(schema, options.toKotlinCodeGeneratorOptions())
try { try {
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -91,10 +91,10 @@ class PklKotlinCodegenCommand : ModulesCommand(name = "pkl-codegen-kotlin", help
metavar = "old_name=new_name", metavar = "old_name=new_name",
help = help =
""" """
Replace a prefix in the names of the generated Kotlin classes (repeatable). Replace a prefix in the names of the generated Kotlin classes (repeatable).
By default, the names of generated classes are derived from the Pkl module names. By default, the names of generated classes are derived from the Pkl module names.
With this option, you can override or modify the default names, renaming entire With this option, you can override or modify the default names, renaming entire
classes or just their packages. classes or just their packages.
""" """
.trimIndent(), .trimIndent(),
) )
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -77,7 +77,7 @@ class CliKotlinCodeGeneratorTest {
open class Mod1( open class Mod1(
open val pigeon: Person open val pigeon: Person
) { ) {
""" """
.trimIndent(), .trimIndent(),
module1KotlinFile.readString(), module1KotlinFile.readString(),
) )
@@ -88,7 +88,7 @@ class CliKotlinCodeGeneratorTest {
pigeon: Mod1.Person, pigeon: Mod1.Person,
val parrot: Mod1.Person val parrot: Mod1.Person
) : Mod1(pigeon) { ) : Mod1(pigeon) {
""" """
.trimIndent(), .trimIndent(),
module2KotlinFile.readString(), module2KotlinFile.readString(),
) )
File diff suppressed because it is too large Load Diff
@@ -144,6 +144,9 @@ data class CliBaseOptions(
/** URL prefixes to rewrite. */ /** URL prefixes to rewrite. */
val httpRewrites: Map<URI, URI>? = null, val httpRewrites: Map<URI, URI>? = null,
/** HTTP headers to add to the request. */
val httpHeaders: Map<String, Map<String, List<String>>>? = null,
/** External module reader process specs */ /** External module reader process specs */
val externalModuleReaders: Map<String, ExternalReader> = mapOf(), val externalModuleReaders: Map<String, ExternalReader> = mapOf(),
@@ -186,16 +189,15 @@ data class CliBaseOptions(
sourceModules sourceModules
.map { uri -> .map { uri ->
if (uri.isAbsolute) uri if (uri.isAbsolute) uri
else if (uri.path.startsWith("@") && !noProject && normalizedProjectFile != null) uri else if (uri.path.startsWith("@")) uri
else IoUtils.resolve(normalizedWorkingDir.toUri(), uri) else IoUtils.resolve(normalizedWorkingDir.toUri(), uri)
} }
// sort modules to make cli output independent of source module order // sort modules to make cli output independent of source module order
.sorted() .sorted()
val normalizedSettingsModule: URI? = val normalizedSettingsModule: URI? = settings?.let { uri ->
settings?.let { uri -> if (uri.isAbsolute) uri else IoUtils.resolve(normalizedWorkingDir.toUri(), uri)
if (uri.isAbsolute) uri else IoUtils.resolve(normalizedWorkingDir.toUri(), uri) }
}
/** [modulePath] after normalization. */ /** [modulePath] after normalization. */
val normalizedModulePath: List<Path>? = modulePath?.map(normalizedWorkingDir::resolve) val normalizedModulePath: List<Path>? = modulePath?.map(normalizedWorkingDir::resolve)
@@ -86,36 +86,6 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
} }
} }
protected fun resolveModuleUri(uri: URI): URI =
if (uri.isAbsolute) uri
else { // must be @dep/mod.pkl notation!!
if (!uri.path.startsWith('@'))
throw CliBugException(
RuntimeException("tried to resolve project URI `$uri` with no @ prefix")
)
if (project == null)
throw CliBugException(
RuntimeException("tried to resolve project URI `$uri` with no project present")
)
val dep = uri.path.substringBefore('/').drop(1)
val path = uri.path.dropWhile { it != '/' }
if (path.isEmpty()) throw CliException("Invalid project dependency URI `$uri`.")
val remoteDep =
project!!.dependencies.remoteDependencies()[dep]
?: if (project!!.dependencies.localDependencies().containsKey(dep))
throw CliException(
"Only remote project dependencies may be referenced using @-notation. Dependency `@$dep` is a local dependency."
)
else throw CliException("Project does not contain dependency `@$dep`.")
remoteDep.packageUri.toPackageAssetUri(path).uri
}
protected val resolvedSourceModules: List<URI> by lazy {
if (project == null) cliOptions.normalizedSourceModules
else cliOptions.normalizedSourceModules.map(::resolveModuleUri)
}
protected fun loadProject(projectFile: Path): Project { protected fun loadProject(projectFile: Path): Project {
val securityManager = val securityManager =
SecurityManagers.standard( SecurityManagers.standard(
@@ -215,7 +185,11 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
} }
protected val httpRewrites: Map<URI, URI>? by lazy { protected val httpRewrites: Map<URI, URI>? by lazy {
cliOptions.httpRewrites ?: evaluatorSettings?.http?.rewrites ?: settings.http?.rewrites() cliOptions.httpRewrites ?: evaluatorSettings?.http?.rewrites ?: settings.http?.rewrites
}
private val httpHeaders: Map<String, Map<String, List<String>>>? by lazy {
cliOptions.httpHeaders ?: evaluatorSettings?.http?.headers ?: settings.http?.headers
} }
protected val externalModuleReaders: Map<String, PklEvaluatorSettings.ExternalReader> by lazy { protected val externalModuleReaders: Map<String, PklEvaluatorSettings.ExternalReader> by lazy {
@@ -277,6 +251,7 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
setProxy(proxyAddress, noProxy ?: listOf()) setProxy(proxyAddress, noProxy ?: listOf())
} }
httpRewrites?.let(::setRewrites) httpRewrites?.let(::setRewrites)
httpHeaders?.let(::setHeaders)
// Lazy building significantly reduces execution time of commands that do minimal work. // Lazy building significantly reduces execution time of commands that do minimal work.
// However, it means that HTTP client initialization errors won't surface until an HTTP // However, it means that HTTP client initialization errors won't surface until an HTTP
// request is made. // request is made.
@@ -307,6 +282,7 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
add(ResourceReaders.modulePath(modulePathResolver)) add(ResourceReaders.modulePath(modulePathResolver))
add(ResourceReaders.pkg()) add(ResourceReaders.pkg())
add(ResourceReaders.projectpackage()) add(ResourceReaders.projectpackage())
addAll(ResourceReaders.fromServiceProviders())
add(ResourceReaders.file()) add(ResourceReaders.file())
add(ResourceReaders.http()) add(ResourceReaders.http())
add(ResourceReaders.https()) add(ResourceReaders.https())
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -22,4 +22,5 @@ class CliTestOptions(
val overwrite: Boolean = false, val overwrite: Boolean = false,
val junitAggregateReports: Boolean = false, val junitAggregateReports: Boolean = false,
val junitAggregateSuiteName: String = "pkl-tests", val junitAggregateSuiteName: String = "pkl-tests",
val reporter: TestReporter = TestReporter.default,
) )
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,15 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.pkl.core.util; package org.pkl.commons.cli
import java.lang.annotation.*; enum class TestReporter {
import javax.annotation.meta.TypeQualifierNickname; SPEC,
import javax.annotation.meta.When; MINIMAL;
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) companion object {
@Retention(RetentionPolicy.RUNTIME) @JvmStatic val default: TestReporter = SPEC
@Documented }
@javax.annotation.Nonnull(when = When.ALWAYS) }
@TypeQualifierNickname
public @interface Nonnull {}
@@ -35,6 +35,7 @@ import org.pkl.core.evaluatorSettings.Color
import org.pkl.core.evaluatorSettings.PklEvaluatorSettings.ExternalReader import org.pkl.core.evaluatorSettings.PklEvaluatorSettings.ExternalReader
import org.pkl.core.evaluatorSettings.TraceMode import org.pkl.core.evaluatorSettings.TraceMode
import org.pkl.core.runtime.VmUtils import org.pkl.core.runtime.VmUtils
import org.pkl.core.util.GlobResolver
import org.pkl.core.util.IoUtils import org.pkl.core.util.IoUtils
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
@@ -93,6 +94,8 @@ class BaseOptions : OptionGroup() {
Pair(it.first, ExternalReader(cmd.first(), cmd.drop(1))) Pair(it.first, ExternalReader(cmd.first(), cmd.drop(1)))
} }
} }
private val headerRegex = Regex("""^(.+?):[ \t]*(.*)$""")
} }
private val defaults = CliBaseOptions() private val defaults = CliBaseOptions()
@@ -285,6 +288,37 @@ class BaseOptions : OptionGroup() {
.multiple() .multiple()
.toMap() .toMap()
val httpHeaders: Map<String, Map<String, List<String>>> by
option(
names = arrayOf("--http-header"),
metavar = "<url-pattern>=<header name>:<header value>",
help = "HTTP header to add to the request.",
)
.splitPair()
.transformAll { pairs ->
buildMap<String, MutableMap<String, MutableList<String>>> {
for ((pattern, headerNameAndValue) in pairs) {
try {
GlobResolver.toRegexPattern(pattern)
} catch (e: GlobResolver.InvalidGlobPatternException) {
fail(e.message!!)
}
val (headerName, headerValue) =
headerRegex.find(headerNameAndValue)?.destructured
?: fail("Header '$headerNameAndValue' is not in 'name:value' format.")
try {
IoUtils.validateHeaderName(headerName)
IoUtils.validateHeaderValue(headerValue)
} catch (e: IllegalArgumentException) {
fail(e.message!!)
}
getOrPut(pattern) { mutableMapOf() }
.getOrPut(headerName) { mutableListOf() }
.add(headerValue)
}
}
}
val externalModuleReaders: Map<String, ExternalReader> by val externalModuleReaders: Map<String, ExternalReader> by
option( option(
names = arrayOf("--external-module-reader"), names = arrayOf("--external-module-reader"),
@@ -351,6 +385,7 @@ class BaseOptions : OptionGroup() {
httpProxy = proxy, httpProxy = proxy,
httpNoProxy = noProxy, httpNoProxy = noProxy,
httpRewrites = httpRewrites.ifEmpty { null }, httpRewrites = httpRewrites.ifEmpty { null },
httpHeaders = httpHeaders.ifEmpty { null },
externalModuleReaders = externalModuleReaders, externalModuleReaders = externalModuleReaders,
externalResourceReaders = externalResourceReaders, externalResourceReaders = externalResourceReaders,
traceMode = traceMode, traceMode = traceMode,
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,9 +19,11 @@ import com.github.ajalt.clikt.parameters.groups.OptionGroup
import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.types.enum
import com.github.ajalt.clikt.parameters.types.path import com.github.ajalt.clikt.parameters.types.path
import java.nio.file.Path import java.nio.file.Path
import org.pkl.commons.cli.CliTestOptions import org.pkl.commons.cli.CliTestOptions
import org.pkl.commons.cli.TestReporter
class TestOptions : OptionGroup() { class TestOptions : OptionGroup() {
private val junitReportDir: Path? by private val junitReportDir: Path? by
@@ -51,7 +53,19 @@ class TestOptions : OptionGroup() {
private val overwrite: Boolean by private val overwrite: Boolean by
option(names = arrayOf("--overwrite"), help = "Force generation of expected examples.").flag() option(names = arrayOf("--overwrite"), help = "Force generation of expected examples.").flag()
private val reporter: TestReporter by
option(names = arrayOf("--test-reporter"), help = "Which test reporter to use for CLI output.")
.enum<TestReporter> { it.name.lowercase() }
.single()
.default(TestReporter.default)
val cliTestOptions: CliTestOptions by lazy { val cliTestOptions: CliTestOptions by lazy {
CliTestOptions(junitReportDir, overwrite, junitAggregateReports, junitAggregateSuiteName) CliTestOptions(
junitReportDir,
overwrite,
junitAggregateReports,
junitAggregateSuiteName,
reporter,
)
} }
} }
@@ -0,0 +1,5 @@
amends "pkl:Project"
dependencies {
["fruit"] { uri = "package://localhost:0/fruit@1.1.0" }
}
@@ -0,0 +1,12 @@
{
"schemaVersion": 1,
"resolvedDependencies": {
"package://localhost:0/fruit@1": {
"type": "remote",
"uri": "projectpackage://localhost:0/fruit@1.1.0",
"checksums": {
"sha256": "$skipChecksumVerification"
}
}
}
}
@@ -17,13 +17,10 @@ package org.pkl.commons.cli
import com.github.ajalt.clikt.core.parse import com.github.ajalt.clikt.core.parse
import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.groups.provideDelegate
import java.net.URI
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.ExperimentalPathApi import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.writeText
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.condition.DisabledOnJre import org.junit.jupiter.api.condition.DisabledOnJre
import org.junit.jupiter.api.condition.JRE import org.junit.jupiter.api.condition.JRE
import org.junit.jupiter.api.io.TempDir import org.junit.jupiter.api.io.TempDir
@@ -49,7 +46,6 @@ class CliCommandTest {
class CliTest(options: CliBaseOptions) : CliCommand(options) { class CliTest(options: CliBaseOptions) : CliCommand(options) {
override fun doRun() = Unit override fun doRun() = Unit
val myResolvedSourceModules = resolvedSourceModules
val myAllowedModules = allowedModules val myAllowedModules = allowedModules
val myAllowedResources = allowedResources val myAllowedResources = allowedResources
val myRootDir = rootDir val myRootDir = rootDir
@@ -98,114 +94,6 @@ class CliCommandTest {
) )
} }
@Test
fun `@-notation package URIs - treated as relative paths when no project present`(
@TempDir tempDir: Path
) {
cmd.parse(arrayOf("--working-dir=$tempDir"))
val opts = cmd.baseOptions.baseOptions(listOf(URI("@foo/bar.pkl")), testMode = true)
val cliTest = CliTest(opts)
assertThat(cliTest.myResolvedSourceModules)
.isEqualTo(listOf(tempDir.toUri().resolve("@foo/bar.pkl")))
}
@Test
fun `@-notation package URIs - empty paths are rejected`(@TempDir tempDir: Path) {
tempDir
.resolve("PklProject")
.writeText(
"""
amends "pkl:Project"
"""
.trimIndent()
)
cmd.parse(arrayOf("--working-dir=$tempDir"))
val opts = cmd.baseOptions.baseOptions(listOf(URI("@no.slash")), testMode = true)
val exc = assertThrows<CliException> { CliTest(opts) }
assertThat(exc.message).isEqualTo("Invalid project dependency URI `@no.slash`.")
}
@Test
fun `@-notation package URIs - missing dependencies are rejected`(@TempDir tempDir: Path) {
tempDir
.resolve("PklProject")
.writeText(
"""
amends "pkl:Project"
"""
.trimIndent()
)
cmd.parse(arrayOf("--working-dir=$tempDir"))
val opts = cmd.baseOptions.baseOptions(listOf(URI("@foo/bar.pkl")), testMode = true)
val exc = assertThrows<CliException> { CliTest(opts) }
assertThat(exc.message).isEqualTo("Project does not contain dependency `@foo`.")
}
@Test
fun `@-notation package URIs - local dependencies are rejected`(
@TempDir tempDir: Path,
@TempDir depDir: Path,
) {
depDir
.resolve("PklProject")
.writeText(
"""
amends "pkl:Project"
package {
name = "foo"
baseUri = "package://example.com/foo"
version = "0.0.1"
packageZipUrl = "https://example.com/foo@\(version).zip"
}
"""
.trimIndent()
)
tempDir
.resolve("PklProject")
.writeText(
"""
amends "pkl:Project"
dependencies {
["foo"] = import("${depDir.toUri().resolve("PklProject")}")
}
"""
.trimIndent()
)
cmd.parse(arrayOf("--working-dir=$tempDir"))
val opts = cmd.baseOptions.baseOptions(listOf(URI("@foo/bar.pkl")), testMode = true)
val exc = assertThrows<CliException> { CliTest(opts) }
assertThat(exc.message)
.isEqualTo(
"Only remote project dependencies may be referenced using @-notation. Dependency `@foo` is a local dependency."
)
}
@Test
fun `@-notation package URIs - remote dependencies are resolved`(@TempDir tempDir: Path) {
tempDir
.resolve("PklProject")
.writeText(
"""
amends "pkl:Project"
dependencies {
["foo"] {
uri = "package://example.com/foo@1.2.3"
}
}
"""
.trimIndent()
)
cmd.parse(arrayOf("--working-dir=$tempDir"))
val opts = cmd.baseOptions.baseOptions(listOf(URI("@foo/bar.pkl")), testMode = true)
val cliTest = CliTest(opts)
assertThat(cliTest.myResolvedSourceModules)
.isEqualTo(listOf(tempDir.toUri().resolve("package://example.com/foo@1.2.3#/bar.pkl")))
}
val projectWithAllEvaluatorSettings = val projectWithAllEvaluatorSettings =
""" """
amends "pkl:Project" amends "pkl:Project"
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package org.pkl.config.java;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.pkl.config.java.mapper.ValueMapper; import org.pkl.config.java.mapper.ValueMapper;
import org.pkl.core.Composite; import org.pkl.core.Composite;
@@ -49,17 +50,37 @@ abstract class AbstractConfig implements Config {
@Override @Override
public <T> T as(Class<T> type) { public <T> T as(Class<T> type) {
return as((Type) type); return trustNonNull(asNullable(type));
}
@Override
public <T> T as(JavaType<T> type) {
return trustNonNull(asNullable(type));
} }
@Override @Override
public <T> T as(Type type) { public <T> T as(Type type) {
return trustNonNull(asNullable(type));
}
@Override
public <T> @Nullable T asNullable(Class<T> type) {
return mapper.map(getRawValue(), type); return mapper.map(getRawValue(), type);
} }
@Override @Override
public <T> T as(JavaType<T> javaType) { public <T> @Nullable T asNullable(JavaType<T> type) {
return as(javaType.getType()); return mapper.map(getRawValue(), type.getType());
}
@Override
public <T extends @Nullable Object> T asNullable(Type type) {
return mapper.map(getRawValue(), type);
}
@SuppressWarnings({"unchecked", "DataFlowIssue", "NullAway"})
private static <T> T trustNonNull(@Nullable Object value) {
return (T) value;
} }
protected abstract Object getRawChildValue(String property); protected abstract Object getRawChildValue(String property);
@@ -17,60 +17,130 @@ package org.pkl.config.java;
import java.io.InputStream; import java.io.InputStream;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.pkl.config.java.mapper.ConversionException; import org.pkl.config.java.mapper.ConversionException;
import org.pkl.config.java.mapper.ValueMapper; import org.pkl.config.java.mapper.ValueMapper;
import org.pkl.core.Evaluator;
/** /**
* A root, intermediate, or leaf node in a configuration tree. Child nodes can be obtained by name * A root, intermediate, or leaf node in a configuration tree.
* using {@link #get(String)}. To consume the node's composite or scalar value, convert the value to *
* the desired Java type, using one of the provided {@link #as} methods. * <p>To navigate to a child node, use {@link #get(String)} with the child's unqualified name.
*
* <p>To retrieve this node's value, use:
*
* <ul>
* <li>{@link #as(Class)} for non-null types.
* <li>{@link #asNullable(Class)} for nullable types.
* <li>{@link #as(JavaType)} for parameterized types, such as {@code List<@Nullable String>}.
* </ul>
*
* <p>Whether a method can return null depends on the method and target type used. For example,
* {@code asNullable(String.class)} can return {@code null}, while {@code
* as(JavaType.listOfNullable(String.class))} can return a {@code List<String>} with nullable
* elements. These nullness rules are for static analysis tools such as IntelliJ IDEA and NullAway
* and are not enforced at runtime.
*/ */
@SuppressWarnings({"DeprecatedIsStillUsed"}) @SuppressWarnings({"DeprecatedIsStillUsed"})
public interface Config { public interface Config {
/** /**
* The dot-separated name of this node. For example, the node reached using {@code * Returns the qualified name of this node, or the empty string if this is the root node.
* rootNode.get("foo").get("bar")} has qualified name {@code foo.bar}. Returns the empty String *
* for the root node itself. * <p>The qualified name is formed by joining child names using {@code '.'}. For example, {@code
* rootNode.get("foo").get("bar").getQualifiedName()} returns {@code "foo.bar"}.
*/ */
String getQualifiedName(); String getQualifiedName();
/** /**
* The raw value of this node, as provided by {@link Evaluator}. Typically, a node's value is not * Returns the underlying value of this node.
* consumed directly, but converted to the desired Java type using {@link #as}. *
* <p>This value is typically accessed indirectly via {@link #as(Class)}, {@link
* #asNullable(Class)}, or {@link #as(JavaType)}.
*/ */
Object getRawValue(); Object getRawValue();
/** /**
* Returns the child node with the given unqualified name. * Returns the child node with the given unqualified name.
* *
* <p>For example, {@code get("foo").get("bar")} returns the child named {@code "bar"} of the
* child named {@code "foo"}. Passing a qualified name to this method, as in {@code
* get("foo.bar")}, is not supported.
*
* @throws NoSuchChildException if a child with the given name does not exist * @throws NoSuchChildException if a child with the given name does not exist
*/ */
Config get(String childName); Config get(String childName);
/** /**
* Converts this node's value to the given {@link Class}. * Returns this node's value as a non-null value of the given {@link Class}.
*
* <p>If this node's value may be {@code null}, use {@link #asNullable(Class)} instead. In a
* future version, this method will perform a non-null check.
* *
* @throws ConversionException if the value cannot be converted to the given type * @throws ConversionException if the value cannot be converted to the given type
*/ */
<T extends @Nullable Object> T as(Class<T> type); @NullUnmarked
<T> T as(Class<T> type);
/** /**
* Converts this node's value to the given {@link Type}. * Returns this node's value as a non-null value of the given {@link JavaType}.
* *
* <p>Note that usages of this method are not type safe. * <p>If this node's value may be {@code null}, use {@link #asNullable(JavaType)} instead. In a
* future version, this method will perform a non-null check.
*
* <p>Use this method when converting to a parameterized type, such as {@code List<@Nullable
* String>}.
* *
* @throws ConversionException if the value cannot be converted to the given type * @throws ConversionException if the value cannot be converted to the given type
*/ */
<T extends @Nullable Object> T as(Type type); @NullUnmarked
<T> T as(JavaType<T> type);
/** /**
* Converts this node's value to the given {@link JavaType}. * Returns this node's value as a non-null value of the given {@link Type}.
*
* <p>If this node's value may be {@code null}, use {@link #asNullable(Type)} instead. In a future
* version, this method will perform a non-null check.
*
* <p>Use this method when the target type is already available as a {@link Type}; otherwise,
* prefer {@link #as(Class)} or {@link #as(JavaType)}.
* *
* @throws ConversionException if the value cannot be converted to the given type * @throws ConversionException if the value cannot be converted to the given type
*/ */
<T extends @Nullable Object> T as(JavaType<T> type); @NullUnmarked
<T> T as(Type type);
/**
* Returns this node's value as a nullable value of the given {@link Class}.
*
* <p>If this node's value cannot be {@code null}, use {@link #as(Class)} instead.
*
* @throws ConversionException if the value cannot be converted to the given type
*/
<T> @Nullable T asNullable(Class<T> type);
/**
* Returns this node's value as a nullable value of the given {@link Class}.
*
* <p>If this node's value cannot be {@code null}, use {@link #as(JavaType)} instead.
*
* <p>Use this method when converting to a parameterized type, such as {@code List<@Nullable
* String>}.
*
* @throws ConversionException if the value cannot be converted to the given type
*/
<T> @Nullable T asNullable(JavaType<T> type);
/**
* Returns this node's value as a nullable value of the given {@link Type}.
*
* <p>If this node's value cannot be {@code null}, use {@link #as(Type)} instead.
*
* <p>Use this method when the target type is already available as a {@link Type}; otherwise,
* prefer {@link #asNullable(Class)} or {@link #as(JavaType)}.
*
* @throws ConversionException if the value cannot be converted to the given type
*/
<T extends @Nullable Object> T asNullable(Type type);
/** /**
* Decodes a config from the supplied byte array. * Decodes a config from the supplied byte array.
@@ -23,30 +23,77 @@ import org.pkl.config.java.mapper.Types;
import org.pkl.core.Pair; import org.pkl.core.Pair;
/** /**
* Runtime representation of a possibly parameterized Java type. Factory methods are provided to * Represents a Java type, including fully parameterized types.
* ease construction of commonly used Java standard library types. For example, a {@code JavaType}
* for {@code List<String>} can be constructed using {@code JavaType.listOf(String.class)}.
* *
* <p>Parameterizations of other types can be constructed using the <em>super type token</em> idiom: * <p>This class captures complete type information that cannot be expressed with {@link Class}, for
* example {@code List<String>} or {@code Result<String, @Nullable Integer>}. It is often used with
* {@link Config#as(JavaType)}.
* *
* <p> * <p>A {@code JavaType} always represents a non-null top-level type, but its type arguments may be
* nullable. For example, {@code listOfNullable(String.class)} represents {@code List<@Nullable
* String>}.
*
* <p>To construct a non-parameterized type, use {@link #of(Class)}.
*
* <p>To construct common parameterized types, use one of:
*
* <ul>
* <li>{@link #optionalOf(Class)}
* <li>{@link #arrayOf(Class)}
* <li>{@link #collectionOf(Class)}
* <li>{@link #iterableOf(Class)}
* <li>{@link #listOf(Class)}
* <li>{@link #setOf(Class)}
* <li>{@link #mapOf(Class, Class)}
* <li>{@link #pairOf(Class, Class)}
* </ul>
*
* <p>Apart from {@code optionalOf()}, the above methods have nullable variants:
*
* <ul>
* <li>{@link #arrayOfNullable(Class)}
* <li>{@link #collectionOfNullable(Class)}
* <li>{@link #iterableOfNullable(Class)}
* <li>{@link #listOfNullable(Class)}
* <li>{@link #setOfNullable(Class)}
* <li>{@link #mapOfNullableKeys(Class, Class)}
* <li>{@link #mapOfNullableValues(Class, Class)}
* <li>{@link #mapOfNullableKeysAndValues(Class, Class)}
* <li>{@link #pairOfNullableFirst(Class, Class)}
* <li>{@link #pairOfNullableSecond(Class, Class)}
* <li>{@link #pairOfNullableFirstAndSecond(Class, Class)}
* </ul>
*
* <p>These methods can be nested. For example, {@code optionalOf(listOfNullable(String.class))}
* represents {@code Optional<List<@Nullable String>>}.
*
* <p>To construct arbitrary parameterized types, use the <em>super-type token</em> idiom:
* *
* <pre>{@code * <pre>{@code
* class Mapping<T> {} // some user-defined type * class Result<T, U> {} // library or user-defined type
*
* Config config = ... * Config config = ...
* *
* Mapping<String> container = config.as( * Result<String, @Nullable Integer> result =
* // construct super type token for Mapping<String> * config.as(new JavaType<Result<String, @Nullable Integer>>() {});
* new JavaType<Mapping<String>>() {}
* );
* }</pre> * }</pre>
* *
* @param <T> the type reified by this {@code JavaType} instance * @param <T> the non-null type represented by this {@code JavaType}
*/ */
@SuppressWarnings("unused")
public class JavaType<T> { public class JavaType<T> {
private final Type type; private final Type type;
/**
* Constructs a {@code JavaType} using the super-type token idiom.
*
* <p>Subclasses must be parameterized with the desired type, for example:
*
* <pre>{@code
* new JavaType<List<@Nullable String>>() {}
* }</pre>
*
* @throws IllegalStateException if this instance is not parameterized
*/
protected JavaType() { protected JavaType() {
var superclass = getClass().getGenericSuperclass(); var superclass = getClass().getGenericSuperclass();
if (!(superclass instanceof ParameterizedType parameterizedType)) { if (!(superclass instanceof ParameterizedType parameterizedType)) {
@@ -59,100 +106,382 @@ public class JavaType<T> {
this.type = type; this.type = type;
} }
/** Creates a {@code JavaType} for the given {@code Class}. */ /** Creates a {@code JavaType} for the given type. */
public static <T> JavaType<T> of(Class<T> type) { public static <T> JavaType<T> of(Class<T> type) {
return new JavaType<>(type); return new JavaType<>(type);
} }
/** /**
* Creates a {@code JavaType} for the given {@code Type}. * Creates a {@code JavaType} for the given {@link Type}.
* *
* <p>Note: This method is not type safe, and should be used with care. * <p>Use this method when the target type is already available as a {@link Type}; otherwise,
* prefer {@link #of(Class)}.
*/ */
public static <T> JavaType<T> of(Type type) { public static <T> JavaType<T> of(Type type) {
return new JavaType<>(type); return new JavaType<>(type);
} }
/** Creates an {@link Optional} type with the given element type. */ /**
* Creates an {@link Optional} type with the given non-null element type.
*
* <p>For a parameterized element type, use {@link #optionalOf(JavaType)}.
*/
public static <E> JavaType<Optional<E>> optionalOf(Class<E> elementType) { public static <E> JavaType<Optional<E>> optionalOf(Class<E> elementType) {
return JavaType.of(Types.optionalOf(elementType)); return JavaType.of(Types.optionalOf(elementType));
} }
/** Creates an {@link Optional} type with the given element type. */ /** Creates an {@link Optional} type with the given non-null element type. */
public static <E> JavaType<Optional<E>> optionalOf(JavaType<E> elementType) { public static <E> JavaType<Optional<E>> optionalOf(JavaType<E> elementType) {
return JavaType.of(Types.optionalOf(elementType.type)); return JavaType.of(Types.optionalOf(elementType.type));
} }
/** Creates a {@link Pair} type with the given first and second element types. */ /**
* Creates a {@link Pair} type with the given non-null first and non-null second element types.
*
* <p>For nullable first and/or second element types, use one of the {@code pairOfNullable*}
* methods.
*
* <p>For parameterized element types, use {@link #pairOf(JavaType, JavaType)}.
*/
public static <F, S> JavaType<Pair<F, S>> pairOf(Class<F> firstType, Class<S> secondType) { public static <F, S> JavaType<Pair<F, S>> pairOf(Class<F> firstType, Class<S> secondType) {
return JavaType.of(Types.pairOf(firstType, secondType)); return JavaType.of(Types.pairOf(firstType, secondType));
} }
/** Creates a {@link Pair} type with the given first and second element types. */ /**
* Creates a {@link Pair} type with the given non-null first and non-null second element types.
*
* <p>For nullable first and/or second element types, use one of the {@code pairOfNullable*}
* methods.
*/
public static <F, S> JavaType<Pair<F, S>> pairOf(JavaType<F> firstType, JavaType<S> secondType) { public static <F, S> JavaType<Pair<F, S>> pairOf(JavaType<F> firstType, JavaType<S> secondType) {
return JavaType.of(Types.pairOf(firstType.type, secondType.type)); return JavaType.of(Types.pairOf(firstType.type, secondType.type));
} }
/** Creates an array type with the given element type. */ /**
* Creates a {@link Pair} type with the given nullable first and non-null second element types.
*
* <p>For parameterized element types, use {@link #pairOfNullableFirst(JavaType, JavaType)}.
*/
public static <F, S> JavaType<Pair<@Nullable F, S>> pairOfNullableFirst(
Class<F> firstType, Class<S> secondType) {
return JavaType.of(Types.pairOf(firstType, secondType));
}
/**
* Creates a {@link Pair} type with the given nullable first and non-null second element types.
*/
public static <F, S> JavaType<Pair<@Nullable F, S>> pairOfNullableFirst(
JavaType<F> firstType, JavaType<S> secondType) {
return JavaType.of(Types.pairOf(firstType.type, secondType.type));
}
/**
* Creates a {@link Pair} type with the given non-null first and nullable second element types.
*
* <p>For parameterized element types, use {@link #pairOfNullableSecond(JavaType, JavaType)}.
*/
public static <F, S> JavaType<Pair<F, @Nullable S>> pairOfNullableSecond(
Class<F> firstType, Class<S> secondType) {
return JavaType.of(Types.pairOf(firstType, secondType));
}
/**
* Creates a {@link Pair} type with the given non-null first and nullable second element types.
*/
public static <F, S> JavaType<Pair<F, @Nullable S>> pairOfNullableSecond(
JavaType<F> firstType, JavaType<S> secondType) {
return JavaType.of(Types.pairOf(firstType.type, secondType.type));
}
/**
* Creates a {@link Pair} type with the given nullable first and nullable second element types.
*
* <p>For parameterized element types, use {@link #pairOfNullableFirstAndSecond(JavaType,
* JavaType)}.
*/
public static <F, S> JavaType<Pair<@Nullable F, @Nullable S>> pairOfNullableFirstAndSecond(
Class<F> firstType, Class<S> secondType) {
return JavaType.of(Types.pairOf(firstType, secondType));
}
/**
* Creates a {@link Pair} type with the given nullable first and nullable second element types.
*/
public static <F, S> JavaType<Pair<@Nullable F, @Nullable S>> pairOfNullableFirstAndSecond(
JavaType<F> firstType, JavaType<S> secondType) {
return JavaType.of(Types.pairOf(firstType.type, secondType.type));
}
/**
* Creates an array type with the given non-null element type.
*
* <p>For a nullable element type, use {@link #arrayOfNullable(Class)}.
*
* <p>For a parameterized element type, use {@link #arrayOf(JavaType)}.
*/
public static <E> JavaType<E[]> arrayOf(Class<E> elementType) { public static <E> JavaType<E[]> arrayOf(Class<E> elementType) {
return JavaType.of(Types.arrayOf(elementType)); return JavaType.of(Types.arrayOf(elementType));
} }
/** Creates an array type with the given element type. */ /**
* Creates an array type with the given non-null element type.
*
* <p>For a nullable element type, use {@link #arrayOfNullable(JavaType)}.
*/
public static <E> JavaType<E[]> arrayOf(JavaType<E> elementType) { public static <E> JavaType<E[]> arrayOf(JavaType<E> elementType) {
return JavaType.of(Types.arrayOf(elementType.type)); return JavaType.of(Types.arrayOf(elementType.type));
} }
/** Creates an {@link Iterable} type with the given element type. */ /**
* Creates an array type whose element type is nullable.
*
* <p>For a non-null element type, use {@link #arrayOf(Class)}.
*
* <p>For a parameterized element type, use {@link #arrayOfNullable(JavaType)}.
*/
public static <E> JavaType<@Nullable E[]> arrayOfNullable(Class<E> elementType) {
return JavaType.of(Types.arrayOf(elementType));
}
/**
* Creates an array type whose element type is nullable.
*
* <p>For a non-null element type, use {@link #arrayOf(JavaType)}.
*/
public static <E> JavaType<@Nullable E[]> arrayOfNullable(JavaType<E> elementType) {
return JavaType.of(Types.arrayOf(elementType.type));
}
/**
* Creates an {@link Iterable} type with the given non-null element type.
*
* <p>For a nullable element type, use {@link #iterableOfNullable(Class)}.
*
* <p>For a parameterized element type, use {@link #iterableOf(JavaType)}.
*/
public static <E> JavaType<Iterable<E>> iterableOf(Class<E> elementType) { public static <E> JavaType<Iterable<E>> iterableOf(Class<E> elementType) {
return JavaType.of(Types.iterableOf(elementType)); return JavaType.of(Types.iterableOf(elementType));
} }
/** Creates an {@link Iterable} type with the given element type. */ /**
* Creates an {@link Iterable} type with the given non-null element type.
*
* <p>For a nullable element type, use {@link #iterableOfNullable(JavaType)}.
*/
public static <E> JavaType<Iterable<E>> iterableOf(JavaType<E> elementType) { public static <E> JavaType<Iterable<E>> iterableOf(JavaType<E> elementType) {
return JavaType.of(Types.iterableOf(elementType.type)); return JavaType.of(Types.iterableOf(elementType.type));
} }
/** Creates a {@link Collection} type with the given element type. */ /**
* Creates an {@link Iterable} type whose element type is nullable.
*
* <p>For a non-null element type, use {@link #iterableOf(Class)}.
*
* <p>For a parameterized element type, use {@link #iterableOfNullable(JavaType)}.
*/
public static <E> JavaType<Iterable<@Nullable E>> iterableOfNullable(Class<E> elementType) {
return JavaType.of(Types.iterableOf(elementType));
}
/**
* Creates an {@link Iterable} type whose element type is nullable.
*
* <p>For a non-null element type, use {@link #iterableOf(JavaType)}.
*/
public static <E> JavaType<Iterable<@Nullable E>> iterableOfNullable(JavaType<E> elementType) {
return JavaType.of(Types.iterableOf(elementType.type));
}
/**
* Creates a {@link Collection} type with the given non-null element type.
*
* <p>For a nullable element type, use {@link #collectionOfNullable(Class)}.
*
* <p>For a parameterized element type, use {@link #collectionOf(JavaType)}.
*/
public static <E> JavaType<Collection<E>> collectionOf(Class<E> elementType) { public static <E> JavaType<Collection<E>> collectionOf(Class<E> elementType) {
return JavaType.of(Types.collectionOf(elementType)); return JavaType.of(Types.collectionOf(elementType));
} }
/** Creates a {@link Collection} type with the given element type. */ /**
* Creates a {@link Collection} type with the given non-null element type.
*
* <p>For a nullable element type, use {@link #collectionOfNullable(JavaType)}.
*/
public static <E> JavaType<Collection<E>> collectionOf(JavaType<E> elementType) { public static <E> JavaType<Collection<E>> collectionOf(JavaType<E> elementType) {
return JavaType.of(Types.collectionOf(elementType.type)); return JavaType.of(Types.collectionOf(elementType.type));
} }
/** Creates a {@link List} type with the given element type. */ /**
* Creates a {@link Collection} type whose element type is nullable.
*
* <p>For a non-null element type, use {@link #collectionOf(Class)}.
*
* <p>For a parameterized element type, use {@link #collectionOfNullable(JavaType)}.
*/
public static <E> JavaType<Collection<@Nullable E>> collectionOfNullable(Class<E> elementType) {
return JavaType.of(Types.collectionOf(elementType));
}
/**
* Creates a {@link Collection} type whose element type is nullable.
*
* <p>For a non-null element type, use {@link #collectionOf(JavaType)}.
*/
public static <E> JavaType<Collection<@Nullable E>> collectionOfNullable(
JavaType<E> elementType) {
return JavaType.of(Types.collectionOf(elementType.type));
}
/**
* Creates a {@link List} type with the given non-null element type.
*
* <p>For a nullable element type, use {@link #listOfNullable(Class)}.
*
* <p>For a parameterized element type, use {@link #listOf(JavaType)}.
*/
public static <E> JavaType<List<E>> listOf(Class<E> elementType) { public static <E> JavaType<List<E>> listOf(Class<E> elementType) {
return JavaType.of(Types.listOf(elementType)); return JavaType.of(Types.listOf(elementType));
} }
/** Creates a {@link List} type with the given element type. */ /**
* Creates a {@link List} type with the given non-null element type.
*
* <p>For a nullable element type, use {@link #listOfNullable(JavaType)}.
*/
public static <E> JavaType<List<E>> listOf(JavaType<E> elementType) { public static <E> JavaType<List<E>> listOf(JavaType<E> elementType) {
return JavaType.of(Types.listOf(elementType.type)); return JavaType.of(Types.listOf(elementType.type));
} }
/** Creates a {@link Set} type with the given element type. */ /**
* Creates a {@link List} type whose element type is nullable.
*
* <p>For a non-null element type, use {@link #listOf(Class)}.
*
* <p>For a parameterized element type, use {@link #listOfNullable(JavaType)}.
*/
public static <E> JavaType<List<@Nullable E>> listOfNullable(Class<E> elementType) {
return JavaType.of(Types.listOf(elementType));
}
/**
* Creates a {@link List} type whose element type is nullable.
*
* <p>For a non-null element type, use {@link #listOf(JavaType)}.
*/
public static <E> JavaType<List<@Nullable E>> listOfNullable(JavaType<E> elementType) {
return JavaType.of(Types.listOf(elementType.type));
}
/**
* Creates a {@link Set} type with the given non-null element type.
*
* <p>For a nullable element type, use {@link #setOfNullable(Class)}.
*
* <p>For a parameterized element type, use {@link #setOf(JavaType)}.
*/
public static <E> JavaType<Set<E>> setOf(Class<E> elementType) { public static <E> JavaType<Set<E>> setOf(Class<E> elementType) {
return JavaType.of(Types.setOf(elementType)); return JavaType.of(Types.setOf(elementType));
} }
/** Creates a {@link Set} type with the given element type. */ /**
* Creates a {@link Set} type with the given non-null element type.
*
* <p>For a nullable element type, use {@link #setOfNullable(JavaType)}.
*/
public static <E> JavaType<Set<E>> setOf(JavaType<E> elementType) { public static <E> JavaType<Set<E>> setOf(JavaType<E> elementType) {
return JavaType.of(Types.setOf(elementType.type)); return JavaType.of(Types.setOf(elementType.type));
} }
/** Creates a {@link Map} type with the given key and value types. */ /**
* Creates a {@link Set} type whose element type is nullable.
*
* <p>For a non-null element type, use {@link #setOf(Class)}.
*
* <p>For a parameterized element type, use {@link #setOfNullable(JavaType)}.
*/
public static <E> JavaType<Set<@Nullable E>> setOfNullable(Class<E> elementType) {
return JavaType.of(Types.setOf(elementType));
}
/**
* Creates a {@link Set} type whose element type is nullable.
*
* <p>For a non-null element type, use {@link #setOf(JavaType)}.
*/
public static <E> JavaType<Set<@Nullable E>> setOfNullable(JavaType<E> elementType) {
return JavaType.of(Types.setOf(elementType.type));
}
/**
* Creates a {@link Map} type with the given non-null key and non-null value types.
*
* <p>For nullable keys and/or values, use one of the {@code mapOfNullable*} methods.
*
* <p>For parameterized key and value types, use {@link #mapOf(JavaType, JavaType)}.
*/
public static <K, V> JavaType<Map<K, V>> mapOf(Class<K> keyType, Class<V> valueType) { public static <K, V> JavaType<Map<K, V>> mapOf(Class<K> keyType, Class<V> valueType) {
return JavaType.of(Types.mapOf(keyType, valueType)); return JavaType.of(Types.mapOf(keyType, valueType));
} }
/** Creates a {@link Map} type with the given key and value types. */ /**
* Creates a {@link Map} type with the given non-null key and non-null value types.
*
* <p>For nullable keys and/or values, use one of the {@code mapOfNullable*} methods.
*/
public static <K, V> JavaType<Map<K, V>> mapOf(JavaType<K> keyType, JavaType<V> valueType) { public static <K, V> JavaType<Map<K, V>> mapOf(JavaType<K> keyType, JavaType<V> valueType) {
return JavaType.of(Types.mapOf(keyType.type, valueType.type)); return JavaType.of(Types.mapOf(keyType.type, valueType.type));
} }
/**
* Creates a {@link Map} type with the given nullable key and non-null value types.
*
* <p>For parameterized key and value types, use {@link #mapOfNullableKeys(JavaType, JavaType)}.
*/
public static <K, V> JavaType<Map<@Nullable K, V>> mapOfNullableKeys(
Class<K> keyType, Class<V> valueType) {
return JavaType.of(Types.mapOf(keyType, valueType));
}
/** Creates a {@link Map} type with the given nullable key and non-null value types. */
public static <K, V> JavaType<Map<@Nullable K, V>> mapOfNullableKeys(
JavaType<K> keyType, JavaType<V> valueType) {
return JavaType.of(Types.mapOf(keyType.type, valueType.type));
}
/**
* Creates a {@link Map} type with the given non-null key and nullable value types.
*
* <p>For parameterized key and value types, use {@link #mapOfNullableValues(JavaType, JavaType)}.
*/
public static <K, V> JavaType<Map<K, @Nullable V>> mapOfNullableValues(
Class<K> keyType, Class<V> valueType) {
return JavaType.of(Types.mapOf(keyType, valueType));
}
/** Creates a {@link Map} type with the given non-null key and nullable value types. */
public static <K, V> JavaType<Map<K, @Nullable V>> mapOfNullableValues(
JavaType<K> keyType, JavaType<V> valueType) {
return JavaType.of(Types.mapOf(keyType.type, valueType.type));
}
/**
* Creates a {@link Map} type with the given nullable key and nullable value types.
*
* <p>For parameterized key and value types, use {@link #mapOfNullableKeysAndValues(JavaType,
* JavaType)}.
*/
public static <K, V> JavaType<Map<@Nullable K, @Nullable V>> mapOfNullableKeysAndValues(
Class<K> keyType, Class<V> valueType) {
return JavaType.of(Types.mapOf(keyType, valueType));
}
/** Creates a {@link Map} type with the given nullable key and nullable value types. */
public static <K, V> JavaType<Map<@Nullable K, @Nullable V>> mapOfNullableKeysAndValues(
JavaType<K> keyType, JavaType<V> valueType) {
return JavaType.of(Types.mapOf(keyType.type, valueType.type));
}
/** Returns the underlying {@link Type}. */ /** Returns the underlying {@link Type}. */
public Type getType() { public Type getType() {
return type; return type;
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -21,8 +21,16 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** Indicates that a type does not accept {@code null} as a value. */ /**
* Indicates that a type does not accept {@code null} as a value.
*
* <p>This annotation is deprecated, and any usage should be replaced with {@link
* org.jspecify.annotations.NonNull}.
*
* @deprecated since 0.32.0
*/
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.CLASS) @Retention(RetentionPolicy.CLASS)
@Documented @Documented
@Deprecated(forRemoval = true)
public @interface NonNull {} public @interface NonNull {}
@@ -17,6 +17,8 @@ package org.pkl.config.java;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import java.lang.reflect.Type;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.pkl.core.ModuleSource; import org.pkl.core.ModuleSource;
@@ -50,4 +52,31 @@ public final class ConfigEvaluatorTest extends AbstractConfigTest {
var address = addressConfig.as(Address.class); var address = addressConfig.as(Address.class);
assertThat(address.street).isEqualTo("Fuzzy St."); assertThat(address.street).isEqualTo("Fuzzy St.");
} }
@Test
public void asNullableWithClass() {
var mod = evaluator.evaluate(ModuleSource.text("nullValue = null; strValue = \"Bob\""));
@Nullable String nullValue = mod.get("nullValue").asNullable(String.class);
@Nullable String strValue = mod.get("strValue").asNullable(String.class);
assertThat(nullValue).isNull();
assertThat(strValue).isNotNull();
}
@Test
public void asNullableWithType() {
var mod = evaluator.evaluate(ModuleSource.text("nullValue = null; strValue = \"Bob\""));
@Nullable String nullValue = mod.get("nullValue").asNullable((Type) String.class);
@Nullable String strValue = mod.get("strValue").asNullable((Type) String.class);
assertThat(nullValue).isNull();
assertThat(strValue).isNotNull();
}
@Test
public void asNullableWithJavaType() {
var mod = evaluator.evaluate(ModuleSource.text("nullValue = null; strValue = \"Bob\""));
@Nullable String nullValue = mod.get("nullValue").asNullable(JavaType.of(String.class));
@Nullable String strValue = mod.get("strValue").asNullable(JavaType.of(String.class));
assertThat(nullValue).isNull();
assertThat(strValue).isNotNull();
}
} }
@@ -17,15 +17,25 @@ package org.pkl.config.java;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import java.lang.reflect.Type;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.*;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.pkl.config.java.mapper.Reflection; import org.pkl.config.java.mapper.Reflection;
import org.pkl.config.java.mapper.Types; import org.pkl.config.java.mapper.Types;
import org.pkl.core.Pair;
public final class JavaTypeTest { public final class JavaTypeTest {
@Test
public void constructSimpleType() {
assertThat(JavaType.of(String.class)).isEqualTo(new JavaType<String>() {});
//noinspection AssertBetweenInconvertibleTypes
assertThat(JavaType.of((Type) String.class)).isEqualTo(new JavaType<String>() {});
}
@Test @Test
public void constructOptionalType() { public void constructOptionalType() {
var type = JavaType.optionalOf(String.class); var type = JavaType.optionalOf(String.class);
@@ -34,6 +44,14 @@ public final class JavaTypeTest {
assertThat(Reflection.toRawType(type.getType())).isEqualTo(Optional.class); assertThat(Reflection.toRawType(type.getType())).isEqualTo(Optional.class);
} }
@Test
public void constructPairType() {
var type = JavaType.pairOf(String.class, Integer.class);
assertThat(type).isEqualTo(new JavaType<Pair<String, Integer>>() {});
assertThat(type)
.isEqualTo(JavaType.pairOf(JavaType.of(String.class), JavaType.of(Integer.class)));
}
@Test @Test
public void constructArrayType() { public void constructArrayType() {
var type = JavaType.arrayOf(String.class); var type = JavaType.arrayOf(String.class);
@@ -42,6 +60,14 @@ public final class JavaTypeTest {
assertThat(Reflection.toRawType(type.getType()).isArray()).isTrue(); assertThat(Reflection.toRawType(type.getType()).isArray()).isTrue();
} }
@Test
public void constructArrayOfNullableType() {
var type = JavaType.arrayOfNullable(String.class);
assertThat(type).isEqualTo(new JavaType<@Nullable String[]>() {});
assertThat(type).isEqualTo(JavaType.arrayOfNullable(JavaType.of(String.class)));
assertThat(Reflection.toRawType(type.getType()).isArray()).isTrue();
}
@Test @Test
public void constructIterableType() { public void constructIterableType() {
var type = JavaType.iterableOf(String.class); var type = JavaType.iterableOf(String.class);
@@ -50,6 +76,14 @@ public final class JavaTypeTest {
assertThat(Reflection.toRawType(type.getType())).isEqualTo(Iterable.class); assertThat(Reflection.toRawType(type.getType())).isEqualTo(Iterable.class);
} }
@Test
public void constructIterableOfNullableType() {
var type = JavaType.iterableOfNullable(String.class);
assertThat(type).isEqualTo(new JavaType<Iterable<@Nullable String>>() {});
assertThat(type).isEqualTo(JavaType.iterableOfNullable(JavaType.of(String.class)));
assertThat(Reflection.toRawType(type.getType())).isEqualTo(Iterable.class);
}
@Test @Test
public void constructCollectionType() { public void constructCollectionType() {
var type = JavaType.collectionOf(String.class); var type = JavaType.collectionOf(String.class);
@@ -58,6 +92,14 @@ public final class JavaTypeTest {
assertThat(Reflection.toRawType(type.getType())).isEqualTo(Collection.class); assertThat(Reflection.toRawType(type.getType())).isEqualTo(Collection.class);
} }
@Test
public void constructCollectionOfNullableType() {
var type = JavaType.collectionOfNullable(String.class);
assertThat(type).isEqualTo(new JavaType<Collection<@Nullable String>>() {});
assertThat(type).isEqualTo(JavaType.collectionOfNullable(JavaType.of(String.class)));
assertThat(Reflection.toRawType(type.getType())).isEqualTo(Collection.class);
}
@Test @Test
public void constructListType() { public void constructListType() {
var type = JavaType.listOf(String.class); var type = JavaType.listOf(String.class);
@@ -66,6 +108,14 @@ public final class JavaTypeTest {
assertThat(Reflection.toRawType(type.getType())).isEqualTo(List.class); assertThat(Reflection.toRawType(type.getType())).isEqualTo(List.class);
} }
@Test
public void constructListOfNullableType() {
var type = JavaType.listOfNullable(String.class);
assertThat(type).isEqualTo(new JavaType<List<@Nullable String>>() {});
assertThat(type).isEqualTo(JavaType.listOfNullable(JavaType.of(String.class)));
assertThat(Reflection.toRawType(type.getType())).isEqualTo(List.class);
}
@Test @Test
public void constructSetType() { public void constructSetType() {
var type = JavaType.setOf(String.class); var type = JavaType.setOf(String.class);
@@ -74,6 +124,14 @@ public final class JavaTypeTest {
assertThat(Reflection.toRawType(type.getType())).isEqualTo(Set.class); assertThat(Reflection.toRawType(type.getType())).isEqualTo(Set.class);
} }
@Test
public void constructSetOfNullableType() {
var type = JavaType.setOfNullable(String.class);
assertThat(type).isEqualTo(new JavaType<Set<@Nullable String>>() {});
assertThat(type).isEqualTo(JavaType.setOfNullable(JavaType.of(String.class)));
assertThat(Reflection.toRawType(type.getType())).isEqualTo(Set.class);
}
@Test @Test
public void constructMapType() { public void constructMapType() {
var type = JavaType.mapOf(String.class, URI.class); var type = JavaType.mapOf(String.class, URI.class);
@@ -83,7 +141,63 @@ public final class JavaTypeTest {
} }
@Test @Test
public void usageAsTypeToken() { public void constructPairOfNullableFirstType() {
var type = JavaType.pairOfNullableFirst(String.class, Integer.class);
assertThat(type).isEqualTo(new JavaType<Pair<@Nullable String, Integer>>() {});
assertThat(type)
.isEqualTo(
JavaType.pairOfNullableFirst(JavaType.of(String.class), JavaType.of(Integer.class)));
}
@Test
public void constructPairOfNullableSecondType() {
var type = JavaType.pairOfNullableSecond(String.class, Integer.class);
assertThat(type).isEqualTo(new JavaType<Pair<String, @Nullable Integer>>() {});
assertThat(type)
.isEqualTo(
JavaType.pairOfNullableSecond(JavaType.of(String.class), JavaType.of(Integer.class)));
}
@Test
public void constructPairOfNullableFirstAndSecondType() {
var type = JavaType.pairOfNullableFirstAndSecond(String.class, Integer.class);
assertThat(type).isEqualTo(new JavaType<Pair<@Nullable String, @Nullable Integer>>() {});
assertThat(type)
.isEqualTo(
JavaType.pairOfNullableFirstAndSecond(
JavaType.of(String.class), JavaType.of(Integer.class)));
}
@Test
public void constructMapOfNullableKeysType() {
var type = JavaType.mapOfNullableKeys(String.class, URI.class);
assertThat(type).isEqualTo(new JavaType<Map<@Nullable String, URI>>() {});
assertThat(type)
.isEqualTo(JavaType.mapOfNullableKeys(JavaType.of(String.class), JavaType.of(URI.class)));
assertThat(Reflection.toRawType(type.getType())).isEqualTo(Map.class);
}
@Test
public void constructMapOfNullableValuesType() {
var type = JavaType.mapOfNullableValues(String.class, URI.class);
assertThat(type).isEqualTo(new JavaType<Map<String, @Nullable URI>>() {});
assertThat(type)
.isEqualTo(JavaType.mapOfNullableValues(JavaType.of(String.class), JavaType.of(URI.class)));
assertThat(Reflection.toRawType(type.getType())).isEqualTo(Map.class);
}
@Test
public void constructMapOfNullableKeysAndValuesType() {
var type = JavaType.mapOfNullableKeysAndValues(String.class, URI.class);
assertThat(type).isEqualTo(new JavaType<Map<@Nullable String, @Nullable URI>>() {});
assertThat(type)
.isEqualTo(
JavaType.mapOfNullableKeysAndValues(JavaType.of(String.class), JavaType.of(URI.class)));
assertThat(Reflection.toRawType(type.getType())).isEqualTo(Map.class);
}
@Test
public void constructTypeToken() {
var javaType = new JavaType<Map<String, List<URI>>>() {}; var javaType = new JavaType<Map<String, List<URI>>>() {};
assertThat(javaType.getType()).isEqualTo(Types.mapOf(String.class, Types.listOf(URI.class))); assertThat(javaType.getType()).isEqualTo(Types.mapOf(String.class, Types.listOf(URI.class)));
@@ -110,6 +224,7 @@ public final class JavaTypeTest {
var type2 = new JavaType<Map<String, List<URL>>>() {}; var type2 = new JavaType<Map<String, List<URL>>>() {};
var type3 = JavaType.of(Types.mapOf(String.class, Types.listOf(Path.class))); var type3 = JavaType.of(Types.mapOf(String.class, Types.listOf(Path.class)));
//noinspection AssertBetweenInconvertibleTypes
assertThat(type2).isNotEqualTo(type1); assertThat(type2).isNotEqualTo(type1);
assertThat(type3).isNotEqualTo(type1); assertThat(type3).isNotEqualTo(type1);
assertThat(type2).isNotEqualTo(type3); assertThat(type2).isNotEqualTo(type3);
@@ -40,14 +40,15 @@ import org.pkl.config.kotlin.mapper.KotlinConverterFactories
* `as(JavaType.listOf(String::class.java))` * `as(JavaType.listOf(String::class.java))`
*/ */
inline fun <reified T> Config.to(): T { inline fun <reified T> Config.to(): T {
val result = `as`<T>(typeOf<T>().javaType) if (null is T) {
if (result == null && null !is T) { return asNullable(typeOf<T>().javaType)
throw ConversionException( }
return `as`(typeOf<T>().javaType)
?: throw ConversionException(
"Expected a non-null value but got `null`. " + "Expected a non-null value but got `null`. " +
"To allow null values, convert to a nullable Kotlin type, for example `String?`." "To allow null values, convert to a nullable Kotlin type, for example `String?`."
) )
}
return result
} }
/** /**
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -109,7 +109,7 @@ class KotlinObjectMappingTest {
thisOneGoesToEleven: Mapping<List<Set<Int>>, Map<Listing<Int>, Mapping<Int, String>>> = new { thisOneGoesToEleven: Mapping<List<Set<Int>>, Map<Listing<Int>, Mapping<Int, String>>> = new {
[List(Set(0), Set(0), Set(7))] = Map(intListing, intStringMapping) [List(Set(0), Set(0), Set(7))] = Map(intListing, intStringMapping)
} }
""" """
.trimIndent() .trimIndent()
val result = ConfigEvaluator.preconfigured().forKotlin().evaluate(text(code)) val result = ConfigEvaluator.preconfigured().forKotlin().evaluate(text(code))
assertDoesNotThrow { result.to<KotlinGenericTypesTest>() } assertDoesNotThrow { result.to<KotlinGenericTypesTest>() }
+17 -1
View File
@@ -13,6 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import net.ltgt.gradle.errorprone.errorprone
import net.ltgt.gradle.nullaway.nullaway
import org.apache.tools.ant.filters.ReplaceTokens import org.apache.tools.ant.filters.ReplaceTokens
plugins { plugins {
@@ -21,6 +23,7 @@ plugins {
id("pklJavaLibrary") id("pklJavaLibrary")
id("pklPublishLibrary") id("pklPublishLibrary")
id("pklNativeLifecycle") id("pklNativeLifecycle")
id("pklJSpecify")
idea idea
} }
@@ -40,7 +43,7 @@ dependencies {
annotationProcessor(libs.truffleDslProcessor) annotationProcessor(libs.truffleDslProcessor)
annotationProcessor(generatorSourceSet.get().runtimeClasspath) annotationProcessor(generatorSourceSet.get().runtimeClasspath)
compileOnly(libs.jsr305) compileOnly(libs.errorProneAnnotations)
// pkl-core implements pkl-executor's ExecutorSpi, but the SPI doesn't ship with pkl-core // pkl-core implements pkl-executor's ExecutorSpi, but the SPI doesn't ship with pkl-core
compileOnly(projects.pklExecutor) compileOnly(projects.pklExecutor)
@@ -57,6 +60,7 @@ dependencies {
add("generatorImplementation", libs.javaPoet) add("generatorImplementation", libs.javaPoet)
add("generatorImplementation", libs.truffleApi) add("generatorImplementation", libs.truffleApi)
add("generatorImplementation", libs.jspecify)
javaExecutableConfiguration(project(":pkl-cli", "javaExecutable")) javaExecutableConfiguration(project(":pkl-cli", "javaExecutable"))
} }
@@ -107,6 +111,18 @@ tasks.processResources {
tasks.compileJava { options.generatedSourceOutputDirectory.set(file("generated/truffle")) } tasks.compileJava { options.generatedSourceOutputDirectory.set(file("generated/truffle")) }
tasks.withType<JavaCompile>().configureEach {
options.errorprone.nullaway {
// Do not require LateInit fields to be initialized at construction time.
// Unfortunately, IntelliJ doesn't currently understand this,
// and therefore emits many warnings related to LateInit.
excludedFieldAnnotations.add("org.pkl.core.util.LateInit")
// For now, don't analyze code that deals with Truffle ASTs.
unannotatedSubPackages.addAll("org.pkl.core.ast", "org.pkl.core.stdlib")
}
}
tasks.compileKotlin { enabled = false } tasks.compileKotlin { enabled = false }
tasks.test { tasks.test {
@@ -39,6 +39,7 @@ import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement; import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeMirror;
import org.jspecify.annotations.Nullable;
/** /**
* Generates a subclass of {@code org.pkl.core.stdlib.registry.ExternalMemberRegistry} for each * Generates a subclass of {@code org.pkl.core.stdlib.registry.ExternalMemberRegistry} for each
@@ -114,6 +115,7 @@ public final class MemberRegistryGenerator extends AbstractProcessor {
Comparator.comparing( Comparator.comparing(
(TypeElement element) -> { (TypeElement element) -> {
var enclosingElement = element.getEnclosingElement(); var enclosingElement = element.getEnclosingElement();
assert enclosingElement != null;
return enclosingElement.getKind() == ElementKind.PACKAGE return enclosingElement.getKind() == ElementKind.PACKAGE
? "" ? ""
: enclosingElement.getSimpleName().toString(); : enclosingElement.getSimpleName().toString();
@@ -155,6 +157,7 @@ public final class MemberRegistryGenerator extends AbstractProcessor {
for (var nodeClass : nodeClasses) { for (var nodeClass : nodeClasses) {
var enclosingClass = nodeClass.getEnclosingElement(); var enclosingClass = nodeClass.getEnclosingElement();
assert enclosingClass != null;
var pklClassName = getAnnotatedPklName(enclosingClass); var pklClassName = getAnnotatedPklName(enclosingClass);
if (pklClassName == null) { if (pklClassName == null) {
@@ -226,7 +229,7 @@ public final class MemberRegistryGenerator extends AbstractProcessor {
writeJavaFile(REGISTRY_PACKAGE_NAME, registryFactoryClass.build()); writeJavaFile(REGISTRY_PACKAGE_NAME, registryFactoryClass.build());
} }
private String getAnnotatedPklName(Element element) { private @Nullable String getAnnotatedPklName(Element element) {
for (var annotation : element.getAnnotationMirrors()) { for (var annotation : element.getAnnotationMirrors()) {
var annotationName = annotation.getAnnotationType().asElement().getSimpleName().toString(); var annotationName = annotation.getAnnotationType().asElement().getSimpleName().toString();
@@ -0,0 +1,4 @@
@NullMarked
package org.pkl.core.generator;
import org.jspecify.annotations.NullMarked;
@@ -22,6 +22,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Context;
import org.jspecify.annotations.Nullable;
import org.pkl.core.evaluatorSettings.TraceMode; import org.pkl.core.evaluatorSettings.TraceMode;
import org.pkl.core.http.HttpClient; import org.pkl.core.http.HttpClient;
import org.pkl.core.http.HttpClientInitException; import org.pkl.core.http.HttpClientInitException;
@@ -36,7 +37,6 @@ import org.pkl.core.runtime.VmContext;
import org.pkl.core.runtime.VmException; import org.pkl.core.runtime.VmException;
import org.pkl.core.runtime.VmImportAnalyzer; import org.pkl.core.runtime.VmImportAnalyzer;
import org.pkl.core.runtime.VmUtils; import org.pkl.core.runtime.VmUtils;
import org.pkl.core.util.Nullable;
/** Utility library for static analysis of Pkl programs. */ /** Utility library for static analysis of Pkl programs. */
public class Analyzer { public class Analyzer {
@@ -21,8 +21,21 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/**
* A specification parsed from a valid {@code pkl:Command} submodule.
*
* @param name the name of the (sub)command.
* @param helpText the CLI help text of the (sub)command.
* @param hidden whether the subcommand should be hidden from CLI help.
* @param noOp whether the (sub)command cannot be directly be executed (if true, it must have
* subcommands).
* @param options specifications for the (sub)command's CLI options.
* @param subcommands specifications for the (sub)command's subcommands.
* @param apply a function that transforms command execution {@link State}, applying the parsed
* options from this command.
*/
public record CommandSpec( public record CommandSpec(
String name, String name,
@Nullable String helpText, @Nullable String helpText,
@@ -32,43 +45,64 @@ public record CommandSpec(
List<CommandSpec> subcommands, List<CommandSpec> subcommands,
ApplyFunction apply) { ApplyFunction apply) {
/** A command line option. */
public sealed interface Option { public sealed interface Option {
/** Primary name of the option with no type-specific punctuation. */
String name(); String name();
/**
* All option names include type-specific punctuation (e.g. {@code -} for flags). If multiple,
* the primary name is listed last.
*/
String[] getNames(); String[] getNames();
/**
* An exception thrown by {@link Flag} and {@link Argument} transform functions to indicate that
* no value was provided for a required option.
*/
class MissingOption extends RuntimeException { class MissingOption extends RuntimeException {
public MissingOption() {} public MissingOption() {}
} }
/**
* An exception thrown by {@link Flag} and {@link Argument} transform functions to indicate that
* a provided option value is not valid.
*/
class BadValue extends RuntimeException { class BadValue extends RuntimeException {
public BadValue(String message) { public BadValue(String message) {
super(message); super(message);
} }
/** Creates an exception for type mismatches. */
public static BadValue invalid(String value, String type) { public static BadValue invalid(String value, String type) {
return new BadValue(String.format("%s is not a valid %s", value, type)); return new BadValue(String.format("%s is not a valid %s", value, type));
} }
/** Creates an exception for invalid key=value strings. */
public static BadValue badKeyValue(String value) { public static BadValue badKeyValue(String value) {
return new BadValue(String.format("%s is not a valid key=value pair", value)); return new BadValue(String.format("%s is not a valid key=value pair", value));
} }
/** Creates an exception for an invalid value with a set of known valid values. */
public static BadValue invalidChoice(String value, List<String> choices) { public static BadValue invalidChoice(String value, List<String> choices) {
return new BadValue( return new BadValue(
String.format( String.format(
"invalid choice: %s. (choose from %s)", value, String.join(", ", choices))); "invalid choice: %s. (choose from %s)", value, String.join(", ", choices)));
} }
/** Creates an exception for an invalid value with a single known valid value. */
public static BadValue invalidChoice(String value, String choice) { public static BadValue invalidChoice(String value, String choice) {
return new BadValue(String.format("invalid choice: %s. (choose from %s)", value, choice)); return new BadValue(String.format("invalid choice: %s. (choose from %s)", value, choice));
} }
} }
} }
/** Specifications for how shells should auto-complete an {@link Option}'s value */
public abstract static sealed class CompletionCandidates { public abstract static sealed class CompletionCandidates {
/** Shells should auto-complete file paths for this option. */
public static final CompletionCandidates PATH = new StaticCompletionCandidates(); public static final CompletionCandidates PATH = new StaticCompletionCandidates();
/** Shells should auto-complete a set of static values for this option. */
public static final class Fixed extends CompletionCandidates { public static final class Fixed extends CompletionCandidates {
private final Set<String> values; private final Set<String> values;
@@ -76,6 +110,7 @@ public record CommandSpec(
this.values = values; this.values = values;
} }
/** Specific static values offered by shell auto-complete. */
public Set<String> getValues() { public Set<String> getValues() {
return values; return values;
} }
@@ -84,12 +119,32 @@ public record CommandSpec(
private static final class StaticCompletionCandidates extends CompletionCandidates {} private static final class StaticCompletionCandidates extends CompletionCandidates {}
} }
/**
* A specification for a single CLI flag.
*
* <p>A flag's name becomes its CLI flag (prefixed with {@code --}) and may optionally have a
* single-character short name (prefixed with {@code -}). A flag is always followed by a single
* argument that becomes its value.
*
* @param name the primary (long) name of the flag.
* @param helpText the flag's CLI help text.
* @param showAsRequired determines whether the CLI help should show the flag as required.
* @param transformEach a function that transforms a flag's raw value (and working dir URI) into a
* valid Pkl value.
* @param transformAll a function that transforms the list of parsed Pkl values for the flag into
* a single final value.
* @param completionCandidates specifies if/how the shell should auto-complete the flag value.
* @param shortName the single-character abbreviated form of the flag.
* @param metavar the text used to substitute for the flag's value in CLI help text.
* @param hidden whether the flag should be hidden from CLI help.
* @param defaultValue a string representation of the flag's default value for use in CLI help.
*/
public record Flag( public record Flag(
String name, String name,
@Nullable String helpText, @Nullable String helpText,
boolean showAsRequired, boolean showAsRequired,
BiFunction<String, URI, Object> transformEach, BiFunction<String, URI, Object> transformEach,
BiFunction<List<Object>, URI, Object> transformAll, BiFunction<List<Object>, URI, @Nullable Object> transformAll,
@Nullable CompletionCandidates completionCandidates, @Nullable CompletionCandidates completionCandidates,
@Nullable String shortName, @Nullable String shortName,
String metavar, String metavar,
@@ -104,6 +159,20 @@ public record CommandSpec(
} }
} }
/**
* A specification for a single on/off CLI flag.
*
* <p>A boolean flag's name becomes its CLI flag (prefixed with {@code --}) and may optionally
* have a single-character short name (prefixed with {@code -}). An additional name for the
* inverted form of the flag (prefixed with {@code --no-} is also added. A boolean flag accepts no
* value argument.
*
* @param name the primary (long) name of the flag.
* @param helpText the flag's CLI help text.
* @param shortName the single-character abbreviated form of the flag.
* @param hidden whether the flag should be hidden from CLI help.
* @param defaultValue a string representation of the flag's default value for use in CLI help.
*/
public record BooleanFlag( public record BooleanFlag(
String name, String name,
@Nullable String helpText, @Nullable String helpText,
@@ -119,6 +188,18 @@ public record CommandSpec(
} }
} }
/**
* A specification for a single CLI flag that counts how many times it is used.
*
* <p>A counted flag's name becomes its CLI flag (prefixed with {@code --}) and may optionally
* have a single-character short name (prefixed with {@code -}). A counted flag accepts no value
* argument.
*
* @param name the primary (long) name of the flag.
* @param helpText the flag's CLI help text.
* @param shortName the single-character abbreviated form of the flag.
* @param hidden whether the flag should be hidden from CLI help.
*/
public record CountedFlag( public record CountedFlag(
String name, @Nullable String helpText, @Nullable String shortName, boolean hidden) String name, @Nullable String helpText, @Nullable String shortName, boolean hidden)
implements Option { implements Option {
@@ -130,11 +211,23 @@ public record CommandSpec(
} }
} }
/**
* A specification for a single CLI positional argument.
*
* @param name the name of the argument.
* @param helpText the argument's CLI help text.
* @param transformEach a function that transforms a argument's raw value (and working dir URI)
* into a valid Pkl value.
* @param transformAll a function that transforms the list of parsed Pkl values for the argument
* into a single final value.
* @param completionCandidates specifies if/how the shell should auto-complete the argument value.
* @param repeated whether the argument accepts multiple values.
*/
public record Argument( public record Argument(
String name, String name,
@Nullable String helpText, @Nullable String helpText,
BiFunction<String, URI, Object> transformEach, BiFunction<String, URI, Object> transformEach,
BiFunction<List<Object>, URI, Object> transformAll, BiFunction<List<Object>, URI, @Nullable Object> transformAll,
@Nullable CompletionCandidates completionCandidates, @Nullable CompletionCandidates completionCandidates,
boolean repeated) boolean repeated)
implements Option { implements Option {
@@ -144,15 +237,31 @@ public record CommandSpec(
} }
} }
/** A function used to transform command {@link State} as arguments are parsed. */
public interface ApplyFunction { public interface ApplyFunction {
State apply(Map<String, Object> options, @Nullable State parent); State apply(Map<String, @Nullable Object> options, @Nullable State parent);
} }
/**
* The execution state of a command.
*
* @param contents the opaque, implementation-defined state of the command. It must not be
* directly inspected or modified outside of an {@link ApplyFunction}.
* @param reify an implementation-defined function that transforms some state contents to a {@link
* Result}.
*/
public record State(Object contents, Function<Object, Result> reify) { public record State(Object contents, Function<Object, Result> reify) {
/** Evaluate the state to produce its output {@link Result}. */
public Result evaluate() { public Result evaluate() {
return reify.apply(contents); return reify.apply(contents);
} }
} }
/**
* The result of executing a command.
*
* @param outputBytes the executed command's {@code output.bytes}.
* @param outputFiles the executed command's {@code output.files}.
*/
public record Result(byte[] outputBytes, Map<String, FileOutput> outputFiles) {} public record Result(byte[] outputBytes, Map<String, FileOutput> outputFiles) {}
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
package org.pkl.core; package org.pkl.core;
import java.util.Map; import java.util.Map;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** A container of properties. */ /** A container of properties. */
public interface Composite extends Value { public interface Composite extends Value {
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,8 +19,8 @@ import static org.pkl.core.DataSizeUnit.*;
import java.io.Serial; import java.io.Serial;
import java.util.Objects; import java.util.Objects;
import org.jspecify.annotations.Nullable;
import org.pkl.core.util.MathUtils; import org.pkl.core.util.MathUtils;
import org.pkl.core.util.Nullable;
/** Java representation of a {@code pkl.base#DataSize} value. */ /** Java representation of a {@code pkl.base#DataSize} value. */
public final class DataSize implements Value { public final class DataSize implements Value {
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
*/ */
package org.pkl.core; package org.pkl.core;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** /**
* The unit of a {@link DataSize}. In Pkl, data size units are represented as String {@link * The unit of a {@link DataSize}. In Pkl, data size units are represented as String {@link
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,8 +19,8 @@ import static org.pkl.core.DurationUnit.*;
import java.io.Serial; import java.io.Serial;
import java.util.Objects; import java.util.Objects;
import org.jspecify.annotations.Nullable;
import org.pkl.core.util.DurationUtils; import org.pkl.core.util.DurationUtils;
import org.pkl.core.util.Nullable;
/** Java representation of a {@code pkl.base#Duration} value. */ /** Java representation of a {@code pkl.base#Duration} value. */
public final class Duration implements Value { public final class Duration implements Value {
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@ package org.pkl.core;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** /**
* The unit of a {@link Duration}. In Pkl, duration units are represented as String {@link * The unit of a {@link Duration}. In Pkl, duration units are represented as String {@link
@@ -19,6 +19,7 @@ import com.oracle.truffle.api.TruffleOptions;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.*;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.jspecify.annotations.Nullable;
import org.pkl.core.SecurityManagers.StandardBuilder; import org.pkl.core.SecurityManagers.StandardBuilder;
import org.pkl.core.evaluatorSettings.PklEvaluatorSettings.ExternalReader; import org.pkl.core.evaluatorSettings.PklEvaluatorSettings.ExternalReader;
import org.pkl.core.evaluatorSettings.TraceMode; import org.pkl.core.evaluatorSettings.TraceMode;
@@ -33,7 +34,6 @@ import org.pkl.core.resource.ResourceReader;
import org.pkl.core.resource.ResourceReaders; import org.pkl.core.resource.ResourceReaders;
import org.pkl.core.runtime.LoggerImpl; import org.pkl.core.runtime.LoggerImpl;
import org.pkl.core.util.IoUtils; import org.pkl.core.util.IoUtils;
import org.pkl.core.util.Nullable;
/** A builder for an {@link Evaluator}. Can be reused to build multiple evaluators. */ /** A builder for an {@link Evaluator}. Can be reused to build multiple evaluators. */
@SuppressWarnings({"UnusedReturnValue", "unused"}) @SuppressWarnings({"UnusedReturnValue", "unused"})
@@ -56,7 +56,7 @@ public final class EvaluatorBuilder {
private final Map<String, String> externalProperties = new HashMap<>(); private final Map<String, String> externalProperties = new HashMap<>();
private @Nullable java.time.Duration timeout; private java.time.@Nullable Duration timeout;
private @Nullable Path moduleCacheDir = IoUtils.getDefaultModuleCacheDir(); private @Nullable Path moduleCacheDir = IoUtils.getDefaultModuleCacheDir();
@@ -386,7 +386,7 @@ public final class EvaluatorBuilder {
/** /**
* Sets an evaluation timeout to be enforced by the {@link Evaluator}'s {@code evaluate} methods. * Sets an evaluation timeout to be enforced by the {@link Evaluator}'s {@code evaluate} methods.
*/ */
public EvaluatorBuilder setTimeout(@Nullable java.time.Duration timeout) { public EvaluatorBuilder setTimeout(java.time.@Nullable Duration timeout) {
this.timeout = timeout; this.timeout = timeout;
return this; return this;
} }
@@ -557,6 +557,9 @@ public final class EvaluatorBuilder {
if (settings.http().rewrites() != null) { if (settings.http().rewrites() != null) {
httpClientBuilder.setRewrites(settings.http().rewrites()); httpClientBuilder.setRewrites(settings.http().rewrites());
} }
if (settings.http().headers() != null) {
httpClientBuilder.setHeaders(settings.http().headers());
}
setHttpClient(httpClientBuilder.buildLazily()); setHttpClient(httpClientBuilder.buildLazily());
} }
@@ -16,6 +16,8 @@
package org.pkl.core; package org.pkl.core;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Path; import java.nio.file.Path;
import java.time.Duration; import java.time.Duration;
import java.util.Collection; import java.util.Collection;
@@ -28,14 +30,17 @@ import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Context;
import org.jspecify.annotations.Nullable;
import org.msgpack.core.MessageBufferPacker; import org.msgpack.core.MessageBufferPacker;
import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePack;
import org.pkl.core.ast.ConstantValueNode; import org.pkl.core.ast.ConstantValueNode;
import org.pkl.core.ast.internal.ToStringNodeGen; import org.pkl.core.ast.internal.ToStringNodeGen;
import org.pkl.core.evaluatorSettings.TraceMode; import org.pkl.core.evaluatorSettings.TraceMode;
import org.pkl.core.externalreader.ExternalReaderProcessException;
import org.pkl.core.http.HttpClient; import org.pkl.core.http.HttpClient;
import org.pkl.core.module.ModuleKeyFactory; import org.pkl.core.module.ModuleKeyFactory;
import org.pkl.core.module.ProjectDependenciesManager; import org.pkl.core.module.ProjectDependenciesManager;
import org.pkl.core.packages.PackageLoadError;
import org.pkl.core.packages.PackageResolver; import org.pkl.core.packages.PackageResolver;
import org.pkl.core.project.DeclaredDependencies; import org.pkl.core.project.DeclaredDependencies;
import org.pkl.core.resource.ResourceReader; import org.pkl.core.resource.ResourceReader;
@@ -56,7 +61,7 @@ import org.pkl.core.runtime.VmUtils;
import org.pkl.core.runtime.VmValue; import org.pkl.core.runtime.VmValue;
import org.pkl.core.runtime.VmValueRenderer; import org.pkl.core.runtime.VmValueRenderer;
import org.pkl.core.util.ErrorMessages; import org.pkl.core.util.ErrorMessages;
import org.pkl.core.util.Nullable; import org.pkl.core.util.IoUtils;
public final class EvaluatorImpl implements Evaluator { public final class EvaluatorImpl implements Evaluator {
private final StackFrameTransformer frameTransformer; private final StackFrameTransformer frameTransformer;
@@ -69,6 +74,7 @@ public final class EvaluatorImpl implements Evaluator {
private final BufferedLogger logger; private final BufferedLogger logger;
private final PackageResolver packageResolver; private final PackageResolver packageResolver;
private final VmValueRenderer vmValueRenderer = VmValueRenderer.singleLine(1000); private final VmValueRenderer vmValueRenderer = VmValueRenderer.singleLine(1000);
private final @Nullable URI projectFileUri;
private @Nullable MessageBufferPacker messagePacker; private @Nullable MessageBufferPacker messagePacker;
public EvaluatorImpl( public EvaluatorImpl(
@@ -94,6 +100,11 @@ public final class EvaluatorImpl implements Evaluator {
moduleResolver = new ModuleResolver(factories); moduleResolver = new ModuleResolver(factories);
this.logger = new BufferedLogger(logger); this.logger = new BufferedLogger(logger);
packageResolver = PackageResolver.getInstance(securityManager, httpClient, moduleCacheDir); packageResolver = PackageResolver.getInstance(securityManager, httpClient, moduleCacheDir);
if (projectDependencies != null) {
this.projectFileUri = projectDependencies.projectFileUri();
} else {
this.projectFileUri = null;
}
polyglotContext = polyglotContext =
VmUtils.createContext( VmUtils.createContext(
() -> { () -> {
@@ -296,7 +307,7 @@ public final class EvaluatorImpl implements Evaluator {
reservedFlagShortNames, reservedFlagShortNames,
(fileOutput) -> new FileOutputImpl(this, fileOutput)); (fileOutput) -> new FileOutputImpl(this, fileOutput));
run.accept(commandRunner.parse(module)); run.accept(commandRunner.parse(module));
return null; return true; // return value is not used; returning null would violate nullness
}); });
} }
@@ -424,10 +435,37 @@ public final class EvaluatorImpl implements Evaluator {
return evalResult; return evalResult;
} }
/** Resolve dependency notation URIs (e.g. `@foo/bar.pkl`) to its resolved absolute URI. */
private ModuleSource normalizeModuleSource(ModuleSource moduleSource) {
if (moduleSource.getContents() != null
|| moduleSource.getUri().isAbsolute()
|| !moduleSource.getUri().getPath().startsWith("@")) {
return moduleSource;
}
try {
if (projectFileUri != null) {
var moduleKey = moduleResolver.resolve(projectFileUri);
var uri = IoUtils.resolve(securityManager, moduleKey, moduleSource.getUri());
return ModuleSource.uri(uri);
} else {
throw new PackageLoadError("cannotResolveDependencyNoProject");
}
} catch (URISyntaxException e) {
// impossible condition
throw PklBugException.unreachableCode();
} catch (IOException e) {
throw new VmExceptionBuilder()
.evalError("ioErrorLoadingModule", moduleSource.getUri())
.build();
} catch (ExternalReaderProcessException | SecurityManagerException | PackageLoadError e) {
throw new VmExceptionBuilder().withCause(e).build();
}
}
private <T> T doEvaluate(ModuleSource moduleSource, Function<VmTyped, T> doEvaluate) { private <T> T doEvaluate(ModuleSource moduleSource, Function<VmTyped, T> doEvaluate) {
return doEvaluate( return doEvaluate(
() -> { () -> {
var moduleKey = moduleResolver.resolve(moduleSource); var moduleKey = moduleResolver.resolve(normalizeModuleSource(moduleSource));
var module = VmLanguage.get(null).loadModule(moduleKey); var module = VmLanguage.get(null).loadModule(moduleKey);
return doEvaluate.apply(module); return doEvaluate.apply(module);
}); });
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** Common base class for TypeAlias, PClass, PClass.Property, and PClass.Method. */ /** Common base class for TypeAlias, PClass, PClass.Property, and PClass.Method. */
public abstract class Member implements Serializable { public abstract class Member implements Serializable {
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,8 +17,8 @@ package org.pkl.core;
import java.net.URI; import java.net.URI;
import java.util.*; import java.util.*;
import org.jspecify.annotations.Nullable;
import org.pkl.core.util.LateInit; import org.pkl.core.util.LateInit;
import org.pkl.core.util.Nullable;
/** Describes the property, method and class members of a module. */ /** Describes the property, method and class members of a module. */
public final class ModuleSchema { public final class ModuleSchema {
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,8 +18,8 @@ package org.pkl.core;
import java.io.File; import java.io.File;
import java.net.URI; import java.net.URI;
import java.nio.file.Path; import java.nio.file.Path;
import org.jspecify.annotations.Nullable;
import org.pkl.core.runtime.VmUtils; import org.pkl.core.runtime.VmUtils;
import org.pkl.core.util.Nullable;
/** /**
* A representation for a Pkl module's source URI, and optionally its source text. * A representation for a Pkl module's source URI, and optionally its source text.
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@ package org.pkl.core;
import java.io.Serial; import java.io.Serial;
import java.util.*; import java.util.*;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** Java representation of a {@code pkl.base#Class} value. */ /** Java representation of a {@code pkl.base#Class} value. */
public final class PClass extends Member implements Value { public final class PClass extends Member implements Value {
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ import java.io.Serializable;
import java.net.URI; import java.net.URI;
import java.util.*; import java.util.*;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** Information about a Pkl class and its Java representation. */ /** Information about a Pkl class and its Java representation. */
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ import java.io.Serial;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** Java representation of a Pkl module. */ /** Java representation of a Pkl module. */
public final class PModule extends PObject { public final class PModule extends PObject {
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@ package org.pkl.core;
import java.io.Serial; import java.io.Serial;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** Java representation of a Pkl object. */ /** Java representation of a Pkl object. */
public class PObject implements Composite { public class PObject implements Composite {
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,10 +18,12 @@ package org.pkl.core;
import java.io.Serial; import java.io.Serial;
import java.util.Iterator; import java.util.Iterator;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import org.pkl.core.util.Nullable; import java.util.Objects;
import org.jspecify.annotations.Nullable;
/** Java representation of a {@code pkl.base#Pair} value. */ /** Java representation of a {@code pkl.base#Pair} value. */
public final class Pair<F, S> implements Value, Iterable<Object> { public final class Pair<F extends @Nullable Object, S extends @Nullable Object>
implements Value, Iterable<@Nullable Object> {
@Serial private static final long serialVersionUID = 0L; @Serial private static final long serialVersionUID = 0L;
private final F first; private final F first;
@@ -44,7 +46,7 @@ public final class Pair<F, S> implements Value, Iterable<Object> {
} }
@Override @Override
public Iterator<Object> iterator() { public Iterator<@Nullable Object> iterator() {
return new Iterator<>() { return new Iterator<>() {
int pos = 0; int pos = 0;
@@ -54,7 +56,7 @@ public final class Pair<F, S> implements Value, Iterable<Object> {
} }
@Override @Override
public Object next() { public @Nullable Object next() {
return switch (pos++) { return switch (pos++) {
case 0 -> first; case 0 -> first;
case 1 -> second; case 1 -> second;
@@ -83,12 +85,12 @@ public final class Pair<F, S> implements Value, Iterable<Object> {
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable Object obj) {
if (this == obj) return true; if (this == obj) return true;
if (!(obj instanceof Pair<?, ?> other)) return false; if (!(obj instanceof Pair<?, ?> other)) return false;
return first.equals(other.first) && second.equals(other.second); return Objects.equals(first, other.first) && Objects.equals(second, other.second);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return first.hashCode() * 31 + second.hashCode(); return Objects.hashCode(first) * 31 + Objects.hashCode(second);
} }
@Override @Override
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -15,16 +15,18 @@
*/ */
package org.pkl.core; package org.pkl.core;
import org.jspecify.annotations.Nullable;
public class PklException extends RuntimeException { public class PklException extends RuntimeException {
public PklException(String message, Throwable cause) { public PklException(@Nullable String message, @Nullable Throwable cause) {
super(message, cause); super(message, cause);
} }
public PklException(String message) { public PklException(@Nullable String message) {
super(message); super(message);
} }
public PklException(Throwable cause) { public PklException(@Nullable Throwable cause) {
super(cause); super(cause);
} }
} }
@@ -21,7 +21,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
import org.pkl.core.util.properties.PropertiesUtils; import org.pkl.core.util.properties.PropertiesUtils;
// To instantiate this class, use ValueRenderers.properties(). // To instantiate this class, use ValueRenderers.properties().
@@ -18,7 +18,7 @@ package org.pkl.core;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.nio.file.Path; import java.nio.file.Path;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** /**
* Enforces a security model during {@link Evaluator evaluation}. * Enforces a security model during {@link Evaluator evaluation}.
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ import java.nio.file.Path;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** /**
* Parent interface to builder classes for configuring a {@link SecurityManager}. * Parent interface to builder classes for configuring a {@link SecurityManager}.
@@ -45,8 +45,7 @@ public interface SecurityManagerBuilder<B extends SecurityManagerBuilder<B>> {
B setRootDir(@Nullable Path rootDir); B setRootDir(@Nullable Path rootDir);
@Nullable @Nullable Path getRootDir();
Path getRootDir();
SecurityManager build(); SecurityManager build();
} }
@@ -23,9 +23,9 @@ import java.nio.file.Path;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.jspecify.annotations.Nullable;
import org.pkl.core.util.ErrorMessages; import org.pkl.core.util.ErrorMessages;
import org.pkl.core.util.IoUtils; import org.pkl.core.util.IoUtils;
import org.pkl.core.util.Nullable;
/** A provider for {@link SecurityManager}s. */ /** A provider for {@link SecurityManager}s. */
public final class SecurityManagers { public final class SecurityManagers {
@@ -273,7 +273,7 @@ public final class SecurityManagers {
private final List<Pattern> allowedResources = new ArrayList<>(); private final List<Pattern> allowedResources = new ArrayList<>();
private Path rootDir; private @Nullable Path rootDir;
private StandardBuilder() {} private StandardBuilder() {}
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@ package org.pkl.core;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** An element of a Pkl stack trace. */ /** An element of a Pkl stack trace. */
// better name would be `StackTraceElement` // better name would be `StackTraceElement`
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@ package org.pkl.core;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** /**
* The results of testing a Pkl test module. * The results of testing a Pkl test module.
@@ -301,7 +301,7 @@ public record TestResults(
* @param message The message of the underlying exception. * @param message The message of the underlying exception.
* @param exception The exception thrown by Pkl * @param exception The exception thrown by Pkl
*/ */
public record Error(String message, PklException exception) {} public record Error(@Nullable String message, PklException exception) {}
/** /**
* Indicates that an assertion failed. * Indicates that an assertion failed.

Some files were not shown because too many files have changed in this diff Show More