Release job for JAXB Spec and API (#105)
Signed-off-by: Tomas Kraus <Tomas.Kraus@oracle.com>
diff --git a/etc/jenkins/release.groovy b/etc/jenkins/release.groovy
new file mode 100644
index 0000000..31b47da
--- /dev/null
+++ b/etc/jenkins/release.groovy
@@ -0,0 +1,80 @@
+// Job input parameters:
+// SPEC_VERSION - Specification version to release
+// NEXT_SPEC_VERSION - Next specification snapshot version to set (e.g. 1.2.4-SNAPSHOT)
+// API_VERSION - API version to release
+// NEXT_API_VERSION - Next API snapshot version to set (e.g. 1.2.4-SNAPSHOT)
+// BRANCH - Branch to release
+// DRY_RUN - Do not publish artifacts to OSSRH and code changes to GitHub
+// OVERWRITE - Allows to overwrite existing version in git and OSSRH staging repositories
+
+// Job internal argumets:
+// GIT_USER_NAME - Git user name (for commits)
+// GIT_USER_EMAIL - Git user e-mail (for commits)
+// SSH_CREDENTIALS_ID - Jenkins ID of SSH credentials
+// GPG_CREDENTIALS_ID - Jenkins ID of GPG credentials (stored as KEYRING variable)
+// SETTINGS_XML_ID - Jenkins ID of settings.xml file
+// SETTINGS_SEC_XML_ID - Jenkins ID of settings-security.xml file
+
+pipeline {
+
+ agent any
+
+ tools {
+ jdk 'openjdk-jdk11-latest'
+ maven 'apache-maven-latest'
+ }
+
+ environment {
+ SPEC_DIR="${WORKSPACE}/spec"
+ API_DIR="${WORKSPACE}"
+ }
+
+ stages {
+ // Initialize build environment
+ stage('Init') {
+ steps {
+ git branch: BRANCH, credentialsId: SSH_CREDENTIALS_ID, url: GIT_URL
+ // GPG initialization
+ withCredentials([file(credentialsId: GPG_CREDENTIALS_ID, variable: 'KEYRING')]) {
+ sh '''
+ gpg --batch --import ${KEYRING}
+ for fpr in $(gpg --list-keys --with-colons | awk -F: '/fpr:/ {print $10}' | sort -u);
+ do
+ echo -e "5\ny\n" | gpg --batch --command-fd 0 --expert --edit-key $fpr trust;
+ done
+
+ '''
+ }
+ // Git configuration
+ sh '''
+ git config --global user.name "${GIT_USER_NAME}"
+ git config --global user.email "${GIT_USER_EMAIL}"
+ '''
+ }
+ }
+ // Perform release
+ stage('Release') {
+ steps {
+ configFileProvider([
+ configFile(
+ fileId: SETTINGS_XML_ID,
+ targetLocation: '/home/jenkins/.m2/settings.xml'
+ ),
+ configFile(
+ fileId: SETTINGS_SEC_XML_ID,
+ targetLocation: '/home/jenkins/.m2/'
+ )]) {
+ sshagent([SSH_CREDENTIALS_ID]) {
+ sh '''
+ etc/jenkins/release.sh "${SPEC_VERSION}" "${NEXT_SPEC_VERSION}" \
+ "${API_VERSION}" "${NEXT_API_VERSION}" \
+ "${DRY_RUN}" "${OVERWRITE}"
+ '''
+ }
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/etc/jenkins/release.sh b/etc/jenkins/release.sh
new file mode 100755
index 0000000..f0592c1
--- /dev/null
+++ b/etc/jenkins/release.sh
@@ -0,0 +1,119 @@
+#!/bin/bash -ex
+#
+# Arguments:
+# $1 - SPEC_VERSION
+# $2 - NEXT_SPEC_VERSION
+# $3 - API_VERSION
+# $4 - NEXT_API_VERSION
+# $5 - DRY_RUN
+# $6 - OVERWRITE
+
+SPEC_VERSION="${1}"
+NEXT_SPEC_VERSION="${2}"
+API_VERSION="${3}"
+NEXT_API_VERSION="${4}"
+DRY_RUN="${5}"
+OVERWRITE="${6}"
+
+. etc/scripts/mvn.sh
+. etc/scripts/nexus.sh
+
+read_version 'SPEC' "${SPEC_DIR}"
+read_version 'API' "${API_DIR}"
+
+if [ -z "${API_RELEASE_VERSION}" ]; then
+ echo '-[ Missing required API release version number! ]-------------------------------'
+ exit 1
+fi
+if [ -z "${SPEC_RELEASE_VERSION}" ]; then
+ echo '-[ Missing required specification release version number! ]---------------------'
+ exit 1
+fi
+
+RELEASE_TAG="SPEC-${SPEC_RELEASE_VERSION}_API-${API_RELEASE_VERSION}"
+RELEASE_BRANCH="SPEC-${SPEC_RELEASE_VERSION}_API-${API_RELEASE_VERSION}_RELEASE"
+
+if [ ${DRY_RUN} = 'true' ]; then
+ echo '-[ Dry run turned on ]----------------------------------------------------------'
+ MVN_DEPLOY_ARGS='install'
+ echo '-[ Skipping GitHub branch and tag checks ]--------------------------------------'
+else
+ MVN_DEPLOY_ARGS='deploy'
+ GIT_ORIGIN=`git remote`
+ echo '-[ Prepare branch ]-------------------------------------------------------------'
+ if [[ -n `git branch -r | grep "${GIT_ORIGIN}/${RELEASE_BRANCH}"` ]]; then
+ if [ "${OVERWRITE}" = 'true' ]; then
+ echo "${GIT_ORIGIN}/${RELEASE_BRANCH} branch already exists, deleting"
+ git push --delete origin "${RELEASE_BRANCH}" && true
+ else
+ echo "Error: ${GIT_ORIGIN}/${RELEASE_BRANCH} branch already exists"
+ exit 1
+ fi
+ fi
+ echo '-[ Release tag cleanup ]--------------------------------------------------------'
+ if [[ -n `git ls-remote --tags ${GIT_ORIGIN} | grep "${RELEASE_TAG}"` ]]; then
+ if [ "${OVERWRITE}" = 'true' ]; then
+ echo "${RELEASE_TAG} tag already exists, deleting"
+ git push --delete origin "${RELEASE_TAG}" && true
+ else
+ echo "Error: ${RELEASE_TAG} tag already exists"
+ exit 1
+ fi
+ fi
+fi
+
+# Always delete local branch if exists
+git branch --delete "${RELEASE_BRANCH}" && true
+git checkout -b ${RELEASE_BRANCH}
+
+# Always delete local tag if exists
+git tag --delete "${RELEASE_TAG}" && true
+
+# Read Maven identifiers
+read_mvn_id 'SPEC' "${SPEC_DIR}"
+read_mvn_id 'API' "${API_DIR}/jaxb-api"
+
+# Set Nexus identifiers
+SPEC_STAGING_DESC="${SPEC_GROUP_ID}:${SPEC_ARTIFACT_ID}:${SPEC_RELEASE_VERSION}"
+SPEC_STAGING_KEY=$(echo ${SPEC_STAGING_DESC} | sed -e 's/\./\\\./g')
+API_STAGING_DESC="${API_GROUP_ID}:${API_ARTIFACT_ID}:${API_RELEASE_VERSION}"
+API_STAGING_KEY=$(echo ${API_STAGING_DESC} | sed -e 's/\./\\\./g')
+
+# Set release versions
+echo '-[ SPEC release version ]-------------------------------------------------------'
+set_version 'SPEC' "${SPEC_DIR}" "${SPEC_RELEASE_VERSION}" "${SPEC_GROUP_ID}" "${SPEC_ARTIFACT_ID}" ''
+echo '-[ API release version ]--------------------------------------------------------'
+set_version 'API' "${API_DIR}" "${API_RELEASE_VERSION}" "${API_GROUP_ID}" "${API_ARTIFACT_ID}" ''
+
+drop_artifacts "${SPEC_STAGING_KEY}" "${SPEC_DIR}"
+drop_artifacts "${API_STAGING_KEY}" "${API_DIR}"
+
+echo '-[ Deploy artifacts to staging repository ]-----------------------------'
+# Verify, sign and deploy release
+(cd ${SPEC_DIR} && \
+ mvn -U -C \
+ -Poss-release,staging -DskipTests \
+ -DstagingDescription="${SPEC_STAGING_DESC}" \
+ clean ${MVN_DEPLOY_ARGS})
+(cd ${API_DIR} && \
+ mvn -U -C \
+ -Poss-release,staging -DskipTests \
+ -DstagingDescription="${API_STAGING_DESC}" \
+ clean ${MVN_DEPLOY_ARGS})
+
+echo '-[ Tag release ]----------------------------------------------------------------'
+git tag "${RELEASE_TAG}" -m "JSON-B Specification and API release"
+
+# Set next release cycle snapshot version
+echo '-[ SPEC next snapshot version ]-------------------------------------------------'
+set_version 'SPEC' "${SPEC_DIR}" "${SPEC_NEXT_SNAPSHOT}" "${SPEC_GROUP_ID}" "${SPEC_ARTIFACT_ID}" ''
+echo '-[ API next snapshot version ]--------------------------------------------------'
+set_version 'API' "${API_DIR}" "${API_NEXT_SNAPSHOT}" "${API_GROUP_ID}" "${API_ARTIFACT_ID}" ''
+
+if [ ${DRY_RUN} = 'true' ]; then
+ echo '-[ Skipping GitHub update ]-----------------------------------------------------'
+else
+ echo '-[ Push branch and tag to GitHub ]----------------------------------------------'
+ git push origin "${RELEASE_BRANCH}"
+ git push origin "${RELEASE_TAG}"
+fi
diff --git a/etc/scripts/mvn.sh b/etc/scripts/mvn.sh
new file mode 100644
index 0000000..47a3ab2
--- /dev/null
+++ b/etc/scripts/mvn.sh
@@ -0,0 +1,87 @@
+# Maven plugins
+VERSIONS_PLUGIN='org.codehaus.mojo:versions-maven-plugin:2.7'
+HELP_PLUGIN='org.apache.maven.plugins:maven-help-plugin:3.2.0'
+
+# Compute version strings for next development cycle.
+# Version strings are set as new shell variables with provided prefix.
+# Arguments:
+# $1 - Variable prefix
+# $2 - Source version
+# Variables set:
+# "${1}_NEXT_VERSION" - Next version string: Source string with last component increased by 1
+# "${1}_NEXT_SNAPSHOT" - Next snapshot string: Next version string with '-SNAPSHOT' suffix
+next_version() {
+ set -f
+ local NEXT_COMPONENTS=(${2//\./ })
+ local LAST_INDEX=$((${#NEXT_COMPONENTS[@]} - 1))
+ local NEXT_COMPONENTS[${LAST_INDEX}]=$((${NEXT_COMPONENTS[${LAST_INDEX}]} + 1))
+ local COMPONENTS_STR="${NEXT_COMPONENTS[@]}"
+ local NEXT_VERSION="${COMPONENTS_STR// /.}"
+ local NEXT_SNAPSHOT="${NEXT_VERSION}-SNAPSHOT"
+ echo "${1} Next Version: ${NEXT_VERSION}"
+ echo "${1} Next Snapshot: ${NEXT_SNAPSHOT}"
+ eval "${1}_NEXT_VERSION"="${NEXT_VERSION}"
+ eval "${1}_NEXT_SNAPSHOT"="${NEXT_SNAPSHOT}"
+}
+
+# Prepare release version string and next development cycle versions.
+# Version strings are set as new shell variables with provided prefix.
+# Arguments:
+# $1 - Variable prefix
+# $2 - Build directory
+# Source variables:
+# "${1}_VERSION" - Release version override (optional)
+# Variables set:
+# "${1}_RELEASE_VERSION" - Release version
+read_version() {
+ local VERSION_VAR="${1}_VERSION"
+ local SNAPSHOT_VERSION=`(cd ${2} && mvn -B ${HELP_PLUGIN}:evaluate -Dexpression=project.version 2> /dev/null | grep -E '^[0-9]+(\.[0-9]+)+-SNAPSHOT$')`
+ if [ -z "${!VERSION_VAR}" ]; then
+ local RELEASE_VERSION="${SNAPSHOT_VERSION/-SNAPSHOT/}"
+ else
+ local RELEASE_VERSION="${!VERSION_VAR}"
+ fi
+ echo "${1} Release Version: ${RELEASE_VERSION}"
+ eval "${1}_RELEASE_VERSION"="${RELEASE_VERSION}"
+ next_version "${1}" "${RELEASE_VERSION}"
+}
+
+# Read Maven identifier (groupId and artifactId).
+# Maven identifier is set as new shell variables with provided prefix.
+# Arguments:
+# $1 - Variable prefix
+# $2 - Build directory
+# Variables set:
+# "${1}_GROUP_ID" - Maven groupId
+# "${1}_ARTIFACT_ID" - Maven artifactId
+read_mvn_id() {
+ local GROUP_ID=`(cd ${2} && mvn -B ${HELP_PLUGIN}:evaluate -Dexpression=project.groupId | grep -Ev '(^\[)')`
+ local ARTIFACT_ID=`(cd ${2} && mvn -B ${HELP_PLUGIN}:evaluate -Dexpression=project.artifactId | grep -Ev '(^\[)')`
+ echo "${1} Group ID: ${GROUP_ID}"
+ echo "${1} Artifact ID: ${ARTIFACT_ID}"
+ eval "${1}_GROUP_ID"="${GROUP_ID}"
+ eval "${1}_ARTIFACT_ID"="${ARTIFACT_ID}"
+}
+
+# Set Maven artifact version.
+# Arguments:
+# $1 - Artifact identifier (e.g. 'SPEC', 'API', 'RI')
+# $2 - Build directory
+# $3 - Version to set
+# $4 - Group ID
+# $5 - Artifact ID
+# $6 - Additional Maven arguments
+set_version() {
+ echo '--[ Set version ]---------------------------------------------------------------'
+ # Set release version
+ (cd ${2} && \
+ mvn -U -C \
+ ${6} \
+ -DnewVersion="${3}" \
+ -DgenerateBackupPoms=false \
+ clean ${VERSIONS_PLUGIN}:set)
+ echo '--[ Commit modified pom.xml files ]---------------------------------------------'
+ local POM_FILES=`git status | grep -E 'modified:.*pom\.xml' | sed -e 's/[[:space:]][[:space:]]*modified:[[:space:]][[:space:]]*//'`
+ git add ${POM_FILES} && \
+ git commit -m "Update ${1} version of ${4}:${5} to ${3}"
+}
diff --git a/etc/scripts/nexus.sh b/etc/scripts/nexus.sh
new file mode 100644
index 0000000..f1e717d
--- /dev/null
+++ b/etc/scripts/nexus.sh
@@ -0,0 +1,14 @@
+# Drop old artifacts from staging repository
+# Arguments:
+# $1 - Staging key value with grep REGEX prefixes
+# $2 - Build directory
+drop_artifacts() {
+ echo '-[ Drop old staging repository deployments ]------------------------------------'
+ for staging_key in `(cd ${2} && mvn -B nexus-staging:rc-list | egrep "^\[INFO\] [A-Z,a-z,-]+-[0-9]+\s+[A-Z]+\s+${1}" | awk '{print $2}')`; do
+ echo "Repository ID: ${staging_key}"
+ (cd ${2} && \
+ mvn -U -C \
+ -DstagingRepositoryId="${staging_key}" \
+ nexus-staging:rc-drop)
+ done
+}