Skip to content

Commit 0c163aa

Browse files
committed
first working version
1 parent 7a9aa58 commit 0c163aa

File tree

54 files changed

+1726
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1726
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Dependency Submission
2+
3+
on:
4+
push:
5+
branches: [ 'master' ]
6+
7+
permissions:
8+
contents: write
9+
10+
env:
11+
GRADLE_OPTS: "-Dorg.gradle.console=plain -Dorg.gradle.daemon=false -Dorg.gradle.stacktrace=always"
12+
13+
jobs:
14+
dependency-submission:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- uses: actions/setup-java@v4
20+
with:
21+
distribution: temurin
22+
java-version: 21
23+
24+
- name: Generate and submit dependency graph
25+
id: dependency-submission
26+
uses: gradle/actions/dependency-submission@v4
27+
with:
28+
dependency-graph-exclude-projects: ':(typed-ids-testing|testing-*)'
29+
dependency-graph-exclude-configurations: '.*[Tt]est(Compile|Runtime)Classpath'
30+
31+
- name: Also upload the raw dependency graph as an artifact
32+
uses: actions/upload-artifact@v4
33+
with:
34+
name: gradle-dependency-graph-file
35+
path: ${{ steps.dependency-submission.outputs.dependency-graph-file }}
36+
retention-days: 1

.github/workflows/gradle-build.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Run Checks via Gradle
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
9+
env:
10+
GRADLE_OPTS: "-Dorg.gradle.console=plain -Dorg.gradle.daemon=false -Dorg.gradle.stacktrace=always"
11+
12+
jobs:
13+
gradle:
14+
strategy:
15+
matrix:
16+
java: [21, 22, 23]
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- name: Setup Java
22+
uses: actions/setup-java@v4
23+
with:
24+
distribution: temurin
25+
java-version: ${{ matrix.java }}
26+
cache: gradle
27+
28+
- name: Setup Gradle
29+
uses: gradle/actions/setup-gradle@v4
30+
with:
31+
add-job-summary-as-pr-comment: on-failure
32+
33+
- name: Execute Gradle build
34+
run: ./gradlew --continue build
35+
36+
- name: Upload Test Report
37+
uses: actions/upload-artifact@v4
38+
if: always() # always run even if the previous step fails
39+
with:
40+
name: junit-test-results
41+
path: '**/build/test-results/test/TEST-*.xml'
42+
retention-days: 1
43+
overwrite: true
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: Release using JReleaser
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Release version'
8+
required: true
9+
nextVersion:
10+
description: 'Next version after release (-SNAPSHOT will be added automatically)'
11+
required: true
12+
13+
env:
14+
GRADLE_OPTS: "-Dorg.gradle.console=plain -Dorg.gradle.daemon=false -Dorg.gradle.stacktrace=always"
15+
16+
jobs:
17+
release:
18+
runs-on: ubuntu-latest
19+
timeout-minutes: 60
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
with:
24+
token: ${{ secrets.JRELEASER_GITHUB_TOKEN }}
25+
fetch-depth: 0
26+
27+
- name: Setup Java
28+
uses: actions/setup-java@v4
29+
with:
30+
distribution: temurin
31+
java-version: 21
32+
cache: gradle
33+
34+
- name: Setup Gradle
35+
uses: gradle/actions/setup-gradle@v4
36+
37+
- name: Gradle build and publish to local
38+
run: ./gradlew publish -Pversion=${{ github.event.inputs.version }}
39+
40+
- name: JReleaser full-release
41+
uses: jreleaser/release-action@v2
42+
with:
43+
setup-java: false
44+
env:
45+
JRELEASER_STRICT: "true"
46+
JRELEASER_OUTPUT_DIRECTORY: "build/"
47+
JRELEASER_PROJECT_VERSION: ${{ github.event.inputs.version }}
48+
JRELEASER_GITHUB_TOKEN: ${{ secrets.JRELEASER_GITHUB_TOKEN }}
49+
JRELEASER_MAVENCENTRAL_USERNAME: ${{ secrets.JRELEASER_MAVENCENTRAL_USERNAME }}
50+
JRELEASER_MAVENCENTRAL_TOKEN: ${{ secrets.JRELEASER_MAVENCENTRAL_TOKEN }}
51+
JRELEASER_GPG_KEYNAME: ${{ secrets.JRELEASER_GPG_KEYNAME }}
52+
JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_GPG_PASSPHRASE }}
53+
JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.JRELEASER_GPG_PUBLIC_KEY }}
54+
JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_GPG_SECRET_KEY }}
55+
56+
- name: JReleaser upload output
57+
if: always()
58+
uses: actions/upload-artifact@v4
59+
with:
60+
name: jreleaser-release
61+
path: |
62+
build/jreleaser/trace.log
63+
build/jreleaser/output.properties
64+
65+
- name: Update version in properties
66+
run: sed -i 's/^version=.*/version=${{ github.event.inputs.nextVersion }}-SNAPSHOT/g' gradle.properties
67+
68+
- name: Commit & Push version update
69+
uses: actions-js/push@master
70+
with:
71+
github_token: ${{ secrets.JRELEASER_GITHUB_TOKEN }}
72+
message: "chore: bump version to ${{ github.event.inputs.nextVersion }}-SNAPSHOT"
73+
author_email: 'bot@framefork.org'
74+
author_name: 'Framefork BOT'
75+
branch: master
76+
tags: false
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Publish Test Results
2+
3+
on:
4+
workflow_run:
5+
workflows: [ 'Run Checks via Gradle' ]
6+
types: [ completed ]
7+
8+
permissions:
9+
checks: write
10+
11+
jobs:
12+
checks:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Download Test Report
16+
uses: dawidd6/action-download-artifact@v2
17+
with:
18+
name: junit-test-results
19+
workflow: ${{ github.event.workflow.id }}
20+
run_id: ${{ github.event.workflow_run.id }}
21+
22+
- name: Publish Test Report
23+
uses: mikepenz/action-junit-report@v5
24+
with:
25+
commit: ${{github.event.workflow_run.head_sha}}
26+
report_paths: '**/build/test-results/test/TEST-*.xml'
27+
detailed_summary: true

.sdkmanrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
java=21.0.5-tem
2+
jreleaser=1.15.0

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Spring properties order-by-configurations
2+
3+
This library reorders `*.properties` files priorities depending on which `@Configuration` classes they're defined on and how those classes are linked via `@Import`.
4+
This enables you to define a stable ordering, making property resolution predictable.
5+
6+
## Installation
7+
8+
Just install the latest version of `org.framefork:spring-properties-order-by-configurations` dependency, and everything should start working - the configuration autoloads in a Spring Boot project.
9+
10+
## Motivation
11+
12+
The author of this library typically structures their Spring Boot applications with the following example modules:
13+
* `app` (depends on `core-business-logic`)
14+
* `core-business-logic` (depends on `common` and `core-separate-module`)
15+
* `core-separate-module` (depends on `common`)
16+
* `commons`
17+
18+
Where
19+
* The `app` adds "entrypoints" (controllers, cli commands, etc.) and may also add some `.properties` file(s)
20+
* The `core-*` have separate tests, and somewhat separate configurations with some `.properties` file(s)
21+
* The `.properties` are loaded with `@PropertySource(...)` on a `@Configuration` class
22+
* The `core-*` may want to define some "defaults" like `spring.main.web-application-type=none`, but the `app` would like it to be `spring.main.web-application-type=servlet`
23+
24+
This usually leads to a situation where it sorts the classes based on some arbitrary rule, and then the properties are sorted by the ordering of the configuration classes,
25+
and the only ordering you can rely on is when you put both `@PropertySource`'s on the same `@Configuration` class, but that kinda defeats the purpose of splitting the application into modules.
26+
You'll end up with working `core-*` but broken `app` because it gives the `.properties` higher priority and the `spring.main.web-application-type=servlet` is ignored.
27+
28+
I think that it's reasonable to assume, that if `app` depends on `core-*` it might want to be able to **override** some default values provided by the `core-*`, and this library solves that.
29+
It sorts the `.properties` based on the `@Import()`'s on your `@Configuration` classes, so that in `app` you can add `@Import` on some `core-*` `@Configuration` to say "I depend on this, allow me to override its properties".
30+
31+
For working example, look into the `testing/` directory.

build.gradle.kts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
plugins {
2+
id("base")
3+
id("idea")
4+
id("org.barfuin.gradle.taskinfo") version ("2.2.0") // ./gradlew tiTree publish
5+
id("be.vbgn.ci-detect") version ("0.5.0")
6+
}
7+
8+
repositories {
9+
mavenCentral()
10+
mavenLocal()
11+
}
12+
13+
group = "org.framefork"
14+
version = (properties["version"] as String).trim()
15+
16+
allprojects {
17+
group = rootProject.group
18+
version = rootProject.version
19+
}
20+
21+
tasks.withType<Wrapper> {
22+
distributionType = Wrapper.DistributionType.ALL
23+
}
24+
25+
tasks.register<Delete>("cleanAllPublications") {
26+
outputs.upToDateWhen { false }
27+
setDelete(rootProject.layout.buildDirectory.dir("staging-deploy"))
28+
}
29+
30+
allprojects {
31+
apply(plugin = "project-report")
32+
33+
this.task("allDependencies", DependencyReportTask::class) {
34+
evaluationDependsOnChildren()
35+
this.setRenderer(org.gradle.api.tasks.diagnostics.internal.dependencies.AsciiDependencyReportRenderer().apply {
36+
outputFile = file(project.layout.buildDirectory.file("reports/dependencies.txt"))
37+
})
38+
}
39+
}
40+
41+
gradle.projectsEvaluated {
42+
// Make sure tests of individual modules are executed sequentially
43+
val testTasks = subprojects
44+
.flatMap { it.tasks.withType<Test>() }
45+
.sortedBy { it.project.path } // Sort to ensure a consistent order
46+
for (i in 1 until testTasks.size) {
47+
testTasks[i].mustRunAfter(testTasks[i - 1])
48+
}
49+
}

buildSrc/build.gradle.kts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
plugins {
2+
`kotlin-dsl`
3+
}
4+
5+
repositories {
6+
gradlePluginPortal()
7+
mavenCentral()
8+
}
9+
10+
dependencies {
11+
implementation("com.adarshr:gradle-test-logger-plugin:4.0.0")
12+
implementation("io.github.joselion:strict-null-check:3.5.0")
13+
implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.1.0")
14+
implementation("net.ltgt.gradle:gradle-nullaway-plugin:2.1.0")
15+
}
16+
17+
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
18+
compilerOptions {
19+
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21 // This option specifies the target version of the generated JVM bytecode
20+
}
21+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
plugins {
2+
id("framefork.java")
3+
`maven-publish`
4+
}
5+
6+
java {
7+
withJavadocJar()
8+
withSourcesJar()
9+
}
10+
11+
publishing {
12+
publications {
13+
create<MavenPublication>("mavenStaging") {
14+
from(components["java"])
15+
16+
pom {
17+
url = "https://github.com/framefork/spring-properties-order-by-configurations"
18+
inceptionYear = "2024"
19+
licenses {
20+
license {
21+
name = "Apache-2.0"
22+
url = "https://spdx.org/licenses/Apache-2.0.html"
23+
}
24+
}
25+
organization {
26+
name = "Framefork"
27+
url = "https://github.com/framefork"
28+
}
29+
developers {
30+
developer {
31+
id = "fprochazka"
32+
name = "Filip Procházka"
33+
url = "https://filip-prochazka.com/"
34+
}
35+
}
36+
scm {
37+
connection = "scm:git:https://github.com/framefork/spring-properties-order-by-configurations.git"
38+
developerConnection = "scm:git:ssh://github.com/framefork/spring-properties-order-by-configurations.git"
39+
url = "https://github.com/framefork/spring-properties-order-by-configurations"
40+
}
41+
issueManagement {
42+
system = "GitHub"
43+
url = "https://github.com/framefork/spring-properties-order-by-configurations/issues"
44+
}
45+
}
46+
47+
afterEvaluate {
48+
pom.name = "${project.group}:${project.name}"
49+
pom.description = project.description
50+
}
51+
}
52+
}
53+
54+
repositories {
55+
maven {
56+
url = uri(rootProject.layout.buildDirectory.dir("staging-deploy"))
57+
}
58+
}
59+
}
60+
61+
tasks.named("publish") {
62+
dependsOn(rootProject.tasks.named("cleanAllPublications"))
63+
}

0 commit comments

Comments
 (0)