88import shutil
99import logging
1010import argparse
11+ import requests
12+ import tempfile
1113import subprocess
1214import collections
1315import urllib .parse
16+ from typing import Tuple
1417
1518pwd = os .getcwd ()
1619os .chdir (os .path .abspath (os .path .dirname (sys .argv [0 ])))
@@ -34,7 +37,6 @@ def generate(
3437 use : str ,
3538 tag : str = None ,
3639 version : str = None ,
37- compile : bool = True ,
3840 ** kwargs ,
3941):
4042 module = ARTIFACT_FORMAT .format (service )
@@ -71,15 +73,108 @@ def generate(
7173 update_root_pom (sdk_root , service )
7274 update_version (sdk_root , service )
7375
74- if compile :
75- if os .system ('mvn clean verify package -f {0}/pom.xml -pl {1}:{2} -am' .
76- format (sdk_root , GROUP_ID , module )) != 0 :
77- logging .error ('[GENERATE] Maven build fail' )
78- return False
76+ return True
77+
7978
79+ def compile_package (sdk_root , service ):
80+ module = ARTIFACT_FORMAT .format (service )
81+ if os .system (
82+ 'mvn clean verify package -f {0}/pom.xml -pl {1}:{2} -am' .format (
83+ sdk_root , GROUP_ID , module )) != 0 :
84+ logging .error ('[COMPILE] Maven build fail' )
85+ return False
8086 return True
8187
8288
89+ def generate_changelog_and_breaking_change (
90+ sdk_root ,
91+ old_jar ,
92+ new_jar ,
93+ ** kwargs ,
94+ ) -> Tuple [bool , str ]:
95+ logging .info ('[CHANGELOG] changelog jar: {0} -> {1}' .format (
96+ old_jar , new_jar ))
97+ stdout = subprocess .run (
98+ 'mvn clean compile exec:java -q -f {0}/eng/mgmt/changelog/pom.xml -DOLD_JAR="{1}" -DNEW_JAR="{2}"'
99+ .format (sdk_root , old_jar , new_jar ),
100+ stdout = subprocess .PIPE ,
101+ shell = True ,
102+ ).stdout
103+ logging .info ('[CHANGELOG] changelog output: {0}' .format (stdout ))
104+
105+ config = json .loads (stdout )
106+ return (config .get ('breaking' , False ), config .get ('changelog' , '' ))
107+
108+
109+ def update_changelog (changelog_file , changelog ):
110+ version_pattern = '^## (\d+\.\d+\.\d+(?:-[\w\d\.]+)?) \((.*?)\)'
111+ with open (changelog_file , 'r' ) as fin :
112+ old_changelog = fin .read ()
113+
114+ first_version = re .search (version_pattern , old_changelog , re .M )
115+ if not first_version :
116+ logging .error (
117+ '[Changelog][Skip] Cannot read first version from {}' .format (
118+ changelog_file ))
119+ return
120+
121+ left = old_changelog [first_version .end ():]
122+ second_version = re .search (version_pattern , left , re .M )
123+ if not second_version :
124+ logging .error (
125+ '[Changelog][Skip] Cannot read second version from {}' .format (
126+ changelog_file ))
127+ return
128+
129+ first_version_part = old_changelog [:first_version .end () +
130+ second_version .start ()]
131+ first_version_part = re .sub ('\s+$' , '' , first_version_part )
132+ first_version_part += '\n \n ' + changelog .strip () + '\n \n '
133+
134+ with open (changelog_file , 'w' ) as fout :
135+ fout .write (first_version_part +
136+ old_changelog [first_version .end () + second_version .start ():])
137+
138+ logging .info ('[Changelog][Success] Write to changelog' )
139+
140+
141+ def compare_with_maven_package (sdk_root , service , stable_version ,
142+ current_version ):
143+ if stable_version == current_version :
144+ logging .info ('[Changelog][Skip] no previous version' )
145+ return
146+
147+ module = ARTIFACT_FORMAT .format (service )
148+ r = requests .get (
149+ MAVEN_URL .format (group_id = GROUP_ID .replace ('.' , '/' ),
150+ artifact_id = module ,
151+ version = stable_version ))
152+ r .raise_for_status ()
153+ old_jar_fd , old_jar = tempfile .mkstemp ('.jar' )
154+ try :
155+ with os .fdopen (old_jar_fd , 'wb' ) as tmp :
156+ tmp .write (r .content )
157+ new_jar = os .path .join (
158+ sdk_root ,
159+ JAR_FORMAT .format (service = service ,
160+ artifact_id = module ,
161+ version = current_version ))
162+ if not os .path .exists (new_jar ):
163+ raise Exception ('Cannot found built jar in {0}' .format (new_jar ))
164+ breaking , changelog = generate_changelog_and_breaking_change (
165+ sdk_root , old_jar , new_jar )
166+ if changelog and changelog .strip () != '' :
167+ changelog_file = os .path .join (
168+ sdk_root ,
169+ CHANGELOG_FORMAT .format (service = service ,
170+ artifact_id = module ))
171+ update_changelog (changelog_file , changelog )
172+ else :
173+ logging .error ('[Changelog][Skip] Cannot get changelog' )
174+ finally :
175+ os .remove (old_jar )
176+
177+
83178def add_module_to_modules (modules : str , module : str ) -> str :
84179 post_module = re .search (r'([^\S\n\r]*)</modules>' , modules )
85180 indent = post_module .group (1 )
@@ -95,7 +190,7 @@ def add_module_to_modules(modules: str, module: str) -> str:
95190 return '<modules>\n ' + '' .join (all_module ) + post_module .group ()
96191
97192
98- def add_module_to_default_profile (pom : str , module : str ) -> ( bool , str ) :
193+ def add_module_to_default_profile (pom : str , module : str ) -> Tuple [ bool , str ] :
99194 for profile in re .finditer (r'<profile>[\s\S]*?</profile>' , pom ):
100195 profile_value = profile .group ()
101196 if re .search (r'<id>default</id>' , profile_value ):
@@ -119,7 +214,7 @@ def add_module_to_default_profile(pom: str, module: str) -> (bool, str):
119214 return (False , '' )
120215
121216
122- def add_module_to_pom (pom : str , module : str ) -> ( bool , str ) :
217+ def add_module_to_pom (pom : str , module : str ) -> Tuple [ bool , str ] :
123218 if pom .find ('<module>{0}</module>' .format (module )) >= 0 :
124219 logging .info ('[POM][Skip] pom already has module {0}' .format (module ))
125220 return (True , pom )
@@ -207,7 +302,9 @@ def update_service_ci_and_pom(sdk_root: str, service: str):
207302 with open (pom_xml_file , 'r' ) as fin :
208303 pom_xml = fin .read ()
209304 else :
210- pom_xml = POM_FORMAT .format (service = service , group_id = GROUP_ID , artifact_id = module )
305+ pom_xml = POM_FORMAT .format (service = service ,
306+ group_id = GROUP_ID ,
307+ artifact_id = module )
211308
212309 logging .info ('[POM][Process] dealing with pom.xml' )
213310 success , pom_xml = add_module_to_pom (pom_xml , module )
@@ -217,6 +314,26 @@ def update_service_ci_and_pom(sdk_root: str, service: str):
217314 logging .info ('[POM][Success] Write to pom.xml' )
218315
219316
317+ def get_version (
318+ sdk_root : str ,
319+ service : str ,
320+ ) -> str :
321+ version_file = os .path .join (sdk_root , 'eng/versioning/version_client.txt' )
322+ module = ARTIFACT_FORMAT .format (service )
323+ project = '{0}:{1}' .format (GROUP_ID , module )
324+
325+ with open (version_file , 'r' ) as fin :
326+ for line in fin .readlines ():
327+ version_line = line .strip ()
328+ if version_line .startswith ('#' ):
329+ continue
330+ versions = version_line .split (';' )
331+ if versions [0 ] == project :
332+ return version_line
333+ logging .error ('Cannot get version of {0}' .format (project ))
334+ return None
335+
336+
220337def update_version (sdk_root : str , service : str ):
221338 pwd = os .getcwd ()
222339 try :
@@ -254,13 +371,13 @@ def write_version(
254371 fout .write ('\n ' )
255372
256373
257- def set_or_increase_version_and_generate (
374+ def set_or_increase_version (
258375 sdk_root : str ,
259376 service : str ,
260377 preview = True ,
261378 version = None ,
262379 ** kwargs ,
263- ):
380+ ) -> Tuple [ str , str ] :
264381 version_file = os .path .join (sdk_root , 'eng/versioning/version_client.txt' )
265382 module = ARTIFACT_FORMAT .format (service )
266383 project = '{0}:{1}' .format (GROUP_ID , module )
@@ -305,13 +422,12 @@ def set_or_increase_version_and_generate(
305422 # version is given, set and return
306423 if version :
307424 if not stable_version :
308- stable_version = current_version
425+ stable_version = version
309426 logging .info (
310427 '[VERSION][Set] set to given version "{0}"' .format (version ))
311428 write_version (version_file , lines , version_index , project ,
312- stable_version , current_version )
313- generate (sdk_root , service , version = version , ** kwargs )
314- return
429+ stable_version , version )
430+ return stable_version , version
315431
316432 current_versions = list (re .findall (version_pattern , current_version )[0 ])
317433 stable_versions = re .findall (version_pattern , stable_version )
@@ -328,7 +444,6 @@ def set_or_increase_version_and_generate(
328444
329445 write_version (version_file , lines , version_index , project ,
330446 stable_version , current_version )
331- generate (sdk_root , service , version = current_version , ** kwargs )
332447 else :
333448 # TODO: auto-increase for stable version and beta version if possible
334449 current_version = version_format .format (* current_versions )
@@ -340,7 +455,8 @@ def set_or_increase_version_and_generate(
340455
341456 write_version (version_file , lines , version_index , project ,
342457 stable_version , current_version )
343- generate (sdk_root , service , version = current_version , ** kwargs )
458+
459+ return stable_version , current_version
344460
345461
346462def parse_args () -> argparse .Namespace :
@@ -375,11 +491,6 @@ def parse_args() -> argparse.Namespace:
375491 default = AUTOREST_CORE_VERSION ,
376492 help = 'Autorest version' ,
377493 )
378- parser .add_argument (
379- '--compile' ,
380- action = 'store_true' ,
381- help = 'Do compile after generation or not' ,
382- )
383494 parser .add_argument ('--suffix' , help = 'Suffix for namespace and artifact' )
384495 parser .add_argument (
385496 '--auto-commit-external-change' ,
@@ -414,7 +525,7 @@ def valid_service(service: str):
414525 return re .sub ('[^a-z0-9_]' , '' , service .lower ())
415526
416527
417- def read_api_specs (api_specs_file : str ) -> ( str , dict ) :
528+ def read_api_specs (api_specs_file : str ) -> Tuple [ str , dict ] :
418529 # return comment and api_specs
419530
420531 with open (api_specs_file ) as fin :
@@ -517,14 +628,20 @@ def sdk_automation(input_file: str, output_file: str):
517628 else :
518629 tag = 'package-resources-2020-10'
519630
520- set_or_increase_version_and_generate (
631+ stable_version , current_version = set_or_increase_version (
632+ sdk_root ,
633+ service ,
634+ )
635+ generate (
521636 sdk_root ,
522637 service ,
523638 spec_root = config ['specFolder' ],
524639 readme = readme ,
525640 autorest = AUTOREST_CORE_VERSION ,
526641 use = AUTOREST_JAVA ,
527- tag = tag )
642+ tag = tag ,
643+ )
644+ compile_package (sdk_root , service )
528645
529646 generated_folder = OUTPUT_FOLDER_FORMAT .format (service )
530647 packages .append ({
@@ -587,7 +704,13 @@ def main():
587704 service = get_and_update_service_from_api_specs (api_specs_file , spec ,
588705 args ['service' ])
589706 args ['service' ] = service
590- set_or_increase_version_and_generate (sdk_root , ** args )
707+ stable_version , current_version = set_or_increase_version (sdk_root , ** args )
708+ args ['version' ] = current_version
709+ generate (sdk_root , ** args )
710+
711+ compile_package (sdk_root , service )
712+ compare_with_maven_package (sdk_root , service , stable_version ,
713+ current_version )
591714
592715 if args .get ('auto_commit_external_change' ) and args .get (
593716 'user_name' ) and args .get ('user_email' ):
@@ -606,7 +729,7 @@ def main():
606729
607730if __name__ == '__main__' :
608731 logging .basicConfig (
609- level = logging .DEBUG ,
732+ level = logging .INFO ,
610733 format = '%(asctime)s %(levelname)s %(message)s' ,
611734 datefmt = '%Y-%m-%d %X' ,
612735 )
0 commit comments