Skip to content

Commit 61f4130

Browse files
committed
add SPLIT_CI option for using split unit tests
1 parent 6fb6ff0 commit 61f4130

3 files changed

Lines changed: 131 additions & 5 deletions

File tree

monorepo-migration/migrate.sh

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ UPDATE_GENERATION_CONFIG_SCRIPT="$TRANSFORM_SCRIPT_DIR/update_generation_config.
5959
UPDATE_OWLBOT_HERMETIC_SCRIPT="$TRANSFORM_SCRIPT_DIR/update_owlbot_hermetic.py"
6060
TRANSFORM_OWLBOT_SCRIPT="$TRANSFORM_SCRIPT_DIR/update_owlbot.py"
6161
UPDATE_DEP_MGMT_SCRIPT="$TRANSFORM_SCRIPT_DIR/update_dependency_management.py"
62+
UPDATE_CI_FILTERS_SCRIPT="$TRANSFORM_SCRIPT_DIR/update_ci_filters.py"
6263

6364
# Track number of commits made by this script
6465
COMMIT_COUNT=0
@@ -378,8 +379,8 @@ if [ -d "$SOURCE_REPO_NAME/.github/workflows" ]; then
378379
if [ -f "$workflow" ]; then
379380
filename=$(basename "$workflow")
380381

381-
if [[ "${filename}" == "ci.yaml" && "${SKIP_CI_WORKFLOW}" == "true" ]]; then
382-
echo "Skipping ci.yaml workflow as requested by user"
382+
if [[ "${filename}" == "ci.yaml" && ( "${SKIP_CI_WORKFLOW}" == "true" || "${SPLIT_CI}" == "true" ) ]]; then
383+
echo "Skipping ci.yaml workflow as requested by user (SKIP_CI_WORKFLOW=${SKIP_CI_WORKFLOW}, SPLIT_CI=${SPLIT_CI})"
383384
continue
384385
fi
385386

@@ -412,6 +413,19 @@ if [ -d "$SOURCE_REPO_NAME/.github/workflows" ]; then
412413
COMMIT_COUNT=$((COMMIT_COUNT + 1))
413414
fi
414415

416+
# 7.5b Update central ci.yaml filters if SPLIT_CI is true
417+
if [ "${SPLIT_CI}" == "true" ]; then
418+
CI_YAML=".github/workflows/ci.yaml"
419+
if [ -f "$CI_YAML" ]; then
420+
echo "Adding $SOURCE_REPO_NAME to $CI_YAML filters..."
421+
python3 "$UPDATE_CI_FILTERS_SCRIPT" "$CI_YAML" "$SOURCE_REPO_NAME"
422+
echo "Committing ci.yaml filter update..."
423+
git add "$CI_YAML"
424+
git commit -n --no-gpg-sign -m "chore($SOURCE_REPO_NAME): add to filters in $CI_YAML"
425+
COMMIT_COUNT=$((COMMIT_COUNT + 1))
426+
fi
427+
fi
428+
415429
# 7.6 Update generation_config.yaml
416430
echo "Updating generation_config.yaml..."
417431
SOURCE_CONFIG="$SOURCE_REPO_NAME/generation_config.yaml"
@@ -524,7 +538,11 @@ modernize_and_extract() {
524538
# 7.11 Modernize root pom.xml
525539
echo "Modernizing root pom.xml..."
526540
PARENT_VERSION=$(grep -m 1 "<version>.*{x-version-update:google-cloud-java:current}" google-cloud-jar-parent/pom.xml | sed -E 's/.*<version>(.*)<\/version>.*/\1/')
527-
modernize_and_extract "$SOURCE_REPO_NAME/pom.xml" "$PARENT_VERSION" --source-repo "$SOURCE_REPO_NAME"
541+
EXTRA_MODERNIZE_ARGS=""
542+
if [ "${SPLIT_CI}" == "true" ]; then
543+
EXTRA_MODERNIZE_ARGS="--add-bulk-tests-profile"
544+
fi
545+
modernize_and_extract "$SOURCE_REPO_NAME/pom.xml" "$PARENT_VERSION" --source-repo "$SOURCE_REPO_NAME" $EXTRA_MODERNIZE_ARGS
528546

529547
echo "Committing root pom.xml modernization..."
530548
git add "$SOURCE_REPO_NAME/pom.xml"

monorepo-migration/modernize_pom.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def get_monorepo_versions(monorepo_root='.'):
171171
versions[artifactId] = version
172172
return versions
173173

174-
def modernize_pom(file_path, parent_version, source_repo_name=None, parent_artifactId='google-cloud-jar-parent', relative_path='../google-cloud-jar-parent/pom.xml', monorepo_versions=None, parent_managed_deps=None, keep_parent=False):
174+
def modernize_pom(file_path, parent_version, source_repo_name=None, parent_artifactId='google-cloud-jar-parent', relative_path='../google-cloud-jar-parent/pom.xml', monorepo_versions=None, parent_managed_deps=None, keep_parent=False, add_bulk_tests_profile=False):
175175
with open(file_path, 'r') as f:
176176
lines = f.readlines()
177177

@@ -196,6 +196,15 @@ def modernize_pom(file_path, parent_version, source_repo_name=None, parent_artif
196196
should_preserve = False
197197
current_group_id = None
198198
has_version = False
199+
in_profiles = False
200+
has_bulk_tests_profile = False
201+
profiles_lines = []
202+
203+
# Check if bulkTests profile already exists if we might add it
204+
if add_bulk_tests_profile:
205+
bulk_tests_pattern = r'<id>\s*bulkTests\s*</id>'
206+
if re.search(bulk_tests_pattern, "".join(lines)):
207+
has_bulk_tests_profile = True
199208

200209
for line in lines:
201210
# URL Modernization
@@ -231,6 +240,17 @@ def modernize_pom(file_path, parent_version, source_repo_name=None, parent_artif
231240
if '<id>native-test</id>' in line:
232241
line = line.replace('<id>native-test</id>', '<id>native</id>')
233242

243+
# Track if we are in profiles section to potentially add bulkTests there
244+
if '<profiles>' in line:
245+
in_profiles = True
246+
if '</profiles>' in line:
247+
in_profiles = False
248+
if add_bulk_tests_profile and not has_bulk_tests_profile:
249+
# Add bulkTests profile before closing </profiles>
250+
indent = " "
251+
line = f"{indent}<profile>\n{indent} <id>bulkTests</id>\n{indent} <properties>\n{indent} <skipTests>true</skipTests>\n{indent} </properties>\n{indent}</profile>\n{line}"
252+
has_bulk_tests_profile = True
253+
234254
# Parent section modernization
235255
if not keep_parent:
236256
if '<parent>' in line and not in_parent:
@@ -469,6 +489,25 @@ def modernize_pom(file_path, parent_version, source_repo_name=None, parent_artif
469489

470490
new_lines.append(line)
471491

492+
# If bulkTests profile was requested but no <profiles> section existed
493+
if add_bulk_tests_profile and not has_bulk_tests_profile:
494+
# Find the last line that isn't </project> and empty space
495+
for i in range(len(new_lines) - 1, -1, -1):
496+
if '</project>' in new_lines[i]:
497+
indent = " "
498+
profile_block = (
499+
f"\n{indent}<profiles>\n"
500+
f"{indent} <profile>\n"
501+
f"{indent} <id>bulkTests</id>\n"
502+
f"{indent} <properties>\n"
503+
f"{indent} <skipTests>true</skipTests>\n"
504+
f"{indent} </properties>\n"
505+
f"{indent} </profile>\n"
506+
f"{indent}</profiles>\n"
507+
)
508+
new_lines.insert(i, profile_block)
509+
break
510+
472511
with open(file_path, 'w') as f:
473512
# Clean up double empty lines potentially introduced by pruning
474513
content = "".join(new_lines)
@@ -483,6 +522,7 @@ def modernize_pom(file_path, parent_version, source_repo_name=None, parent_artif
483522
parser.add_argument("--parent-artifactId", default="google-cloud-jar-parent", help="Artifact ID of the parent POM.")
484523
parser.add_argument("--relative-path", default="../google-cloud-jar-parent/pom.xml", help="Relative path to the parent POM.")
485524
parser.add_argument("--keep-parent", action="store_true", help="Keep the existing parent section.")
525+
parser.add_argument("--add-bulk-tests-profile", action="store_true", help="Add bulkTests profile to skip tests.")
486526

487527
args = parser.parse_args()
488528

@@ -506,6 +546,7 @@ def modernize_pom(file_path, parent_version, source_repo_name=None, parent_artif
506546
args.relative_path,
507547
monorepo_versions,
508548
parent_managed_deps,
509-
args.keep_parent
549+
args.keep_parent,
550+
args.add_bulk_tests_profile
510551
)
511552

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env python3
2+
# Copyright 2026 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import argparse
17+
import os
18+
19+
def update_ci_filters(ci_yaml, repo_name):
20+
if not os.path.exists(ci_yaml):
21+
print(f"Error: {ci_yaml} does not exist.")
22+
return
23+
24+
with open(ci_yaml, "r") as f:
25+
lines = f.readlines()
26+
27+
final_lines = []
28+
in_filters = False
29+
filter_lines = []
30+
new_filter = f" {repo_name}: {repo_name}/**\n"
31+
32+
for line in lines:
33+
if "filters: |" in line:
34+
final_lines.append(line)
35+
in_filters = True
36+
continue
37+
38+
if in_filters:
39+
# End of filter block is an empty line or line with less indentation
40+
if line.strip() == "" or not line.startswith(" "):
41+
if not any(f" {repo_name}:" in l for l in filter_lines):
42+
filter_lines.append(new_filter)
43+
filter_lines.sort()
44+
final_lines.extend(filter_lines)
45+
final_lines.append(line)
46+
in_filters = False
47+
else:
48+
filter_lines.append(line)
49+
else:
50+
final_lines.append(line)
51+
52+
if in_filters:
53+
if not any(f" {repo_name}:" in l for l in filter_lines):
54+
filter_lines.append(new_filter)
55+
filter_lines.sort()
56+
final_lines.extend(filter_lines)
57+
58+
with open(ci_yaml, "w") as f:
59+
f.writelines(final_lines)
60+
61+
if __name__ == "__main__":
62+
parser = argparse.ArgumentParser(description="Update central ci.yaml filters.")
63+
parser.add_argument("ci_yaml", help="Path to the ci.yaml file.")
64+
parser.add_argument("repo_name", help="Name of the repository to add to filters.")
65+
args = parser.parse_args()
66+
67+
update_ci_filters(args.ci_yaml, args.repo_name)

0 commit comments

Comments
 (0)