diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-build.yml index 86872ee4..0d4ce187 100644 --- a/.github/workflows/maven-build.yml +++ b/.github/workflows/maven-build.yml @@ -8,6 +8,9 @@ name: Maven Build +permissions: + contents: read + on: push: branches: [ 'dev-1.x' ] @@ -18,6 +21,7 @@ jobs: build: runs-on: ubuntu-latest strategy: + max-parallel: 7 matrix: java: [ '8', '11' , '17' , '21' , '25' ] maven-profile-spring-boot: [ 'spring-boot-2.1' , 'spring-boot-2.2' , 'spring-boot-2.3', diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index 7f5c04c6..5ee1f198 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -21,6 +21,8 @@ on: jobs: build: runs-on: ubuntu-latest + permissions: + contents: read if: ${{ inputs.revision }} steps: - name: Validate version format @@ -60,12 +62,12 @@ jobs: SIGN_KEY: ${{ secrets.OSS_SIGNING_KEY }} SIGN_KEY_PASS: ${{ secrets.OSS_SIGNING_PASSWORD }} - release: runs-on: ubuntu-latest needs: build permissions: contents: write + models: read steps: - name: Checkout Source uses: actions/checkout@v5 @@ -83,14 +85,96 @@ jobs: git push origin ${{ inputs.revision }} fi + - name: Generate Release Notes with Copilot + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + CURRENT_TAG="${{ inputs.revision }}" + + # Find the previous tag (the one before the current tag) + PREV_TAG=$(git describe --tags --abbrev=0 --exclude="${CURRENT_TAG}" HEAD 2>/dev/null || echo "") + + # Collect commits between the previous tag and HEAD + if [ -n "$PREV_TAG" ]; then + COMMITS=$(git log --oneline "${PREV_TAG}..HEAD" 2>/dev/null || echo "No commits found") + SINCE_LABEL="$PREV_TAG" + else + COMMITS=$(git log --oneline -50 2>/dev/null || echo "No commits found") + SINCE_LABEL="the beginning" + fi + + # Export for Python (avoids shell-escaping issues with multiline content) + export CURRENT_TAG_DATA="$CURRENT_TAG" + export PREV_TAG_DATA="$SINCE_LABEL" + export COMMITS_DATA="$COMMITS" + + # Call GitHub Copilot via GitHub Models API and capture the summary + SUMMARY=$(python3 << 'PYEOF' + import json, os, urllib.request, sys + + current_tag = os.environ['CURRENT_TAG_DATA'] + prev_tag = os.environ['PREV_TAG_DATA'] + commits = os.environ['COMMITS_DATA'] + token = os.environ['GH_TOKEN'] + + prompt = ( + f"Generate concise release notes for version {current_tag}.\n\n" + f"Commits since {prev_tag}:\n{commits}\n\n" + "Format the output as markdown with sections if present for New Features, Bug Fixes, " + "Documentations, Dependency Updates, Test Improvements, Build and Workflow Enhancements " + "and Other Changes(excludes Full Changelog).\n\n" + "Be concise and clear." + ) + + payload = json.dumps({ + "model": "gpt-4o", + "messages": [{"role": "user", "content": prompt}] + }).encode() + + req = urllib.request.Request( + "https://models.inference.ai.azure.com/chat/completions", + data=payload, + headers={ + "Content-Type": "application/json", + "Authorization": f"Bearer {token}" + } + ) + + try: + with urllib.request.urlopen(req) as resp: + data = json.loads(resp.read()) + print(data["choices"][0]["message"]["content"]) + except Exception as e: + print(f"Failed to generate summary via Copilot: {e}", file=sys.stderr) + print(f"_Release notes generation failed. Raw commits since {prev_tag}:_\n\n```\n{commits}\n```") + PYEOF + ) + + # Append the summary (with version header) to release-notes.md + NOTES_FILE="release-notes.md" + if [ ! -f "$NOTES_FILE" ]; then + printf "# Release Notes\n\n" > "$NOTES_FILE" + fi + + FULL_CHANGELOG="**Full Changelog**: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/compare/$PREV_TAG...$CURRENT_TAG" + + printf "## v%s\n\n%s\n\n" "$CURRENT_TAG" "$SUMMARY" >> "$NOTES_FILE" + printf "%s" "$FULL_CHANGELOG" >> "$NOTES_FILE" + + # Write the current release notes to a temp file for the Create Release step + printf "%s\n\n" "$SUMMARY" > /tmp/current-release-notes.md + printf "%s" "$FULL_CHANGELOG" >> /tmp/current-release-notes.md + + echo "Release notes generated and appended to $NOTES_FILE" + - name: Create Release run: | - if gh release view "v${{ inputs.revision }}" >/dev/null 2>&1; then - echo "Release v${{ inputs.revision }} already exists, skipping." + if gh release view "${{ inputs.revision }}" >/dev/null 2>&1; then + echo "Release ${{ inputs.revision }} already exists, skipping." else - gh release create v${{ inputs.revision }} \ - --title "v${{ inputs.revision }}" \ - --generate-notes \ + gh release create ${{ inputs.revision }} \ + --title "${{ inputs.revision }}" \ + --notes-file /tmp/current-release-notes.md \ --latest fi env: @@ -111,7 +195,7 @@ jobs: run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - git add pom.xml + git add pom.xml release-notes.md git diff --cached --quiet && echo "No changes to commit" || \ git commit -m "chore: bump version to next patch after publishing ${{ inputs.revision }}" && git push @@ -127,4 +211,4 @@ jobs: echo "::error::Merge conflict detected when merging release-1.x into dev-1.x. Manual intervention required." exit 1 fi - git push origin dev-1.x \ No newline at end of file + git push origin dev-1.x diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index ba3515c9..f8a57317 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,3 +1,3 @@ wrapperVersion=3.3.4 distributionType=only-script -distributionUrl=https://dlcdn.apache.org/maven/maven-3/3.9.14/binaries/apache-maven-3.9.14-bin.zip +distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.9.15/apache-maven-3.9.15-bin.zip diff --git a/README.md b/README.md index 20ae97c3..8222c6aa 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ ![Maven](https://img.shields.io/maven-central/v/io.github.microsphere-projects/microsphere-spring-boot.svg) ![License](https://img.shields.io/github/license/microsphere-projects/microsphere-spring-boot.svg) - Microsphere Spring Boot is a collection of libraries that extends Spring Boot's capabilities with additional features focused on configuration management, application diagnostics, and enhanced monitoring. The project is structured as a multi-module Maven project that follows Spring Boot's conventions while providing value-added functionality. @@ -41,6 +40,7 @@ The easiest way to get started is by adding the Microsphere Spring Boot BOM (Bil pom.xml: ```xml + ... @@ -61,12 +61,13 @@ pom.xml: | **Branches** | **Purpose** | **Latest Version** | |--------------|--------------------------------------------------|--------------------| -| **0.2.x** | Compatible with Spring Boot 3.0.x - 3.5.x, 4.0.x | 0.2.10 | -| **0.1.x** | Compatible with Spring Boot 2.0.x - 2.7.x | 0.1.10 | +| **0.2.x** | Compatible with Spring Boot 3.0.x - 3.5.x, 4.0.x | 0.2.11 | +| **0.1.x** | Compatible with Spring Boot 2.0.x - 2.7.x | 0.1.11 | Then add the specific modules you need: ```xml + @@ -131,7 +132,8 @@ We welcome your contributions! Please read [Code of Conduct](./CODE_OF_CONDUCT.m ## Reporting Issues -* Before you log a bug, please search the [issues](https://github.com/microsphere-projects/microsphere-spring-boot/issues) +* Before you log a bug, please search + the [issues](https://github.com/microsphere-projects/microsphere-spring-boot/issues) to see if someone has already reported the problem. * If the issue doesn't already exist, [create a new issue](https://github.com/microsphere-projects/microsphere-spring-boot/issues/new). diff --git a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfiguration.java b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfiguration.java index 4ac5be12..e7f841dd 100644 --- a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfiguration.java +++ b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfiguration.java @@ -16,7 +16,6 @@ */ package io.microsphere.spring.boot.actuate.autoconfigure; -import io.micrometer.core.instrument.MeterRegistry; import io.microsphere.annotation.ConfigurationProperty; import io.microsphere.spring.boot.actuate.MonitoredThreadPoolTaskScheduler; import org.springframework.beans.factory.annotation.Value; @@ -87,6 +86,12 @@ public class ActuatorAutoConfiguration { */ public static final String ACTUATOR_TASK_SCHEDULER_SERVICE_BEAN_NAME = "actuatorTaskScheduler"; + /** + * The class name of {@link io.micrometer.core.instrument.MeterRegistry} + * @see io.micrometer.core.instrument.MeterRegistry + */ + static final String METER_REGISTRY_CLASS_NAME = "io.micrometer.core.instrument.MeterRegistry"; + /** * Creates a {@link MonitoredThreadPoolTaskScheduler} bean for actuator tasks, configured * with the given pool size and thread name prefix. @@ -103,7 +108,7 @@ public class ActuatorAutoConfiguration { * @param threadNamePrefix the prefix for thread names created by the scheduler * @return a configured {@link ThreadPoolTaskScheduler} instance */ - @ConditionalOnBean(MeterRegistry.class) + @ConditionalOnBean(type = METER_REGISTRY_CLASS_NAME) @Bean(name = ACTUATOR_TASK_SCHEDULER_SERVICE_BEAN_NAME, destroyMethod = "shutdown") public ThreadPoolTaskScheduler actuatorTaskScheduler( @Value(TASK_SCHEDULER_POOL_SIZE_VALUE_EXPRESSION) int poolSize, diff --git a/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfigurationTest.java b/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfigurationTest.java index f26d9830..14be10be 100644 --- a/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfigurationTest.java +++ b/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfigurationTest.java @@ -16,6 +16,7 @@ */ package io.microsphere.spring.boot.actuate.autoconfigure; +import io.micrometer.core.instrument.MeterRegistry; import org.junit.jupiter.api.ClassOrderer.OrderAnnotation; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -31,6 +32,7 @@ import static io.microsphere.spring.boot.actuate.autoconfigure.ActuatorAutoConfiguration.ACTUATOR_TASK_SCHEDULER_SERVICE_BEAN_NAME; import static io.microsphere.spring.boot.actuate.autoconfigure.ActuatorAutoConfiguration.DEFAULT_TASK_SCHEDULER_POOL_SIZE; +import static io.microsphere.spring.boot.actuate.autoconfigure.ActuatorAutoConfiguration.METER_REGISTRY_CLASS_NAME; import static io.microsphere.spring.boot.actuate.autoconfigure.ActuatorAutoConfiguration.TASK_SCHEDULER_POOL_SIZE_PROPERTY_NAME; import static io.microsphere.spring.boot.actuate.autoconfigure.ActuatorAutoConfiguration.TASK_SCHEDULER_THREAD_NAME_PREFIX_PROPERTY_NAME; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -53,6 +55,9 @@ void testConstants() { assertEquals("1", DEFAULT_TASK_SCHEDULER_POOL_SIZE); assertEquals("microsphere.spring.boot.actuator.task-scheduler.pool-size", TASK_SCHEDULER_POOL_SIZE_PROPERTY_NAME); assertEquals("microsphere.spring.boot.actuator.task-scheduler.thread-name-prefix", TASK_SCHEDULER_THREAD_NAME_PREFIX_PROPERTY_NAME); + assertEquals("io.micrometer.core.instrument.MeterRegistry", METER_REGISTRY_CLASS_NAME); + // test for strong type check + assertEquals(MeterRegistry.class.getName(), METER_REGISTRY_CLASS_NAME); } @Order(1) @@ -61,7 +66,8 @@ void testConstants() { @SpringBootTest( webEnvironment = NONE, classes = { - MeterRegistryPresent.class + MeterRegistryPresent.class, + ActuatorAutoConfigurationTest.class }, properties = { "microsphere.spring.boot.actuator.task-scheduler.pool-size=2", "microsphere.spring.boot.actuator.task-scheduler.thread-name-prefix=my-prefix", @@ -104,7 +110,8 @@ void testActuatorTaskScheduler() { @SpringBootTest( webEnvironment = NONE, classes = { - MeterRegistryAbsent.class + MeterRegistryAbsent.class, + ActuatorAutoConfigurationTest.class }, properties = { // Spring Boot [2.x,3.x] "microsphere.autoconfigure.exclude[0]=org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration", diff --git a/microsphere-spring-boot-core/pom.xml b/microsphere-spring-boot-core/pom.xml index d686f513..9d0437be 100644 --- a/microsphere-spring-boot-core/pom.xml +++ b/microsphere-spring-boot-core/pom.xml @@ -65,20 +65,6 @@ io.github.microsphere-projects microsphere-spring-test test - - - org.apache.zookeeper - zookeeper - - - org.apache.curator - curator-recipes - - - org.apache.curator - curator-test - - diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/SpringBootVersion.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/SpringBootVersion.java index 25e90349..14c394b1 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/SpringBootVersion.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/SpringBootVersion.java @@ -25,6 +25,7 @@ import static io.microsphere.constants.SymbolConstants.DOT_CHAR; import static io.microsphere.constants.SymbolConstants.UNDER_SCORE_CHAR; import static io.microsphere.util.Version.of; +import static io.microsphere.util.Version.ofVersion; /** * The enumeration for the released Spring Boot versions since 2.0 @@ -292,7 +293,7 @@ public enum SpringBootVersion { SPRING_BOOT_2_7_18, - CURRENT(of(org.springframework.boot.SpringBootVersion.getVersion())); + CURRENT(ofVersion(org.springframework.boot.SpringBootVersion.class)); private final Version version; diff --git a/microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/util/SpringApplicationUtilsTest.java b/microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/util/SpringApplicationUtilsTest.java index a35badd0..3ec52905 100644 --- a/microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/util/SpringApplicationUtilsTest.java +++ b/microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/util/SpringApplicationUtilsTest.java @@ -112,7 +112,7 @@ void testLog() { void testGetLoggingLevel(String level) { MockEnvironment environment = new MockEnvironment(); - environment.setProperty(MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL_PROPERTY_NAME, level); + environment.withProperty(MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL_PROPERTY_NAME, level); assertEquals(level, getLoggingLevel(environment)); } diff --git a/microsphere-spring-boot-parent/pom.xml b/microsphere-spring-boot-parent/pom.xml index 810cf22e..caedf5f7 100644 --- a/microsphere-spring-boot-parent/pom.xml +++ b/microsphere-spring-boot-parent/pom.xml @@ -19,7 +19,7 @@ Microsphere Spring Boot Parent - 0.1.9 + 0.1.14 1.7.2 5.14.3 @@ -57,7 +57,6 @@ - spring-boot-2.1 @@ -109,6 +108,5 @@ 2.7.18 - \ No newline at end of file diff --git a/pom.xml b/pom.xml index 414e1b2d..6096a99e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.github.microsphere-projects microsphere-build - 0.2.6 + 0.2.7 4.0.0