| 
									
										
										
										
											2017-10-18 19:53:10 +08:00
										 |  |  | #!/usr/bin/env python | 
					
						
							| 
									
										
										
										
											2022-06-15 16:46:55 +02:00
										 |  |  | # SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD | 
					
						
							|  |  |  | # SPDX-License-Identifier: Apache-2.0 | 
					
						
							| 
									
										
										
										
											2017-10-18 19:53:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | # internal use only | 
					
						
							|  |  |  | # called by CI jobs when it uses a project related to IDF | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import argparse | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  | import json | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  | import re | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  | import subprocess | 
					
						
							| 
									
										
										
										
											2022-09-14 02:43:40 +08:00
										 |  |  | from typing import List, Tuple | 
					
						
							| 
									
										
										
										
											2017-10-18 19:53:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  | IDF_GIT_DESCRIBE_PATTERN = re.compile(r'^v(\d)\.(\d)') | 
					
						
							| 
									
										
										
										
											2022-09-14 02:43:40 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _idf_version_from_cmake() -> Tuple[int, int]: | 
					
						
							|  |  |  |     version_path = os.path.join(os.environ['IDF_PATH'], 'tools/cmake/version.cmake') | 
					
						
							|  |  |  |     regex = re.compile(r'^\s*set\s*\(\s*IDF_VERSION_([A-Z]{5})\s+(\d+)') | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         ver = {} | 
					
						
							|  |  |  |         with open(version_path) as f: | 
					
						
							|  |  |  |             for line in f: | 
					
						
							|  |  |  |                 m = regex.match(line) | 
					
						
							|  |  |  |                 if m: | 
					
						
							|  |  |  |                     ver[m.group(1)] = m.group(2) | 
					
						
							|  |  |  |         return (int(ver['MAJOR']), int(ver['MINOR'])) | 
					
						
							|  |  |  |     except (KeyError, OSError): | 
					
						
							|  |  |  |         print('WARNING: Cannot find ESP-IDF version in version.cmake') | 
					
						
							|  |  |  |         return (0, 0) | 
					
						
							| 
									
										
										
										
											2020-10-30 14:39:42 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 |  |  | def get_customized_project_revision(proj_name: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-10-30 14:39:42 +08:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     get customized project revision defined in bot message | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |     revision = '' | 
					
						
							| 
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 |  |  |     customized_project_revisions_file = os.getenv('BOT_CUSTOMIZED_REVISION') | 
					
						
							|  |  |  |     if customized_project_revisions_file: | 
					
						
							|  |  |  |         customized_project_revisions = json.loads(customized_project_revisions_file) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             revision = customized_project_revisions[proj_name.lower()] | 
					
						
							|  |  |  |         except (KeyError, TypeError): | 
					
						
							|  |  |  |             pass | 
					
						
							| 
									
										
										
										
											2020-10-30 14:39:42 +08:00
										 |  |  |     return revision | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-28 19:00:12 +02:00
										 |  |  | def target_branch_candidates(proj_name: str) -> List: | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     :return: a list of target branch candidates, from highest priority to lowest priority. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     candidates = [ | 
					
						
							|  |  |  |         # branch name (or tag name) of current IDF | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |         os.getenv('CI_COMMIT_REF_NAME'), | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  |         # CI_MERGE_REQUEST_TARGET_BRANCH_NAME | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |         os.getenv('CI_MERGE_REQUEST_TARGET_BRANCH_NAME'), | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  |     ] | 
					
						
							| 
									
										
										
										
											2020-10-30 14:39:42 +08:00
										 |  |  |     customized_candidate = get_customized_project_revision(proj_name) | 
					
						
							|  |  |  |     if customized_candidate: | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  |         # highest priority, insert to head of list | 
					
						
							| 
									
										
										
										
											2020-10-30 14:39:42 +08:00
										 |  |  |         candidates.insert(0, customized_candidate) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  |     # branch name read from IDF | 
					
						
							| 
									
										
										
										
											2022-09-14 02:43:40 +08:00
										 |  |  |     major_revision, minor_revision = _idf_version_from_cmake() | 
					
						
							|  |  |  |     # release branch | 
					
						
							|  |  |  |     candidates.append('release/v{}.{}'.format(major_revision, minor_revision)) | 
					
						
							|  |  |  |     # branch to match all major branches, like v3.x or v3 | 
					
						
							|  |  |  |     candidates.append('release/v{}.x'.format(major_revision)) | 
					
						
							|  |  |  |     candidates.append('release/v{}'.format(major_revision)) | 
					
						
							| 
									
										
										
										
											2017-10-18 19:53:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  |     return [c for c in candidates if c]  # filter out null value | 
					
						
							| 
									
										
										
										
											2017-10-18 19:53:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											2017-10-18 19:53:10 +08:00
										 |  |  |     parser = argparse.ArgumentParser() | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |     parser.add_argument('project', | 
					
						
							|  |  |  |                         help='the name of project') | 
					
						
							|  |  |  |     parser.add_argument('project_relative_path', | 
					
						
							|  |  |  |                         help='relative path of project to IDF repository directory') | 
					
						
							| 
									
										
										
										
											2020-10-30 14:39:42 +08:00
										 |  |  |     parser.add_argument('--customized_only', action='store_true', | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |                         help='Only to find customized revision') | 
					
						
							| 
									
										
										
										
											2017-10-18 19:53:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     args = parser.parse_args() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 14:39:42 +08:00
										 |  |  |     if args.customized_only: | 
					
						
							|  |  |  |         customized_revision = get_customized_project_revision(args.project) | 
					
						
							|  |  |  |         candidate_branches = [customized_revision] if customized_revision else [] | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         candidate_branches = target_branch_candidates(args.project) | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # change to project dir for checkout | 
					
						
							|  |  |  |     os.chdir(args.project_relative_path) | 
					
						
							| 
									
										
										
										
											2017-10-18 19:53:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |     ref_to_use = '' | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  |     for candidate in candidate_branches: | 
					
						
							| 
									
										
										
										
											2022-01-06 23:42:48 +08:00
										 |  |  |         # check if the branch, tag or commit exists | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2022-01-26 16:40:52 +08:00
										 |  |  |             subprocess.check_call(['git', 'cat-file', '-t', 'origin/{}'.format(candidate)], stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 
					
						
							| 
									
										
										
										
											2020-10-30 14:39:42 +08:00
										 |  |  |             ref_to_use = candidate | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  |             break | 
					
						
							| 
									
										
										
										
											2022-01-06 23:42:48 +08:00
										 |  |  |         except subprocess.CalledProcessError: | 
					
						
							| 
									
										
										
										
											2022-01-26 16:40:52 +08:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 # For customized commits | 
					
						
							|  |  |  |                 subprocess.check_call(['git', 'cat-file', '-t', candidate], stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 
					
						
							|  |  |  |                 ref_to_use = candidate | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             except subprocess.CalledProcessError: | 
					
						
							|  |  |  |                 pass | 
					
						
							| 
									
										
										
										
											2022-01-06 23:42:48 +08:00
										 |  |  |             continue | 
					
						
							| 
									
										
										
										
											2020-10-30 14:39:42 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ref_to_use: | 
					
						
							| 
									
										
										
										
											2022-09-14 02:43:40 +08:00
										 |  |  |         try: | 
					
						
							|  |  |  |             subprocess.check_call(['git', 'checkout', '-f', ref_to_use], stdout=subprocess.PIPE)  # not print the stdout | 
					
						
							|  |  |  |             print('CI using ref {} for project {}'.format(ref_to_use, args.project)) | 
					
						
							|  |  |  |         except subprocess.CalledProcessError: | 
					
						
							|  |  |  |             pass | 
					
						
							| 
									
										
										
										
											2019-04-28 16:57:59 +08:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |         print('using default branch') |