Compare commits

..

103 Commits

Author SHA1 Message Date
Jen Basch efc9e2c819 Prepare 0.31.1 release 2026-03-26 09:08:16 -07:00
Jen Basch a9544ebbaf Add 0.31.1 changelog (#1473)
Closes #1472

Co-authored-by: Islon Scherer <i_desouzascherer@apple.com>
2026-03-26 09:02:12 -07:00
Islon Scherer 0eb619b387 Disable gradle cache for release builds (#1474) 2026-03-26 09:01:52 -07:00
Jen Basch 2c74108a6a Do not activate power assertions when a single union member containing a type constraint fails (#1462)
Prior to this change, this code would activate powers assertions /
instrumentation permanently:
```pkl
foo: String(contains("a")) | String(contains("b")) = "boo"
```

This is because the `contains("a")` constraint would fail, triggering
power assertions, but the subsequent check of the union's
`contains("b")` branch would succeed.
As observed in #1419, once instrumentation is enabled, all subsequent
evaluation slows significantly.
As with #1419, the fix here is to disable power assertions via
`VmLocalContext` until we know that all union members failed type
checking; then, each member is re-executed with power assertions allowed
to provide the improved user-facing error.
2026-03-25 12:13:21 -07:00
Jen Basch bd914f266a Prevent --multiple-file-output-path writes from following symlinks outside the target directory (#1467) 2026-03-25 12:13:13 -07:00
Jen Basch c069fb9611 Prevent I/O when checking UNC paths against --root-dir (#1466)
Test on [windows] please
2026-03-25 12:12:36 -07:00
Jen Basch b1fa8bea32 Allow custom/external resources to be "not found" (#1471)
This allows custom/external resources to produce `null` values for
nullable reads (`read?`)

Ref: https://github.com/apple/pkl-go/issues/157
2026-03-25 12:12:31 -07:00
Jen Basch 3bdadb0bcd Correct SecurityManager check for HTTP(S) module URIs (#1463) 2026-03-25 12:12:24 -07:00
Jen Basch 4f33a7e521 Fix module reflection when instrumentation is active (#1464) 2026-03-25 12:12:15 -07:00
dependabot[bot] 51dc0dc14d Bump actions/create-github-app-token from 2.2.1 to 2.2.2 (#1469) 2026-03-25 12:12:01 -07:00
Jen Basch 3a91a51c5f Bump pkl.impl.ghactions to version 1.5.0 (#1460) 2026-03-25 12:11:54 -07:00
Jen Basch c4c0325268 Respect --omit-project-settings for all evaluator options (#1459) 2026-03-25 12:11:47 -07:00
dependabot[bot] 58d0fc2e05 Bump gradle/actions from 5.0.1 to 5.0.2 (#1456) 2026-03-25 12:11:26 -07:00
Kushal Pisavadia 0f054d5c10 Fix command typealias unwrapping in resolveType (#1449)
The loop unwraps nullables and constraints but breaks straight away
after a `typealias`. This means the nullable is missed. Removing the
`break` fixes it.

## Exception

```
org.pkl.core.PklException: –– Pkl Error ––
Command option property `foo` has unsupported type `String?`.

11 | foo: OptionalString
     ^^^^^^^^^^^^^^^^^^^
at <unknown> (file:///var/folders/xh/lmp1n6qj4m13t53cfmbqnkwh0000gn/T/junit-1378070630576324311/cmd.pkl)

Use a supported type or define a transformEach and/or transformAll function
```
2026-03-25 12:11:07 -07:00
Kushal Pisavadia 9315b8410d Fix stream double-consumption in CommandSpecParser (#1448)
The `choices` stream was consumed eagerly for metavar construction, then
captured in a lambda for later validation—which promptly fell over with
`IllegalStateException`. Materialise to a `List` straightaway.
2026-03-25 12:10:57 -07:00
layla 853ac26e44 Fix typo: recieve to receive (#1455) 2026-03-02 09:44:58 -08:00
Jen Basch 40ee6c6124 Fix typo in 0.31 release notes (#1450) 2026-02-27 13:18:36 -08:00
Jen Basch e8ecc17709 Fix 0.31 release date in changelog 2026-02-26 11:09:54 -08:00
Islon Scherer 2904b719bb Prepare 0.31.0 release 2026-02-26 18:13:41 +01:00
Jen Basch 4cf2a1b42c Allow command options to have nullable types and default values (#1444) 2026-02-26 08:34:46 -08:00
Jen Basch 3ef065b6b6 Correct --root-dir check to also work for jar:file: URIs (#1442) 2026-02-25 10:57:01 -08:00
Jen Basch be21c34938 Allow command transformAll functions to perform imports (#1440) 2026-02-25 08:03:53 -08:00
Jen Basch 2e4d73b957 Fix regression in CLI error handling when project loading fails (#1439) 2026-02-25 01:28:05 -08:00
Jen Basch 28b09134d7 Add release notes for 0.31 (#1438) 2026-02-24 08:56:16 -08:00
Jen Basch 4611d181a8 Remove broken Collection.transpose method (#1437) 2026-02-24 08:09:52 -08:00
Jen Basch 12915f520f Fix command error and import handling (#1436) 2026-02-24 08:09:25 -08:00
Jen Basch 2ec0baad53 Allow referring to remote project dependencies on the CLI with @-notation (#1434) 2026-02-23 08:52:56 -08:00
dependabot[bot] 77395a86f4 Bump EnricoMi/publish-unit-test-result-action from 2.22.0 to 2.23.0 (#1435) 2026-02-23 08:51:04 -08:00
Jen Basch a5dc91f0a5 Command flag behavior improvements (#1432)
* Forbid overlap of built-in and command-defined flag names 
* Allow interleaving built-in and command-defined flags on the command
line
* List abbreviated flag names first, matching the behavior of built-in
flags
2026-02-20 12:00:18 -08:00
Jen Basch 08712e8b26 Fix display of evaluation errors thrown by command convert/transformAll (#1431) 2026-02-20 07:51:33 -08:00
Jen Basch e07868b404 Handle lexer errors in pkl format (#1430)
Resolves #1421
2026-02-19 10:00:00 -08:00
Jen Basch 72a57af164 SPICE-0025: pkl run CLI framework (#1367) 2026-02-12 07:53:02 -08:00
Jen Basch 63a20dd453 Improve org.pkl.formatter.Formatter JVM API (#1428)
Makes for less fussing around to consume this API from the Gradle side
2026-02-11 09:22:42 -08:00
Islon Scherer 60f628eb36 Fix possible race condition during module and resource reading (#1426) 2026-02-11 11:18:11 +01:00
Jen Basch 817e433a7f Document annotations and annotation converters (#1427) 2026-02-09 10:19:47 -08:00
Islon Scherer 08d8c8ec7a Improve import formatting (#1424) 2026-02-06 17:57:50 +01:00
Jen Basch effa4844e6 Bump pkl.impl.ghactions to version 1.3.5 (#1422) 2026-02-06 08:43:45 -08:00
Islon Scherer f0449c8330 Add flag to turn power assertions on/off (#1419) 2026-02-03 09:35:16 +01:00
dependabot[bot] 7b7b51c0ae Bump gradle/actions from 5.0.0 to 5.0.1 (#1420)
Bumps [gradle/actions](https://github.com/gradle/actions) from 5.0.0 to
5.0.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/gradle/actions/releases">gradle/actions's
releases</a>.</em></p>
<blockquote>
<h2>v5.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump <code>npm</code> code dependency versions</li>
<li>Bump Gradle versions used in sample builds</li>
<li>Bump dependencies versions in Gradle sample builds</li>
<li>Bump GitHub actions used for build and test</li>
<li>Update known wrapper checksums to include Gradle 9.2+</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/gradle/actions/compare/v5.0.0...v5.0.1">https://github.com/gradle/actions/compare/v5.0.0...v5.0.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/gradle/actions/commit/f29f5a9d7b09a7c6b29859002d29d24e1674c884"><code>f29f5a9</code></a>
Attempt to fix flaky caching tests (<a
href="https://redirect.github.com/gradle/actions/issues/836">#836</a>)</li>
<li><a
href="https://github.com/gradle/actions/commit/8c7f3ffba4042e38a9b017ec1433452e674e4403"><code>8c7f3ff</code></a>
Bump to v1.4.1 of the dependency-submission plugin</li>
<li><a
href="https://github.com/gradle/actions/commit/85e9805d21cf3b1d1c54c470ae15083df20e00ed"><code>85e9805</code></a>
[bot] Update dist directory</li>
<li><a
href="https://github.com/gradle/actions/commit/acb81f1e15dbc4ea06da2aa52ac9a056747ba8cf"><code>acb81f1</code></a>
Bump the npm-dependencies group across 1 directory with 8 updates (<a
href="https://redirect.github.com/gradle/actions/issues/821">#821</a>)</li>
<li><a
href="https://github.com/gradle/actions/commit/00660c8721edeac5845b81ab1a2d47af4de1e150"><code>00660c8</code></a>
Bump github/codeql-action from 4.31.10 to 4.32.0 in the github-actions
group ...</li>
<li><a
href="https://github.com/gradle/actions/commit/d498ad3b5f3030c0feb2913ae7059605e5d4de40"><code>d498ad3</code></a>
[bot] Update dist directory</li>
<li><a
href="https://github.com/gradle/actions/commit/de83f3396312260c9a3dfc1d77ee4b6f2361eb9a"><code>de83f33</code></a>
Update Gradle version and Gradle dependencies (<a
href="https://redirect.github.com/gradle/actions/issues/834">#834</a>)</li>
<li><a
href="https://github.com/gradle/actions/commit/baabf402fa7896574cf6caf18668d5509e3ce8ef"><code>baabf40</code></a>
Bump the github-actions group across 2 directories with 5 updates</li>
<li><a
href="https://github.com/gradle/actions/commit/69353a9e141a8a7865bcbf48a099ad644e9adf2f"><code>69353a9</code></a>
Bump the gradle group across 1 directory with 4 updates</li>
<li><a
href="https://github.com/gradle/actions/commit/221c7f4dbd2468936638e2ba4fe1d987ce3bbe0d"><code>221c7f4</code></a>
Update known wrapper checksums</li>
<li>Additional commits viewable in <a
href="https://github.com/gradle/actions/compare/4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2...f29f5a9d7b09a7c6b29859002d29d24e1674c884">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=gradle/actions&package-manager=github_actions&previous-version=5.0.0&new-version=5.0.1)](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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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-02-02 09:39:13 -08:00
dependabot[bot] a2bfbd72a7 Bump actions/checkout from 6.0.1 to 6.0.2 (#1417) 2026-01-26 09:04:22 -08:00
dependabot[bot] 11b65e4d7a Bump actions/setup-java from 5.1.0 to 5.2.0 (#1416) 2026-01-26 08:55:53 -08:00
Jen Basch 73264e8fd1 SPICE-0024: Annotation converters (#1333)
This enables defining declarative key and/or value transformations in
cases where neither `Class`- nor path-based converters can be applied
gracefully. It is also the only way to express transforming the
resulting property names in `Typed` objects without applying a converter
to the entire containing type, which is cumbersome at best.

SPICE: https://github.com/apple/pkl-evolution/pull/26
2026-01-23 12:44:41 -08:00
Daniel Chao ed0cad668f Fix Function.toString (#1411)
Fixes an issue where the underlying default Java toString() is leaking
through
2026-01-21 07:29:58 -08:00
Daniel Chao 03a7676e64 Implement power assertions (#1384)
This adds power assertions to Pkl!

This implements the SPICE described in
https://github.com/apple/pkl-evolution/pull/29

This follows the power assertions style of reporting also found in
Groovy, Kotlin, and others.

* Literal values are not emitted in the diagram
* Stdlib constructors of literals like `List(1, 2)` are also considered
  literals

Power assertions are added to:

* Failing type constraints
* Failing test facts

Power assertions are implemented as a truffle instrument to observe
execution.
When an assertion fails, the instrument is created and the assertion is
run again to observe facts.
This incurs runtime overhead to collect facts, but has no impact on code
in the non-error case.

---------

Co-authored-by: Islon Scherer <islonscherer@gmail.com>
2026-01-20 21:41:33 -08:00
Daniel Chao 3cd294b62a Add 'let' to list of control keywords (#1409)
Small improvement to syntax highlighting
2026-01-19 20:00:21 -08:00
Jen Basch f6cfc82201 Bump pkl.impl.ghactions to version 1.3.3 (#1408)
Updates pkl.impl.ghactions package to version 1.3.3
2026-01-15 12:06:56 -08:00
Jen Basch fd66438828 Bump pkl.impl.ghactions to version 1.3.2 (#1403)
Updates pkl.impl.ghactions package to version 1.3.2
2026-01-12 18:01:46 -08:00
Daniel Chao b4bd292511 Handle IOException when creating PklProject.deps.json (#1405)
Fixes an issue that otherwise bubbles up as "An unexpected error has
occured".
2026-01-12 15:08:38 -08:00
Daniel Chao f1c71bc9bb Emit error stack trace on non Pkl exceptions (#1402)
If the thrown error is not a Pkl exception, some internal error
occurred, and we need to emit the stack trace for visibility.
2026-01-12 13:45:39 -08:00
Akshat Anand 9d385f2194 Fix super method call inside let expression (#1383)
Fixes #1309

The issue was that super calls were blocked inside let expressions
because:
1. The compiler's isClassMemberScope() check didn't skip over lambda
scopes created by let expressions
2. The runtime's findSupermethod() didn't traverse past VmFunction
owners to find the actual class prototype

Changes:
- SymbolTable.java: Updated isClassMemberScope() to skip lambda scopes
before checking if the parent is a class or module scope
- InvokeSuperMethodNode.java: Updated findSupermethod() to skip
VmFunction owners when looking for the class prototype

Added regression tests covering:
- Super method calls inside let expressions
- Super property access inside let expressions
- Nested let expressions with super calls

---------

Co-authored-by: Jen Basch <jbasch@apple.com>
2026-01-09 19:59:20 -08:00
Jen Basch 3595c03078 Fix spotless ratcheting on release branches (#1401) 2026-01-09 14:18:18 -08:00
Jen Basch 9b6f72d5d0 Fix doc links from pkl:base to pkl:math (#1400) 2026-01-09 11:30:56 -08:00
Daniel Chao ac4f2fd9a6 Add isNotEmpty, isNotBlank methods (#1396)
Adds convenience methods `isNotEmpty` and `isNotBlank`. This borrows the
same methods from Kotlin.

This helps users write more fluent constraints, for example,
`foo.isNotEmpty.implies(bar)`.

Adds:

* List#isNotEmpty
* Map#isNotEmpty
* Set#isNotEmpty
* Mapping#isNotEmpty
* Listing#isNotEmpty
* String#isNotEmpty
* String#isNotBlank
2026-01-08 13:22:43 -08:00
Daniel Chao 14d58a17b0 Address warning diagnostics (#1395)
This addressess various warning diagnostics throughout the codebase.
2026-01-07 22:11:24 -08:00
Daniel Chao 474305c7b9 Use gradle/actions/setup-gradle (#1397)
This adds the setup-gradle action; which has the following improvements:

* Improved cacheing (compared to setup-java's Gradle cache)
* Validates the gradle wrapper jar
2026-01-07 21:10:07 -08:00
Daniel Chao 6b9c670cfd Add syntax highlighting of Pkl code (#1385)
This adds syntax highlighting of Pkl code!

It adds highlighting for:

* Stack frames within error messages
* CLI REPL (highlights as you type, highlights error output)
* Power assertions (coming in https://github.com/apple/pkl/pull/1384)

This uses the lexer for highlighting. It will highlight strings,
numbers, keywords, but doesn't understand how to highlight nodes like
types, function params, etc.
The reason for this is because a single line of code by itself may not
be grammatically valid.
2026-01-06 10:33:11 -08:00
Daniel Chao 4f4f03dbca Fix cacheing of module type (#1393)
This fixes an issue where the `module` type is incorrectly cached.
2026-01-05 14:49:07 -08:00
Eduardo Aguilar Moreno 6cd03c7f56 Add pkl bom module (#1390)
This adds a module that will publish a bom file that will help consumers
align versions for all pkl artifacts using the single bom.
2026-01-05 14:47:28 -08:00
Daniel Chao 8f83885c75 Fix default value for non-final module type (#1392)
This fixes an issue where the `module` type produces the wrong default
value.

Closes #1391
2026-01-05 11:39:24 -08:00
Stefan M. 0a4281366f Do not throw if output dir is symlink (#1389) 2026-01-05 10:16:32 -08:00
dependabot[bot] 35861240a0 Bump EnricoMi/publish-unit-test-result-action from 2.21.0 to 2.22.0 (#1382)
Bumps
[EnricoMi/publish-unit-test-result-action](https://github.com/enricomi/publish-unit-test-result-action)
from 2.21.0 to 2.22.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/enricomi/publish-unit-test-result-action/releases">EnricoMi/publish-unit-test-result-action's
releases</a>.</em></p>
<blockquote>
<h2>v2.22.0</h2>
<p>Adds the following improvements:</p>
<ul>
<li>Upgrade all Python dependencies to latest version <a
href="https://redirect.github.com/enricomi/publish-unit-test-result-action/issues/710">#710</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/EnricoMi/publish-unit-test-result-action/compare/v2.21.0...v2.22.0">https://github.com/EnricoMi/publish-unit-test-result-action/compare/v2.21.0...v2.22.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/EnricoMi/publish-unit-test-result-action/commit/27d65e188ec43221b20d26de30f4892fad91df2f"><code>27d65e1</code></a>
Releasing v2.22.0</li>
<li><a
href="https://github.com/EnricoMi/publish-unit-test-result-action/commit/2deae407d71f83660c8129d55379ef777127b1bf"><code>2deae40</code></a>
Upgrade transient dependencies (<a
href="https://redirect.github.com/enricomi/publish-unit-test-result-action/issues/710">#710</a>)</li>
<li><a
href="https://github.com/EnricoMi/publish-unit-test-result-action/commit/a6d8f3d6cae9c3d19a7a97f61e44d5754b97d803"><code>a6d8f3d</code></a>
Add Ubuntu slim runner (<a
href="https://redirect.github.com/enricomi/publish-unit-test-result-action/issues/709">#709</a>)</li>
<li><a
href="https://github.com/EnricoMi/publish-unit-test-result-action/commit/d3ed9acf9b75c81bd3ed28fac2ef38e7631afd0b"><code>d3ed9ac</code></a>
CI: Merge check upgrades jobs into single job (<a
href="https://redirect.github.com/enricomi/publish-unit-test-result-action/issues/700">#700</a>)</li>
<li>See full diff in <a
href="https://github.com/enricomi/publish-unit-test-result-action/compare/34d7c956a59aed1bfebf31df77b8de55db9bbaaf...27d65e188ec43221b20d26de30f4892fad91df2f">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=EnricoMi/publish-unit-test-result-action&package-manager=github_actions&previous-version=2.21.0&new-version=2.22.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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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>
2025-12-22 09:34:57 -08:00
Daniel Chao 3f4e894e43 Import release notes from 0.30.2 (#1375) 2025-12-15 13:14:18 -08:00
Daniel Chao dcf3f24e3b Sort list of repos alphabetically (#1376) 2025-12-15 12:48:26 -08:00
Daniel Chao 6614cf11fb Add highlight.js and pkl-readers repo entries to README (#1371)
Co-authored-by: Jen Basch <jbasch94@gmail.com>
2025-12-15 11:28:30 -08:00
Daniel Chao b92c773555 Bump pkl.impl.ghactions (#1366) 2025-12-12 11:30:47 -08:00
Daniel Chao f528927797 Fix building of pkl-doc (#1365)
Ensure that `assembleNative` is called before testing the native
executable
2025-12-12 09:36:38 -08:00
Islon Scherer 41cf485ffb Fix bug in parsing of super expression (#1364) 2025-12-12 18:02:48 +01:00
Daniel Chao cd9cfaae8f Bump pkl.impl.ghactions, update lockfile to not run (#1362) 2025-12-10 21:39:18 -08:00
Daniel Chao 2578703081 Bump versions, fix dependabot updates (#1361) 2025-12-10 18:03:32 -08:00
Daniel Chao b170968e9e Bump pkl.impl.ghactions to 1.1.0, add version locking. (#1359)
This adopts the version locking introduced in pkl.impl.ghactions@1.1.0.
2025-12-10 16:35:15 -08:00
Daniel Chao 32e9087da9 Fix formatting of nodes with no children (#1351)
For example, this fixes an issue where an empty module turns into ` \n`.

Closes https://github.com/apple/pkl/issues/1348

---------

Co-authored-by: Jen Basch <jbasch94@gmail.com>
2025-12-09 11:03:50 -08:00
Daniel Chao 9d41518553 Bump pkl.impl.ghactions to 1.0.1 (#1358) 2025-12-09 10:53:04 -08:00
Daniel Chao b7ccc67bd8 Adjust CI to not publish test results for deploy-snapshot (#1357) 2025-12-08 09:56:57 -08:00
Daniel Chao 252f44728e Adjust native lifecycle builds to not throw during configuration phase (#1356)
Allow Gradle to run other tasks on unsupported machines, but throw when
running native lifecycle tasks (e.g. `buildNative`).
2025-12-07 11:35:14 -08:00
Jen Basch 139f70bb79 Change pkl format --write to exit 0 when formatting violations are found (#1340) 2025-12-05 16:01:09 -08:00
Daniel Chao 2de1d5b9d2 Build linux executables that link to glibc 2.17 (#1352)
Fixes an unintentional breakage in 0.30.1 that bumped the required glibc to 2.34.
2025-12-05 15:24:27 -08:00
Jen Basch 81a4e687b4 Fix IDEA gradle project sync on Windows Aarch64 (#1353) 2025-12-05 14:53:06 -08:00
Daniel Chao e1559c66ad Fix CI build for pkldoc (#1349)
Fixes an issue where the executable is not built.

Haven't dug into why this broke; this was working just a little bit ago
(see
https://github.com/apple/pkl/actions/runs/19911073549/job/57079605641?pr=1342).
Nevertheless, the lifecycle job dependencies were a little wonky (test
should assemble first).

[native-pkl-doc]
2025-12-05 09:54:57 -08:00
Daniel Chao c2d672e943 Omit superfluous newline when writing formatted content to stdout (#1350)
Fixes an issue where an extra newline is added when writing formatted
code to stdout.

Closes https://github.com/apple/pkl/issues/1346
2025-12-05 09:54:31 -08:00
Jen Basch 1d94ab5c3c Prepare 0.30.1 release (#1345) 2025-12-03 21:13:36 -08:00
Jen Basch c73fc87583 Fix release publishing (#1343) 2025-12-03 15:13:31 -08:00
Daniel Chao bcbe1b8995 Fix testing of pkldoc executables (#1342)
These tests are actually not running right now.
2025-12-03 15:12:08 -08:00
Daniel Chao c5b98d6510 CI job polish (#1341)
Avoids issues where setup-java post-task cacheing will hang with "device
or resource busy".
2025-12-03 15:11:33 -08:00
Jen Basch db6ff394d7 Fix fetch depth for gradle-compatibility and java-executables-* CI jobs (#1339) 2025-12-03 10:34:03 -08:00
Daniel Chao 53f3be64f3 Fix parsing of URLs with plus signs (#1335)
This fixes an issue where URLs with schemes that contain `+`, `-`, and
`.` would not be parsed correctly.

For example, `foo+bar:///?baz.pkl` would turn into
`foo+bar:///%3Fbaz.pkl`. The query param is lost, and turned into the
path.
2025-12-03 10:11:23 -08:00
Jen Basch d1c652f736 Vendor paguro's RrbTree, fix an int overflow breaking large Lists (#1337) 2025-12-03 09:02:17 -08:00
Islon Scherer 6c3683c55e Fix snapshot publishing (#1330) 2025-11-26 09:17:14 +01:00
Spencer Phillip Young cc02b6b685 Fix newline checks in parser (#1328) 2025-11-24 14:40:54 +01:00
Jen Basch f4938dccca Add support for evaluating module output and expressions to ConfigEvaluator (#1297) 2025-11-19 15:47:12 -08:00
Jen Basch 67f1ff5ab8 Update CLI docs to clarify that --version only applies to the root command (#1326) 2025-11-18 21:08:03 -08:00
Spencer Phillip Young ba281e8475 Fix empty parenthesized type unexpected error (#1323) 2025-11-18 15:35:44 +01:00
Daniel Chao bc5d675b6e Fix macos/amd64 image builds (#1322) 2025-11-17 12:16:28 -08:00
Daniel Chao a2cc70ae37 Fix deploy jobs (#1319)
Specify `merge-multiple` to prevent new directories from being created
when downloading artifacts.
2025-11-15 16:30:51 -08:00
Daniel Chao 0ff99d31c9 Replace broken references to CircleCI (#1318) 2025-11-14 15:44:59 -08:00
Daniel Chao ef9b53be98 Fix release builds (#1317)
In order to preserve the folder hierarchy in our uploaded artifact,
we need to insert a wildcard in the root path.

Also, fix fan-in of tasks that lead to the publish test result task.
2025-11-14 15:18:30 -08:00
Daniel Chao 0ff9125062 Fix build java executable (#1316) 2025-11-13 17:46:35 -08:00
Daniel Chao f948ba2a20 Switch to GitHub Actions (#1315)
This switches our builds over to GitHub Actions!

TODO:

* Add macOS/amd64 native-image builds; this isn't working right now
* Patch musl with security patches
* Add benchmark jobs over time

As part of this build, PRBs will now only run `./gradlew check` on Linux,
but other jobs can be run using slash commands, e.g. `[windows]`
to run `./gradle check` on Windows.
2025-11-13 16:03:05 -08:00
Islon Scherer ecf2d8ba33 Fix Map formatting (#1312) 2025-11-11 09:37:09 +01:00
Daniel Chao 445d94ccff Improve plugin logic (#1296) 2025-11-04 07:33:54 -08:00
Daniel Chao 9e1303ed57 Disable spotless ratcheting of Pkl sources (#1295)
This causes spotless to _always_ format Pkl files, instead of only
formatting them if there's a diff between the file and what's in main.

This means that formatting changes in pkl-formatter will be propagated
to the standard library.
2025-11-04 05:31:49 -08:00
Dan Chao 4c13952b64 Apply spotless formatting 2025-11-03 12:26:58 -08:00
Dan Chao 4d70baba86 Start next dev iteration 2025-11-03 12:26:58 -08:00
Dan Chao 7f231cd916 Prepare 0.30.0 release 2025-11-03 12:26:58 -08:00
393 changed files with 12513 additions and 2207 deletions
+2 -2
View File
@@ -2,9 +2,9 @@ amends "pkl:Project"
dependencies { dependencies {
["pkl.impl.ghactions"] { ["pkl.impl.ghactions"] {
uri = "package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@0.7.1" uri = "package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@1.5.0"
} }
["gha"] { ["gha"] {
uri = "package://pkg.pkl-lang.org/github.com/stefma/pkl-gha/com.github.action@0.0.6" uri = "package://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1.2.0"
} }
} }
+27 -6
View File
@@ -1,18 +1,39 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"resolvedDependencies": { "resolvedDependencies": {
"package://pkg.pkl-lang.org/github.com/stefma/pkl-gha/com.github.action@0": { "package://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1": {
"type": "remote", "type": "remote",
"uri": "projectpackage://pkg.pkl-lang.org/github.com/stefma/pkl-gha/com.github.action@0.0.6", "uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1.3.1",
"checksums": { "checksums": {
"sha256": "84365239996740252a91abab084d443aa3a3438f375b667ac16cb765461c1555" "sha256": "fd515da685ea126678c3ec684e84a4f992d43481cc1d75cb866cd55775f675f9"
} }
}, },
"package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@0": { "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@0.7.1", "uri": "projectpackage://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@1.5.0",
"checksums": { "checksums": {
"sha256": "f8efc4b174855a2fafdab8ed792de4b0cb89b0516d688c8540eea13af20e0f80" "sha256": "2c1e0d9efcd65b3c3207bf535c325ebc0ec2ab169187b324c4bb70821cac0e51"
}
},
"package://pkg.pkl-lang.org/pkl-pantry/pkl.experimental.deepToTyped@1": {
"type": "remote",
"uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/pkl.experimental.deepToTyped@1.2.0",
"checksums": {
"sha256": "84c7feb391f4ac273a99dc89b8fd51dbcd21dbda4ce640f6908527f83acdd4d6"
}
},
"package://pkg.pkl-lang.org/pkl-pantry/pkl.github.dependabotManagedActions@1": {
"type": "remote",
"uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/pkl.github.dependabotManagedActions@1.0.3",
"checksums": {
"sha256": "d368900942efb88ed51a98f9614748b06c74ba43423f045fcd6dedb5dbdc0bea"
}
},
"package://pkg.pkl-lang.org/pkl-pantry/com.github.dependabot@1": {
"type": "remote",
"uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/com.github.dependabot@1.0.0",
"checksums": {
"sha256": "02ef6f25bfca5b1d095db73ea15de79d2d2c6832ebcab61e6aba90554382abcb"
} }
} }
} }
+10
View File
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
ignore:
- dependency-name: '*'
update-types:
- version-update:semver-major
schedule:
interval: weekly
+1 -25
View File
@@ -21,8 +21,8 @@ testReports {
} }
excludeJobs { excludeJobs {
"bench" "bench"
"deploy-release"
"github-release" "github-release"
Regex("deploy-.*")
} }
} }
@@ -196,27 +196,3 @@ release {
} }
} |> toWorkflowJobs } |> toWorkflowJobs
} }
output {
files {
[[true]] {
renderer {
converters {
["jobs"] = (it: Mapping<String, Workflow.Job>) ->
it
.toMap()
.mapValues((name, job) ->
if (name.contains("linux") && !name.contains("alpine"))
job
.toMap()
.put("container", new Dynamic {
image = "redhat/ubi8:8.10"
})
else
job
)
}
}
}
}
}
+3 -4
View File
@@ -1,7 +1,6 @@
extends "GradleJob.pkl" extends "GradleJob.pkl"
import "@gha/actions/Artifact.pkl" import "@gha/catalog.pkl"
import "@gha/actions/Common.pkl"
// Keep this in sync with projects that build java executables // Keep this in sync with projects that build java executables
local projects: List<String> = List("pkl-doc", "pkl-cli", "pkl-codegen-java", "pkl-codegen-kotlin") local projects: List<String> = List("pkl-doc", "pkl-cli", "pkl-codegen-java", "pkl-codegen-kotlin")
@@ -17,13 +16,13 @@ local command =
}.join(" ") }.join(" ")
steps { steps {
new Common.Checkout {} catalog.`actions/checkout@v6`
new { new {
name = "gradle build java executables" name = "gradle build java executables"
shell = "bash" shell = "bash"
run = command run = command
} }
new Artifact.Upload { (catalog.`actions/upload-artifact@v5`) {
name = "Upload executable artifacts" name = "Upload executable artifacts"
with { with {
name = "executable-java" name = "executable-java"
+13 -5
View File
@@ -1,7 +1,7 @@
extends "GradleJob.pkl" extends "GradleJob.pkl"
import "@gha/actions/Artifact.pkl" import "@gha/catalog.pkl"
import "@gha/Context.pkl" import "@gha/context.pkl"
/// Whether to link to musl. Otherwise, links to glibc. /// Whether to link to musl. Otherwise, links to glibc.
musl: Boolean(implies(module.os == "linux")) = false musl: Boolean(implies(module.os == "linux")) = false
@@ -12,7 +12,7 @@ project: String
extraGradleArgs { extraGradleArgs {
when (os == "macOS" && arch == "amd64") { when (os == "macOS" && arch == "amd64") {
"-Dpkl.targetArch=\(module.arch)" "-Dpkl.targetArch=\(module.arch)"
"-Dpkl.native--native-compiler-path=\(Context.github.workspace)/.github/scripts/cc_macos_amd64.sh" #""-Dpkl.native--native-compiler-path=${GITHUB_WORKSPACE}/.github/scripts/cc_macos_amd64.sh""#
} }
when (musl) { when (musl) {
"-Dpkl.musl=true" "-Dpkl.musl=true"
@@ -40,7 +40,7 @@ steps {
new { new {
name = "Fix git ownership" name = "Fix git ownership"
// language=bash // language=bash
run = "git status || git config --system --add safe.directory $GITHUB_WORKSPACE" run = #"git status || git config --system --add safe.directory "$GITHUB_WORKSPACE""#
} }
} }
new { new {
@@ -48,7 +48,7 @@ steps {
shell = "bash" shell = "bash"
run = "./gradlew \(module.gradleArgs) \(project):buildNative" run = "./gradlew \(module.gradleArgs) \(project):buildNative"
} }
new Artifact.Upload { (catalog.`actions/upload-artifact@v5`) {
name = "Upload executable artifacts" name = "Upload executable artifacts"
with { with {
name = name =
@@ -62,3 +62,11 @@ steps {
} }
} }
} }
fixed job {
when (os == "linux" && !musl) {
container {
image = "redhat/ubi8:8.10"
}
}
}
+3 -4
View File
@@ -1,7 +1,6 @@
extends "GradleJob.pkl" extends "GradleJob.pkl"
import "@gha/actions/Artifact.pkl" import "@gha/catalog.pkl"
import "@gha/actions/Common.pkl"
import "@gha/Workflow.pkl" import "@gha/Workflow.pkl"
import "@pkl.impl.ghactions/helpers.pkl" import "@pkl.impl.ghactions/helpers.pkl"
@@ -14,8 +13,8 @@ arch = "amd64"
os = "linux" os = "linux"
steps { steps {
new Common.Checkout {} catalog.`actions/checkout@v6`
new Artifact.Download { (catalog.`actions/download-artifact@v6`) {
with { with {
pattern = "executable-**" pattern = "executable-**"
`merge-multiple` = true `merge-multiple` = true
+7 -7
View File
@@ -2,8 +2,8 @@ module GithubRelease
extends "PklJob.pkl" extends "PklJob.pkl"
import "@gha/actions/Artifact.pkl" import "@gha/catalog.pkl"
import "@gha/Context.pkl" import "@gha/context.pkl"
fixed job { fixed job {
`runs-on` = "ubuntu-latest" `runs-on` = "ubuntu-latest"
@@ -12,7 +12,7 @@ fixed job {
} }
needs = "deploy-release" needs = "deploy-release"
steps { steps {
new Artifact.Download { (catalog.`actions/download-artifact@v6`) {
with { with {
pattern = "executable-**" pattern = "executable-**"
`merge-multiple` = true `merge-multiple` = true
@@ -21,10 +21,10 @@ fixed job {
new { new {
name = "Publish release on GitHub" name = "Publish release on GitHub"
env { env {
["GH_TOKEN"] = Context.github.token ["GH_TOKEN"] = context.github.token
["TAG_NAME"] = Context.github.refName ["TAG_NAME"] = context.github.refName
["GIT_SHA"] = Context.github.sha ["GIT_SHA"] = context.github.sha
["GH_REPO"] = Context.github.repository ["GH_REPO"] = context.github.repository
} }
// language=bash // language=bash
run = run =
+12 -7
View File
@@ -2,9 +2,8 @@ abstract module GradleJob
extends "PklJob.pkl" extends "PklJob.pkl"
import "@gha/actions/Common.pkl"
import "@gha/actions/Setup.pkl"
import "@gha/Workflow.pkl" import "@gha/Workflow.pkl"
import "@pkl.impl.ghactions/catalog.pkl"
/// Whether this is a release build or not. /// Whether this is a release build or not.
isRelease: Boolean = false isRelease: Boolean = false
@@ -21,9 +20,9 @@ nightlyMacOS: Boolean(implies(os == "macOS")) = false
extraGradleArgs: Listing<String> extraGradleArgs: Listing<String>
steps: Listing<*Workflow.Step | Workflow.TypedStep> steps: Listing<Workflow.Step>
preSteps: Listing<*Workflow.Step | Workflow.TypedStep> preSteps: Listing<Workflow.Step>
/// The fetch depth to use when doing a git checkout. /// The fetch depth to use when doing a git checkout.
fetchDepth: Int? fetchDepth: Int?
@@ -73,18 +72,17 @@ fixed job {
steps { steps {
...preSteps ...preSteps
// full checkout (needed for spotless) // full checkout (needed for spotless)
new Common.Checkout { (catalog.`actions/checkout@v6`) {
when (fetchDepth != null) { when (fetchDepth != null) {
with { with {
`fetch-depth` = fetchDepth `fetch-depth` = fetchDepth
} }
} }
} }
new Setup.Java { (catalog.`actions/setup-java@v5`) {
with { with {
`java-version` = "21" `java-version` = "21"
distribution = "temurin" distribution = "temurin"
cache = "gradle"
architecture = architecture =
if (arch == "amd64") if (arch == "amd64")
"x64" "x64"
@@ -92,6 +90,13 @@ fixed job {
"aarch64" "aarch64"
} }
} }
(catalog.`gradle/actions/setup-gradle@v5`) {
when (isRelease) {
with {
`cache-disabled` = true
}
}
}
...module.steps ...module.steps
} }
} }
+34
View File
@@ -0,0 +1,34 @@
#file: noinspection MandatoryParamsAbsent,UndefinedAction
# This is a fake workflow that never runs.
# It's used to pin actions to specific git SHAs when generating actual workflows.
# It also gets updated by dependabot (see .github/dependabot.yml).
# Generated from Workflow.pkl. DO NOT EDIT.
name: __lockfile__
'on':
push:
branches-ignore:
- '**'
tags-ignore:
- '**'
permissions: {}
jobs:
locks:
if: 'false'
runs-on: nothing
steps:
- name: EnricoMi/publish-unit-test-result-action@v2
uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
- name: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: actions/create-github-app-token@v2
uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
- name: actions/download-artifact@v6
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
- name: actions/setup-java@v5
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
- name: actions/upload-artifact@v5
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
- name: dawidd6/action-download-artifact@v11
uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11
- name: gradle/actions/setup-gradle@v5
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
+158 -110
View File
@@ -1,12 +1,11 @@
# Do not modify! # Generated from Workflow.pkl. DO NOT EDIT.
# This file was generated from a template using https://github.com/StefMa/pkl-gha
name: Build name: Build
'on': 'on':
push: push:
branches-ignore: branches-ignore:
- main - main
- release/* - release/*
- dependabot/**
tags-ignore: tags-ignore:
- '**' - '**'
concurrency: concurrency:
@@ -20,27 +19,29 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-check name: test-results-xml-gradle-check
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-check name: test-results-html-gradle-check
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -51,27 +52,29 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-check-windows name: test-results-xml-gradle-check-windows
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-check-windows name: test-results-html-gradle-check-windows
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -81,13 +84,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: bench:jmh - name: bench:jmh
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh
@@ -96,27 +102,29 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --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@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-compatibility name: test-results-xml-gradle-compatibility
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-compatibility name: test-results-html-gradle-compatibility
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -126,33 +134,37 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
- uses: actions/checkout@v5 with: {}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
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 --info --stacktrace --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@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-java name: executable-java
path: '*/build/executable/**/*' path: '*/build/executable/**/*'
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-java-executables-snapshot name: test-results-xml-java-executables-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-java-executables-snapshot name: test-results-html-java-executables-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -165,30 +177,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --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
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-macOS-amd64 name: executable-pkl-cli-macOS-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-macOS-amd64-snapshot name: test-results-xml-pkl-cli-macOS-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-macOS-amd64-snapshot name: test-results-html-pkl-cli-macOS-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -200,32 +215,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-linux-amd64 name: executable-pkl-cli-linux-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-linux-amd64-snapshot name: test-results-xml-pkl-cli-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-linux-amd64-snapshot name: test-results-html-pkl-cli-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -240,30 +258,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-macOS-aarch64 name: executable-pkl-cli-macOS-aarch64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-macOS-aarch64-snapshot name: test-results-xml-pkl-cli-macOS-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-macOS-aarch64-snapshot name: test-results-html-pkl-cli-macOS-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -275,32 +296,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-linux-aarch64 name: executable-pkl-cli-linux-aarch64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-linux-aarch64-snapshot name: test-results-xml-pkl-cli-linux-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-linux-aarch64-snapshot name: test-results-html-pkl-cli-linux-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -312,13 +336,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -396,19 +423,19 @@ jobs:
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-alpine-linux-amd64 name: executable-pkl-cli-alpine-linux-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-alpine-linux-amd64-snapshot name: test-results-xml-pkl-cli-alpine-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-alpine-linux-amd64-snapshot name: test-results-html-pkl-cli-alpine-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -419,30 +446,33 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-windows-amd64 name: executable-pkl-cli-windows-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-windows-amd64-snapshot name: test-results-xml-pkl-cli-windows-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-windows-amd64-snapshot name: test-results-html-pkl-cli-windows-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -455,30 +485,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --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
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-macOS-amd64 name: executable-pkl-doc-macOS-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-macOS-amd64-snapshot name: test-results-xml-pkl-doc-macOS-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-macOS-amd64-snapshot name: test-results-html-pkl-doc-macOS-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -490,32 +523,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-linux-amd64 name: executable-pkl-doc-linux-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-linux-amd64-snapshot name: test-results-xml-pkl-doc-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-linux-amd64-snapshot name: test-results-html-pkl-doc-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -530,30 +566,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-macOS-aarch64 name: executable-pkl-doc-macOS-aarch64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-macOS-aarch64-snapshot name: test-results-xml-pkl-doc-macOS-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-macOS-aarch64-snapshot name: test-results-html-pkl-doc-macOS-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -565,32 +604,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-linux-aarch64 name: executable-pkl-doc-linux-aarch64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-linux-aarch64-snapshot name: test-results-xml-pkl-doc-linux-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-linux-aarch64-snapshot name: test-results-html-pkl-doc-linux-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -602,13 +644,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -686,19 +731,19 @@ jobs:
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-alpine-linux-amd64 name: executable-pkl-doc-alpine-linux-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-alpine-linux-amd64-snapshot name: test-results-xml-pkl-doc-alpine-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-alpine-linux-amd64-snapshot name: test-results-html-pkl-doc-alpine-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -709,36 +754,39 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-windows-amd64 name: executable-pkl-doc-windows-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-windows-amd64-snapshot name: test-results-xml-pkl-doc-windows-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-windows-amd64-snapshot name: test-results-html-pkl-doc-windows-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
if-no-files-found: ignore if-no-files-found: ignore
publish-test-results: publish-test-results:
if: '!failure() && !cancelled()' if: '!cancelled()'
needs: needs:
- gradle-check - gradle-check
- gradle-check-windows - gradle-check-windows
@@ -760,18 +808,18 @@ jobs:
checks: write checks: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/download-artifact@v6 - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with: with:
pattern: test-results-xml-* pattern: test-results-xml-*
- name: Publish test results - name: Publish test results
if: '!cancelled()' if: '!cancelled()'
uses: EnricoMi/publish-unit-test-result-action@v2 uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
with: with:
comment_mode: 'off' comment_mode: 'off'
files: test-results-xml-*/**/*.xml files: test-results-xml-*/**/*.xml
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-publish-test-results name: test-results-html-publish-test-results
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
+170 -131
View File
@@ -1,6 +1,4 @@
# Do not modify! # Generated from Workflow.pkl. DO NOT EDIT.
# This file was generated from a template using https://github.com/StefMa/pkl-gha
name: Build (main) name: Build (main)
'on': 'on':
push: push:
@@ -19,27 +17,29 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-check name: test-results-xml-gradle-check
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-check name: test-results-html-gradle-check
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -50,27 +50,29 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-check-windows name: test-results-xml-gradle-check-windows
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-check-windows name: test-results-html-gradle-check-windows
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -80,13 +82,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: bench:jmh - name: bench:jmh
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh
@@ -95,27 +100,29 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --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@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-compatibility name: test-results-xml-gradle-compatibility
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-compatibility name: test-results-html-gradle-compatibility
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -125,33 +132,37 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
- uses: actions/checkout@v5 with: {}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
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 --info --stacktrace --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@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-java name: executable-java
path: '*/build/executable/**/*' path: '*/build/executable/**/*'
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-java-executables-snapshot name: test-results-xml-java-executables-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-java-executables-snapshot name: test-results-html-java-executables-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -164,30 +175,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --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
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-macOS-amd64 name: executable-pkl-cli-macOS-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-macOS-amd64-snapshot name: test-results-xml-pkl-cli-macOS-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-macOS-amd64-snapshot name: test-results-html-pkl-cli-macOS-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -199,32 +213,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-linux-amd64 name: executable-pkl-cli-linux-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-linux-amd64-snapshot name: test-results-xml-pkl-cli-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-linux-amd64-snapshot name: test-results-html-pkl-cli-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -239,30 +256,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-macOS-aarch64 name: executable-pkl-cli-macOS-aarch64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-macOS-aarch64-snapshot name: test-results-xml-pkl-cli-macOS-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-macOS-aarch64-snapshot name: test-results-html-pkl-cli-macOS-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -274,32 +294,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-linux-aarch64 name: executable-pkl-cli-linux-aarch64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-linux-aarch64-snapshot name: test-results-xml-pkl-cli-linux-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-linux-aarch64-snapshot name: test-results-html-pkl-cli-linux-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -311,13 +334,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -395,19 +421,19 @@ jobs:
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-alpine-linux-amd64 name: executable-pkl-cli-alpine-linux-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-alpine-linux-amd64-snapshot name: test-results-xml-pkl-cli-alpine-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-alpine-linux-amd64-snapshot name: test-results-html-pkl-cli-alpine-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -418,30 +444,33 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-windows-amd64 name: executable-pkl-cli-windows-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-windows-amd64-snapshot name: test-results-xml-pkl-cli-windows-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-windows-amd64-snapshot name: test-results-html-pkl-cli-windows-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -454,30 +483,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --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
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-macOS-amd64 name: executable-pkl-doc-macOS-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-macOS-amd64-snapshot name: test-results-xml-pkl-doc-macOS-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-macOS-amd64-snapshot name: test-results-html-pkl-doc-macOS-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -489,32 +521,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-linux-amd64 name: executable-pkl-doc-linux-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-linux-amd64-snapshot name: test-results-xml-pkl-doc-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-linux-amd64-snapshot name: test-results-html-pkl-doc-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -529,30 +564,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-macOS-aarch64 name: executable-pkl-doc-macOS-aarch64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-macOS-aarch64-snapshot name: test-results-xml-pkl-doc-macOS-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-macOS-aarch64-snapshot name: test-results-html-pkl-doc-macOS-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -564,32 +602,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-linux-aarch64 name: executable-pkl-doc-linux-aarch64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-linux-aarch64-snapshot name: test-results-xml-pkl-doc-linux-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-linux-aarch64-snapshot name: test-results-html-pkl-doc-linux-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -601,13 +642,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -685,19 +729,19 @@ jobs:
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-alpine-linux-amd64 name: executable-pkl-doc-alpine-linux-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-alpine-linux-amd64-snapshot name: test-results-xml-pkl-doc-alpine-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-alpine-linux-amd64-snapshot name: test-results-html-pkl-doc-alpine-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -708,30 +752,33 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-windows-amd64 name: executable-pkl-doc-windows-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-windows-amd64-snapshot name: test-results-xml-pkl-doc-windows-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-windows-amd64-snapshot name: test-results-html-pkl-doc-windows-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -760,15 +807,20 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
environment: maven-release environment: maven-release
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
- uses: actions/checkout@v5 with: {}
- uses: actions/download-artifact@v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with: with:
pattern: executable-** pattern: executable-**
merge-multiple: true merge-multiple: true
@@ -779,21 +831,8 @@ jobs:
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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true --no-parallel publishToSonatype
- name: Upload Test Result XML
if: '!cancelled()'
uses: actions/upload-artifact@v5
with:
name: test-results-xml-deploy-snapshot
path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML
if: '!cancelled()'
uses: actions/upload-artifact@v5
with:
name: test-results-html-deploy-snapshot
path: '**/build/reports/tests/**/*'
if-no-files-found: ignore
publish-test-results: publish-test-results:
if: '!failure() && !cancelled()' if: '!cancelled()'
needs: needs:
- gradle-check - gradle-check
- gradle-check-windows - gradle-check-windows
@@ -811,23 +850,22 @@ jobs:
- pkl-doc-linux-aarch64-snapshot - pkl-doc-linux-aarch64-snapshot
- pkl-doc-alpine-linux-amd64-snapshot - pkl-doc-alpine-linux-amd64-snapshot
- pkl-doc-windows-amd64-snapshot - pkl-doc-windows-amd64-snapshot
- deploy-snapshot
permissions: permissions:
checks: write checks: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/download-artifact@v6 - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with: with:
pattern: test-results-xml-* pattern: test-results-xml-*
- name: Publish test results - name: Publish test results
if: '!cancelled()' if: '!cancelled()'
uses: EnricoMi/publish-unit-test-result-action@v2 uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
with: with:
comment_mode: 'off' comment_mode: 'off'
files: test-results-xml-*/**/*.xml files: test-results-xml-*/**/*.xml
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-publish-test-results name: test-results-html-publish-test-results
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -858,7 +896,7 @@ jobs:
steps: steps:
- name: Create app token - name: Create app token
id: app-token id: app-token
uses: actions/create-github-app-token@v2 uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
with: with:
app-id: ${{ secrets.PKL_CI_CLIENT_ID }} app-id: ${{ secrets.PKL_CI_CLIENT_ID }}
private-key: ${{ secrets.PKL_CI }} private-key: ${{ secrets.PKL_CI }}
@@ -866,9 +904,10 @@ jobs:
- name: Trigger pkl-lang.org build - name: Trigger pkl-lang.org build
env: env:
GH_TOKEN: ${{ steps.app-token.outputs.token }} GH_TOKEN: ${{ steps.app-token.outputs.token }}
SOURCE_RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |- run: |-
gh workflow run \ gh workflow run \
--repo apple/pkl-lang.org \ --repo apple/pkl-lang.org \
--ref main \ --ref main \
--field source_run="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ --field source_run="${SOURCE_RUN}" \
main.yml main.yml
+135 -93
View File
@@ -1,6 +1,4 @@
# Do not modify! # Generated from Workflow.pkl. DO NOT EDIT.
# This file was generated from a template using https://github.com/StefMa/pkl-gha
name: Pull Request name: Pull Request
'on': 'on':
pull_request: {} pull_request: {}
@@ -15,28 +13,30 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-check name: test-results-xml-gradle-check
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-check name: test-results-html-gradle-check
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -48,28 +48,30 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-check-windows name: test-results-xml-gradle-check-windows
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-check-windows name: test-results-html-gradle-check-windows
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -82,31 +84,34 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --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
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-macOS-amd64 name: executable-pkl-cli-macOS-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-macOS-amd64-snapshot name: test-results-xml-pkl-cli-macOS-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-macOS-amd64-snapshot name: test-results-html-pkl-cli-macOS-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -119,33 +124,36 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-linux-amd64 name: executable-pkl-cli-linux-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-linux-amd64-snapshot name: test-results-xml-pkl-cli-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-linux-amd64-snapshot name: test-results-html-pkl-cli-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -160,31 +168,34 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-macOS-aarch64 name: executable-pkl-cli-macOS-aarch64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-macOS-aarch64-snapshot name: test-results-xml-pkl-cli-macOS-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-macOS-aarch64-snapshot name: test-results-html-pkl-cli-macOS-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -197,33 +208,36 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-linux-aarch64 name: executable-pkl-cli-linux-aarch64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-linux-aarch64-snapshot name: test-results-xml-pkl-cli-linux-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-linux-aarch64-snapshot name: test-results-html-pkl-cli-linux-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -236,13 +250,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -320,20 +337,20 @@ jobs:
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-alpine-linux-amd64 name: executable-pkl-cli-alpine-linux-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-alpine-linux-amd64-snapshot name: test-results-xml-pkl-cli-alpine-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-alpine-linux-amd64-snapshot name: test-results-html-pkl-cli-alpine-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -345,31 +362,34 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-windows-amd64 name: executable-pkl-cli-windows-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-windows-amd64-snapshot name: test-results-xml-pkl-cli-windows-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-windows-amd64-snapshot name: test-results-html-pkl-cli-windows-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -382,31 +402,34 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --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
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-macOS-amd64 name: executable-pkl-doc-macOS-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-macOS-amd64-snapshot name: test-results-xml-pkl-doc-macOS-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-macOS-amd64-snapshot name: test-results-html-pkl-doc-macOS-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -419,33 +442,36 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-linux-amd64 name: executable-pkl-doc-linux-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-linux-amd64-snapshot name: test-results-xml-pkl-doc-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-linux-amd64-snapshot name: test-results-html-pkl-doc-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -460,31 +486,34 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-macOS-aarch64 name: executable-pkl-doc-macOS-aarch64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-macOS-aarch64-snapshot name: test-results-xml-pkl-doc-macOS-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-macOS-aarch64-snapshot name: test-results-html-pkl-doc-macOS-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -497,33 +526,36 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-linux-aarch64 name: executable-pkl-doc-linux-aarch64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-linux-aarch64-snapshot name: test-results-xml-pkl-doc-linux-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-linux-aarch64-snapshot name: test-results-html-pkl-doc-linux-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -536,13 +568,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -620,20 +655,20 @@ jobs:
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-alpine-linux-amd64 name: executable-pkl-doc-alpine-linux-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-alpine-linux-amd64-snapshot name: test-results-xml-pkl-doc-alpine-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-alpine-linux-amd64-snapshot name: test-results-html-pkl-doc-alpine-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -645,31 +680,34 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-windows-amd64 name: executable-pkl-doc-windows-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-windows-amd64-snapshot name: test-results-xml-pkl-doc-windows-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
if-no-files-found: ignore if-no-files-found: ignore
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-windows-amd64-snapshot name: test-results-html-pkl-doc-windows-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -679,14 +717,16 @@ jobs:
steps: steps:
- name: Upload event file - name: Upload event file
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-event-file name: test-results-event-file
path: ${{ github.event_path }} path: ${{ github.event_path }}
check-pkl-github-actions: check-pkl-github-actions:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Setup Pkl - name: Setup Pkl
id: setup-pkl id: setup-pkl
env: env:
@@ -701,6 +741,8 @@ jobs:
chmod +x $PKL_EXEC chmod +x $PKL_EXEC
echo "$DIR" >> "$GITHUB_PATH" echo "$DIR" >> "$GITHUB_PATH"
echo "pkl_exec=$PKL_EXEC" >> "$GITHUB_OUTPUT" echo "pkl_exec=$PKL_EXEC" >> "$GITHUB_OUTPUT"
- shell: bash
run: rm -rf .github/**/[a-z]*.yml
- shell: bash - shell: bash
run: pkl eval -m .github/ --project-dir .github/ .github/index.pkl run: pkl eval -m .github/ --project-dir .github/ .github/index.pkl
- name: check git status - name: check git status
+160 -112
View File
@@ -1,6 +1,4 @@
# Do not modify! # Generated from Workflow.pkl. DO NOT EDIT.
# This file was generated from a template using https://github.com/StefMa/pkl-gha
name: Build (release branch) name: Build (release branch)
'on': 'on':
push: push:
@@ -19,27 +17,29 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-check name: test-results-xml-gradle-check
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-check name: test-results-html-gradle-check
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -50,27 +50,29 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-check-windows name: test-results-xml-gradle-check-windows
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-check-windows name: test-results-html-gradle-check-windows
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -80,13 +82,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: bench:jmh - name: bench:jmh
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh
@@ -95,27 +100,29 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --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@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-compatibility name: test-results-xml-gradle-compatibility
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-compatibility name: test-results-html-gradle-compatibility
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -125,33 +132,37 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
- uses: actions/checkout@v5 with: {}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
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 --info --stacktrace --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@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-java name: executable-java
path: '*/build/executable/**/*' path: '*/build/executable/**/*'
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-java-executables-snapshot name: test-results-xml-java-executables-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-java-executables-snapshot name: test-results-html-java-executables-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -164,30 +175,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --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
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-macOS-amd64 name: executable-pkl-cli-macOS-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-macOS-amd64-snapshot name: test-results-xml-pkl-cli-macOS-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-macOS-amd64-snapshot name: test-results-html-pkl-cli-macOS-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -199,32 +213,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-linux-amd64 name: executable-pkl-cli-linux-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-linux-amd64-snapshot name: test-results-xml-pkl-cli-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-linux-amd64-snapshot name: test-results-html-pkl-cli-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -239,30 +256,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-macOS-aarch64 name: executable-pkl-cli-macOS-aarch64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-macOS-aarch64-snapshot name: test-results-xml-pkl-cli-macOS-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-macOS-aarch64-snapshot name: test-results-html-pkl-cli-macOS-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -274,32 +294,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-linux-aarch64 name: executable-pkl-cli-linux-aarch64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-linux-aarch64-snapshot name: test-results-xml-pkl-cli-linux-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-linux-aarch64-snapshot name: test-results-html-pkl-cli-linux-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -311,13 +334,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -395,19 +421,19 @@ jobs:
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-alpine-linux-amd64 name: executable-pkl-cli-alpine-linux-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-alpine-linux-amd64-snapshot name: test-results-xml-pkl-cli-alpine-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-alpine-linux-amd64-snapshot name: test-results-html-pkl-cli-alpine-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -418,30 +444,33 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-windows-amd64 name: executable-pkl-cli-windows-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-windows-amd64-snapshot name: test-results-xml-pkl-cli-windows-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-windows-amd64-snapshot name: test-results-html-pkl-cli-windows-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -454,30 +483,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --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
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-macOS-amd64 name: executable-pkl-doc-macOS-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-macOS-amd64-snapshot name: test-results-xml-pkl-doc-macOS-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-macOS-amd64-snapshot name: test-results-html-pkl-doc-macOS-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -489,32 +521,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-linux-amd64 name: executable-pkl-doc-linux-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-linux-amd64-snapshot name: test-results-xml-pkl-doc-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-linux-amd64-snapshot name: test-results-html-pkl-doc-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -529,30 +564,33 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-macOS-aarch64 name: executable-pkl-doc-macOS-aarch64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-macOS-aarch64-snapshot name: test-results-xml-pkl-doc-macOS-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-macOS-aarch64-snapshot name: test-results-html-pkl-doc-macOS-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -564,32 +602,35 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-linux-aarch64 name: executable-pkl-doc-linux-aarch64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-linux-aarch64-snapshot name: test-results-xml-pkl-doc-linux-aarch64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-linux-aarch64-snapshot name: test-results-html-pkl-doc-linux-aarch64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -601,13 +642,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -685,19 +729,19 @@ jobs:
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -Dpkl.musl=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-alpine-linux-amd64 name: executable-pkl-doc-alpine-linux-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-alpine-linux-amd64-snapshot name: test-results-xml-pkl-doc-alpine-linux-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-alpine-linux-amd64-snapshot name: test-results-html-pkl-doc-alpine-linux-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -708,36 +752,39 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: gradle buildNative - name: gradle buildNative
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-windows-amd64 name: executable-pkl-doc-windows-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-windows-amd64-snapshot name: test-results-xml-pkl-doc-windows-amd64-snapshot
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-windows-amd64-snapshot name: test-results-html-pkl-doc-windows-amd64-snapshot
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
if-no-files-found: ignore if-no-files-found: ignore
publish-test-results: publish-test-results:
if: '!failure() && !cancelled()' if: '!cancelled()'
needs: needs:
- gradle-check - gradle-check
- gradle-check-windows - gradle-check-windows
@@ -759,18 +806,18 @@ jobs:
checks: write checks: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/download-artifact@v6 - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with: with:
pattern: test-results-xml-* pattern: test-results-xml-*
- name: Publish test results - name: Publish test results
if: '!cancelled()' if: '!cancelled()'
uses: EnricoMi/publish-unit-test-result-action@v2 uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
with: with:
comment_mode: 'off' comment_mode: 'off'
files: test-results-xml-*/**/*.xml files: test-results-xml-*/**/*.xml
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-publish-test-results name: test-results-html-publish-test-results
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -800,7 +847,7 @@ jobs:
steps: steps:
- name: Create app token - name: Create app token
id: app-token id: app-token
uses: actions/create-github-app-token@v2 uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
with: with:
app-id: ${{ secrets.PKL_CI_CLIENT_ID }} app-id: ${{ secrets.PKL_CI_CLIENT_ID }}
private-key: ${{ secrets.PKL_CI }} private-key: ${{ secrets.PKL_CI }}
@@ -808,9 +855,10 @@ jobs:
- name: Trigger pkl-lang.org build - name: Trigger pkl-lang.org build
env: env:
GH_TOKEN: ${{ steps.app-token.outputs.token }} GH_TOKEN: ${{ steps.app-token.outputs.token }}
SOURCE_RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |- run: |-
gh workflow run \ gh workflow run \
--repo apple/pkl-lang.org \ --repo apple/pkl-lang.org \
--ref main \ --ref main \
--field source_run="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ --field source_run="${SOURCE_RUN}" \
main.yml main.yml
+185 -118
View File
@@ -1,6 +1,4 @@
# Do not modify! # Generated from Workflow.pkl. DO NOT EDIT.
# This file was generated from a template using https://github.com/StefMa/pkl-gha
name: Release name: Release
'on': 'on':
push: push:
@@ -19,27 +17,29 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-check name: test-results-xml-gradle-check
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-check name: test-results-html-gradle-check
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -50,27 +50,29 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: check - name: check
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true check
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-check-windows name: test-results-xml-gradle-check-windows
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-check-windows name: test-results-html-gradle-check-windows
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -80,13 +82,16 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- name: bench:jmh - name: bench:jmh
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true bench:jmh
@@ -95,27 +100,29 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with: {}
- 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 --info --stacktrace --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@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-gradle-compatibility name: test-results-xml-gradle-compatibility
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-gradle-compatibility name: test-results-html-gradle-compatibility
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -125,33 +132,38 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-java@v5 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
- uses: actions/checkout@v5 with:
cache-disabled: true
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
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 --info --stacktrace --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@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-java name: executable-java
path: '*/build/executable/**/*' path: '*/build/executable/**/*'
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-java-executables-release name: test-results-xml-java-executables-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-java-executables-release name: test-results-html-java-executables-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -164,30 +176,34 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- 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 --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
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-macOS-amd64 name: executable-pkl-cli-macOS-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-macOS-amd64-release name: test-results-xml-pkl-cli-macOS-amd64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-macOS-amd64-release name: test-results-html-pkl-cli-macOS-amd64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -199,32 +215,36 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-linux-amd64 name: executable-pkl-cli-linux-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-linux-amd64-release name: test-results-xml-pkl-cli-linux-amd64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-linux-amd64-release name: test-results-html-pkl-cli-linux-amd64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -239,30 +259,34 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-macOS-aarch64 name: executable-pkl-cli-macOS-aarch64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-macOS-aarch64-release name: test-results-xml-pkl-cli-macOS-aarch64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-macOS-aarch64-release name: test-results-html-pkl-cli-macOS-aarch64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -274,32 +298,36 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-linux-aarch64 name: executable-pkl-cli-linux-aarch64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-linux-aarch64-release name: test-results-xml-pkl-cli-linux-aarch64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-linux-aarch64-release name: test-results-html-pkl-cli-linux-aarch64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -311,13 +339,17 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -395,19 +427,19 @@ jobs:
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.musl=true pkl-cli:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.musl=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-alpine-linux-amd64 name: executable-pkl-cli-alpine-linux-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-alpine-linux-amd64-release name: test-results-xml-pkl-cli-alpine-linux-amd64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-alpine-linux-amd64-release name: test-results-html-pkl-cli-alpine-linux-amd64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -418,30 +450,34 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-cli:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-cli-windows-amd64 name: executable-pkl-cli-windows-amd64
path: pkl-cli*/build/executable/**/* path: pkl-cli*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-cli-windows-amd64-release name: test-results-xml-pkl-cli-windows-amd64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-cli-windows-amd64-release name: test-results-html-pkl-cli-windows-amd64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -454,30 +490,34 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- 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 --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
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-macOS-amd64 name: executable-pkl-doc-macOS-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-macOS-amd64-release name: test-results-xml-pkl-doc-macOS-amd64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-macOS-amd64-release name: test-results-html-pkl-doc-macOS-amd64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -489,32 +529,36 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-linux-amd64 name: executable-pkl-doc-linux-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-linux-amd64-release name: test-results-xml-pkl-doc-linux-amd64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-linux-amd64-release name: test-results-html-pkl-doc-linux-amd64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -529,30 +573,34 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-macOS-aarch64 name: executable-pkl-doc-macOS-aarch64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-macOS-aarch64-release name: test-results-xml-pkl-doc-macOS-aarch64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-macOS-aarch64-release name: test-results-html-pkl-doc-macOS-aarch64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -564,32 +612,36 @@ jobs:
steps: steps:
- name: Install deps - name: Install deps
run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en run: dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: aarch64 architecture: aarch64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-linux-aarch64 name: executable-pkl-doc-linux-aarch64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-linux-aarch64-release name: test-results-xml-pkl-doc-linux-aarch64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-linux-aarch64-release name: test-results-html-pkl-doc-linux-aarch64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -601,13 +653,17 @@ jobs:
env: env:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- name: Install musl and zlib - name: Install musl and zlib
run: | run: |
set -e set -e
@@ -685,19 +741,19 @@ jobs:
shell: bash shell: bash
run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.musl=true pkl-doc:buildNative run: ./gradlew --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true -Dpkl.musl=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-alpine-linux-amd64 name: executable-pkl-doc-alpine-linux-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-alpine-linux-amd64-release name: test-results-xml-pkl-doc-alpine-linux-amd64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-alpine-linux-amd64-release name: test-results-html-pkl-doc-alpine-linux-amd64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -708,30 +764,34 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
JAVA_HOME: /jdk JAVA_HOME: /jdk
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
cache-disabled: true
- 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 --info --stacktrace --no-daemon -DpklMultiJdkTesting=true -DreleaseBuild=true pkl-doc:buildNative
- name: Upload executable artifacts - name: Upload executable artifacts
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: executable-pkl-doc-windows-amd64 name: executable-pkl-doc-windows-amd64
path: pkl-doc*/build/executable/**/* path: pkl-doc*/build/executable/**/*
- name: Upload Test Result XML - name: Upload Test Result XML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-xml-pkl-doc-windows-amd64-release name: test-results-xml-pkl-doc-windows-amd64-release
path: '**/build/test-results/**/*.xml' path: '**/build/test-results/**/*.xml'
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-pkl-doc-windows-amd64-release name: test-results-html-pkl-doc-windows-amd64-release
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -760,15 +820,21 @@ jobs:
LANG: en_US.UTF-8 LANG: en_US.UTF-8
environment: maven-release environment: maven-release
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-java@v5 with:
persist-credentials: false
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with: with:
java-version: '21' java-version: '21'
distribution: temurin distribution: temurin
architecture: x64 architecture: x64
cache: gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
- uses: actions/checkout@v5 with:
- uses: actions/download-artifact@v6 cache-disabled: true
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with: with:
pattern: executable-** pattern: executable-**
merge-multiple: true merge-multiple: true
@@ -785,7 +851,7 @@ jobs:
contents: write contents: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/download-artifact@v6 - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with: with:
pattern: executable-** pattern: executable-**
merge-multiple: true merge-multiple: true
@@ -806,7 +872,7 @@ jobs:
--notes "Release notes: https://pkl-lang.org/main/current/release-notes/changelog.html#release-${TAG_NAME}" \ --notes "Release notes: https://pkl-lang.org/main/current/release-notes/changelog.html#release-${TAG_NAME}" \
*/build/executable/* */build/executable/*
publish-test-results: publish-test-results:
if: '!failure() && !cancelled()' if: '!cancelled()'
needs: needs:
- gradle-check - gradle-check
- gradle-check-windows - gradle-check-windows
@@ -828,18 +894,18 @@ jobs:
checks: write checks: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/download-artifact@v6 - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with: with:
pattern: test-results-xml-* pattern: test-results-xml-*
- name: Publish test results - name: Publish test results
if: '!cancelled()' if: '!cancelled()'
uses: EnricoMi/publish-unit-test-result-action@v2 uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
with: with:
comment_mode: 'off' comment_mode: 'off'
files: test-results-xml-*/**/*.xml files: test-results-xml-*/**/*.xml
- name: Upload Test Result HTML - name: Upload Test Result HTML
if: '!cancelled()' if: '!cancelled()'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with: with:
name: test-results-html-publish-test-results name: test-results-html-publish-test-results
path: '**/build/reports/tests/**/*' path: '**/build/reports/tests/**/*'
@@ -871,7 +937,7 @@ jobs:
steps: steps:
- name: Create app token - name: Create app token
id: app-token id: app-token
uses: actions/create-github-app-token@v2 uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
with: with:
app-id: ${{ secrets.PKL_CI_CLIENT_ID }} app-id: ${{ secrets.PKL_CI_CLIENT_ID }}
private-key: ${{ secrets.PKL_CI }} private-key: ${{ secrets.PKL_CI }}
@@ -879,9 +945,10 @@ jobs:
- name: Trigger pkl-lang.org build - name: Trigger pkl-lang.org build
env: env:
GH_TOKEN: ${{ steps.app-token.outputs.token }} GH_TOKEN: ${{ steps.app-token.outputs.token }}
SOURCE_RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |- run: |-
gh workflow run \ gh workflow run \
--repo apple/pkl-lang.org \ --repo apple/pkl-lang.org \
--ref main \ --ref main \
--field source_run="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ --field source_run="${SOURCE_RUN}" \
main.yml main.yml
+4 -6
View File
@@ -1,6 +1,4 @@
# Do not modify! # Generated from Workflow.pkl. DO NOT EDIT.
# This file was generated from a template using https://github.com/StefMa/pkl-gha
name: PR Test Reports name: PR Test Reports
'on': 'on':
workflow_run: workflow_run:
@@ -20,14 +18,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Download artifacts - name: Download artifacts
uses: dawidd6/action-download-artifact@v11 uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11
with: with:
path: artifacts path: artifacts
name: test-results-.* name: test-results-.*
name_is_regex: true name_is_regexp: true
run_id: ${{ github.event.workflow_run.id }} run_id: ${{ github.event.workflow_run.id }}
- name: Publish test results - name: Publish test results
uses: EnricoMi/publish-unit-test-result-action@v2 uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
with: with:
commit: ${{ github.event.workflow_run.head_sha }} commit: ${{ github.event.workflow_run.head_sha }}
comment_mode: 'off' comment_mode: 'off'
+23 -1
View File
@@ -12,6 +12,27 @@
<option name="REPORT_FIELDS" value="true" /> <option name="REPORT_FIELDS" value="true" />
</inspection_tool> </inspection_tool>
<inspection_tool class="ClassCanBeRecord" enabled="false" level="WEAK WARNING" enabled_by_default="false" /> <inspection_tool class="ClassCanBeRecord" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="CustomRegExpInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myConfigurations">
<list>
<RegExpInspectionConfiguration>
<option name="name" value="PklCliDirectProjectEvaluatorSettingsAccess" />
<option name="suppressId" value="PklCliDirectProjectEvaluatorSettingsAccess" />
<option name="uuid" value="dd497f47-d38f-3fab-9ed7-eabe699620c8" />
<option name="patterns">
<list>
<InspectionPattern>
<option name="regExp" value="project\?\.evaluatorSettings" />
<option name="_fileType" value="Kotlin" />
<option name="searchContext" value="ANY" />
<option name="replacement" value="evaluatorSettings" />
</InspectionPattern>
</list>
</option>
</RegExpInspectionConfiguration>
</list>
</option>
</inspection_tool>
<inspection_tool class="FieldMayBeFinal" enabled="true" level="INFORMATION" enabled_by_default="true"> <inspection_tool class="FieldMayBeFinal" enabled="true" level="INFORMATION" enabled_by_default="true">
<scope name="AllExceptTruffleAst" level="WARNING" enabled="true" /> <scope name="AllExceptTruffleAst" level="WARNING" enabled="true" />
</inspection_tool> </inspection_tool>
@@ -73,5 +94,6 @@
<option name="processLiterals" value="true" /> <option name="processLiterals" value="true" />
<option name="processComments" value="true" /> <option name="processComments" value="true" />
</inspection_tool> </inspection_tool>
<inspection_tool class="dd497f47-d38f-3fab-9ed7-eabe699620c8" enabled="true" level="ERROR" enabled_by_default="true" editorAttributes="ERRORS_ATTRIBUTES" />
</profile> </profile>
</component> </component>
+10 -4
View File
@@ -63,6 +63,9 @@ image:https://github.com/apple/pkl/actions/workflows/main.yml/badge.svg?style=sv
|https://github.com/apple/pkl-go-examples[`apple/pkl-go-examples`] |https://github.com/apple/pkl-go-examples[`apple/pkl-go-examples`]
|Examples for using Pkl within Go applications |Examples for using Pkl within Go applications
|https://github.com/apple/highlightjs-pkl[`apple/highlightjs-pkl`]
|Highlight.js syntax highlighting for Pkl
|https://github.com/apple/pkl-intellij[`apple/pkl-intellij`] |https://github.com/apple/pkl-intellij[`apple/pkl-intellij`]
|JetBrains editor plugins providing Pkl language support |JetBrains editor plugins providing Pkl language support
@@ -79,7 +82,7 @@ image:https://github.com/apple/pkl/actions/workflows/main.yml/badge.svg?style=sv
|The pkl-lang.org website |The pkl-lang.org website
|https://github.com/apple/pkl-lsp[`apple/pkl-lsp`] |https://github.com/apple/pkl-lsp[`apple/pkl-lsp`]
| Language server for Pkl, implementing the server-side of the Language Server Protocol |Language server for Pkl, implementing the server-side of the Language Server Protocol
|https://github.com/apple/pkl-neovim[`apple/pkl-neovim`] |https://github.com/apple/pkl-neovim[`apple/pkl-neovim`]
|Pkl language support for Neovim |Pkl language support for Neovim
@@ -93,6 +96,9 @@ image:https://github.com/apple/pkl/actions/workflows/main.yml/badge.svg?style=sv
|https://github.com/apple/pkl-project-commons[`apple/pkl-project-commons`] |https://github.com/apple/pkl-project-commons[`apple/pkl-project-commons`]
|Utility libraries for Pkl |Utility libraries for Pkl
|https://github.com/apple/pkl-readers[`apple/pkl-readers`]
|Shared Pkl https://pkl-lang.org/main/current/language-reference/index.html#external-readers[external reader] tools
|https://github.com/apple/pkl-spring[`apple/pkl-spring`] |https://github.com/apple/pkl-spring[`apple/pkl-spring`]
|Spring Boot extension for configuring Boot apps with Pkl |Spring Boot extension for configuring Boot apps with Pkl
@@ -108,9 +114,9 @@ image:https://github.com/apple/pkl/actions/workflows/main.yml/badge.svg?style=sv
|https://github.com/apple/pkl.tmbundle[`apple/pkl.tmbundle`] |https://github.com/apple/pkl.tmbundle[`apple/pkl.tmbundle`]
|TextMate bundle for Pkl |TextMate bundle for Pkl
|https://github.com/apple/rules_pkl[`apple/rules_pkl`]
| Bazel build rules for Pkl
|https://github.com/apple/tree-sitter-pkl[`apple/tree-sitter-pkl`] |https://github.com/apple/tree-sitter-pkl[`apple/tree-sitter-pkl`]
|Tree-sitter parser for Pkl |Tree-sitter parser for Pkl
|https://github.com/apple/rules_pkl[`apple/rules_pkl`]
|Bazel build rules for Pkl
|=== |===
+1 -3
View File
@@ -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.
@@ -14,8 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
// https://youtrack.jetbrains.com/issue/KTIJ-19369 // https://youtrack.jetbrains.com/issue/KTIJ-19369
@file:Suppress("DSL_SCOPE_VIOLATION")
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
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-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,20 +47,11 @@ class PklFormatterFunc(@Transient private val configuration: Configuration) :
private val formatterClass by lazy { classLoader.loadClass("org.pkl.formatter.Formatter") } private val formatterClass by lazy { classLoader.loadClass("org.pkl.formatter.Formatter") }
private val grammarVersionClass by lazy { private val formatMethod by lazy { formatterClass.getMethod("format", String::class.java) }
classLoader.loadClass("org.pkl.formatter.GrammarVersion")
}
private val grammarVersionLatestMethod by lazy { grammarVersionClass.getMethod("latest") }
private val formatMethod by lazy {
formatterClass.getMethod("format", String::class.java, grammarVersionClass)
}
private val formatterInstance by lazy { formatterClass.getConstructor().newInstance() } private val formatterInstance by lazy { formatterClass.getConstructor().newInstance() }
override fun apply(input: String): String { override fun apply(input: String): String {
val latestGrammarVersion = grammarVersionLatestMethod(null) return formatMethod(formatterInstance, input) as String
return formatMethod(formatterInstance, input, latestGrammarVersion) as String
} }
} }
+147
View File
@@ -0,0 +1,147 @@
/*
* 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.charset.StandardCharsets
import java.util.Base64
import org.gradle.api.Project
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
import org.gradle.kotlin.dsl.*
import org.gradle.plugins.signing.SigningExtension
/** Configures common POM metadata (licenses, developers, SCM, etc.) for all Pkl publications. */
fun Project.configurePklPomMetadata() {
extensions.configure<PublishingExtension> {
publications.withType<MavenPublication>().configureEach {
pom {
name.set(artifactId)
licenses {
license {
name.set("The Apache Software License, Version 2.0")
url.set("https://github.com/apple/pkl/blob/main/LICENSE.txt")
}
}
developers {
developer {
id.set("pkl-authors")
name.set("The Pkl Authors")
email.set("pkl-oss@group.apple.com")
}
}
scm {
connection.set("scm:git:git://github.com/apple/pkl.git")
developerConnection.set("scm:git:ssh://github.com/apple/pkl.git")
val buildInfo = extensions.getByType<BuildInfo>()
url.set("https://github.com/apple/pkl/tree/${buildInfo.commitish}")
}
issueManagement {
system.set("GitHub Issues")
url.set("https://github.com/apple/pkl/issues")
}
ciManagement {
system.set("GitHub Actions")
url.set("https://github.com/apple/pkl/actions")
}
}
}
}
}
/** Configures POM validation task to check for unresolved versions and snapshots in releases. */
fun Project.configurePomValidation() {
val validatePom by
tasks.registering {
if (tasks.findByName("generatePomFileForLibraryPublication") == null) {
return@registering
}
val generatePomFileForLibraryPublication by tasks.existing(GenerateMavenPom::class)
val outputFile =
layout.buildDirectory.file("validatePom") // dummy output to satisfy up-to-date check
dependsOn(generatePomFileForLibraryPublication)
inputs.file(generatePomFileForLibraryPublication.get().destination)
outputs.file(outputFile)
doLast {
outputFile.get().asFile.delete()
val pomFile = generatePomFileForLibraryPublication.get().destination
assert(pomFile.exists())
val text = pomFile.readText()
run {
val unresolvedVersion = Regex("<version>.*[+,()\\[\\]].*</version>")
val matches = unresolvedVersion.findAll(text).toList()
if (matches.isNotEmpty()) {
throw org.gradle.api.GradleException(
"""
Found unresolved version selector(s) in generated POM:
${matches.joinToString("\n") { it.groupValues[0] }}
"""
.trimIndent()
)
}
}
val buildInfo = project.extensions.getByType<BuildInfo>()
if (buildInfo.isReleaseBuild) {
val snapshotVersion = Regex("<version>.*-SNAPSHOT</version>")
val matches = snapshotVersion.findAll(text).toList()
if (matches.isNotEmpty()) {
throw org.gradle.api.GradleException(
"""
Found snapshot version(s) in generated POM of Pkl release version:
${matches.joinToString("\n") { it.groupValues[0] }}
"""
.trimIndent()
)
}
}
outputFile.get().asFile.writeText("OK")
}
}
tasks.named("publish") { dependsOn(validatePom) }
}
/** Configures signing for Pkl publications. */
fun Project.configurePklSigning() {
// Workaround for maven publish plugin not setting up dependencies correctly.
// Taken from https://github.com/gradle/gradle/issues/26091#issuecomment-1798137734
val dependsOnTasks = mutableListOf<String>()
tasks.withType<AbstractPublishToMaven>().configureEach {
dependsOnTasks.add(name.replace("publish", "sign").replaceAfter("Publication", ""))
dependsOn(dependsOnTasks)
}
extensions.configure<SigningExtension> {
// provided as env vars `ORG_GRADLE_PROJECT_signingKey` and
// `ORG_GRADLE_PROJECT_signingPassword` in CI.
val signingKey =
(findProperty("signingKey") as String?)?.let {
Base64.getDecoder().decode(it).toString(StandardCharsets.US_ASCII)
}
val signingPassword = findProperty("signingPassword") as String?
if (signingKey != null && signingPassword != null) {
useInMemoryPgpKeys(signingKey, signingPassword)
}
extensions.getByType<PublishingExtension>().publications.findByName("library")?.let { sign(it) }
}
}
@@ -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.
@@ -142,9 +142,17 @@ private fun KotlinGradleExtension.configureFormatter() {
} }
val originalRemoteName = System.getenv("PKL_ORIGINAL_REMOTE_NAME") ?: "origin" val originalRemoteName = System.getenv("PKL_ORIGINAL_REMOTE_NAME") ?: "origin"
// if we're running against a release branch (or a PR targeted at one), use that branch for
// ratcheting
// these env vars are set by GitHub actions:
// https://docs.github.com/en/actions/reference/workflows-and-actions/variables#default-environment-variables
val ratchetBranchName =
(System.getenv("GITHUB_BASE_REF") ?: System.getenv("GITHUB_REF_NAME"))?.let {
if (it.startsWith("release/")) it else null
} ?: "main"
spotless { spotless {
ratchetFrom = "$originalRemoteName/main" ratchetFrom = "$originalRemoteName/$ratchetBranchName"
// When building root project, format buildSrc files too. // When building root project, format buildSrc files too.
// We need this because buildSrc is not a subproject of the root project, so a top-level // We need this because buildSrc is not a subproject of the root project, so a top-level
@@ -69,13 +69,12 @@ val assembleNative by
buildInfo.os.isWindows && buildInfo.targetArch == "amd64" -> { buildInfo.os.isWindows && buildInfo.targetArch == "amd64" -> {
wraps(assembleNativeWindowsAmd64) wraps(assembleNativeWindowsAmd64)
} }
buildInfo.musl -> {
throw GradleException("Building musl on ${buildInfo.os} is not supported")
}
else -> { else -> {
throw GradleException( doLast {
"Unsupported os/arch pair: ${buildInfo.os.name}/${buildInfo.targetArch}" throw GradleException(
) "Cannot build targeting ${buildInfo.os.name}/${buildInfo.targetArch} with musl=${buildInfo.musl}"
)
}
} }
} }
} }
@@ -83,6 +82,7 @@ val assembleNative by
val testNative by val testNative by
tasks.registering { tasks.registering {
group = "verification" group = "verification"
dependsOn(assembleNative)
if (!buildInfo.isCrossArchSupported && buildInfo.isCrossArch) { if (!buildInfo.isCrossArchSupported && buildInfo.isCrossArch) {
throw GradleException("Cross-arch builds are not supported on ${buildInfo.os.name}") throw GradleException("Cross-arch builds are not supported on ${buildInfo.os.name}")
@@ -105,13 +105,12 @@ val testNative by
buildInfo.os.isWindows && buildInfo.targetArch == "amd64" -> { buildInfo.os.isWindows && buildInfo.targetArch == "amd64" -> {
dependsOn(testNativeWindowsAmd64) dependsOn(testNativeWindowsAmd64)
} }
buildInfo.musl -> {
throw GradleException("Building musl on ${buildInfo.os} is not supported")
}
else -> { else -> {
throw GradleException( doLast {
"Unsupported os/arch pair: ${buildInfo.os.name}/${buildInfo.targetArch}" throw GradleException(
) "Cannot build targeting ${buildInfo.os.name}/${buildInfo.targetArch} with musl=${buildInfo.musl}"
)
}
} }
} }
} }
@@ -125,5 +124,5 @@ val checkNative by
val buildNative by val buildNative by
tasks.registering { tasks.registering {
group = "build" group = "build"
dependsOn(assembleNative, checkNative) dependsOn(checkNative)
} }
@@ -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.
@@ -13,10 +13,6 @@
* 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 java.nio.charset.StandardCharsets
import java.util.Base64
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
plugins { plugins {
`maven-publish` `maven-publish`
signing signing
@@ -27,119 +23,14 @@ publishing {
components.findByName("java")?.let { javaComponent -> components.findByName("java")?.let { javaComponent ->
create<MavenPublication>("library") { from(javaComponent) } create<MavenPublication>("library") { from(javaComponent) }
} }
withType<MavenPublication>().configureEach {
pom {
name.set(artifactId)
licenses {
license {
name.set("The Apache Software License, Version 2.0")
url.set("https://github.com/apple/pkl/blob/main/LICENSE.txt")
}
}
developers {
developer {
id.set("pkl-authors")
name.set("The Pkl Authors")
email.set("pkl-oss@group.apple.com")
}
}
scm {
connection.set("scm:git:git://github.com/apple/pkl.git")
developerConnection.set("scm:git:ssh://github.com/apple/pkl.git")
val buildInfo = project.extensions.getByType<BuildInfo>()
url.set("https://github.com/apple/pkl/tree/${buildInfo.commitish}")
}
issueManagement {
system.set("GitHub Issues")
url.set("https://github.com/apple/pkl/issues")
}
ciManagement {
system.set("GitHub Actions")
url.set("https://github.com/apple/pkl/actions")
}
}
}
} }
} }
val validatePom by configurePklPomMetadata()
tasks.registering {
if (tasks.findByName("generatePomFileForLibraryPublication") == null) {
return@registering
}
val generatePomFileForLibraryPublication by tasks.existing(GenerateMavenPom::class)
val outputFile =
layout.buildDirectory.file("validatePom") // dummy output to satisfy up-to-date check
dependsOn(generatePomFileForLibraryPublication) configurePomValidation()
inputs.file(generatePomFileForLibraryPublication.get().destination)
outputs.file(outputFile)
doLast { configurePklSigning()
outputFile.get().asFile.delete()
val pomFile = generatePomFileForLibraryPublication.get().destination
assert(pomFile.exists())
val text = pomFile.readText()
run {
val unresolvedVersion = Regex("<version>.*[+,()\\[\\]].*</version>")
val matches = unresolvedVersion.findAll(text).toList()
if (matches.isNotEmpty()) {
throw GradleException(
"""
Found unresolved version selector(s) in generated POM:
${matches.joinToString("\n") { it.groupValues[0] }}
"""
.trimIndent()
)
}
}
val buildInfo = project.extensions.getByType<BuildInfo>()
if (buildInfo.isReleaseBuild) {
val snapshotVersion = Regex("<version>.*-SNAPSHOT</version>")
val matches = snapshotVersion.findAll(text).toList()
if (matches.isNotEmpty()) {
throw GradleException(
"""
Found snapshot version(s) in generated POM of Pkl release version:
${matches.joinToString("\n") { it.groupValues[0] }}
"""
.trimIndent()
)
}
}
outputFile.get().asFile.writeText("OK")
}
}
tasks.publish { dependsOn(validatePom) }
// Workaround for maven publish plugin not setting up dependencies correctly.
// Taken from https://github.com/gradle/gradle/issues/26091#issuecomment-1798137734
val dependsOnTasks = mutableListOf<String>()
tasks.withType<AbstractPublishToMaven>().configureEach {
dependsOnTasks.add(name.replace("publish", "sign").replaceAfter("Publication", ""))
dependsOn(dependsOnTasks)
}
signing {
// provided as env vars `ORG_GRADLE_PROJECT_signingKey` and `ORG_GRADLE_PROJECT_signingPassword`
// in CI.
val signingKey =
(findProperty("signingKey") as String?)?.let {
Base64.getDecoder().decode(it).toString(StandardCharsets.US_ASCII)
}
val signingPassword = findProperty("signingPassword") as String?
if (signingKey != null && signingPassword != null) {
useInMemoryPgpKeys(signingKey, signingPassword)
}
publishing.publications.findByName("library")?.let { sign(it) }
}
artifacts { artifacts {
project.tasks.findByName("javadocJar")?.let { archives(it) } project.tasks.findByName("javadocJar")?.let { archives(it) }
+1 -1
View File
@@ -1,6 +1,6 @@
name: main name: main
title: Main Project title: Main Project
version: 0.30.2 version: 0.31.1
prerelease: false prerelease: false
nav: nav:
- nav.adoc - nav.adoc
@@ -3,7 +3,7 @@
// the following attributes must be updated immediately before a release // the following attributes must be updated immediately before a release
// pkl version corresponding to current git commit without -dev suffix or git hash // pkl version corresponding to current git commit without -dev suffix or git hash
:pkl-version-no-suffix: 0.30.2 :pkl-version-no-suffix: 0.31.1
// tells whether pkl version corresponding to current git commit // tells whether pkl version corresponding to current git commit
// is a release version (:is-release-version: '') or dev version (:!is-release-version:) // is a release version (:is-release-version: '') or dev version (:!is-release-version:)
:is-release-version: '' :is-release-version: ''
@@ -68,6 +68,7 @@ endif::[]
:uri-pkldoc-example: {uri-pkl-examples-tree}/pkldoc :uri-pkldoc-example: {uri-pkl-examples-tree}/pkldoc
:uri-stdlib-baseModule: {uri-pkl-stdlib-docs}/base :uri-stdlib-baseModule: {uri-pkl-stdlib-docs}/base
:uri-stdlib-CommandModule: {uri-pkl-stdlib-docs}/Command
:uri-stdlib-analyzeModule: {uri-pkl-stdlib-docs}/analyze :uri-stdlib-analyzeModule: {uri-pkl-stdlib-docs}/analyze
:uri-stdlib-jsonnetModule: {uri-pkl-stdlib-docs}/jsonnet :uri-stdlib-jsonnetModule: {uri-pkl-stdlib-docs}/jsonnet
:uri-stdlib-reflectModule: {uri-pkl-stdlib-docs}/reflect :uri-stdlib-reflectModule: {uri-pkl-stdlib-docs}/reflect
@@ -150,6 +151,13 @@ endif::[]
:uri-stdlib-Resource: {uri-stdlib-baseModule}/Resource :uri-stdlib-Resource: {uri-stdlib-baseModule}/Resource
:uri-stdlib-outputFiles: {uri-stdlib-baseModule}/ModuleOutput#files :uri-stdlib-outputFiles: {uri-stdlib-baseModule}/ModuleOutput#files
:uri-stdlib-FileOutput: {uri-stdlib-baseModule}/FileOutput :uri-stdlib-FileOutput: {uri-stdlib-baseModule}/FileOutput
:uri-stdlib-Annotation: {uri-stdlib-baseModule}/Annotation
:uri-stdlib-ConvertProperty: {uri-stdlib-baseModule}/ConvertProperty
:uri-stdlib-Command-Flag: {uri-stdlib-CommandModule}/Flag
:uri-stdlib-Command-BooleanFlag: {uri-stdlib-CommandModule}/BooleanFlag
:uri-stdlib-Command-CountedFlag: {uri-stdlib-CommandModule}/CountedFlag
:uri-stdlib-Command-Argument: {uri-stdlib-CommandModule}/Argument
:uri-stdlib-Command-Import: {uri-stdlib-CommandModule}/Import
:uri-messagepack: https://msgpack.org/index.html :uri-messagepack: https://msgpack.org/index.html
:uri-messagepack-spec: https://github.com/msgpack/msgpack/blob/master/spec.md :uri-messagepack-spec: https://github.com/msgpack/msgpack/blob/master/spec.md
@@ -4,7 +4,7 @@ import org.pkl.config.java.JavaType;
import org.pkl.core.ModuleSource; import org.pkl.core.ModuleSource;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@SuppressWarnings("unused") @SuppressWarnings({"unused", "NewClassNamingConvention"})
// the pkl-jvm-examples repo has a similar example // the pkl-jvm-examples repo has a similar example
public class JavaConfigExample { public class JavaConfigExample {
@Test @Test
@@ -2736,6 +2736,10 @@ output {
For more on path-based converters, see {uri-stdlib-PcfRenderer-converters}[PcfRenderer.converters]. For more on path-based converters, see {uri-stdlib-PcfRenderer-converters}[PcfRenderer.converters].
Special <<annotations,Annotations>> may also be used to influence how class properties are rendered.
The `ConvertProperty` annotation (and subclasses of it) are automatically applied during.
For more on annotation-based converters, see link:{uri-stdlib-ConvertProperty}[ConvertProperty].
Sometimes it is useful to directly compute the final module output, bypassing `output.value` and `output.converters`. Sometimes it is useful to directly compute the final module output, bypassing `output.value` and `output.converters`.
To do so, set the link:{uri-stdlib-baseModule}/ModuleOutput#text[output.text] property to a String value: To do so, set the link:{uri-stdlib-baseModule}/ModuleOutput#text[output.text] property to a String value:
@@ -3203,6 +3207,7 @@ This section discusses language features that are generally more relevant to tem
<<module-keyword,`module` Keyword>> + <<module-keyword,`module` Keyword>> +
<<glob-patterns,Glob Patterns>> + <<glob-patterns,Glob Patterns>> +
<<doc-comments,Doc Comments>> + <<doc-comments,Doc Comments>> +
<<annotations,Annotations>> +
<<name-resolution,Name Resolution>> + <<name-resolution,Name Resolution>> +
<<reserved-keywords,Reserved Keywords>> + <<reserved-keywords,Reserved Keywords>> +
<<blank-identifiers,Blank Identifiers>> + <<blank-identifiers,Blank Identifiers>> +
@@ -3956,6 +3961,7 @@ emailList: List<EmailAddress> // <2>
<1> equivalent to `email: String(contains("@"))` for type checking purposes <1> equivalent to `email: String(contains("@"))` for type checking purposes
<2> equivalent to `emailList: List<String(contains("@"))>` for type checking purposes <2> equivalent to `emailList: List<String(contains("@"))>` for type checking purposes
[[nullable-types]]
==== Nullable Types ==== Nullable Types
Class types such as `Bird` (see above) do not admit `null` values. Class types such as `Bird` (see above) do not admit `null` values.
@@ -4916,7 +4922,7 @@ animals {
==== Receiver ==== Receiver
The receiver is the bottom-most object in the <<prototype-chain>>. The receiver is the bottom-most object in the <<prototype-chain>>.
That means that, within the context of an amending object, the reciever is the amending object. That means that, within the context of an amending object, the receiver is the amending object.
Example: Example:
[source,pkl] [source,pkl]
@@ -5332,7 +5338,7 @@ Module-level members can be prefixed with `module.` to resolve name conflicts:
/// See [module.pigeon]. /// See [module.pigeon].
---- ----
To exclude a member from documentation and code completion, annotate it with `@Unlisted`: To exclude a member from documentation and code completion, <<annotations,annotate>> it with `@Unlisted`:
[source%parsed,{pkl}] [source%parsed,{pkl}]
---- ----
@@ -5349,6 +5355,47 @@ The following member links are marked up as code but not rendered as links:footn
Nevertheless, it is a good practice to use member links in the above cases. Nevertheless, it is a good practice to use member links in the above cases.
[[annotations]]
=== Annotations
Annotations are a mechanism to provides extra metadata about Pkl <<modules,modules>>, <<classes,classes>>, <<methods,methods>>, and <<properties,properties>>.
They provide metadata about the type or member they annotate that can be via link:{uri-stdlib-reflectModule}[reflection] or Pkl's Java APIs.
The most common use cases for annotations are to add metadata to influence behavior of xref:pkl-doc:index.adoc[Pkldoc], code generation tools, or <<module-output,module output>>.
Annotations are regular Pkl objects whose class extends link:{uri-stdlib-Annotation}[`Annotation`].
Annotation instances are defined similarly to regular <<classes, class instances>>, but instead of using the `new` keyword the class name is prefixed with `@`.
The object body may be omitted if an annotation's class has no properties or the declared annotation does not override any of the class's default values
Multiple annotations may be defined on a member.
If the annotated member has a <<doc-comments,doc comment>>, the annotation is defined between the comment and the member.
[source%tested,{pkl}]
----
/// Module doc comment
@SomeAnnotation // <1>
module myModule
class SomeAnnotation extends Annotation { // <2>
description: String = "some annotation"
}
/// Module doc comment
@SomeAnnotation // <3>
class Bird {
@SomeAnnotation { description = "some property" } // <4>
name: String
@SomeAnnotation { description = "some method" } // <5>
@Unlisted // <6>
function greet(greeting: String): String = "\(greeting), \(name)!"
}
----
<1> An annotation applied to a module. The annotation(s) must precede the `module` clause and follow the doc comment. The object body is omitted.
<2> The definition of an annotation class.
<3> An annotation appied to a class. The object body is omitted.
<4> An annotation applied to a property. The object body is included because the `description` property is overridden.
<5> An annotation applied to a method. The object body is included because the `description` property is overridden.
<6> A second annotation applied to the same method.
[[name-resolution]] [[name-resolution]]
=== Name Resolution === Name Resolution
+347 -4
View File
@@ -454,6 +454,16 @@ output {
---- ----
==== ====
[[power-assertions-eval]]
.--power-assertions, --no-power-assertions
[%collapsible]
====
Default: enabled +
Enable or disable power assertions for detailed assertion failure messages.
When enabled, type constraint failures will show intermediate values in the assertion expression.
Use `--no-power-assertions` to disable this feature if you prefer simpler output or better performance.
====
This command also takes <<common-options, common options>>. This command also takes <<common-options, common options>>.
[[command-server]] [[command-server]]
@@ -479,7 +489,9 @@ If these are the only failures, the command exits with exit code 10.
Otherwise, failures result in exit code 1. Otherwise, failures result in exit code 1.
<modules>:: <modules>::
The absolute or relative URIs of the modules to test. Relative URIs are resolved against the working directory. The absolute or relative URIs of the modules to test.
The module must extend `pkl:test`.
Relative URIs are resolved against the working directory.
==== Options ==== Options
@@ -524,6 +536,33 @@ Force generation of expected examples. +
The old expected files will be deleted if present. The old expected files will be deleted if present.
==== ====
[[power-assertions-test]]
.--power-assertions, --no-power-assertions
[%collapsible]
====
Default: enabled +
Enable or disable power assertions for detailed assertion failure messages.
When enabled, test failures will show intermediate values in the assertion expression, making it easier to understand why a test failed.
Use `--no-power-assertions` to disable this feature if you prefer simpler output.
====
This command also takes <<common-options, common options>>.
[[command-run]]
=== `pkl run`
*Synopsis:* `pkl run [<options>] [<module>] [<command options>]`
Evaluate a <<cli-tools,CLI command>> defined by `<module>`.
<module>::
The absolute or relative URIs of the command module to run.
The module must extend `pkl:Command`.
Relative URIs are resolved against the working directory.
<command options>::
Additional CLI options and arguments defined by `<module>`.
This command also takes <<common-options, common options>>. This command also takes <<common-options, common options>>.
[[command-repl]] [[command-repl]]
@@ -741,9 +780,9 @@ pkl shell-completion zsh
This command formats or checks formatting of Pkl files. + This command formats or checks formatting of Pkl files. +
Exit codes: Exit codes:
* 0: No violations found. * 0: No violations found or files were updated.
* 1: An unexpected error happened (ex.: IO error) * 1: An unexpected error happened (ex.: IO error)
* 11: Violations were found. * 11: Violations were found (when running without `--write`).
If the path is a directory, recursively looks for files with a `.pkl` extension, or files named `PklProject`. If the path is a directory, recursively looks for files with a `.pkl` extension, or files named `PklProject`.
@@ -780,7 +819,7 @@ Write the path of files with formatting violations to stdout.
[[common-options]] [[common-options]]
=== Common options === Common options
The <<command-eval>>, <<command-test>>, <<command-repl>>, <<command-project-resolve>>, <<command-project-package>>, <<command-download-package>>, and <<command-analyze-imports>> commands support the following common options: The <<command-eval>>, <<command-test>>, <<command-run>>, <<command-repl>>, <<command-project-resolve>>, <<command-project-package>>, <<command-download-package>>, and <<command-analyze-imports>> commands support the following common options:
include::../../pkl-cli/partials/cli-common-options.adoc[] include::../../pkl-cli/partials/cli-common-options.adoc[]
@@ -881,6 +920,310 @@ If multiple module outputs are written to the same file, or to standard output,
By default, module outputs are separated with `---`, as in a YAML stream. By default, module outputs are separated with `---`, as in a YAML stream.
The separator can be customized using the `--module-output-separator` option. The separator can be customized using the `--module-output-separator` option.
[[cli-tools]]
== Implementing CLI Tools
CLI tools can be implemented in Pkl by modules extending the `pkl:Command` module.
With `pkl:Command`, you can define a script in Pkl that is executed by your shell, providing a better CLI experience.
Regular evaluation requires use of xref:language-reference:index.adoc#resources[resources] like properties and evironment variables to provide parameters:
[source,bash]
----
$ pkl eval script.pkl -p username=me -p password=password
----
Commands provide a native, familiar CLI experience:
[source,bash]
----
$ pkl run script.pkl --username=admin --password=hunter2
$ ./script.pkl --username=admin --password=hunter2
----
Pkl commands have a few properties that distinguish them from standard module evaluation:
* Users provide input to commands using familiar command line idioms, providing a better experience than deriving inputs from xref:language-reference:index.adoc#resources[resources] like external properties or environment variables.
* Commands can dynamically import modules when they are specified as command line options.
* Commands may write to standard output (via `output.text` or `output.bytes`) and the filesystem (via `output.files`) in the same evaluation.
* Command file output may write to any absolute path (not only relative to the `--multiple-file-output-path` option).
** Relative output paths are written relative to the current working directory (or `--working-dir`, if specified).
** Paths of output file are printed to the command's standard error.
IMPORTANT: Users of `pkl run` must be aware of the security implications of this behavior.
Using `pkl eval` prevents accidental overwrites by not allowing absolute paths, but `pkl run` does not offer this protection.
Commands may write to any path the invoking user has permissions to modify.
Commands are implemented as regular modules and declare their supported command line flags and positional arguments using a class with annotated properties.
=== Defining Commands
Commands are defined by creating a module that extends `pkl:Command`:
[source,pkl%tested]
.my-tool.pkl
----
/// This doc comment becomes part of the command's CLI help!
/// Markdown formatting is **allowed!**
extends "pkl:Command"
options: Options // <1>
class Options {
// Define CLI flags/arguments...
}
// Regular module code...
----
<1> Re-declaration of the `options` property's type.
Like `pkl eval`, when a command completes without an evaluation error the process exits successfully (exit code 0).
Commands can return a failure using `throw` (exit code 1), but otherwise may not control the exit code.
Other than the differences listed above, commands behave like any other Pkl module.
For example, there is no way to execute other programs or make arbitrary HTTP requests.
If additional functionality is desired, xref:language-reference:index.adoc#external-readers[external readers] may be used to extends Pkl's capabilities.
=== Command Options
Each property of a command's options class becomes a command line option.
Properties with the `local`, `hidden`, `fixed`, and/or `const` modifiers are not parsed as options
A property's doc comment, if present, becomes the corresponding option's CLI help description.
Doc comments are interpreted as Markdown text and formatted nicely when displayed to users.
Properties must have xref:language-reference:index.adoc#type-annotations[type annotations] to determine how they are parsed.
Properties may be xref:language-reference:index.adoc#annotations[annotated] to influence how they behave:
* Properties annotated with link:{uri-stdlib-Command-Flag}[`@Flag`] become CLI flags named `--<property name>` that accept a value.
* `Boolean` properties annotated with link:{uri-stdlib-Command-BooleanFlag}[`@BooleanFlag`] become CLI flags named `--<property name>` and `--no-<property name>` that result in `true` and `false` values, respectively.
* `Int` (and type aliases of `Int`) properties annotated with link:{uri-stdlib-Command-CountedFlag}[`@CountedFlag`] become CLI flags named `--<property name>` that produce a value equal to the number of times they are present on the command line.
* Properties annotated with link:{uri-stdlib-Command-Argument}[`@Argument`] become positional CLI arguments and are parsed in the order they appear in the class.
* Properties with no annotation are treated the same as `@Flag` with no further customization.
Flag options may set a `shortName` property to define a single-character abbreviation (`-<short name>`).
Flag abbreviations may be combined (e.g. `-a -b -v -v -q some-value` is equivalent to `-abvvq some-value`).
[CAUTION]
====
Flag names and short names may not conflict with <<common-options,common options>>.
Future versions of Pkl may introduce additional common options and the names of these options will become forbidden for use in `pkl:Command`.
Thus, any Pkl release that adds common options may introduce breaking changes for commands.
While unfortunate, this behavior eliminates potentially dangerous or misleading ambiguities between Pkl-defined and user-defined options.
====
A `@Flag` or `@Argument` property's type annotation determines how it is converted from the raw string value:
|===
|Type |Behavior
|`String`
|Value is used verbatim.
|`Char`
|Value is used verbatim but must be exactly one character.
|`Boolean`
|True values: `true`, `t`, `1`, `yes`, `y`, `on`
False values: `false`, `f`, `0`, `no`, `n`, `off`
|`Number`
|Value is parsed as an `Int` if possible, otherwise parsed as `Float`.
|`Float`
|Value is parsed as a `Float`.
|`Int`
|Value is parsed as a `Int`.
|`Int8`, `Int16`, `Int32`, `UInt`, `UInt8`, `UInt16`, `UInt32`
|Value is parsed as a `Int` and must be within the type's range.
|xref:language-reference:index.adoc#union-types[Union] of xref:language-reference:index.adoc#string-literal-types[string literals]
|Value is used verbatim but must match a member of the union.
|`List<Element>`, `Listing<Element>`, `Set<Element>`
|Each occurrence of the option becomes an element of the final value.
`Element` values are parsed based on the above primitive types.
|`Map<Key, Value>`, `Mapping<Key, Value>`
|Each occurrence of the option becomes an entry of the final value.
Values are split on the first `"="` character; the first part is parsed as `Key` and the second as `Value`, both based on the above primitive types.
|`Pair<First, Second>`
|Value is split on the first `"="` character; the first part is parsed as `First` and the second as `Second`, both based on the above primitive types.
|===
If a flag that accepts only a single value is provided multiple times, the last occurrence becomes the final value.
Only a single positional argument accepting multiple values is permitted per command.
A property with a xref:language-reference:index.adoc#nullable-types[nullable type] is optional and, if not specified on the command line, will have value `null`.
Properties with default values are also optional.
Type constraints are evaluated when the command is executed, so additional restrictions on option values are enforced at runtime.
==== Custom Option Conversion and Aggregation
A property may be annotated with any type if its `@Flag` or `@Argument` annotation sets the `convert` or `transformAll` properties.
The `convert` property is a xref:language-reference:index.adoc#anonymous-functions[function] that overrides how _each_ raw option value is interpreted.
The `transformAll` property is a function that overrides how _all_ parsed option values become the final property value.
The `convert` and `transformAll` functions may return an pkldoc:Import[pkl:Command] value that is replaced during option parsing with the actual value of the module specified by its `uri` property.
If `glob` is `true`, the replacement value is a `Mapping`; its keys are the _absolute_ URIs of the matched modules and its values are the actual module values.
When specifying glob import options on the command line, it is often necessary to quote the value to avoid it being interpreted by the shell.
If the return value of `convert` or `transformAll` is a `List`, `Set`, `Map`, or `Pair`, each contained value (elements and entry keys/values) that are `Import` values are also replaced.
[IMPORTANT]
====
If an option has type `Mapping<String, «some module type»>` and should accept a single glob pattern value, the option's annotation must also set `multiple = false` to override the default behavior of `Mapping` options accepting multiple values.
Example:
[source%parsed,{pkl}]
----
@Flag {
convert = (it) -> new Import { uri = it; glob = true }
multiple = false
}
birds: Mapping<String, Bird>
----
If multiple glob patterns values should be accepted and merged, `transformAll` may be used to merge every glob-imported `Mapping`:
[source%parsed,{pkl}]
----
@Flag {
convert = (it) -> new Import { uri = it; glob = true }
transformAll =
(values) -> values.fold(new Mapping {}, (result, element) ->
(result) { ...element }
)
}
birds: Mapping<String, Bird>
----
====
=== Subcommands
Like many other command line libraries, `pkl:Command` allows building commands into a hierarchy with a root command and subcommands:
[source,pkl%tested]
.my-tool.pkl
----
extends "pkl:Command"
command {
subcommands {
import("subcommand1.pkl")
import("subcommand2.pkl")
for (_, subcommand in import*("./subcommands/*.pkl")) {
subcommand
}
}
}
----
[source,pkl%tested]
.subcommand1.pkl
----
extends "pkl:Command"
import "my-tool.pkl"
parent: `my-tool` // <1>
// Regular module code...
----
<1> Optional; asserts that this is a subcommand of `my-tool` and simplifies accessing properties and options of the parent command
Each element of `subcommands` must have a unique value for `command.name`.
=== Testing Commands
Command modules are normal Pkl modules, so they may be imported and used like any other module.
This is particularly helpful when testing commands, as the command's `options` and `parent` properties can be populated by test code.
Testing the above command and subcommand might look like this:
[source,pkl%tested]
----
amends "pkl:test"
import "my-tool.pkl"
import "subcommand1.pkl"
examples {
["Test my-tool"] {
(`my-tool`) {
options {
// Set my-tool options here...
}
}.output.text
}
["Test subcommand1"] {
(subcommand1) {
parent { // this amends `my-tool`
options {
// Set my-tool options here...
}
}
options {
// Set subcommand options here...
}
}.output.text
}
}
----
[[commands-as-standalone-scripts]]
=== Commands as standalone scripts
On *nix platforms, Pkl commands can be configured to run as standalone tools that can be invoked without the `pkl run` command.
To achieve this, the command file must be marked executable (i.e. `chmod +x my-tool.pkl`) and a link:https://en.wikipedia.org/wiki/Shebang_(Unix)[shebang comment] must be added on the first line of the file:
[source,pkl%parsed]
----
#!/usr/bin/env -S pkl run
----
NOTE: The `-S` flag for `env` is required on Linux systems due to a limitation of shebang handling in the Linux kernel.
While not required on other *nix platforms like macOS, but it should be included for compatibility.
==== Shell Completion
Like with Pkl's own CLI, <<command-shell-completion, shell completions>> can be generated for standalone scripts.
[source,shell]
----
# Generate shell completion script for bash
./my-tool.pkl shell-completion bash
# Generate shell completion script for zsh
./my-tool.pkl shell-completion zsh
----
==== Customizing Completion Candidates
`@Flag` and `@Argument` annotations may specify the `completionCandidates` to improve generated shell completions.
Valid values include:
* A `Listing<String>` of literal string values to offer for completion.
* The literal string `"path"`, which offers local file paths for completion.
Options with a string literal union type implicitly offer the members of the union as completion candidates.
=== Flag name ambiguities
It is possible for commands to define flags with names or short names that collide with Pkl's own command line options.
To avoid ambiguity in parsing these options, all flags for Pkl itself (e.g. `--root-dir`) must be placed before the root command module's URI.
Command authors are encouraged to avoid overlapping with Pkl's built-in flags, but this may not always be feasible, especially for single-character abbreviated names.
This imposes a limitation around <<commands-as-standalone-scripts,standalone commands>> that prevents users from customizing Pkl evaluator options when they are invoked.
There are two recommended workarounds for this limitation:
* Use a `PklProject` to define evaluator settings instead of doing so on the command line.
* If the command line must be used, switch to invoking via `pkl run [<flags>] [<root command module>]`.
[[repl]] [[repl]]
== Working with the REPL == Working with the REPL
@@ -7,7 +7,7 @@ import org.pkl.core.PObject;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
// the pkl-jvm-examples repo has a similar example // the pkl-jvm-examples repo has a similar example
@SuppressWarnings({"unchecked", "unused", "ConstantConditions"}) @SuppressWarnings({"unchecked", "unused", "ConstantConditions", "NewClassNamingConvention"})
public class CoreEvaluatorExample { public class CoreEvaluatorExample {
@Test @Test
public void usage() { public void usage() {
+10
View File
@@ -322,6 +322,16 @@ Default: `false` +
Whether to ignore expected example files and generate them again. Whether to ignore expected example files and generate them again.
==== ====
[[power-assertions-test]]
.powerAssertions: Property<Boolean>
[%collapsible]
====
Default: `true` (for test tasks) +
Example: `powerAssertions = false` +
Enable or disable power assertions for detailed assertion failure messages.
When enabled, test failures will show intermediate values in the assertion expression, making it easier to understand why a test failed.
====
Common properties: Common properties:
include::../partials/gradle-modules-properties.adoc[] include::../partials/gradle-modules-properties.adoc[]
@@ -118,3 +118,13 @@ The left-hand side describes the source prefix, and the right-hand describes the
This option is commonly used to enable package mirroring. 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`.
==== ====
.powerAssertions: Property<Boolean>
[%collapsible]
====
Default: `false` (except for test tasks, which default to `true`) +
Example: `powerAssertions = true` +
Enable power assertions for detailed assertion failure messages.
When enabled, type constraint failures will show intermediate values in the assertion expression.
This option has a performance impact when constraint failures occur.
====
Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

+1 -1
View File
@@ -266,7 +266,7 @@ Thanks to https://github.com/gordonbondon[@gordonbondon] for contributing to thi
=== `@Generated` annotation for Java/Kotlin codegen === `@Generated` annotation for Java/Kotlin codegen
Classes generated by the Java and Kotlin code generator can optionally recieve new annotation called `Generated` (https://github.com/apple/pkl/pull/1075[#1075], https://github.com/apple/pkl/pull/1115[#1115]). Classes generated by the Java and Kotlin code generator can optionally receive new annotation called `Generated` (https://github.com/apple/pkl/pull/1075[#1075], https://github.com/apple/pkl/pull/1115[#1115]).
This behavior is toggled with the `--generated-annotation` CLI flag, or the similarly named Gradle property. This behavior is toggled with the `--generated-annotation` CLI flag, or the similarly named Gradle property.
+352
View File
@@ -0,0 +1,352 @@
= Pkl 0.31 Release Notes
:version: 0.31
:version-minor: 0.31.1
:release-date: February 26th, 2026
:version-next: 0.32
:version-next-date: July 2026
include::partial$intro.adoc[]
== Highlights [small]#💖#
[[power-assertions]]
=== Power Assertions
Pkl's test output and error output has been improved with power assertions (pr:https://github.com/apple/pkl/pull/1384[], pr:https://github.com/apple/pkl/pull/1419[])!
Pkl has two places that are effectively assertions.
These are:
* Type constraint expressions
* Test facts
Currently, when these assertions fail, the error message prints the assertion's source section.
However, this information can sometimes be lacking.
It tells you what the mechanics of the assertion is, but doesn't tell you _why_ the assertion is failing.
For example, here is the current error output of a failing typecheck.
[source,text]
----
–– Pkl Error ––
Type constraint `name.endsWith(lastName)` violated.
Value: new Person { name = "Bub Johnson" }
7 | passenger: Person(name.endsWith(lastName)) = new { name = "Bub Johnson" }
----
Just from this error message, we don't know what the last name is supposed to be.
What is `name` supposed to end with?
We just know it's some property called `lastName` but, we don't know what it _is_.
In Pkl 0.31, the error output becomes:
[source,text]
----
–– Pkl Error ––
Type constraint `name.endsWith(lastName)` violated.
Value: new Person { name = "Bub Johnson" }
name.endsWith(lastName)
│ │ │
│ false "Smith"
"Bub Johnson"
7 | passenger: Person(name.endsWith(lastName)) = new { name = "Bub Johnson" }
----
Now, we know what the expectation is.
This type of diagram is also added to test facts.
When tests fail, Pkl emits a diagram of the expression, and the values produced.
For example, given the following test:
.math.pkl
[source,pkl]
----
amends "pkl:test"
facts {
local function add(a: Int, b: Int) = a * b
local function divide(a: Int, b: Int) = a % b
["math"] {
add(3, 4) == 7
divide(8, 2) == 4
}
}
----
The error output now includes a power assertion diagram, which helps explain why the test failed.
[source,text]
----
module math
facts
✘ math
add(3, 4) == 7 (math.pkl:9)
│ │
12 false
divide(8, 2) == 4 (math.pkl:10)
│ │
0 false
0.0% tests pass [1/1 failed], 0.0% asserts pass [2/2 failed]
----
To learn more about this feature, consult https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0026-power-assertions.adoc[SPICE-0026].
[[cli-framework]]
=== CLI Framework
Pkl 0.31 introduces a new framework for implementing CLI tools in Pkl (pr:https://github.com/apple/pkl/pull/1367[], pr:https://github.com/apple/pkl/pull/1431[], pr:https://github.com/apple/pkl/pull/1432[], pr:https://github.com/apple/pkl/pull/1436[], pr:https://github.com/apple/pkl/pull/1440[], pr:https://github.com/apple/pkl/pull/1444[]).
The framework provides a way to build command line tools with user experience idioms that will be immediately familiar to users.
CLI tools implemented in Pkl have largely the same capabilities as normal Pkl evaluation (i.e. writing to standard output and files), but this may be extended using xref:language-reference:index.adoc#external-readers[external readers].
Commands are defined by extending the pkldoc:#[pkl:Command] module:
.bird-generator.pkl
[source,pkl]
----
extends "pkl:Command"
options: Options
class Options {
/// Mapping of <bird>=<bird age> pairs defining the list of birds.
@Argument
birds: Mapping<String, Number>
/// Aggregation function to apply to all bird ages.
aggregate: *"sum" | "mean" | "count"
}
class Bird {
/// Name of the bird.
name: String
/// Age of the bird in years.
age: Number
}
birds: Listing<Bird> = new {
for (_name, _age in options.birds) {
new { name = _name; age = _age }
}
}
result: Number =
if (options.aggregate == "sum")
birds.toList().fold(0.0, (result, bird) -> result + bird.age)
else if (options.aggregate == "mean")
birds.toList().fold(0.0, (result, bird) -> result + bird.age) / birds.length
else
birds.length
----
Commands are executed using the `pkl run` CLI subcommand:
[source,bash]
----
$ pkl run bird-generator.pkl pigeon --aggregate=mean Pigeon=1 Hawk=8 Eagle=3
birds {
new {
name = "Pigeon"
age = 1
}
new {
name = "Hawk"
age = 8
}
new {
name = "Eagle"
age = 3
}
}
result = 4.0
----
Automatic CLI help is provided:
[source,bash]
----
$ pkl run test.pkl -h
Usage: test.pkl [<options>] [<birds>]... <command> [<args>]...
Options:
--aggregate=<count, mean, sum> Aggregation function to apply to all bird ages.
-h, --help Show this message and exit
Arguments:
<birds> Mapping of <bird>=<bird age> pairs defining the list of birds.
----
To learn more about this feature, consult xref:pkl-cli:index.adoc#cli-tools[the documentation] and https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0025-pkl-run-cli-framework.adoc[SPICE-0025].
== Noteworthy [small]#🎶#
=== Syntax Highlighting
The Pkl CLI displays Pkl code in several locations: stack frames within errors messages, <<power-assertions,power assertions>>, and in the xref:pkl-cli:index.adoc#repl[REPL].
This code is now syntax highlighted to improve readability (pr:https://github.com/apple/pkl/pull/1385[], pr:https://github.com/apple/pkl/pull/1409[]):
image::syntax-highlight-error.png[syntax highlighted output]
[[cli-dependency-notation]]
=== CLI Support for Dependency Notation
The Pkl CLI now supports specifying modules using xref:language-reference:index.adoc#project-dependencies[dependency notation] (pr:https://github.com/apple/pkl/pull/1434[], pr:https://github.com/apple/pkl/pull/1439[]).
This is especially helpful for <<cli-framework,CLI commands>> defined in Packages:
[source,bash]
----
$ pkl run @my-tool/cmd.pkl ...
----
This enhancement applies to the `pkl eval`, `pkl run`, `pkl test`, and `pkl analyze imports` commands.
It also applies to the `pkldoc`, `pkl-codegen-java`, and `pkl-codegen-kotlin` tools.
[NOTE]
Dependency notation only works for remote package dependencies. xref:language-reference:index.adoc#local-dependencies[Local dependencies] are not supported.
=== Property Converter Annotations
Pkl provides the pkldoc:BaseValueRenderers#converters[] mechanism for transforming values during rendering.
Converters are flexible, but their design makes some transformations awkward.
In particular, modifying property names during rendering required a lot of extra code.
The new pkldoc:ConvertProperty[] annotation adds a way to express parameterized per-property name and value transformations (pr:https://github.com/apple/pkl/pull/1333[]).
To learn more about this feature, consult https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0024-annotation-converters.adoc[SPICE-0024].
Additional new Pkl APIs for per-format property renaming will be added for many built-in renderers:
.fmt.pkl
[source,pkl]
----
import "pkl:json"
import "pkl:yaml"
@json.Property { name = "foo_bar" }
@yaml.Property { name = "foo-bar" }
fooBar: String = "hello world"
----
[source,terminaloutput]
----
$ pkl eval fmt.pkl -f json
{
"foo_bar": "hello world"
}
$ pkl eval fmt.pkl -f yaml
foo-bar: hello world
----
=== Java API changes
==== New classes
New classes are introduced to the Java API.
* `org.pkl.core.CommandSpec`
==== New methods
New methods are introduced to the Java API.
* `org.pkl.core.Evaluator.evaluateCommand`
* `org.pkl.core.EvaluatorBuilder.setPowerAssertionsEnabled`
* `org.pkl.core.EvaluatorBuilder.getPowerAssertionsEnabled`
* `org.pkl.core.SecurityManager.resolveSecurePath`
* `org.pkl.config.java.ConfigEvaluator.evaluateOutputValue`
* `org.pkl.coznfig.java.ConfigEvaluator.evaluateExpression`
=== Standard Library changes
New properties have been added to the standard library (pr:https://github.com/apple/pkl/pull/1396[]).
==== Additions to `pkl:base`
* pkldoc:List#isNotEmpty[]
* pkldoc:Map#isNotEmpty[]
* pkldoc:Set#isNotEmpty[]
* pkldoc:Listing#isNotEmpty[]
* pkldoc:Mapping#isNotEmpty[]
* pkldoc:String#isNotEmpty[]
* pkldoc:String#isNotBlank[]
* pkldoc:ConvertProperty[]
* pkldoc:BaseValueRenderer#convertPropertyTransformers[]
==== New module `pkl:Command`
The pkldoc:#[pkl:Command] standard library module is added.
==== Additions to `pkl:json`
* pkldoc:Property[pkl:json]
==== Additions to `pkl:jsonnet`
* pkldoc:Property[pkl:jsonnet]
==== Additions to `pkl:protobuf`
* pkldoc:Property[pkl:protobuf]
==== Additions to `pkl:xml`
* pkldoc:Property[pkl:xml]
==== Additions to `pkl:yaml`
* pkldoc:Property[pkl:yaml]
== Breaking Changes [small]#💔#
Things to watch out for when upgrading.
=== Removal of `@argfile` support
Prior versions of Pkl had an undocumented feature allowing inclusion of CLI arguments from files using `@path/to/file`.
In order to support <<cli-dependency-notation,dependency notation>> on the CLI, `@argfile` support has been removed from Pkl.
=== Removal of `Collection#transpose()`
Prior versions of Pkl defined a `transpose()` method on the `Collection` class.
This method was never implemented and threw an error when called.
As it was never functional, it has been removed entirely without a deprecation warning (pr:https://github.com/apple/pkl/pull/1437[]).
== Miscellaneous [small]#🐸#
* Improve formatting of imports to keep surrounding comments (pr:https://github.com/apple/pkl/pull/1424[]).
* Add support for evaluating module output and expressions to `ConfigEvaluator` (pr:https://github.com/apple/pkl/pull/1297[]).
* The `pkl format --write` command now exits successfully when formatting violations are found and updated (pr:https://github.com/apple/pkl/pull/1340[]).
* Add `pkl-bom` module to aid in aligning Pkl Java dependencies (pr:https://github.com/apple/pkl/pull/1390[]).
* Improve error message when writing `PklProject.deps.json` fails (pr:https://github.com/apple/pkl/pull/1405[]).
* Add information about pkldoc:Annotation[]s to the language reference (pr:https://github.com/apple/pkl/pull/1427[]).
* Improved usability for the `org.pkl.formatter.Formatter` Java API (pr:https://github.com/apple/pkl/pull/1428[]).
== Bugs fixed [small]#🐜#
The following bugs have been fixed.
* `Function.toString()` returns incorrect result (pr:https://github.com/apple/pkl/pull/1411[]).
* Failure when `--multiple-file-output-path` is a symlink (pr:https://github.com/apple/pkl/pull/1389[]).
* The `module` type in a non-final module has default value of type `Dynamic` (pr:https://github.com/apple/pkl/pull/1392[]).
* The `module` type is cached incorrectly in some cases (pr:https://github.com/apple/pkl/pull/1393[]).
* A possible race condition involving symlinks could bypass `--root-dir` during module and resource reading (pr:https://github.com/apple/pkl/pull/1426[]).
* `pkl format` produces internal stack traces when lexing fails (pr:https://github.com/apple/pkl/pull/1430[]).
* `super` access expressions are parsed incorrectly inside the spread operator (pr:https://github.com/apple/pkl/pull/1364[]).
* Modules and resources with `jar:file:` URIs were not properly sandboxed by `--root-dir` (pr:https://github.com/apple/pkl/pull/1442[]).
== Contributors [small]#🙏#
We would like to thank the contributors to this release (in alphabetical order):
* https://github.com/bioball[@bioball]
* https://github.com/eddie4941[@eddie4941]
* https://github.com/HT154[@HT154]
* https://github.com/stackoverflow[@stackoverflow]
* https://github.com/StefMa[@StefMa]
@@ -1,7 +1,43 @@
= Changelog = Changelog
include::ROOT:partial$component-attributes.adoc[] include::ROOT:partial$component-attributes.adoc[]
[[release-0.31.1]]
== 0.31.1 (2026-03-26)
=== Breaking Changes [small]#💔#
* Allow nullable reads for custom/external resources (pr:https://github.com/apple/pkl/pull/1471[]).
This allows custom/external resources to produce `null` values for xref:language-reference:index.adoc#nullable-reads[nullable reads] (`read?`).
While this is a breaking change in behavior, it is currently not possible to exercise with versions of pkl-go or pkl-swift released prior to this change.
=== Fixes
* Fix typo in changelog and language reference (pr:https://github.com/apple/pkl/pull/1455[]).
* Fix bugs in `CommandSpecParser` (pr:https://github.com/apple/pkl/pull/1448[], pr:https://github.com/apple/pkl/pull/1449[]).
* Respect `--omit-project-settings` for all evaluator options (pr:https://github.com/apple/pkl/pull/1459[]).
* Fix SecurityManager check for HTTP(S) module URIs (pr:https://github.com/apple/pkl/pull/1463[]).
* Fix performance regression caused by activation of power assertion instrumentation during some union type checks (pr:https://github.com/apple/pkl/pull/1462[]).
* Fix module reflection when power assertion instrumentation is active (pr:https://github.com/apple/pkl/pull/1464[]).
* Prevent I/O when checking UNC paths against `--root-dir` (pr:https://github.com/apple/pkl/pull/1466[]).
* Prevent `--multiple-file-output-path` writes from following symlinks outside the target directory
(pr:https://github.com/apple/pkl/pull/1467[]).
=== Contributors ❤️
Thank you to all the contributors for this release!
* https://github.com/04cb[@04cb]
* https://github.com/HT154[@HT154]
* https://github.com/KushalP[@KushalP]
[[release-0.31.0]]
== 0.31.0 (2026-02-26)
xref:0.31.adoc[Release Notes]
[[release-0.30.2]] [[release-0.30.2]]
== 0.30.2 (2025-12-15) == 0.30.2 (2025-12-15)
=== Fixes === Fixes
@@ -2,6 +2,7 @@
The Pkl team aims to release a new version of Pkl in February, June, and October of each year. The Pkl team aims to release a new version of Pkl in February, June, and October of each year.
* xref:0.31.adoc[0.31 Release Notes]
* xref:0.30.adoc[0.30 Release Notes] * xref:0.30.adoc[0.30 Release Notes]
* xref:0.29.adoc[0.29 Release Notes] * xref:0.29.adoc[0.29 Release Notes]
* xref:0.28.adoc[0.28 Release Notes] * xref:0.28.adoc[0.28 Release Notes]
@@ -0,0 +1,12 @@
include::ROOT:partial$component-attributes.adoc[]
Pkl {version} was released on {release-date}. +
[.small]#The latest bugfix release is {version-minor}. (xref:changelog.adoc[All Versions])#
The next release ({version-next}) is scheduled for {version-next-date}.
To see what's coming in the future, follow the {uri-pkl-roadmap}[Pkl Roadmap].
Please send feedback and questions to https://github.com/apple/pkl/discussions[GitHub Discussions], or submit an issue on https://github.com/apple/pkl/issues/new[GitHub]. +
[small]#Pkl is hosted on https://github.com/apple/pkl[GitHub].
To get started, follow xref:pkl-cli:index.adoc#installation[Installation].#
+3 -13
View File
@@ -2,20 +2,10 @@
:version: XXX (e.g., 0.9) :version: XXX (e.g., 0.9)
:version-minor: XXX (e.g., 0.9.0) :version-minor: XXX (e.g., 0.9.0)
:release-date: XXX (e.g., July 11, 2018) :release-date: XXX (e.g., July 11, 2018)
:version-next: XXX (e.g., 0.10)
:version-next-date: XXX (e.g., July 2018)
include::ROOT:partial$component-attributes.adoc[] include::partial$intro.adoc[]
Pkl {version} was released on {release-date}. +
[.small]#The latest bugfix release is {version-minor}. (xref:changelog.adoc[All Versions])#
XXX
The next release (XXX) is scheduled for XXX (e.g., August 2, 2021).
Please send feedback and questions to https://github.com/apple/pkl/discussions[GitHub Discussions], or submit an issue on https://github.com/apple/pkl/issues/new[GitHub]. +
[small]#Pkl is hosted on https://github.com/apple/pkl[GitHub].
To get started, follow xref:pkl-cli:index.adoc#installation[Installation].#
== Highlights [small]#💖# == Highlights [small]#💖#
+1
View File
@@ -41,6 +41,7 @@
* xref:ROOT:evolution-and-roadmap.adoc[Evolution and Roadmap] * xref:ROOT:evolution-and-roadmap.adoc[Evolution and Roadmap]
* xref:release-notes:index.adoc[Release Notes] * xref:release-notes:index.adoc[Release Notes]
** xref:release-notes:0.31.adoc[0.31 Release Notes]
** xref:release-notes:0.30.adoc[0.30 Release Notes] ** xref:release-notes:0.30.adoc[0.30 Release Notes]
** xref:release-notes:0.29.adoc[0.29 Release Notes] ** xref:release-notes:0.29.adoc[0.29 Release Notes]
** xref:release-notes:0.28.adoc[0.28 Release Notes] ** xref:release-notes:0.28.adoc[0.28 Release Notes]
+1 -1
View File
@@ -1,7 +1,7 @@
# suppress inspection "UnusedProperty" for whole file # suppress inspection "UnusedProperty" for whole file
group=org.pkl-lang group=org.pkl-lang
version=0.30.2 version=0.31.1
# google-java-format requires jdk.compiler exports # google-java-format requires jdk.compiler exports
org.gradle.jvmargs= \ org.gradle.jvmargs= \
+9 -1
View File
@@ -9,12 +9,18 @@ googleJavaFormat = "1.25.2"
# must not use `+` because used in download URL # must not use `+` because used in download URL
# 23.1.x requires JDK 20+ # 23.1.x requires JDK 20+
graalVm = "25.0.0" graalVm = "25.0.0"
#noinspection UnusedVersionCatalogEntry
graalVmJdkVersion = "25.0.0" graalVmJdkVersion = "25.0.0"
# slightly hacky but convenient place so we remember to update the checksum # slightly hacky but convenient place so we remember to update the checksum
#noinspection UnusedVersionCatalogEntry
graalVmSha256-macos-x64 = "04278cf867d040e29dc71dd7727793f0ea67eb72adce8a35d04b87b57906778d" graalVmSha256-macos-x64 = "04278cf867d040e29dc71dd7727793f0ea67eb72adce8a35d04b87b57906778d"
#noinspection UnusedVersionCatalogEntry
graalVmSha256-macos-aarch64 = "c446d5aaeda98660a4c14049d299e9fba72105a007df89f19d27cf3979d37158" graalVmSha256-macos-aarch64 = "c446d5aaeda98660a4c14049d299e9fba72105a007df89f19d27cf3979d37158"
#noinspection UnusedVersionCatalogEntry
graalVmSha256-linux-x64 = "1862f2ce97387a303cae4c512cb21baf36fafd2457c3cbbc10d87db94b89d3dd" graalVmSha256-linux-x64 = "1862f2ce97387a303cae4c512cb21baf36fafd2457c3cbbc10d87db94b89d3dd"
#noinspection UnusedVersionCatalogEntry
graalVmSha256-linux-aarch64 = "6c3c8b7617006c5d174d9cf7d357ccfb4bae77a4df1294ee28084fcb6eea8921" graalVmSha256-linux-aarch64 = "6c3c8b7617006c5d174d9cf7d357ccfb4bae77a4df1294ee28084fcb6eea8921"
#noinspection UnusedVersionCatalogEntry
graalVmSha256-windows-x64 = "33ef1d186b5c1e95465fcc97e637bc26e72d5f2250a8615b9c5d667ed5c17fd0" graalVmSha256-windows-x64 = "33ef1d186b5c1e95465fcc97e637bc26e72d5f2250a8615b9c5d667ed5c17fd0"
ideaExtPlugin = "1.1.9" ideaExtPlugin = "1.1.9"
intellijPlugin = "2.10.1" intellijPlugin = "2.10.1"
@@ -62,6 +68,7 @@ geantyref = { group = "io.leangen.geantyref", name = "geantyref", version.ref =
graalCompiler = { group = "org.graalvm.compiler", name = "compiler", version.ref = "graalVm" } graalCompiler = { group = "org.graalvm.compiler", name = "compiler", version.ref = "graalVm" }
graalSdk = { group = "org.graalvm.sdk", name = "graal-sdk", version.ref = "graalVm" } graalSdk = { group = "org.graalvm.sdk", name = "graal-sdk", version.ref = "graalVm" }
graalJs = { group = "org.graalvm.js", name = "js", version.ref = "graalVm" } graalJs = { group = "org.graalvm.js", name = "js", version.ref = "graalVm" }
#noinspection UnusedVersionCatalogEntry
intellij = { group = "com.jetbrains.intellij.idea", name = "ideaIC", version.ref = "intellij" } intellij = { group = "com.jetbrains.intellij.idea", name = "ideaIC", version.ref = "intellij" }
javaPoet = { group = "com.palantir.javapoet", name = "javapoet", version.ref = "javaPoet" } javaPoet = { group = "com.palantir.javapoet", name = "javapoet", version.ref = "javaPoet" }
javaxInject = { group = "javax.inject", name = "javax.inject", version.ref = "javaxInject" } javaxInject = { group = "javax.inject", name = "javax.inject", version.ref = "javaxInject" }
@@ -75,7 +82,6 @@ junitApi = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.re
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" }
junitLauncher = { group = "org.junit.platform", name = "junit-platform-launcher", version.ref = "junitPlatform" } junitLauncher = { group = "org.junit.platform", name = "junit-platform-launcher", version.ref = "junitPlatform" }
kotlinCompilerEmbeddable = { group = "org.jetbrains.kotlin", name = "kotlin-compiler-embeddable", version.ref = "kotlin" }
kotlinPlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } kotlinPlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
kotlinPoet = { group = "com.squareup", name = "kotlinpoet", version.ref = "kotlinPoet" } kotlinPoet = { group = "com.squareup", name = "kotlinpoet", version.ref = "kotlinPoet" }
kotlinReflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" } kotlinReflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" }
@@ -84,8 +90,10 @@ kotlinStdLib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", ve
kotlinxHtml = { group = "org.jetbrains.kotlinx", name = "kotlinx-html-jvm", version.ref = "kotlinxHtml" } kotlinxHtml = { group = "org.jetbrains.kotlinx", name = "kotlinx-html-jvm", version.ref = "kotlinxHtml" }
kotlinxSerializationJson = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerialization" } kotlinxSerializationJson = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerialization" }
kotlinxCoroutinesCore = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" } kotlinxCoroutinesCore = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" }
#noinspection UnusedVersionCatalogEntry
log4j12Api = { group = "org.apache.logging.log4j", name = "log4j-1.2-api", version.ref = "log4j" } log4j12Api = { group = "org.apache.logging.log4j", name = "log4j-1.2-api", version.ref = "log4j" }
msgpack = { group = "org.msgpack", name = "msgpack-core", version.ref = "msgpack" } msgpack = { group = "org.msgpack", name = "msgpack-core", version.ref = "msgpack" }
#noinspection UnusedVersionCatalogEntry
nuValidator = { group = "nu.validator", name = "validator", version.ref = "nuValidator" } nuValidator = { group = "nu.validator", name = "validator", version.ref = "nuValidator" }
# to be replaced with https://github.com/usethesource/capsule or https://github.com/lacuna/bifurcan # to be replaced with https://github.com/usethesource/capsule or https://github.com/lacuna/bifurcan
paguro = { group = "org.organicdesign", name = "Paguro", version.ref = "paguro" } paguro = { group = "org.organicdesign", name = "Paguro", version.ref = "paguro" }
+3 -3
View File
@@ -2,15 +2,15 @@
"catalogs": {}, "catalogs": {},
"aliases": { "aliases": {
"pkl": { "pkl": {
"script-ref": "org.pkl-lang:pkl-cli-java:0.30.2", "script-ref": "org.pkl-lang:pkl-cli-java:0.31.1",
"java-agents": [] "java-agents": []
}, },
"pkl-codegen-java": { "pkl-codegen-java": {
"script-ref": "org.pkl-lang:pkl-codegen-java:0.30.2", "script-ref": "org.pkl-lang:pkl-codegen-java:0.31.1",
"java-agents": [] "java-agents": []
}, },
"pkl-codegen-kotlin": { "pkl-codegen-kotlin": {
"script-ref": "org.pkl-lang:pkl-codegen-kotlin:0.30.2", "script-ref": "org.pkl-lang:pkl-codegen-kotlin:0.31.1",
"java-agents": [] "java-agents": []
} }
}, },
+60
View File
@@ -0,0 +1,60 @@
/*
* 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.
*/
plugins {
pklAllProjects
`java-platform`
`maven-publish`
signing
}
description = "Pkl BOM that includes all modules"
dependencies {
constraints {
api(projects.pklCli)
api(projects.pklCodegenJava)
api(projects.pklCodegenKotlin)
// Use explicit coordinates for pkl-config-java to avoid ambiguity with fatJar publication
api("${project.group}:pkl-config-java:${project.version}")
api("${project.group}:pkl-config-java-all:${project.version}")
api(projects.pklConfigKotlin)
api(projects.pklCore)
api(projects.pklDoc)
api(projects.pklExecutor)
api(projects.pklFormatter)
api(projects.pklGradle)
api(projects.pklParser)
api(projects.pklTools)
}
}
publishing {
publications {
create<MavenPublication>("library") {
from(components["javaPlatform"])
pom {
url.set("https://github.com/apple/pkl/tree/main/pkl-bom")
description.set("Bill of Materials for managing Pkl dependency versions")
}
}
}
}
configurePklPomMetadata()
configurePomValidation()
configurePklSigning()
@@ -0,0 +1,270 @@
/*
* Copyright © 2025-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.
*/
package org.pkl.cli
import com.github.ajalt.clikt.completion.CompletionCandidates
import com.github.ajalt.clikt.completion.CompletionCommand
import com.github.ajalt.clikt.core.*
import com.github.ajalt.clikt.parameters.arguments.*
import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.types.int
import java.io.OutputStream
import java.net.URI
import java.nio.file.Path
import kotlin.io.path.createParentDirectories
import kotlin.io.path.exists
import kotlin.io.path.isDirectory
import kotlin.io.path.writeBytes
import org.pkl.commons.cli.CliBaseOptions
import org.pkl.commons.cli.CliCommand
import org.pkl.commons.cli.CliException
import org.pkl.commons.cli.commands.installCommonOptions
import org.pkl.commons.currentWorkingDir
import org.pkl.core.Closeables
import org.pkl.core.CommandSpec
import org.pkl.core.EvaluatorBuilder
import org.pkl.core.FileOutput
import org.pkl.core.ModuleSource.uri
import org.pkl.core.PklBugException
import org.pkl.core.PklException
import org.pkl.core.util.IoUtils
class CliCommandRunner
@JvmOverloads
constructor(
private val options: CliBaseOptions,
private val reservedFlagNames: Set<String>,
private val reservedFlagShortNames: Set<String>,
private val args: List<String>,
private val outputStream: OutputStream = System.out,
private val errStream: OutputStream = System.err,
) : CliCommand(options) {
override fun doRun() {
val builder = evaluatorBuilder()
try {
evalCmd(builder)
} finally {
Closeables.closeQuietly(builder.moduleKeyFactories)
Closeables.closeQuietly(builder.resourceReaders)
}
}
private fun evalCmd(builder: EvaluatorBuilder) {
val evaluator = builder.build()
evaluator.use {
evaluator.evaluateCommand(
uri(resolvedSourceModules.first()),
reservedFlagNames,
reservedFlagShortNames,
) { spec ->
try {
val root = SynthesizedRunCommand(spec, this, options.sourceModules.first().toString())
root.installCommonOptions(includeVersion = false)
root.subcommands(
CompletionCommand(
name = "shell-completion",
help = "Generate a completion script for the given shell",
)
)
root.parse(args)
} catch (e: PklException) {
throw e
} catch (e: Exception) {
throw e.message?.let { PklException(it, e) } ?: PklException(e)
}
}
}
}
/** Renders the comand's `output.bytes`, writing it to the standard output stream. */
fun writeOutput(outputBytes: ByteArray) {
if (outputBytes.isEmpty()) return
outputStream.write(outputBytes)
outputStream.flush()
}
/**
* Renders the command's `output.files`, writing each entry as a file.
*
* File paths are written to the standard error stream.
*
* Unlike CliEvaluator, command outputs write relative to --working-dir and may write files
* anywhere in the filesystem. This is intentionally less sandboxed than `pkl eval` and directly
* targets the capabilities of CLI tools written in general purpose languages. Pkl commands should
* therefore be treated as untrusted code the way that any other CLI tool would be.
*/
fun writeMultipleFileOutput(outputFiles: Map<String, FileOutput>) {
if (outputFiles.isEmpty()) return
val writtenFiles = mutableMapOf<Path, String>()
val outputDir = options.normalizedWorkingDir
if (outputDir.exists() && !outputDir.isDirectory()) {
throw CliException("Output path `$outputDir` exists and is not a directory.")
}
for ((pathSpec, fileOutput) in outputFiles) {
checkPathSpec(pathSpec)
val resolvedPath = outputDir.resolve(pathSpec).normalize()
val realPath = if (resolvedPath.exists()) resolvedPath.toRealPath() else resolvedPath
val previousOutput = writtenFiles[realPath]
if (previousOutput != null) {
throw CliException(
"Output file conflict: `output.files` entries `\"${previousOutput}\"` and `\"$pathSpec\"` resolve to the same file path `$realPath`."
)
}
if (realPath.isDirectory()) {
throw CliException(
"Output file conflict: `output.files` entry `\"$pathSpec\"` resolves to file path `$realPath`, which is a directory."
)
}
writtenFiles[realPath] = pathSpec
realPath.createParentDirectories()
realPath.writeBytes(fileOutput.bytes)
val displayPath =
if (Path.of(pathSpec).isAbsolute) pathSpec
else IoUtils.relativize(resolvedPath, currentWorkingDir).toString()
errStream.writeText(displayPath + IoUtils.getLineSeparator())
errStream.flush()
}
}
class SynthesizedRunCommand(
private val spec: CommandSpec,
private val runner: CliCommandRunner,
name: String? = null,
) : CliktCommand(name = name ?: spec.name) {
init {
spec.options.forEach { opt ->
when (opt) {
is CommandSpec.Flag ->
registerOption(
option(
names = opt.names,
help = opt.helpText ?: "",
metavar = opt.metavar,
hidden = opt.hidden,
completionCandidates = opt.completionCandidates?.toClikt(),
)
.convert {
try {
opt.transformEach.apply(it, workingDirUri)
} catch (e: CommandSpec.Option.BadValue) {
fail(e.message!!)
} catch (_: CommandSpec.Option.MissingOption) {
throw MissingOption(option)
}
}
.transformAll(opt.defaultValue, opt.showAsRequired) {
try {
opt.transformAll.apply(it, workingDirUri)
} catch (e: CommandSpec.Option.BadValue) {
fail(e.message!!)
} catch (_: CommandSpec.Option.MissingOption) {
throw MissingOption(option)
}
}
)
is CommandSpec.BooleanFlag ->
registerOption(
if (opt.defaultValue != null)
option(names = opt.names, help = opt.helpText ?: "", hidden = opt.hidden)
.flag("--no-${opt.name}", default = opt.defaultValue!!)
else
option(names = opt.names, help = opt.helpText ?: "", hidden = opt.hidden)
.nullableFlag("--no-${opt.name}")
)
is CommandSpec.CountedFlag ->
registerOption(
option(names = opt.names, help = opt.helpText ?: "", hidden = opt.hidden)
.int()
.transformValues(0..0) { it.lastOrNull() ?: 1 }
.transformAll { it.sum().toLong() }
)
is CommandSpec.Argument ->
registerArgument(
argument(
opt.name,
opt.helpText ?: "",
completionCandidates = opt.completionCandidates?.toClikt(),
)
.convert {
try {
opt.transformEach.apply(it, workingDirUri)
} catch (e: CommandSpec.Option.BadValue) {
fail(e.message!!)
} catch (_: CommandSpec.Option.MissingOption) {
throw MissingArgument(argument)
}
}
.transformAll(if (opt.repeated) -1 else 1, !opt.repeated) {
try {
opt.transformAll.apply(it, workingDirUri)
} catch (e: CommandSpec.Option.BadValue) {
fail(e.message!!)
} catch (_: CommandSpec.Option.MissingOption) {
throw MissingArgument(argument)
}
}
)
}
}
spec.subcommands.forEach { subcommands(SynthesizedRunCommand(it, runner)) }
}
val workingDirUri: URI by lazy { runner.options.normalizedWorkingDir.toUri() }
override val invokeWithoutSubcommand = true
override val hiddenFromHelp: Boolean = spec.hidden
override fun help(context: Context): String = spec.helpText ?: ""
override fun run() {
if (currentContext.invokedSubcommand is CompletionCommand) return
val opts =
registeredOptions()
.mapNotNull {
val opt = it as? OptionWithValues<*, *, *> ?: return@mapNotNull null
return@mapNotNull if (it.names.contains("--help")) null
else it.names.last().trimStart('-') to opt.value
}
.toMap() +
registeredArguments()
.mapNotNull { it as? ArgumentDelegate<*> }
.associateBy({ it.name }, { it.value })
val state = spec.apply.apply(opts, currentContext.obj as CommandSpec.State?)
currentContext.obj = state
if (currentContext.invokedSubcommand != null) return
if (spec.subcommands.isNotEmpty() && spec.noOp) {
throw PrintHelpMessage(currentContext, true, 1)
}
val result = state.evaluate()
runner.writeOutput(result.outputBytes)
runner.writeMultipleFileOutput(result.outputFiles)
}
}
}
fun CommandSpec.CompletionCandidates.toClikt(): CompletionCandidates =
when (this) {
CommandSpec.CompletionCandidates.PATH -> CompletionCandidates.Path
is CommandSpec.CompletionCandidates.Fixed -> CompletionCandidates.Fixed(values)
else -> throw PklBugException.unreachableCode()
}
@@ -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.
@@ -111,12 +111,11 @@ constructor(
} }
private fun resolveOutputPaths(pathStr: String): Map<URI, Path> { private fun resolveOutputPaths(pathStr: String): Map<URI, Path> {
val moduleUris = options.base.normalizedSourceModules
val workingDir = options.base.normalizedWorkingDir val workingDir = options.base.normalizedWorkingDir
// 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 moduleUris.associateWith { uri -> return resolvedSourceModules.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 { "." }
@@ -143,17 +142,6 @@ constructor(
} }
} }
private fun Evaluator.writeOutput(moduleSource: ModuleSource, writeTo: Path): Boolean {
if (options.expression == null) {
val bytes = evaluateOutputBytes(moduleSource)
writeTo.writeBytes(bytes)
return bytes.isNotEmpty()
}
val text = evaluateExpressionString(moduleSource, options.expression)
writeTo.writeString(text)
return text.isNotEmpty()
}
private fun Evaluator.evalOutput(moduleSource: ModuleSource): ByteArray { private fun Evaluator.evalOutput(moduleSource: ModuleSource): ByteArray {
if (options.expression == null) { if (options.expression == null) {
return evaluateOutputBytes(moduleSource) return evaluateOutputBytes(moduleSource)
@@ -203,7 +191,7 @@ constructor(
} }
} else { } else {
var outputWritten = false var outputWritten = false
for (moduleUri in options.base.normalizedSourceModules) { for (moduleUri in resolvedSourceModules) {
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)
@@ -227,13 +215,6 @@ constructor(
} }
} }
private fun OutputStream.writeText(text: String) = write(text.toByteArray())
private fun OutputStream.writeLine(text: String) {
writeText(text)
writeText("\n")
}
private fun toModuleSource(uri: URI, reader: InputStream) = private fun toModuleSource(uri: URI, reader: InputStream) =
if (uri == VmUtils.REPL_TEXT_URI) { if (uri == VmUtils.REPL_TEXT_URI) {
ModuleSource.create(uri, reader.readAllBytes().toString(StandardCharsets.UTF_8)) ModuleSource.create(uri, reader.readAllBytes().toString(StandardCharsets.UTF_8))
@@ -241,14 +222,6 @@ constructor(
ModuleSource.uri(uri) ModuleSource.uri(uri)
} }
private fun checkPathSpec(pathSpec: String) {
val illegal = pathSpec.indexOfFirst { IoUtils.isReservedFilenameChar(it) && it != '/' }
if (illegal == -1) {
return
}
throw CliException("Path spec `$pathSpec` contains illegal character `${pathSpec[illegal]}`.")
}
/** /**
* Renders each module's `output.files`, writing each entry as a file into the specified output * Renders each module's `output.files`, writing each entry as a file into the specified output
* directory. * directory.
@@ -263,13 +236,14 @@ constructor(
} }
val moduleSource = toModuleSource(moduleUri, inputStream) val moduleSource = toModuleSource(moduleUri, inputStream)
val output = evaluator.evaluateOutputFiles(moduleSource) val output = evaluator.evaluateOutputFiles(moduleSource)
val realOutputDir = if (outputDir.exists()) outputDir.toRealPath() else outputDir
for ((pathSpec, fileOutput) in output) { for ((pathSpec, fileOutput) in output) {
checkPathSpec(pathSpec) checkPathSpec(pathSpec)
val resolvedPath = outputDir.resolve(pathSpec).normalize() val (realPath, resolvedPath) = realOutputDir.resolveRealPath(Path.of(pathSpec))
val realPath = if (resolvedPath.exists()) resolvedPath.toRealPath() else resolvedPath if (!realPath.startsWith(realOutputDir)) {
if (!realPath.startsWith(outputDir)) {
throw CliException( throw CliException(
"Output file conflict: `output.files` entry `\"$pathSpec\"` in module `$moduleUri` resolves to file path `$realPath`, which is outside output directory `$outputDir`." "Output file conflict: `output.files` entry `\"$pathSpec\"` in module `$moduleUri` resolves to file path `$realPath`, which is outside output directory `$realOutputDir`."
) )
} }
val previousOutput = writtenFiles[realPath] val previousOutput = writtenFiles[realPath]
@@ -294,4 +268,22 @@ constructor(
} }
} }
} }
/**
* Resolves [rel] against this Path name-by-name. At each step, the real path is resolved if the
* file exists. The normalized real path and normalized resolved path are returned. This has a
* similar effect to `this.resolve(rel).toRealPath().normalize()`, but the real paths account for
* symlinks in the middle of the relative path so the full path need not exist.
*/
private fun Path.resolveRealPath(rel: Path): Pair<Path, Path> {
assert(!rel.isAbsolute)
var resolved = this
var real = this
for (name in rel) {
resolved = resolved.resolve(name)
real = real.resolve(name)
if (real.exists()) real = real.toRealPath()
}
return real.normalize() to resolved.normalize()
}
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-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.
@@ -33,6 +33,7 @@ import org.pkl.core.util.IoUtils
import org.pkl.formatter.Formatter import org.pkl.formatter.Formatter
import org.pkl.formatter.GrammarVersion import org.pkl.formatter.GrammarVersion
import org.pkl.parser.GenericParserError import org.pkl.parser.GenericParserError
import org.pkl.parser.ParserError
class CliFormatterCommand class CliFormatterCommand
@JvmOverloads @JvmOverloads
@@ -110,7 +111,6 @@ constructor(
val formatted = format(contents) val formatted = format(contents)
if (contents != formatted) { if (contents != formatted) {
status.update(FORMATTING_VIOLATION)
if (diffNameOnly || overwrite) { if (diffNameOnly || overwrite) {
// if `--diff-name-only` or `-w` is specified, only write file names // if `--diff-name-only` or `-w` is specified, only write file names
writeLine(pathStr) writeLine(pathStr)
@@ -118,6 +118,9 @@ constructor(
if (overwrite) { if (overwrite) {
path.writeText(formatted, Charsets.UTF_8) path.writeText(formatted, Charsets.UTF_8)
} else {
// only exit on violation for "check" operations, not when overwriting
status.update(FORMATTING_VIOLATION)
} }
} }
@@ -125,7 +128,10 @@ constructor(
consoleWriter.write(formatted) consoleWriter.write(formatted)
consoleWriter.flush() consoleWriter.flush()
} }
} catch (pe: GenericParserError) { } catch (pe: ParserError) { // thrown by the lexer
writeErrLine("Could not format `$pathStr`: $pe")
status.update(ERROR)
} catch (pe: GenericParserError) { // thrown by the generic parser
writeErrLine("Could not format `$pathStr`: $pe") writeErrLine("Could not format `$pathStr`: $pe")
status.update(ERROR) status.update(ERROR)
} catch (e: IOException) { } catch (e: IOException) {
@@ -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.
@@ -66,7 +66,7 @@ constructor(
try { try {
return builder return builder
.apply { .apply {
for ((idx, sourceModule) in options.base.normalizedSourceModules.withIndex()) { for ((idx, sourceModule) in resolvedSourceModules.withIndex()) {
addExternalProperty("pkl.analyzeImports.$idx", sourceModule.toString()) addExternalProperty("pkl.analyzeImports.$idx", sourceModule.toString())
} }
} }
@@ -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.
@@ -15,9 +15,11 @@
*/ */
package org.pkl.cli package org.pkl.cli
import java.io.IOException
import java.io.Writer import java.io.Writer
import java.nio.file.Path import java.nio.file.Path
import org.pkl.commons.cli.CliBaseOptions import org.pkl.commons.cli.CliBaseOptions
import org.pkl.core.PklException
import org.pkl.core.SecurityManagers import org.pkl.core.SecurityManagers
import org.pkl.core.module.ProjectDependenciesManager import org.pkl.core.module.ProjectDependenciesManager
import org.pkl.core.packages.PackageResolver import org.pkl.core.packages.PackageResolver
@@ -46,9 +48,13 @@ class CliProjectResolver(
val dependencies = ProjectDependenciesResolver(project, packageResolver, errWriter).resolve() val dependencies = ProjectDependenciesResolver(project, packageResolver, errWriter).resolve()
val depsFile = val depsFile =
projectFile.parent.resolve(ProjectDependenciesManager.PKL_PROJECT_DEPS_FILENAME).toFile() projectFile.parent.resolve(ProjectDependenciesManager.PKL_PROJECT_DEPS_FILENAME).toFile()
depsFile.outputStream().use { dependencies.writeTo(it) } try {
consoleWriter.appendLine(depsFile.toString()) depsFile.outputStream().use { dependencies.writeTo(it) }
consoleWriter.flush() consoleWriter.appendLine(depsFile.toString())
consoleWriter.flush()
} catch (e: IOException) {
throw PklException("Failed to write to $depsFile: ${e.message}", e)
}
} }
} }
} }
@@ -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.
@@ -71,7 +71,7 @@ internal class CliRepl(private val options: CliEvaluatorOptions) : CliCommand(op
options.base.color?.hasColor() ?: false, options.base.color?.hasColor() ?: false,
options.base.traceMode ?: TraceMode.COMPACT, options.base.traceMode ?: TraceMode.COMPACT,
) )
Repl(options.base.normalizedWorkingDir, server).run() Repl(options.base.normalizedWorkingDir, server, options.base.color?.hasColor() ?: false).run()
} }
} }
} }
@@ -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.
@@ -20,6 +20,7 @@ import org.pkl.commons.cli.*
import org.pkl.core.Closeables import org.pkl.core.Closeables
import org.pkl.core.EvaluatorBuilder 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.TestResults import org.pkl.core.TestResults
import org.pkl.core.stdlib.test.report.JUnitReport import org.pkl.core.stdlib.test.report.JUnitReport
import org.pkl.core.stdlib.test.report.SimpleReport import org.pkl.core.stdlib.test.report.SimpleReport
@@ -46,7 +47,7 @@ constructor(
private fun evalTest(builder: EvaluatorBuilder) { private fun evalTest(builder: EvaluatorBuilder) {
val sources = val sources =
options.normalizedSourceModules.ifEmpty { project?.tests?.map { it.toUri() } } resolvedSourceModules.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(
@@ -106,6 +107,9 @@ constructor(
} catch (ex: Exception) { } catch (ex: Exception) {
errWriter.appendLine("Error evaluating module ${moduleUri.path}:") errWriter.appendLine("Error evaluating module ${moduleUri.path}:")
errWriter.write(ex.message ?: "") errWriter.write(ex.message ?: "")
if (ex !is PklException) {
errWriter.write(ex.stackTraceToString())
}
if (moduleUri != sources.last()) { if (moduleUri != sources.last()) {
errWriter.appendLine() errWriter.appendLine()
} }
@@ -0,0 +1,35 @@
/*
* Copyright © 2025-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.
*/
package org.pkl.cli
import java.io.OutputStream
import org.pkl.commons.cli.CliException
import org.pkl.core.util.IoUtils
fun checkPathSpec(pathSpec: String) {
val illegal = pathSpec.indexOfFirst { IoUtils.isReservedFilenameChar(it) && it != '/' }
if (illegal == -1) {
return
}
throw CliException("Path spec `$pathSpec` contains illegal character `${pathSpec[illegal]}`.")
}
fun OutputStream.writeText(text: String) = write(text.toByteArray())
fun OutputStream.writeLine(text: String) {
writeText(text)
writeText("\n")
}
@@ -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.
@@ -16,7 +16,6 @@
package org.pkl.cli.commands package org.pkl.cli.commands
import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.Context
import com.github.ajalt.clikt.core.NoOpCliktCommand
import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.core.subcommands
import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.types.path import com.github.ajalt.clikt.parameters.types.path
@@ -24,9 +23,10 @@ import java.nio.file.Path
import org.pkl.cli.CliImportAnalyzer import org.pkl.cli.CliImportAnalyzer
import org.pkl.cli.CliImportAnalyzerOptions import org.pkl.cli.CliImportAnalyzerOptions
import org.pkl.commons.cli.commands.ModulesCommand import org.pkl.commons.cli.commands.ModulesCommand
import org.pkl.commons.cli.commands.NoOpCommand
import org.pkl.commons.cli.commands.single import org.pkl.commons.cli.commands.single
class AnalyzeCommand : NoOpCliktCommand(name = "analyze") { class AnalyzeCommand : NoOpCommand(name = "analyze") {
override fun help(context: Context) = "Commands related to static analysis" override fun help(context: Context) = "Commands related to static analysis"
override fun helpEpilog(context: Context) = "For more information, visit $helpLink" override fun helpEpilog(context: Context) = "For more information, visit $helpLink"
@@ -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,10 +74,23 @@ class EvalCommand : ModulesCommand(name = "eval", helpLink = helpLink) {
private val testMode: Boolean by private val testMode: Boolean by
option(names = arrayOf("--test-mode"), help = "Internal test mode", hidden = true).flag() option(names = arrayOf("--test-mode"), help = "Internal test mode", hidden = true).flag()
private val powerAssertionsEnabled: Boolean by
option(
names = arrayOf("--power-assertions"),
help = "Enable power assertions for detailed assertion failure messages.",
)
.flag("--no-power-assertions", default = true, defaultForHelp = "enabled")
override fun run() { override fun run() {
val options = val options =
CliEvaluatorOptions( CliEvaluatorOptions(
base = baseOptions.baseOptions(modules, projectOptions, testMode = testMode), base =
baseOptions.baseOptions(
modules,
projectOptions,
testMode = testMode,
powerAssertionsEnabled = powerAssertionsEnabled,
),
outputPath = outputPath, outputPath = outputPath,
outputFormat = baseOptions.format, outputFormat = baseOptions.format,
moduleOutputSeparator = moduleOutputSeparator, moduleOutputSeparator = moduleOutputSeparator,
@@ -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.
@@ -17,7 +17,6 @@ package org.pkl.cli.commands
import com.github.ajalt.clikt.completion.CompletionCandidates import com.github.ajalt.clikt.completion.CompletionCandidates
import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.Context
import com.github.ajalt.clikt.core.NoOpCliktCommand
import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.core.subcommands
import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.multiple import com.github.ajalt.clikt.parameters.arguments.multiple
@@ -30,10 +29,11 @@ import java.nio.file.Path
import org.pkl.cli.CliProjectPackager import org.pkl.cli.CliProjectPackager
import org.pkl.cli.CliProjectResolver import org.pkl.cli.CliProjectResolver
import org.pkl.commons.cli.commands.BaseCommand import org.pkl.commons.cli.commands.BaseCommand
import org.pkl.commons.cli.commands.NoOpCommand
import org.pkl.commons.cli.commands.TestOptions import org.pkl.commons.cli.commands.TestOptions
import org.pkl.commons.cli.commands.single import org.pkl.commons.cli.commands.single
class ProjectCommand : NoOpCliktCommand(name = "project") { class ProjectCommand : NoOpCommand(name = "project") {
override fun help(context: Context) = "Run commands related to projects" override fun help(context: Context) = "Run commands related to projects"
override fun helpEpilog(context: Context) = "For more information, visit $helpLink" override fun helpEpilog(context: Context) = "For more information, visit $helpLink"
@@ -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.
@@ -17,21 +17,22 @@ package org.pkl.cli.commands
import com.github.ajalt.clikt.completion.CompletionCommand import com.github.ajalt.clikt.completion.CompletionCommand
import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.Context
import com.github.ajalt.clikt.core.NoOpCliktCommand
import com.github.ajalt.clikt.core.context import com.github.ajalt.clikt.core.context
import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.core.subcommands
import org.pkl.commons.cli.commands.NoOpCommand
import org.pkl.commons.cli.commands.installCommonOptions import org.pkl.commons.cli.commands.installCommonOptions
import org.pkl.core.Release import org.pkl.core.Release
internal val helpLink = "${Release.current().documentation.homepage}pkl-cli/index.html#usage" internal val helpLink = "${Release.current().documentation.homepage}pkl-cli/index.html#usage"
class RootCommand : NoOpCliktCommand(name = "pkl") { class RootCommand : NoOpCommand(name = "pkl") {
override val printHelpOnEmptyArgs = true override val printHelpOnEmptyArgs = true
override fun helpEpilog(context: Context) = "For more information, visit $helpLink" override fun helpEpilog(context: Context) = "For more information, visit $helpLink"
init { init {
context { context {
readArgumentFile = null
suggestTypoCorrection = { given, possible -> suggestTypoCorrection = { given, possible ->
if (!given.startsWith("-")) { if (!given.startsWith("-")) {
registeredSubcommands().map { it.commandName } registeredSubcommands().map { it.commandName }
@@ -50,6 +51,7 @@ class RootCommand : NoOpCliktCommand(name = "pkl") {
DownloadPackageCommand(), DownloadPackageCommand(),
AnalyzeCommand(), AnalyzeCommand(),
FormatterCommand(), FormatterCommand(),
RunCommand(),
CompletionCommand( CompletionCommand(
name = "shell-completion", name = "shell-completion",
help = "Generate a completion script for the given shell", help = "Generate a completion script for the given shell",
@@ -0,0 +1,86 @@
/*
* Copyright © 2025-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.
*/
package org.pkl.cli.commands
import com.github.ajalt.clikt.completion.CompletionCandidates
import com.github.ajalt.clikt.core.MissingArgument
import com.github.ajalt.clikt.core.PrintHelpMessage
import com.github.ajalt.clikt.core.context
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.convert
import com.github.ajalt.clikt.parameters.arguments.multiple
import com.github.ajalt.clikt.parameters.arguments.optional
import com.github.ajalt.clikt.parameters.groups.provideDelegate
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.option
import java.net.URI
import org.pkl.cli.CliCommandRunner
import org.pkl.commons.cli.commands.BaseCommand
import org.pkl.commons.cli.commands.BaseOptions
import org.pkl.commons.cli.commands.ProjectOptions
class RunCommand : BaseCommand(name = "run", helpLink = helpLink) {
override val helpString = "Run a Pkl pkl:Command CLI tool"
override val treatUnknownOptionsAsArgs = true
init {
context {
// override clikt's built-in help behavior
// the built-in --help is eager so any --help/-h would force printing of pkl run's help
// which is not desired when a command module (or any of its subcommands) are present
// since that would mean command-defined help is gated behind a non-obvious `-- --help`
helpOptionNames = emptySet()
}
}
private val showHelp by option("-h", "--help", help = "Show this message and exit").flag()
val module: URI? by
argument(
name = "module",
help = "Root pkl:Command module to invoke.",
completionCandidates = CompletionCandidates.Path,
)
.convert { BaseOptions.parseModuleName(it) }
.optional()
val args: List<String> by argument(name = "args").multiple()
private val projectOptions by ProjectOptions()
override fun run() {
// if no module is specified but --help is show help, otherwise error becuase module is missing
if (module == null)
if (showHelp) throw PrintHelpMessage(currentContext)
else throw MissingArgument(registeredArguments().find { it.name == "module" }!!)
val reservedFlagNames = mutableSetOf("help")
val reservedFlagShortNames = mutableSetOf("h")
registeredOptions().forEach { opt ->
(opt.names + opt.secondaryNames).forEach {
if (it.startsWith("--")) reservedFlagNames.add(it.trimStart('-'))
else reservedFlagShortNames.add(it.trimStart('-'))
}
}
CliCommandRunner(
baseOptions.baseOptions(listOf(module!!), projectOptions),
reservedFlagNames,
reservedFlagShortNames,
if (showHelp) args + listOf("--help") else args,
)
.run()
}
}
@@ -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.
@@ -20,6 +20,8 @@ import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.convert import com.github.ajalt.clikt.parameters.arguments.convert
import com.github.ajalt.clikt.parameters.arguments.multiple import com.github.ajalt.clikt.parameters.arguments.multiple
import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.groups.provideDelegate
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.option
import java.net.URI import java.net.URI
import org.pkl.cli.CliTestRunner import org.pkl.cli.CliTestRunner
import org.pkl.commons.cli.commands.BaseCommand import org.pkl.commons.cli.commands.BaseCommand
@@ -43,9 +45,21 @@ class TestCommand : BaseCommand(name = "test", helpLink = helpLink) {
private val testOptions by TestOptions() private val testOptions by TestOptions()
private val powerAssertionsEnabled: Boolean by
option(
names = arrayOf("--power-assertions"),
help = "Enable power assertions for detailed assertion failure messages.",
)
.flag("--no-power-assertions", default = true, defaultForHelp = "enabled")
override fun run() { override fun run() {
CliTestRunner( CliTestRunner(
options = baseOptions.baseOptions(modules, projectOptions), options =
baseOptions.baseOptions(
modules,
projectOptions,
powerAssertionsEnabled = powerAssertionsEnabled,
),
testOptions = testOptions.cliTestOptions, testOptions = testOptions.cliTestOptions,
) )
.run() .run()
@@ -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.
@@ -18,22 +18,40 @@ package org.pkl.cli.repl
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 java.util.regex.Pattern
import kotlin.io.path.deleteIfExists import kotlin.io.path.deleteIfExists
import org.fusesource.jansi.Ansi import org.fusesource.jansi.Ansi
import org.jline.reader.EndOfFileException import org.jline.reader.EndOfFileException
import org.jline.reader.Highlighter
import org.jline.reader.LineReader
import org.jline.reader.LineReader.Option import org.jline.reader.LineReader.Option
import org.jline.reader.LineReaderBuilder import org.jline.reader.LineReaderBuilder
import org.jline.reader.UserInterruptException import org.jline.reader.UserInterruptException
import org.jline.reader.impl.completer.AggregateCompleter import org.jline.reader.impl.completer.AggregateCompleter
import org.jline.reader.impl.history.DefaultHistory import org.jline.reader.impl.history.DefaultHistory
import org.jline.terminal.TerminalBuilder import org.jline.terminal.TerminalBuilder
import org.jline.utils.AttributedString
import org.jline.utils.InfoCmp import org.jline.utils.InfoCmp
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.util.AnsiStringBuilder
import org.pkl.core.util.AnsiStringBuilder.AnsiCode
import org.pkl.core.util.IoUtils import org.pkl.core.util.IoUtils
import org.pkl.core.util.SyntaxHighlighter
internal class Repl(workingDir: Path, private val server: ReplServer) { class PklHighlighter : Highlighter {
override fun highlight(reader: LineReader, buffer: String): AttributedString {
val ansi = AnsiStringBuilder(true).apply { SyntaxHighlighter.writeTo(this, buffer) }.toString()
return AttributedString.fromAnsi(ansi)
}
override fun setErrorPattern(pattern: Pattern) {}
override fun setErrorIndex(idx: Int) {}
}
internal class Repl(workingDir: Path, private val server: ReplServer, private val color: Boolean) {
private val terminal = TerminalBuilder.builder().apply { jansi(true) }.build() private val terminal = TerminalBuilder.builder().apply { jansi(true) }.build()
private val history = DefaultHistory() private val history = DefaultHistory()
private val reader = private val reader =
@@ -41,12 +59,12 @@ internal class Repl(workingDir: Path, private val server: ReplServer) {
.apply { .apply {
history(history) history(history)
terminal(terminal) terminal(terminal)
if (color) {
highlighter(PklHighlighter())
}
completer(AggregateCompleter(CommandCompleter, FileCompleter(workingDir))) completer(AggregateCompleter(CommandCompleter, FileCompleter(workingDir)))
option(Option.DISABLE_EVENT_EXPANSION, true) option(Option.DISABLE_EVENT_EXPANSION, true)
variable( variable(LineReader.HISTORY_FILE, (IoUtils.getPklHomeDir().resolve("repl-history")))
org.jline.reader.LineReader.HISTORY_FILE,
(IoUtils.getPklHomeDir().resolve("repl-history")),
)
} }
.build() .build()
@@ -55,6 +73,12 @@ internal class Repl(workingDir: Path, private val server: ReplServer) {
private var maybeQuit = false private var maybeQuit = false
private var nextRequestId = 0 private var nextRequestId = 0
private fun String.faint(): String {
val sb = AnsiStringBuilder(color)
sb.append(AnsiCode.FAINT, this)
return sb.toString()
}
fun run() { fun run() {
// JLine 2 history file is incompatible with JLine 3 // JLine 2 history file is incompatible with JLine 3
IoUtils.getPklHomeDir().resolve("repl-history.bin").deleteIfExists() IoUtils.getPklHomeDir().resolve("repl-history.bin").deleteIfExists()
@@ -70,11 +94,11 @@ internal class Repl(workingDir: Path, private val server: ReplServer) {
try { try {
if (continuation) { if (continuation) {
nextRequestId -= 1 nextRequestId -= 1
reader.readLine(" ".repeat("pkl$nextRequestId> ".length)) reader.readLine(" ".repeat("pkl$nextRequestId> ".length).faint())
} else { } else {
reader.readLine("pkl$nextRequestId> ") reader.readLine("pkl$nextRequestId> ".faint())
} }
} catch (e: UserInterruptException) { } catch (_: UserInterruptException) {
if (!continuation && reader.buffer.length() == 0) { if (!continuation && reader.buffer.length() == 0) {
if (maybeQuit) quit() if (maybeQuit) quit()
else { else {
@@ -87,7 +111,7 @@ internal class Repl(workingDir: Path, private val server: ReplServer) {
inputBuffer = "" inputBuffer = ""
continuation = false continuation = false
continue continue
} catch (e: EndOfFileException) { } catch (_: EndOfFileException) {
":quit" ":quit"
} }
@@ -111,10 +135,10 @@ internal class Repl(workingDir: Path, private val server: ReplServer) {
} finally { } finally {
try { try {
history.save() history.save()
} catch (ignored: IOException) {} } catch (_: IOException) {}
try { try {
terminal.close() terminal.close()
} catch (ignored: IOException) {} } catch (_: IOException) {}
} }
} }
@@ -124,10 +148,12 @@ internal class Repl(workingDir: Path, private val server: ReplServer) {
candidates.isEmpty() -> { candidates.isEmpty() -> {
println("Unknown command: `${inputBuffer.drop(1)}`") println("Unknown command: `${inputBuffer.drop(1)}`")
} }
candidates.size > 1 -> { candidates.size > 1 -> {
print("Which of the following did you mean? ") print("Which of the following did you mean? ")
println(candidates.joinToString(separator = " ") { "`:${it.type}`" }) println(candidates.joinToString(separator = " ") { "`:${it.type}`" })
} }
else -> { else -> {
doExecuteCommand(candidates.single()) doExecuteCommand(candidates.single())
} }
@@ -193,16 +219,20 @@ internal class Repl(workingDir: Path, private val server: ReplServer) {
is ReplResponse.EvalSuccess -> { is ReplResponse.EvalSuccess -> {
println(response.result) println(response.result)
} }
is ReplResponse.EvalError -> { is ReplResponse.EvalError -> {
println(response.message) println(response.message)
} }
is ReplResponse.InternalError -> { is ReplResponse.InternalError -> {
throw response.cause throw response.cause
} }
is ReplResponse.IncompleteInput -> { is ReplResponse.IncompleteInput -> {
assert(responses.size == 1) assert(responses.size == 1)
continuation = true continuation = true
} }
else -> throw IllegalStateException("Unexpected response: $response") else -> throw IllegalStateException("Unexpected response: $response")
} }
} }
File diff suppressed because it is too large Load Diff
@@ -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.
@@ -931,6 +931,37 @@ result = someLib.x
.hasMessageContaining("which is outside output directory") .hasMessageContaining("which is outside output directory")
} }
@Test
@DisabledOnOs(OS.WINDOWS)
fun `multiple file output throws if files are written outside the base path via symlink`() {
val output = tempDir.resolve(".output").createDirectories()
val outside = tempDir.resolve("outside").createDirectories()
output.resolve("outside").createSymbolicLinkPointingTo(outside)
val moduleUri =
writePklFile(
"test.pkl",
"""
output {
files {
["outside/foo.txt"] {
text = "bar"
}
}
}
"""
.trimIndent(),
)
val options =
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(moduleUri), workingDir = tempDir),
multipleFileOutputPath = ".output",
)
assertThatCode { evalToConsole(options) }
.hasMessageStartingWith("Output file conflict:")
.hasMessageContaining("which is outside output directory")
}
@Test @Test
fun `multiple file output throws if file path is a directory`() { fun `multiple file output throws if file path is a directory`() {
tempDir.resolve(".output/myDir").createDirectories() tempDir.resolve(".output/myDir").createDirectories()
@@ -1634,6 +1665,95 @@ result = someLib.x
) )
} }
@Test
@DisabledOnOs(OS.WINDOWS)
fun `multiple file output works with symlinked output directory`() {
val realOutputDir = tempDir.resolve("real-output").createDirectories()
val symlinkOutputDir =
Files.createSymbolicLink(tempDir.resolve("symlink-output"), realOutputDir)
val sourceFile =
writePklFile(
"test.pkl",
"""
pigeon {
name = "Pigeon"
diet = "Seeds"
}
parrot {
name = "Parrot"
diet = "Seeds"
}
output {
files {
["pigeon.json"] {
value = pigeon
renderer = new JsonRenderer {}
}
["birds/parrot.yaml"] {
value = parrot
renderer = new YamlRenderer {}
}
}
}
"""
.trimIndent(),
)
val options =
CliEvaluatorOptions(
CliBaseOptions(sourceModules = listOf(sourceFile), workingDir = tempDir),
multipleFileOutputPath = symlinkOutputDir.toString(),
)
CliEvaluator(options).run()
checkOutputFile(
realOutputDir.resolve("pigeon.json"),
"pigeon.json",
"""
{
"name": "Pigeon",
"diet": "Seeds"
}
"""
.trimIndent(),
)
checkOutputFile(
realOutputDir.resolve("birds/parrot.yaml"),
"parrot.yaml",
"""
name: Parrot
diet: Seeds
"""
.trimIndent(),
)
checkOutputFile(
symlinkOutputDir.resolve("pigeon.json"),
"pigeon.json",
"""
{
"name": "Pigeon",
"diet": "Seeds"
}
"""
.trimIndent(),
)
checkOutputFile(
symlinkOutputDir.resolve("birds/parrot.yaml"),
"parrot.yaml",
"""
name: Parrot
diet: Seeds
"""
.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 © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-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,9 @@ import java.nio.file.Path
import kotlin.io.path.writeText 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.io.TempDir import org.junit.jupiter.api.io.TempDir
import org.pkl.commons.cli.CliBugException
import org.pkl.commons.cli.CliException import org.pkl.commons.cli.CliException
import org.pkl.core.util.StringBuilderWriter import org.pkl.core.util.StringBuilderWriter
import org.pkl.formatter.GrammarVersion import org.pkl.formatter.GrammarVersion
@@ -44,4 +46,22 @@ class CliFormatterTest {
} catch (_: CliException) {} } catch (_: CliException) {}
assertThat(sb.toString()).isEqualTo("foo = 1\n") assertThat(sb.toString()).isEqualTo("foo = 1\n")
} }
@Test
fun `parse errors do not result in bug exceptions`(@TempDir tempDir: Path) {
val file = tempDir.resolve("foo.pkl").also { it.writeText("foo = \"/foo/\\\${BAR}/baz\"") }
val sb = StringBuilder()
val writer = StringBuilderWriter(sb)
val cmd =
CliFormatterCommand(
listOf(file),
GrammarVersion.latest(),
overwrite = false,
diffNameOnly = false,
silent = false,
consoleWriter = writer,
)
val exc = assertThrows<CliException> { cmd.run() }
assertThat(exc).isNotInstanceOf(CliBugException::class.java)
}
} }
@@ -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.
@@ -18,7 +18,9 @@ package org.pkl.cli
import java.io.File import java.io.File
import java.io.StringWriter import java.io.StringWriter
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.createDirectories
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatCode
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.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows
@@ -27,6 +29,7 @@ import org.pkl.commons.cli.CliBaseOptions
import org.pkl.commons.cli.CliException import org.pkl.commons.cli.CliException
import org.pkl.commons.test.FileTestUtils import org.pkl.commons.test.FileTestUtils
import org.pkl.commons.test.PackageServer import org.pkl.commons.test.PackageServer
import org.pkl.commons.writeString
import org.pkl.core.util.IoUtils import org.pkl.core.util.IoUtils
class CliProjectResolverTest { class CliProjectResolverTest {
@@ -457,4 +460,40 @@ class CliProjectResolverTest {
.trimIndent() .trimIndent()
) )
} }
@Test
fun `IOException when writing to PklProject-deps-json`(@TempDir tempDir: Path) {
val consoleOut = StringWriter()
val errOut = StringWriter()
tempDir
.resolve("PklProject")
.writeString(
"""
amends "pkl:Project"
dependencies {
["birds"] {
uri = "package://localhost:0/birds@0.5.0"
}
}
"""
.trimIndent()
)
// coerce an IOException by making this a directory
val depsJsonFile = tempDir.resolve("PklProject.deps.json").also { it.createDirectories() }
assertThatCode {
CliProjectResolver(
CliBaseOptions(
caCertificates = listOf(FileTestUtils.selfSignedCertificate),
testPort = packageServer.port,
noCache = true,
),
listOf(tempDir),
consoleWriter = consoleOut,
errWriter = errOut,
)
.run()
}
.hasMessageContaining("Failed to write to $depsJsonFile")
}
} }
@@ -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.
@@ -52,7 +52,12 @@ class CliTestRunnerTest {
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val out = StringWriter() val out = StringWriter()
val err = StringWriter() val err = StringWriter()
val opts = CliBaseOptions(sourceModules = listOf(input.toUri()), settings = URI("pkl:settings")) val opts =
CliBaseOptions(
sourceModules = listOf(input.toUri()),
settings = URI("pkl:settings"),
powerAssertionsEnabled = true,
)
val testOpts = CliTestOptions() val testOpts = CliTestOptions()
val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err) val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err)
runner.run() runner.run()
@@ -81,7 +86,7 @@ class CliTestRunnerTest {
facts { facts {
["fail"] { ["fail"] {
4 == 9 4 == 9
"foo" != "bar" 1 == 5
} }
} }
""" """
@@ -89,7 +94,12 @@ class CliTestRunnerTest {
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val out = StringWriter() val out = StringWriter()
val err = StringWriter() val err = StringWriter()
val opts = CliBaseOptions(sourceModules = listOf(input.toUri()), settings = URI("pkl:settings")) val opts =
CliBaseOptions(
sourceModules = listOf(input.toUri()),
settings = URI("pkl:settings"),
powerAssertionsEnabled = true,
)
val testOpts = CliTestOptions() val testOpts = CliTestOptions()
val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err) val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err)
assertThatCode { runner.run() }.hasMessage("Tests failed.") assertThatCode { runner.run() }.hasMessage("Tests failed.")
@@ -101,8 +111,13 @@ class CliTestRunnerTest {
facts facts
fail fail
4 == 9 (/tempDir/test.pkl, line xx) 4 == 9 (/tempDir/test.pkl, line xx)
false
1 == 5 (/tempDir/test.pkl, line xx)
false
0.0% tests pass [1/1 failed], 50.0% asserts pass [1/2 failed] 0.0% tests pass [1/1 failed], 0.0% asserts pass [2/2 failed]
""" """
.trimIndent() .trimIndent()
@@ -126,7 +141,12 @@ class CliTestRunnerTest {
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val out = StringWriter() val out = StringWriter()
val err = StringWriter() val err = StringWriter()
val opts = CliBaseOptions(sourceModules = listOf(input.toUri()), settings = URI("pkl:settings")) val opts =
CliBaseOptions(
sourceModules = listOf(input.toUri()),
settings = URI("pkl:settings"),
powerAssertionsEnabled = true,
)
val testOpts = CliTestOptions() val testOpts = CliTestOptions()
val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err) val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err)
assertThatCode { runner.run() }.hasMessage("Tests failed.") assertThatCode { runner.run() }.hasMessage("Tests failed.")
@@ -168,7 +188,12 @@ class CliTestRunnerTest {
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val out = StringWriter() val out = StringWriter()
val err = StringWriter() val err = StringWriter()
val opts = CliBaseOptions(sourceModules = listOf(input.toUri()), settings = URI("pkl:settings")) val opts =
CliBaseOptions(
sourceModules = listOf(input.toUri()),
settings = URI("pkl:settings"),
powerAssertionsEnabled = true,
)
val testOpts = CliTestOptions() val testOpts = CliTestOptions()
val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err) val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err)
assertThatCode { runner.run() }.hasMessage("Tests failed.") assertThatCode { runner.run() }.hasMessage("Tests failed.")
@@ -224,7 +249,12 @@ class CliTestRunnerTest {
) )
val out = StringWriter() val out = StringWriter()
val err = StringWriter() val err = StringWriter()
val opts = CliBaseOptions(sourceModules = listOf(input.toUri()), settings = URI("pkl:settings")) val opts =
CliBaseOptions(
sourceModules = listOf(input.toUri()),
settings = URI("pkl:settings"),
powerAssertionsEnabled = true,
)
val testOpts = CliTestOptions() val testOpts = CliTestOptions()
val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err) val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err)
assertThatCode { runner.run() }.hasMessage("Tests failed.") assertThatCode { runner.run() }.hasMessage("Tests failed.")
@@ -270,7 +300,12 @@ class CliTestRunnerTest {
.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()
val opts = CliBaseOptions(sourceModules = listOf(input.toUri()), settings = URI("pkl:settings")) val opts =
CliBaseOptions(
sourceModules = listOf(input.toUri()),
settings = URI("pkl:settings"),
powerAssertionsEnabled = true,
)
val testOpts = CliTestOptions(junitDir = tempDir) val testOpts = CliTestOptions(junitDir = tempDir)
val runner = CliTestRunner(opts, testOpts, noopWriter, noopWriter) val runner = CliTestRunner(opts, testOpts, noopWriter, noopWriter)
assertThatCode { runner.run() }.hasMessageContaining("failed") assertThatCode { runner.run() }.hasMessageContaining("failed")
@@ -283,12 +318,14 @@ class CliTestRunnerTest {
<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> <failure message="Fact Failure">5 == 9 (/tempDir/test.pkl, line xx)
false</failure>
</testcase> </testcase>
<system-err><![CDATA[9 = 9 <system-err><![CDATA[9 = 9
]]></system-err> ]]></system-err>
</testsuite> </testsuite>
""" """
.trimIndent() .trimIndent()
) )
@@ -313,7 +350,12 @@ class CliTestRunnerTest {
.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()
val opts = CliBaseOptions(sourceModules = listOf(input.toUri()), settings = URI("pkl:settings")) val opts =
CliBaseOptions(
sourceModules = listOf(input.toUri()),
settings = URI("pkl:settings"),
powerAssertionsEnabled = true,
)
val testOpts = CliTestOptions(junitDir = tempDir) val testOpts = CliTestOptions(junitDir = tempDir)
val runner = CliTestRunner(opts, testOpts, noopWriter, noopWriter) val runner = CliTestRunner(opts, testOpts, noopWriter, noopWriter)
assertThatCode { runner.run() }.hasMessageContaining("failed") assertThatCode { runner.run() }.hasMessageContaining("failed")
@@ -467,6 +509,7 @@ class CliTestRunnerTest {
CliBaseOptions( CliBaseOptions(
sourceModules = listOf(input1.toUri(), input2.toUri()), sourceModules = listOf(input1.toUri(), input2.toUri()),
settings = URI("pkl:settings"), settings = URI("pkl:settings"),
powerAssertionsEnabled = true,
) )
val testOpts = CliTestOptions(junitDir = tempDir, junitAggregateReports = true) val testOpts = CliTestOptions(junitDir = tempDir, junitAggregateReports = true)
val runner = CliTestRunner(opts, testOpts, noopWriter, noopWriter) val runner = CliTestRunner(opts, testOpts, noopWriter, noopWriter)
@@ -481,26 +524,30 @@ class CliTestRunnerTest {
assertThat(junitReport) assertThat(junitReport)
.isEqualTo( .isEqualTo(
""" """
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuites name="pkl-tests" tests="5" failures="3"> <testsuites name="pkl-tests" tests="5" failures="3">
<testsuite name="test1" tests="2" failures="1"> <testsuite name="test1" tests="2" failures="1">
<testcase classname="test1.facts" name="foo"></testcase> <testcase classname="test1.facts" name="foo"></testcase>
<testcase classname="test1.facts" name="bar"> <testcase classname="test1.facts" name="bar">
<failure message="Fact Failure">5 == 9 (/tempDir/test1.pkl, line xx)</failure> <failure message="Fact Failure">5 == 9 (/tempDir/test1.pkl, line xx)
</testcase>
</testsuite> false</failure>
<testsuite name="test2" tests="3" failures="2"> </testcase>
<testcase classname="test2.facts" name="xxx"> </testsuite>
<failure message="Fact Failure">false (/tempDir/test2.pkl, line xx)</failure> <testsuite name="test2" tests="3" failures="2">
</testcase> <testcase classname="test2.facts" name="xxx">
<testcase classname="test2.facts" name="yyy"> <failure message="Fact Failure">false (/tempDir/test2.pkl, line xx)
<failure message="Fact Failure">false (/tempDir/test2.pkl, line xx)</failure> </failure>
</testcase> </testcase>
<testcase classname="test2.facts" name="zzz"></testcase> <testcase classname="test2.facts" name="yyy">
</testsuite> <failure message="Fact Failure">false (/tempDir/test2.pkl, line xx)
</testsuites> </failure>
</testcase>
""" <testcase classname="test2.facts" name="zzz"></testcase>
</testsuite>
</testsuites>
"""
.trimIndent() .trimIndent()
) )
} }
@@ -590,7 +637,12 @@ class CliTestRunnerTest {
) )
val out = StringWriter() val out = StringWriter()
val err = StringWriter() val err = StringWriter()
val opts = CliBaseOptions(sourceModules = listOf(input.toUri()), settings = URI("pkl:settings")) val opts =
CliBaseOptions(
sourceModules = listOf(input.toUri()),
settings = URI("pkl:settings"),
powerAssertionsEnabled = true,
)
val testOpts = CliTestOptions() val testOpts = CliTestOptions()
val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err) val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err)
assertThatCode { runner.run() }.hasMessage("Tests failed.") assertThatCode { runner.run() }.hasMessage("Tests failed.")
@@ -629,7 +681,12 @@ class CliTestRunnerTest {
val input = tempDir.resolve("test.pkl").writeString(code).toString() val input = tempDir.resolve("test.pkl").writeString(code).toString()
val out = StringWriter() val out = StringWriter()
val err = StringWriter() val err = StringWriter()
val opts = CliBaseOptions(sourceModules = listOf(input.toUri()), settings = URI("pkl:settings")) val opts =
CliBaseOptions(
sourceModules = listOf(input.toUri()),
settings = URI("pkl:settings"),
powerAssertionsEnabled = true,
)
val testOpts = CliTestOptions() val testOpts = CliTestOptions()
val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err) val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err)
val exception = assertThrows<CliException> { runner.run() } val exception = assertThrows<CliException> { runner.run() }
@@ -669,7 +726,11 @@ class CliTestRunnerTest {
val out = StringWriter() val out = StringWriter()
val err = StringWriter() val err = StringWriter()
val opts = val opts =
CliBaseOptions(sourceModules = listOf(input.toUri()), settings = URI("pkl:settings")) CliBaseOptions(
sourceModules = listOf(input.toUri()),
settings = URI("pkl:settings"),
powerAssertionsEnabled = true,
)
val testOpts = CliTestOptions() val testOpts = CliTestOptions()
val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err) val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err)
runner.run() runner.run()
@@ -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.
@@ -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 options.base.normalizedSourceModules) { for (moduleUri in resolvedSourceModules) {
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 {
@@ -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.
@@ -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.
*/ */
@file:Suppress("unused")
package org.pkl.codegen.java package org.pkl.codegen.java
import com.palantir.javapoet.* import com.palantir.javapoet.*
@@ -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.
@@ -595,10 +595,7 @@ class JavaCodeGeneratorTest {
assertAll( assertAll(
"toString() returns Pkl name", "toString() returns Pkl name",
javaClass.enumConstants.zip(cases) { enumConstant, (pklName, _) -> javaClass.enumConstants.zip(cases) { enumConstant, (pklName, _) ->
{ { assertThat(enumConstant.toString()).isEqualTo(pklName) }
assertThat(enumConstant.toString()).isEqualTo(pklName)
Unit
}
}, },
) )
} }
@@ -2264,7 +2261,7 @@ class JavaCodeGeneratorTest {
} }
private fun Map<String, String>.validateContents( private fun Map<String, String>.validateContents(
vararg assertions: kotlin.Pair<String, List<String>> @Suppress("RemoveRedundantQualifierName") vararg assertions: kotlin.Pair<String, List<String>>
) { ) {
val files = toMutableMap() val files = toMutableMap()
@@ -2289,7 +2286,7 @@ class JavaCodeGeneratorTest {
} }
private fun JavaCodeGeneratorOptions.generateFiles( private fun JavaCodeGeneratorOptions.generateFiles(
vararg pklModules: kotlin.Pair<String, String> @Suppress("RemoveRedundantQualifierName") vararg pklModules: kotlin.Pair<String, String>
): Map<String, String> = ): Map<String, String> =
generateFiles(*pklModules.map { (name, text) -> PklModule(name, text) }.toTypedArray()) generateFiles(*pklModules.map { (name, text) -> PklModule(name, text) }.toTypedArray())
@@ -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.
@@ -32,7 +32,7 @@ class CliKotlinCodeGenerator(private val options: CliKotlinCodeGeneratorOptions)
try { try {
builder.build().use { evaluator -> builder.build().use { evaluator ->
for (moduleUri in options.base.normalizedSourceModules) { for (moduleUri in resolvedSourceModules) {
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.
@@ -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.
*/ */
@file:Suppress("unused")
package org.pkl.codegen.kotlin package org.pkl.codegen.kotlin
import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.*
@@ -66,6 +68,7 @@ class KotlinCodeGenerator(
private val STRING = String::class.asClassName() private val STRING = String::class.asClassName()
private val ANY_NULL = ANY.copy(nullable = true) private val ANY_NULL = ANY.copy(nullable = true)
private val NOTHING = Nothing::class.asClassName() private val NOTHING = Nothing::class.asClassName()
@Suppress("RemoveRedundantQualifierName")
private val KOTLIN_PAIR = kotlin.Pair::class.asClassName() private val KOTLIN_PAIR = kotlin.Pair::class.asClassName()
private val COLLECTION = Collection::class.asClassName() private val COLLECTION = Collection::class.asClassName()
private val LIST = List::class.asClassName() private val LIST = List::class.asClassName()
@@ -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.
@@ -2054,7 +2054,7 @@ class KotlinCodeGeneratorTest {
} }
private fun Map<String, String>.validateContents( private fun Map<String, String>.validateContents(
vararg assertions: kotlin.Pair<String, List<String>> @Suppress("RemoveRedundantQualifierName") vararg assertions: kotlin.Pair<String, List<String>>
) { ) {
val files = toMutableMap() val files = toMutableMap()
@@ -2079,7 +2079,7 @@ class KotlinCodeGeneratorTest {
} }
private fun KotlinCodeGeneratorOptions.generateFiles( private fun KotlinCodeGeneratorOptions.generateFiles(
vararg pklModules: kotlin.Pair<String, String> @Suppress("RemoveRedundantQualifierName") vararg pklModules: kotlin.Pair<String, String>
): Map<String, String> = ): Map<String, String> =
generateFiles(*pklModules.map { (name, text) -> PklModule(name, text) }.toTypedArray()) generateFiles(*pklModules.map { (name, text) -> PklModule(name, text) }.toTypedArray())
@@ -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.
@@ -29,7 +29,7 @@ import org.pkl.core.util.IoUtils
/** Base options shared between CLI commands. */ /** Base options shared between CLI commands. */
data class CliBaseOptions( data class CliBaseOptions(
/** The source modules to evaluate. Relative URIs are resolved against [workingDir]. */ /** The source modules to evaluate. Relative URIs are resolved against [workingDir]. */
private val sourceModules: List<URI> = listOf(), val sourceModules: List<URI> = listOf(),
/** /**
* The URI patterns that determine which modules can be loaded and evaluated. Patterns are matched * The URI patterns that determine which modules can be loaded and evaluated. Patterns are matched
@@ -152,6 +152,9 @@ data class CliBaseOptions(
/** Defines options for the formatting of calls to the trace() method. */ /** Defines options for the formatting of calls to the trace() method. */
val traceMode: TraceMode? = null, val traceMode: TraceMode? = null,
/** Whether power assertions are enabled. */
val powerAssertionsEnabled: Boolean = false,
) { ) {
companion object { companion object {
@@ -172,11 +175,19 @@ data class CliBaseOptions(
/** [rootDir] after normalization. */ /** [rootDir] after normalization. */
val normalizedRootDir: Path? = rootDir?.let(normalizedWorkingDir::resolve) val normalizedRootDir: Path? = rootDir?.let(normalizedWorkingDir::resolve)
/** The effective project directory, if exists. */
val normalizedProjectFile: Path? by lazy {
projectDir?.resolve(ProjectDependenciesManager.PKL_PROJECT_FILENAME)
?: normalizedWorkingDir.getProjectFile(rootDir)
}
/** [sourceModules] after normalization. */ /** [sourceModules] after normalization. */
val normalizedSourceModules: List<URI> = val normalizedSourceModules: List<URI> =
sourceModules sourceModules
.map { uri -> .map { uri ->
if (uri.isAbsolute) uri else IoUtils.resolve(normalizedWorkingDir.toUri(), uri) if (uri.isAbsolute) uri
else if (uri.path.startsWith("@") && !noProject && normalizedProjectFile != null) 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()
@@ -192,12 +203,6 @@ data class CliBaseOptions(
/** [moduleCacheDir] after normalization. */ /** [moduleCacheDir] after normalization. */
val normalizedModuleCacheDir: Path? = moduleCacheDir?.let(normalizedWorkingDir::resolve) val normalizedModuleCacheDir: Path? = moduleCacheDir?.let(normalizedWorkingDir::resolve)
/** The effective project directory, if exists. */
val normalizedProjectFile: Path? by lazy {
projectDir?.resolve(ProjectDependenciesManager.PKL_PROJECT_FILENAME)
?: normalizedWorkingDir.getProjectFile(rootDir)
}
/** [caCertificates] after normalization. */ /** [caCertificates] after normalization. */
val normalizedCaCertificates: List<Path> = caCertificates.map(normalizedWorkingDir::resolve) val normalizedCaCertificates: List<Path> = caCertificates.map(normalizedWorkingDir::resolve)
} }
@@ -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.
@@ -15,6 +15,7 @@
*/ */
package org.pkl.commons.cli package org.pkl.commons.cli
import com.github.ajalt.clikt.core.CliktError
import java.net.URI import java.net.URI
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
@@ -46,6 +47,7 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
proxyAddress?.let(IoUtils::setSystemProxy) proxyAddress?.let(IoUtils::setSystemProxy)
doRun() doRun()
} catch (e: PklException) { } catch (e: PklException) {
if (e.cause is CliktError) throw e.cause!!
throw CliException(e.message!!) throw CliException(e.message!!)
} catch (e: CliException) { } catch (e: CliException) {
throw e throw e
@@ -84,6 +86,36 @@ 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(
@@ -102,10 +134,12 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
cliOptions.timeout, cliOptions.timeout,
stackFrameTransformer, stackFrameTransformer,
envVars, envVars,
cliOptions.powerAssertionsEnabled,
) )
} }
private val evaluatorSettings: PklEvaluatorSettings? by lazy { private val evaluatorSettings: PklEvaluatorSettings? by lazy {
@Suppress("PklCliDirectProjectEvaluatorSettingsAccess")
if (cliOptions.omitProjectSettings) null else project?.evaluatorSettings if (cliOptions.omitProjectSettings) null else project?.evaluatorSettings
} }
@@ -166,34 +200,30 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
) )
} }
protected val useColor: Boolean by lazy { cliOptions.color?.hasColor() ?: false } protected val useColor: Boolean by lazy {
cliOptions.color?.hasColor() ?: evaluatorSettings?.color?.hasColor() ?: false
private val proxyAddress: URI? by lazy {
cliOptions.httpProxy
?: project?.evaluatorSettings?.http?.proxy?.address
?: settings.http?.proxy?.address
} }
private val noProxy: List<String>? by lazy { protected val proxyAddress: URI? by lazy {
cliOptions.httpProxy ?: evaluatorSettings?.http?.proxy?.address ?: settings.http?.proxy?.address
}
protected val noProxy: List<String>? by lazy {
cliOptions.httpNoProxy cliOptions.httpNoProxy
?: project?.evaluatorSettings?.http?.proxy?.noProxy ?: evaluatorSettings?.http?.proxy?.noProxy
?: settings.http?.proxy?.noProxy ?: settings.http?.proxy?.noProxy
} }
private val httpRewrites: Map<URI, URI>? by lazy { protected val httpRewrites: Map<URI, URI>? by lazy {
cliOptions.httpRewrites cliOptions.httpRewrites ?: evaluatorSettings?.http?.rewrites ?: settings.http?.rewrites()
?: project?.evaluatorSettings?.http?.rewrites
?: settings.http?.rewrites()
} }
private val externalModuleReaders: Map<String, PklEvaluatorSettings.ExternalReader> by lazy { protected val externalModuleReaders: Map<String, PklEvaluatorSettings.ExternalReader> by lazy {
(project?.evaluatorSettings?.externalModuleReaders ?: emptyMap()) + (evaluatorSettings?.externalModuleReaders ?: emptyMap()) + cliOptions.externalModuleReaders
cliOptions.externalModuleReaders
} }
private val externalResourceReaders: Map<String, PklEvaluatorSettings.ExternalReader> by lazy { protected val externalResourceReaders: Map<String, PklEvaluatorSettings.ExternalReader> by lazy {
(project?.evaluatorSettings?.externalResourceReaders ?: emptyMap()) + (evaluatorSettings?.externalResourceReaders ?: emptyMap()) + cliOptions.externalResourceReaders
cliOptions.externalResourceReaders
} }
private val externalProcesses: private val externalProcesses:
@@ -207,7 +237,7 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
} }
private val traceMode: TraceMode by lazy { private val traceMode: TraceMode by lazy {
cliOptions.traceMode ?: project?.evaluatorSettings?.traceMode ?: TraceMode.COMPACT cliOptions.traceMode ?: evaluatorSettings?.traceMode ?: TraceMode.COMPACT
} }
private fun HttpClient.Builder.addDefaultCliCertificates() { private fun HttpClient.Builder.addDefaultCliCertificates() {
@@ -308,5 +338,6 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
.setTimeout(cliOptions.timeout) .setTimeout(cliOptions.timeout)
.setModuleCacheDir(moduleCacheDir) .setModuleCacheDir(moduleCacheDir)
.setTraceMode(traceMode) .setTraceMode(traceMode)
.setPowerAssertionsEnabled(cliOptions.powerAssertionsEnabled)
} }
} }
@@ -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.
@@ -17,9 +17,14 @@ package org.pkl.commons.cli.commands
import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.Context
import com.github.ajalt.clikt.core.context
import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.groups.provideDelegate
abstract class BaseCommand(name: String, private val helpLink: String) : CliktCommand(name = name) { abstract class BaseCommand(name: String, private val helpLink: String) : CliktCommand(name = name) {
init {
context { readArgumentFile = null }
}
abstract val helpString: String abstract val helpString: String
override fun help(context: Context) = helpString override fun help(context: Context) = helpString
@@ -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.
@@ -98,7 +98,17 @@ class BaseOptions : OptionGroup() {
private val defaults = CliBaseOptions() private val defaults = CliBaseOptions()
private val output = private val output =
arrayOf("json", "jsonnet", "pcf", "properties", "plist", "textproto", "xml", "yaml") arrayOf(
"json",
"jsonnet",
"pcf",
"properties",
"plist",
"textproto",
"xml",
"yaml",
"pkl-binary",
)
val allowedModules: List<Pattern> by val allowedModules: List<Pattern> by
option( option(
@@ -316,6 +326,7 @@ class BaseOptions : OptionGroup() {
modules: List<URI>, modules: List<URI>,
projectOptions: ProjectOptions? = null, projectOptions: ProjectOptions? = null,
testMode: Boolean = false, testMode: Boolean = false,
powerAssertionsEnabled: Boolean = false,
): CliBaseOptions { ): CliBaseOptions {
return CliBaseOptions( return CliBaseOptions(
sourceModules = modules, sourceModules = modules,
@@ -343,6 +354,7 @@ class BaseOptions : OptionGroup() {
externalModuleReaders = externalModuleReaders, externalModuleReaders = externalModuleReaders,
externalResourceReaders = externalResourceReaders, externalResourceReaders = externalResourceReaders,
traceMode = traceMode, traceMode = traceMode,
powerAssertionsEnabled = powerAssertionsEnabled,
) )
} }
} }
@@ -0,0 +1,25 @@
/*
* 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.
*/
package org.pkl.commons.cli.commands
import com.github.ajalt.clikt.core.NoOpCliktCommand
import com.github.ajalt.clikt.core.context
open class NoOpCommand(name: String? = null) : NoOpCliktCommand(name) {
init {
context { readArgumentFile = null }
}
}
@@ -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.
@@ -27,14 +27,16 @@ import org.pkl.core.Release
private val theme = Theme { styles["markdown.code.span"] = TextStyle(bold = true) } private val theme = Theme { styles["markdown.code.span"] = TextStyle(bold = true) }
fun <T : BaseCliktCommand<T>> T.installCommonOptions() { fun <T : BaseCliktCommand<T>> T.installCommonOptions(includeVersion: Boolean = true) {
installMordantMarkdown() installMordantMarkdown()
versionOption( if (includeVersion) {
Release.current().versionInfo, versionOption(
names = setOf("-v", "--version"), Release.current().versionInfo,
message = { if (commandName == "pkl") it else it.replaceFirst("Pkl", commandName) }, names = setOf("-v", "--version"),
) message = { if (commandName == "pkl") it else it.replaceFirst("Pkl", commandName) },
)
}
context { terminal = Terminal(theme = theme) } context { terminal = Terminal(theme = theme) }
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2025-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,27 +16,54 @@
package org.pkl.commons.cli 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 java.net.URI
import java.nio.file.Path
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.io.TempDir
import org.pkl.commons.cli.commands.BaseCommand import org.pkl.commons.cli.commands.BaseCommand
import org.pkl.commons.cli.commands.ProjectOptions
import org.pkl.commons.writeString
import org.pkl.core.SecurityManagers import org.pkl.core.SecurityManagers
import org.pkl.core.evaluatorSettings.TraceMode
import org.pkl.core.util.IoUtils
@OptIn(ExperimentalPathApi::class)
class CliCommandTest { class CliCommandTest {
class CliTest(private val options: CliBaseOptions) : CliCommand(options) {
override fun doRun() = Unit
val _allowedResources = allowedResources
val _allowedModules = allowedModules
}
private val cmd = private val cmd =
object : BaseCommand("test", "") { object : BaseCommand("test", "") {
val projectOptions: ProjectOptions by ProjectOptions()
override fun run() = Unit override fun run() = Unit
override val helpString: String = "" override val helpString: String = ""
} }
class CliTest(options: CliBaseOptions) : CliCommand(options) {
override fun doRun() = Unit
val myResolvedSourceModules = resolvedSourceModules
val myAllowedModules = allowedModules
val myAllowedResources = allowedResources
val myRootDir = rootDir
val myModulePath = modulePath
val myProxyAddress = proxyAddress
val myNoProxy = noProxy
val myHttpRewrites = httpRewrites
val myExternalModuleReaders = externalModuleReaders
val myExternalResourceReaders = externalResourceReaders
fun myEvaluatorBuilder() = evaluatorBuilder()
@Suppress("PklCliDirectProjectEvaluatorSettingsAccess")
val myProjectEvaluatorSettings = project?.evaluatorSettings
}
@Test @Test
fun `--external-resource-reader and --external-module-reader populate allowed modules and resources`() { fun `--external-resource-reader and --external-module-reader populate allowed modules and resources`() {
cmd.parse( cmd.parse(
@@ -55,17 +82,202 @@ class CliCommandTest {
"scheme+ext=reader5 with args", "scheme+ext=reader5 with args",
) )
) )
val opts = cmd.baseOptions.baseOptions(emptyList(), null, true) val opts = cmd.baseOptions.baseOptions(emptyList(), testMode = true)
val cliTest = CliTest(opts) val cliTest = CliTest(opts)
assertThat(cliTest._allowedModules.map { it.pattern() }) assertThat(cliTest.myAllowedModules.map { it.pattern() })
.isEqualTo( .isEqualTo(
SecurityManagers.defaultAllowedModules.map { it.pattern() } + SecurityManagers.defaultAllowedModules.map { it.pattern() } +
listOf("\\Qscheme3:\\E", "\\Qscheme4:\\E", "\\Qscheme+ext:\\E") listOf("\\Qscheme3:\\E", "\\Qscheme4:\\E", "\\Qscheme+ext:\\E")
) )
assertThat(cliTest._allowedResources.map { it.pattern() }) assertThat(cliTest.myAllowedResources.map { it.pattern() })
.isEqualTo( .isEqualTo(
SecurityManagers.defaultAllowedResources.map { it.pattern() } + SecurityManagers.defaultAllowedResources.map { it.pattern() } +
listOf("\\Qscheme1:\\E", "\\Qscheme2:\\E", "\\Qscheme+ext:\\E") listOf("\\Qscheme1:\\E", "\\Qscheme2:\\E", "\\Qscheme+ext:\\E")
) )
} }
@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 =
"""
amends "pkl:Project"
evaluatorSettings {
externalProperties { ["foo"] = "bar" }
env { ["foo"] = "bar" }
allowedModules { "file:" }
allowedResources { "file:" }
color = "always"
noCache = true
modulePath { "/tmp/modulepath" }
timeout = 30.s
moduleCacheDir = "/tmp/cache"
rootDir = "/tmp/root"
http {
proxy {
address = "http://example.com:80"
noProxy { "example.com" }
}
rewrites {
["https://example.com/foo/"] = "https://example.com/bar/"
}
}
externalModuleReaders {
["foo"] { executable = "foo" }
}
externalResourceReaders {
["foo"] { executable = "foo" }
}
traceMode = "pretty"
}
"""
.trimIndent()
@Test
fun `test that --omit-project-settings actually omits project settings`(@TempDir tempDir: Path) {
val project = tempDir.resolve("PklProject").writeString(projectWithAllEvaluatorSettings)
cmd.parse(arrayOf("--working-dir=$tempDir", "--omit-project-settings"))
val opts =
cmd.baseOptions.baseOptions(listOf(project.toUri()), cmd.projectOptions, testMode = true)
val cliTest = CliTest(opts)
val builder = cliTest.myEvaluatorBuilder()
assertThat(cliTest.myAllowedModules).isEqualTo(SecurityManagers.defaultAllowedModules)
assertThat(cliTest.myAllowedResources).isEqualTo(SecurityManagers.defaultAllowedResources)
assertThat(cliTest.myRootDir).isNull()
assertThat(builder.environmentVariables).isEqualTo(System.getenv())
assertThat(builder.externalProperties).isEmpty()
assertThat(builder.moduleCacheDir).isEqualTo(IoUtils.getDefaultModuleCacheDir())
assertThat(cliTest.myModulePath).isEmpty()
assertThat(builder.color).isFalse
assertThat(cliTest.myProxyAddress).isNull()
assertThat(cliTest.myNoProxy).isNull()
assertThat(cliTest.myHttpRewrites).isNull()
assertThat(cliTest.myExternalModuleReaders).isEmpty()
assertThat(cliTest.myExternalResourceReaders).isEmpty()
assertThat(builder.traceMode).isEqualTo(TraceMode.COMPACT)
}
// hygiene test to ensure new evaluator settings get covered by the above test
@Test
fun `test project sets all evaluator settings`(@TempDir tempDir: Path) {
val project = tempDir.resolve("PklProject").writeString(projectWithAllEvaluatorSettings)
cmd.parse(arrayOf("--working-dir=$tempDir"))
val opts = cmd.baseOptions.baseOptions(listOf(project.toUri()), testMode = true)
val cliTest = CliTest(opts)
cliTest.myProjectEvaluatorSettings
?.javaClass
?.declaredMethods
?.filter { it.parameterCount == 0 }
?.forEach {
assertThat(it.invoke(cliTest.myProjectEvaluatorSettings))
.overridingErrorMessage("project evaluator settings returned null for ${it.name}")
.isNotNull
}
}
} }
@@ -110,7 +110,7 @@ public interface Config {
return fromPklBinary(inputStream, ValueMapper.preconfigured()); return fromPklBinary(inputStream, ValueMapper.preconfigured());
} }
private static Config makeConfig(Object decoded, ValueMapper mapper) { static Config makeConfig(Object decoded, ValueMapper mapper) {
if (decoded instanceof Composite composite) { if (decoded instanceof Composite composite) {
return new CompositeConfig("", mapper, composite); return new CompositeConfig("", mapper, composite);
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2025 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.
@@ -41,6 +41,12 @@ public interface ConfigEvaluator extends AutoCloseable {
/** Evaluates the given module source into a {@link Config} tree. */ /** Evaluates the given module source into a {@link Config} tree. */
Config evaluate(ModuleSource moduleSource); Config evaluate(ModuleSource moduleSource);
/** Evaluates the given module's {@code output.value} property into a {@link Config} tree. */
Config evaluateOutputValue(ModuleSource moduleSource);
/** Evaluates the Pkl expression represented as {@code expression} into a {@link Config} tree. */
Config evaluateExpression(ModuleSource moduleSource, String expression);
/** /**
* Releases all resources held by this evaluator. If an {@code evaluate} method is currently * Releases all resources held by this evaluator. If an {@code evaluate} method is currently
* executing, this method blocks until cancellation of that execution has completed. * executing, this method blocks until cancellation of that execution has completed.
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2025 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.
@@ -34,6 +34,18 @@ final class ConfigEvaluatorImpl implements ConfigEvaluator {
return new CompositeConfig("", mapper, module); return new CompositeConfig("", mapper, module);
} }
@Override
public Config evaluateOutputValue(ModuleSource moduleSource) {
var value = evaluator.evaluateOutputValue(moduleSource);
return Config.makeConfig(value, mapper);
}
@Override
public Config evaluateExpression(ModuleSource moduleSource, String expression) {
var value = evaluator.evaluateExpression(moduleSource, expression);
return Config.makeConfig(value, mapper);
}
@Override @Override
public ValueMapper getValueMapper() { public ValueMapper getValueMapper() {
return mapper; return mapper;
@@ -15,16 +15,20 @@
*/ */
package org.pkl.config.java; package org.pkl.config.java;
import static org.assertj.core.api.Assertions.assertThat;
import static org.pkl.core.ModuleSource.text; import static org.pkl.core.ModuleSource.text;
import org.junit.jupiter.api.Test;
public class ConfigTest extends AbstractConfigTest { public class ConfigTest extends AbstractConfigTest {
private static final ConfigEvaluator evaluator = ConfigEvaluator.preconfigured(); private static final ConfigEvaluator evaluator = ConfigEvaluator.preconfigured();
private static final String pigeonText =
"pigeon { age = 30; friends = List(\"john\", \"mary\"); address { street = \"Fuzzy St.\" } }";
@Override @Override
protected Config getPigeonConfig() { protected Config getPigeonConfig() {
return evaluator.evaluate( return evaluator.evaluate(text(pigeonText));
text(
"pigeon { age = 30; friends = List(\"john\", \"mary\"); address { street = \"Fuzzy St.\" } }"));
} }
@Override @Override
@@ -42,4 +46,20 @@ public class ConfigTest extends AbstractConfigTest {
protected Config getMapConfig() { protected Config getMapConfig() {
return evaluator.evaluate(text("x = Map(\"one\", 1, \"two\", 2)")); return evaluator.evaluate(text("x = Map(\"one\", 1, \"two\", 2)"));
} }
@Test
public void evaluateOutputValue() {
var valueConfig =
evaluator.evaluateOutputValue(
text(pigeonText + "\noutput { value = (outer) { pigeon { age = 99 } } }"));
var pigeon = valueConfig.get("pigeon").as(Person.class);
assertThat(pigeon.age).isEqualTo(99);
}
@Test
public void evaluateExpression() {
var addressConfig = evaluator.evaluateExpression(text(pigeonText), "pigeon.address");
var address = addressConfig.as(Address.class);
assertThat(address.street).isEqualTo("Fuzzy St.");
}
} }
@@ -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.
@@ -89,6 +89,7 @@ public class JavaTypeTest {
assertThat(javaType.getType()).isEqualTo(Types.mapOf(String.class, Types.listOf(URI.class))); assertThat(javaType.getType()).isEqualTo(Types.mapOf(String.class, Types.listOf(URI.class)));
} }
@SuppressWarnings({"EqualsWithItself", "AssertBetweenInconvertibleTypes"})
@Test @Test
public void sameTypesConstructedInDifferentWaysAreEqual() { public void sameTypesConstructedInDifferentWaysAreEqual() {
var type1 = JavaType.mapOf(JavaType.of(String.class), JavaType.listOf(URI.class)); var type1 = JavaType.mapOf(JavaType.of(String.class), JavaType.listOf(URI.class));
@@ -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.
@@ -28,46 +28,51 @@ import org.pkl.core.DurationUnit;
public class ConversionsTest { public class ConversionsTest {
@Test @Test
public void pStringToFile() { public void pStringToFile() {
var file = Conversions.pStringToFile.converter.convert("relative/path", null); var file =
Conversions.pStringToFile.converter.convert("relative/path", ValueMapper.preconfigured());
assertThat(file).isEqualTo(new File("relative/path")); assertThat(file).isEqualTo(new File("relative/path"));
var file2 = Conversions.pStringToFile.converter.convert("/absolute/path", null); var file2 =
Conversions.pStringToFile.converter.convert("/absolute/path", ValueMapper.preconfigured());
assertThat(file2).isEqualTo(new File("/absolute/path")); assertThat(file2).isEqualTo(new File("/absolute/path"));
var file3 = Conversions.pStringToFile.converter.convert("", null); var file3 = Conversions.pStringToFile.converter.convert("", ValueMapper.preconfigured());
assertThat(file3).isEqualTo(new File("")); assertThat(file3).isEqualTo(new File(""));
} }
@Test @Test
public void pStringToPath() { public void pStringToPath() {
var path = Conversions.pStringToPath.converter.convert("relative/path", null); var path =
Conversions.pStringToPath.converter.convert("relative/path", ValueMapper.preconfigured());
assertThat(path).isEqualTo(Path.of("relative/path")); assertThat(path).isEqualTo(Path.of("relative/path"));
var path2 = Conversions.pStringToPath.converter.convert("/absolute/path", null); var path2 =
Conversions.pStringToPath.converter.convert("/absolute/path", ValueMapper.preconfigured());
assertThat(path2).isEqualTo(Path.of("/absolute/path")); assertThat(path2).isEqualTo(Path.of("/absolute/path"));
var path3 = Conversions.pStringToPath.converter.convert("", null); var path3 = Conversions.pStringToPath.converter.convert("", ValueMapper.preconfigured());
assertThat(path3).isEqualTo(Path.of("")); assertThat(path3).isEqualTo(Path.of(""));
} }
@Test @Test
public void pStringToPattern() { public void pStringToPattern() {
var str = "(?i)\\w*"; var str = "(?i)\\w*";
var pattern = Conversions.pStringToPattern.converter.convert(str, null); var pattern = Conversions.pStringToPattern.converter.convert(str, ValueMapper.preconfigured());
assertThat(pattern.pattern()).isEqualTo(str); assertThat(pattern.pattern()).isEqualTo(str);
} }
@Test @Test
public void pRegexToString() { public void pRegexToString() {
var regex = Pattern.compile("(?i)\\w*"); var regex = Pattern.compile("(?i)\\w*");
var str = Conversions.pRegexToString.converter.convert(regex, null); var str = Conversions.pRegexToString.converter.convert(regex, ValueMapper.preconfigured());
assertThat(str).isEqualTo("(?i)\\w*"); assertThat(str).isEqualTo("(?i)\\w*");
} }
@Test @Test
public void pDurationToDuration() { public void pDurationToDuration() {
var pDuration = new Duration(100, DurationUnit.MINUTES); var pDuration = new Duration(100, DurationUnit.MINUTES);
var duration = Conversions.pDurationToDuration.converter.convert(pDuration, null); var duration =
Conversions.pDurationToDuration.converter.convert(pDuration, ValueMapper.preconfigured());
assertThat(duration).isEqualTo(java.time.Duration.of(100, ChronoUnit.MINUTES)); assertThat(duration).isEqualTo(java.time.Duration.of(100, ChronoUnit.MINUTES));
} }
} }
@@ -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.
@@ -31,7 +31,7 @@ public class PModuleToDataObjectTest {
private static final PModule module = private static final PModule module =
evaluator.evaluate(modulePath("org/pkl/config/java/mapper/PModuleToDataObjectTest.pkl")); evaluator.evaluate(modulePath("org/pkl/config/java/mapper/PModuleToDataObjectTest.pkl"));
PObjectToDataObjectTest.Person pigeon = private final PObjectToDataObjectTest.Person pigeon =
new PObjectToDataObjectTest.Person( new PObjectToDataObjectTest.Person(
"pigeon", "pigeon",
40, 40,
@@ -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.
@@ -24,6 +24,7 @@ import org.pkl.core.PNull;
public class PNullToAnyTest { public class PNullToAnyTest {
private static final ValueMapper mapper = ValueMapperBuilder.preconfigured().build(); private static final ValueMapper mapper = ValueMapperBuilder.preconfigured().build();
@SuppressWarnings("DataFlowIssue")
@Test @Test
public void test() { public void test() {
// due to Conversions.identities // due to Conversions.identities
@@ -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.
@@ -120,7 +120,8 @@ public class Analyzer {
? null ? null
: new ProjectDependenciesManager( : new ProjectDependenciesManager(
projectDependencies, moduleResolver, securityManager), projectDependencies, moduleResolver, securityManager),
traceMode)); traceMode,
false));
}); });
} }
} }
@@ -0,0 +1,158 @@
/*
* Copyright © 2025-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.
*/
package org.pkl.core;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.pkl.core.util.Nullable;
public record CommandSpec(
String name,
@Nullable String helpText,
boolean hidden,
boolean noOp,
Iterable<Option> options,
List<CommandSpec> subcommands,
ApplyFunction apply) {
public sealed interface Option {
String name();
String[] getNames();
class MissingOption extends RuntimeException {
public MissingOption() {}
}
class BadValue extends RuntimeException {
public BadValue(String message) {
super(message);
}
public static BadValue invalid(String value, String type) {
return new BadValue(String.format("%s is not a valid %s", value, type));
}
public static BadValue badKeyValue(String value) {
return new BadValue(String.format("%s is not a valid key=value pair", value));
}
public static BadValue invalidChoice(String value, List<String> choices) {
return new BadValue(
String.format(
"invalid choice: %s. (choose from %s)", value, String.join(", ", choices)));
}
public static BadValue invalidChoice(String value, String choice) {
return new BadValue(String.format("invalid choice: %s. (choose from %s)", value, choice));
}
}
}
public abstract static sealed class CompletionCandidates {
public static final CompletionCandidates PATH = new StaticCompletionCandidates();
public static final class Fixed extends CompletionCandidates {
private final Set<String> values;
public Fixed(Set<String> values) {
this.values = values;
}
public Set<String> getValues() {
return values;
}
}
private static final class StaticCompletionCandidates extends CompletionCandidates {}
}
public record Flag(
String name,
@Nullable String helpText,
boolean showAsRequired,
BiFunction<String, URI, Object> transformEach,
BiFunction<List<Object>, URI, Object> transformAll,
@Nullable CompletionCandidates completionCandidates,
@Nullable String shortName,
String metavar,
boolean hidden,
@Nullable String defaultValue)
implements Option {
@Override
public String[] getNames() {
return shortName == null
? new String[] {"--" + name}
: new String[] {"-" + shortName, "--" + name};
}
}
public record BooleanFlag(
String name,
@Nullable String helpText,
@Nullable String shortName,
boolean hidden,
@Nullable Boolean defaultValue)
implements Option {
@Override
public String[] getNames() {
return shortName == null
? new String[] {"--" + name}
: new String[] {"-" + shortName, "--" + name};
}
}
public record CountedFlag(
String name, @Nullable String helpText, @Nullable String shortName, boolean hidden)
implements Option {
@Override
public String[] getNames() {
return shortName == null
? new String[] {"--" + name}
: new String[] {"-" + shortName, "--" + name};
}
}
public record Argument(
String name,
@Nullable String helpText,
BiFunction<String, URI, Object> transformEach,
BiFunction<List<Object>, URI, Object> transformAll,
@Nullable CompletionCandidates completionCandidates,
boolean repeated)
implements Option {
@Override
public String[] getNames() {
return new String[] {name};
}
}
public interface ApplyFunction {
State apply(Map<String, Object> options, @Nullable State parent);
}
public record State(Object contents, Function<Object, Result> reify) {
public Result evaluate() {
return reify.apply(contents);
}
}
public record Result(byte[] outputBytes, Map<String, FileOutput> outputFiles) {}
}
@@ -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.
@@ -16,6 +16,8 @@
package org.pkl.core; package org.pkl.core;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import org.pkl.core.runtime.VmEvalException; import org.pkl.core.runtime.VmEvalException;
/** /**
@@ -224,6 +226,24 @@ public interface Evaluator extends AutoCloseable {
*/ */
TestResults evaluateTest(ModuleSource moduleSource, boolean overwrite); TestResults evaluateTest(ModuleSource moduleSource, boolean overwrite);
/**
* Parses the command module into a spec that describes the CLI options and subcommands.
*
* <p>This requires that the target module be a {@code "pkl:Command"} instance.
*
* <p>Unlike other evaluator methods, the resulting {@link CommandSpec} must be handled in a
* closure. This is because specs must be applied to parsed CLI options to produce command state
* that is eventually evaluated, which must happen in the active context of an evaluator.
*
* @throws PklException if an error occurs during evaluation
* @throws IllegalStateException if this evaluator has already been closed
*/
void evaluateCommand(
ModuleSource moduleSource,
Set<String> reservedFlagNames,
Set<String> reservedFlagShortNames,
Consumer<CommandSpec> run);
/** /**
* Releases all resources held by this evaluator. If an {@code evaluate} method is currently * Releases all resources held by this evaluator. If an {@code evaluate} method is currently
* executing, this method blocks until cancellation of that execution has completed. * executing, this method blocks until cancellation of that execution has completed.
@@ -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.
@@ -70,6 +70,8 @@ public final class EvaluatorBuilder {
private TraceMode traceMode = TraceMode.COMPACT; private TraceMode traceMode = TraceMode.COMPACT;
private boolean powerAssertionsEnabled = false;
private EvaluatorBuilder() {} private EvaluatorBuilder() {}
/** /**
@@ -468,6 +470,17 @@ public final class EvaluatorBuilder {
return this.traceMode; return this.traceMode;
} }
/** Sets whether power assertions are enabled. */
public EvaluatorBuilder setPowerAssertionsEnabled(boolean powerAssertions) {
this.powerAssertionsEnabled = powerAssertions;
return this;
}
/** Returns whether power assertions are enabled. */
public boolean getPowerAssertionsEnabled() {
return powerAssertionsEnabled;
}
/** /**
* Given a project, sets its dependencies, and also applies any evaluator settings if set. * Given a project, sets its dependencies, and also applies any evaluator settings if set.
* *
@@ -578,6 +591,7 @@ public final class EvaluatorBuilder {
moduleCacheDir, moduleCacheDir,
dependencies, dependencies,
outputFormat, outputFormat,
traceMode); traceMode,
powerAssertionsEnabled);
} }
} }
@@ -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.
@@ -15,16 +15,16 @@
*/ */
package org.pkl.core; package org.pkl.core;
import com.oracle.truffle.api.TruffleStackTrace;
import java.io.IOException; import java.io.IOException;
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;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
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;
@@ -40,6 +40,7 @@ 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;
import org.pkl.core.runtime.BaseModule; import org.pkl.core.runtime.BaseModule;
import org.pkl.core.runtime.CommandSpecParser;
import org.pkl.core.runtime.Identifier; import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.ModuleResolver; import org.pkl.core.runtime.ModuleResolver;
import org.pkl.core.runtime.ResourceManager; import org.pkl.core.runtime.ResourceManager;
@@ -48,8 +49,6 @@ import org.pkl.core.runtime.VmContext;
import org.pkl.core.runtime.VmException; import org.pkl.core.runtime.VmException;
import org.pkl.core.runtime.VmExceptionBuilder; import org.pkl.core.runtime.VmExceptionBuilder;
import org.pkl.core.runtime.VmLanguage; import org.pkl.core.runtime.VmLanguage;
import org.pkl.core.runtime.VmMapping;
import org.pkl.core.runtime.VmNull;
import org.pkl.core.runtime.VmPklBinaryEncoder; import org.pkl.core.runtime.VmPklBinaryEncoder;
import org.pkl.core.runtime.VmStackOverflowException; import org.pkl.core.runtime.VmStackOverflowException;
import org.pkl.core.runtime.VmTyped; import org.pkl.core.runtime.VmTyped;
@@ -86,7 +85,8 @@ public final class EvaluatorImpl implements Evaluator {
@Nullable Path moduleCacheDir, @Nullable Path moduleCacheDir,
@Nullable DeclaredDependencies projectDependencies, @Nullable DeclaredDependencies projectDependencies,
@Nullable String outputFormat, @Nullable String outputFormat,
TraceMode traceMode) { TraceMode traceMode,
boolean powerAssertions) {
securityManager = manager; securityManager = manager;
frameTransformer = transformer; frameTransformer = transformer;
@@ -115,7 +115,8 @@ public final class EvaluatorImpl implements Evaluator {
? null ? null
: new ProjectDependenciesManager( : new ProjectDependenciesManager(
projectDependencies, moduleResolver, securityManager), projectDependencies, moduleResolver, securityManager),
traceMode)); traceMode,
powerAssertions));
}); });
this.timeout = timeout; this.timeout = timeout;
// NOTE: would probably make sense to share executor between evaluators // NOTE: would probably make sense to share executor between evaluators
@@ -146,7 +147,7 @@ public final class EvaluatorImpl implements Evaluator {
return doEvaluate( return doEvaluate(
moduleSource, moduleSource,
(module) -> { (module) -> {
var output = readModuleOutput(module); var output = VmUtils.readModuleOutput(module);
return VmUtils.readTextProperty(output); return VmUtils.readTextProperty(output);
}); });
} }
@@ -155,7 +156,7 @@ public final class EvaluatorImpl implements Evaluator {
return doEvaluate( return doEvaluate(
moduleSource, moduleSource,
(module) -> { (module) -> {
var output = readModuleOutput(module); var output = VmUtils.readModuleOutput(module);
var vmBytes = VmUtils.readBytesProperty(output); var vmBytes = VmUtils.readBytesProperty(output);
return vmBytes.export(); return vmBytes.export();
}); });
@@ -166,7 +167,7 @@ public final class EvaluatorImpl implements Evaluator {
return doEvaluate( return doEvaluate(
moduleSource, moduleSource,
(module) -> { (module) -> {
var output = readModuleOutput(module); var output = VmUtils.readModuleOutput(module);
var value = VmUtils.readMember(output, Identifier.VALUE); var value = VmUtils.readMember(output, Identifier.VALUE);
if (value instanceof VmValue vmValue) { if (value instanceof VmValue vmValue) {
vmValue.force(false); vmValue.force(false);
@@ -181,20 +182,9 @@ public final class EvaluatorImpl implements Evaluator {
return doEvaluate( return doEvaluate(
moduleSource, moduleSource,
(module) -> { (module) -> {
var output = readModuleOutput(module); var output = VmUtils.readModuleOutput(module);
var filesOrNull = VmUtils.readMember(output, Identifier.FILES); return VmUtils.readFilesProperty(
if (filesOrNull instanceof VmNull) { output, (fileOutput) -> new FileOutputImpl(this, fileOutput));
return Map.of();
}
var files = (VmMapping) filesOrNull;
var result = new LinkedHashMap<String, FileOutput>();
files.forceAndIterateMemberValues(
(key, member, value) -> {
assert member.isEntry();
result.put((String) key, new FileOutputImpl(this, (VmTyped) value));
return true;
});
return result;
}); });
} }
@@ -237,10 +227,10 @@ public final class EvaluatorImpl implements Evaluator {
var expressionResult = var expressionResult =
switch (expression) { switch (expression) {
case "module" -> module; case "module" -> module;
case "output.text" -> VmUtils.readTextProperty(readModuleOutput(module)); case "output.text" -> VmUtils.readTextProperty(VmUtils.readModuleOutput(module));
case "output.value" -> case "output.value" ->
VmUtils.readMember(readModuleOutput(module), Identifier.VALUE); VmUtils.readMember(VmUtils.readModuleOutput(module), Identifier.VALUE);
case "output.bytes" -> VmUtils.readBytesProperty(readModuleOutput(module)); case "output.bytes" -> VmUtils.readBytesProperty(VmUtils.readModuleOutput(module));
default -> default ->
VmUtils.evaluateExpression(module, expression, securityManager, moduleResolver); VmUtils.evaluateExpression(module, expression, securityManager, moduleResolver);
}; };
@@ -287,12 +277,35 @@ public final class EvaluatorImpl implements Evaluator {
}); });
} }
@Override
public void evaluateCommand(
ModuleSource moduleSource,
Set<String> reservedFlagNames,
Set<String> reservedFlagShortNames,
Consumer<CommandSpec> run) {
doEvaluate(
moduleSource,
(module) -> {
var commandRunner =
new CommandSpecParser(
moduleResolver,
securityManager,
frameTransformer,
color,
reservedFlagNames,
reservedFlagShortNames,
(fileOutput) -> new FileOutputImpl(this, fileOutput));
run.accept(commandRunner.parse(module));
return null;
});
}
@Override @Override
public <T> T evaluateOutputValueAs(ModuleSource moduleSource, PClassInfo<T> classInfo) { public <T> T evaluateOutputValueAs(ModuleSource moduleSource, PClassInfo<T> classInfo) {
return doEvaluate( return doEvaluate(
moduleSource, moduleSource,
(module) -> { (module) -> {
var output = readModuleOutput(module); var output = VmUtils.readModuleOutput(module);
var value = VmUtils.readMember(output, Identifier.VALUE); var value = VmUtils.readMember(output, Identifier.VALUE);
var valueClassInfo = VmUtils.getClass(value).getPClassInfo(); var valueClassInfo = VmUtils.getClass(value).getPClassInfo();
if (valueClassInfo.equals(classInfo)) { if (valueClassInfo.equals(classInfo)) {
@@ -323,6 +336,16 @@ public final class EvaluatorImpl implements Evaluator {
} }
} }
// for use in tests to determine whether an evaluator ever triggered instrumentation
boolean isInstrumentationEverUsed() {
polyglotContext.enter();
try {
return VmLanguage.get(null).localContext.get().isInstrumentationEverUsed();
} finally {
polyglotContext.leave();
}
}
String evaluateOutputText(VmTyped fileOutput) { String evaluateOutputText(VmTyped fileOutput) {
return doEvaluate(() -> VmUtils.readTextProperty(fileOutput)); return doEvaluate(() -> VmUtils.readTextProperty(fileOutput));
} }
@@ -353,7 +376,7 @@ public final class EvaluatorImpl implements Evaluator {
try { try {
evalResult = supplier.get(); evalResult = supplier.get();
} catch (VmStackOverflowException e) { } catch (VmStackOverflowException e) {
if (isPklBug(e)) { if (VmUtils.isPklBug(e)) {
throw new VmExceptionBuilder() throw new VmExceptionBuilder()
.bug("Stack overflow") .bug("Stack overflow")
.withCause(e.getCause()) .withCause(e.getCause())
@@ -365,6 +388,9 @@ public final class EvaluatorImpl implements Evaluator {
} catch (VmException e) { } catch (VmException e) {
handleTimeout(timeoutTask); handleTimeout(timeoutTask);
throw e.toPklException(frameTransformer, color); throw e.toPklException(frameTransformer, color);
} catch (PklException e) {
// evaluateCommand can throw PklException from the CLI layer, pass them through
throw e;
} catch (Exception e) { } catch (Exception e) {
throw new PklBugException(e); throw new PklBugException(e);
} catch (ExceptionInInitializerError e) { } catch (ExceptionInInitializerError e) {
@@ -379,7 +405,7 @@ public final class EvaluatorImpl implements Evaluator {
if (e.getClass() if (e.getClass()
.getName() .getName()
.equals("com.oracle.truffle.polyglot.PolyglotEngineImpl$CancelExecution")) { .equals("com.oracle.truffle.polyglot.PolyglotEngineImpl$CancelExecution")) {
// Truffle cancelled evaluation in response to polyglotContext.close(true) triggered by // Truffle canceled evaluation in response to polyglotContext.close(true) triggered by
// TimeoutTask // TimeoutTask
handleTimeout(timeoutTask); handleTimeout(timeoutTask);
throw PklBugException.unreachableCode(); throw PklBugException.unreachableCode();
@@ -390,7 +416,7 @@ public final class EvaluatorImpl implements Evaluator {
try { try {
polyglotContext.leave(); polyglotContext.leave();
} catch (IllegalStateException ignored) { } catch (IllegalStateException ignored) {
// happens if evaluation has already been cancelled with polyglotContext.close(true) // happens if evaluation has already been canceled with polyglotContext.close(true)
} }
} }
@@ -418,32 +444,6 @@ public final class EvaluatorImpl implements Evaluator {
"evaluationTimedOut", (timeout.getSeconds() + timeout.getNano() / 1_000_000_000d))); "evaluationTimedOut", (timeout.getSeconds() + timeout.getNano() / 1_000_000_000d)));
} }
private VmTyped readModuleOutput(VmTyped module) {
var value = VmUtils.readMember(module, Identifier.OUTPUT);
if (value instanceof VmTyped typedOutput
&& typedOutput.getVmClass().getPClassInfo() == PClassInfo.ModuleOutput) {
return typedOutput;
}
var moduleUri = module.getModuleInfo().getModuleKey().getUri();
var builder =
new VmExceptionBuilder()
.evalError(
"invalidModuleOutput",
"output",
PClassInfo.ModuleOutput.getDisplayName(),
VmUtils.getClass(value).getPClassInfo().getDisplayName(),
moduleUri);
var outputMember = module.getMember(Identifier.OUTPUT);
assert outputMember != null;
var uriOfValueMember = outputMember.getSourceSection().getSource().getURI();
// If `output` was explicitly re-assigned, show that in the stack trace.
if (!uriOfValueMember.equals(PClassInfo.pklBaseUri)) {
builder.withSourceSection(outputMember.getBodySection()).withMemberName("output");
}
throw builder.build();
}
private VmException moduleOutputValueTypeMismatch( private VmException moduleOutputValueTypeMismatch(
VmTyped module, PClassInfo<?> expectedClassInfo, Object value, VmTyped output) { VmTyped module, PClassInfo<?> expectedClassInfo, Object value, VmTyped output) {
var moduleUri = module.getModuleInfo().getModuleKey().getUri(); var moduleUri = module.getModuleInfo().getModuleKey().getUri();
@@ -482,15 +482,6 @@ public final class EvaluatorImpl implements Evaluator {
} }
} }
private boolean isPklBug(VmStackOverflowException e) {
// There's no good way to tell if a StackOverflowError came from Pkl, or from our
// implementation.
// This is a simple heuristic; it's pretty likely that any stack overflow error that occurs
// if there's less than 100 truffle frames is due to our own doing.
var truffleStackTraceElements = TruffleStackTrace.getStackTrace(e);
return truffleStackTraceElements != null && truffleStackTraceElements.size() < 100;
}
// ScheduledFuture.cancel() is problematic, so let's handle cancellation on our own // ScheduledFuture.cancel() is problematic, so let's handle cancellation on our own
private final class TimeoutTask implements Runnable { private final class TimeoutTask implements Runnable {
// both fields guarded by synchronizing on `this` // both fields guarded by synchronizing on `this`
@@ -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.
@@ -105,7 +105,8 @@ final class JsonRenderer implements ValueRenderer {
@Override @Override
public void visitBytes(byte[] value) { public void visitBytes(byte[] value) {
throw new RendererException( throw new RendererException(
String.format("Values of type `Bytes` cannot be rendered as JSON. Value: %s", value)); String.format(
"Values of type `Bytes` cannot be rendered as JSON. Value: %s", (Object) value));
} }
@Override @Override
@@ -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.
@@ -110,7 +110,8 @@ final class PropertiesRenderer implements ValueRenderer {
public String convertBytes(byte[] value) { public String convertBytes(byte[] value) {
throw new RendererException( throw new RendererException(
String.format( String.format(
"Values of type `Bytes` cannot be rendered as Properties. Value: %s", value)); "Values of type `Bytes` cannot be rendered as Properties. Value: %s",
(Object) value));
} }
@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,7 +15,10 @@
*/ */
package org.pkl.core; package org.pkl.core;
import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.nio.file.Path;
import org.pkl.core.util.Nullable;
/** /**
* Enforces a security model during {@link Evaluator evaluation}. * Enforces a security model during {@link Evaluator evaluation}.
@@ -40,4 +43,38 @@ public interface SecurityManager {
* to access the given URI. * to access the given URI.
*/ */
void checkResolveResource(URI resource) throws SecurityManagerException; void checkResolveResource(URI resource) throws SecurityManagerException;
/**
* Resolves the given {@code file:} URI to a secure, symlink-free path that has been verified to
* be within the root directory (if one is configured). The returned path can be opened with
* {@link java.nio.file.LinkOption#NOFOLLOW_LINKS}.
*
* <p>Returns {@code null} for non-{@code file:} URIs or if no root directory is configured.
*
* @param uri the URI to resolve
* @param isResource denotes if uri belongs to a resource (otherwise, a module)
* @return the resolved, symlink-free path under root directory, or {@code null}
* @throws SecurityManagerException if the resolved path is not within the root directory
* @throws IOException if the path cannot be resolved
*/
default @Nullable Path resolveSecurePath(URI uri, boolean isResource)
throws SecurityManagerException, IOException {
return null;
}
/**
* Resolves the given {@code file:} URI to a secure, symlink-free path that has been verified to
* be within the root directory (if one is configured). The returned path can be opened with
* {@link java.nio.file.LinkOption#NOFOLLOW_LINKS}.
*
* <p>Returns {@code null} for non-{@code file:} URIs or if no root directory is configured.
*
* @param uri the URI to resolve
* @return the resolved, symlink-free path under root directory, or {@code null}
* @throws SecurityManagerException if the resolved path is not within the root directory
* @throws IOException if the path cannot be resolved
*/
default @Nullable Path resolveSecurePath(URI uri) throws SecurityManagerException, IOException {
return resolveSecurePath(uri, false);
}
} }
@@ -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.
@@ -24,6 +24,7 @@ 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.pkl.core.util.ErrorMessages; import org.pkl.core.util.ErrorMessages;
import org.pkl.core.util.IoUtils;
import org.pkl.core.util.Nullable; import org.pkl.core.util.Nullable;
/** A provider for {@link SecurityManager}s. */ /** A provider for {@link SecurityManager}s. */
@@ -171,6 +172,25 @@ public final class SecurityManagers {
} }
} }
@Override
public @Nullable Path resolveSecurePath(URI uri, boolean isResource)
throws SecurityManagerException, IOException {
if (rootDir == null
|| !uri.isAbsolute()
|| !uri.getScheme().equals("file")
|| (uri.getAuthority() != null && !uri.getAuthority().isEmpty())) {
return null;
}
var path = Path.of(uri);
var realPath = path.toRealPath();
if (!realPath.startsWith(rootDir)) {
var errorMessageKey = isResource ? "resourcePastRootDir" : "modulePastRootDir";
var message = ErrorMessages.create(errorMessageKey, uri, rootDir);
throw new SecurityManagerException(message);
}
return realPath;
}
private @Nullable Path normalizePath(@Nullable Path path) { private @Nullable Path normalizePath(@Nullable Path path) {
if (path == null) { if (path == null) {
return null; return null;
@@ -200,13 +220,27 @@ public final class SecurityManagers {
} }
private void checkIsUnderRootDir(URI uri, boolean isResource) throws SecurityManagerException { private void checkIsUnderRootDir(URI uri, boolean isResource) throws SecurityManagerException {
if (!uri.isAbsolute()) { // handle jar:file: URIs correctly:
throw new AssertionError("Expected absolute URI but got: " + uri); var checkUri =
uri.getScheme().equals("jar") ? IoUtils.createUri(uri.getSchemeSpecificPart()) : uri;
if (!checkUri.isAbsolute()) {
throw new AssertionError("Expected absolute URI but got: " + checkUri);
} }
if (rootDir == null || !uri.getScheme().equals("file")) return; if (rootDir == null || !checkUri.getScheme().equals("file")) return;
var path = Path.of(checkUri);
// uri represents a UNC path if authority is non-null
// so treat this like a potentially redirected HTTP read:
// check if both the given and real paths are under rootDir
if (checkUri.getAuthority() != null && !checkUri.getAuthority().isEmpty()) {
doCheckIsUnderRootDir(path.normalize(), uri, isResource);
}
// if given path is under rootDir, do I/O to determine if the real path is under the root dir
// this can result in a nasty timeout (~20s) in Files.exists if the server doesn't respond :(
var path = Path.of(uri);
if (Files.exists(path)) { if (Files.exists(path)) {
try { try {
path = path.toRealPath(); path = path.toRealPath();
@@ -219,6 +253,12 @@ public final class SecurityManagers {
path = path.normalize(); path = path.normalize();
} }
doCheckIsUnderRootDir(path, uri, isResource);
}
private void doCheckIsUnderRootDir(Path path, URI uri, boolean isResource)
throws SecurityManagerException {
assert rootDir != null;
if (!path.startsWith(rootDir)) { if (!path.startsWith(rootDir)) {
var errorMessageKey = isResource ? "resourcePastRootDir" : "modulePastRootDir"; var errorMessageKey = isResource ? "resourcePastRootDir" : "modulePastRootDir";
var message = ErrorMessages.create(errorMessageKey, uri, rootDir); var message = ErrorMessages.create(errorMessageKey, uri, rootDir);
@@ -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,12 +16,18 @@
package org.pkl.core.ast; package org.pkl.core.ast;
import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrumentation.GenerateWrapper;
import com.oracle.truffle.api.instrumentation.InstrumentableNode;
import com.oracle.truffle.api.instrumentation.ProbeNode;
import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.source.SourceSection;
import org.pkl.core.runtime.PklTags;
import org.pkl.core.runtime.VmTypesGen; import org.pkl.core.runtime.VmTypesGen;
import org.pkl.core.runtime.VmUtils; import org.pkl.core.runtime.VmUtils;
public abstract class ExpressionNode extends PklNode { @GenerateWrapper
public abstract class ExpressionNode extends PklNode implements InstrumentableNode {
protected ExpressionNode(SourceSection sourceSection) { protected ExpressionNode(SourceSection sourceSection) {
super(sourceSection); super(sourceSection);
} }
@@ -43,4 +49,19 @@ public abstract class ExpressionNode extends PklNode {
public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException {
return VmTypesGen.expectBoolean(executeGeneric(frame)); return VmTypesGen.expectBoolean(executeGeneric(frame));
} }
@Override
public boolean hasTag(Class<? extends Tag> tag) {
return tag == PklTags.Expression.class;
}
@Override
public boolean isInstrumentable() {
return true;
}
@Override
public WrapperNode createWrapper(ProbeNode probe) {
return new ExpressionNodeWrapper(this, probe);
}
} }
@@ -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.
@@ -16,6 +16,7 @@
package org.pkl.core.ast; package org.pkl.core.ast;
import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.source.SourceSection;
import org.pkl.core.ast.member.DefaultPropertyBodyNode; import org.pkl.core.ast.member.DefaultPropertyBodyNode;
import org.pkl.core.runtime.VmExceptionBuilder; import org.pkl.core.runtime.VmExceptionBuilder;
@@ -46,7 +47,8 @@ public abstract class MemberNode extends PklRootNode {
return new VmExceptionBuilder().withSourceSection(getHeaderSection()); return new VmExceptionBuilder().withSourceSection(getHeaderSection());
} }
public boolean isUndefined() { public boolean isUndefined(VirtualFrame frame) {
return bodyNode instanceof DefaultPropertyBodyNode propBodyNode && propBodyNode.isUndefined(); return bodyNode instanceof DefaultPropertyBodyNode propBodyNode
&& propBodyNode.isUndefined(frame);
} }
} }
@@ -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.core.ast;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.dsl.TypeSystemReference;
import com.oracle.truffle.api.instrumentation.InstrumentableNode.WrapperNode;
import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.source.SourceSection;
@@ -38,7 +39,10 @@ public abstract class PklNode extends Node {
} }
@Override @Override
public SourceSection getSourceSection() { public final SourceSection getSourceSection() {
if (this instanceof WrapperNode wrapperNode) {
return wrapperNode.getDelegateNode().getSourceSection();
}
return sourceSection; return sourceSection;
} }
@@ -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.
@@ -146,6 +146,10 @@ public final class VmModifier {
return (modifiers & (LOCAL | EXTERNAL | ABSTRACT)) != 0; return (modifiers & (LOCAL | EXTERNAL | ABSTRACT)) != 0;
} }
public static boolean isLocalOrExternalOrAbstractOrFixedOrConst(int modifiers) {
return (modifiers & (LOCAL | EXTERNAL | ABSTRACT | FIXED | CONST)) != 0;
}
public static boolean isConstOrFixed(int modifiers) { public static boolean isConstOrFixed(int modifiers) {
return (modifiers & (CONST | FIXED)) != 0; return (modifiers & (CONST | FIXED)) != 0;
} }
@@ -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.
@@ -2449,8 +2449,7 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
if (dataSizeUnit != null) { if (dataSizeUnit != null) {
//noinspection ConstantConditions //noinspection ConstantConditions
return new ConstantValueNode( return new ConstantValueNode(
sourceSection, sourceSection, new VmDataSize(intLiteralNode.executeInt(null), dataSizeUnit));
new VmDataSize(((IntLiteralNode) receiver).executeInt(null), dataSizeUnit));
} }
} }
@@ -2465,8 +2464,7 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
if (dataSizeUnit != null) { if (dataSizeUnit != null) {
//noinspection ConstantConditions //noinspection ConstantConditions
return new ConstantValueNode( return new ConstantValueNode(
sourceSection, sourceSection, new VmDataSize(floatLiteralNode.executeFloat(null), dataSizeUnit));
new VmDataSize(((FloatLiteralNode) receiver).executeFloat(null), dataSizeUnit));
} }
} }
@@ -2815,7 +2813,7 @@ public class AstBuilder extends AbstractAstBuilder<Object> {
throw exceptionBuilder() throw exceptionBuilder()
.evalError(e.getMessage(), e.getMessageArguments()) .evalError(e.getMessage(), e.getMessageArguments())
.withCause(e.getCause()) .withCause(e.getCause())
.withHint(e.getHint()) .withHintBuilder(e.getHintBuilder())
.withSourceSection(createSourceSection(ctx)) .withSourceSection(createSourceSection(ctx))
.build(); .build();
} catch (ExternalReaderProcessException e) { } catch (ExternalReaderProcessException e) {
@@ -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.
@@ -327,6 +327,8 @@ public final class SymbolTable {
} }
public final boolean isClassMemberScope() { public final boolean isClassMemberScope() {
var effectiveScope = skipLambdaScopes();
var parent = effectiveScope.parent;
if (parent == null) return false; if (parent == null) return false;
return parent.isClassScope() return parent.isClassScope()

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