jdaugherty commented on code in PR #16528:
URL: https://github.com/apache/grails-core/pull/16528#discussion_r4190556936
##########
grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/asciidoctor/template/asciidocGradle.rocker.raw:
##########
@@ -45,3 +45,9 @@ asciidoctorj {
"revnumber": "$project.version"
}
+// The Asciidoctor Gradle plugin does not support the configuration cache, so
a build that runs
+// its tasks runs without the cache instead of failing
+tasks.withType(org.asciidoctor.gradle.jvm.AsciidoctorTask).configureEach {
Review Comment:
Fixed in b1fef67: the template names the task, `tasks.named('asciidoctor')`.
I added `AsciidoctorBuildSpec` to `test-core`, which generates an app with the
`asciidoctor` feature and runs `./gradlew asciidoctor`: it builds the guide,
and the configuration cache entry is discarded instead of the build failing.
##########
gradle.properties:
##########
@@ -70,17 +70,17 @@ codenarcVersion=4.0.0
jacocoVersion=0.8.15
pmdVersion=7.27.0
spotbugsPluginVersion=6.4.8
-sonatypeScanPluginVersion=3.1.6
snakeyamlVersion=2.6
# This prevents the Grails Gradle Plugin from unnecessarily excluding
slf4j-simple in the generated POMs
# https://github.com/apache/grails-gradle-plugin/issues/222
slf4jPreventExclusion=true
org.gradle.caching=true
-# Configuration cache is explicitly disabled until known issues are resolved.
-# See: https://github.com/apache/grails-core/issues/15497
-org.gradle.configuration-cache=false
+# A build that runs the same tasks again skips configuration and reuses the
stored task graph.
+# Build logic must stay compatible: task actions may not reach the project,
other tasks or script
+# state, see the gradle-developer skill.
+org.gradle.configuration-cache=true
Review Comment:
Fixed in b1fef67: the task reads the project directory while it is
configured and logs through the task. I ran the task's code in a scratch build
with the configuration cache set to fail on problems; it stores an entry and
reuses it.
##########
build-logic/vulnerability-scan/src/main/groovy/org/apache/grails/buildsrc/scan/VulnerabilityScanExtension.groovy:
##########
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.grails.buildsrc.scan
+
+import groovy.transform.CompileStatic
+
+import org.gradle.api.provider.ListProperty
+import org.gradle.api.provider.Property
+
+/**
+ * Configures the {@link VulnerabilityScanTask vulnerability scan} of a
project.
+ */
+@CompileStatic
+abstract class VulnerabilityScanExtension {
+
+ /** The configurations whose dependencies are scanned, {@code
runtimeClasspath} and {@code compileClasspath} unless set. */
+ abstract ListProperty<String> getConfigurations()
+
+ /** The vulnerabilities the scan does not report. */
+ abstract ListProperty<VulnerabilityExclusion> getExclusions()
+
+ /** Whether to only report the vulnerabilities instead of failing the
build. */
+ abstract Property<Boolean> getIgnoreFailures()
+
+ /**
+ * Excludes a vulnerability from the scan.
+ *
+ * @param vulnerabilityId the OSV or Sonatype Guide id of the
vulnerability, or one of its aliases such as its CVE
+ * @param module the {@code group:artifact} it is excluded for, or {@code
null} for every module
+ * @param reason why it is excluded and when the exclusion can be removed
+ */
+ void exclude(String vulnerabilityId, String module, String reason) {
+ exclusions.add(new VulnerabilityExclusion(vulnerabilityId, module,
reason))
Review Comment:
Fixed in b1fef67. `ListProperty` has no public `append` in Gradle 9.8, only
`add`, so the plugin now sets the built-in exclusions as the property's value
instead of its convention, which `add` builds on. A new
`VulnerabilityScanPluginSpec` case calls `exclude(...)` and checks that every
built-in exclusion is still in the report.
##########
build-logic/vulnerability-scan/src/main/groovy/org/apache/grails/buildsrc/scan/VulnerabilityScanReportTask.groovy:
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.grails.buildsrc.scan
+
+import groovy.json.JsonSlurper
+import groovy.transform.CompileDynamic
+import groovy.transform.CompileStatic
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.ConfigurableFileCollection
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.PathSensitive
+import org.gradle.api.tasks.PathSensitivity
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.UntrackedTask
+
+/**
+ * Summarizes the reports of {@link VulnerabilityScanTask vulnerability scans}
in Markdown: each vulnerable
+ * dependency once, with the projects it was found in and the databases that
know of each vulnerability, the
+ * vulnerabilities that were excluded, and the exclusions that no longer match
anything. The last are only listed
+ * when every database was consulted.
+ */
+@CompileStatic
+@UntrackedTask(because = 'It summarizes scans whose results change without the
build changing')
+abstract class VulnerabilityScanReportTask extends DefaultTask {
+
+ /** The reports of the scans; those that do not exist are skipped. */
+ @InputFiles
+ @PathSensitive(PathSensitivity.RELATIVE)
+ abstract ConfigurableFileCollection getReports()
+
+ /** Truncates the listing to this many bytes; {@code 0} keeps all of it. */
+ @Input
+ abstract Property<Integer> getMaxBytes()
+
+ @OutputFile
+ abstract RegularFileProperty getSummaryFile()
+
+ @TaskAction
+ void summarize() {
+ List<Map<String, Object>> scans = reports.files.findAll { it.isFile()
}.sort().collect { File file ->
Review Comment:
Fixed in b1fef67: when a lookup fails, `scan()` writes the project, its
dependency count, the error and its exclusions to the report before rethrowing.
The summary lists those projects with ⚠️, never prints ✅ while one of them
failed, and leaves out "Exclusions that match nothing". A new spec has an OSV
stub answer 503 for one project's dependency and checks the summary.
##########
grails-doc/src/en/guide/upgrading/upgrading80x.adoc:
##########
@@ -4718,3 +4718,17 @@ for template renders:
Objects passed with `bean` or `collection` are not part of `model`. See
link:theWebLayer.html#definingInterceptors[Defining Interceptors].
+
+==== 85. Gradle Configuration Cache
Review Comment:
Moved in b1fef67 to a new `upgrading81x.adoc`, "Upgrading from Grails 8.0 to
Grails 8.1". It says the property needs the Grails 8.1 Gradle plugins and BOM,
and not to add it to a project still on the 8.0 plugins. Note 85 is gone from
the Grails 7 to 8 page, and the guide section and the `grails-8-upgrade` skill
say the same now.
##########
grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy:
##########
@@ -228,16 +228,14 @@ class GrailsGradlePlugin implements Plugin<Project> {
}
}
+ /**
+ * The main class the {@code findMainClass} task found. The value is read
from the task's output when it is
+ * queried, so the configuration cache keeps it lazy instead of storing
whatever the file held before the task ran.
+ */
protected static Provider<String> getMainClassProvider(Project project) {
- Provider<FindMainClassTask> findMainClassTask =
project.tasks.named('findMainClass', FindMainClassTask)
- project.provider {
- File cacheFile =
findMainClassTask.get().mainClassCacheFile.orNull?.asFile
- if (!cacheFile?.exists()) {
- return null
- }
-
- cacheFile?.text
- }
+ project.tasks.named('findMainClass', FindMainClassTask)
+ .flatMap { FindMainClassTask task -> task.mainClassCacheFile }
+ .map { RegularFile cacheFile -> cacheFile.asFile.exists() ?
cacheFile.asFile.text : null }
Review Comment:
Fixed in b1fef67. As you suspected, a provider mapped from the task output
would make `springBoot.mainClass.get()` fail during configuration, so
`springBoot.mainClass` and `ext.mainClassName` now read the cache file through
a `ValueSource` (`FoundMainClassValueSource`). It has no value during
configuration on a clean build, as before, and Gradle obtains it again when an
entry is reused. `MainClassConfigurationCacheSpec` covers a task reading both
with a stored and with a reused entry, and a script reading
`springBoot.mainClass` while it is configured.
##########
build-logic/docs-core/src/main/groovy/grails/doc/gradle/ConvertAsciidocTask.groovy:
##########
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 grails.doc.gradle
+
+import javax.inject.Inject
+
+import groovy.transform.CompileStatic
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.Project
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.file.FileSystemOperations
+import org.gradle.api.file.FileVisitDetails
+import org.gradle.api.model.ObjectFactory
+import org.gradle.api.provider.ListProperty
+import org.gradle.api.provider.MapProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.CacheableTask
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputDirectory
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.PathSensitive
+import org.gradle.api.tasks.PathSensitivity
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.util.PatternSet
+import org.gradle.workers.WorkQueue
+import org.gradle.workers.WorkerExecutor
+
+/**
+ * Converts the AsciiDoc documents of a directory to HTML pages.
+ *
+ * <p>Every document matching {@link #getIncludes()} and not {@link
#getExcludes()} - by default
+ * every {@code .adoc} file whose name does not start with an underscore - is
converted on its
+ * own, with its own directory as the base directory, to the same relative
path under
+ * {@link #getOutputDir()}. The {@code images} directory of the source
directory is copied
+ * alongside the pages.</p>
+ *
+ * <p>Like the Asciidoctor Gradle plugin, the task sets {@code revnumber} and
the
+ * {@code gradle-project-name}, {@code gradle-project-group} and {@code
gradle-project-version}
+ * attributes from the project, and {@code includedir} to the source
directory, unless
+ * {@link #getAttributes()} sets them.</p>
+ *
+ * <p>The conversion runs in a forked worker process, like {@link
PublishGuideTask}, so the JRuby
+ * runtime AsciidoctorJ starts never lands in the Gradle daemon.</p>
+ *
+ * @since 8.0
+ */
+@CompileStatic
+@CacheableTask
Review Comment:
Fixed in b1fef67. The task has `includedFiles` (`@InputFiles
@PathSensitive(RELATIVE)`) and `pathAttributes`: the documents get those paths
absolute, while the task's inputs only have them relative to the root project.
The MongoDB, Hibernate 5/7 and Neo4j docs declare the example sources they
include, and Neo4j's and GraphQL's absolute paths moved to `pathAttributes`.
The new spec checks that a changed included file converts the documents again
and that a copy of the project at another path gets the result FROM-CACHE.
One thing I found on the way: GraphQL's `{sourcedir}/core/...` and
`{sourcedir}/examples/...` includes do not resolve in this repository (the
files are under `grails-data-graphql/core` and `grails-test-examples/graphql`
now), so those examples are missing from its guide. That predates this PR and
needs its own fix of the include paths.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]