Skip to content

Commit 9da6ae7

Browse files
committed
Remove broken plugins
1 parent 558a3ca commit 9da6ae7

20 files changed

Lines changed: 593 additions & 407 deletions

File tree

‎CONTRIBUTING.md‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,29 @@
33
The team welcomes contributions! To make changes:
44

55
- Fork the repo and make a branch
6-
- Write your code (ideally with tests) and make sure the CircleCI build passes
6+
- Write your code (ideally with tests) and make sure the GitHub Actions build passes
7+
(`mise run build` locally, `mise run ci:build` to exercise the workflow itself)
78
- Open a PR (optionally linking to a github issue)
89

910
## Local development
1011

11-
We recommend using [Intellij IDEA Community Edition](https://www.jetbrains.com/idea/) for Java projects. You'll need Java 8 on your machine.
12+
We recommend using [Intellij IDEA Community Edition](https://www.jetbrains.com/idea/) for Java projects.
13+
14+
Install the tooling with [mise](https://mise.jdx.dev/) — it pins the bootstrap JDK and `act`:
1215

1316
1. Fork the repository
14-
1. Generate the IDE configuration: `./gradlew idea`
15-
1. Import projects into Intellij: `open *.ipr`
17+
1. `mise trust && mise install`
18+
1. `mise run build`
19+
1. Import the project into IntelliJ
20+
21+
See [Building and testing locally](README.md#building-and-testing-locally) for the full set of
22+
tasks, how to run the CI workflows under `act`, and which JDKs the build needs.
1623

1724
Tips:
1825

19-
- run `./gradlew checkstyleMain checkstyleTest` locally to make sure your code conforms to the code-style.
26+
- run `mise run format` before pushing; the build fails if the repo is not formatted with the
27+
formatter it builds.
2028

2129
## Working on `:idea-plugin`
2230

23-
Tip: run `./gradlew runIde` to spin up an instance of IntelliJ with the plugin applied.
31+
Tip: run `mise run idea` to spin up an instance of IntelliJ with the plugin applied.

‎README.md‎

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ replaced with something a stranger can run.
125125
| Changelog | Palantir changelog-app (`.changelog.yml`) | Release Drafter, changelog entry in the PR template |
126126
| Version pinning | `gradle-consistent-versions` (`versions.props` / `versions.lock`) | Version catalog (`gradle/libs.versions.toml`) + Gradle dependency locking |
127127
| Static analysis | `gradle-baseline`, `baseline-error-prone`, `suppressible-error-prone`, `baseline-null-away`, `.baseline/` | `net.ltgt.errorprone` + NullAway directly; vendor the checkstyle config (checkstyle is disabled in this build today anyway) |
128-
| JDK provisioning | `gradle-jdks`, `gradle-jdks-latest`, `gradle-jdks-settings`, `gradle/jdks/**`, `palantir.jdk.setup.enabled` | Gradle toolchains + foojay resolver locally; `actions/setup-java` and `graalvm/setup-graalvm` in CI |
128+
| JDK provisioning | ~~`gradle-jdks`, `gradle-jdks-latest`, `gradle-jdks-settings`, `gradle/jdks/**`, `palantir.jdk.setup.enabled`, a patched `gradlew`~~ | **Done** — Gradle toolchains resolved from JDKs that mise installs locally and `actions/setup-java` / `graalvm/setup-graalvm` install in CI |
129129
| Version string | `gradle-git-version` + `CIRCLE_TAG` | `git describe` / `GITHUB_REF_NAME` |
130130
| API compatibility | `gradle-revapi` (`.palantir/revapi.yml`) | japicmp, or revapi's own plugin |
131131
| IntelliJ plugin publish | `com.palantir.external-publish-intellij` | `org.jetbrains.intellij.platform` + `publishPlugin` with a marketplace token |
@@ -165,18 +165,19 @@ point at.
165165
| Gradle plugin | ✅ | — | — | — | — | — |
166166
| IntelliJ plugin | ✅ | — | — | — | — | — |
167167
| Eclipse plugin | ✅ | — | — | — | — | — |
168-
| Native image | ⚠️ | ✅ | ✅ | ❌ | ❌ | ❌ |
168+
| Native image | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
169169

170-
✅ built and uploaded by [`ci.yml`](.github/workflows/ci.yml) · ⚠️ built, but as a side effect of
171-
`assemble` rather than by a job of its own · ❌ missing · — not applicable
170+
✅ built and uploaded by [`ci.yml`](.github/workflows/ci.yml) · ❌ missing · — not applicable
171+
172+
Every native image now comes from a job of its own, on a GraalVM installed by
173+
`graalvm/setup-graalvm`, never as a side effect of `./gradlew build` — pass `-PnativeImage=true`
174+
to wire it back into the lifecycle tasks.
172175

173176
Remaining gaps, each a self-contained PR:
174177

175-
- [ ] macOS x86-64 (`macos-13` runner)
176178
- [ ] Windows x86-64 — the coordinate already exists in `NativeImageFormatProviderPlugin`, nothing
177179
produces the binary
178180
- [ ] linux musl / Alpine
179-
- [ ] Give linux x86-64 its own `nativeCompile` job instead of relying on `build`
180181

181182
### Phase 2 — Republish under neutral coordinates
182183

@@ -366,11 +367,15 @@ mise run format # format this repo with the formatter it builds
366367
mise tasks # everything else
367368
```
368369

369-
The Gradle build provisions its own JDKs — Amazon Corretto 21 for the daemon and GraalVM CE 23 for
370-
`nativeCompile`, pinned in `gradle/jdks/**` — and ignores whatever is on `PATH`, because
371-
`gradle.properties` sets `org.gradle.java.installations.auto-detect=false`. The first build
372-
therefore downloads about 500 MB before it compiles anything. All of it comes from public vendor
373-
URLs (corretto.aws, github.com/graalvm), not from any private mirror.
370+
Nothing inside the build downloads a JDK. `mise.toml` pins all three the build uses — Temurin 17
371+
(library target), Temurin 21 (daemon and runtime target) and GraalVM Community 23 (the native
372+
image) — and Gradle resolves its toolchains from them; `org.gradle.java.installations.auto-download`
373+
is off, so a missing JDK is an error you can read rather than a silent download. CI installs the
374+
same three with `actions/setup-java` and `graalvm/setup-graalvm`.
375+
376+
GraalVM specifically has to come from outside Gradle: unpacking a JDK Gradle downloaded itself does
377+
not preserve the symlink GraalVM ships at `bin/native-image`, and `nativeCompile` then fails on an
378+
empty, unexecutable file.
374379

375380
### Running CI locally
376381

‎build.gradle‎

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,23 @@ buildscript {
1515
classpath 'com.palantir.gradle.guide:gradle-guide:1.27.0'
1616
classpath 'com.palantir.gradle.idea-configuration:gradle-idea-configuration:0.11.0'
1717
classpath 'com.palantir.gradle.idea-language-injector:gradle-idea-language-injector:0.5.0'
18-
classpath 'com.palantir.gradle.plugintesting:gradle-plugin-testing:0.54.0'
19-
// Not applied: versions come from gradle/libs.versions.toml now. It is on the
20-
// classpath only because com.palantir.gradle-plugin-testing links against
21-
// VersionsLockExtension and fails to instantiate without it. Applying it is what
22-
// breaks Gradle 9 (unsafe cross-project configuration resolution); merely having the
23-
// jar present does not. Goes away with gradle-plugin-testing itself.
24-
classpath 'com.palantir.gradle.consistentversions:gradle-consistent-versions:3.19.0'
2518
classpath 'com.palantir.javaformat:gradle-palantir-java-format:2.97.0'
2619
classpath 'com.palantir.suppressible-error-prone:gradle-suppressible-error-prone:2.28.0'
2720
classpath 'me.champeau.jmh:jmh-gradle-plugin:0.7.3'
28-
classpath 'com.palantir.gradle.revapi:gradle-revapi:2.3.0'
2921
}
3022
}
3123

3224
apply plugin: 'com.palantir.failure-reports'
3325
apply plugin: 'com.palantir.git-version'
3426
apply plugin: 'com.palantir.gradle-guide'
3527
apply plugin: 'com.palantir.idea-language-injector'
36-
apply plugin: 'com.palantir.baseline'
28+
// Not the `com.palantir.baseline` aggregate: it also applies baseline-format (Spotless) and
29+
// baseline-class-uniqueness, and both are incompatible with the configuration cache at their
30+
// latest versions — Spotless fails serialising its Groovy extension, checkClassUniqueness casts
31+
// a ResolvingFileCollection to Configuration. The rest of what baseline gives us is applied
32+
// per project below, so error-prone and the JUnit wiring survive.
3733
apply plugin: 'com.palantir.baseline-error-prone-root'
3834
apply plugin: 'com.palantir.baseline-java-versions'
39-
apply plugin: 'com.palantir.baseline-java-versions'
4035

4136
// GitHub Actions sets GITHUB_REF_TYPE=tag on a tag build; otherwise derive the
4237
// version from git history (needs a full clone: actions/checkout fetch-depth: 0).
@@ -48,13 +43,51 @@ version System.env.GITHUB_REF_TYPE == 'tag' ? System.env.GITHUB_REF_NAME : gitVe
4843
// what .github/workflows/ci.yml's `native` jobs do.
4944
ext.nativeImageRequested = Boolean.parseBoolean(providers.gradleProperty('nativeImage').getOrElse('false'))
5045

46+
// The javac internals the formatter parses with. Was baseline's `moduleJvmArgs`, which is
47+
// dropped because it resolves its extension at execution time and the configuration cache
48+
// forbids that — so the exports are handed to javac and to the test JVMs here instead.
49+
def javacInternalExports = [
50+
'jdk.compiler/com.sun.tools.javac.api',
51+
'jdk.compiler/com.sun.tools.javac.code',
52+
'jdk.compiler/com.sun.tools.javac.file',
53+
'jdk.compiler/com.sun.tools.javac.main',
54+
'jdk.compiler/com.sun.tools.javac.parser',
55+
'jdk.compiler/com.sun.tools.javac.tree',
56+
'jdk.compiler/com.sun.tools.javac.util',
57+
]
58+
5159
allprojects {
5260
apply plugin: 'com.palantir.baseline-null-away'
61+
apply plugin: 'com.palantir.baseline-encoding'
62+
apply plugin: 'com.palantir.baseline-immutables'
63+
apply plugin: 'com.palantir.baseline-java-compiler-diagnostics'
64+
apply plugin: 'com.palantir.baseline-java-compiler-heap'
65+
apply plugin: 'com.palantir.baseline-java-properties'
66+
apply plugin: 'com.palantir.baseline-prefer-project-modules'
67+
apply plugin: 'com.palantir.baseline-reproducibility'
68+
apply plugin: 'com.palantir.baseline-test-heap'
69+
apply plugin: com.palantir.baseline.plugins.BaselineTesting
5370
apply plugin: 'com.palantir.java-format'
5471
apply plugin: 'com.palantir.jakarta-package-alignment'
5572
group = 'com.palantir.javaformat'
5673
version = rootProject.version
5774

75+
tasks.withType(JavaCompile).configureEach {
76+
options.compilerArgs.addAll(javacInternalExports.collect { "--add-exports=${it}=ALL-UNNAMED".toString() })
77+
}
78+
79+
tasks.withType(Test).configureEach {
80+
jvmArgs(javacInternalExports.collect { "--add-exports=${it}=ALL-UNNAMED".toString() })
81+
}
82+
83+
tasks.withType(Javadoc).configureEach {
84+
options.addMultilineStringsOption('-add-exports')
85+
.setValue(javacInternalExports.collect { "${it}=ALL-UNNAMED".toString() })
86+
// baseline used to silence doclint; these sources carry inherited javadoc from
87+
// google-java-format that has never satisfied it (unknown tags, malformed HTML).
88+
options.addStringOption('Xdoclint:none', '-quiet')
89+
}
90+
5891
repositories {
5992
mavenCentral() { metadataSources { mavenPom(); ignoreGradleMetadataRedirection() } }
6093
gradlePluginPortal()

‎eclipse_plugin/build.gradle‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
plugins {
1616
id 'java-library'
17-
id 'dev.equo.p2deps' version '1.7.3'
17+
id 'dev.equo.p2deps' version '1.7.8'
1818
}
1919

2020
p2deps {

‎gradle-palantir-java-format/build.gradle‎

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
apply plugin: 'java-gradle-plugin'
2-
apply plugin: 'com.palantir.revapi'
32
apply plugin: 'groovy'
4-
apply plugin: 'com.palantir.gradle-plugin-testing'
53

64
configurations {
75
pluginClasspath {
@@ -24,14 +22,19 @@ dependencies {
2422
testImplementation libs.junit.jupiter
2523
testImplementation libs.assertj
2624
testImplementation libs.jackson.dataformat.xml
25+
// @Language on the XML fixtures; used to arrive transitively via gradle-plugin-testing.
26+
testImplementation libs.jetbrainsAnnotations
2727

2828
testRuntimeOnly libs.junit.vintage.engine
2929

30-
pluginClasspath libs.spotless.gradlePlugin
30+
// Plain Gradle TestKit drives the generated projects; see
31+
// src/test/java/com/palantir/javaformat/gradle/testing/GradleTestProject.java.
32+
testImplementation gradleTestKit()
3133

32-
gradlePluginForTesting libs.consistentVersions.gradlePlugin
33-
gradlePluginForTesting libs.spotless.gradlePlugin
34-
gradlePluginForTesting libs.baseline.gradlePlugin
34+
// Third-party plugins the generated test projects apply. java-gradle-plugin injects this
35+
// alongside the plugin under test, so `plugins { id '...' }` resolves them without a version.
36+
pluginClasspath libs.spotless.gradlePlugin
37+
pluginClasspath libs.baseline.gradlePlugin
3538
}
3639

3740
gradlePlugin {
@@ -70,7 +73,10 @@ gradlePlugin {
7073
}
7174

7275
tasks.withType(PluginUnderTestMetadata).configureEach {
73-
pluginClasspath.from += configurations.pluginClasspath
76+
// `from(...)`, not `from += ...`: the latter reads the collection and reassigns it, dropping the
77+
// task dependency on `jar` that java-gradle-plugin put there. It only shows up on a clean build,
78+
// where the jar has not been produced yet.
79+
pluginClasspath.from(configurations.pluginClasspath)
7480
}
7581

7682
configurations {
@@ -106,16 +112,28 @@ tasks.register("copyNativeImage", Copy.class) {
106112

107113
// Split in two so the jar build does not need a GraalVM image: every test reads
108114
// impl.classpath, only the four that drive the binary read nativeImage.path.
115+
//
116+
// Everything the doLast bodies touch is captured here, at configuration time: reaching for
117+
// `configurations` or `tasks` from inside them would pull the whole script into the task and
118+
// the configuration cache rejects that.
119+
def implFiles = configurations.impl
120+
def implClasspathFile = layout.buildDirectory.file("impl.classpath")
121+
def nativeImageDir = layout.buildDirectory.dir("nativeImage")
122+
def nativeImagePathFile = layout.buildDirectory.file("nativeImage.path")
123+
109124
def writeImplClasspath = tasks.register("writeImplClasspath") {
125+
inputs.files(implFiles)
126+
outputs.file(implClasspathFile)
110127
doLast {
111-
file("$buildDir/impl.classpath").text = configurations.impl.asPath
128+
implClasspathFile.get().asFile.text = implFiles.asPath
112129
}
113130
}
114131

115132
def writeNativeImagePath = tasks.register("writeNativeImagePath") {
116133
inputs.files(tasks.named("copyNativeImage"))
134+
outputs.file(nativeImagePathFile)
117135
doLast {
118-
file("$buildDir/nativeImage.path").text = tasks.named("copyNativeImage").get().getOutputs().getFiles().getSingleFile().listFiles()[0].getAbsolutePath()
136+
nativeImagePathFile.get().asFile.text = nativeImageDir.get().asFile.listFiles()[0].absolutePath
119137
}
120138
}
121139

@@ -135,7 +153,3 @@ tasks.named("test").configure {
135153
exclude '**/FormatDiffTest.class'
136154
}
137155
}
138-
139-
gradleTestUtils {
140-
configurationCacheEnabled = true
141-
}

‎gradle-palantir-java-format/src/test/java/com/palantir/javaformat/gradle/PalantirJavaFormatIdeaPluginTest.java‎

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
1716
package com.palantir.javaformat.gradle;
1817

1918
import static org.assertj.core.api.Assertions.assertThat;
@@ -23,20 +22,16 @@
2322
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
2423
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
2524
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
26-
import com.palantir.gradle.testing.execution.GradleInvoker;
27-
import com.palantir.gradle.testing.files.arbitrary.ArbitraryFile;
28-
import com.palantir.gradle.testing.junit.DisabledConfigurationCache;
29-
import com.palantir.gradle.testing.junit.GradlePluginTests;
30-
import com.palantir.gradle.testing.project.RootProject;
25+
import com.palantir.javaformat.gradle.testing.GradleTestProject;
3126
import java.io.File;
3227
import java.io.IOException;
28+
import java.nio.file.Path;
3329
import java.util.List;
3430
import java.util.Optional;
31+
import org.junit.jupiter.api.io.TempDir;
3532
import org.junit.jupiter.params.ParameterizedTest;
3633
import org.junit.jupiter.params.provider.ValueSource;
3734

38-
@GradlePluginTests
39-
@DisabledConfigurationCache
4035
class PalantirJavaFormatIdeaPluginTest {
4136

4237
private static final String NATIVE_IMAGE_FILE = new File("build/nativeImage.path").getAbsolutePath();
@@ -46,28 +41,30 @@ class PalantirJavaFormatIdeaPluginTest {
4641

4742
private static final ObjectMapper XML_MAPPER = new XmlMapper();
4843

44+
@TempDir
45+
private Path projectDir;
46+
4947
@ParameterizedTest(name = "extraGradleProperties={0}")
5048
@ValueSource(strings = {"", "palantir.native.formatter=true"})
51-
void idea_configures_xml_files(String extraGradleProperties, GradleInvoker gradle, RootProject rootProject)
52-
throws IOException {
53-
54-
rootProject.gradlePropertiesFile().appendLine(extraGradleProperties);
55-
56-
rootProject.buildGradle().plugins().add("com.palantir.java-format-idea").add("idea");
57-
58-
rootProject.buildGradle().append("""
59-
dependencies {
60-
palantirJavaFormat project.files() // no need to store the real thing in here
61-
%s
62-
}
63-
""", extraGradleProperties.isBlank() ? "" : NATIVE_CONFIG);
64-
65-
gradle.withArgs("idea").buildsSuccessfully();
66-
67-
ArbitraryFile pjfXmlFile = rootProject.file(".idea/palantir-java-format.xml");
68-
pjfXmlFile.assertThat().exists();
69-
70-
Project xmlContent = XML_MAPPER.readValue(pjfXmlFile.path().toFile(), Project.class);
49+
void idea_configures_xml_files(String extraGradleProperties) throws IOException {
50+
GradleTestProject project = new GradleTestProject(projectDir)
51+
.plugins("com.palantir.java-format-idea", "idea")
52+
.gradleProperties(extraGradleProperties)
53+
.buildGradle(
54+
"""
55+
dependencies {
56+
palantirJavaFormat project.files() // no need to store the real thing in here
57+
%s
58+
}
59+
""",
60+
extraGradleProperties.isBlank() ? "" : NATIVE_CONFIG);
61+
62+
project.succeeds("idea");
63+
64+
assertThat(project.file(".idea/palantir-java-format.xml")).exists();
65+
66+
Project xmlContent =
67+
XML_MAPPER.readValue(project.file(".idea/palantir-java-format.xml").toFile(), Project.class);
7168

7269
assertThat(xmlContent.components()).anyMatch(c -> "PalantirJavaFormatSettings".equals(c.name()));
7370

@@ -81,10 +78,9 @@ void idea_configures_xml_files(String extraGradleProperties, GradleInvoker gradl
8178
assertThat(allOptions).anyMatch(o -> "nativeImageClassPath".equals(o.name()));
8279
}
8380

84-
ArbitraryFile workspaceXmlFile = rootProject.file(".idea/workspace.xml");
85-
workspaceXmlFile.assertThat().exists();
81+
assertThat(project.file(".idea/workspace.xml")).exists();
8682

87-
Project workspaceContent = XML_MAPPER.readValue(workspaceXmlFile.path().toFile(), Project.class);
83+
Project workspaceContent = XML_MAPPER.readValue(project.file(".idea/workspace.xml").toFile(), Project.class);
8884

8985
assertThat(workspaceContent.components()).anyMatch(c -> "FormatOnSaveOptions".equals(c.name()));
9086
assertThat(workspaceContent.components()).anyMatch(c -> "OptimizeOnSaveOptions".equals(c.name()));
@@ -93,16 +89,14 @@ void idea_configures_xml_files(String extraGradleProperties, GradleInvoker gradl
9389
@JsonIgnoreProperties(ignoreUnknown = true)
9490
private record Project(
9591
@JacksonXmlProperty(localName = "component") @JacksonXmlElementWrapper(useWrapping = false)
96-
List<Component> components) {}
92+
List<Component> components) {}
9793

9894
@JsonIgnoreProperties(ignoreUnknown = true)
9995
private record Component(
10096
@JacksonXmlProperty(isAttribute = true) String name,
101-
10297
@JacksonXmlProperty(localName = "option") @JacksonXmlElementWrapper(useWrapping = false)
103-
List<Option> options) {}
98+
List<Option> options) {}
10499

105100
@JsonIgnoreProperties(ignoreUnknown = true)
106-
private record Option(
107-
@JacksonXmlProperty(isAttribute = true) String name) {}
101+
private record Option(@JacksonXmlProperty(isAttribute = true) String name) {}
108102
}

0 commit comments

Comments
 (0)