From 0e90a818258f9deaa33ebb843014996e53659e38 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 17 May 2026 18:40:08 +0000
Subject: [PATCH 01/10] Add Bazel dependency sync generator
---
.github/workflows/bazel.yml | 9 +-
CONTRIBUTING.md | 10 +
MODULE.bazel | 47 +++--
pom.xml | 156 ++++++++++++++--
scripts/sync_bazel_dependencies.py | 286 +++++++++++++++++++++++++++++
5 files changed, 471 insertions(+), 37 deletions(-)
create mode 100644 scripts/sync_bazel_dependencies.py
diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml
index 907475adb0..866f684564 100644
--- a/.github/workflows/bazel.yml
+++ b/.github/workflows/bazel.yml
@@ -18,6 +18,8 @@ on:
- "**/*.java"
- "**/BUILD.bazel"
- "MODULE.bazel"
+ - "pom.xml"
+ - "scripts/sync_bazel_dependencies.py"
- ".bazelversion"
- ".bazelrc"
- ".github/workflows/bazel.yml"
@@ -27,6 +29,8 @@ on:
- "**/*.java"
- "**/BUILD.bazel"
- "MODULE.bazel"
+ - "pom.xml"
+ - "scripts/sync_bazel_dependencies.py"
- ".bazelversion"
- ".bazelrc"
- ".github/workflows/bazel.yml"
@@ -74,11 +78,14 @@ jobs:
path: |
~/.cache/bazel-disk-cache
~/.cache/bazel/cache/repos/v1
- key: bazel-${{ runner.os }}-java${{ matrix.java }}-${{ hashFiles('MODULE.bazel', '.bazelversion', 'maven_install.json') }}
+ key: bazel-${{ runner.os }}-java${{ matrix.java }}-${{ hashFiles('MODULE.bazel', 'pom.xml', 'scripts/sync_bazel_dependencies.py', '.bazelversion', 'maven_install.json') }}
restore-keys: |
bazel-${{ runner.os }}-java${{ matrix.java }}-
bazel-${{ runner.os }}-
+ - name: Verify Bazel dependency sync
+ run: python3 scripts/sync_bazel_dependencies.py --check
+
# Re-generate the Maven lock file so it is always consistent with
# MODULE.bazel. The __INPUT_ARTIFACTS_HASH in the committed file is
# intentionally set to -1 to signal that the file needs to be regenerated;
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4274c74da3..73e36ef669 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -20,5 +20,15 @@ If you have any problem with the package or any suggestions, please file an [iss
3. Submit a pull request.
4. The bot will automatically assign someone to review your PR. Check the full list of bot commands [here](https://prow.k8s.io/command-help).
+### Sync Bazel dependency versions
+
+The root `pom.xml` is the source of truth for Maven and Bazel dependency versions.
+If you update a managed dependency version there, also regenerate the Bazel dependency
+block and lock file before sending your PR:
+
+1. Run `python3 scripts/sync_bazel_dependencies.py`
+2. Run `REPIN=1 bazel run @maven//:pin`
+3. Commit the updated `MODULE.bazel` and `maven_install.json`
+
### Contact
You can reach the maintainers of this project at [SIG API Machinery](https://github.com/kubernetes/community/tree/master/sig-api-machinery) or on the [#kubernetes-client](https://kubernetes.slack.com/messages/kubernetes-client) channel on the Kubernetes slack.
diff --git a/MODULE.bazel b/MODULE.bazel
index 26f7670721..5124f4ca73 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -25,10 +25,12 @@ bazel_dep(name = "contrib_rules_jvm", version = "0.27.0")
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
+# BEGIN: generated by scripts/sync_bazel_dependencies.py
+# Generated from pom.xml by scripts/sync_bazel_dependencies.py.
+# Do not edit this block by hand; update pom.xml and rerun the script instead.
maven.install(
artifacts = [
# ---- core ----
- # Versions kept in sync with the property values in the root pom.xml.
"jakarta.annotation:jakarta.annotation-api:3.0.0",
"io.swagger:swagger-annotations:1.6.16",
"com.squareup.okhttp3:okhttp:5.3.2",
@@ -37,8 +39,8 @@ maven.install(
"com.squareup.okio:okio:3.16.4",
"com.squareup.okio:okio-jvm:3.16.4",
"com.google.code.gson:gson:2.14.0",
- "com.fasterxml.jackson.core:jackson-databind:2.21.2",
- "com.fasterxml.jackson.core:jackson-core:2.21.2",
+ "com.fasterxml.jackson.core:jackson-databind:2.21.3",
+ "com.fasterxml.jackson.core:jackson-core:2.21.3",
"com.fasterxml.jackson.core:jackson-annotations:2.21",
"io.gsonfire:gson-fire:1.9.0",
"org.apache.commons:commons-lang3:3.20.0",
@@ -47,18 +49,18 @@ maven.install(
"commons-io:commons-io:2.22.0",
"commons-codec:commons-codec:1.22.0",
"org.yaml:snakeyaml:2.6",
- "org.slf4j:slf4j-api:2.0.17",
+ "org.slf4j:slf4j-api:2.0.18",
"org.bouncycastle:bcpkix-jdk18on:1.84",
"org.bouncycastle:bcprov-jdk18on:1.84",
"com.google.protobuf:protobuf-java:4.34.1",
"org.bitbucket.b_c:jose4j:0.9.6",
- "com.google.auth:google-auth-library-oauth2-http:1.46.0",
- "software.amazon.awssdk:auth:2.43.0",
- "software.amazon.awssdk:http-auth-aws:2.43.0",
- "software.amazon.awssdk:http-auth-spi:2.43.0",
- "software.amazon.awssdk:http-client-spi:2.43.0",
- "software.amazon.awssdk:sts:2.43.0",
- "software.amazon.awssdk:utils:2.43.0",
+ "com.google.auth:google-auth-library-oauth2-http:1.47.0",
+ "software.amazon.awssdk:auth:2.44.4",
+ "software.amazon.awssdk:http-auth-aws:2.44.4",
+ "software.amazon.awssdk:http-auth-spi:2.44.4",
+ "software.amazon.awssdk:http-client-spi:2.44.4",
+ "software.amazon.awssdk:sts:2.44.4",
+ "software.amazon.awssdk:utils:2.44.4",
"io.prometheus:simpleclient:0.16.0",
"io.prometheus:simpleclient_httpserver:0.16.0",
"com.bucket4j:bucket4j-core:8.10.1",
@@ -67,16 +69,12 @@ maven.install(
"org.jetbrains:annotations:26.1.0",
"org.reflections:reflections:0.10.2",
# ---- spring (Java 17+ modules) ----
- # spring-boot 4.0.6 transitively brings in spring-framework 7.0.x, but the
- # root pom.xml pins spring.version=6.2.12. Explicitly declare all
- # spring-framework modules at 6.2.12 and use maven.artifact() with
- # exclusions on the spring-boot artifacts so Coursier does not upgrade them.
- "org.springframework:spring-aop:6.2.12",
- "org.springframework:spring-beans:6.2.12",
- "org.springframework:spring-context:6.2.12",
- "org.springframework:spring-core:6.2.12",
- "org.springframework:spring-expression:6.2.12",
- "org.springframework:spring-test:6.2.12",
+ "org.springframework:spring-aop:6.2.8",
+ "org.springframework:spring-beans:6.2.8",
+ "org.springframework:spring-context:6.2.8",
+ "org.springframework:spring-core:6.2.8",
+ "org.springframework:spring-expression:6.2.8",
+ "org.springframework:spring-test:6.2.8",
# ---- test ----
"org.junit.jupiter:junit-jupiter-api:5.13.4",
"org.junit.jupiter:junit-jupiter-engine:5.13.4",
@@ -103,9 +101,8 @@ maven.install(
lock_file = "//:maven_install.json",
)
-# Spring Boot 4.0.6 artifacts declared with exclusions to pin spring-framework at
-# 6.2.12 (matching pom.xml spring.version) instead of the 7.0.x that spring-boot
-# 4.0.x normally pulls in.
+# Spring Boot 4.0.6 artifacts declared with exclusions to keep
+# spring-framework pinned to 6.2.8.
_SPRING_FRAMEWORK_EXCLUSIONS = [
"org.springframework:spring-aop",
"org.springframework:spring-beans",
@@ -143,4 +140,6 @@ maven.artifact(
exclusions = _SPRING_FRAMEWORK_EXCLUSIONS,
)
+# END: generated by scripts/sync_bazel_dependencies.py
+
use_repo(maven, "maven")
diff --git a/pom.xml b/pom.xml
index 8a84bd5011..9f6c270250 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,7 +52,7 @@
3.0.0
4.34.1
5.13.4
- 5.13.4
+ 1.13.4
${junit-jupiter.version}
8.10.1
1.84
@@ -73,6 +73,18 @@
6.2.8
0.16.0
0.10.2
+ 2.44.4
+ 1.47.0
+ 0.9.6
+ 26.1.0
+ 1.5.32
+ 5.23.0
+ 3.16.4
+ 3.27.7
+ 4.3.0
+ 2.1.8
+ 3.13.2
+ 0.4.16
org.apache.commons
commons-lang3
@@ -161,10 +174,40 @@
bcpkix-jdk18on
${bouncycastle.version}
+
+ org.bouncycastle
+ bcprov-jdk18on
+ ${bouncycastle.version}
+
software.amazon.awssdk
sts
- 2.44.4
+ ${aws.sdk.version}
+
+
+ software.amazon.awssdk
+ auth
+ ${aws.sdk.version}
+
+
+ software.amazon.awssdk
+ http-auth-aws
+ ${aws.sdk.version}
+
+
+ software.amazon.awssdk
+ http-auth-spi
+ ${aws.sdk.version}
+
+
+ software.amazon.awssdk
+ http-client-spi
+ ${aws.sdk.version}
+
+
+ software.amazon.awssdk
+ utils
+ ${aws.sdk.version}
com.google.protobuf
@@ -174,7 +217,7 @@
org.bitbucket.b_c
jose4j
- 0.9.6
+ ${jose4j.version}
com.bucket4j
@@ -196,11 +239,26 @@
spring-core
${spring.version}
+
+ org.springframework
+ spring-aop
+ ${spring.version}
+
+
+ org.springframework
+ spring-beans
+ ${spring.version}
+
org.springframework
spring-context
${spring.version}
+
+ org.springframework
+ spring-expression
+ ${spring.version}
+
org.springframework.boot
spring-boot-autoconfigure
@@ -274,19 +332,57 @@
com.google.auth
google-auth-library-oauth2-http
- 1.47.0
+ ${google.auth.version}
org.jetbrains
annotations
- 26.1.0
+ ${jetbrains.annotations.version}
+
+
+ org.reflections
+ reflections
+ ${reflections.version}
+
+
+ com.squareup.okhttp3
+ okhttp-jvm
+ ${okhttp3.version}
+
+
+ com.squareup.okio
+ okio
+ ${okio.version}
+
+
+ com.squareup.okio
+ okio-jvm
+ ${okio.version}
ch.qos.logback
logback-classic
- 1.5.32
+ ${logback.version}
+ test
+
+
+ ch.qos.logback
+ logback-core
+ ${logback.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit-jupiter.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit-jupiter.version}
test
@@ -301,22 +397,58 @@
${junit-jupiter.version}
test
+
+ org.junit.platform
+ junit-platform-launcher
+ ${junit-platform.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-commons
+ ${junit-platform.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-engine
+ ${junit-platform.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-reporting
+ ${junit-platform.version}
+ test
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
org.mockito
mockito-junit-jupiter
- 5.23.0
+ ${mockito.version}
test
uk.org.webcompere
system-stubs-jupiter
- 2.1.8
+ ${system-stubs.version}
+ test
+
+
+ uk.org.webcompere
+ system-stubs-core
+ ${system-stubs.version}
test
org.wiremock
wiremock
- 3.13.2
+ ${wiremock.version}
test
@@ -334,7 +466,7 @@
com.flipkart.zjsonpatch
zjsonpatch
- 0.4.16
+ ${zjsonpatch.version}
com.fasterxml.jackson.core
@@ -345,13 +477,13 @@
org.assertj
assertj-core
- 3.27.7
+ ${assertj.version}
test
org.awaitility
awaitility
- 4.3.0
+ ${awaitility.version}
test
diff --git a/scripts/sync_bazel_dependencies.py b/scripts/sync_bazel_dependencies.py
new file mode 100644
index 0000000000..3262319f78
--- /dev/null
+++ b/scripts/sync_bazel_dependencies.py
@@ -0,0 +1,286 @@
+#!/usr/bin/env python3
+
+from __future__ import annotations
+
+import argparse
+import re
+import sys
+import xml.etree.ElementTree as ET
+from pathlib import Path
+
+
+GENERATED_START = "# BEGIN: generated by scripts/sync_bazel_dependencies.py"
+GENERATED_END = "# END: generated by scripts/sync_bazel_dependencies.py"
+
+MAVEN_INSTALL_ARTIFACTS = {
+ "core": [
+ "jakarta.annotation:jakarta.annotation-api",
+ "io.swagger:swagger-annotations",
+ "com.squareup.okhttp3:okhttp",
+ "com.squareup.okhttp3:okhttp-jvm",
+ "com.squareup.okhttp3:logging-interceptor",
+ "com.squareup.okio:okio",
+ "com.squareup.okio:okio-jvm",
+ "com.google.code.gson:gson",
+ "com.fasterxml.jackson.core:jackson-databind",
+ "com.fasterxml.jackson.core:jackson-core",
+ "com.fasterxml.jackson.core:jackson-annotations",
+ "io.gsonfire:gson-fire",
+ "org.apache.commons:commons-lang3",
+ "org.apache.commons:commons-collections4",
+ "org.apache.commons:commons-compress",
+ "commons-io:commons-io",
+ "commons-codec:commons-codec",
+ "org.yaml:snakeyaml",
+ "org.slf4j:slf4j-api",
+ "org.bouncycastle:bcpkix-jdk18on",
+ "org.bouncycastle:bcprov-jdk18on",
+ "com.google.protobuf:protobuf-java",
+ "org.bitbucket.b_c:jose4j",
+ "com.google.auth:google-auth-library-oauth2-http",
+ "software.amazon.awssdk:auth",
+ "software.amazon.awssdk:http-auth-aws",
+ "software.amazon.awssdk:http-auth-spi",
+ "software.amazon.awssdk:http-client-spi",
+ "software.amazon.awssdk:sts",
+ "software.amazon.awssdk:utils",
+ "io.prometheus:simpleclient",
+ "io.prometheus:simpleclient_httpserver",
+ "com.bucket4j:bucket4j-core",
+ "com.github.ben-manes.caffeine:caffeine",
+ "com.flipkart.zjsonpatch:zjsonpatch",
+ "org.jetbrains:annotations",
+ "org.reflections:reflections",
+ ],
+ "spring (Java 17+ modules)": [
+ "org.springframework:spring-aop",
+ "org.springframework:spring-beans",
+ "org.springframework:spring-context",
+ "org.springframework:spring-core",
+ "org.springframework:spring-expression",
+ "org.springframework:spring-test",
+ ],
+ "test": [
+ "org.junit.jupiter:junit-jupiter-api",
+ "org.junit.jupiter:junit-jupiter-engine",
+ "org.junit.jupiter:junit-jupiter-params",
+ "org.junit.platform:junit-platform-launcher",
+ "org.junit.platform:junit-platform-commons",
+ "org.junit.platform:junit-platform-engine",
+ "org.junit.platform:junit-platform-reporting",
+ "org.mockito:mockito-core",
+ "org.mockito:mockito-junit-jupiter",
+ "uk.org.webcompere:system-stubs-jupiter",
+ "uk.org.webcompere:system-stubs-core",
+ "org.wiremock:wiremock",
+ "org.awaitility:awaitility",
+ "org.assertj:assertj-core",
+ "ch.qos.logback:logback-classic",
+ "ch.qos.logback:logback-core",
+ ],
+}
+
+SPRING_BOOT_ARTIFACTS = [
+ "spring-boot",
+ "spring-boot-autoconfigure",
+ "spring-boot-actuator",
+ "spring-boot-test",
+]
+
+SPRING_FRAMEWORK_EXCLUSIONS = [
+ "org.springframework:spring-aop",
+ "org.springframework:spring-beans",
+ "org.springframework:spring-context",
+ "org.springframework:spring-core",
+ "org.springframework:spring-expression",
+ "org.springframework:spring-test",
+]
+
+
+def parse_args() -> argparse.Namespace:
+ parser = argparse.ArgumentParser(
+ description="Sync Bazel dependency declarations from the root pom.xml."
+ )
+ parser.add_argument(
+ "--root",
+ type=Path,
+ default=Path(__file__).resolve().parents[1],
+ help="Repository root containing pom.xml and MODULE.bazel.",
+ )
+ parser.add_argument(
+ "--check",
+ action="store_true",
+ help="Fail if MODULE.bazel is not up to date.",
+ )
+ return parser.parse_args()
+
+
+def local_name(tag: str) -> str:
+ return tag.split("}", 1)[-1]
+
+
+def parse_managed_versions(pom_path: Path) -> dict[str, str]:
+ root = ET.parse(pom_path).getroot()
+ namespace = {}
+ if root.tag.startswith("{"):
+ namespace["m"] = root.tag[1:].split("}", 1)[0]
+ prefix = "m:"
+ else:
+ prefix = ""
+
+ properties_element = root.find(f"{prefix}properties", namespace)
+ properties = {}
+ if properties_element is not None:
+ for child in properties_element:
+ properties[local_name(child.tag)] = (child.text or "").strip()
+
+ project_version = (root.findtext(f"{prefix}version", default="", namespaces=namespace) or "").strip()
+ if project_version:
+ properties.setdefault("project.version", project_version)
+ properties.setdefault("pom.version", project_version)
+ properties.setdefault("version", project_version)
+
+ def resolve(value: str) -> str:
+ resolved = value
+ for _ in range(20):
+ updated = re.sub(
+ r"\$\{([^}]+)\}",
+ lambda match: properties.get(match.group(1), match.group(0)),
+ resolved,
+ )
+ if updated == resolved:
+ return updated
+ resolved = updated
+ raise ValueError(f"Could not fully resolve property expression: {value}")
+
+ managed_versions = {}
+ dependency_path = f"{prefix}dependencyManagement/{prefix}dependencies/{prefix}dependency"
+ for dependency in root.findall(dependency_path, namespace):
+ group_id = dependency.findtext(f"{prefix}groupId", default="", namespaces=namespace).strip()
+ artifact_id = dependency.findtext(
+ f"{prefix}artifactId", default="", namespaces=namespace
+ ).strip()
+ version = dependency.findtext(f"{prefix}version", default="", namespaces=namespace).strip()
+ if group_id and artifact_id and version:
+ managed_versions[f"{group_id}:{artifact_id}"] = resolve(version)
+ return managed_versions
+
+
+def render_generated_block(managed_versions: dict[str, str]) -> str:
+ missing = [
+ coordinate
+ for artifacts in MAVEN_INSTALL_ARTIFACTS.values()
+ for coordinate in artifacts
+ if coordinate not in managed_versions
+ ]
+ missing.extend(
+ f"org.springframework.boot:{artifact}"
+ for artifact in SPRING_BOOT_ARTIFACTS
+ if f"org.springframework.boot:{artifact}" not in managed_versions
+ )
+ if missing:
+ missing_list = "\n".join(f" - {coordinate}" for coordinate in sorted(missing))
+ raise KeyError(f"Missing dependencyManagement entries:\n{missing_list}")
+
+ lines = [
+ GENERATED_START,
+ "# Generated from pom.xml by scripts/sync_bazel_dependencies.py.",
+ "# Do not edit this block by hand; update pom.xml and rerun the script instead.",
+ "maven.install(",
+ " artifacts = [",
+ ]
+ for section, artifacts in MAVEN_INSTALL_ARTIFACTS.items():
+ lines.append(f" # ---- {section} ----")
+ for coordinate in artifacts:
+ lines.append(f' "{coordinate}:{managed_versions[coordinate]}",')
+ lines.extend(
+ [
+ " ],",
+ " repositories = [",
+ ' "https://repo1.maven.org/maven2",',
+ ' "https://repo.spring.io/milestone",',
+ " ],",
+ " fetch_sources = False,",
+ ' lock_file = "//:maven_install.json",',
+ ")",
+ "",
+ "_SPRING_FRAMEWORK_EXCLUSIONS = [",
+ ]
+ )
+ for exclusion in SPRING_FRAMEWORK_EXCLUSIONS:
+ lines.append(f' "{exclusion}",')
+ lines.extend(["]", ""])
+
+ spring_boot_version = managed_versions["org.springframework.boot:spring-boot"]
+ for artifact in SPRING_BOOT_ARTIFACTS:
+ lines.extend(
+ [
+ "maven.artifact(",
+ f' artifact = "{artifact}",',
+ ' group = "org.springframework.boot",',
+ f' version = "{managed_versions[f"org.springframework.boot:{artifact}"]}",',
+ " exclusions = _SPRING_FRAMEWORK_EXCLUSIONS,",
+ ")",
+ "",
+ ]
+ )
+
+ if len({managed_versions[f"org.springframework.boot:{artifact}"] for artifact in SPRING_BOOT_ARTIFACTS}) != 1:
+ raise ValueError("Spring Boot artifact versions diverged in dependencyManagement.")
+
+ lines.insert(
+ lines.index("_SPRING_FRAMEWORK_EXCLUSIONS = ["),
+ f"# Spring Boot {spring_boot_version} artifacts declared with exclusions to keep",
+ )
+ lines.insert(
+ lines.index("_SPRING_FRAMEWORK_EXCLUSIONS = ["),
+ f'# spring-framework pinned to {managed_versions["org.springframework:spring-core"]}.',
+ )
+
+ lines.append(GENERATED_END)
+ return "\n".join(lines) + "\n"
+
+
+def sync_module(module_path: Path, generated_block: str, check_only: bool) -> bool:
+ module_text = module_path.read_text()
+ pattern = re.compile(
+ rf"{re.escape(GENERATED_START)}\n.*?{re.escape(GENERATED_END)}\n?",
+ re.DOTALL,
+ )
+ match = pattern.search(module_text)
+ if not match:
+ raise ValueError(
+ f"Could not find generated block markers in {module_path}. "
+ f"Expected {GENERATED_START!r} and {GENERATED_END!r}."
+ )
+
+ updated_text = module_text[: match.start()] + generated_block + module_text[match.end() :]
+ changed = updated_text != module_text
+ if changed and not check_only:
+ module_path.write_text(updated_text)
+ return changed
+
+
+def main() -> int:
+ args = parse_args()
+ root = args.root.resolve()
+ pom_path = root / "pom.xml"
+ module_path = root / "MODULE.bazel"
+
+ managed_versions = parse_managed_versions(pom_path)
+ generated_block = render_generated_block(managed_versions)
+ changed = sync_module(module_path, generated_block, args.check)
+
+ if args.check and changed:
+ print(f"{module_path} is out of date. Run {Path(__file__).name} to regenerate it.")
+ return 1
+
+ if not args.check and changed:
+ print(f"Updated {module_path}")
+ elif not args.check:
+ print(f"{module_path} is already up to date")
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
From 530756e19b702b2f26b5e9a0deb3617cd3501c61 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 17 May 2026 18:42:12 +0000
Subject: [PATCH 02/10] Refine Bazel dependency sync script
---
scripts/sync_bazel_dependencies.py | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/scripts/sync_bazel_dependencies.py b/scripts/sync_bazel_dependencies.py
index 3262319f78..4ae7f43607 100644
--- a/scripts/sync_bazel_dependencies.py
+++ b/scripts/sync_bazel_dependencies.py
@@ -11,6 +11,7 @@
GENERATED_START = "# BEGIN: generated by scripts/sync_bazel_dependencies.py"
GENERATED_END = "# END: generated by scripts/sync_bazel_dependencies.py"
+MAX_PROPERTY_RESOLUTION_DEPTH = 20
MAVEN_INSTALL_ARTIFACTS = {
"core": [
@@ -142,7 +143,7 @@ def parse_managed_versions(pom_path: Path) -> dict[str, str]:
def resolve(value: str) -> str:
resolved = value
- for _ in range(20):
+ for _ in range(MAX_PROPERTY_RESOLUTION_DEPTH):
updated = re.sub(
r"\$\{([^}]+)\}",
lambda match: properties.get(match.group(1), match.group(0)),
@@ -193,6 +194,8 @@ def render_generated_block(managed_versions: dict[str, str]) -> str:
lines.append(f" # ---- {section} ----")
for coordinate in artifacts:
lines.append(f' "{coordinate}:{managed_versions[coordinate]}",')
+ spring_boot_version = managed_versions["org.springframework.boot:spring-boot"]
+ spring_framework_version = managed_versions["org.springframework:spring-core"]
lines.extend(
[
" ],",
@@ -204,6 +207,8 @@ def render_generated_block(managed_versions: dict[str, str]) -> str:
' lock_file = "//:maven_install.json",',
")",
"",
+ f"# Spring Boot {spring_boot_version} artifacts declared with exclusions to keep",
+ f"# spring-framework pinned to {spring_framework_version}.",
"_SPRING_FRAMEWORK_EXCLUSIONS = [",
]
)
@@ -211,7 +216,6 @@ def render_generated_block(managed_versions: dict[str, str]) -> str:
lines.append(f' "{exclusion}",')
lines.extend(["]", ""])
- spring_boot_version = managed_versions["org.springframework.boot:spring-boot"]
for artifact in SPRING_BOOT_ARTIFACTS:
lines.extend(
[
@@ -228,15 +232,6 @@ def render_generated_block(managed_versions: dict[str, str]) -> str:
if len({managed_versions[f"org.springframework.boot:{artifact}"] for artifact in SPRING_BOOT_ARTIFACTS}) != 1:
raise ValueError("Spring Boot artifact versions diverged in dependencyManagement.")
- lines.insert(
- lines.index("_SPRING_FRAMEWORK_EXCLUSIONS = ["),
- f"# Spring Boot {spring_boot_version} artifacts declared with exclusions to keep",
- )
- lines.insert(
- lines.index("_SPRING_FRAMEWORK_EXCLUSIONS = ["),
- f'# spring-framework pinned to {managed_versions["org.springframework:spring-core"]}.',
- )
-
lines.append(GENERATED_END)
return "\n".join(lines) + "\n"
From 97e5feab2d927f238eedd77f16b5aec2e5c42e82 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 19 May 2026 01:38:08 +0000
Subject: [PATCH 03/10] Extract Bazel dependency list from pom
---
MODULE.bazel | 52 ++++----
scripts/sync_bazel_dependencies.py | 197 +++++++++++++----------------
2 files changed, 111 insertions(+), 138 deletions(-)
diff --git a/MODULE.bazel b/MODULE.bazel
index 5124f4ca73..658e698d04 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -31,51 +31,53 @@ maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
artifacts = [
# ---- core ----
- "jakarta.annotation:jakarta.annotation-api:3.0.0",
- "io.swagger:swagger-annotations:1.6.16",
- "com.squareup.okhttp3:okhttp:5.3.2",
- "com.squareup.okhttp3:okhttp-jvm:5.3.2",
- "com.squareup.okhttp3:logging-interceptor:5.3.2",
- "com.squareup.okio:okio:3.16.4",
- "com.squareup.okio:okio-jvm:3.16.4",
- "com.google.code.gson:gson:2.14.0",
- "com.fasterxml.jackson.core:jackson-databind:2.21.3",
- "com.fasterxml.jackson.core:jackson-core:2.21.3",
- "com.fasterxml.jackson.core:jackson-annotations:2.21",
- "io.gsonfire:gson-fire:1.9.0",
"org.apache.commons:commons-lang3:3.20.0",
"org.apache.commons:commons-collections4:4.5.0",
+ "org.yaml:snakeyaml:2.6",
+ "commons-codec:commons-codec:1.22.0",
"org.apache.commons:commons-compress:1.28.0",
"commons-io:commons-io:2.22.0",
- "commons-codec:commons-codec:1.22.0",
- "org.yaml:snakeyaml:2.6",
+ "com.github.ben-manes.caffeine:caffeine:3.0.0",
"org.slf4j:slf4j-api:2.0.18",
"org.bouncycastle:bcpkix-jdk18on:1.84",
"org.bouncycastle:bcprov-jdk18on:1.84",
- "com.google.protobuf:protobuf-java:4.34.1",
- "org.bitbucket.b_c:jose4j:0.9.6",
- "com.google.auth:google-auth-library-oauth2-http:1.47.0",
+ "software.amazon.awssdk:sts:2.44.4",
"software.amazon.awssdk:auth:2.44.4",
"software.amazon.awssdk:http-auth-aws:2.44.4",
"software.amazon.awssdk:http-auth-spi:2.44.4",
"software.amazon.awssdk:http-client-spi:2.44.4",
- "software.amazon.awssdk:sts:2.44.4",
"software.amazon.awssdk:utils:2.44.4",
+ "com.google.protobuf:protobuf-java:4.34.1",
+ "org.bitbucket.b_c:jose4j:0.9.6",
+ "com.bucket4j:bucket4j-core:8.10.1",
"io.prometheus:simpleclient:0.16.0",
"io.prometheus:simpleclient_httpserver:0.16.0",
- "com.bucket4j:bucket4j-core:8.10.1",
- "com.github.ben-manes.caffeine:caffeine:3.0.0",
- "com.flipkart.zjsonpatch:zjsonpatch:0.4.16",
+ "com.google.code.gson:gson:2.14.0",
+ "com.fasterxml.jackson.core:jackson-databind:2.21.3",
+ "com.fasterxml.jackson.core:jackson-annotations:2.21",
+ "com.fasterxml.jackson.core:jackson-core:2.21.3",
+ "io.gsonfire:gson-fire:1.9.0",
+ "com.squareup.okhttp3:okhttp:5.3.2",
+ "com.squareup.okhttp3:logging-interceptor:5.3.2",
+ "io.swagger:swagger-annotations:1.6.16",
+ "jakarta.annotation:jakarta.annotation-api:3.0.0",
+ "com.google.auth:google-auth-library-oauth2-http:1.47.0",
"org.jetbrains:annotations:26.1.0",
"org.reflections:reflections:0.10.2",
+ "com.squareup.okhttp3:okhttp-jvm:5.3.2",
+ "com.squareup.okio:okio:3.16.4",
+ "com.squareup.okio:okio-jvm:3.16.4",
+ "com.flipkart.zjsonpatch:zjsonpatch:0.4.16",
# ---- spring (Java 17+ modules) ----
+ "org.springframework:spring-core:6.2.8",
"org.springframework:spring-aop:6.2.8",
"org.springframework:spring-beans:6.2.8",
"org.springframework:spring-context:6.2.8",
- "org.springframework:spring-core:6.2.8",
"org.springframework:spring-expression:6.2.8",
"org.springframework:spring-test:6.2.8",
# ---- test ----
+ "ch.qos.logback:logback-classic:1.5.32",
+ "ch.qos.logback:logback-core:1.5.32",
"org.junit.jupiter:junit-jupiter-api:5.13.4",
"org.junit.jupiter:junit-jupiter-engine:5.13.4",
"org.junit.jupiter:junit-jupiter-params:5.13.4",
@@ -88,10 +90,8 @@ maven.install(
"uk.org.webcompere:system-stubs-jupiter:2.1.8",
"uk.org.webcompere:system-stubs-core:2.1.8",
"org.wiremock:wiremock:3.13.2",
- "org.awaitility:awaitility:4.3.0",
"org.assertj:assertj-core:3.27.7",
- "ch.qos.logback:logback-classic:1.5.32",
- "ch.qos.logback:logback-core:1.5.32",
+ "org.awaitility:awaitility:4.3.0",
],
repositories = [
"https://repo1.maven.org/maven2",
@@ -104,10 +104,10 @@ maven.install(
# Spring Boot 4.0.6 artifacts declared with exclusions to keep
# spring-framework pinned to 6.2.8.
_SPRING_FRAMEWORK_EXCLUSIONS = [
+ "org.springframework:spring-core",
"org.springframework:spring-aop",
"org.springframework:spring-beans",
"org.springframework:spring-context",
- "org.springframework:spring-core",
"org.springframework:spring-expression",
"org.springframework:spring-test",
]
diff --git a/scripts/sync_bazel_dependencies.py b/scripts/sync_bazel_dependencies.py
index 4ae7f43607..fbc1a24b94 100644
--- a/scripts/sync_bazel_dependencies.py
+++ b/scripts/sync_bazel_dependencies.py
@@ -3,6 +3,7 @@
from __future__ import annotations
import argparse
+from dataclasses import dataclass
import re
import sys
import xml.etree.ElementTree as ET
@@ -12,90 +13,32 @@
GENERATED_START = "# BEGIN: generated by scripts/sync_bazel_dependencies.py"
GENERATED_END = "# END: generated by scripts/sync_bazel_dependencies.py"
MAX_PROPERTY_RESOLUTION_DEPTH = 20
-
-MAVEN_INSTALL_ARTIFACTS = {
- "core": [
- "jakarta.annotation:jakarta.annotation-api",
- "io.swagger:swagger-annotations",
- "com.squareup.okhttp3:okhttp",
- "com.squareup.okhttp3:okhttp-jvm",
- "com.squareup.okhttp3:logging-interceptor",
- "com.squareup.okio:okio",
- "com.squareup.okio:okio-jvm",
- "com.google.code.gson:gson",
- "com.fasterxml.jackson.core:jackson-databind",
- "com.fasterxml.jackson.core:jackson-core",
- "com.fasterxml.jackson.core:jackson-annotations",
- "io.gsonfire:gson-fire",
- "org.apache.commons:commons-lang3",
- "org.apache.commons:commons-collections4",
- "org.apache.commons:commons-compress",
- "commons-io:commons-io",
- "commons-codec:commons-codec",
- "org.yaml:snakeyaml",
- "org.slf4j:slf4j-api",
- "org.bouncycastle:bcpkix-jdk18on",
- "org.bouncycastle:bcprov-jdk18on",
- "com.google.protobuf:protobuf-java",
- "org.bitbucket.b_c:jose4j",
- "com.google.auth:google-auth-library-oauth2-http",
- "software.amazon.awssdk:auth",
- "software.amazon.awssdk:http-auth-aws",
- "software.amazon.awssdk:http-auth-spi",
- "software.amazon.awssdk:http-client-spi",
- "software.amazon.awssdk:sts",
- "software.amazon.awssdk:utils",
- "io.prometheus:simpleclient",
- "io.prometheus:simpleclient_httpserver",
- "com.bucket4j:bucket4j-core",
- "com.github.ben-manes.caffeine:caffeine",
- "com.flipkart.zjsonpatch:zjsonpatch",
- "org.jetbrains:annotations",
- "org.reflections:reflections",
- ],
- "spring (Java 17+ modules)": [
- "org.springframework:spring-aop",
- "org.springframework:spring-beans",
- "org.springframework:spring-context",
- "org.springframework:spring-core",
- "org.springframework:spring-expression",
- "org.springframework:spring-test",
- ],
- "test": [
- "org.junit.jupiter:junit-jupiter-api",
- "org.junit.jupiter:junit-jupiter-engine",
- "org.junit.jupiter:junit-jupiter-params",
- "org.junit.platform:junit-platform-launcher",
- "org.junit.platform:junit-platform-commons",
- "org.junit.platform:junit-platform-engine",
- "org.junit.platform:junit-platform-reporting",
- "org.mockito:mockito-core",
- "org.mockito:mockito-junit-jupiter",
- "uk.org.webcompere:system-stubs-jupiter",
- "uk.org.webcompere:system-stubs-core",
- "org.wiremock:wiremock",
- "org.awaitility:awaitility",
- "org.assertj:assertj-core",
- "ch.qos.logback:logback-classic",
- "ch.qos.logback:logback-core",
- ],
+SECTION_CORE = "core"
+SECTION_SPRING = "spring (Java 17+ modules)"
+SECTION_TEST = "test"
+SPRING_BOOT_GROUP = "org.springframework.boot"
+SPRING_FRAMEWORK_GROUP = "org.springframework"
+EXCLUDED_BAZEL_COORDINATES = {
+ "commons-cli:commons-cli",
+ "com.google.code.findbugs:jsr305",
+ "org.junit.jupiter:junit-jupiter",
}
-SPRING_BOOT_ARTIFACTS = [
- "spring-boot",
- "spring-boot-autoconfigure",
- "spring-boot-actuator",
- "spring-boot-test",
-]
-SPRING_FRAMEWORK_EXCLUSIONS = [
- "org.springframework:spring-aop",
- "org.springframework:spring-beans",
- "org.springframework:spring-context",
- "org.springframework:spring-core",
- "org.springframework:spring-expression",
- "org.springframework:spring-test",
-]
+@dataclass(frozen=True)
+class ManagedDependency:
+ group_id: str
+ artifact_id: str
+ version: str
+ scope: str = ""
+
+ @property
+ def coordinate(self) -> str:
+ return f"{self.group_id}:{self.artifact_id}"
+
+ @property
+ def bazel_artifact(self) -> str:
+ return f"{self.coordinate}:{self.version}"
def parse_args() -> argparse.Namespace:
@@ -120,7 +63,7 @@ def local_name(tag: str) -> str:
return tag.split("}", 1)[-1]
-def parse_managed_versions(pom_path: Path) -> dict[str, str]:
+def parse_managed_dependencies(pom_path: Path) -> list[ManagedDependency]:
root = ET.parse(pom_path).getroot()
namespace = {}
if root.tag.startswith("{"):
@@ -154,7 +97,7 @@ def resolve(value: str) -> str:
resolved = updated
raise ValueError(f"Could not fully resolve property expression: {value}")
- managed_versions = {}
+ managed_dependencies = []
dependency_path = f"{prefix}dependencyManagement/{prefix}dependencies/{prefix}dependency"
for dependency in root.findall(dependency_path, namespace):
group_id = dependency.findtext(f"{prefix}groupId", default="", namespaces=namespace).strip()
@@ -162,26 +105,56 @@ def resolve(value: str) -> str:
f"{prefix}artifactId", default="", namespaces=namespace
).strip()
version = dependency.findtext(f"{prefix}version", default="", namespaces=namespace).strip()
+ scope = dependency.findtext(f"{prefix}scope", default="", namespaces=namespace).strip()
if group_id and artifact_id and version:
- managed_versions[f"{group_id}:{artifact_id}"] = resolve(version)
- return managed_versions
+ managed_dependencies.append(
+ ManagedDependency(
+ group_id=group_id,
+ artifact_id=artifact_id,
+ version=resolve(version),
+ scope=scope,
+ )
+ )
+ return managed_dependencies
-def render_generated_block(managed_versions: dict[str, str]) -> str:
- missing = [
- coordinate
- for artifacts in MAVEN_INSTALL_ARTIFACTS.values()
- for coordinate in artifacts
- if coordinate not in managed_versions
- ]
- missing.extend(
- f"org.springframework.boot:{artifact}"
- for artifact in SPRING_BOOT_ARTIFACTS
- if f"org.springframework.boot:{artifact}" not in managed_versions
- )
- if missing:
- missing_list = "\n".join(f" - {coordinate}" for coordinate in sorted(missing))
- raise KeyError(f"Missing dependencyManagement entries:\n{missing_list}")
+def classify_dependency(dependency: ManagedDependency) -> str:
+ if dependency.group_id == SPRING_FRAMEWORK_GROUP:
+ return SECTION_SPRING
+ if dependency.scope == "test":
+ return SECTION_TEST
+ return SECTION_CORE
+
+
+def partition_dependencies(
+ managed_dependencies: list[ManagedDependency],
+) -> tuple[dict[str, list[ManagedDependency]], list[ManagedDependency]]:
+ install_sections = {
+ SECTION_CORE: [],
+ SECTION_SPRING: [],
+ SECTION_TEST: [],
+ }
+ spring_boot_dependencies = []
+
+ for dependency in managed_dependencies:
+ if dependency.group_id == SPRING_BOOT_GROUP:
+ spring_boot_dependencies.append(dependency)
+ continue
+ if dependency.coordinate in EXCLUDED_BAZEL_COORDINATES:
+ continue
+ install_sections[classify_dependency(dependency)].append(dependency)
+
+ if not spring_boot_dependencies:
+ raise ValueError("No org.springframework.boot dependencies found in dependencyManagement.")
+
+ return install_sections, spring_boot_dependencies
+
+
+def render_generated_block(managed_dependencies: list[ManagedDependency]) -> str:
+ install_sections, spring_boot_dependencies = partition_dependencies(managed_dependencies)
+ spring_framework_exclusions = [dependency.coordinate for dependency in install_sections[SECTION_SPRING]]
+ if not spring_framework_exclusions:
+ raise ValueError("No spring-framework exclusions found for spring boot artifacts.")
lines = [
GENERATED_START,
@@ -190,12 +163,12 @@ def render_generated_block(managed_versions: dict[str, str]) -> str:
"maven.install(",
" artifacts = [",
]
- for section, artifacts in MAVEN_INSTALL_ARTIFACTS.items():
+ for section, dependencies in install_sections.items():
lines.append(f" # ---- {section} ----")
- for coordinate in artifacts:
- lines.append(f' "{coordinate}:{managed_versions[coordinate]}",')
- spring_boot_version = managed_versions["org.springframework.boot:spring-boot"]
- spring_framework_version = managed_versions["org.springframework:spring-core"]
+ for dependency in dependencies:
+ lines.append(f' "{dependency.bazel_artifact}",')
+ spring_boot_version = spring_boot_dependencies[0].version
+ spring_framework_version = install_sections[SECTION_SPRING][0].version
lines.extend(
[
" ],",
@@ -212,24 +185,24 @@ def render_generated_block(managed_versions: dict[str, str]) -> str:
"_SPRING_FRAMEWORK_EXCLUSIONS = [",
]
)
- for exclusion in SPRING_FRAMEWORK_EXCLUSIONS:
+ for exclusion in spring_framework_exclusions:
lines.append(f' "{exclusion}",')
lines.extend(["]", ""])
- for artifact in SPRING_BOOT_ARTIFACTS:
+ for dependency in spring_boot_dependencies:
lines.extend(
[
"maven.artifact(",
- f' artifact = "{artifact}",',
+ f' artifact = "{dependency.artifact_id}",',
' group = "org.springframework.boot",',
- f' version = "{managed_versions[f"org.springframework.boot:{artifact}"]}",',
+ f' version = "{dependency.version}",',
" exclusions = _SPRING_FRAMEWORK_EXCLUSIONS,",
")",
"",
]
)
- if len({managed_versions[f"org.springframework.boot:{artifact}"] for artifact in SPRING_BOOT_ARTIFACTS}) != 1:
+ if len({dependency.version for dependency in spring_boot_dependencies}) != 1:
raise ValueError("Spring Boot artifact versions diverged in dependencyManagement.")
lines.append(GENERATED_END)
@@ -262,8 +235,8 @@ def main() -> int:
pom_path = root / "pom.xml"
module_path = root / "MODULE.bazel"
- managed_versions = parse_managed_versions(pom_path)
- generated_block = render_generated_block(managed_versions)
+ managed_dependencies = parse_managed_dependencies(pom_path)
+ generated_block = render_generated_block(managed_dependencies)
changed = sync_module(module_path, generated_block, args.check)
if args.check and changed:
From 0ee9f2e536cf6b3275cec55dfad5b9f2841303ef Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 19 May 2026 01:38:59 +0000
Subject: [PATCH 04/10] Harden pom-derived version lookup
---
scripts/sync_bazel_dependencies.py | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/scripts/sync_bazel_dependencies.py b/scripts/sync_bazel_dependencies.py
index fbc1a24b94..566201630c 100644
--- a/scripts/sync_bazel_dependencies.py
+++ b/scripts/sync_bazel_dependencies.py
@@ -18,6 +18,8 @@
SECTION_TEST = "test"
SPRING_BOOT_GROUP = "org.springframework.boot"
SPRING_FRAMEWORK_GROUP = "org.springframework"
+SPRING_BOOT_COORDINATE = "org.springframework.boot:spring-boot"
+SPRING_CORE_COORDINATE = "org.springframework:spring-core"
EXCLUDED_BAZEL_COORDINATES = {
"commons-cli:commons-cli",
"com.google.code.findbugs:jsr305",
@@ -150,6 +152,15 @@ def partition_dependencies(
return install_sections, spring_boot_dependencies
+def find_dependency(
+ dependencies: list[ManagedDependency], coordinate: str
+) -> ManagedDependency:
+ for dependency in dependencies:
+ if dependency.coordinate == coordinate:
+ return dependency
+ raise ValueError(f"Missing expected dependencyManagement entry: {coordinate}")
+
+
def render_generated_block(managed_dependencies: list[ManagedDependency]) -> str:
install_sections, spring_boot_dependencies = partition_dependencies(managed_dependencies)
spring_framework_exclusions = [dependency.coordinate for dependency in install_sections[SECTION_SPRING]]
@@ -167,8 +178,12 @@ def render_generated_block(managed_dependencies: list[ManagedDependency]) -> str
lines.append(f" # ---- {section} ----")
for dependency in dependencies:
lines.append(f' "{dependency.bazel_artifact}",')
- spring_boot_version = spring_boot_dependencies[0].version
- spring_framework_version = install_sections[SECTION_SPRING][0].version
+ spring_boot_version = find_dependency(
+ spring_boot_dependencies, SPRING_BOOT_COORDINATE
+ ).version
+ spring_framework_version = find_dependency(
+ install_sections[SECTION_SPRING], SPRING_CORE_COORDINATE
+ ).version
lines.extend(
[
" ],",
From a5b40ab7874ebf46d4049f8f34512e060072cf7b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 19 May 2026 01:39:44 +0000
Subject: [PATCH 05/10] Clarify spring dependency classification
---
scripts/sync_bazel_dependencies.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/scripts/sync_bazel_dependencies.py b/scripts/sync_bazel_dependencies.py
index 566201630c..a7c43553fb 100644
--- a/scripts/sync_bazel_dependencies.py
+++ b/scripts/sync_bazel_dependencies.py
@@ -121,6 +121,10 @@ def resolve(value: str) -> str:
def classify_dependency(dependency: ManagedDependency) -> str:
+ # Keep all org.springframework modules together so the generated spring
+ # section also doubles as the exclusion list for the spring-boot artifacts.
+ # This intentionally keeps spring-test in the spring section even though its
+ # Maven scope is test.
if dependency.group_id == SPRING_FRAMEWORK_GROUP:
return SECTION_SPRING
if dependency.scope == "test":
@@ -165,7 +169,7 @@ def render_generated_block(managed_dependencies: list[ManagedDependency]) -> str
install_sections, spring_boot_dependencies = partition_dependencies(managed_dependencies)
spring_framework_exclusions = [dependency.coordinate for dependency in install_sections[SECTION_SPRING]]
if not spring_framework_exclusions:
- raise ValueError("No spring-framework exclusions found for spring boot artifacts.")
+ raise ValueError("No org.springframework dependencies found in dependencyManagement.")
lines = [
GENERATED_START,
From fc7c2873dc18f13cf18b5658545797b2e6e20429 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 19 May 2026 01:40:22 +0000
Subject: [PATCH 06/10] Polish sync script constants
---
scripts/sync_bazel_dependencies.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/scripts/sync_bazel_dependencies.py b/scripts/sync_bazel_dependencies.py
index a7c43553fb..bb3f852c06 100644
--- a/scripts/sync_bazel_dependencies.py
+++ b/scripts/sync_bazel_dependencies.py
@@ -16,6 +16,7 @@
SECTION_CORE = "core"
SECTION_SPRING = "spring (Java 17+ modules)"
SECTION_TEST = "test"
+SCOPE_TEST = "test"
SPRING_BOOT_GROUP = "org.springframework.boot"
SPRING_FRAMEWORK_GROUP = "org.springframework"
SPRING_BOOT_COORDINATE = "org.springframework.boot:spring-boot"
@@ -32,7 +33,7 @@ class ManagedDependency:
group_id: str
artifact_id: str
version: str
- scope: str = ""
+ scope: str | None = None
@property
def coordinate(self) -> str:
@@ -107,7 +108,7 @@ def resolve(value: str) -> str:
f"{prefix}artifactId", default="", namespaces=namespace
).strip()
version = dependency.findtext(f"{prefix}version", default="", namespaces=namespace).strip()
- scope = dependency.findtext(f"{prefix}scope", default="", namespaces=namespace).strip()
+ scope = dependency.findtext(f"{prefix}scope", default="", namespaces=namespace).strip() or None
if group_id and artifact_id and version:
managed_dependencies.append(
ManagedDependency(
@@ -127,7 +128,7 @@ def classify_dependency(dependency: ManagedDependency) -> str:
# Maven scope is test.
if dependency.group_id == SPRING_FRAMEWORK_GROUP:
return SECTION_SPRING
- if dependency.scope == "test":
+ if dependency.scope == SCOPE_TEST:
return SECTION_TEST
return SECTION_CORE
From 58ff98cc16e0831f5e933de7775e5ebe4ce92e8b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 19 May 2026 01:41:02 +0000
Subject: [PATCH 07/10] Refine sync script error text
---
scripts/sync_bazel_dependencies.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/sync_bazel_dependencies.py b/scripts/sync_bazel_dependencies.py
index bb3f852c06..a1009ce926 100644
--- a/scripts/sync_bazel_dependencies.py
+++ b/scripts/sync_bazel_dependencies.py
@@ -170,7 +170,7 @@ def render_generated_block(managed_dependencies: list[ManagedDependency]) -> str
install_sections, spring_boot_dependencies = partition_dependencies(managed_dependencies)
spring_framework_exclusions = [dependency.coordinate for dependency in install_sections[SECTION_SPRING]]
if not spring_framework_exclusions:
- raise ValueError("No org.springframework dependencies found in dependencyManagement.")
+ raise ValueError("No spring-framework dependencies found in dependencyManagement.")
lines = [
GENERATED_START,
From 813146d2b303eb078ea9b44cba6c733a9c1fe0a4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 19 May 2026 01:41:42 +0000
Subject: [PATCH 08/10] Document sync script helpers
---
scripts/sync_bazel_dependencies.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/scripts/sync_bazel_dependencies.py b/scripts/sync_bazel_dependencies.py
index a1009ce926..0c1496bd1b 100644
--- a/scripts/sync_bazel_dependencies.py
+++ b/scripts/sync_bazel_dependencies.py
@@ -124,8 +124,8 @@ def resolve(value: str) -> str:
def classify_dependency(dependency: ManagedDependency) -> str:
# Keep all org.springframework modules together so the generated spring
# section also doubles as the exclusion list for the spring-boot artifacts.
- # This intentionally keeps spring-test in the spring section even though its
- # Maven scope is test.
+ # The group_id check intentionally runs before the scope check so spring-test
+ # stays in the spring section even though its Maven scope is test.
if dependency.group_id == SPRING_FRAMEWORK_GROUP:
return SECTION_SPRING
if dependency.scope == SCOPE_TEST:
@@ -136,6 +136,7 @@ def classify_dependency(dependency: ManagedDependency) -> str:
def partition_dependencies(
managed_dependencies: list[ManagedDependency],
) -> tuple[dict[str, list[ManagedDependency]], list[ManagedDependency]]:
+ """Split dependencyManagement entries into Bazel install sections and spring boot artifacts."""
install_sections = {
SECTION_CORE: [],
SECTION_SPRING: [],
@@ -160,6 +161,7 @@ def partition_dependencies(
def find_dependency(
dependencies: list[ManagedDependency], coordinate: str
) -> ManagedDependency:
+ """Return the dependency matching a group/artifact coordinate or raise ValueError."""
for dependency in dependencies:
if dependency.coordinate == coordinate:
return dependency
From c1fa31fe166b325528a7f585c99ea6ce980f692e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 19 May 2026 01:42:27 +0000
Subject: [PATCH 09/10] Improve sync script validation errors
---
scripts/sync_bazel_dependencies.py | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/scripts/sync_bazel_dependencies.py b/scripts/sync_bazel_dependencies.py
index 0c1496bd1b..c66133ce5f 100644
--- a/scripts/sync_bazel_dependencies.py
+++ b/scripts/sync_bazel_dependencies.py
@@ -170,9 +170,12 @@ def find_dependency(
def render_generated_block(managed_dependencies: list[ManagedDependency]) -> str:
install_sections, spring_boot_dependencies = partition_dependencies(managed_dependencies)
- spring_framework_exclusions = [dependency.coordinate for dependency in install_sections[SECTION_SPRING]]
- if not spring_framework_exclusions:
+ spring_framework_dependencies = install_sections[SECTION_SPRING]
+ if not spring_framework_dependencies:
raise ValueError("No spring-framework dependencies found in dependencyManagement.")
+ spring_framework_exclusions = [
+ dependency.coordinate for dependency in spring_framework_dependencies
+ ]
lines = [
GENERATED_START,
@@ -189,7 +192,7 @@ def render_generated_block(managed_dependencies: list[ManagedDependency]) -> str
spring_boot_dependencies, SPRING_BOOT_COORDINATE
).version
spring_framework_version = find_dependency(
- install_sections[SECTION_SPRING], SPRING_CORE_COORDINATE
+ spring_framework_dependencies, SPRING_CORE_COORDINATE
).version
lines.extend(
[
@@ -224,8 +227,12 @@ def render_generated_block(managed_dependencies: list[ManagedDependency]) -> str
]
)
- if len({dependency.version for dependency in spring_boot_dependencies}) != 1:
- raise ValueError("Spring Boot artifact versions diverged in dependencyManagement.")
+ spring_boot_versions = {dependency.version for dependency in spring_boot_dependencies}
+ if len(spring_boot_versions) != 1:
+ raise ValueError(
+ "Spring Boot artifact versions diverged in dependencyManagement: "
+ + ", ".join(sorted(spring_boot_versions))
+ )
lines.append(GENERATED_END)
return "\n".join(lines) + "\n"
From 6e42086e9d6aadbe5208873867706d3ec831e044 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 19 May 2026 01:43:18 +0000
Subject: [PATCH 10/10] Document generated dependency ordering
---
MODULE.bazel | 1 +
scripts/sync_bazel_dependencies.py | 1 +
2 files changed, 2 insertions(+)
diff --git a/MODULE.bazel b/MODULE.bazel
index 658e698d04..7580497d75 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -28,6 +28,7 @@ maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
# BEGIN: generated by scripts/sync_bazel_dependencies.py
# Generated from pom.xml by scripts/sync_bazel_dependencies.py.
# Do not edit this block by hand; update pom.xml and rerun the script instead.
+# Artifact order follows pom.xml dependencyManagement order within each section.
maven.install(
artifacts = [
# ---- core ----
diff --git a/scripts/sync_bazel_dependencies.py b/scripts/sync_bazel_dependencies.py
index c66133ce5f..bbef5a7281 100644
--- a/scripts/sync_bazel_dependencies.py
+++ b/scripts/sync_bazel_dependencies.py
@@ -181,6 +181,7 @@ def render_generated_block(managed_dependencies: list[ManagedDependency]) -> str
GENERATED_START,
"# Generated from pom.xml by scripts/sync_bazel_dependencies.py.",
"# Do not edit this block by hand; update pom.xml and rerun the script instead.",
+ "# Artifact order follows pom.xml dependencyManagement order within each section.",
"maven.install(",
" artifacts = [",
]