From 1a41ba3cf6a11e6a29d591f0069fc8aa2ef561e1 Mon Sep 17 00:00:00 2001 From: Kai Graeper Date: Wed, 12 Nov 2025 11:28:54 +0100 Subject: [PATCH 1/8] update modules to latest mains --- .github/workflows/test_integration.yml | 8 + known_good.json | 58 +++++++ known_good.updated.json | 58 +++++++ score_modules.MODULE.bazel | 53 ++++--- tools/requirements.txt | 1 + tools/update_module_from_known_good.py | 190 ++++++++++++++++++++++ tools/update_module_latest.py | 212 +++++++++++++++++++++++++ 7 files changed, 559 insertions(+), 21 deletions(-) create mode 100644 known_good.json create mode 100644 known_good.updated.json create mode 100644 tools/requirements.txt create mode 100644 tools/update_module_from_known_good.py create mode 100644 tools/update_module_latest.py diff --git a/.github/workflows/test_integration.yml b/.github/workflows/test_integration.yml index 6f4fc00dd..adb3f58ae 100644 --- a/.github/workflows/test_integration.yml +++ b/.github/workflows/test_integration.yml @@ -53,6 +53,14 @@ jobs: repository-cache: true - name: Bazel build targets run: | + echo "::group::get latest commits from main branches" + python3 tools/update_module_latest.py --output known_good.updated.json + cat known_good.updated.json + echo "::endgroup::" + echo "::group::update score_modules.MODULE.bazel" + python3 tools/update_module_from_known_good.py --known known_good.updated.json + cat score_modules.MODULE.bazel + echo "::endgroup::" ./integration_test.sh - name: Show disk space after build if: always() diff --git a/known_good.json b/known_good.json new file mode 100644 index 000000000..1e1cf57cb --- /dev/null +++ b/known_good.json @@ -0,0 +1,58 @@ +{ + "timestamp": "2025-08-13T12:55:10Z", + "modules": [ + { + "name": "score_baselibs", + "version": "0.1.3", + "repo": "https://github.com/eclipse-score/baselibs.git" + }, + { + "name": "score_communication", + "version": "0.1.1", + "repo": "https://github.com/eclipse-score/communication.git" + }, + { + "name": "score_persistency", + "version": "0.2.1", + "repo": "https://github.com/eclipse-score/persistency.git" + }, + { + "name": "score_orchestrator", + "version": "0.0.3", + "repo": "https://github.com/eclipse-score/orchestrator.git" + }, + { + "name": "score_tooling", + "version": "1.0.2", + "repo": "https://github.com/eclipse-score/tooling.git" + }, + { + "name": "score_platform", + "hash": "a9cf44be1342f3c62111de2249eb3132f5ab88da", + "repo": "https://github.com/eclipse-score/score.git" + }, + { + "name": "score_bazel_platforms", + "version": "0.0.2", + "repo": "https://github.com/eclipse-score/bazel_platforms.git" + }, + { + "name": "score_test_scenarios", + "version": "0.3.0", + "repo": "https://github.com/eclipse-score/testing_tools.git" + }, + { + "name": "score_docs_as_code", + "version": "2.0.1", + "repo": "https://github.com/eclipse-score/docs-as-code.git" + }, + { + "name": "score_process", + "version": "1.3.1", + "repo": "https://github.com/eclipse-score/process_description.git" + } + ], + "manifest_sha256": "4c9b7f...", + "suite": "full", + "duration_s": 742 +} \ No newline at end of file diff --git a/known_good.updated.json b/known_good.updated.json new file mode 100644 index 000000000..8fa8093d4 --- /dev/null +++ b/known_good.updated.json @@ -0,0 +1,58 @@ +{ + "timestamp": "2025-11-12T10:56:14Z", + "modules": [ + { + "name": "score_baselibs", + "repo": "https://github.com/eclipse-score/baselibs.git", + "hash": "18badf00dc2210d11ef310049a78644ff3d039a3" + }, + { + "name": "score_communication", + "repo": "https://github.com/eclipse-score/communication.git", + "hash": "ff40e5f1e90ce406b71c664cc6c8e902ab465305" + }, + { + "name": "score_persistency", + "repo": "https://github.com/eclipse-score/persistency.git", + "hash": "7548876ed3e40ec3f3053c57634de68129287e05" + }, + { + "name": "score_orchestrator", + "repo": "https://github.com/eclipse-score/orchestrator.git", + "hash": "7bb94ebae08805ea0a83dcc14f7c17da5ab927e6" + }, + { + "name": "score_tooling", + "repo": "https://github.com/eclipse-score/tooling.git", + "hash": "f36904e8c3d06c0ee761b14877ce7e5f6d3d9edb" + }, + { + "name": "score_platform", + "repo": "https://github.com/eclipse-score/score.git", + "hash": "6e2a756c5c52a6587a3c8da74126523fe1ca9336" + }, + { + "name": "score_bazel_platforms", + "repo": "https://github.com/eclipse-score/bazel_platforms.git", + "hash": "0115193f958e8e592168df1e29cf86174bdba761" + }, + { + "name": "score_test_scenarios", + "repo": "https://github.com/eclipse-score/testing_tools.git", + "hash": "a2f9cded3deb636f5dc800bf7a47131487119721" + }, + { + "name": "score_docs_as_code", + "repo": "https://github.com/eclipse-score/docs-as-code.git", + "hash": "1067fb67782389b50827f8637a74b1027ece52ee" + }, + { + "name": "score_process", + "repo": "https://github.com/eclipse-score/process_description.git", + "hash": "ea78e6d616adf1f13236c31479a31db813086a77" + } + ], + "manifest_sha256": "4c9b7f...", + "suite": "full", + "duration_s": 742 +} diff --git a/score_modules.MODULE.bazel b/score_modules.MODULE.bazel index 5855393ce..dff7b3e44 100644 --- a/score_modules.MODULE.bazel +++ b/score_modules.MODULE.bazel @@ -11,34 +11,42 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* +# Generated from known_good.json at 2025-11-12T10:20:19Z +# Do not edit manually - use tools/update_module_from_known_good.py + bazel_dep(name = "score_baselibs") -single_version_override( +git_override( module_name = "score_baselibs", - version = "0.1.3", + remote = "https://github.com/eclipse-score/baselibs.git", + commit = "edc4f8841c2210d11ef310049a78644ff3d039a3", ) bazel_dep(name = "score_communication") -single_version_override( +git_override( module_name = "score_communication", - version = "0.1.1", + remote = "https://github.com/eclipse-score/communication.git", + commit = "ff40e5f1e90ce406b71c664cc6c8e902ab465305", ) bazel_dep(name = "score_persistency") -single_version_override( +git_override( module_name = "score_persistency", - version = "0.2.1", + remote = "https://github.com/eclipse-score/persistency.git", + commit = "7548876ed3e40ec3f3053c57634de68129287e05", ) bazel_dep(name = "score_orchestrator") -single_version_override( +git_override( module_name = "score_orchestrator", - version = "0.0.3", + remote = "https://github.com/eclipse-score/orchestrator.git", + commit = "7bb94ebae08805ea0a83dcc14f7c17da5ab927e6", ) bazel_dep(name = "score_tooling") -single_version_override( +git_override( module_name = "score_tooling", - version = "1.0.2", + remote = "https://github.com/eclipse-score/tooling.git", + commit = "b3a120a36c7a0e1b82d151732961af3330922e20", ) bazel_dep(name = "score_platform") @@ -48,28 +56,31 @@ single_version_override( ) bazel_dep(name = "score_bazel_platforms") -single_version_override( +git_override( module_name = "score_bazel_platforms", - version = "0.0.2", + remote = "https://github.com/eclipse-score/bazel_platforms.git", + commit = "0115193f958e8e592168df1e29cf86174bdba761", ) bazel_dep(name = "score_test_scenarios") -single_version_override( +git_override( module_name = "score_test_scenarios", - version = "0.3.0", + remote = "https://github.com/eclipse-score/testing_tools.git", + commit = "a2f9cded3deb636f5dc800bf7a47131487119721", ) -bazel_dep(name = "score_docs_as_code", version = "2.0.1") -single_version_override( +bazel_dep(name = "score_docs_as_code") +git_override( module_name = "score_docs_as_code", - version = "2.0.1", + remote = "https://github.com/eclipse-score/docs-as-code.git", + commit = "bb52c96dd98799bdce68c166ad3b826f017f7cf6", ) - -bazel_dep(name = "score_process", version = "1.3.1") -single_version_override( +bazel_dep(name = "score_process") +git_override( module_name = "score_process", - version = "1.3.1", + remote = "https://github.com/eclipse-score/process_description.git", + commit = "ea78e6d616adf1f13236c31479a31db813086a77", ) bazel_dep(name = "score_feo", version = "1.0.2") diff --git a/tools/requirements.txt b/tools/requirements.txt new file mode 100644 index 000000000..1c871cd93 --- /dev/null +++ b/tools/requirements.txt @@ -0,0 +1 @@ +PyGithub>=2.1.1 diff --git a/tools/update_module_from_known_good.py b/tools/update_module_from_known_good.py new file mode 100644 index 000000000..c542344fa --- /dev/null +++ b/tools/update_module_from_known_good.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python3 +""" +Read a known_good.json file and generate a score_modules.MODULE.bazel file +with `bazel_dep` and `git_override` calls for each module in the JSON. + +Usage: + python3 tools/update_module_from_known_good.py \ + --known known_good.json \ + --output score_modules.MODULE.bazel + +The generated score_modules.MODULE.bazel file is included by MODULE.bazel. +""" +import argparse +import json +import os +import re +from datetime import datetime +import logging + + +def load_known_good(path): + """Load and parse the known_good.json file.""" + with open(path, "r", encoding="utf-8") as f: + data = json.load(f) + + # Expect a single JSON object containing a "modules" list; do not support legacy list format. + if isinstance(data, dict) and isinstance(data.get("modules"), list): + return data + raise SystemExit( + f"Invalid known_good.json at {path} (expected object with 'modules' list)" + ) + + +def generate_git_override_blocks(modules, repo_commit_dict): + """Generate bazel_dep and git_override blocks for each module.""" + blocks = [] + + for module in modules: + name = module.get("name") + repo = module.get("repo") + commit = module.get("hash") or module.get("commit") + if not name: + logging.warning("Skipping module with missing name: %s", module) + continue + + # Allow overriding specific repos via command line + if repo in repo_commit_dict: + commit = repo_commit_dict[repo] + + # Check if module has a version, use different logic + version = module.get("version") + + if version: + # If version is provided, use bazel_dep with single_version_override + block = ( + f'bazel_dep(name = "{name}")\n' + 'single_version_override(\n' + f' module_name = "{name}",\n' + f' version = "{version}",\n' + ')\n' + ) + else: + if not repo or not commit: + logging.warning("Skipping module %s with missing repo or commit: repo=%s, commit=%s", name, repo, commit) + continue + + # Validate commit hash format (7-40 hex characters) + if not re.match(r'^[a-fA-F0-9]{7,40}$', commit): + logging.warning("Skipping module %s with invalid commit hash: %s", name, commit) + continue + # If no version, use bazel_dep with git_override + block = ( + f'bazel_dep(name = "{name}")\n' + 'git_override(\n' + f' module_name = "{name}",\n' + f' remote = "{repo}",\n' + f' commit = "{commit}",\n' + ')\n' + ) + + blocks.append(block) + + return blocks + + +def generate_file_content(modules, repo_commit_dict, timestamp=None): + """Generate the complete content for score_modules.MODULE.bazel.""" + # License header assembled with parenthesis grouping (no indentation preserved in output). + header = ( + "# *******************************************************************************\n" + "# Copyright (c) 2025 Contributors to the Eclipse Foundation\n" + "#\n" + "# See the NOTICE file(s) distributed with this work for additional\n" + "# information regarding copyright ownership.\n" + "#\n" + "# This program and the accompanying materials are made available under the\n" + "# terms of the Apache License Version 2.0 which is available at\n" + "# https://www.apache.org/licenses/LICENSE-2.0\n" + "#\n" + "# SPDX-License-Identifier: Apache-2.0\n" + "# *******************************************************************************\n" + "\n" + ) + + if timestamp: + header += ( + f"# Generated from known_good.json at {timestamp}\n" + "# Do not edit manually - use tools/update_module_from_known_good.py\n" + "\n" + ) + + blocks = generate_git_override_blocks(modules, repo_commit_dict) + + if not blocks: + raise SystemExit("No valid modules to generate git_override blocks") + + return header + "\n".join(blocks) + + +def main(): + parser = argparse.ArgumentParser( + description="Generate score_modules.MODULE.bazel from known_good.json" + ) + parser.add_argument( + "--known", + default="known_good.json", + help="Path to known_good.json (default: known_good.json)" + ) + parser.add_argument( + "--output", + default="score_modules.MODULE.bazel", + help="Output file path (default: score_modules.MODULE.bazel)" + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Print generated content instead of writing to file" + ) + parser.add_argument( + "--repo-override", + action="append", + help="Override commit for a specific repo (format: @)" + ) + + args = parser.parse_args() + + known_path = os.path.abspath(args.known) + output_path = os.path.abspath(args.output) + + if not os.path.exists(known_path): + raise SystemExit(f"known_good.json not found at {known_path}") + + # Parse repo overrides + repo_commit_dict = {} + if args.repo_override: + repo_pattern = re.compile(r'https://[a-zA-Z0-9.-]+/[a-zA-Z0-9._/-]+\.git@[a-fA-F0-9]{7,40}$') + for entry in args.repo_override: + if not repo_pattern.match(entry): + raise SystemExit( + f"Invalid --repo-override format: {entry}\n" + "Expected format: https://github.com/org/repo.git@" + ) + repo_url, commit_hash = entry.split("@", 1) + repo_commit_dict[repo_url] = commit_hash + + # Load known_good.json + data = load_known_good(known_path) + modules = data.get("modules") or [] + + if not modules: + raise SystemExit("No modules found in known_good.json") + + # Generate file content + timestamp = data.get("timestamp") or datetime.now().isoformat() + content = generate_file_content(modules, repo_commit_dict, timestamp) + + if args.dry_run: + print(f"Dry run: would write to {output_path}\n") + print("---- BEGIN GENERATED CONTENT ----") + print(content) + print("---- END GENERATED CONTENT ----") + print(f"\nGenerated {len(modules)} git_override entries") + else: + with open(output_path, "w", encoding="utf-8") as f: + f.write(content) + print(f"Generated {output_path} with {len(modules)} git_override entries") + + +if __name__ == "__main__": + main() diff --git a/tools/update_module_latest.py b/tools/update_module_latest.py new file mode 100644 index 000000000..deafc5e01 --- /dev/null +++ b/tools/update_module_latest.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python3 +"""Update module commit hashes to latest on a given branch. + +Reads a known_good.json file containing a list of modules with keys: + name, hash, repo + +For each module's repo (expected to be a GitHub HTTPS URL), queries the GitHub API +for the latest commit hash on the provided branch (default: main) and prints a +summary. Optionally writes out an updated JSON file with refreshed hashes. + +Usage: + python tools/update_module_latest.py \ + --known-good score_reference_integration/known_good.json \ + [--branch main] [--output updated_known_good.json] + +Environment: + Optionally set GITHUB_TOKEN to increase rate limits / access private repos. + +Exit codes: + 0 success + 2 partial failure (at least one repo failed) + 3 fatal failure (e.g., cannot read JSON) +""" + +from __future__ import annotations + +import argparse +import shutil +import subprocess +import datetime as dt +import json +import os +import sys +from dataclasses import dataclass +from urllib.parse import urlparse + +from github import Github, GithubException + + +@dataclass +class Module: + name: str + hash: str + repo: str + version: str | None = None + + @property + def owner_repo(self) -> str: + """Return owner/repo part extracted from HTTPS GitHub URL.""" + # Examples: + # https://github.com/eclipse-score/logging.git -> eclipse-score/logging + parsed = urlparse(self.repo) + if parsed.netloc != "github.com": + raise ValueError(f"Not a GitHub URL: {self.repo}") + + # Extract path, remove leading slash and .git suffix + path = parsed.path.lstrip("/").removesuffix(".git") + + # Split and validate owner/repo format + parts = path.split("/", 2) # Split max 2 times to get owner and repo + if len(parts) < 2 or not parts[0] or not parts[1]: + raise ValueError(f"Cannot parse owner/repo from: {self.repo}") + + return f"{parts[0]}/{parts[1]}" + + +def fetch_latest_commit(owner_repo: str, branch: str, token: str | None) -> str: + """Fetch latest commit sha for given owner_repo & branch using PyGithub.""" + try: + gh = Github(token) if token else Github() + repo = gh.get_repo(owner_repo) + branch_obj = repo.get_branch(branch) + return branch_obj.commit.sha + except GithubException as e: + raise RuntimeError(f"GitHub API error for {owner_repo}:{branch} - {e.status}: {e.data.get('message', str(e))}") from e + except Exception as e: + raise RuntimeError(f"Error fetching {owner_repo}:{branch} - {e}") from e + + +def fetch_latest_commit_gh(owner_repo: str, branch: str) -> str: + """Fetch latest commit using GitHub CLI 'gh' if installed. + + Uses: gh api repos/{owner_repo}/branches/{branch} --jq .commit.sha + Raises RuntimeError on failure. + """ + if not shutil.which("gh"): + raise RuntimeError("'gh' CLI not found in PATH") + cmd = [ + "gh", + "api", + f"repos/{owner_repo}/branches/{branch}", + "--jq", + ".commit.sha", + ] + try: + res = subprocess.run(cmd, check=True, capture_output=True, text=True, timeout=30) + except subprocess.CalledProcessError as e: + raise RuntimeError(f"gh api failed: {e.stderr.strip() or e}") from e + sha = res.stdout.strip() + if not sha: + raise RuntimeError("Empty sha returned by gh") + return sha + + +def load_known_good(path: str) -> dict: + with open(path, "r", encoding="utf-8") as f: + return json.load(f) + + +def write_known_good(path: str, original: dict, modules: list[Module]) -> None: + out = dict(original) # shallow copy + out["timestamp"] = dt.datetime.utcnow().replace(microsecond=0).isoformat() + "Z" + out["modules"] = [] + for m in modules: + mod_dict = {"name": m.name, "repo": m.repo, "hash": m.hash} + out["modules"].append(mod_dict) + with open(path, "w", encoding="utf-8") as f: + json.dump(out, f, indent=2, sort_keys=False) + f.write("\n") + + +def parse_args(argv: list[str]) -> argparse.Namespace: + p = argparse.ArgumentParser(description="Update module hashes to latest commit on branch") + p.add_argument( + "--known-good", + default="known_good.json", + help="Path to known_good.json file (default: known_good.json in CWD)", + ) + p.add_argument("--branch", default="main", help="Git branch to fetch latest commits from (default: main)") + p.add_argument("--output", help="Optional output path to write updated JSON") + p.add_argument("--fail-fast", action="store_true", help="Stop on first failure instead of continuing") + p.add_argument("--no-gh", action="store_true", help="Disable GitHub CLI usage even if installed; fall back to HTTP API; GITHUB_TOKEN has to be known in the environment") + return p.parse_args(argv) + + +def main(argv: list[str]) -> int: + args = parse_args(argv) + try: + data = load_known_good(args.known_good) + except OSError as e: + print(f"ERROR: Cannot read known_good file: {e}", file=sys.stderr) + return 3 + except json.JSONDecodeError as e: + print(f"ERROR: Invalid JSON: {e}", file=sys.stderr) + return 3 + + modules_raw = data.get("modules", []) + modules: list[Module] = [] + for m in modules_raw: + try: + version = m.get("version") + hash_val = m.get("hash", "") + modules.append(Module( + name=m["name"], + hash=hash_val, + repo=m["repo"], + version=version + )) + except KeyError as e: + print(f"WARNING: skipping module missing key {e}: {m}", file=sys.stderr) + if not modules: + print("ERROR: No modules found to update.", file=sys.stderr) + return 3 + + token = os.environ.get("GITHUB_TOKEN") + failures = 0 + updated: list[Module] = [] + # Default: use gh if available unless --no-gh specified + use_gh = (not args.no_gh) and shutil.which("gh") is not None + if not args.no_gh and not use_gh: + print("INFO: 'gh' CLI not found; using direct GitHub API", file=sys.stderr) + if args.no_gh and shutil.which("gh") is not None: + print("INFO: --no-gh specified; ignoring installed 'gh' CLI", file=sys.stderr) + + for mod in modules: + try: + if use_gh: + latest = fetch_latest_commit_gh(mod.owner_repo, args.branch) + else: + latest = fetch_latest_commit(mod.owner_repo, args.branch, token) + updated.append(Module(name=mod.name, hash=latest, repo=mod.repo, version=mod.version)) + + # Display format: if version exists, show "version -> hash", otherwise "hash -> hash" + if mod.version: + print(f"{mod.name}: {mod.version} -> {latest[:8]} (branch {args.branch})") + else: + print(f"{mod.name}: {mod.hash[:8]} -> {latest[:8]} (branch {args.branch})") + except Exception as e: # noqa: BLE001 + failures += 1 + print(f"ERROR {mod.name}: {e}", file=sys.stderr) + if args.fail_fast: + break + # Preserve old hash if continuing + updated.append(mod) + + if args.output and updated: + try: + write_known_good(args.output, data, updated) + print(f"Updated JSON written to {args.output}") + except OSError as e: + print(f"ERROR: Failed writing output file: {e}", file=sys.stderr) + return 3 + + if failures: + print(f"Completed with {failures} failure(s).", file=sys.stderr) + return 2 + return 0 + + +if __name__ == "__main__": # pragma: no cover + sys.exit(main(sys.argv[1:])) + From a2c465526af769d2bc46362ea5f416ca53ed1bfe Mon Sep 17 00:00:00 2001 From: Kai Graeper Date: Thu, 13 Nov 2025 08:34:05 +0100 Subject: [PATCH 2/8] make pyGithub optional --- tools/update_module_latest.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/update_module_latest.py b/tools/update_module_latest.py index deafc5e01..9691e1077 100644 --- a/tools/update_module_latest.py +++ b/tools/update_module_latest.py @@ -34,7 +34,13 @@ from dataclasses import dataclass from urllib.parse import urlparse -from github import Github, GithubException +try: + from github import Github, GithubException + HAS_PYGITHUB = True +except ImportError: + HAS_PYGITHUB = False + Github = None + GithubException = None @dataclass @@ -66,6 +72,8 @@ def owner_repo(self) -> str: def fetch_latest_commit(owner_repo: str, branch: str, token: str | None) -> str: """Fetch latest commit sha for given owner_repo & branch using PyGithub.""" + if not HAS_PYGITHUB: + raise RuntimeError("PyGithub not installed. Install it with: pip install PyGithub") try: gh = Github(token) if token else Github() repo = gh.get_repo(owner_repo) @@ -167,6 +175,13 @@ def main(argv: list[str]) -> int: updated: list[Module] = [] # Default: use gh if available unless --no-gh specified use_gh = (not args.no_gh) and shutil.which("gh") is not None + + # If PyGithub is not available and gh CLI is not available, error out + if not use_gh and not HAS_PYGITHUB: + print("ERROR: Neither 'gh' CLI nor PyGithub library found.", file=sys.stderr) + print("Please install PyGithub (pip install PyGithub) or install GitHub CLI.", file=sys.stderr) + return 3 + if not args.no_gh and not use_gh: print("INFO: 'gh' CLI not found; using direct GitHub API", file=sys.stderr) if args.no_gh and shutil.which("gh") is not None: From 88491b633113d62f3a6adb6ed073a76328002f67 Mon Sep 17 00:00:00 2001 From: Kai Graeper Date: Thu, 13 Nov 2025 08:41:46 +0100 Subject: [PATCH 3/8] add git token to the update --- .github/workflows/test_integration.yml | 6 +++++- integration_test.sh | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_integration.yml b/.github/workflows/test_integration.yml index adb3f58ae..ce8ef8964 100644 --- a/.github/workflows/test_integration.yml +++ b/.github/workflows/test_integration.yml @@ -51,7 +51,7 @@ jobs: disk-cache: ${{ github.workflow }} # Share repository cache between workflows. repository-cache: true - - name: Bazel build targets + - name: Update known good commits run: | echo "::group::get latest commits from main branches" python3 tools/update_module_latest.py --output known_good.updated.json @@ -61,6 +61,10 @@ jobs: python3 tools/update_module_from_known_good.py --known known_good.updated.json cat score_modules.MODULE.bazel echo "::endgroup::" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Bazel build targets + run: | ./integration_test.sh - name: Show disk space after build if: always() diff --git a/integration_test.sh b/integration_test.sh index b35e2492c..9ed642ad4 100755 --- a/integration_test.sh +++ b/integration_test.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -euox pipefail +set -euo pipefail # Integration build script. # Captures warning counts for regression tracking. @@ -52,9 +52,10 @@ for group in "${!BUILD_TARGET_GROUPS[@]}"; do log_file="${LOG_DIR}/${group}.log" # Log build group banner only to stdout/stderr (not into summary table file) echo "--- Building group: ${group} ---" + start_ts=$(date +%s) + echo "bazel build --config "${CONFIG}" ${targets} --verbose_failures" # GitHub Actions log grouping start echo "::group::Bazel build (${group})" - start_ts=$(date +%s) set +e bazel build --config "${CONFIG}" ${targets} --verbose_failures 2>&1 | tee "$log_file" build_status=${PIPESTATUS[0]} From 9f131e4b35ebaf82e22ae434c8585b775896cca4 Mon Sep 17 00:00:00 2001 From: Kai Graeper Date: Thu, 13 Nov 2025 08:45:13 +0100 Subject: [PATCH 4/8] com has no score prefix on main, add wait_free_stack_fix --- .bazelrc | 2 +- MODULE.bazel | 10 +++++----- README.md | 2 +- integration_test.sh | 2 +- known_good.json | 7 +++++-- known_good.updated.json | 11 +++++++---- score_modules.MODULE.bazel | 14 +++++++++----- tools/update_module_from_known_good.py | 11 +++++++++++ tools/update_module_latest.py | 9 +++++++-- wait_free_stack_fix.patch | 11 +++++++++++ 10 files changed, 58 insertions(+), 21 deletions(-) create mode 100644 wait_free_stack_fix.patch diff --git a/.bazelrc b/.bazelrc index 1b1902509..d2f996174 100644 --- a/.bazelrc +++ b/.bazelrc @@ -20,7 +20,7 @@ common --registry=https://bcr.bazel.build build --@score_baselibs//score/mw/log/detail/flags:KUse_Stub_Implementation_Only=False build --@score_baselibs//score/mw/log/flags:KRemote_Logging=False build --@score_baselibs//score/json:base_library=nlohmann -build --@score_communication//score/mw/com/flags:tracing_library=stub +build --@communication//score/mw/com/flags:tracing_library=stub # stop legacy behavior of creating __init__.py files build --incompatible_default_to_explicit_init_py diff --git a/MODULE.bazel b/MODULE.bazel index 8f2fb7e02..e4cbb5396 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -47,11 +47,11 @@ use_repo(pip, "pip_score_venv_test") # communication module dependencies # archive_override are not forwarded by bazel_dep, so we need to redefine it here -archive_override( - module_name = "rules_boost", - strip_prefix = "rules_boost-master", - urls = ["https://github.com/nelhage/rules_boost/archive/refs/heads/master.tar.gz"], -) +# archive_override( +# module_name = "rules_boost", +# strip_prefix = "rules_boost-master", +# urls = ["https://github.com/nelhage/rules_boost/archive/refs/heads/master.tar.gz"], +# ) # git_override are not forwarded by bazel_dep, so we need to redefine it here git_override( diff --git a/README.md b/README.md index ca07fd6ef..f56b3abeb 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ bazel build --config bl-x86_64-linux @score_baselibs//score/... --verbose_failur ### Communication ```bash -bazel build --config bl-x86_64-linux @score_communication//score/mw/com:com --verbose_failures +bazel build --config bl-x86_64-linux @communication//score/mw/com:com --verbose_failures ``` ### Persistency diff --git a/integration_test.sh b/integration_test.sh index 9ed642ad4..7358bbcfc 100755 --- a/integration_test.sh +++ b/integration_test.sh @@ -11,7 +11,7 @@ mkdir -p "${LOG_DIR}" || true declare -A BUILD_TARGET_GROUPS=( [baselibs]="@score_baselibs//score/..." - [score_communication]="@score_communication//score/mw/com:com" + [communication]="@communication//score/mw/com:com" [persistency]="@score_persistency//src/cpp/src/... @score_persistency//src/rust/..." #[score_logging]="@score_logging//src/..." [score_orchestrator]="@score_orchestrator//src/..." diff --git a/known_good.json b/known_good.json index 1e1cf57cb..7fb160fc2 100644 --- a/known_good.json +++ b/known_good.json @@ -4,10 +4,13 @@ { "name": "score_baselibs", "version": "0.1.3", - "repo": "https://github.com/eclipse-score/baselibs.git" + "repo": "https://github.com/eclipse-score/baselibs.git", + "patches": [ + "//:wait_free_stack_fix.patch" + ] }, { - "name": "score_communication", + "name": "communication", "version": "0.1.1", "repo": "https://github.com/eclipse-score/communication.git" }, diff --git a/known_good.updated.json b/known_good.updated.json index 8fa8093d4..7d230687e 100644 --- a/known_good.updated.json +++ b/known_good.updated.json @@ -1,13 +1,16 @@ { - "timestamp": "2025-11-12T10:56:14Z", + "timestamp": "2025-11-13T08:26:11Z", "modules": [ { "name": "score_baselibs", "repo": "https://github.com/eclipse-score/baselibs.git", - "hash": "18badf00dc2210d11ef310049a78644ff3d039a3" + "hash": "edc4f8841c2210d11ef310049a78644ff3d039a3", + "patches": [ + "//:wait_free_stack_fix.patch" + ] }, { - "name": "score_communication", + "name": "communication", "repo": "https://github.com/eclipse-score/communication.git", "hash": "ff40e5f1e90ce406b71c664cc6c8e902ab465305" }, @@ -29,7 +32,7 @@ { "name": "score_platform", "repo": "https://github.com/eclipse-score/score.git", - "hash": "6e2a756c5c52a6587a3c8da74126523fe1ca9336" + "hash": "4277c625daca11ef1fe16ffe7670498b354baa72" }, { "name": "score_bazel_platforms", diff --git a/score_modules.MODULE.bazel b/score_modules.MODULE.bazel index dff7b3e44..266c4975e 100644 --- a/score_modules.MODULE.bazel +++ b/score_modules.MODULE.bazel @@ -11,7 +11,7 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -# Generated from known_good.json at 2025-11-12T10:20:19Z +# Generated from known_good.json at 2025-11-13T08:26:11Z # Do not edit manually - use tools/update_module_from_known_good.py bazel_dep(name = "score_baselibs") @@ -19,11 +19,15 @@ git_override( module_name = "score_baselibs", remote = "https://github.com/eclipse-score/baselibs.git", commit = "edc4f8841c2210d11ef310049a78644ff3d039a3", + patches = [ + "//:wait_free_stack_fix.patch", + ], + patch_strip = 1, ) -bazel_dep(name = "score_communication") +bazel_dep(name = "communication") git_override( - module_name = "score_communication", + module_name = "communication", remote = "https://github.com/eclipse-score/communication.git", commit = "ff40e5f1e90ce406b71c664cc6c8e902ab465305", ) @@ -46,7 +50,7 @@ bazel_dep(name = "score_tooling") git_override( module_name = "score_tooling", remote = "https://github.com/eclipse-score/tooling.git", - commit = "b3a120a36c7a0e1b82d151732961af3330922e20", + commit = "f36904e8c3d06c0ee761b14877ce7e5f6d3d9edb", ) bazel_dep(name = "score_platform") @@ -73,7 +77,7 @@ bazel_dep(name = "score_docs_as_code") git_override( module_name = "score_docs_as_code", remote = "https://github.com/eclipse-score/docs-as-code.git", - commit = "bb52c96dd98799bdce68c166ad3b826f017f7cf6", + commit = "1067fb67782389b50827f8637a74b1027ece52ee", ) bazel_dep(name = "score_process") diff --git a/tools/update_module_from_known_good.py b/tools/update_module_from_known_good.py index c542344fa..dc70a2032 100644 --- a/tools/update_module_from_known_good.py +++ b/tools/update_module_from_known_good.py @@ -39,6 +39,7 @@ def generate_git_override_blocks(modules, repo_commit_dict): name = module.get("name") repo = module.get("repo") commit = module.get("hash") or module.get("commit") + patches = module.get("patches", []) if not name: logging.warning("Skipping module with missing name: %s", module) continue @@ -49,6 +50,12 @@ def generate_git_override_blocks(modules, repo_commit_dict): # Check if module has a version, use different logic version = module.get("version") + patches_lines = "" + if patches: + patches_lines = " patches = [\n" + for patch in patches: + patches_lines += f' "{patch}",\n' + patches_lines += " ],\n patch_strip = 1,\n" if version: # If version is provided, use bazel_dep with single_version_override @@ -57,6 +64,7 @@ def generate_git_override_blocks(modules, repo_commit_dict): 'single_version_override(\n' f' module_name = "{name}",\n' f' version = "{version}",\n' + f'{patches_lines}' ')\n' ) else: @@ -68,13 +76,16 @@ def generate_git_override_blocks(modules, repo_commit_dict): if not re.match(r'^[a-fA-F0-9]{7,40}$', commit): logging.warning("Skipping module %s with invalid commit hash: %s", name, commit) continue + # If no version, use bazel_dep with git_override + block = ( f'bazel_dep(name = "{name}")\n' 'git_override(\n' f' module_name = "{name}",\n' f' remote = "{repo}",\n' f' commit = "{commit}",\n' + f'{patches_lines}' ')\n' ) diff --git a/tools/update_module_latest.py b/tools/update_module_latest.py index 9691e1077..2a025b06a 100644 --- a/tools/update_module_latest.py +++ b/tools/update_module_latest.py @@ -49,6 +49,7 @@ class Module: hash: str repo: str version: str | None = None + patches: list[str] | None = None @property def owner_repo(self) -> str: @@ -121,6 +122,8 @@ def write_known_good(path: str, original: dict, modules: list[Module]) -> None: out["modules"] = [] for m in modules: mod_dict = {"name": m.name, "repo": m.repo, "hash": m.hash} + if m.patches: + mod_dict["patches"] = m.patches out["modules"].append(mod_dict) with open(path, "w", encoding="utf-8") as f: json.dump(out, f, indent=2, sort_keys=False) @@ -158,11 +161,13 @@ def main(argv: list[str]) -> int: try: version = m.get("version") hash_val = m.get("hash", "") + patches = m.get("patches") modules.append(Module( name=m["name"], hash=hash_val, repo=m["repo"], - version=version + version=version, + patches=patches )) except KeyError as e: print(f"WARNING: skipping module missing key {e}: {m}", file=sys.stderr) @@ -193,7 +198,7 @@ def main(argv: list[str]) -> int: latest = fetch_latest_commit_gh(mod.owner_repo, args.branch) else: latest = fetch_latest_commit(mod.owner_repo, args.branch, token) - updated.append(Module(name=mod.name, hash=latest, repo=mod.repo, version=mod.version)) + updated.append(Module(name=mod.name, hash=latest, repo=mod.repo, version=mod.version, patches=mod.patches)) # Display format: if version exists, show "version -> hash", otherwise "hash -> hash" if mod.version: diff --git a/wait_free_stack_fix.patch b/wait_free_stack_fix.patch new file mode 100644 index 000000000..e44ae447a --- /dev/null +++ b/wait_free_stack_fix.patch @@ -0,0 +1,11 @@ +diff --git a/score/mw/log/BUILD b/score/mw/log/BUILD +--- a/score/mw/log/BUILD ++++ b/score/mw/log/BUILD +@@ -25,6 +25,7 @@ cc_library( + visibility = ["//visibility:public"], + deps = [ + ":frontend", ++ "//score/mw/log/detail/wait_free_stack:wait_free_stack", + ] + select({ + "@score_baselibs//score/mw/log/detail/flags:config_KUse_Stub_Implementation_Only": [ + "@score_baselibs//score/mw/log/detail:recorder_factory_stub", \ No newline at end of file From d2093a2fff7c48589ed9cf1b79fe71ae4d7e07a1 Mon Sep 17 00:00:00 2001 From: Kai Graeper Date: Thu, 13 Nov 2025 13:11:10 +0100 Subject: [PATCH 5/8] display git hash in the summary --- integration_test.sh | 88 +++++++++++++++++--- known_good.json | 34 +++----- known_good.updated.json | 108 +++++++++++-------------- tools/get_module_info.py | 73 +++++++++++++++++ tools/update_module_from_known_good.py | 16 ++-- tools/update_module_latest.py | 22 ++--- 6 files changed, 230 insertions(+), 111 deletions(-) create mode 100644 tools/get_module_info.py diff --git a/integration_test.sh b/integration_test.sh index 7358bbcfc..58eb02487 100755 --- a/integration_test.sh +++ b/integration_test.sh @@ -3,16 +3,70 @@ set -euo pipefail # Integration build script. # Captures warning counts for regression tracking. +# +# Usage: ./integration_test.sh [--known-good ] +# --known-good: Optional path to known_good.json file CONFIG=${CONFIG:-bl-x86_64-linux} LOG_DIR=${LOG_DIR:-_logs/logs} SUMMARY_FILE=${SUMMARY_FILE:-_logs/build_summary.md} +KNOWN_GOOD_FILE="" + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --known-good) + KNOWN_GOOD_FILE="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + echo "Usage: $0 [--known-good ]" + exit 1 + ;; + esac +done + mkdir -p "${LOG_DIR}" || true +# Function to extract commit hash from known_good.json +get_commit_hash() { + local module_name=$1 + local known_good_file=$2 + + if [[ -z "${known_good_file}" ]] || [[ ! -f "${known_good_file}" ]]; then + echo "N/A" + return + fi + + # Get the script directory + local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + + # Use the Python script to extract module info + python3 "${script_dir}/tools/get_module_info.py" "${known_good_file}" "${module_name}" "hash" 2>/dev/null || echo "N/A" +} + +# Function to extract repo URL from known_good.json +get_module_repo() { + local module_name=$1 + local known_good_file=$2 + + if [[ -z "${known_good_file}" ]] || [[ ! -f "${known_good_file}" ]]; then + echo "N/A" + return + fi + + # Get the script directory + local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + + # Use the Python script to extract module repo + python3 "${script_dir}/tools/get_module_info.py" "${known_good_file}" "${module_name}" "repo" 2>/dev/null || echo "N/A" +} + declare -A BUILD_TARGET_GROUPS=( - [baselibs]="@score_baselibs//score/..." + [score_baselibs]="@score_baselibs//score/..." [communication]="@communication//score/mw/com:com" - [persistency]="@score_persistency//src/cpp/src/... @score_persistency//src/rust/..." + [score_persistency]="@score_persistency//src/cpp/src/... @score_persistency//src/rust/..." #[score_logging]="@score_logging//src/..." [score_orchestrator]="@score_orchestrator//src/..." [score_test_scenarios]="@score_test_scenarios//..." @@ -35,13 +89,16 @@ timestamp() { date '+%Y-%m-%d %H:%M:%S'; } echo "=== Integration Build Started $(timestamp) ===" | tee "${SUMMARY_FILE}" echo "Config: ${CONFIG}" | tee -a "${SUMMARY_FILE}" +if [[ -n "${KNOWN_GOOD_FILE}" ]]; then + echo "Known Good File: ${KNOWN_GOOD_FILE}" | tee -a "${SUMMARY_FILE}" +fi echo "" >> "${SUMMARY_FILE}" echo "## Build Groups Summary" >> "${SUMMARY_FILE}" echo "" >> "${SUMMARY_FILE}" # Markdown table header { - echo "| Group | Status | Duration (s) | Warnings | Deprecated refs |"; - echo "|-------|--------|--------------|----------|-----------------|"; + echo "| Group | Status | Duration (s) | Warnings | Deprecated refs | Commit/Version |"; + echo "|-------|--------|--------------|----------|-----------------|----------------|"; } >> "${SUMMARY_FILE}" overall_warn_total=0 @@ -50,6 +107,7 @@ overall_depr_total=0 for group in "${!BUILD_TARGET_GROUPS[@]}"; do targets="${BUILD_TARGET_GROUPS[$group]}" log_file="${LOG_DIR}/${group}.log" + # Log build group banner only to stdout/stderr (not into summary table file) echo "--- Building group: ${group} ---" start_ts=$(date +%s) @@ -73,16 +131,24 @@ for group in "${!BUILD_TARGET_GROUPS[@]}"; do else status_symbol="❌(${build_status})" fi - echo "| ${group} | ${status_symbol} | ${duration} | ${w_count} | ${d_count} |" | tee -a "${SUMMARY_FILE}" + + # Get commit hash/version for this group (group name is the module name) + commit_hash=$(get_commit_hash "${group}" "${KNOWN_GOOD_FILE}") + repo=$(get_module_repo "${group}" "${KNOWN_GOOD_FILE}") + + # Truncate commit hash for display (first 8 chars) + if [[ "${commit_hash}" != "N/A" ]] && [[ ${#commit_hash} -gt 8 ]]; then + commit_hash_display="${commit_hash:0:8}" + else + commit_hash_display="${commit_hash}" + fi + + echo "| ${group} | ${status_symbol} | ${duration} | ${w_count} | ${d_count} | [${commit_hash_display}](${repo}/tree/${commit_hash}) |" | tee -a "${SUMMARY_FILE}" done # Append aggregate totals row to summary table -echo "| TOTAL | | | ${overall_warn_total} | ${overall_depr_total} |" >> "${SUMMARY_FILE}" - -# Display the full build summary explicitly at the end +echo "| TOTAL | | | ${overall_warn_total} | ${overall_depr_total} | |" >> "${SUMMARY_FILE}"# Display the full build summary explicitly at the end echo '::group::Build Summary' echo '=== Build Summary (echo) ===' cat "${SUMMARY_FILE}" || echo "(Could not read summary file ${SUMMARY_FILE})" -echo '::endgroup::' - -exit 0 \ No newline at end of file +echo '::endgroup::' \ No newline at end of file diff --git a/known_good.json b/known_good.json index 7fb160fc2..fd906d521 100644 --- a/known_good.json +++ b/known_good.json @@ -1,60 +1,50 @@ { "timestamp": "2025-08-13T12:55:10Z", - "modules": [ - { - "name": "score_baselibs", + "modules": { + "score_baselibs": { "version": "0.1.3", "repo": "https://github.com/eclipse-score/baselibs.git", "patches": [ "//:wait_free_stack_fix.patch" ] }, - { - "name": "communication", + "communication": { "version": "0.1.1", "repo": "https://github.com/eclipse-score/communication.git" }, - { - "name": "score_persistency", + "score_persistency": { "version": "0.2.1", "repo": "https://github.com/eclipse-score/persistency.git" }, - { - "name": "score_orchestrator", + "score_orchestrator": { "version": "0.0.3", "repo": "https://github.com/eclipse-score/orchestrator.git" }, - { - "name": "score_tooling", + "score_tooling": { "version": "1.0.2", "repo": "https://github.com/eclipse-score/tooling.git" }, - { - "name": "score_platform", + "score_platform": { "hash": "a9cf44be1342f3c62111de2249eb3132f5ab88da", "repo": "https://github.com/eclipse-score/score.git" }, - { - "name": "score_bazel_platforms", + "score_bazel_platforms": { "version": "0.0.2", "repo": "https://github.com/eclipse-score/bazel_platforms.git" }, - { - "name": "score_test_scenarios", + "score_test_scenarios": { "version": "0.3.0", "repo": "https://github.com/eclipse-score/testing_tools.git" }, - { - "name": "score_docs_as_code", + "score_docs_as_code": { "version": "2.0.1", "repo": "https://github.com/eclipse-score/docs-as-code.git" }, - { - "name": "score_process", + "score_process": { "version": "1.3.1", "repo": "https://github.com/eclipse-score/process_description.git" } - ], + }, "manifest_sha256": "4c9b7f...", "suite": "full", "duration_s": 742 diff --git a/known_good.updated.json b/known_good.updated.json index 7d230687e..5165a69df 100644 --- a/known_good.updated.json +++ b/known_good.updated.json @@ -1,61 +1,51 @@ { - "timestamp": "2025-11-13T08:26:11Z", - "modules": [ - { - "name": "score_baselibs", - "repo": "https://github.com/eclipse-score/baselibs.git", - "hash": "edc4f8841c2210d11ef310049a78644ff3d039a3", - "patches": [ - "//:wait_free_stack_fix.patch" - ] - }, - { - "name": "communication", - "repo": "https://github.com/eclipse-score/communication.git", - "hash": "ff40e5f1e90ce406b71c664cc6c8e902ab465305" - }, - { - "name": "score_persistency", - "repo": "https://github.com/eclipse-score/persistency.git", - "hash": "7548876ed3e40ec3f3053c57634de68129287e05" - }, - { - "name": "score_orchestrator", - "repo": "https://github.com/eclipse-score/orchestrator.git", - "hash": "7bb94ebae08805ea0a83dcc14f7c17da5ab927e6" - }, - { - "name": "score_tooling", - "repo": "https://github.com/eclipse-score/tooling.git", - "hash": "f36904e8c3d06c0ee761b14877ce7e5f6d3d9edb" - }, - { - "name": "score_platform", - "repo": "https://github.com/eclipse-score/score.git", - "hash": "4277c625daca11ef1fe16ffe7670498b354baa72" - }, - { - "name": "score_bazel_platforms", - "repo": "https://github.com/eclipse-score/bazel_platforms.git", - "hash": "0115193f958e8e592168df1e29cf86174bdba761" - }, - { - "name": "score_test_scenarios", - "repo": "https://github.com/eclipse-score/testing_tools.git", - "hash": "a2f9cded3deb636f5dc800bf7a47131487119721" - }, - { - "name": "score_docs_as_code", - "repo": "https://github.com/eclipse-score/docs-as-code.git", - "hash": "1067fb67782389b50827f8637a74b1027ece52ee" - }, - { - "name": "score_process", - "repo": "https://github.com/eclipse-score/process_description.git", - "hash": "ea78e6d616adf1f13236c31479a31db813086a77" - } - ], - "manifest_sha256": "4c9b7f...", - "suite": "full", - "duration_s": 742 + "timestamp": "2025-11-13T10:12:42Z", + "modules": { + "score_baselibs": { + "repo": "https://github.com/eclipse-score/baselibs.git", + "hash": "edc4f8841c2210d11ef310049a78644ff3d039a3", + "patches": [ + "//:wait_free_stack_fix.patch" + ] + }, + "communication": { + "repo": "https://github.com/eclipse-score/communication.git", + "hash": "ff40e5f1e90ce406b71c664cc6c8e902ab465305" + }, + "score_persistency": { + "repo": "https://github.com/eclipse-score/persistency.git", + "hash": "7548876ed3e40ec3f3053c57634de68129287e05" + }, + "score_orchestrator": { + "repo": "https://github.com/eclipse-score/orchestrator.git", + "hash": "7bb94ebae08805ea0a83dcc14f7c17da5ab927e6" + }, + "score_tooling": { + "repo": "https://github.com/eclipse-score/tooling.git", + "hash": "654664dae7df2700fd5840c5ed6c07ac6c61705d" + }, + "score_platform": { + "repo": "https://github.com/eclipse-score/score.git", + "hash": "4277c625daca11ef1fe16ffe7670498b354baa72" + }, + "score_bazel_platforms": { + "repo": "https://github.com/eclipse-score/bazel_platforms.git", + "hash": "0115193f958e8e592168df1e29cf86174bdba761" + }, + "score_test_scenarios": { + "repo": "https://github.com/eclipse-score/testing_tools.git", + "hash": "a2f9cded3deb636f5dc800bf7a47131487119721" + }, + "score_docs_as_code": { + "repo": "https://github.com/eclipse-score/docs-as-code.git", + "hash": "1067fb67782389b50827f8637a74b1027ece52ee" + }, + "score_process": { + "repo": "https://github.com/eclipse-score/process_description.git", + "hash": "e62e4c30808436e790590845f6c297cf605d7649" + } + }, + "manifest_sha256": "4c9b7f...", + "suite": "full", + "duration_s": 742 } diff --git a/tools/get_module_info.py b/tools/get_module_info.py new file mode 100644 index 000000000..a9fb3d285 --- /dev/null +++ b/tools/get_module_info.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +"""Extract module information from known_good.json.""" + +import json +import sys + + +def load_module_data(known_good_file, module_name): + """ + Load module data from known_good.json. + + Args: + known_good_file: Path to the known_good.json file + module_name: Name of the module to look up + + Returns: + Dictionary with module data, or empty dict if not found + """ + try: + with open(known_good_file, 'r') as f: + data = json.load(f) + modules = data.get('modules', {}) + return modules.get(module_name, {}) + except Exception: + return {} + + +def get_module_field(module_data, field='hash'): + """ + Extract a specific field from module data. + + Args: + module_data: Dictionary with module information + field: Field to extract ('hash', 'version', 'repo', or 'all') + + Returns: + Requested field value, or 'N/A' if not found + For 'hash': truncated to 8 chars if longer + For 'all': returns hash/version (prefers hash, falls back to version) + """ + if not module_data: + return 'N/A' + + if field == 'repo': + repo = module_data.get('repo', 'N/A') + # Remove .git suffix if present + if repo.endswith('.git'): + repo = repo[:-4] + return repo + elif field == 'version': + return module_data.get('version', 'N/A') + elif field == 'hash': + hash_val = module_data.get('hash', 'N/A') + return hash_val + else: # field == 'all' or default + hash_val = module_data.get('hash', module_data.get('version', 'N/A')) + return hash_val + + +if __name__ == '__main__': + if len(sys.argv) < 3 or len(sys.argv) > 4: + print('Usage: get_module_info.py [field]') + print(' field: hash (default), version, repo, or all') + print('N/A') + sys.exit(1) + + known_good_file = sys.argv[1] + module_name = sys.argv[2] + field = sys.argv[3] if len(sys.argv) == 4 else 'all' + + module_data = load_module_data(known_good_file, module_name) + result = get_module_field(module_data, field) + print(result) diff --git a/tools/update_module_from_known_good.py b/tools/update_module_from_known_good.py index dc70a2032..e05ab1a12 100644 --- a/tools/update_module_from_known_good.py +++ b/tools/update_module_from_known_good.py @@ -23,26 +23,22 @@ def load_known_good(path): with open(path, "r", encoding="utf-8") as f: data = json.load(f) - # Expect a single JSON object containing a "modules" list; do not support legacy list format. - if isinstance(data, dict) and isinstance(data.get("modules"), list): + # Expect a single JSON object containing a "modules" dict/object + if isinstance(data, dict) and isinstance(data.get("modules"), dict): return data raise SystemExit( - f"Invalid known_good.json at {path} (expected object with 'modules' list)" + f"Invalid known_good.json at {path} (expected object with 'modules' dict)" ) -def generate_git_override_blocks(modules, repo_commit_dict): +def generate_git_override_blocks(modules_dict, repo_commit_dict): """Generate bazel_dep and git_override blocks for each module.""" blocks = [] - for module in modules: - name = module.get("name") + for name, module in modules_dict.items(): repo = module.get("repo") commit = module.get("hash") or module.get("commit") patches = module.get("patches", []) - if not name: - logging.warning("Skipping module with missing name: %s", module) - continue # Allow overriding specific repos via command line if repo in repo_commit_dict: @@ -176,7 +172,7 @@ def main(): # Load known_good.json data = load_known_good(known_path) - modules = data.get("modules") or [] + modules = data.get("modules") or {} if not modules: raise SystemExit("No modules found in known_good.json") diff --git a/tools/update_module_latest.py b/tools/update_module_latest.py index 2a025b06a..e4e498e16 100644 --- a/tools/update_module_latest.py +++ b/tools/update_module_latest.py @@ -119,14 +119,14 @@ def load_known_good(path: str) -> dict: def write_known_good(path: str, original: dict, modules: list[Module]) -> None: out = dict(original) # shallow copy out["timestamp"] = dt.datetime.utcnow().replace(microsecond=0).isoformat() + "Z" - out["modules"] = [] + out["modules"] = {} for m in modules: - mod_dict = {"name": m.name, "repo": m.repo, "hash": m.hash} + mod_dict = {"repo": m.repo, "hash": m.hash} if m.patches: mod_dict["patches"] = m.patches - out["modules"].append(mod_dict) + out["modules"][m.name] = mod_dict with open(path, "w", encoding="utf-8") as f: - json.dump(out, f, indent=2, sort_keys=False) + json.dump(out, f, indent=4, sort_keys=False) f.write("\n") @@ -155,22 +155,26 @@ def main(argv: list[str]) -> int: print(f"ERROR: Invalid JSON: {e}", file=sys.stderr) return 3 - modules_raw = data.get("modules", []) + modules_raw = data.get("modules", {}) modules: list[Module] = [] - for m in modules_raw: + for name, m in modules_raw.items(): try: version = m.get("version") hash_val = m.get("hash", "") patches = m.get("patches") + repo = m.get("repo") + if not repo: + print(f"WARNING: skipping module {name} with missing repo", file=sys.stderr) + continue modules.append(Module( - name=m["name"], + name=name, hash=hash_val, - repo=m["repo"], + repo=repo, version=version, patches=patches )) except KeyError as e: - print(f"WARNING: skipping module missing key {e}: {m}", file=sys.stderr) + print(f"WARNING: skipping module {name} missing key {e}: {m}", file=sys.stderr) if not modules: print("ERROR: No modules found to update.", file=sys.stderr) return 3 From 7f9011bdfee1175443ae28c2e8a28bc9b972b296 Mon Sep 17 00:00:00 2001 From: Kai Graeper Date: Thu, 13 Nov 2025 13:20:56 +0100 Subject: [PATCH 6/8] fix display --- .github/workflows/test_integration.yml | 2 +- integration_test.sh | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_integration.yml b/.github/workflows/test_integration.yml index ce8ef8964..4398cf0a2 100644 --- a/.github/workflows/test_integration.yml +++ b/.github/workflows/test_integration.yml @@ -65,7 +65,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Bazel build targets run: | - ./integration_test.sh + ./integration_test.sh --known-good known_good.updated.json - name: Show disk space after build if: always() run: | diff --git a/integration_test.sh b/integration_test.sh index 58eb02487..5bed74bad 100755 --- a/integration_test.sh +++ b/integration_test.sh @@ -143,7 +143,14 @@ for group in "${!BUILD_TARGET_GROUPS[@]}"; do commit_hash_display="${commit_hash}" fi - echo "| ${group} | ${status_symbol} | ${duration} | ${w_count} | ${d_count} | [${commit_hash_display}](${repo}/tree/${commit_hash}) |" | tee -a "${SUMMARY_FILE}" + # Only add link if KNOWN_GOOD_FILE is set + if [[ -n "${KNOWN_GOOD_FILE}" ]]; then + commit_version_cell="[${commit_hash_display}](${repo}/tree/${commit_hash})" + else + commit_version_cell="${commit_hash_display}" + fi + + echo "| ${group} | ${status_symbol} | ${duration} | ${w_count} | ${d_count} | ${commit_version_cell} |" | tee -a "${SUMMARY_FILE}" done # Append aggregate totals row to summary table From 22dd5aaa808e3bea314ddb67fa7ffbf3d5f2ca76 Mon Sep 17 00:00:00 2001 From: Kai Graeper Date: Mon, 17 Nov 2025 10:21:05 +0100 Subject: [PATCH 7/8] add typing --- .github/workflows/test_integration.yml | 2 +- integration_test.sh | 14 +++++++++++++- tools/get_module_info.py | 5 +++-- tools/update_module_from_known_good.py | 9 +++++---- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test_integration.yml b/.github/workflows/test_integration.yml index 4398cf0a2..b06b89346 100644 --- a/.github/workflows/test_integration.yml +++ b/.github/workflows/test_integration.yml @@ -14,7 +14,7 @@ # Workflow configuration for S-CORE CI - Bazel Build & Test baselibs # This workflow runs Bazel build and test when triggered by specific pull request events. -name: Bazel Build some repositories +name: build latest mains on: workflow_dispatch: push: diff --git a/integration_test.sh b/integration_test.sh index 5bed74bad..b59f7f040 100755 --- a/integration_test.sh +++ b/integration_test.sh @@ -104,6 +104,9 @@ echo "" >> "${SUMMARY_FILE}" overall_warn_total=0 overall_depr_total=0 +# Track if any build group failed +any_failed=0 + for group in "${!BUILD_TARGET_GROUPS[@]}"; do targets="${BUILD_TARGET_GROUPS[$group]}" log_file="${LOG_DIR}/${group}.log" @@ -117,6 +120,10 @@ for group in "${!BUILD_TARGET_GROUPS[@]}"; do set +e bazel build --config "${CONFIG}" ${targets} --verbose_failures 2>&1 | tee "$log_file" build_status=${PIPESTATUS[0]} + # Track if any build group failed + if [[ ${build_status} -ne 0 ]]; then + any_failed=1 + fi set -e echo "::endgroup::" # End Bazel build group end_ts=$(date +%s) @@ -158,4 +165,9 @@ echo "| TOTAL | | | ${overall_warn_total} | ${overall_depr_total} | |" >> "${ echo '::group::Build Summary' echo '=== Build Summary (echo) ===' cat "${SUMMARY_FILE}" || echo "(Could not read summary file ${SUMMARY_FILE})" -echo '::endgroup::' \ No newline at end of file +echo '::endgroup::' + +# Report to GitHub Actions if any build group failed +if [[ ${any_failed} -eq 1 ]]; then + echo "::error::One or more build groups failed. See summary above." +fi diff --git a/tools/get_module_info.py b/tools/get_module_info.py index a9fb3d285..ac463ef1f 100644 --- a/tools/get_module_info.py +++ b/tools/get_module_info.py @@ -3,9 +3,10 @@ import json import sys +from typing import Dict, Any -def load_module_data(known_good_file, module_name): +def load_module_data(known_good_file: str, module_name: str) -> Dict[str, Any]: """ Load module data from known_good.json. @@ -25,7 +26,7 @@ def load_module_data(known_good_file, module_name): return {} -def get_module_field(module_data, field='hash'): +def get_module_field(module_data: Dict[str, Any], field: str = 'hash') -> str: """ Extract a specific field from module data. diff --git a/tools/update_module_from_known_good.py b/tools/update_module_from_known_good.py index e05ab1a12..67820ecf0 100644 --- a/tools/update_module_from_known_good.py +++ b/tools/update_module_from_known_good.py @@ -16,9 +16,10 @@ import re from datetime import datetime import logging +from typing import Dict, List, Any, Optional -def load_known_good(path): +def load_known_good(path: str) -> Dict[str, Any]: """Load and parse the known_good.json file.""" with open(path, "r", encoding="utf-8") as f: data = json.load(f) @@ -31,7 +32,7 @@ def load_known_good(path): ) -def generate_git_override_blocks(modules_dict, repo_commit_dict): +def generate_git_override_blocks(modules_dict: Dict[str, Any], repo_commit_dict: Dict[str, str]) -> List[str]: """Generate bazel_dep and git_override blocks for each module.""" blocks = [] @@ -90,7 +91,7 @@ def generate_git_override_blocks(modules_dict, repo_commit_dict): return blocks -def generate_file_content(modules, repo_commit_dict, timestamp=None): +def generate_file_content(modules: Dict[str, Any], repo_commit_dict: Dict[str, str], timestamp: Optional[str] = None) -> str: """Generate the complete content for score_modules.MODULE.bazel.""" # License header assembled with parenthesis grouping (no indentation preserved in output). header = ( @@ -124,7 +125,7 @@ def generate_file_content(modules, repo_commit_dict, timestamp=None): return header + "\n".join(blocks) -def main(): +def main() -> None: parser = argparse.ArgumentParser( description="Generate score_modules.MODULE.bazel from known_good.json" ) From fb6535c9cb0ce9905414fa0daea940ee182caf49 Mon Sep 17 00:00:00 2001 From: Kai Graeper Date: Tue, 25 Nov 2025 13:17:14 +0100 Subject: [PATCH 8/8] add capability to pin modules to branches --- .bazelrc | 2 +- .github/workflows/test_integration.yml | 5 ++-- MODULE.bazel | 12 +++++---- integration_test.sh | 21 ++++++++------- known_good.json | 14 ++++++---- known_good.updated.json | 29 ++++++++++++-------- score_modules.MODULE.bazel | 37 ++++++++++++-------------- tools/update_module_latest.py | 19 ++++++++----- wait_free_stack_fix.patch | 11 -------- 9 files changed, 79 insertions(+), 71 deletions(-) delete mode 100644 wait_free_stack_fix.patch diff --git a/.bazelrc b/.bazelrc index d2f996174..1b1902509 100644 --- a/.bazelrc +++ b/.bazelrc @@ -20,7 +20,7 @@ common --registry=https://bcr.bazel.build build --@score_baselibs//score/mw/log/detail/flags:KUse_Stub_Implementation_Only=False build --@score_baselibs//score/mw/log/flags:KRemote_Logging=False build --@score_baselibs//score/json:base_library=nlohmann -build --@communication//score/mw/com/flags:tracing_library=stub +build --@score_communication//score/mw/com/flags:tracing_library=stub # stop legacy behavior of creating __init__.py files build --incompatible_default_to_explicit_init_py diff --git a/.github/workflows/test_integration.yml b/.github/workflows/test_integration.yml index b06b89346..4809d04ee 100644 --- a/.github/workflows/test_integration.yml +++ b/.github/workflows/test_integration.yml @@ -17,8 +17,9 @@ name: build latest mains on: workflow_dispatch: - push: pull_request: + schedule: + - cron: '30 2 * * *' # Every night at 02:30 UTC on main branch jobs: integration_test: runs-on: ubuntu-latest @@ -53,7 +54,7 @@ jobs: repository-cache: true - name: Update known good commits run: | - echo "::group::get latest commits from main branches" + echo "::group::get latest commits from module branches" python3 tools/update_module_latest.py --output known_good.updated.json cat known_good.updated.json echo "::endgroup::" diff --git a/MODULE.bazel b/MODULE.bazel index e4cbb5396..7cce020da 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -47,13 +47,15 @@ use_repo(pip, "pip_score_venv_test") # communication module dependencies # archive_override are not forwarded by bazel_dep, so we need to redefine it here -# archive_override( -# module_name = "rules_boost", -# strip_prefix = "rules_boost-master", -# urls = ["https://github.com/nelhage/rules_boost/archive/refs/heads/master.tar.gz"], -# ) +bazel_dep(name = "rules_boost", repo_name = "com_github_nelhage_rules_boost") +archive_override( + module_name = "rules_boost", + strip_prefix = "rules_boost-master", + urls = ["https://github.com/nelhage/rules_boost/archive/refs/heads/master.tar.gz"], +) # git_override are not forwarded by bazel_dep, so we need to redefine it here +bazel_dep(name = "trlc") git_override( module_name = "trlc", remote = "https://github.com/bmw-software-engineering/trlc.git", diff --git a/integration_test.sh b/integration_test.sh index b59f7f040..478555f06 100755 --- a/integration_test.sh +++ b/integration_test.sh @@ -12,6 +12,17 @@ LOG_DIR=${LOG_DIR:-_logs/logs} SUMMARY_FILE=${SUMMARY_FILE:-_logs/build_summary.md} KNOWN_GOOD_FILE="" +# maybe move this to known_good.json or a config file later +declare -A BUILD_TARGET_GROUPS=( + [score_baselibs]="@score_baselibs//score/..." + [score_communication]="@score_communication//score/mw/com:com" + [score_persistency]="@score_persistency//src/cpp/src/... @score_persistency//src/rust/..." + #[score_logging]="@score_logging//src/..." + [score_orchestrator]="@score_orchestrator//src/..." + [score_test_scenarios]="@score_test_scenarios//..." + [score_feo]="@score_feo//..." +) + # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in @@ -63,16 +74,6 @@ get_module_repo() { python3 "${script_dir}/tools/get_module_info.py" "${known_good_file}" "${module_name}" "repo" 2>/dev/null || echo "N/A" } -declare -A BUILD_TARGET_GROUPS=( - [score_baselibs]="@score_baselibs//score/..." - [communication]="@communication//score/mw/com:com" - [score_persistency]="@score_persistency//src/cpp/src/... @score_persistency//src/rust/..." - #[score_logging]="@score_logging//src/..." - [score_orchestrator]="@score_orchestrator//src/..." - [score_test_scenarios]="@score_test_scenarios//..." - [score_feo]="@score_feo//..." -) - warn_count() { # Grep typical compiler and Bazel warnings; adjust patterns as needed. local file=$1 diff --git a/known_good.json b/known_good.json index fd906d521..f0df662a8 100644 --- a/known_good.json +++ b/known_good.json @@ -4,13 +4,12 @@ "score_baselibs": { "version": "0.1.3", "repo": "https://github.com/eclipse-score/baselibs.git", - "patches": [ - "//:wait_free_stack_fix.patch" - ] + "branch": "s_core_release_v0_5_0" }, - "communication": { + "score_communication": { "version": "0.1.1", - "repo": "https://github.com/eclipse-score/communication.git" + "repo": "https://github.com/eclipse-score/communication.git", + "branch": "s_core_release_v0_5_0" }, "score_persistency": { "version": "0.2.1", @@ -43,6 +42,11 @@ "score_process": { "version": "1.3.1", "repo": "https://github.com/eclipse-score/process_description.git" + }, + "score_feo": { + "version": "1.0.2", + "repo": "https://github.com/eclipse-score/feo.git", + "branch": "candidate_v0.5" } }, "manifest_sha256": "4c9b7f...", diff --git a/known_good.updated.json b/known_good.updated.json index 5165a69df..92b08d836 100644 --- a/known_good.updated.json +++ b/known_good.updated.json @@ -1,32 +1,34 @@ { - "timestamp": "2025-11-13T10:12:42Z", + "timestamp": "2025-11-25T12:05:14Z", "modules": { "score_baselibs": { "repo": "https://github.com/eclipse-score/baselibs.git", - "hash": "edc4f8841c2210d11ef310049a78644ff3d039a3", + "hash": "9457533471c8f0d4a1bb9435e91ff12c62d19c7c", "patches": [ "//:wait_free_stack_fix.patch" - ] + ], + "branch": "s_core_release_v0_5_0" }, - "communication": { + "score_communication": { "repo": "https://github.com/eclipse-score/communication.git", - "hash": "ff40e5f1e90ce406b71c664cc6c8e902ab465305" + "hash": "24d6e8916b89dbb405eae0b082348645d190dc18", + "branch": "s_core_release_v0_5_0" }, "score_persistency": { "repo": "https://github.com/eclipse-score/persistency.git", - "hash": "7548876ed3e40ec3f3053c57634de68129287e05" + "hash": "6f20545e0bbe90fcc36a0c6783e91a4fd867b110" }, "score_orchestrator": { "repo": "https://github.com/eclipse-score/orchestrator.git", - "hash": "7bb94ebae08805ea0a83dcc14f7c17da5ab927e6" + "hash": "acd3cb614d2f97c2e140c776923c8c6623969691" }, "score_tooling": { "repo": "https://github.com/eclipse-score/tooling.git", - "hash": "654664dae7df2700fd5840c5ed6c07ac6c61705d" + "hash": "8f025ef11f5ad3ea5b02fdff338a75cbac655ec4" }, "score_platform": { "repo": "https://github.com/eclipse-score/score.git", - "hash": "4277c625daca11ef1fe16ffe7670498b354baa72" + "hash": "0d5e37a60ac63a8f2265660f917f7184a6763a48" }, "score_bazel_platforms": { "repo": "https://github.com/eclipse-score/bazel_platforms.git", @@ -38,11 +40,16 @@ }, "score_docs_as_code": { "repo": "https://github.com/eclipse-score/docs-as-code.git", - "hash": "1067fb67782389b50827f8637a74b1027ece52ee" + "hash": "7e747c91521417c56289eb33b55c33dd1f8e9c77" }, "score_process": { "repo": "https://github.com/eclipse-score/process_description.git", - "hash": "e62e4c30808436e790590845f6c297cf605d7649" + "hash": "3bafefc8e81febdaf8e0468716ec2f81d3c12717" + }, + "score_feo": { + "repo": "https://github.com/eclipse-score/feo.git", + "hash": "4841281ab81aad114cfc86a19a69c029a274f28d", + "branch": "candidate_v0.5" } }, "manifest_sha256": "4c9b7f...", diff --git a/score_modules.MODULE.bazel b/score_modules.MODULE.bazel index 266c4975e..c7d6dec39 100644 --- a/score_modules.MODULE.bazel +++ b/score_modules.MODULE.bazel @@ -11,52 +11,49 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -# Generated from known_good.json at 2025-11-13T08:26:11Z +# Generated from known_good.json at 2025-11-25T12:05:14Z # Do not edit manually - use tools/update_module_from_known_good.py bazel_dep(name = "score_baselibs") git_override( module_name = "score_baselibs", remote = "https://github.com/eclipse-score/baselibs.git", - commit = "edc4f8841c2210d11ef310049a78644ff3d039a3", - patches = [ - "//:wait_free_stack_fix.patch", - ], - patch_strip = 1, + commit = "9457533471c8f0d4a1bb9435e91ff12c62d19c7c", ) -bazel_dep(name = "communication") +bazel_dep(name = "score_communication") git_override( - module_name = "communication", + module_name = "score_communication", remote = "https://github.com/eclipse-score/communication.git", - commit = "ff40e5f1e90ce406b71c664cc6c8e902ab465305", + commit = "24d6e8916b89dbb405eae0b082348645d190dc18", ) bazel_dep(name = "score_persistency") git_override( module_name = "score_persistency", remote = "https://github.com/eclipse-score/persistency.git", - commit = "7548876ed3e40ec3f3053c57634de68129287e05", + commit = "6f20545e0bbe90fcc36a0c6783e91a4fd867b110", ) bazel_dep(name = "score_orchestrator") git_override( module_name = "score_orchestrator", remote = "https://github.com/eclipse-score/orchestrator.git", - commit = "7bb94ebae08805ea0a83dcc14f7c17da5ab927e6", + commit = "acd3cb614d2f97c2e140c776923c8c6623969691", ) bazel_dep(name = "score_tooling") git_override( module_name = "score_tooling", remote = "https://github.com/eclipse-score/tooling.git", - commit = "f36904e8c3d06c0ee761b14877ce7e5f6d3d9edb", + commit = "8f025ef11f5ad3ea5b02fdff338a75cbac655ec4", ) bazel_dep(name = "score_platform") -single_version_override( +git_override( module_name = "score_platform", - version = "0.4.2", + remote = "https://github.com/eclipse-score/score.git", + commit = "0d5e37a60ac63a8f2265660f917f7184a6763a48", ) bazel_dep(name = "score_bazel_platforms") @@ -77,19 +74,19 @@ bazel_dep(name = "score_docs_as_code") git_override( module_name = "score_docs_as_code", remote = "https://github.com/eclipse-score/docs-as-code.git", - commit = "1067fb67782389b50827f8637a74b1027ece52ee", + commit = "7e747c91521417c56289eb33b55c33dd1f8e9c77", ) bazel_dep(name = "score_process") git_override( module_name = "score_process", remote = "https://github.com/eclipse-score/process_description.git", - commit = "ea78e6d616adf1f13236c31479a31db813086a77", + commit = "3bafefc8e81febdaf8e0468716ec2f81d3c12717", ) -bazel_dep(name = "score_feo", version = "1.0.2") -single_version_override( +bazel_dep(name = "score_feo") +git_override( module_name = "score_feo", - version = "1.0.2", + remote = "https://github.com/eclipse-score/feo.git", + commit = "4841281ab81aad114cfc86a19a69c029a274f28d", ) - diff --git a/tools/update_module_latest.py b/tools/update_module_latest.py index e4e498e16..77fdee311 100644 --- a/tools/update_module_latest.py +++ b/tools/update_module_latest.py @@ -50,6 +50,7 @@ class Module: repo: str version: str | None = None patches: list[str] | None = None + branch: str = "main" @property def owner_repo(self) -> str: @@ -124,6 +125,8 @@ def write_known_good(path: str, original: dict, modules: list[Module]) -> None: mod_dict = {"repo": m.repo, "hash": m.hash} if m.patches: mod_dict["patches"] = m.patches + if m.branch: + mod_dict["branch"] = m.branch out["modules"][m.name] = mod_dict with open(path, "w", encoding="utf-8") as f: json.dump(out, f, indent=4, sort_keys=False) @@ -163,6 +166,7 @@ def main(argv: list[str]) -> int: hash_val = m.get("hash", "") patches = m.get("patches") repo = m.get("repo") + branch = m.get("branch") if not repo: print(f"WARNING: skipping module {name} with missing repo", file=sys.stderr) continue @@ -171,7 +175,8 @@ def main(argv: list[str]) -> int: hash=hash_val, repo=repo, version=version, - patches=patches + patches=patches, + branch=branch )) except KeyError as e: print(f"WARNING: skipping module {name} missing key {e}: {m}", file=sys.stderr) @@ -198,17 +203,19 @@ def main(argv: list[str]) -> int: for mod in modules: try: + # Use module-specific branch if available, otherwise use command-line branch + branch = mod.branch if mod.branch else args.branch if use_gh: - latest = fetch_latest_commit_gh(mod.owner_repo, args.branch) + latest = fetch_latest_commit_gh(mod.owner_repo, branch) else: - latest = fetch_latest_commit(mod.owner_repo, args.branch, token) - updated.append(Module(name=mod.name, hash=latest, repo=mod.repo, version=mod.version, patches=mod.patches)) + latest = fetch_latest_commit(mod.owner_repo, branch, token) + updated.append(Module(name=mod.name, hash=latest, repo=mod.repo, version=mod.version, patches=mod.patches, branch=mod.branch)) # Display format: if version exists, show "version -> hash", otherwise "hash -> hash" if mod.version: - print(f"{mod.name}: {mod.version} -> {latest[:8]} (branch {args.branch})") + print(f"{mod.name}: {mod.version} -> {latest[:8]} (branch {branch})") else: - print(f"{mod.name}: {mod.hash[:8]} -> {latest[:8]} (branch {args.branch})") + print(f"{mod.name}: {mod.hash[:8]} -> {latest[:8]} (branch {branch})") except Exception as e: # noqa: BLE001 failures += 1 print(f"ERROR {mod.name}: {e}", file=sys.stderr) diff --git a/wait_free_stack_fix.patch b/wait_free_stack_fix.patch deleted file mode 100644 index e44ae447a..000000000 --- a/wait_free_stack_fix.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff --git a/score/mw/log/BUILD b/score/mw/log/BUILD ---- a/score/mw/log/BUILD -+++ b/score/mw/log/BUILD -@@ -25,6 +25,7 @@ cc_library( - visibility = ["//visibility:public"], - deps = [ - ":frontend", -+ "//score/mw/log/detail/wait_free_stack:wait_free_stack", - ] + select({ - "@score_baselibs//score/mw/log/detail/flags:config_KUse_Stub_Implementation_Only": [ - "@score_baselibs//score/mw/log/detail:recorder_factory_stub", \ No newline at end of file