blob: 074c14d347042880a93327b96ed74845ee42df65 [file] [log] [blame]
Ray Milkeyebc673f2018-07-20 16:51:55 -07001#!/usr/bin/env python
2"""
3 Copyright 2018-present Open Networking Foundation
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16"""
17
18from subprocess import call
19import tempfile
20import hashlib
21import requests, os
22import xml.etree.ElementTree, shutil
Ray Milkeyf77ea412018-08-10 17:37:28 -070023import time
Ray Milkeyebc673f2018-07-20 16:51:55 -070024
25SONATYPE_USER=os.environ.get("SONATYPE_USER")
26SONATYPE_PASSWORD=os.environ.get("SONATYPE_PASSWORD")
27SONATYPE_PROFILE=os.environ.get("SONATYPE_PROFILE")
Ray Milkeyebc673f2018-07-20 16:51:55 -070028
29CREATE_REPO_REQUEST_TEMPLATE = '''\
30<promoteRequest>
31 <data>
32 <description>%(description)</description>
33 </data>
34</promoteRequest>
35'''
36
37CLOSE_REPO_REQUEST_TEMPLATE = '''\
38<promoteRequest>
39 <data>
40 <description>%(description)</description>
41 <stagedRepositoryId>%(repo_id)</stagedRepositoryId>
42 </data>
43</promoteRequest>
44'''
45
Ray Milkeyf77ea412018-08-10 17:37:28 -070046CLOSE_RETRY_ATTEMPTS = 12 * 2
47
Ray Milkeyebc673f2018-07-20 16:51:55 -070048def hashlib_compute(hash, input_file, output_file):
49 with open(input_file, 'rb') as f:
50 for block in iter(lambda: f.read(100000), b''):
51 hash.update(block)
52 md5_string = hash.hexdigest()
53 output = open(output_file, "w")
54 output.write(md5_string + "\n")
55 f.close()
56 output.close()
57
58
Ray Milkey7f46b1f2018-07-24 19:01:58 -070059def generate_metadata_files(input_file, dest):
Ray Milkeyebc673f2018-07-20 16:51:55 -070060 # create a temporary directory to hold the metadata files
61 global tempdir
Ray Milkey7f46b1f2018-07-24 19:01:58 -070062 base_metadata_filename = tempdir + "/" + os.path.basename(dest)
Ray Milkeyebc673f2018-07-20 16:51:55 -070063
64 files = []
65
66 # generate the signature file
67 signature_filename = base_metadata_filename + ".asc"
68 call(["gpg", "--armor", "--detach-sig", "--output", signature_filename, input_file])
69 files.append(signature_filename)
70
71 # generate the md5 checksum file
72 md5_filename = base_metadata_filename + ".md5"
73 md5 = hashlib.md5()
74 hashlib_compute(md5, input_file, md5_filename)
75 files.append(md5_filename)
76
77 # generate the SHA checksum file
78 sha1_filename = base_metadata_filename + ".sha1"
79 sha1 = hashlib.sha1()
80 hashlib_compute(sha1, input_file, sha1_filename)
81 files.append(sha1_filename)
82
Ray Milkey7f46b1f2018-07-24 19:01:58 -070083 # generate the base artifact
84 base_artifact_filename = base_metadata_filename
85 shutil.copyfile(input_file, base_artifact_filename)
86 files.append(base_artifact_filename)
87
Ray Milkeyebc673f2018-07-20 16:51:55 -070088 return files
89
90
91def create_staging_repo(description):
Ray Milkeyd111751b2018-07-24 10:14:02 -070092 if destination_repo_url is None:
93 return None
Ray Milkeyebc673f2018-07-20 16:51:55 -070094 create_request = CREATE_REPO_REQUEST_TEMPLATE.replace("%(description)", description)
Ray Milkeyd111751b2018-07-24 10:14:02 -070095 url = "https://" + destination_repo_url + "/service/local/staging/profiles" + "/" + SONATYPE_PROFILE + "/start"
Ray Milkeyebc673f2018-07-20 16:51:55 -070096 headers = {'Content-Type': 'application/xml'}
97 r = requests.post(url, create_request, headers=headers, auth=(SONATYPE_USER, SONATYPE_PASSWORD))
98 root = xml.etree.ElementTree.fromstring(r.text)
99 repo_id = root.find("data").find("stagedRepositoryId").text
Ray Milkeyebc673f2018-07-20 16:51:55 -0700100 return repo_id
101
102
103def close_staging_repo(description, repo_id):
Ray Milkeyd111751b2018-07-24 10:14:02 -0700104 if repo_id is None:
105 return
Ray Milkeyebc673f2018-07-20 16:51:55 -0700106 close_request = CLOSE_REPO_REQUEST_TEMPLATE.replace("%(description)", description).replace("%(repo_id)", repo_id)
Ray Milkeyd111751b2018-07-24 10:14:02 -0700107 url = "https://" + destination_repo_url + "/service/local/staging/profiles" + "/" + SONATYPE_PROFILE + "/finish"
Ray Milkeyebc673f2018-07-20 16:51:55 -0700108 headers = {'Content-Type': 'application/xml'}
109 r = requests.post(url, close_request, headers=headers, auth=(SONATYPE_USER, SONATYPE_PASSWORD))
110
111
Ray Milkeyf77ea412018-08-10 17:37:28 -0700112def wait_for_staging_repo(description, repo_id):
113 base_url = "https://" + destination_repo_url + "/service/local/staging/profiles" + "/" + SONATYPE_PROFILE
114 if repo_id is None:
115 return
116 close_request = CLOSE_REPO_REQUEST_TEMPLATE.replace("%(description)", description).replace("%(repo_id)", repo_id)
117 url = base_url + "/finish"
118 headers = {'Content-Type': 'application/xml'}
119 repo_query_url = "https://oss.sonatype.org/service/local/staging/repository/" + repo_id
120
121 attempt = 1
122 print ("waiting for repo to close...")
123 while True:
124 r = requests.get(repo_query_url, close_request, headers=headers, auth=(SONATYPE_USER, SONATYPE_PASSWORD))
125 root = xml.etree.ElementTree.fromstring(r.text)
126 transitioning = root.find("transitioning").text
127 if transitioning != "true":
128 break
129 if attempt == CLOSE_RETRY_ATTEMPTS:
130 print ("Unable to close repo")
131 sys.exit(1)
132 attempt = attempt + 1
133 time.sleep(5)
134 print ("Repo closed successfully")
135
136
Ray Milkeyebc673f2018-07-20 16:51:55 -0700137def stage_file(file, repo_id, dest):
Ray Milkey7f46b1f2018-07-24 19:01:58 -0700138 filename_in_repo = os.path.dirname(dest) + "/" + os.path.basename(file)
Ray Milkeyd111751b2018-07-24 10:14:02 -0700139 if destination_repo_url is not None:
140 # deploy to Nexus repo
141 upload_base = "https://" + destination_repo_url + "/service/local/staging/deployByRepositoryId"
Ray Milkey7f46b1f2018-07-24 19:01:58 -0700142 url = upload_base + "/" + repo_id + "/" + filename_in_repo
Ray Milkeyd111751b2018-07-24 10:14:02 -0700143 headers = {'Content-Type': 'application/xml'}
144 with open(file, 'rb') as f:
Ray Milkey7f46b1f2018-07-24 19:01:58 -0700145 r = requests.post(url, data=f.read(), headers=headers, auth=(SONATYPE_USER, SONATYPE_PASSWORD))
146 if r.status_code != 201:
147 print (r.status_code)
148 print (r.text)
149 sys.exit(1)
Ray Milkeyd111751b2018-07-24 10:14:02 -0700150 else:
151 # deploy to local repo
Ray Milkey7f46b1f2018-07-24 19:01:58 -0700152 file_in_local_repo = os.path.expanduser(local_maven_repo + "/" + filename_in_repo)
153 dir_in_local_repo = os.path.dirname(file_in_local_repo)
154 if not os.path.isdir(dir_in_local_repo):
155 os.makedirs(dir_in_local_repo)
156 shutil.copyfile(src, file_in_local_repo)
Ray Milkeyebc673f2018-07-20 16:51:55 -0700157
158
159def stage_files(files, dest):
160 for file in files:
161 stage_file(file=file, repo_id=repo_id, dest=dest)
162
163
164def upload_file(src, dest):
Ray Milkey7f46b1f2018-07-24 19:01:58 -0700165 print ("publishing: " + dest.replace("org/onosproject", ""))
166 files = generate_metadata_files(src, dest)
Ray Milkeyebc673f2018-07-20 16:51:55 -0700167 stage_files(files, dest)
168
169
170if __name__ == '__main__':
171 import sys
172
173 if len(sys.argv) < 2:
Ray Milkeyd111751b2018-07-24 10:14:02 -0700174 print 'USAGE: upload-maven-artifacts catalog-file-name [nexus root url]'
Ray Milkeyebc673f2018-07-20 16:51:55 -0700175 sys.exit(1)
176
177 input_list_file = sys.argv[1]
Ray Milkeyd111751b2018-07-24 10:14:02 -0700178
179 local_maven_repo = None
180 destination_repo_url = None
181
182 if len(sys.argv) == 3:
183 destination_repo_url = sys.argv[2]
184 else:
185 local_maven_repo = os.environ.get("MAVEN_REPO")
186 if local_maven_repo is None:
187 local_maven_repo = "~/.m2/repository"
188
189 if destination_repo_url is not None:
190 if SONATYPE_USER is None:
191 print "Environment variable SONATYPE_USER must be set"
192 sys.exit(1)
193
194 if SONATYPE_PASSWORD is None:
195 print "Environment variable SONATYPE_PASSWORD must be set"
196 sys.exit(1)
197
198 if SONATYPE_PROFILE is None:
199 print "Environment variable SONATYPE_PROFILE must be set"
200 sys.exit(1)
201
202 print ("Uploading to remote repo: " + destination_repo_url)
203 else:
204 print ("Installing in local repo: " + local_maven_repo)
205
Ray Milkeyebc673f2018-07-20 16:51:55 -0700206 list_file = open(input_list_file, "r")
207 lines = list_file.readlines()
208 list_file.close()
209
Ray Milkeyd111751b2018-07-24 10:14:02 -0700210 tempdir = tempfile.mkdtemp(prefix="upload-maven-artifacts-")
Ray Milkeyebc673f2018-07-20 16:51:55 -0700211 description = "test repo"
212 repo_id = create_staging_repo(description)
213 for line in lines:
214 s = line.split()
215 src = s[0]
216 dest = s[1]
217 upload_file(src, dest)
218 close_staging_repo(repo_id=repo_id, description=description)
Ray Milkeyf77ea412018-08-10 17:37:28 -0700219 wait_for_staging_repo(repo_id=repo_id, description=description)
Ray Milkeyebc673f2018-07-20 16:51:55 -0700220 shutil.rmtree(tempdir)