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..7f8bc0e2 --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,16 @@ +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 + shell: bash + 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/.github/workflows/rollback.yml b/.github/workflows/rollback.yml new file mode 100644 index 00000000..43e04a4d --- /dev/null +++ b/.github/workflows/rollback.yml @@ -0,0 +1,41 @@ +name: Rollback +run-name: >- + Rollback of version ${{ inputs.version }} (build number ${{ inputs.build-number}}) by ${{ github.actor }} +on: + workflow_dispatch: + inputs: + environment: + description: Environment + type: environment + required: true + version: + description: The version number to roll back + type: string + required: true + build-number: + description: The build number to roll back + type: string + required: true +jobs: + rollback: + environment: ${{ inputs.environment }} + name: Roll Back + runs-on: ubuntu-latest + steps: + - name: Check Out + uses: actions/checkout@v4 + - name: Set Up JFrog CLI + uses: jfrog/setup-jfrog-cli@7c95feb32008765e1b4e626b078dfd897c4340ad # v4.1.2 + env: + JF_ENV_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }} + - name: Delete Staged Artifacts + run: | + url=${{ format('libs-staging-local/io/spring/javaformat/spring-javaformat/{0}/spring-javaformat-{0}.pom', inputs.version) }} + artifact_count=$( jf rt s ${url} --count ) + if [ "${artifact_count}" != 1 ]; then + echo "Unexpected aretifact count ${artifact_count}" + exit 1 + fi + build_name=${{ format('spring-javaformat-{0}', inputs.version)}} + build_number=${{ inputs.build-number }} + jf rt delete --build ${build_name}/${build_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