Adding script to close Nexus staging repo
Change-Id: Ibfcbb6b58159393493e1a4be58d2e2360810d0d6
diff --git a/tools/build/onos-buck-publish b/tools/build/onos-buck-publish
index 53af0e4..24ce932 100755
--- a/tools/build/onos-buck-publish
+++ b/tools/build/onos-buck-publish
@@ -36,4 +36,5 @@
cat $TEST_PUB
bash $TEST_PUB
-# FIXME Close the staging area
+# Close the staging area
+onos-close-staging
\ No newline at end of file
diff --git a/tools/build/onos-close-staging b/tools/build/onos-close-staging
new file mode 100755
index 0000000..e262db8
--- /dev/null
+++ b/tools/build/onos-close-staging
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+#
+# This script finds an open staging repository, checks that it contains an
+# expected artifact, attemps to close the repository, and checks that it is closed.
+#
+
+import sys
+import json
+import time
+import os
+import requests
+from requests.auth import HTTPBasicAuth
+
+USER = os.environ['SONATYPE_USER']
+PASSWORD = os.environ['SONATYPE_PASSWORD']
+BASE_URL = 'https://oss.sonatype.org/service/local/'
+GROUP_ID = 'org.onosproject'
+ARTIFACT = 'onos-api'
+VERSION = os.environ['ONOS_VERSION']
+MAX_TRIES = 3
+
+# Performs an HTTP GET up to MAX_TRIES times
+def get(url):
+ headers = { 'Accept': 'application/json' }
+ error = None
+ for i in range(MAX_TRIES):
+ resp = requests.get(url, auth=HTTPBasicAuth(USER, PASSWORD), headers=headers)
+ try:
+ resp.raise_for_status()
+ return resp
+ except requests.exceptions.HTTPError as e:
+ print 'Encountered error:', e
+ error = e
+ time.sleep(1)
+ if error:
+ raise error
+ return resp
+
+# Performs an HTTP POST with the specified data up to MAX_TRIES times
+def post(url, data):
+ headers = { 'Accept': 'application/xml', 'Content-type': 'application/xml' }
+ error = None
+ for i in range(MAX_TRIES):
+ resp = requests.post(url, data=data, auth=HTTPBasicAuth(USER, PASSWORD), headers=headers)
+ try:
+ resp.raise_for_status()
+ return resp
+ except requests.exceptions.HTTPError as e:
+ print 'Encountered error:', e
+ error = e
+ time.sleep(1)
+ if error:
+ raise error
+ return resp
+
+# Get the staging repos and filter the ones related to onos
+def getStagingRepo(groupId):
+ resp = get(BASE_URL + 'staging/profile_repositories')
+ data = resp.json()['data']
+
+ repos = []
+ for entry in data:
+ if entry['profileName'] == groupId and entry['type'] == 'open':
+ repos.append(( entry['repositoryId'], entry['profileId'] ))
+
+ if len(repos) > 1:
+ print 'Aborting... too many open staging repos'
+ print repos
+ sys.exit(1)
+ elif len(repos) == 0:
+ print 'Aborting... there are no open staging repos'
+ sys.exit(1)
+
+ return repos[0]
+
+# Check to make sure the open repo contains the onos-api artifact for the appropriate version
+def checkStagingRepo(respositoryId, artifact, groupId, version):
+ base = BASE_URL + 'repositories/%s/content/' % repositoryId
+ path = '%(groupId)s/%(artifact)s/%(version)s/%(artifact)s-%(version)s.pom' % {
+ 'artifact': artifact,
+ 'groupId': groupId.replace('.','/'),
+ 'version': version }
+ get(base + path) # will raise exception if not present
+
+# Close the repo (Note: /drop can be used to drop the repo, e.g. if failed)
+def closeRepo(repositoryId, profileId, version):
+ url = BASE_URL + 'staging/profiles/%s/finish' % profileId
+ # Argument info: https://oss.sonatype.org/nexus-staging-plugin/default/docs/index.html
+ xml = '''<?xml version="1.0" encoding="UTF-8"?>
+ <promoteRequest>
+ <data>
+ <stagedRepositoryId>%s</stagedRepositoryId>
+ <description>%s</description>
+ <targetRepositoryId>%s</targetRepositoryId>
+ </data>
+ </promoteRequest>''' % (repositoryId, version, '')
+ post(url, xml)
+ # Wait for the close to be registered
+ time.sleep(3)
+
+# Drop the repo
+def dropRepo(repositoryId, profileId):
+ url = BASE_URL + 'staging/profiles/%s/drop' % profileId
+ # Argument info: https://oss.sonatype.org/nexus-staging-plugin/default/docs/index.html
+ xml = '''<?xml version="1.0" encoding="UTF-8"?>
+ <promoteRequest>
+ <data>
+ <stagedRepositoryId>%s</stagedRepositoryId>
+ <description></description>
+ <targetRepositoryId></targetRepositoryId>
+ </data>
+ </promoteRequest>''' % (repositoryId)
+ post(url, xml)
+ # Wait for the close to be registered
+ time.sleep(3)
+
+# Check closing status
+def checkClose(repositoryId):
+ url = BASE_URL + 'staging/repository/%s/activity' % repositoryId
+ data = get(url).json()
+ closeActivity = None
+ for activity in data:
+ # find the last close activity
+ if activity['name'] == 'close':
+ closeActivity = activity
+
+ if not closeActivity:
+ return False
+
+ for event in activity['events']:
+ if event['name'] == 'repositoryClosed':
+ return True
+ elif event['name'] == 'repositoryCloseFailed':
+ print 'Aborting... repository failed to close'
+ print json.dumps(activity, sort_keys=True, indent=2, separators=(',', ': '))
+ sys.exit(1)
+ return False
+
+# Wait until the repository is closed
+def waitClosed(repositoryId):
+ sys.stdout.write('Closing...')
+ sys.stdout.flush()
+ while not checkClose(repositoryId):
+ sys.stdout.write('.')
+ sys.stdout.flush()
+ time.sleep(2)
+ print ' Closed.'
+
+if __name__ == '__main__':
+ repositoryId, profileId = getStagingRepo(GROUP_ID)
+ print 'Repository Id:', repositoryId
+ print 'Profile Id:', profileId
+
+ checkStagingRepo(repositoryId, ARTIFACT, GROUP_ID, VERSION)
+
+ closeRepo(repositoryId, profileId, VERSION)
+
+ waitClosed(repositoryId)
+
+ if '-d' in sys.argv:
+ print 'Dropping repo %s' % repositoryId
+ dropRepo(repositoryId, profileId)
diff --git a/tools/build/onos-release-prerequisites b/tools/build/onos-release-prerequisites
index 9268e50..5880669 100755
--- a/tools/build/onos-release-prerequisites
+++ b/tools/build/onos-release-prerequisites
@@ -107,10 +107,10 @@
# Sonatype account must be created & ~/.m2/settings.xml must be configured
# Test by "releasing" a fake project setup for that purpose to validate access.
-function testSonatypeAccess {
+function testSonatypeAccessMvn {
aux=$(mktemp)
trap "cat $aux; rm -f $aux; echo 'FAILED'" ERR
- printf "Checking Sonatype access... "
+ printf "Checking Sonatype access via Maven... "
pushd $ONOS_ROOT/tools/build/release-test >/dev/null
# TODO: Figure out how to supress the GPG note
mvn -Prelease clean deploy org.sonatype.plugins:nexus-staging-maven-plugin:drop \
@@ -121,6 +121,31 @@
echo "OK"
}
+function testSonatypeAccessRest {
+ #FIXME check SONATYPE_USER SONATYPE_PASSWORD
+ export ONOS_VERSION=1.2.3
+ printf "Checking Sonatype access via REST... "
+ pushd $ONOS_ROOT/tools/build/release-test >/dev/null
+ #FIXME this won't work on Linux
+ md5 pom.xml > pom.xml.md5
+ shasum pom.xml > pom.xml.sha1
+ gpg --detach-sign --output pom.xml.asc pom.xml
+ # Upload the files to staging
+ curl -s -u$SONATYPE_USER:$SONATYPE_PASSWORD --upload-file pom.xml \
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/org/onosproject/onos-api/$ONOS_VERSION/onos-api-$ONOS_VERSION.pom
+ curl -s -u$SONATYPE_USER:$SONATYPE_PASSWORD --upload-file pom.xml.md5 \
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/org/onosproject/onos-api/$ONOS_VERSION/onos-api-$ONOS_VERSION.pom.md5
+ curl -s -u$SONATYPE_USER:$SONATYPE_PASSWORD --upload-file pom.xml.sha1 \
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/org/onosproject/onos-api/$ONOS_VERSION/onos-api-$ONOS_VERSION.pom.sha1
+ curl -s -u$SONATYPE_USER:$SONATYPE_PASSWORD --upload-file pom.xml.asc \
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/org/onosproject/onos-api/$ONOS_VERSION/onos-api-$ONOS_VERSION.pom.asc
+ rm pom.xml.md5 pom.xml.sha1 pom.xml.asc
+ onos-close-staging -d >/dev/null
+ popd >/dev/null
+ unset ONOS_VERSION
+ echo "OK"
+}
+
# .buckconfig.local must exist and the sonatype credentials must be set up
function testBuckconfigLocal() {
printf "Checking local buck config..."
@@ -153,7 +178,7 @@
testGerritAccess
testWikiAccess
testEC2Access
-testSonatypeAccess
+testSonatypeAccessMvn
+testSonatypeAccessRest
echo "Ready to commence release process!"
-