diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 2515f16..550931f 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -162,3 +162,26 @@ jobs: run: | ./scripts/generate_summary.py -c zephyr.yaml >> $GITHUB_STEP_SUMMARY + - id: gcp-auth + if: ${{github.event_name == 'push' && github.ref == 'refs/heads/main'}} + name: GCP Authentcation + uses: google-github-actions/auth@v1 + with: + service_account: ${{ secrets.GCP_SA }} + workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} + cleanup_credentials: true + create_credentials_file: true + export_environment_variables: false + + - name: Set up Cloud SDK + if: ${{github.event_name == 'push' && github.ref == 'refs/heads/main'}} + uses: google-github-actions/setup-gcloud@v1 + env: + GOOGLE_GHA_CREDS_PATH: ${{ steps.gcp-auth.outputs.credentials_file_path }} + with: + version: '>= 363.0.0' + + - name: Upload artifacts to GCP + if: ${{github.event_name == 'push' && github.ref == 'refs/heads/main'}} + run: | + gsutil cp build/result.json gs://zephyr-samples-builder/zephyr/$ZEPHYR_VERSION diff --git a/scripts/build.py b/scripts/build.py index 423f916..dabfdf3 100755 --- a/scripts/build.py +++ b/scripts/build.py @@ -11,6 +11,7 @@ from argparse import ArgumentParser import json import config +import yaml from common import bold, print_frame, create_zip_archive, find_node_size, get_sample_path, calculate_md5, get_versions, zephyr_config_to_list templateLoader = jinja2.FileSystemLoader(searchpath="./") @@ -169,7 +170,29 @@ def try_build_copy_sample(platform: str, sample_name: str, sample_path: str, sam return (return_code, extended_memory) -def main(board_name: str, sample_name: str) -> None: +def get_full_name(yaml_filename): + if os.path.exists(yaml_filename): + with open(yaml_filename) as f: + board_data = yaml.load(f, Loader=yaml.FullLoader) + full_board_name = board_data['name'] + if len(full_board_name) > 50: + full_board_name = re.sub(r'\(.*\)', '', full_board_name) + else: + full_board_name = '' + return full_board_name + + +def get_board_yaml_path(arch, board_name): + board_yaml = f'{config.project_path}/boards/{arch}/{board_name}/{board_name}.yaml' + + # this hack is needed for pinetime_devkit0 + if not os.path.exists(board_yaml): + board_yaml = f'{config.project_path}/boards/{arch}/{board_name}/{board_name.replace("_", "-")}.yaml' + + return board_yaml + + +def main(arch: str, board_name: str, sample_name: str) -> None: """ Main function to build a Zephyr sample for a specific board and create relevant artifacts. @@ -197,6 +220,8 @@ def main(board_name: str, sample_name: str) -> None: elf_name = config.artifact_paths["elf"].format(**format_args) elf_md5_name = config.artifact_paths["elf-md5"].format(**format_args) + platform_full_name = get_full_name(get_board_yaml_path(arch, board_name)) + result = { "platform": board_name, "sample_name": sample_name, @@ -205,6 +230,8 @@ def main(board_name: str, sample_name: str) -> None: "configs": zephyr_config_to_list(config_path) if sample_args is not None else None, "zephyr_sha": get_versions()["zephyr"], "zephyr_sdk": get_versions()["sdk"], + "arch": arch, + "platform_full_name": platform_full_name } # Create JSON with build results @@ -230,6 +257,7 @@ def main(board_name: str, sample_name: str) -> None: if __name__ == "__main__": ap = ArgumentParser() + ap.add_argument("arch") ap.add_argument("board_name") ap.add_argument("sample_name") ap.add_argument("-j", "--job-number") @@ -239,6 +267,7 @@ def main(board_name: str, sample_name: str) -> None: config.load() multijob = args.job_number is not None and args.jobs_total is not None + arch = args.arch board_name = args.board_name sample_name = args.sample_name @@ -246,7 +275,7 @@ def main(board_name: str, sample_name: str) -> None: start_time = time.time() print_frame(f"job {args.job_number} / {args.jobs_total} started") - main(board_name, sample_name) + main(arch, board_name, sample_name) if multijob: total_time = time.time() - start_time diff --git a/scripts/generate_summary.py b/scripts/generate_summary.py index ab3ce61..cbb1b95 100755 --- a/scripts/generate_summary.py +++ b/scripts/generate_summary.py @@ -91,12 +91,42 @@ def process_sample_data(aggregated_jsons: list) -> dict: return sample_dict + +def collective_json_result(aggregated_results: list) -> str: + """ + Process aggregated build result into a single JSON organized by board names. + """ + collective = dict() + for result in aggregated_results: + sample_name = result["sample_name"] + platform = result["platform"] + + if platform not in collective: + collective[platform] = dict( + arch=result["arch"], + name=result["platform_full_name"], + samples=dict()) + + sample_entry = dict( + status="BUILT" if result["success"] else "NOT BUILT", + extended_memory=result["extended_memory"], + ) + + collective[platform]["samples"][sample_name] = sample_entry + + return json.dumps(collective) + def main(): versions = get_versions() summary_data = aggregate_json_files("build/") # Data for markdown table stats = generate_stats(summary_data) + json_res = collective_json_result(summary_data) + + with open('build/result.json', 'w') as res: + res.write(json_res) + sample_data = process_sample_data(summary_data) # Render the table diff --git a/scripts/get_boards_samples_pairs.py b/scripts/get_boards_samples_pairs.py index 1995007..86f9b15 100755 --- a/scripts/get_boards_samples_pairs.py +++ b/scripts/get_boards_samples_pairs.py @@ -13,7 +13,7 @@ def get_boards() -> list: - Supported CPU architecture Returns: - list: A filtered list of Zephyr's board objects. + list: A filtered list of pairs (arch, board). """ # the Zephyr utility has its own argument parsing, so avoid args clash sys.path.append(f"{config.project_path}/scripts") @@ -41,7 +41,7 @@ class Args: omit_board = ("acrn", "qemu", "native", "nsim", "xenvm", "xt-sim") boards_to_run = list(filter(lambda x: all(map(lambda y: y not in x.name, omit_board)), boards_to_run)) - return [board.name for board in boards_to_run] + return [(board.arch, board.name) for board in boards_to_run] def generate_samples() -> None: @@ -51,12 +51,12 @@ def generate_samples() -> None: If sample has defined 'boards' key, only generate the samples for given boards, otherwise generate the sample for all boards """ - all_boards = get_boards() - for board in all_boards: + all_boards_data = get_boards() + for arch, board in all_boards_data: for sample, sample_data in config.samples.items(): sample_boards = sample_data.get("boards", [board]) if board in sample_boards: - print(f"{board} {sample}") + print(f"{arch} {board} {sample}") if __name__ == "__main__": config.load()