diff --git a/.github/actions/.bats/bats b/.github/actions/.bats/bats
new file mode 160000
index 00000000..902578da
--- /dev/null
+++ b/.github/actions/.bats/bats
@@ -0,0 +1 @@
+Subproject commit 902578da790fbcb035747d2964747f192f6e1603
diff --git a/.github/actions/.bats/test_helper/bats-assert b/.github/actions/.bats/test_helper/bats-assert
new file mode 160000
index 00000000..e2d855bc
--- /dev/null
+++ b/.github/actions/.bats/test_helper/bats-assert
@@ -0,0 +1 @@
+Subproject commit e2d855bc78619ee15b0c702b5c30fb074101159f
diff --git a/.github/actions/.bats/test_helper/bats-support b/.github/actions/.bats/test_helper/bats-support
new file mode 160000
index 00000000..9bf10e87
--- /dev/null
+++ b/.github/actions/.bats/test_helper/bats-support
@@ -0,0 +1 @@
+Subproject commit 9bf10e876dd6b624fe44423f0b35e064225f7556
diff --git a/.github/actions/deduce-versions/action.yml b/.github/actions/deduce-versions/action.yml
new file mode 100644
index 00000000..b8e197c4
--- /dev/null
+++ b/.github/actions/deduce-versions/action.yml
@@ -0,0 +1,22 @@
+name: 'Deduce Versions'
+description: 'Deduce the version to stage and the next SNAPSHOT version'
+inputs:
+ current-version:
+ required: true
+ release-type:
+ required: true
+outputs:
+ release-version:
+ value: ${{ steps.deduce-versions.outputs.release-version }}
+ next-version:
+ value: ${{ steps.deduce-versions.outputs.next-version }}
+runs:
+ using: composite
+ steps:
+ - name: Deduce Versions
+ id: deduce-versions
+ shell: bash
+ run: . ${{ github.action_path }}/deduce-versions.sh; deduce_versions
+ env:
+ CURRENT_VERSION: "${{ inputs.current-version }}"
+ RELEASE_TYPE: "${{ inputs.release-type }}"
diff --git a/.github/actions/deduce-versions/deduce-versions.sh b/.github/actions/deduce-versions/deduce-versions.sh
new file mode 100755
index 00000000..6a3d14e0
--- /dev/null
+++ b/.github/actions/deduce-versions/deduce-versions.sh
@@ -0,0 +1,116 @@
+#!/usr/bin/env bash
+
+# Get the next milestone release for the given number by inspecting current tags
+get_next_milestone_release() {
+ [[ -n $1 ]] || { echo "missing get_next_milestone_release() version argument" >&2; return 1; }
+ get_next_tag_based_release "$1" "M"
+}
+
+# Get the next RC release for the given number by inspecting current tags
+get_next_rc_release() {
+ [[ -n $1 ]] || { echo "missing get_next_rc_release() version argument" >&2; return 1; }
+ get_next_tag_based_release "$1" "RC"
+}
+
+# Get the next release for the given number
+get_next_release() {
+ [[ -n $1 ]] || { echo "missing get_next_release() version argument" >&2; return 1; }
+ if [[ $1 =~ ^(.*)\.BUILD-SNAPSHOT$ ]]; then
+ local join="."
+ else
+ local join="-"
+ fi
+ local version
+ local result
+ version=$( strip_snapshot_suffix "$1" )
+ if [[ -n $2 ]]; then
+ result="${version}${join}${2}"
+ else
+ result="${version}"
+ fi
+ echo $result
+}
+
+# Get the next milestone or RC release for the given number by inspecting current tags
+get_next_tag_based_release() {
+ [[ -n $1 ]] || { echo "missing get_next_tag_based_release() version argument" >&2; return 1; }
+ [[ -n $2 ]] || { echo "missing get_next_tag_based_release() tag type argument" >&2; return 1; }
+ if [[ $1 =~ ^(.*)\.BUILD-SNAPSHOT$ ]]; then
+ local join="."
+ else
+ local join="-"
+ fi
+ local version
+ local last
+ version=$( strip_snapshot_suffix "$1" )
+ git fetch --tags --all > /dev/null
+ last=$( git tag --list "v${version}${join}${2}*" | sed -E "s/^.*${2}([0-9]+)$/\1/g" | sort -rn | head -n1 )
+ if [[ -z $last ]]; then
+ last="0"
+ fi
+ last="${version}${join}${2}${last}"
+ bump_version_number "$last"
+}
+
+# Remove any "-SNAPSHOT" or ".BUILD-SNAPSHOT" suffix
+strip_snapshot_suffix() {
+ [[ -n $1 ]] || { echo "missing get_relase_version() argument" >&2; return 1; }
+ if [[ $1 =~ ^(.*)\.BUILD-SNAPSHOT$ ]]; then
+ echo "${BASH_REMATCH[1]}"
+ elif [[ $1 =~ ^(.*)-SNAPSHOT$ ]]; then
+ echo "${BASH_REMATCH[1]}"
+ else
+ echo "$1"
+ fi
+}
+
+# Bump version number by incrementing the last numeric, RC or M token
+bump_version_number() {
+ local version=$1
+ [[ -n $version ]] || { echo "missing bump_version_number() argument" >&2; return 1; }
+ if [[ $version =~ ^(.*(\.|-)([A-Za-z]+))([0-9]+)$ ]]; then
+ local prefix=${BASH_REMATCH[1]}
+ local suffix=${BASH_REMATCH[4]}
+ (( suffix++ ))
+ echo "${prefix}${suffix}"
+ return 0;
+ fi
+ local suffix
+ if [[ $version =~ ^(.*)(\-SNAPSHOT)$ ]]; then
+ version=${BASH_REMATCH[1]}
+ suffix="-SNAPSHOT"
+ fi
+ tokens=(${version//\./ })
+ local bumpIndex
+ for i in "${!tokens[@]}"; do
+ if [[ "${tokens[$i]}" =~ ^[0-9]+$ ]] ; then
+ bumpIndex=$i
+ fi
+ done
+ [[ -n $bumpIndex ]] || { echo "unsupported version number" >&2; return 1; }
+ (( tokens[bumpIndex]++ ))
+ local bumpedVersion
+ IFS=. eval 'bumpedVersion="${tokens[*]}"'
+ echo "${bumpedVersion}${suffix}"
+}
+
+# Deduce versions
+deduce_versions() {
+ [[ -n ${GITHUB_OUTPUT} ]] || { echo "missing GITHUB_OUTPUT environment variable" >&2; return 1; }
+ [[ -n ${CURRENT_VERSION} ]] || { echo "missing CURRENT_VERSION environment variable" >&2; return 1; }
+ [[ -n ${RELEASE_TYPE} ]] || { echo "missing RELEASE_TYPE environment variable" >&2; return 1; }
+ if [[ ${RELEASE_TYPE,,} = "milestone" ]]; then
+ releaseVersion=$( get_next_milestone_release ${CURRENT_VERSION})
+ nextVersion=${CURRENT_VERSION}
+ elif [[ ${RELEASE_TYPE,,} = "release-candidate" ]]; then
+ releaseVersion=$( get_next_rc_release ${CURRENT_VERSION})
+ nextVersion=${CURRENT_VERSION}
+ elif [[ ${RELEASE_TYPE,,} = "release" ]]; then
+ releaseVersion=$( get_next_release ${CURRENT_VERSION})
+ nextVersion=$( bump_version_number ${CURRENT_VERSION})
+ else
+ echo "Unknown release type '${RELEASE_TYPE}'" >&2; exit 1;
+ fi
+ echo "release-version=${releaseVersion}" >> "$GITHUB_OUTPUT"
+ echo "next-version=${nextVersion}" >> "$GITHUB_OUTPUT"
+}
diff --git a/.github/actions/deduce-versions/test.sh b/.github/actions/deduce-versions/test.sh
new file mode 100755
index 00000000..0a8e4130
--- /dev/null
+++ b/.github/actions/deduce-versions/test.sh
@@ -0,0 +1 @@
+../.bats/bats/bin/bats test/*.bats
\ No newline at end of file
diff --git a/.github/actions/deduce-versions/test/bump_version.bats b/.github/actions/deduce-versions/test/bump_version.bats
new file mode 100644
index 00000000..5efd9f0b
--- /dev/null
+++ b/.github/actions/deduce-versions/test/bump_version.bats
@@ -0,0 +1,58 @@
+#!./test/libs/bats/bin/bats
+
+load '../../.bats/test_helper/bats-support/load'
+load '../../.bats/test_helper/bats-assert/load'
+
+source "$PWD/deduce-versions.sh"
+
+@test "bump_version_number() should bump '.M'" {
+ run bump_version_number "1.2.0.M2"
+ assert_output "1.2.0.M3"
+}
+
+@test "bump_version_number() should bump '.RC'" {
+ run bump_version_number "1.2.0.RC3"
+ assert_output "1.2.0.RC4"
+}
+
+@test "bump_version_number() should bump '-M'" {
+ run bump_version_number "1.2.0-M2"
+ assert_output "1.2.0-M3"
+}
+
+@test "bump_version_number() should bump '-RC'" {
+ run bump_version_number "1.2.0-RC3"
+ assert_output "1.2.0-RC4"
+}
+
+@test "bump_version_number() should bump without suffix" {
+ run bump_version_number "1.2.0"
+ assert_output "1.2.1"
+}
+
+@test "bump_version_number() should bump '.RELEASE'" {
+ run bump_version_number "1.2.0.RELEASE"
+ assert_output "1.2.1.RELEASE"
+}
+
+@test "bump_version_number() should bump '-SNAPSHOT'" {
+ run bump_version_number "1.2.0-SNAPSHOT"
+ assert_output "1.2.1-SNAPSHOT"
+}
+
+@test "bump_version_number() should bump '.BUILD-SNAPSHOT'" {
+ run bump_version_number "1.2.0.BUILD-SNAPSHOT"
+ assert_output "1.2.1.BUILD-SNAPSHOT"
+}
+
+@test "bump_version_number() when missing argument should fail" {
+ run bump_version_number
+ assert_output "missing bump_version_number() argument"
+ assert [ "$status" -eq 1 ]
+}
+
+@test "bump_version_number() when bad argument should fail" {
+ run bump_version_number "foo.bar.baz"
+ assert_output "unsupported version number"
+ assert [ "$status" -eq 1 ]
+}
diff --git a/.github/actions/deduce-versions/test/deduce_versions.bats b/.github/actions/deduce-versions/test/deduce_versions.bats
new file mode 100644
index 00000000..2ffbf599
--- /dev/null
+++ b/.github/actions/deduce-versions/test/deduce_versions.bats
@@ -0,0 +1,96 @@
+#!./test/libs/bats/bin/bats
+
+load '../../.bats/test_helper/bats-support/load'
+load '../../.bats/test_helper/bats-assert/load'
+
+source "$PWD/deduce-versions.sh"
+
+teardown() {
+ rm .githuboutput | true
+}
+
+@test "deduce_versions() when 'milestone' should export versions" {
+ repo=$( mock_git_repo "v1.2.3-M1" )
+ cd "$repo"
+ GITHUB_OUTPUT=".githuboutput"
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ RELEASE_TYPE="milestone"
+ run deduce_versions
+ readarray -t githuboutput < .githuboutput
+ assert [ "$status" -eq 0 ]
+ assert [ "${githuboutput[0]}" = "release-version=1.2.3-M2" ]
+ assert [ "${githuboutput[1]}" = "next-version=1.2.3-SNAPSHOT" ]
+}
+
+@test "deduce_versions() when 'release-candidate' should export versions" {
+ repo=$( mock_git_repo "v1.2.3-M1" "v1.2.3-M2" "v1.2.3-RC1" )
+ cd "$repo"
+ GITHUB_OUTPUT=".githuboutput"
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ RELEASE_TYPE="release-candidate"
+ run deduce_versions
+ readarray -t githuboutput < .githuboutput
+ assert [ "$status" -eq 0 ]
+ assert [ "${githuboutput[0]}" = "release-version=1.2.3-RC2" ]
+ assert [ "${githuboutput[1]}" = "next-version=1.2.3-SNAPSHOT" ]
+}
+
+@test "deduce_versions() when 'release' should export versions" {
+ repo=$( mock_git_repo "v1.2.3-M1" "v1.2.3-M2" "v1.2.3-RC1" )
+ cd "$repo"
+ GITHUB_OUTPUT=".githuboutput"
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ RELEASE_TYPE="release"
+ run deduce_versions
+ readarray -t githuboutput < .githuboutput
+ assert [ "$status" -eq 0 ]
+ assert [ "${githuboutput[0]}" = "release-version=1.2.3" ]
+ assert [ "${githuboutput[1]}" = "next-version=1.2.4-SNAPSHOT" ]
+}
+
+@test "deduce_versions() when no GITHUB_OUTPUT should fail" {
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ RELEASE_TYPE="release"
+ run deduce_versions
+ assert [ "$status" -eq 1 ]
+ assert_output "missing GITHUB_OUTPUT environment variable"
+}
+
+@test "deduce_versions() when no CURRENT_VERSION should fail" {
+ GITHUB_OUTPUT=".githuboutput"
+ RELEASE_TYPE="release"
+ run deduce_versions
+ assert [ "$status" -eq 1 ]
+ assert_output "missing CURRENT_VERSION environment variable"
+}
+
+@test "deduce_versions() when no RELEASE_TYPE should fail" {
+ GITHUB_OUTPUT=".githuboutput"
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ run deduce_versions
+ assert [ "$status" -eq 1 ]
+ assert_output "missing RELEASE_TYPE environment variable"
+}
+
+@test "deduce_versions() when wrong RELEASE_TYPE should fail" {
+ GITHUB_OUTPUT=".githuboutput"
+ CURRENT_VERSION="1.2.3-SNAPSHOT"
+ RELEASE_TYPE="nope"
+ run deduce_versions
+ assert [ "$status" -eq 1 ]
+ assert_output "Unknown release type 'nope'"
+}
+
+mock_git_repo() {
+ local tmpdir=$(mktemp -d $BATS_TMPDIR/gitrepo.XXXXXX) >&2
+ mkdir -p "$tmpdir" >&2
+ cd "$tmpdir" >&2
+ git init >&2
+ echo "foo" > foo.txt
+ git add foo.txt >&2
+ git commit -m'Initial commit' >&2
+ for tag in "$@"; do
+ git tag "$tag" >&2
+ done
+ echo "$tmpdir"
+}
\ No newline at end of file
diff --git a/.github/actions/deduce-versions/test/get_next_release.bats b/.github/actions/deduce-versions/test/get_next_release.bats
new file mode 100644
index 00000000..b9be5c0e
--- /dev/null
+++ b/.github/actions/deduce-versions/test/get_next_release.bats
@@ -0,0 +1,119 @@
+#!./test/libs/bats/bin/bats
+
+load '../../.bats/test_helper/bats-support/load'
+load '../../.bats/test_helper/bats-assert/load'
+
+source "$PWD/deduce-versions.sh"
+
+@test "get_next_milestone_release() when has no version should fail" {
+ run get_next_milestone_release
+ assert [ "$status" -eq 1 ]
+ assert_output "missing get_next_milestone_release() version argument"
+}
+
+@test "get_next_rc_release() when has no version should fail" {
+ run get_next_rc_release
+ assert [ "$status" -eq 1 ]
+ assert_output "missing get_next_rc_release() version argument"
+}
+
+@test "get_next_tag_based_release() when has no version should fail" {
+ run get_next_tag_based_release
+ assert [ "$status" -eq 1 ]
+ assert_output "missing get_next_tag_based_release() version argument"
+}
+
+@test "get_next_tag_based_release() when has no tag type should fail" {
+ run get_next_tag_based_release "1.2.3"
+ assert [ "$status" -eq 1 ]
+ assert_output "missing get_next_tag_based_release() tag type argument"
+}
+
+@test "get_next_milestone_release() when has no tag should return M1" {
+ repo=$( mock_git_repo )
+ cd "$repo"
+ run get_next_milestone_release "1.2.3-SNAPSHOT"
+ assert_output "1.2.3-M1"
+}
+
+@test "get_next_rc_release() when has no tag should return RC1" {
+ repo=$( mock_git_repo )
+ cd "$repo"
+ run get_next_rc_release "1.2.3-SNAPSHOT"
+ assert_output "1.2.3-RC1"
+}
+
+@test "get_next_tag_based_release() when has no tag and dash SNAPSHOT suffix should return dashed X1" {
+ repo=$( mock_git_repo )
+ cd "$repo"
+ run get_next_tag_based_release "1.2.3-SNAPSHOT" "X"
+ assert_output "1.2.3-X1"
+}
+
+@test "get_next_tag_based_release() when has no tag and dash BUILD-SNAPSHOT suffix should return dashed X1" {
+ repo=$( mock_git_repo )
+ cd "$repo"
+ run get_next_tag_based_release "1.2.3.BUILD-SNAPSHOT" "X"
+ assert_output "1.2.3.X1"
+}
+
+@test "get_next_tag_based_release() when has tags and dashed should return dashed X tag+1" {
+ repo=$( mock_git_repo "v1.2.3-X1" "v1.2.3-X3" "v1.2.3-X2" )
+ cd "$repo"
+ run get_next_tag_based_release "1.2.3-SNAPSHOT" "X"
+ assert_output "1.2.3-X4"
+}
+
+@test "get_next_tag_based_release() when has tags and dashed should return dot X tag+1" {
+ repo=$( mock_git_repo "v1.2.3.X1" "v1.2.3.X3" "v1.2.3.X2" )
+ cd "$repo"
+ run get_next_tag_based_release "1.2.3.BUILD-SNAPSHOT" "X"
+ assert_output "1.2.3.X4"
+}
+
+@test "get_next_tag_based_release() when has multiple tags should return version match tag+1" {
+ repo=$( mock_git_repo "v1.5.0.A1" "v1.5.0.A2" "v1.5.0.B1" "v2.0.0.A1" "v2.0.0.B1" "v2.0.0.B2" )
+ cd "$repo"
+ run get_next_tag_based_release "1.5.0.BUILD-SNAPSHOT" "A"
+ assert_output "1.5.0.A3"
+ run get_next_tag_based_release "1.5.0.BUILD-SNAPSHOT" "B"
+ assert_output "1.5.0.B2"
+ run get_next_tag_based_release "2.0.0.BUILD-SNAPSHOT" "A"
+ assert_output "2.0.0.A2"
+ run get_next_tag_based_release "2.0.0.BUILD-SNAPSHOT" "B"
+ assert_output "2.0.0.B3"
+}
+
+@test "get_next_release() should return next release version with release suffix" {
+ run get_next_release "1.5.0.BUILD-SNAPSHOT" "RELEASE"
+ assert_output "1.5.0.RELEASE"
+ run get_next_release "1.5.0-SNAPSHOT" "RELEASE"
+ assert_output "1.5.0-RELEASE"
+}
+
+@test "get_next_release() should return next release version" {
+ run get_next_release "1.5.0.BUILD-SNAPSHOT"
+ assert_output "1.5.0"
+ run get_next_release "1.5.0-SNAPSHOT"
+ assert_output "1.5.0"
+}
+
+@test "get_next_release() when has no version should fail" {
+ run get_next_release
+ assert [ "$status" -eq 1 ]
+ assert_output "missing get_next_release() version argument"
+}
+
+mock_git_repo() {
+ local tmpdir=$(mktemp -d $BATS_TMPDIR/gitrepo.XXXXXX) >&2
+ mkdir -p "$tmpdir" >&2
+ cd "$tmpdir" >&2
+ git init >&2
+ echo "foo" > foo.txt
+ git add foo.txt >&2
+ git commit -m'Initial commit' >&2
+ for tag in "$@"; do
+ git tag "$tag" >&2
+ done
+ echo "$tmpdir"
+}
diff --git a/.github/actions/deduce-versions/test/strip_snapshot_suffix.bats b/.github/actions/deduce-versions/test/strip_snapshot_suffix.bats
new file mode 100644
index 00000000..bef64867
--- /dev/null
+++ b/.github/actions/deduce-versions/test/strip_snapshot_suffix.bats
@@ -0,0 +1,21 @@
+#!./test/libs/bats/bin/bats
+
+load '../../.bats/test_helper/bats-support/load'
+load '../../.bats/test_helper/bats-assert/load'
+
+source "$PWD/deduce-versions.sh"
+
+@test "strip_snapshot_suffix() should strip '-SNAPSHOT" {
+ run strip_snapshot_suffix "1.2.0-SNAPSHOT"
+ assert_output "1.2.0"
+}
+
+@test "strip_snapshot_suffix() should strip '.BUILD-SNAPSHOT" {
+ run strip_snapshot_suffix "1.2.0.BUILD-SNAPSHOT"
+ assert_output "1.2.0"
+}
+
+@test "strip_snapshot_suffix() when no suffix should return unchanged" {
+ run strip_snapshot_suffix "1.2.0"
+ assert_output "1.2.0"
+}
diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml
new file mode 100644
index 00000000..6f967b7a
--- /dev/null
+++ b/.github/actions/setup/action.yml
@@ -0,0 +1,15 @@
+name: 'Setup'
+runs:
+ using: composite
+ steps:
+ - name: Set Up Utilities
+ shell: bash
+ run: sudo apt-get -y install libxml2-utils
+ - name: Set Up Java
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'liberica'
+ java-version: '17'
+ cache: maven
+ - name: Disable Java Problem Matcher
+ run: echo "::remove-matcher owner=java::"
diff --git a/.github/actions/stage-code/action.yml b/.github/actions/stage-code/action.yml
new file mode 100644
index 00000000..a71086eb
--- /dev/null
+++ b/.github/actions/stage-code/action.yml
@@ -0,0 +1,23 @@
+name: 'Stage '
+description: 'Stage Code'
+inputs:
+ current-version:
+ required: true
+ release-version:
+ required: true
+ next-version:
+ required: true
+outputs:
+ distribution-repository:
+ value: ${{ steps.stage.outputs.distribution-repository }}
+runs:
+ using: composite
+ steps:
+ - name: Stage
+ id: stage
+ shell: bash
+ run: . ${{ github.action_path }}/stage.sh;
+ env:
+ CURRENT_VERSION: "${{ inputs.current-version }}"
+ RELEASE_VERSION: "${{ inputs.release-version }}"
+ NEXT_VERSION: "${{ inputs.next-version }}"
diff --git a/.github/actions/stage-code/stage.sh b/.github/actions/stage-code/stage.sh
new file mode 100644
index 00000000..6ac9c2f0
--- /dev/null
+++ b/.github/actions/stage-code/stage.sh
@@ -0,0 +1,32 @@
+repository=${GITHUB_WORKSPACE}/distribution-repository
+
+echo "Staging ${RELEASE_VERSION} to ${repository} (next version will be ${NEXT_VERSION})"
+
+./mvnw versions:set --batch-mode --no-transfer-progress -DnewVersion=${RELEASE_VERSION} -DgenerateBackupPoms=false
+./mvnw org.eclipse.tycho:tycho-versions-plugin:update-eclipse-metadata --batch-mode --no-transfer-progress
+./mvnw --projects io.spring.javaformat:spring-javaformat-vscode-extension --batch-mode --no-transfer-progress -P '!formatter-dependencies' antrun:run@update-version frontend:install-node-and-npm frontend:npm@update-package-lock
+
+git config user.name "Spring Builds" > /dev/null
+git config user.email "spring-builds@users.noreply.github.com" > /dev/null
+git add pom.xml > /dev/null
+git commit -m"Release v${RELEASE_VERSION}" > /dev/null
+git tag -a "v${RELEASE_VERSION}" -m"Release v${RELEASE_VERSION}" > /dev/null
+
+./mvnw clean deploy --batch-mode --no-transfer-progress -U -Dfull -DaltDeploymentRepository=distribution::file://${repository}
+
+git reset --hard HEAD^ > /dev/null
+if [[ ${NEXT_VERSION} != ${CURRENT_VERSION} ]]; then
+ echo "Setting next development version (v${NEXT_VERSION})"
+ ./mvnw versions:set --batch-mode --no-transfer-progress -DnewVersion=${NEXT_VERSION} -DgenerateBackupPoms=false
+ ./mvnw org.eclipse.tycho:tycho-versions-plugin:update-eclipse-metadata --batch-mode --no-transfer-progress
+ ./mvnw --projects io.spring.javaformat:spring-javaformat-vscode-extension --batch-mode --no-transfer-progress -P '!formatter-dependencies' antrun:run@update-version frontend:npm@update-package-lock
+ sed -i "s/:release-version:.*/:release-version: ${RELEASE_VERSION}/g" README.adoc
+ sed -i "s/spring-javaformat-gradle-plugin:.*/spring-javaformat-gradle-plugin:${NEXT_VERSION}\"\)/g" samples/spring-javaformat-gradle-sample/build.gradle
+ sed -i "s/spring-javaformat-checkstyle:.*/spring-javaformat-checkstyle:${NEXT_VERSION}\"\)/g" samples/spring-javaformat-gradle-sample/build.gradle
+ sed -i "s|.*|${NEXT_VERSION}|" samples/spring-javaformat-maven-sample/pom.xml
+ git add -u . > /dev/null
+ git commit -m"Next development version (v${NEXT_VERSION})" > /dev/null
+fi;
+
+echo "Staged the following files:"
+find ${repository}
diff --git a/.github/workflows/build-and-deploy-snapshot.yml b/.github/workflows/build-and-deploy-snapshot.yml
index ac74bfca..d269a903 100644
--- a/.github/workflows/build-and-deploy-snapshot.yml
+++ b/.github/workflows/build-and-deploy-snapshot.yml
@@ -6,29 +6,25 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
- build:
- if: ${{ github.repository == 'spring-io/spring-javaformat' }}
+ build-and-deploy-snapshot:
name: Build and Deploy Snapshot
runs-on: ubuntu-latest
+ if: ${{ github.repository == 'spring-io/spring-javaformat' }}
steps:
- - name: Check Out Code
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: Set Up Java
- uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
- with:
- distribution: 'liberica'
- java-version: 17
- cache: maven
- - name: Build and Publish
- run: ./mvnw clean deploy --batch-mode --no-transfer-progress --update-snapshots -Dfull -DaltDeploymentRepository=distribution::file://$(pwd)/distribution-repository
- - name: Deploy
- uses: spring-io/artifactory-deploy-action@26bbe925a75f4f863e1e529e85be2d0093cac116 # v0.0.1
- with:
- uri: 'https://repo.spring.io'
- username: ${{ secrets.ARTIFACTORY_USERNAME }}
- password: ${{ secrets.ARTIFACTORY_PASSWORD }}
- build-name: spring-javaformat
- repository: 'libs-snapshot-local'
- folder: 'distribution-repository'
- signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
- signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
+ - name: Check Out
+ uses: actions/checkout@v4
+ - name: Set Up
+ uses: ./.github/actions/setup
+ - name: Build
+ run: ./mvnw clean deploy --batch-mode --no-transfer-progress --update-snapshots -DaltDeploymentRepository=distribution::file://$(pwd)/distribution-repository
+ - name: Deploy
+ uses: spring-io/artifactory-deploy-action@v0.0.1
+ with:
+ folder: 'distribution-repository'
+ uri: 'https://repo.spring.io'
+ repository: 'libs-snapshot-local'
+ build-name: spring-javaformat
+ username: ${{ secrets.ARTIFACTORY_USERNAME }}
+ password: ${{ secrets.ARTIFACTORY_PASSWORD }}
+ signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
+ signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml
new file mode 100644
index 00000000..0965a8c3
--- /dev/null
+++ b/.github/workflows/build-pull-request.yml
@@ -0,0 +1,16 @@
+name: Build Pull Request
+on: pull_request
+permissions:
+ contents: read
+jobs:
+ build:
+ name: Build Pull Request
+ runs-on: ubuntu-latest
+ if: ${{ github.repository == 'spring-projects/spring-boot' }}
+ steps:
+ - name: Check Out
+ uses: actions/checkout@v4
+ - name: Set Up
+ uses: ./.github/actions/setup
+ - name: Build
+ run: ./mvnw clean install --batch-mode --no-transfer-progress --update-snapshots
diff --git a/.github/workflows/promote.yml b/.github/workflows/promote.yml
new file mode 100644
index 00000000..968b265f
--- /dev/null
+++ b/.github/workflows/promote.yml
@@ -0,0 +1,37 @@
+name: Promote
+run-name: >-
+ Promote of version ${{ inputs.version }} (build number ${{ inputs.build-number}}) by ${{ github.actor }} to '${{ inputs.environment }}' environment'
+on:
+ workflow_call:
+ inputs:
+ environment:
+ type: string
+ required: true
+ version:
+ type: string
+ required: true
+ build-number:
+ type: string
+ required: true
+ workflow_dispatch:
+ inputs:
+ environment:
+ description: Environment
+ type: environment
+ required: true
+ version:
+ description: The version number to promote
+ type: string
+ required: true
+ build-number:
+ description: The build number to promote
+ type: string
+ required: true
+jobs:
+ promote:
+ environment: ${{ inputs.environment }}
+ name: Promote
+ runs-on: ubuntu-latest
+ steps:
+ - name: Promote
+ run: echo "Promote happens here"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..4e5d4746
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,58 @@
+name: Release
+run-name: >-
+ Release of '${{ github.ref_name }}' branch to '${{ inputs.environment }}' environment by ${{ github.actor }}
+on:
+ workflow_dispatch:
+ inputs:
+ environment:
+ description: Environment
+ type: environment
+ required: true
+jobs:
+ stage:
+ name: Stage
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check Out
+ uses: actions/checkout@v4
+ - name: Set Up
+ uses: ./.github/actions/setup
+ - name: Get Current Version
+ id: get-version
+ run: echo "current-version=$(xmllint --xpath '/*[local-name()="project"]/*[local-name()="version"]/text()' pom.xml)" >> $GITHUB_OUTPUT
+ - name: Deduce Versions
+ id: deduce-versions
+ uses: ./.github/actions/deduce-versions
+ with:
+ current-version: ${{ steps.get-version.outputs.current-version }}
+ release-type: ${{ inputs.environment }}
+ - name: Stage Code
+ id: stage-code
+ uses: ./.github/actions/stage-code
+ with:
+ current-version: ${{ steps.get-version.outputs.current-version }}
+ release-version: ${{ steps.deduce-versions.outputs.release-version }}
+ next-version: ${{ steps.deduce-versions.outputs.next-version }}
+ - name: Deploy to Staging
+ uses: spring-io/artifactory-deploy-action@v0.0.1
+ with:
+ folder: distribution-repository
+ uri: 'https://repo.spring.io'
+ repository: 'libs-staging-local'
+ build-name: ${{ format('spring-javaformat-{0}', steps.deduce-versions.outputs.release-version)}}
+ username: ${{ secrets.ARTIFACTORY_USERNAME }}
+ password: ${{ secrets.ARTIFACTORY_PASSWORD }}
+ signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
+ signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
+ - name: Push
+ run: git push origin HEAD --tags
+ outputs:
+ release-version: ${{ steps.deduce-versions.outputs.release-version }}
+ promote:
+ name: Promote
+ needs: stage
+ uses: ./.github/workflows/promote.yml
+ with:
+ environment: ${{ inputs.environment }}
+ version: ${{needs.stage.outputs.release-version}}
+ build-number: ${{ github.run_number }}
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..64d1aa9d
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,12 @@
+[submodule ".github/actions/.bats/bats"]
+ path = .github/actions/.bats/bats
+ url = https://github.com/bats-core/bats-core.git
+ tag = v1.11.0
+[submodule ".github/actions/.bats/test_helper/bats-support"]
+ path = .github/actions/.bats/test_helper/bats-support
+ url = https://github.com/bats-core/bats-support.git
+ tag = v0.3.0
+[submodule ".github/actions/.bats/test_helper/bats-assert"]
+ path = .github/actions/.bats/test_helper/bats-assert
+ url = https://github.com/bats-core/bats-assert.git
+ tag = v2.1.0