diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8526a994..d0baeb59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,19 +11,17 @@ on: workflow_dispatch: env: -# SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} -# GRADLE_ENTERPRISE_CACHE_USER: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USER }} -# GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }} -# GRADLE_ENTERPRISE_SECRET_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }} COMMIT_OWNER: ${{ github.event.pusher.name }} COMMIT_SHA: ${{ github.sha }} ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} jobs: - build: + build_and_deploy: if: github.repository == 'spring-projects-experimental/spring-pulsar' runs-on: ubuntu-latest + outputs: + project_version: ${{ steps.extract_version.outputs.project_version }} steps: - name: Checkout repo uses: actions/checkout@v2 @@ -41,10 +39,6 @@ jobs: env: GRADLE_USER_HOME: ~/.gradle - name: Run Gradle build -# env: -# GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USER }} -# GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }} -# GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }} run: | ./gradlew clean build --continue -PartifactoryUsername="$ARTIFACTORY_USERNAME" -PartifactoryPassword="$ARTIFACTORY_PASSWORD" - name: Capture Test Results @@ -55,15 +49,84 @@ jobs: path: '*/build/reports/tests/**/*.*' retention-days: 3 - name: Deploy artifacts -# env: -# ORG_GRADLE_PROJECT_signingKey: ${{ secrets.GPG_PRIVATE_KEY }} -# ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.GPG_PASSPHRASE }} -# OSSRH_TOKEN_USERNAME: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }} -# OSSRH_TOKEN_PASSWORD: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }} -# ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} -# ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} -# GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USER }} -# GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }} -# GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }} run: | ./gradlew publishArtifact -PartifactoryUsername="$ARTIFACTORY_USERNAME" -PartifactoryPassword="$ARTIFACTORY_PASSWORD" -PossrhUsername="$OSSRH_TOKEN_USERNAME" -PossrhPassword="$OSSRH_TOKEN_PASSWORD" --stacktrace + - id: extract_version + name: Extract current version + run: | + version=$(cat gradle.properties | grep "version=" | awk -F'=' '{print $2}') + echo "::set-output name=project_version::$version" + perform_release: + name: Perform release + needs: [build_and_deploy] + runs-on: ubuntu-latest + permissions: + contents: write + timeout-minutes: 90 + if: ${{ !endsWith(needs.build_and_deploy.outputs.project_version, '-SNAPSHOT') }} + env: + REPO: ${{ github.repository }} + BRANCH: ${{ github.ref_name }} + TOKEN: ${{ github.token }} + VERSION: ${{ needs.build_and_deploy.outputs.project_version }} + steps: + - uses: actions/checkout@v2 + with: + token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }} + - name: Set up gradle + uses: spring-io/spring-gradle-build-action@v1 + with: + java-version: '17' + distribution: 'temurin' + - name: Wait for Artifactory Artifacts + if: ${{ contains(needs.build_and_deploy.outputs.project_version, '-RC') || contains(needs.build_and_deploy.outputs.project_version, '-M') }} + run: | + echo "Wait for artifacts of $REPO@$VERSION to appear on Artifactory." + until curl -f -s https://repo.spring.io/artifactory/milestone/org/springframework/pulsar/spring-pulsar/$VERSION/ > /dev/null + do + sleep 30 + echo "." + done + echo "Artifacts for $REPO@$VERSION have been released to Artifactory." + - name: Wait for Maven Central Artifacts + if: ${{ !contains(needs.build_and_deploy.outputs.project_version, '-RC') && !contains(needs.build_and_deploy.outputs.project_version, '-M') }} + run: | + echo "Wait for artifacts of $REPO@$VERSION to appear on Maven Central." + until curl -f -s https://repo1.maven.org/maven2/org/springframework/pulsar/spring-pulsar/$VERSION/ > /dev/null + do + sleep 30 + echo "." + done + echo "Artifacts for $REPO@$VERSION have been released to Maven Central." + - name: Setup git config + run: | + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + - name: Tag Release + if: ${{ contains(needs.build_and_deploy.outputs.project_version, '-RC') || contains(needs.build_and_deploy.outputs.project_version, '-M') }} + run: | + echo "Tagging $REPO@$VERSION release." + git tag $VERSION + git push --tags origin + - name: Create Branch and Tag Release + if: ${{ !contains(needs.build_and_deploy.outputs.project_version, '-RC') && !contains(needs.build_and_deploy.outputs.project_version, '-M') }} + run: | + echo "Tagging $REPO@$VERSION and creating release branch." + git checkout -b $VERSION + git commit -am "[Release $VERSION] create release branch" + git push origin $VERSION + git tag $VERSION + git push --tags origin + - name: Create GitHub Release + uses: ./.github/workflows/github-release.yml + with: + releaseVersion: $VERSION + secrets: + GH_ACTIONS_REPO_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Update to next Snapshot Version + run: | + echo "Updating $REPO@$VERSION to next snapshot version." + ./gradlew :updateToSnapshotVersion + git commit -am "[Release $VERSION] Next development version" + git push diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index b14ed215..65975546 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -33,8 +33,8 @@ jobs: - id: check-open-issues name: Check for open issues run: | - echo "::set-output name=is_open_issues::false" echo "TODO actually check for open issues" + echo "::set-output name=is_open_issues::false" - id: validate-release-state name: Validate release state if: steps.check-open-issues.outputs.is_open_issues == 'true' @@ -52,15 +52,7 @@ jobs: releaseVersion="${{ inputs.releaseVersion }}" releaseBranch="release-initiate/$releaseVersion" git checkout -b $releaseBranch - currentVersion=$(cat gradle.properties | grep "version=" | awk -F'=' '{print $2}') - echo "Updating version from $currentVersion to $releaseVersion" - sed -i.orig "s/version=$currentVersion/version=$releaseVersion/" gradle.properties - rm -rf gradle.properties.orig - updatedVersion=$(cat gradle.properties | grep "version=" | awk -F'=' '{print $2}') - if [ "$updatedVersion" != "$releaseVersion" ]; then - echo "Version was updated to $updatedVersion but expected $releaseVersion" - exit 1 - fi + ./gradlew :updateToReleaseVersion -PreleaseVersion=$releaseVersion git commit -am "[Release $releaseVersion] Update version" git push origin $releaseBranch gh pr create --title "[Release $releaseVersion] Update version" --body "Merge to initiate release." diff --git a/build.gradle b/build.gradle index 0aaa1f2b..5005b504 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ plugins { id 'io.spring.nohttp' id 'org.springframework.pulsar.root-project' + id 'org.springframework.pulsar.update-version' id 'org.ajoberstar.grgit' version '4.0.1' apply false } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index ae6efb25..7a85986d 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -96,6 +96,10 @@ gradlePlugin { id = "org.springframework.pulsar.spring-module" implementationClass = "org.springframework.pulsar.gradle.SpringModulePlugin" } + updateProjectVersion { + id = "org.springframework.pulsar.update-version" + implementationClass = "org.springframework.pulsar.gradle.versions.UpdateProjectVersionPlugin" + } // groovy plugins artifactoryPlugin { id = "io.spring.convention.artfiactory" diff --git a/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/FileUtils.java b/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/FileUtils.java new file mode 100644 index 00000000..351e903b --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/FileUtils.java @@ -0,0 +1,49 @@ +/* + * Copyright 2019-2022 the original author or authors. + * + * Licensed 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. + */ + +package org.springframework.pulsar.gradle.versions; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.function.Function; + +class FileUtils { + static void replaceFileText(File file, Function replaceText) { + String buildFileText = readString(file); + String updatedBuildFileText = replaceText.apply(buildFileText); + writeString(file, updatedBuildFileText); + } + + static String readString(File file) { + try { + byte[] bytes = Files.readAllBytes(file.toPath()); + return new String(bytes); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static void writeString(File file, String text) { + try { + Files.write(file.toPath(), text.getBytes()); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateProjectVersionPlugin.java b/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateProjectVersionPlugin.java new file mode 100644 index 00000000..655e3b56 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateProjectVersionPlugin.java @@ -0,0 +1,35 @@ +/* + * Copyright 2019-2022 the original author or authors. + * + * Licensed 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. + */ + +package org.springframework.pulsar.gradle.versions; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; + +public class UpdateProjectVersionPlugin implements Plugin { + @Override + public void apply(Project project) { + project.getTasks().register("updateToReleaseVersion", UpdateToReleaseVersionTask.class, updateToReleaseVersionTask -> { + updateToReleaseVersionTask.setGroup("Release"); + updateToReleaseVersionTask.setDescription("Updates the project version to the next release in gradle.properties"); + updateToReleaseVersionTask.setReleaseVersion((String) project.findProperty("releaseVersion")); + }); + project.getTasks().register("updateToSnapshotVersion", UpdateToSnapshotVersionTask.class, updateToSnapshotVersionTask -> { + updateToSnapshotVersionTask.setGroup("Release"); + updateToSnapshotVersionTask.setDescription("Updates the project version to the next snapshot in gradle.properties"); + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateProjectVersionTask.java b/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateProjectVersionTask.java new file mode 100644 index 00000000..71cb2595 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateProjectVersionTask.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019-2022 the original author or authors. + * + * Licensed 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. + */ + +package org.springframework.pulsar.gradle.versions; + +import java.io.File; + +import org.gradle.api.DefaultTask; +import org.gradle.api.Project; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.TaskAction; + +public abstract class UpdateProjectVersionTask extends DefaultTask { + + protected void updateVersionInGradleProperties(String newVersion) { + String currentVersion = getProject().getVersion().toString(); + File gradlePropertiesFile = getProject().getRootProject().file(Project.GRADLE_PROPERTIES); + if (!gradlePropertiesFile.exists()) { + throw new RuntimeException("No gradle.properties to update version in"); + } + System.out.printf("Updating the project version in %s from %s to %s%n", + Project.GRADLE_PROPERTIES, currentVersion, newVersion); + FileUtils.replaceFileText(gradlePropertiesFile, (gradlePropertiesText) -> { + gradlePropertiesText = gradlePropertiesText.replace( + "version=" + currentVersion, "version=" + newVersion); + return gradlePropertiesText; + }); + } +} diff --git a/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateToReleaseVersionTask.java b/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateToReleaseVersionTask.java new file mode 100644 index 00000000..6e897182 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateToReleaseVersionTask.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019-2022 the original author or authors. + * + * Licensed 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. + */ + +package org.springframework.pulsar.gradle.versions; + +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.TaskAction; + +public abstract class UpdateToReleaseVersionTask extends UpdateProjectVersionTask { + + @Input + private String releaseVersion; + + @TaskAction + public void updateToReleaseVersion() { + updateVersionInGradleProperties(this.releaseVersion); + } + + public String getReleaseVersion() { + return releaseVersion; + } + + public void setReleaseVersion(String releaseVersion) { + this.releaseVersion = releaseVersion; + } +} diff --git a/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateToSnapshotVersionTask.java b/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateToSnapshotVersionTask.java new file mode 100644 index 00000000..4bf132d6 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/pulsar/gradle/versions/UpdateToSnapshotVersionTask.java @@ -0,0 +1,55 @@ +/* + * Copyright 2019-2022 the original author or authors. + * + * Licensed 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. + */ + +package org.springframework.pulsar.gradle.versions; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.gradle.api.tasks.TaskAction; + +public abstract class UpdateToSnapshotVersionTask extends UpdateProjectVersionTask { + + private static final String RELEASE_VERSION_PATTERN = "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-M\\d+|-RC\\d+)?$"; + + @TaskAction + public void updateToSnapshotVersion() { + String currentVersion = getProject().getVersion().toString(); + updateVersionInGradleProperties(calculateNextSnapshotVersion(currentVersion)); + } + + private String calculateNextSnapshotVersion(String currentVersion) { + Pattern releaseVersionPattern = Pattern.compile(RELEASE_VERSION_PATTERN); + Matcher releaseVersion = releaseVersionPattern.matcher(currentVersion); + + if (releaseVersion.find()) { + String majorSegment = releaseVersion.group(1); + String minorSegment = releaseVersion.group(2); + String patchSegment = releaseVersion.group(3); + String modifier = releaseVersion.group(4); + if (modifier == null) { + patchSegment = String.valueOf(Integer.parseInt(patchSegment) + 1); + } + System.out.println("modifier = " + modifier); + return String.format("%s.%s.%s-SNAPSHOT", majorSegment, minorSegment, patchSegment); + } + else { + throw new IllegalStateException( + "Cannot calculate next snapshot version because the current project version does not conform to the expected format"); + } + } + +}