blob: 1e37ef395654ca2ca1bb8e2d74b83b1e71b135e5 [file] [log] [blame]
pierventre69db90c2022-05-06 23:06:20 +02001#!/usr/bin/env python3
Brian O'Connord89bfd02016-11-22 15:39:49 -08002#
3# This script finds an open staging repository, checks that it contains an
4# expected artifact, attemps to close the repository, and checks that it is closed.
5#
6
7import sys
8import json
9import time
10import os
11import requests
12from requests.auth import HTTPBasicAuth
13
14USER = os.environ['SONATYPE_USER']
15PASSWORD = os.environ['SONATYPE_PASSWORD']
16BASE_URL = 'https://oss.sonatype.org/service/local/'
17GROUP_ID = 'org.onosproject'
18ARTIFACT = 'onos-api'
19VERSION = os.environ['ONOS_VERSION']
Ray Milkeyc6076a12017-11-17 17:34:50 -080020MAX_TRIES = 10
Brian O'Connord89bfd02016-11-22 15:39:49 -080021
22# Performs an HTTP GET up to MAX_TRIES times
23def get(url):
24 headers = { 'Accept': 'application/json' }
25 error = None
26 for i in range(MAX_TRIES):
27 resp = requests.get(url, auth=HTTPBasicAuth(USER, PASSWORD), headers=headers)
28 try:
29 resp.raise_for_status()
30 return resp
31 except requests.exceptions.HTTPError as e:
pierventre69db90c2022-05-06 23:06:20 +020032 print('Encountered error:', e)
Brian O'Connord89bfd02016-11-22 15:39:49 -080033 error = e
34 time.sleep(1)
35 if error:
36 raise error
37 return resp
38
39# Performs an HTTP POST with the specified data up to MAX_TRIES times
40def post(url, data):
41 headers = { 'Accept': 'application/xml', 'Content-type': 'application/xml' }
42 error = None
43 for i in range(MAX_TRIES):
44 resp = requests.post(url, data=data, auth=HTTPBasicAuth(USER, PASSWORD), headers=headers)
45 try:
46 resp.raise_for_status()
47 return resp
48 except requests.exceptions.HTTPError as e:
pierventre69db90c2022-05-06 23:06:20 +020049 print('Encountered error:', e)
Brian O'Connord89bfd02016-11-22 15:39:49 -080050 error = e
51 time.sleep(1)
52 if error:
53 raise error
54 return resp
55
56# Get the staging repos and filter the ones related to onos
57def getStagingRepo(groupId):
58 resp = get(BASE_URL + 'staging/profile_repositories')
59 data = resp.json()['data']
60
61 repos = []
62 for entry in data:
63 if entry['profileName'] == groupId and entry['type'] == 'open':
64 repos.append(( entry['repositoryId'], entry['profileId'] ))
65
66 if len(repos) > 1:
pierventre69db90c2022-05-06 23:06:20 +020067 print('Aborting... too many open staging repos')
68 print(repos)
Brian O'Connord89bfd02016-11-22 15:39:49 -080069 sys.exit(1)
70 elif len(repos) == 0:
pierventre69db90c2022-05-06 23:06:20 +020071 print('Aborting... there are no open staging repos')
Brian O'Connord89bfd02016-11-22 15:39:49 -080072 sys.exit(1)
73
74 return repos[0]
75
76# Check to make sure the open repo contains the onos-api artifact for the appropriate version
77def checkStagingRepo(respositoryId, artifact, groupId, version):
78 base = BASE_URL + 'repositories/%s/content/' % repositoryId
79 path = '%(groupId)s/%(artifact)s/%(version)s/%(artifact)s-%(version)s.pom' % {
80 'artifact': artifact,
81 'groupId': groupId.replace('.','/'),
82 'version': version }
83 get(base + path) # will raise exception if not present
84
85# Close the repo (Note: /drop can be used to drop the repo, e.g. if failed)
86def closeRepo(repositoryId, profileId, version):
87 url = BASE_URL + 'staging/profiles/%s/finish' % profileId
88 # Argument info: https://oss.sonatype.org/nexus-staging-plugin/default/docs/index.html
89 xml = '''<?xml version="1.0" encoding="UTF-8"?>
90 <promoteRequest>
91 <data>
92 <stagedRepositoryId>%s</stagedRepositoryId>
93 <description>%s</description>
94 <targetRepositoryId>%s</targetRepositoryId>
95 </data>
96 </promoteRequest>''' % (repositoryId, version, '')
97 post(url, xml)
98 # Wait for the close to be registered
99 time.sleep(3)
100
101# Drop the repo
102def dropRepo(repositoryId, profileId):
103 url = BASE_URL + 'staging/profiles/%s/drop' % profileId
104 # Argument info: https://oss.sonatype.org/nexus-staging-plugin/default/docs/index.html
105 xml = '''<?xml version="1.0" encoding="UTF-8"?>
106 <promoteRequest>
107 <data>
108 <stagedRepositoryId>%s</stagedRepositoryId>
109 <description></description>
110 <targetRepositoryId></targetRepositoryId>
111 </data>
112 </promoteRequest>''' % (repositoryId)
113 post(url, xml)
114 # Wait for the close to be registered
115 time.sleep(3)
116
117# Check closing status
118def checkClose(repositoryId):
119 url = BASE_URL + 'staging/repository/%s/activity' % repositoryId
120 data = get(url).json()
121 closeActivity = None
122 for activity in data:
123 # find the last close activity
124 if activity['name'] == 'close':
125 closeActivity = activity
126
127 if not closeActivity:
128 return False
129
130 for event in activity['events']:
131 if event['name'] == 'repositoryClosed':
132 return True
133 elif event['name'] == 'repositoryCloseFailed':
pierventre69db90c2022-05-06 23:06:20 +0200134 print('Aborting... repository failed to close')
135 print(json.dumps(activity, sort_keys=True, indent=2, separators=(',', ': ')))
Brian O'Connord89bfd02016-11-22 15:39:49 -0800136 sys.exit(1)
137 return False
138
139# Wait until the repository is closed
140def waitClosed(repositoryId):
141 sys.stdout.write('Closing...')
142 sys.stdout.flush()
143 while not checkClose(repositoryId):
144 sys.stdout.write('.')
145 sys.stdout.flush()
146 time.sleep(2)
pierventre69db90c2022-05-06 23:06:20 +0200147 print(' Closed.')
Brian O'Connord89bfd02016-11-22 15:39:49 -0800148
149if __name__ == '__main__':
150 repositoryId, profileId = getStagingRepo(GROUP_ID)
pierventre69db90c2022-05-06 23:06:20 +0200151 print('Repository Id:', repositoryId)
152 print('Profile Id:', profileId)
Brian O'Connord89bfd02016-11-22 15:39:49 -0800153
154 checkStagingRepo(repositoryId, ARTIFACT, GROUP_ID, VERSION)
155
156 closeRepo(repositoryId, profileId, VERSION)
157
158 waitClosed(repositoryId)
159
160 if '-d' in sys.argv:
pierventre69db90c2022-05-06 23:06:20 +0200161 print('Dropping repo %s' % repositoryId)
Brian O'Connord89bfd02016-11-22 15:39:49 -0800162 dropRepo(repositoryId, profileId)