diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..a5480a936 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "python.autoComplete.extraPaths": [ + "${workspaceFolder}/sources/poky/bitbake/lib", + "${workspaceFolder}/sources/poky/meta/lib" + ], + "python.analysis.extraPaths": [ + "${workspaceFolder}/sources/poky/bitbake/lib", + "${workspaceFolder}/sources/poky/meta/lib" + ], + "files.associations": { + "*.conf": "bitbake", + "*.inc": "bitbake" + } +} \ No newline at end of file diff --git a/scripts/dev/upstream_merge/README.md b/scripts/dev/upstream_merge/README.md index a3db57abd..c1be0c033 100644 --- a/scripts/dev/upstream_merge/README.md +++ b/scripts/dev/upstream_merge/README.md @@ -97,8 +97,9 @@ The script is user configurable and uses `automation_conf.json` to define variou - **`build_args`**: String of extra arguments to pass to the build process (e.g., `"--org"` for NI corporate network builds). -- **`rt_target_IP`**: - The IP address or hostname of the RT target where images will be installed and tested via SSH. +- **`ssh_connection`**: + The SSH connection of the RT target where images will be installed. + Usage example: [username]@[hostname or IP address] **`Note`**: - If the configuration file is `automation_conf.json`, you do not need to specify its path explicitly, as it is set as default. However, if you are using a different configuration file, you must provide its path using the `-c` argument. diff --git a/scripts/dev/upstream_merge/automation_conf.json b/scripts/dev/upstream_merge/automation_conf.json index a466ff944..f9fcc2e66 100644 --- a/scripts/dev/upstream_merge/automation_conf.json +++ b/scripts/dev/upstream_merge/automation_conf.json @@ -6,11 +6,11 @@ "upstream_repo_name": "automerge_upstream", "merge_branch_name": "dev/automerge/ni", "fork_name": "myfork", - "email_log_level": 1, + "email_log_level": 0, "log_level": 10, - "email_from": "shreejit.c@emerson.com", - "email_to": "pratheeksha.s.n@emerson.com", + "email_from": "", + "email_to": "", "username": "", "build_args":"", - "rt_target_IP":"" + "ssh_connection":"" } diff --git a/scripts/dev/upstream_merge/json_config.py b/scripts/dev/upstream_merge/json_config.py index 8f911f966..533fd64f9 100644 --- a/scripts/dev/upstream_merge/json_config.py +++ b/scripts/dev/upstream_merge/json_config.py @@ -26,4 +26,4 @@ def __init__(self, automation_conf_path, work_item_id): self.email_log_level = config.get("email_log_level") self.log_level = config.get("log_level") self.build_args = config.get("build_args", "") - self.rt_target_IP = config.get("rt_target_IP") + self.ssh_connection = config.get("ssh_connection") diff --git a/scripts/dev/upstream_merge/log_and_email_utils.py b/scripts/dev/upstream_merge/log_and_email_utils.py index 99a46699f..11df12bc9 100644 --- a/scripts/dev/upstream_merge/log_and_email_utils.py +++ b/scripts/dev/upstream_merge/log_and_email_utils.py @@ -50,17 +50,14 @@ def format_status(status, message): :param message: Associated message or details. :return: Tuple of formatted status strings for summary and detailed logs. """ - error_msg = f" ... ERRORS\n {message or ''}\n\n\n" - ok_no_changes = " ... OK (no changes)" - ok_msg = f" ... OK\n {message}\n\n\n" if status != 0: - return (" ... ERRORS", error_msg) + return (" Merge Conflict\n", f" Merge Conflict\n {message or ''}\n\n\n") if message is None: - return (ok_no_changes, f"{ok_no_changes}\n\n\n") + return (" Up to date (no changes)\n", " Up to date (no changes)\n\n\n") - return (" ... OK", ok_msg) + return (" Upstream Merge Successful\n", f"{message}\n\n\n") def format_merge_report(merge_report, email_log_level, skip_push_and_pr=False): @@ -102,7 +99,7 @@ def format_merge_report(merge_report, email_log_level, skip_push_and_pr=False): for git_obj, (status, message) in merge_report.items(): min_line, additional_line = format_status(status, message) - layer_name = git_obj.local_repo.split("/")[-1] + layer_name = git_obj.local_repo.split("/")[-1].upper() min_detail += f"{layer_name}\n{min_line}\n" if status != 0: @@ -151,7 +148,7 @@ def format_merge_report(merge_report, email_log_level, skip_push_and_pr=False): if email_log_level == 0: return min_detail + "\n\n" + error_detail - return min_detail + "\n\n" + error_detail + "\n\n" + diff_detail + return min_detail + "\n\n\t\t\t\t\t\t\t\t\tERROR DETAILS\n\n" + error_detail + "\n\n\t\t\t\t\t\t\t\t\tSUMMARY\n\n" + diff_detail def write_log(email_file_name, contents): diff --git a/scripts/dev/upstream_merge/upstream_merge_and_test.py b/scripts/dev/upstream_merge/upstream_merge_and_test.py index 14c60ce73..3fb593b85 100644 --- a/scripts/dev/upstream_merge/upstream_merge_and_test.py +++ b/scripts/dev/upstream_merge/upstream_merge_and_test.py @@ -120,12 +120,12 @@ def merge_submodules_with_upstream( return merge_report -def build_and_test(clean_build, rt_target_IP, build_args): +def build_and_test(clean_build, ssh_connection, build_args): """ Build images and run tests on a VM if there are no merge errors. :param clean_build: Boolean indicating whether to perform a clean build. - :param rt_target_IP: The target IP address of the RT system. + :param ssh_connection: The SSH connection string for the RT system. :param build_args: To build with NI specific arguments. :return: A tuple (status_code, message). Returns (0, None) on success, or error details on failure. @@ -133,14 +133,13 @@ def build_and_test(clean_build, rt_target_IP, build_args): success = setup_env_and_build_packages(build_args, clean_build) if success[0] != 0: return success - success = install_and_test_image(rt_target_IP) + success = install_and_test_image(ssh_connection) return success def push_submodules_and_create_PRs( merge_report, merge_branch_name, - pr_title, pr_description, username ): @@ -153,11 +152,11 @@ def push_submodules_and_create_PRs( :param merge_report: Dictionary mapping GitRepo objects to (status, message). :param merge_branch_name: Name of the branch to push and create PRs from. - :param pr_title: Title for the pull request. :param pr_description: Description for the pull request. :param username: GitHub username owning the downstream fork. :return: Dictionary with push and PR results for each sub-module. """ + current_dir = os.getcwd() push_and_pr_results = {} for git_obj, (status, message) in list(merge_report.items()): if status == 0 and message is not None: @@ -166,10 +165,11 @@ def push_submodules_and_create_PRs( git_obj, merge_branch_name, username, - pr_title, + f"{git_obj.local_repo.split('/')[-1]}: Merge latest upstream", pr_description ) + os.chdir(current_dir) return push_and_pr_results @@ -181,18 +181,20 @@ def get_pr_description(work_item_id): :return: A formatted string containing the PR checklist and work item. """ checklist = ( + "# Testing\n" + "- [x] Built pyrex container\n" "- [x] bitbake packagefeed-ni-core\n" "- [x] bitbake packagegroup-ni-desirable\n" "- [x] bitbake package-index && bitbake nilrt-base-system-image\n" "- [x] Installed BSI on a VM and verified it boots successfully" ) work_item_line = ( - f"\n\nAB#{work_item_id}\n" + f"\n# Justification\nAB#{work_item_id}\n" if work_item_id is not None else "" ) return ( f"Merge latest from upstream. No conflicts." - f"{work_item_line}\n\n{checklist}" + f"{work_item_line}\n\n{checklist}\n@ni/rtos" ) @@ -293,7 +295,7 @@ def main(): else: build_and_test_details = build_and_test( clean_build=skip_merge, - rt_target_IP=json_config_obj.rt_target_IP, + ssh_connection=json_config_obj.ssh_connection, build_args=json_config_obj.build_args, ) @@ -301,11 +303,10 @@ def main(): push_and_pr_results = push_submodules_and_create_PRs( merge_report, json_config_obj.merge_branch_name, - "Automated Merge PR", get_pr_description(json_config_obj.work_item_id), json_config_obj.username, ) - merge_report["Push and pr"] = push_and_pr_results + merge_report["Push and PR"] = push_and_pr_results merge_report["Build and Test"] = build_and_test_details diff --git a/scripts/dev/upstream_merge/utils/build.py b/scripts/dev/upstream_merge/utils/build.py index c7c176f73..b796af751 100644 --- a/scripts/dev/upstream_merge/utils/build.py +++ b/scripts/dev/upstream_merge/utils/build.py @@ -76,7 +76,7 @@ def clean_feeds_and_images(args=""): """ print("\nCleaning build feeds and images...\n") return execute_and_stream_cmd_output( - "bash scripts/pipelines/clean_build.core-feeds_and_core-images.sh " + "bash scripts/pipelines/clean.core-feeds_and_core-images.sh " f"{args}" ) diff --git a/scripts/dev/upstream_merge/utils/git_commands.py b/scripts/dev/upstream_merge/utils/git_commands.py index 8155f3986..fe0270862 100644 --- a/scripts/dev/upstream_merge/utils/git_commands.py +++ b/scripts/dev/upstream_merge/utils/git_commands.py @@ -211,6 +211,7 @@ def git_diff( target="HEAD", compare_with=None, staged=False, + name_only=False, capture_output=True ): """ @@ -218,12 +219,15 @@ def git_diff( :param target: Target commit or branch (default: "HEAD"). :param compare_with: Commit or branch to compare with (optional). :param staged: Whether to show staged changes. + :param name_only: Show only changed file names. :param capture_output: Whether to capture the command output. """ if compare_with: command = f"git diff {target} {compare_with}" else: command = "git diff --staged" if staged else "git diff" + if name_only: + command += " --name-only" return run_command(command, capture_output) diff --git a/scripts/dev/upstream_merge/utils/git_repo.py b/scripts/dev/upstream_merge/utils/git_repo.py index af7e82952..40614b27e 100644 --- a/scripts/dev/upstream_merge/utils/git_repo.py +++ b/scripts/dev/upstream_merge/utils/git_repo.py @@ -144,7 +144,7 @@ def diff( self ): """Check if there are differences in the last merge.""" - return git_diff(compare_with="HEAD~1", capture_output=True) + return git_diff(compare_with="HEAD~1", name_only=True, capture_output=True) def pull( self,