jdaugherty opened a new pull request, #16718:
URL: https://github.com/apache/grails-core/pull/16718

   ## Description
   
   Fixes #16711.
   
   The forked compilers that compile GSP pages, JSON views and markup views 
ahead of time read `application.yml` (and, for pages, `application.groovy`) for 
the environment they run in: `CodeGenConfig` merges that environment's block 
over the rest, and the page parser writes the codecs it reads there into the 
compiled page as constants. The environment was never stated to the compiler. 
It fell back to `GRAILS_ENV`, inherited from the Gradle daemon and so from the 
shell, and to `development` where that was not set; `-Dgrails.env` given to 
Gradle never reached it. The compile tasks have been `@CacheableTask` since 
8a3cf63ae2 (7.0.0) with no input for the environment, so two clean builds that 
differed only in `GRAILS_ENV` shared a cache entry, and a production build 
could be handed pages compiled with development's codecs. The issue was filed 
against 8.0.x, where caching had been off between fe4c9cfc2e and #16702, but 
every 7.x release has the same exposure, so the fix starts here and me
 rges up.
   
   ### What changes
   
   - `GroovyPageForkCompileTask` and `AbstractGroovyTemplateCompileTask` (the 
gson and markup compile tasks) carry the environment as an `@Input`, 
`grailsEnvironment`, and pass it to the forked compiler as the `grails.env` 
system property, so nothing the compiler inherits decides. Two environments 
never share a cache entry.
   - The default is the environment the build runs with: a `-Dgrails.env` the 
build already gave the compiler among the task's fork options, else the 
`grails.env` system property given to Gradle, else `GRAILS_ENV`, each read for 
a blank before the next is consulted, as the application's own resolution reads 
them, and `production` where none is set. That is what the archive the views 
are packaged into is built for, and what `grails.build.info` already records. 
The fork argument is withheld from the compiler, which gets the input; a blank 
`grailsEnvironment` fails the build naming the task.
   - Each task empties its destination before it compiles. The page compiler 
leaves a page alone whose class is newer than its source, and leaves the class 
of a page that is gone, so a destination that kept earlier output would carry 
pages of another environment, or pages that no longer exist, into the archive 
and into the cache under the new key. The destination now holds exactly what 
the execution compiled. The page task's `srcDir` is `@Internal` rather than an 
input directory, since the pages are fingerprinted through the source and the 
directory need not exist.
   - `ViewCompileEnvironment` holds the default and the reading of the input 
for both tasks.
   
   ### Behaviour change
   
   A build that set GSP codecs only under `environments.development` used to 
ship them in its archive; it now gets the production configuration there, as 
the running application does. `./gradlew bootJar -Dgrails.env=uat` now reaches 
the page and view compilers. The same compiled views serve the tests, which the 
guide now says.
   
   ### Documentation
   
   The "Packaging and Running for Different Environments" section of the 
environments guide describes which environment views are compiled for, how to 
set it, the `grailsEnvironment` property on the compile tasks, and that the 
cache keeps environments apart.
   
   ### Tests
   
   - `AbstractViewCompileEnvironmentFunctionalSpec`, run for the GSP task and 
the gson task (TestKit, with stand-in compilers that record what they are 
started with and keep an output they find, as the real page compiler does): the 
default, the variable, the system property outranking it, a blank property, the 
task property, a blank task property failing, a fork JVM argument kept and 
outranked by the task property, an environment change compiling from an empty 
destination and the clean build restored from the cache getting the new 
environment's output, an edit or a removal compiling from an empty destination, 
and two environments never restoring each other's output.
   - `ViewCompileEnvironmentSpec`: name resolution, blank handling, the 
fork-argument default, and the reading of the input.
   
   Run locally: these specs, the full `grails-gradle-plugins` suite, and 
`:grails-gradle-plugins:codeStyle`. The rest of the build runs on CI.
   
   ### Merge-up
   
   8.0.x already has `srcDir` `@Internal`, a rewritten javadoc on the page task 
from #16702, its own `GroovyPageBuildCacheFunctionalSpec` and a stand-in 
`GroovyPageForkedCompiler` under the plugin's tests; those need reconciling on 
the way up.
   
   ## Contributor Checklist
   
   ### Issue and Scope
   
   - [x] This PR is linked to an existing issue that has been **acknowledged or 
approved** by the project team. If no approved issue exists, please give 
background on why this change is necessary.  Tickets are preferred for release 
change log history.
   - [x] This PR addresses the **complete scope** of the linked issue. Partial 
implementations or unfinished work should not be submitted for review.
   - [x] This PR contains a **single, focused change**. Unrelated changes 
should be submitted as separate pull requests.
   - [x] This PR targets the **correct branch** for the type of change:
       - **Patch release branches** (e.g., `7.0.x`): Bug fixes only. No new 
features or API changes.
       - **Minor release branches** (e.g., `7.1.x`): New features are welcome, 
but breaking existing APIs must be avoided.
       - **Major release branches** (e.g., `8.0.x`): Reserved for major 
changes. Breaking API changes are permitted.
   
   ### Code Quality
   
   - [x] I have **added or updated tests** that cover the changes introduced in 
this PR. All code contributions are expected to include appropriate test 
coverage.
   - [ ] I have verified that all existing tests pass by running `./gradlew 
build --rerun-tasks`.
   - [x] My code follows the project's **code style** guidelines. I have run 
`./gradlew codeStyle` and resolved any violations. See [Code 
Style](../CONTRIBUTING.md#code-style) for details.
   - [x] This PR does **not** include mass reformatting, style-only changes, or 
large-scale refactoring unless it was **explicitly approved** in the linked 
issue. Unsolicited reformatting will not be accepted.
   - [ ] If generative AI tooling was used in preparing this contribution, a 
quality model was used to ensure contributions are **consistent with the 
project's quality standards**.
   
   ### Licensing and Attribution
   
   - [x] All contributed code is provided under the [Apache License 
2.0](https://www.apache.org/licenses/LICENSE-2.0), and new source files include 
the appropriate **Apache license header**.
   - [x] I have the necessary rights to submit this contribution and confirm it 
is my own original work (see [Legal 
Notice](../CONTRIBUTING.md#i-want-to-contribute)).
   - [ ] If generative AI tooling was used in preparing this contribution, I 
have followed the [Apache Software Foundation's policy on generative 
tooling](https://www.apache.org/legal/generative-tooling.html) and have 
properly attributed its use.
   
   ### Documentation
   
   - [x] If this PR introduces user-facing changes, I have included or updated 
the relevant documentation.
   - [ ] If this PR adds a new feature, I have updated the **What's New** 
section of the Grails Guide.
   - [ ] If this PR introduces breaking changes or changes that require user 
action during an upgrade, I have updated the **Upgrade Notes** for the 
corresponding version in the Grails Guide.
   - [x] The PR description clearly explains **what** was changed and **why**.
   


-- 
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]

Reply via email to