[AETHER-602] CI job for the release of TOST artifacts

The pipeline updates the <version> tag according to the
given repo, and pushes two new Gerrit changes:

1) With version the given ${version} (e.g., 1.0.0)
2) With ${nextVersion}-SNAPSHOT (e.g., 1.1.0-SNAPSHOT)

Users must manually approve and merge these changes on Gerrit. Once merged,
it's up to the maven-publish and version-tag jobs to complete the release.

Change-Id: Id52797193912c2f72f6450c0c70108fda0065936
diff --git a/jjb/pipeline/artifact-release.groovy b/jjb/pipeline/artifact-release.groovy
new file mode 100644
index 0000000..e6c759a
--- /dev/null
+++ b/jjb/pipeline/artifact-release.groovy
@@ -0,0 +1,137 @@
+// Copyright 2020-present Open Networking Foundation
+//
+// 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
+//
+// http://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.
+
+def project = '${project}'
+def version = '${version}'
+def nextVersion = '${nextVersion}'
+def branch = '${branch}'
+def snapshot = '${nextVersion}-SNAPSHOT'
+
+// This pipeline updates the <version> tag according to the
+// given repo, and pushes two new Gerrit changes:
+//   1) With version the given ${version} (e.g., 1.0.0)
+//   2) With ${nextVersion}-SNAPSHOT (e.g., 1.1.0-SNAPSHOT)
+//
+// Users must manually approve and merge these changes on Gerrit. Once merged,
+// it's up to the maven-publish and version-tag jobs to complete the release by
+// uploading artifacts to Sonatype and creating Git tags.
+
+def changeVersion(def newVersion) {
+  /* Update the top-level <version> tag. */
+  sh( script: """
+     #!/usr/bin/env bash
+     set -eu -o pipefail
+
+     # Artifact with VERSION file
+     if [ -f "VERSION" ]
+     then
+        echo "${newVersion}" > VERSION
+     # Maven artifact
+     elif [ -f "pom.xml" ]
+     then
+        mvn versions:set -DnewVersion="${newVersion}" versions:commit
+     else
+        echo "ERROR: No versioning file found!"
+        exit 1
+     fi
+     """)
+}
+
+/* artifact-release pipeline */
+pipeline {
+
+  /* executor is determined by JJB */
+  agent {
+    label "${params.buildNode}"
+  }
+
+  stages {
+
+    /* clone the artifact and install the commit hook */
+    stage('Checkout') {
+      steps {
+        sshagent (credentials: ['onos-jenkins-ssh']) {
+          git branch: branch, url: "ssh://jenkins@gerrit.onosproject.org:29418/${params.project}", credentialsId: 'onos-jenkins-ssh'
+          sh 'gitdir=$(git rev-parse --git-dir); scp -p -P 29418 jenkins@gerrit.onosproject.org:hooks/commit-msg ${gitdir}/hooks/'
+        }
+      }
+    }
+
+    /* configure the repository */
+    stage('Configure') {
+      steps {
+        sh 'echo Releasing ' + project + ' repository on ' + branch + ' branch'
+        sh 'echo Releasing version ' + version + ' and starting ' + nextVersion + '-SNAPSHOT'
+        sh 'git config --global user.name "Jenkins"'
+        sh 'git config --global user.email "jenkins@onlab.us"'
+      }
+    }
+
+    /* release commit */
+    stage ('Move to release version') {
+      steps {
+        changeVersion(version)
+        sh 'git add -A && git commit -m "Release version ' + version + '"'
+      }
+    }
+
+    /* verify step */
+    stage ('Verify code') {
+      steps {
+        script {
+          found = sh(script:"egrep -R SNAPSHOT . --exclude=$egrepExclude || true", returnStdout: true).trim()
+        }
+        sh( script: """
+           #!/usr/bin/env bash
+           set -eu -o pipefail
+           if [ -n "$found" ]; then
+              echo "Found references to SNAPSHOT in the code. Are you sure you want to release?"
+              echo "$found"
+              exit 1
+           fi
+          """)
+      }
+    }
+
+    /* push to gerrit the release/tag commit */
+    stage ('Push to Gerrit') {
+      steps {
+        sshagent (credentials: ['onos-jenkins-ssh']) {
+          sh 'git push origin HEAD:refs/for/' + branch
+        }
+      }
+    }
+
+    /* snapshot commit */
+    stage ('Move to next SNAPSHOT version') {
+      steps {
+        changeVersion(snapshot)
+        sh 'git add -A && git commit -m "Starting snapshot ' + snapshot + '"'
+        sshagent (credentials: ['onos-jenkins-ssh']) {
+          sh 'git push origin HEAD:refs/for/' + branch
+        }
+      }
+    }
+
+    /* finish step */
+    stage ('Finish') {
+      steps {
+        sh 'echo "Release done!"'
+        sh 'echo "Go to Gerrit and merge new changes"'
+        sh 'echo "Go to http://oss.sonatype.org and release the artifacts (after the maven-publish job completes)"'
+      }
+    }
+  }
+
+}
diff --git a/jjb/repos/tost-onos.yaml b/jjb/repos/tost-onos.yaml
index b581054..802309c 100644
--- a/jjb/repos/tost-onos.yaml
+++ b/jjb/repos/tost-onos.yaml
@@ -12,6 +12,9 @@
       - 'publish-tost-onos-jobs':
           branch-regexp: '{supported-branches-regexp}'
 
+      - 'release-tost-onos-jobs':
+          branch-regexp: '{supported-branches-regexp}'
+
 - job-group:
     name: 'verify-tost-onos-jobs'
 
@@ -34,3 +37,8 @@
           maintainers: 'charles@opennetworking.org, pier@opennetworking.org'
           build-timeout: 30
           dependency-jobs: 'version-tag'
+
+- job-group:
+    name: 'release-tost-onos-jobs'
+    jobs:
+      - 'artifact-release'
\ No newline at end of file
diff --git a/jjb/templates/artifact-release.yml b/jjb/templates/artifact-release.yml
new file mode 100644
index 0000000..2cff260
--- /dev/null
+++ b/jjb/templates/artifact-release.yml
@@ -0,0 +1,57 @@
+---
+# Release artifcats using different means
+
+- job-template:
+    id: artifact-release
+    name: 'artifact-release_{project}'
+    description: |
+      <!-- Managed by Jenkins Job Builder -->
+      Created by {id} job-template from ci-management/jjb/artifact-release.yaml
+
+    properties:
+      - onf-infra-properties:
+          build-days-to-keep: '{build-days-to-keep}'
+          artifact-num-to-keep: '{artifact-num-to-keep}'
+
+    wrappers:
+      - lf-infra-wrappers:
+          build-timeout: '{build-timeout}'
+          jenkins-ssh-credential: '{jenkins-ssh-credential}'
+
+    parameters:
+      - string:
+          name: buildNode
+          default: '{build-node}'
+          description: 'Name of the Jenkins build executor to run the job on'
+
+      - string:
+          name: project
+          default: ''
+          description: 'Name of the repository on the ONOS Gerrit server.\n e.g. trellis-control'
+
+      - string:
+          name: version
+          default: ''
+          description: 'Version to release.\n e.g. 1.0.0'
+
+      - string:
+          name: nextVersion
+          default: ''
+          description: 'Snapshot version to move the code forward to.\n e.g. 1.1.0'
+
+      - string:
+          name: branch
+          default: 'master'
+          description: 'Name of the branch to release on.'
+
+      - string:
+          name: egrepExclude
+          default: ''
+          description: 'Exclude pattern for egrep (e.g. Makefile.vars,VERSION).'
+
+
+    project-type: pipeline
+    concurrent: true
+
+    dsl: !include-raw-escape: ../pipeline/artifact-release.groovy
+