Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
55af4eb
style: conform to style rules
matrei Aug 26, 2025
3bb575b
fix: add style enforcement
matrei Aug 26, 2025
1f4739e
ci: run style checks in dedicated workflow
matrei Aug 26, 2025
73e3278
fix: `skipCodeStyle` task condition
matrei Aug 26, 2025
ae2efa2
ci: add report upload
matrei Aug 26, 2025
6fc1cc6
ci: set correct report directory
matrei Aug 26, 2025
12a1270
chore: trigger code style errors
matrei Aug 26, 2025
20468a4
ci: specify code style reports more granular
matrei Aug 26, 2025
37355fc
ci: add `--continue` to get all codestyle errors
matrei Aug 26, 2025
8238b0a
ci: set correct `skipCodeStyle` condition for `grails-gradle`
matrei Aug 26, 2025
1b6d267
ci: stop using Gradle --continue for code style checks
matrei Aug 26, 2025
5dd8fcd
Revert "chore: trigger code style errors"
matrei Aug 26, 2025
d4214c8
style: conform to code style
matrei Aug 27, 2025
43dcd6f
refactor(build): dry up `code-style-config`
matrei Aug 27, 2025
cc80268
fix(build): align code style checking in `grails-forge`
matrei Aug 27, 2025
611c745
ci: add `grails-forge` code style checking
matrei Aug 27, 2025
ef17c7f
ci: fix typos
matrei Aug 27, 2025
40b134c
ci: remove redundant gradle param
matrei Aug 27, 2025
c2118ca
docs: add `skipCodeStyle` to `DEVELOPMENT.md`
matrei Aug 27, 2025
955b423
docs: update `DEVELOPMENT.md`
matrei Aug 27, 2025
6395939
docs: update `DEVELOPMENT.md`
matrei Aug 27, 2025
2dbf541
docs: update `CONTRIBUTING.md`
matrei Aug 27, 2025
8b1a7d4
Merge branch '7.0.x' into enforce-code-style
matrei Aug 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .github/workflows/codestyle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# 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.

name: "Code Style"
on:
push:
branches:
- '[0-9]+.[0-9]+.x'
pull_request:
workflow_dispatch:
# queue jobs and only allow 1 run per branch due to the likelihood of hitting GitHub resource limits
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
check_core_projects:
name: "Core Projects"
runs-on: ubuntu-24.04
steps:
- name: "🌐 Output Agent IP" # in the event RAO blocks this agent, this can be used to debug it
run: curl -s https://api.ipify.org
- name: "📥 Checkout repository"
uses: actions/checkout@v4
- name: "☕️ Setup JDK"
uses: actions/setup-java@v4
with:
distribution: liberica
java-version: 17
- name: "🐘 Setup Gradle"
uses: gradle/actions/setup-gradle@v4
with:
develocity-access-key: ${{ secrets.GRAILS_DEVELOCITY_ACCESS_KEY }}
- name: "🔎 Check Core Projects"
run: ./gradlew codeStyle
- name: "📤 Upload Failure Reports"
if: failure()
uses: actions/upload-artifact@v4
with:
name: core-reports
path: |
**/build/reports/checkstyle/
**/build/reports/codenarc/
check_gradle_plugin_projects:
name: "Gradle Plugin Projects"
runs-on: ubuntu-24.04
steps:
- name: "🌐 Output Agent IP" # in the event RAO blocks this agent, this can be used to debug it
run: curl -s https://api.ipify.org
- name: "📥 Checkout repository"
uses: actions/checkout@v4
- name: "☕️ Setup JDK"
uses: actions/setup-java@v4
with:
distribution: liberica
java-version: 17
- name: "🐘 Setup Gradle"
uses: gradle/actions/setup-gradle@v4
with:
develocity-access-key: ${{ secrets.GRAILS_DEVELOCITY_ACCESS_KEY }}
- name: "🔎 Check Gradle Plugin Projects"
working-directory: grails-gradle
run: ./gradlew codeStyle
- name: "📤 Upload Failure Reports"
if: failure()
uses: actions/upload-artifact@v4
with:
name: gradle-plugin-reports
path: |
grails-gradle/**/build/reports/checkstyle/
grails-gradle/**/build/reports/codenarc/
45 changes: 33 additions & 12 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,19 @@ jobs:
working-directory: 'grails-gradle'
run: >
./gradlew build
--continue --stacktrace -PskipTests
--continue
--stacktrace
-PskipCodeStyle
-PskipTests
- name: "🔨 Build project with tests"
if: ${{ !contains(github.event.head_commit.message, '[skip tests]') }}
working-directory: 'grails-gradle'
run: >
./gradlew build
--continue --stacktrace
--continue
--stacktrace
--rerun-tasks
-PskipCodeStyle
build:
if: ${{ !contains(github.event.head_commit.message, '[skip tests]') }}
name: 'Build Grails-Core'
Expand All @@ -85,8 +90,11 @@ jobs:
- name: "🔨 Build project"
run: >
./gradlew build :grails-shell-cli:installDist groovydoc
--continue --stacktrace -PonlyCoreTests
--continue
--rerun-tasks
--stacktrace
-PonlyCoreTests
-PskipCodeStyle
buildForge:
name: "Build Grails Forge"
strategy:
Expand All @@ -113,14 +121,19 @@ jobs:
working-directory: 'grails-forge'
run: >
./gradlew build
--continue --stacktrace -PskipTests
--continue
--stacktrace
-PskipCodeStyle
-PskipTests
- name: "🔨 Build project with tests"
if: ${{ !contains(github.event.head_commit.message, '[skip tests]') }}
working-directory: 'grails-forge'
run: >
./gradlew build
--continue --stacktrace
--continue
--rerun-tasks
--stacktrace
-PskipCodeStyle
- name: "✅ Verify combined CLI"
run: |
cd grails-forge
Expand Down Expand Up @@ -162,11 +175,13 @@ jobs:
- name: "🏃 Run Functional Tests"
run: >
./gradlew bootJar check
--continue --stacktrace
--continue
--rerun-tasks
--stacktrace
-PonlyFunctionalTests
-PskipCodeStyle
-PskipHibernate5Tests
-PskipMongodbTests
--rerun-tasks
mongodbFunctional:
if: ${{ !contains(github.event.head_commit.message, '[skip tests]') }}
name: "Mongodb Functional Tests"
Expand Down Expand Up @@ -195,10 +210,12 @@ jobs:
GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
run: >
./gradlew bootJar cleanTest check
--continue --stacktrace
--continue
--rerun-tasks
--stacktrace
-PonlyMongodbTests
-PmongodbContainerVersion=${{ matrix.mongodb-version }}
--rerun-tasks
-PskipCodeStyle
hibernate5Functional:
if: ${{ !contains(github.event.head_commit.message, '[skip tests]') }}
name: "Hibernate5 Functional Tests"
Expand Down Expand Up @@ -226,9 +243,11 @@ jobs:
GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
run: >
./gradlew bootJar cleanTest check
--continue --stacktrace
-PonlyHibernate5Tests
--continue
--rerun-tasks
--stacktrace
-PonlyHibernate5Tests
-PskipCodeStyle
publishGradle:
if: github.repository_owner == 'apache' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
needs: [ buildGradle ]
Expand Down Expand Up @@ -256,7 +275,9 @@ jobs:
working-directory: 'grails-gradle'
run: >
./gradlew publish aggregateChecksums aggregatePublishedArtifacts
-Dorg.gradle.internal.publish.checksums.insecure=true --no-build-cache --rerun-tasks
--no-build-cache
--rerun-tasks
-Dorg.gradle.internal.publish.checksums.insecure=true
- name: "📤 Upload grails-gradle checksums"
uses: actions/upload-artifact@v4
with:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/groovy-joint-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,4 @@ jobs:
run: >
./gradlew build
-x groovydoc
-PskipCodeStyle
22 changes: 22 additions & 0 deletions etc/config/checkstyle/checkstyle-suppressions.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<!--
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

http://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.
-->
<!DOCTYPE suppressions PUBLIC "-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN" "https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
</suppressions>
89 changes: 89 additions & 0 deletions etc/config/checkstyle/checkstyle.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0"?>
<!--
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

http://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.
-->
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">

<!-- Suppressions -->
<module name="SuppressionFilter">
<property name="file" value="${config_loc}/checkstyle-suppressions.xml"/>
</module>

<!-- Root Checks -->
<module name="NewlineAtEndOfFile"/>
<module name="FileTabCharacter"/>
<module name="SuppressWarningsFilter"/>

<!-- TreeWalker Checks -->
<module name="TreeWalker">

<module name="SuppressWarningsHolder"/>

<!-- Imports -->
<module name="AvoidStarImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports">
<property name="processJavadoc" value="false"/>
</module>
<module name="ImportOrderCheck">
<!-- Import groups: JAVA, JAVAX, GROOVY, JAKARTA, OTHER, SPRING, GRAILS, STATIC -->
<property name="groups" value="java,javax,/^(groovy|org\.apache\.groovy|org\.codehaus\.groovy)\..+/,jakarta,*,/(^io\.spring|org\.springframework)\..+/,/^(grails|org\.apache\.grails|org\.grails)\..+/"/>
<property name="ordered" value="true"/>
<property name="option" value="bottom"/>
<property name="separated" value="true"/>
<property name="sortStaticImportsAlphabetically" value="true"/>
</module>

<!-- Whitespace -->
<module name="CommentsIndentation"/>
<module name="EmptyLineSeparator">
<property name="allowMultipleEmptyLines" value="false"/>
<property name="allowMultipleEmptyLinesInsideClassMembers" value="false"/>
<property name="allowNoEmptyLineBetweenFields" value="true"/>
<property name="tokens" value="IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF, STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF, COMPACT_CTOR_DEF"/><!-- PACKAGE_DEF removed from defaults -->
</module>
<module name="GenericWhitespace"/>
<module name="Indentation"/>
<module name="NoLineWrap"/>
<module name="MethodParamPad"/>
<module name="NoWhitespaceAfter">
<property name="tokens" value="AT, INC, DEC, UNARY_MINUS, UNARY_PLUS, BNOT, LNOT, DOT, ARRAY_DECLARATOR, INDEX_OP"/><!-- ARRAY_INIT removed from defaults -->
</module>
<module name="NoWhitespaceBefore"/>
<module name="NoWhitespaceBeforeCaseDefaultColon"/>
<module name="OperatorWrap">
<property name="option" value="eol"/>
</module>
<module name="ParenPad"/>
<module name="SeparatorWrap">
<property name="option" value="nl"/>
<property name="tokens" value="DOT"/>
</module>
<module name="SingleSpaceSeparator"/>
<module name="TypecastParenPad"/>
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround">
<property name="allowEmptyCatches" value="true"/>
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
</module>
</module>

</module>
76 changes: 76 additions & 0 deletions etc/config/codenarc/codenarc.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 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.
*/
ruleset {

description 'A Codenarc ruleset for the Grails codebase'

BracesForClass
ClassStartsWithBlankLine {
ignoreInnerClasses = true
}
ClosureStatementOnOpeningLineOfMultipleLineClosure
ConsecutiveBlankLines
FileEndsWithoutNewline
NoTabCharacter
DuplicateImport
ImportFromSamePackage
Indentation
MisorderedStaticImports {
comesBefore = false // static imports should come last
}
MissingBlankLineAfterImports
MissingBlankLineAfterPackage
MissingBlankLineBeforeAnnotatedField
NoWildcardImports
SpaceAfterCatch
SpaceAfterClosingBrace
SpaceAfterComma
SpaceAfterFor
SpaceAfterIf
SpaceAfterMethodCallName
SpaceAfterMethodDeclarationName
SpaceAfterNotOperator
SpaceAfterOpeningBrace {
ignoreEmptyBlock = true
}
SpaceAfterSemicolon
SpaceAfterSwitch
SpaceAfterWhile
SpaceAroundClosureArrow
SpaceAroundMapEntryColon {
characterAfterColonRegex = ' '
}
SpaceAroundOperator {
ignoreParameterDefaultValueAssignments = false
}
SpaceBeforeClosingBrace {
ignoreEmptyBlock = true
}
SpaceBeforeOpeningBrace
SpaceInsideParentheses
UnnecessaryConstructor
UnnecessaryDotClass
UnnecessaryGroovyImport
UnnecessaryGString
UnnecessaryOverridingMethod
UnnecessaryPublicModifier
UnnecessarySafeNavigationOperator
UnnecessarySemicolon
UnusedImport
}
Loading
Loading