From 4c67b43fe75255c1d8163bb8dedfccc3c7d61fe3 Mon Sep 17 00:00:00 2001 From: Greg Turnquist Date: Tue, 27 Nov 2018 11:04:47 -0600 Subject: [PATCH] Automated release process * Scriptify rolling the version numbers. * Delegate building release versions on the CI server. * Add ability to promot to bintray. * Add ability to sync to maven central. * Add ability to promote to bintray --- README.adoc | 36 ++++++-- ci/README.adoc | 12 +-- ci/create-release-2.0.x.sh | 25 ++++++ ci/create-release.sh | 25 ++++++ ci/pipeline-template.yml | 162 ++++++++++++++++++++++++++++++++++- ci/promote-to-bintray.sh | 46 ++++++++++ ci/promote-to-bintray.yml | 19 ++++ ci/sync-to-maven-central.sh | 24 ++++++ ci/sync-to-maven-central.yml | 21 +++++ 9 files changed, 351 insertions(+), 19 deletions(-) create mode 100755 ci/create-release-2.0.x.sh create mode 100755 ci/create-release.sh create mode 100755 ci/promote-to-bintray.sh create mode 100644 ci/promote-to-bintray.yml create mode 100755 ci/sync-to-maven-central.sh create mode 100644 ci/sync-to-maven-central.yml diff --git a/README.adoc b/README.adoc index 0f2a6ef..00be2b6 100644 --- a/README.adoc +++ b/README.adoc @@ -74,17 +74,35 @@ You can also import the project into your IDE. To do a release (.RELEASE, .RC?, .M?): . Check in all changes and ensure there are no edited files. -. Bump up the version in `pom.xml` to the desired version and commit the change. -. `git tag ` (like v2.0.1.RELEASE) -. Execute a maven deploy. -* For a milestone: `USERNAME= PASSWORD= mvn -Pdistribute,milestone,docs clean deploy` -* For a release: `USERNAME= PASSWORD= mvn -Pdistribute,release,docs clean deploy` -* For a release to maven central: `USERNAME= PASSWORD= mvn -Pdistribute,gpg,central clean deploy -s settings.xml` (At SonaType, *close* and *releases*) -. Bump up the version in `pom.xml` again to the next BUILD-SNAPSHOT. -. Commit the change. +. Run `ci/create-release-2.0.x.sh ` e.g. (`ci/create-release-2.0.x.sh 2.1.1.RELEASE 2.1.2.BUILD-SNAPSHOT`) + +From here, test things out locally. + +. `git checkout release-2.0.x` +. `./mvnw clean package` +. ...do all your testing... + +Once verified, push the `release-2.0.x` branch to `origin` and let the CI server deploy it. + +. `git push` + +After a clean release, switch back to 2.0.x branch and push it. + +. `git checkout 2.0.x` . `git push` . `git push --tags` -. Inspect handiwork at https://repo.spring.io/ or https://oss.sonatype.org/#stagingRepositories + +//To deploy your changes: +// +//. `git checkout release` +//. Execute a maven deploy. +//* For a milestone: `USERNAME= PASSWORD= ./mvnw -Pdistribute,milestone,docs clean deploy` +//* For a release: `USERNAME= PASSWORD= ./mvnw -Pdistribute,release,docs clean deploy` +//* For a release to maven central: `USERNAME= PASSWORD= ./mvnw -Pdistribute,gpg,central clean deploy -s settings.xml` (At SonaType, *close* and *releases*) +//. Inspect handiwork at https://repo.spring.io/ or https://oss.sonatype.org/#stagingRepositories + + +CI server should build the new snapshot and automatically deploy to artifactory. NOTE: A word about reference documentation. Based upon https://github.com/spring-projects/spring-framework/wiki/gradle-build-and-release-faq#user-content-wiki-docs_schema_dist_publication[this], the `distribute` profile contains an artifactory property that is applied to the ZIP file generated by the `docs` profile. A CRON job will scoop up the zipped up docs and unpack them inside the target location. diff --git a/ci/README.adoc b/ci/README.adoc index cdcf4a7..a26b414 100644 --- a/ci/README.adoc +++ b/ci/README.adoc @@ -28,8 +28,8 @@ WARNING: Do NOT check this file into source control! If you'll check, `credentia With this in place, run the following `fly` commands to create pipelines: ---- -% fly -t sp -p spring-session-data-mongodb -c ci/pipeline-template.yml -l credentials.yml -v branch=master -% fly -t sp -p spring-session-data-mongodb-2.0.x -c ci/pipeline-template.yml -l credentials.yml -v branch=2.0.x +% fly -t spring-team sp -p spring-session-data-mongodb -c ci/pipeline-template.yml -l credentials.yml -v branch=master -v release-branch=release +% fly -t spring-team sp -p spring-session-data-mongodb-2.0.x -c ci/pipeline-template.yml -l credentials.yml -v branch=2.0.x -v release-branch=release-2.0.x ---- This creates pipelines for: @@ -40,8 +40,8 @@ This creates pipelines for: With these pipelines in place, you can now activate and expose them: ---- -% fly -t unpause-pipeline -p spring-session-data-mongodb -% fly -t expose-pipeline -p spring-session-data-mongodb -% fly -t unpause-pipeline -p spring-session-data-mongodb-2.0.x -% fly -t expose-pipeline -p spring-session-data-mongodb-2.x +% fly -t spring-team unpause-pipeline -p spring-session-data-mongodb +% fly -t spring-team expose-pipeline -p spring-session-data-mongodb +% fly -t spring-team unpause-pipeline -p spring-session-data-mongodb-2.0.x +% fly -t spring-team expose-pipeline -p spring-session-data-mongodb-2.x ---- \ No newline at end of file diff --git a/ci/create-release-2.0.x.sh b/ci/create-release-2.0.x.sh new file mode 100755 index 0000000..d3eac35 --- /dev/null +++ b/ci/create-release-2.0.x.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +set -euo pipefail + +RELEASE=$1 +SNAPSHOT=$2 + +git branch -f release-2.0.x +git checkout release-2.0.x + +# Bump up the version in pom.xml to the desired version and commit the change +./mvnw versions:set -DnewVersion=$RELEASE -DgenerateBackupPoms=false +git add . +git commit --message "Releasing Spring Session MongoDB v$RELEASE" + +# Tag the release +git tag -s v$RELEASE -m "v$RELEASE" + +# Bump up the version in pom.xml to the next snapshot +git checkout 2.0.x +./mvnw versions:set -DnewVersion=$SNAPSHOT -DgenerateBackupPoms=false +git add . +git commit --message "Continue development on v$SNAPSHOT" + + diff --git a/ci/create-release.sh b/ci/create-release.sh new file mode 100755 index 0000000..1aa456b --- /dev/null +++ b/ci/create-release.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +set -euo pipefail + +RELEASE=$1 +SNAPSHOT=$2 + +git branch -f release +git checkout release + +# Bump up the version in pom.xml to the desired version and commit the change +./mvnw versions:set -DnewVersion=$RELEASE -DgenerateBackupPoms=false +git add . +git commit --message "Releasing Spring Session MongoDB v$RELEASE" + +# Tag the release +git tag -s v$RELEASE -m "v$RELEASE" + +# Bump up the version in pom.xml to the next snapshot +git checkout master +./mvnw versions:set -DnewVersion=$SNAPSHOT -DgenerateBackupPoms=false +git add . +git commit --message "Continue development on v$SNAPSHOT" + + diff --git a/ci/pipeline-template.yml b/ci/pipeline-template.yml index 9fe468b..f347b5c 100644 --- a/ci/pipeline-template.yml +++ b/ci/pipeline-template.yml @@ -4,7 +4,7 @@ resource_types: type: docker-image source: repository: springio/artifactory-resource - tag: 0.0.4 + tag: 0.0.6 - name: github-status type: docker-image @@ -48,7 +48,7 @@ resources: uri: https://repo.spring.io username: ((artifactory-username)) password: ((artifactory-password)) - build_name: Spring Session for MongoDB + build_name: spring-session-data-mongodb - name: spring-session-data-mongodb-pull-requests type: pull-request @@ -57,6 +57,12 @@ resources: repo: spring-projects/spring-session-data-mongodb base: ((branch)) +- name: spring-session-data-mongodb-release + type: git + source: + uri: https://github.com/spring-projects/spring-session-data-mongodb.git + branch: ((release-branch)) + - name: spring-session-data-mongodb-status type: github-status source: @@ -84,6 +90,11 @@ groups: - name: pull-requests jobs: - spring-session-data-mongodb-pull-requests +- name: release + jobs: + - release-to-artifactory + - promote-to-bintray + - sync-to-maven-central jobs: - name: Test - JDK 8 @@ -445,7 +456,7 @@ jobs: attachments: - color: danger fallback: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME " - text: "Build has failed" + text: "Pull request has failed" title: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME" title_link: $ATC_EXTERNAL_URL/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME on_success: @@ -459,6 +470,149 @@ jobs: attachments: - color: good fallback: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME " - text: "Build has succeeded!" + text: "Pull request has succeeded!" + title: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME" + title_link: $ATC_EXTERNAL_URL/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME + +- name: release-to-artifactory + serial: true + public: true + plan: + - get: spring-session-data-mongodb-github + resource: spring-session-data-mongodb-release + trigger: true + - put: spring-session-data-mongodb-status + params: + commit: spring-session-data-mongodb-github + state: pending + - task: build + file: spring-session-data-mongodb-github/ci/build.yml + - put: spring-session-data-mongodb-artifactory + params: + build_number: ${BUILD_NAME} + build_uri: ${ATC_EXTERNAL_URL}/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME} + repo: libs-release-local + folder: spring-session-data-mongodb-artifactory + artifact_set: + - include: + - "/**" + properties: + archives: '*:*:*:*@zip zip.name:spring-session-data-mongodb, zip.displayname:Spring Session Data MongoDB, zip.deployed:false' + on_failure: + aggregate: + - put: spring-session-data-mongodb-status + params: + commit: spring-session-data-mongodb-github + state: failure + - put: slack + params: + attachments: + - color: danger + fallback: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME " + text: "Releasing to artifactory has failed" + title: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME" + title_link: $ATC_EXTERNAL_URL/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME + on_success: + aggregate: + - put: spring-session-data-mongodb-status + params: + commit: spring-session-data-mongodb-github + state: success + - put: slack + params: + attachments: + - color: good + fallback: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME " + text: "Releasing to artifactory has succeeded!" + title: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME" + title_link: $ATC_EXTERNAL_URL/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME + +- name: promote-to-bintray + serial: true + plan: + - get: spring-session-data-mongodb-github + - get: spring-session-data-mongodb-artifactory + trigger: true + passed: [release-to-artifactory] + params: + save_build_info: true + - task: promote-to-bintray + file: spring-session-data-mongodb-github/ci/promote-to-bintray.yml + params: + ARTIFACTORY_USERNAME: ((artifactory-username)) + ARTIFACTORY_PASSWORD: ((artifactory-password)) + on_failure: + aggregate: + - put: spring-session-data-mongodb-status + params: + commit: spring-session-data-mongodb-github + state: failure + - put: slack + params: + attachments: + - color: danger + fallback: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME " + text: "Promoting to bintray has failed" + title: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME" + title_link: $ATC_EXTERNAL_URL/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME + on_success: + aggregate: + - put: spring-session-data-mongodb-status + params: + commit: spring-session-data-mongodb-github + state: success + - put: slack + params: + attachments: + - color: good + fallback: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME " + text: "Promoting to bintray has succeeded!" + title: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME" + title_link: $ATC_EXTERNAL_URL/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME + +- name: sync-to-maven-central + serial: true + plan: + - get: spring-session-data-mongodb-github + - get: spring-session-data-mongodb-artifactory + trigger: true + passed: [promote-to-bintray] + params: + save_build_info: true + - task: sync-to-maven-central + file: spring-session-data-mongodb-github/ci/sync-to-maven-central.yml + params: + BINTRAY_USERNAME: ((bintray-username)) + BINTRAY_API_KEY: ((bintray-api-key)) + SONATYPE_USER_TOKEN: ((sonatype-user-token)) + SONATYPE_PASSWORD_TOKEN: ((sonatype-user-token-password)) + ARTIFACTORY_USERNAME: ((artifactory-username)) + ARTIFACTORY_PASSWORD: ((artifactory-password)) + on_failure: + aggregate: + - put: spring-session-data-mongodb-status + params: + commit: spring-session-data-mongodb-github + state: failure + - put: slack + params: + attachments: + - color: danger + fallback: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME " + text: "Syncing to maven central has failed" + title: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME" + title_link: $ATC_EXTERNAL_URL/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME + on_success: + aggregate: + - put: spring-session-data-mongodb-status + params: + commit: spring-session-data-mongodb-github + state: success + - put: slack + params: + attachments: + - color: good + fallback: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME " + text: "Syncing to maven central has succeeded!" title: "$BUILD_PIPELINE_NAME/$BUILD_JOB_NAME #$BUILD_NAME" title_link: $ATC_EXTERNAL_URL/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME diff --git a/ci/promote-to-bintray.sh b/ci/promote-to-bintray.sh new file mode 100755 index 0000000..82f8862 --- /dev/null +++ b/ci/promote-to-bintray.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +set -e -u + +apt-get update +apt-get install -y jq + +buildName=$( cat spring-session-data-mongodb-artifactory/build-info.json | jq -r '.buildInfo.name' ) +buildNumber=$( cat spring-session-data-mongodb-artifactory/build-info.json | jq -r '.buildInfo.number' ) +groupId=$( cat spring-session-data-mongodb-artifactory/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/\(.*\):.*:.*/\1/' ) +version=$( cat spring-session-data-mongodb-artifactory/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' ) +targetRepo="libs-release-local" + +echo "Promoting ${buildName}/${buildNumber} to ${targetRepo}" + +curl \ + -s \ + --connect-timeout 240 \ + --max-time 2700 \ + -u ${ARTIFACTORY_USERNAME}:${ARTIFACTORY_PASSWORD} \ + -H "Content-type:application/json" \ + -d "{\"sourceRepos\": [\"libs-release-local\"], \"targetRepo\" : \"spring-distributions\", \"async\":\"true\"}" \ + -f \ + -X \ + POST "https://repo.spring.io/api/build/distribute/${buildName}/${buildNumber}" > /dev/null || { echo "Failed to distribute" >&2; exit 1; } + +echo "Waiting for artifacts to be published" + +ARTIFACTS_PUBLISHED=false +WAIT_TIME=10 +COUNTER=0 + +while [ $ARTIFACTS_PUBLISHED == "false" ] && [ $COUNTER -lt 120 ]; do + + result=$( curl -s https://api.bintray.com/packages/spring/jars/"${groupId}" ) + versions=$( echo "$result" | jq -r '.versions' ) + exists=$( echo "$versions" | grep "$version" -o || true ) + + if [ "$exists" = "$version" ]; then + ARTIFACTS_PUBLISHED=true + fi + + COUNTER=$(( COUNTER + 1 )) + sleep $WAIT_TIME + +done diff --git a/ci/promote-to-bintray.yml b/ci/promote-to-bintray.yml new file mode 100644 index 0000000..5420db5 --- /dev/null +++ b/ci/promote-to-bintray.yml @@ -0,0 +1,19 @@ +--- +platform: linux + +image_resource: + type: docker-image + source: + repository: openjdk + tag: 8-jdk + +inputs: +- name: spring-session-data-mongodb-artifactory +- name: spring-session-data-mongodb-github + +run: + path: spring-session-data-mongodb-github/ci/promote-to-bintray.sh + +params: + ARTIFACTORY_USERNAME: + ARTIFACTORY_PASSWORD: diff --git a/ci/sync-to-maven-central.sh b/ci/sync-to-maven-central.sh new file mode 100755 index 0000000..461ea05 --- /dev/null +++ b/ci/sync-to-maven-central.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +set -e -u + +apt-get update +apt-get install -y jq + +buildName=$( cat spring-session-data-mongodb-artifactory/build-info.json | jq -r '.buildInfo.name' ) +buildNumber=$( cat spring-session-data-mongodb-artifactory/build-info.json | jq -r '.buildInfo.number' ) +groupId=$( cat spring-session-data-mongodb-artifactory/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/\(.*\):.*:.*/\1/' ) +version=$( cat spring-session-data-mongodb-artifactory/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' ) + +echo "Syncing ${buildName}/${buildNumber} to Maven Central" + curl \ + -s \ + --connect-timeout 240 \ + --max-time 2700 \ + -u ${BINTRAY_USERNAME}:${BINTRAY_API_KEY} \ + -H "Content-Type: application/json" -d "{ \"username\": \"${SONATYPE_USER_TOKEN}\", \"password\": \"${SONATYPE_PASSWORD_TOKEN}\"}" \ + -f \ + -X \ + POST "https://api.bintray.com/maven_central_sync/spring/jars/${groupId}/versions/${version}" > /dev/null || { echo "Failed to sync" >&2; exit 1; } + +echo "Sync complete" diff --git a/ci/sync-to-maven-central.yml b/ci/sync-to-maven-central.yml new file mode 100644 index 0000000..76cd449 --- /dev/null +++ b/ci/sync-to-maven-central.yml @@ -0,0 +1,21 @@ +--- +platform: linux + +image_resource: + type: docker-image + source: + repository: openjdk + tag: 8-jdk + +inputs: +- name: spring-session-data-mongodb-artifactory +- name: spring-session-data-mongodb-github + +run: + path: spring-session-data-mongodb-github/ci/sync-to-maven-central.sh + +params: + BINTRAY_USERNAME: + BINTRAY_API_KEY: + SONATYPE_USER_TOKEN: + SONATYPE_PASSWORD_TOKEN: