@@ -29,6 +29,8 @@ check_command() {
2929check_command git
3030check_command python3
3131check_command mvn
32+ check_command jq
33+ check_command git-filter-repo
3234
3335# Configuration
3436MONOREPO_URL=" https://github.com/googleapis/google-cloud-java"
@@ -56,6 +58,7 @@ FIX_COPYRIGHT_SCRIPT="$TRANSFORM_SCRIPT_DIR/fix_copyright_headers.py"
5658UPDATE_GENERATION_CONFIG_SCRIPT=" $TRANSFORM_SCRIPT_DIR /update_generation_config.py"
5759UPDATE_OWLBOT_HERMETIC_SCRIPT=" $TRANSFORM_SCRIPT_DIR /update_owlbot_hermetic.py"
5860TRANSFORM_OWLBOT_SCRIPT=" $TRANSFORM_SCRIPT_DIR /update_owlbot.py"
61+ UPDATE_DEP_MGMT_SCRIPT=" $TRANSFORM_SCRIPT_DIR /update_dependency_management.py"
5962
6063# Track number of commits made by this script
6164COMMIT_COUNT=0
@@ -72,14 +75,22 @@ echo "Basing migration branch on: ${MIGRATION_HEAD_BRANCH}"
7275if [ ! -d " $SOURCE_DIR " ]; then
7376 echo " Cloning source repo: $SOURCE_REPO_URL into $SOURCE_DIR "
7477 git clone " $SOURCE_REPO_URL " " $SOURCE_DIR "
78+ fi
79+
80+ if [ " $SKIP_SOURCE_UPDATE " == " true" ]; then
81+ echo " Skipping source update"
7582else
76- echo " Source directory $SOURCE_DIR already exists. Ensuring it is clean and up-to-date..."
77- cd " $SOURCE_DIR "
83+ pushd " $SOURCE_DIR "
7884 git fetch origin
7985 git checkout -f " main"
8086 git reset --hard origin/main
8187 git clean -fd
82- cd - > /dev/null
88+
89+ # 1.1 Modify history of the split repo to move files to the destination target directory
90+ echo " Moving files to destination path: ${SOURCE_REPO_NAME} "
91+ git filter-repo \
92+ --to-subdirectory-filter " ${SOURCE_REPO_NAME} " --force
93+ popd
8394fi
8495
8596# 1.5 Extract CODEOWNERS from source repository as default
147158
148159
149160# 2.5 Create a new feature branch for the migration
150- BRANCH_NAME=" migrate-$SOURCE_REPO_NAME "
161+ BRANCH_NAME_SUFFIX=" ${BRANCH_NAME_SUFFIX:- } "
162+ BRANCH_NAME=" migrate-${SOURCE_REPO_NAME}${BRANCH_NAME_SUFFIX} "
151163echo " Creating feature branch: $BRANCH_NAME "
152164if git rev-parse --verify " $BRANCH_NAME " > /dev/null 2>&1 ; then
153165 git branch -D " $BRANCH_NAME "
@@ -167,11 +179,8 @@ git fetch "$SOURCE_REPO_NAME"
167179
168180# 5. Merge the histories using 'ours' strategy to keep monorepo content
169181echo " Merging histories (strategy: ours)..."
170- git merge --allow-unrelated-histories --no-ff " $SOURCE_REPO_NAME /main" -s ours --no-commit -m " chore($SOURCE_REPO_NAME ): migrate $SOURCE_REPO_NAME into monorepo"
171-
172- # 6. Read the tree from the source repo into the desired subdirectory
173- echo " Reading tree into prefix $SOURCE_REPO_NAME /..."
174- git read-tree --prefix=" $SOURCE_REPO_NAME /" -u " $SOURCE_REPO_NAME /main"
182+ # git merge --allow-unrelated-histories -s ours --no-ff "$SOURCE_REPO_NAME/main" --no-commit -m "chore($SOURCE_REPO_NAME): migrate $SOURCE_REPO_NAME into monorepo"
183+ git merge --allow-unrelated-histories --no-commit " $SOURCE_REPO_NAME /main" -m " chore($SOURCE_REPO_NAME ): migrate $SOURCE_REPO_NAME into monorepo"
175184
176185# 6.5 Remove common files from the root of the migrated library
177186echo " Removing common files from the root of $SOURCE_REPO_NAME /..."
@@ -180,7 +189,154 @@ rm -f "$SOURCE_REPO_NAME/renovate.json"
180189rm -f " $SOURCE_REPO_NAME /LICENSE"
181190rm -f " $SOURCE_REPO_NAME /java.header"
182191rm -rf " $SOURCE_REPO_NAME /.kokoro"
192+ git checkout -- " $SOURCE_REPO_NAME /.kokoro/presubmit/*.sh" || true
183193# rm -rf "$SOURCE_REPO_NAME/.kokoro/continuous" "$SOURCE_REPO_NAME/.kokoro/nightly" "$SOURCE_REPO_NAME/.kokoro/presubmit"
194+
195+ # 6.6 Create split integration config if needed
196+ SOURCE_INTEGRATION_CFG=" $SOURCE_DIR /.kokoro/presubmit/integration.cfg"
197+ if [ -f " $SOURCE_INTEGRATION_CFG " ]; then
198+ echo " Creating split integration config for $SOURCE_REPO_NAME ..."
199+ SHORT_NAME=" ${SOURCE_REPO_NAME# java-} "
200+ TARGET_INTEGRATION_CFG=" .kokoro/presubmit/${SHORT_NAME} -integration.cfg"
201+
202+ cp " $SOURCE_INTEGRATION_CFG " " $TARGET_INTEGRATION_CFG "
203+
204+ # Replace JOB_TYPE with integration-single. Robustly handle multi-line or single-line.
205+ perl -0777 -i -pe ' s/(key:\s*"JOB_TYPE"\s*value:\s*")[^"]*(")/$1integration-single$2/g' " $TARGET_INTEGRATION_CFG "
206+
207+ # Append BUILD_SUBDIR
208+ cat << EOF >> "$TARGET_INTEGRATION_CFG "
209+
210+ env_vars: {
211+ key: "BUILD_SUBDIR"
212+ value: "$SOURCE_REPO_NAME "
213+ }
214+ EOF
215+
216+ if [ -n " $INTEGRATION_TEST_ARGS " ]; then
217+ cat << EOF >> "$TARGET_INTEGRATION_CFG "
218+
219+ env_vars: {
220+ key: "INTEGRATION_TEST_ARGS"
221+ value: "$INTEGRATION_TEST_ARGS "
222+ }
223+ EOF
224+ fi
225+
226+ if [ -n " $EXTRA_KOKORO_ENVS " ]; then
227+ OLD_IFS=" $IFS "
228+ IFS=' ,'
229+ for env in $EXTRA_KOKORO_ENVS ; do
230+ key=" ${env%% =* } "
231+ value=" ${env#* =} "
232+ cat << EOF >> "$TARGET_INTEGRATION_CFG "
233+
234+ env_vars: {
235+ key: "$key "
236+ value: "$value "
237+ }
238+ EOF
239+ done
240+ IFS=" $OLD_IFS "
241+ fi
242+
243+ if [ " ${TEST_WITH_EXISTING:- false} " = " true" ]; then
244+ echo " Copying to logging-integration.cfg for testing..."
245+ cp " $TARGET_INTEGRATION_CFG " " .kokoro/presubmit/logging-integration.cfg"
246+ git add " .kokoro/presubmit/logging-integration.cfg"
247+ fi
248+
249+ echo " Committing split integration config..."
250+ git add " $TARGET_INTEGRATION_CFG "
251+ git commit -n --no-gpg-sign -m " chore($SOURCE_REPO_NAME ): create split integration config"
252+ COMMIT_COUNT=$(( COMMIT_COUNT + 1 ))
253+ fi
254+
255+ # 6.6b Create split GraalVM config if needed
256+ SOURCE_GRAALVM_CFG=" $SOURCE_DIR /.kokoro/presubmit/graalvm-native-a.cfg"
257+ if [ -f " $SOURCE_GRAALVM_CFG " ]; then
258+ echo " Creating split GraalVM config for $SOURCE_REPO_NAME ..."
259+ SHORT_NAME=" ${SOURCE_REPO_NAME# java-} "
260+ TARGET_GRAALVM_CFG=" .kokoro/presubmit/${SHORT_NAME} -graalvm-native-presubmit.cfg"
261+
262+ cp " $SOURCE_GRAALVM_CFG " " $TARGET_GRAALVM_CFG "
263+
264+ # Replace JOB_TYPE with graalvm-single. Robustly handle multi-line or single-line.
265+ perl -0777 -i -pe ' s/(key:\s*"JOB_TYPE"\s*value:\s*")[^"]*(")/$1graalvm-single$2/g' " $TARGET_GRAALVM_CFG "
266+
267+ # Append BUILD_SUBDIR
268+ cat << EOF >> "$TARGET_GRAALVM_CFG "
269+
270+ env_vars: {
271+ key: "BUILD_SUBDIR"
272+ value: "$SOURCE_REPO_NAME "
273+ }
274+ EOF
275+
276+ if [ -n " $INTEGRATION_TEST_ARGS " ]; then
277+ cat << EOF >> "$TARGET_GRAALVM_CFG "
278+
279+ env_vars: {
280+ key: "INTEGRATION_TEST_ARGS"
281+ value: "$INTEGRATION_TEST_ARGS "
282+ }
283+ EOF
284+ fi
285+
286+ if [ -n " $EXTRA_KOKORO_ENVS " ]; then
287+ OLD_IFS=" $IFS "
288+ IFS=' ,'
289+ for env in $EXTRA_KOKORO_ENVS ; do
290+ key=" ${env%% =* } "
291+ value=" ${env#* =} "
292+ cat << EOF >> "$TARGET_GRAALVM_CFG "
293+
294+ env_vars: {
295+ key: "$key "
296+ value: "$value "
297+ }
298+ EOF
299+ done
300+ IFS=" $OLD_IFS "
301+ fi
302+
303+ if [ " ${TEST_WITH_EXISTING:- false} " = " true" ]; then
304+ echo " Copying to logging-graalvm-native-presubmit.cfg for testing..."
305+ cp " $TARGET_GRAALVM_CFG " " .kokoro/presubmit/logging-graalvm-native-presubmit.cfg"
306+ git add " .kokoro/presubmit/logging-graalvm-native-presubmit.cfg"
307+ fi
308+
309+ echo " Committing split GraalVM config..."
310+ git add " $TARGET_GRAALVM_CFG "
311+ git commit -n --no-gpg-sign -m " chore($SOURCE_REPO_NAME ): create split GraalVM config"
312+ COMMIT_COUNT=$(( COMMIT_COUNT + 1 ))
313+ fi
314+
315+ # 6.7 Update excluded_modules in .kokoro/common.sh
316+ COMMON_SH=" .kokoro/common.sh"
317+ if [ -f " $COMMON_SH " ]; then
318+ echo " Updating excluded_modules in $COMMON_SH ..."
319+ # Insert the new module name before the closing parenthesis of the excluded_modules array
320+ sed -i " /^excluded_modules=(/,/^)/ s/^)/ '$SOURCE_REPO_NAME '\n)/" " $COMMON_SH "
321+
322+ echo " Committing excluded_modules update..."
323+ git add " $COMMON_SH "
324+ git commit -n --no-gpg-sign -m " chore($SOURCE_REPO_NAME ): add to excluded_modules in .kokoro/common.sh"
325+ COMMIT_COUNT=$(( COMMIT_COUNT + 1 ))
326+ fi
327+
328+ # 6.8 Update .repo-metadata.json if it exists
329+ REPO_METADATA=" $SOURCE_REPO_NAME /.repo-metadata.json"
330+ if [ -f " $REPO_METADATA " ]; then
331+ echo " Updating $REPO_METADATA ..."
332+ # Update "repo" to googleapis/google-cloud-java and "repo_short" to google-cloud-java
333+ jq ' .repo = "googleapis/google-cloud-java" | .repo_short = "google-cloud-java"' " $REPO_METADATA " > " ${REPO_METADATA} .tmp" && mv " ${REPO_METADATA} .tmp" " $REPO_METADATA "
334+
335+ echo " Committing $REPO_METADATA update..."
336+ git add " $REPO_METADATA "
337+ git commit -n --no-gpg-sign -m " chore($SOURCE_REPO_NAME ): update .repo-metadata.json"
338+ COMMIT_COUNT=$(( COMMIT_COUNT + 1 ))
339+ fi
184340rm -f " $SOURCE_REPO_NAME /codecov.yaml"
185341rm -f " $SOURCE_REPO_NAME /synth.metadata"
186342rm -f " $SOURCE_REPO_NAME /license-checks.xml"
@@ -223,6 +379,11 @@ if [ -d "$SOURCE_REPO_NAME/.github/workflows" ]; then
223379 if [ -f " $workflow " ]; then
224380 filename=$( basename " $workflow " )
225381
382+ if [ " ${filename} " == " ci.yaml" && " ${SKIP_CI_WORKFLOW} " == " true" ]; then
383+ echo " Skipping ci.yaml workflow as requested by user"
384+ continue
385+ fi
386+
226387 # Skip redundant workflows as requested by user
227388 case " $filename " in
228389 " hermetic_library_generation.yaml" | " update_generation_config.yaml" | \
@@ -243,6 +404,7 @@ if [ -d "$SOURCE_REPO_NAME/.github/workflows" ]; then
243404
244405 # Cleanup empty .github directory if it exists
245406 rm -rf " $SOURCE_REPO_NAME /.github"
407+ git checkout -- " $SOURCE_REPO_NAME /.github/scripts" || true
246408 git add -- " $SOURCE_REPO_NAME /.github"
247409
248410 echo " Committing workflow migration..."
@@ -266,6 +428,19 @@ if [ -f "$SOURCE_CONFIG" ]; then
266428 COMMIT_COUNT=$(( COMMIT_COUNT + 1 ))
267429fi
268430
431+ # 7.6b Update generation/check_non_release_please_versions.sh
432+ CHECK_VERSIONS_SCRIPT=" generation/check_non_release_please_versions.sh"
433+ if [ -f " $CHECK_VERSIONS_SCRIPT " ]; then
434+ echo " Updating exclusions in $CHECK_VERSIONS_SCRIPT ..."
435+ # Insert the new module name before the .github exclusion
436+ sed -i " /\.github\*\./ i \ [[ \"\$ {pomFile}\" =~ .*$SOURCE_REPO_NAME .* ]] || \\\\ " " $CHECK_VERSIONS_SCRIPT "
437+
438+ echo " Committing $CHECK_VERSIONS_SCRIPT update..."
439+ git add " $CHECK_VERSIONS_SCRIPT "
440+ git commit -n --no-gpg-sign -m " chore($SOURCE_REPO_NAME ): add to exclusions in $CHECK_VERSIONS_SCRIPT "
441+ COMMIT_COUNT=$(( COMMIT_COUNT + 1 ))
442+ fi
443+
269444# 7.7 Consolidate versions.txt
270445echo " Consolidating versions.txt..."
271446SOURCE_VERSIONS=" $SOURCE_REPO_NAME /versions.txt"
323498# git commit -n --no-gpg-sign -m "chore($SOURCE_REPO_NAME): update copyright headers to 2026 Google LLC"
324499# COMMIT_COUNT=$((COMMIT_COUNT + 1))
325500
501+ # 7.10 Modernize pom.xml files and extract google-api-services dependencies
502+ modernize_and_extract () {
503+ local pom_file=" $1 "
504+ shift
505+ local cmd_output
506+ cmd_output=$( python3 " $MODERNIZE_POM_SCRIPT " " $pom_file " " $@ " 2>&1 )
507+ echo " $cmd_output " | grep -v " EXTRACT_DEP:" || true
508+
509+ # Process extracted dependencies
510+ echo " $cmd_output " | grep " EXTRACT_DEP:" | while read -r line; do
511+ dep_info=" ${line# EXTRACT_DEP: } "
512+ IFS=' :' read -r gid aid ver <<< " $dep_info"
513+ echo " Extracting $gid :$aid :$ver to parent POM..."
514+ python3 " $UPDATE_DEP_MGMT_SCRIPT " " google-cloud-jar-parent/pom.xml" " $gid " " $aid " " $ver "
515+
516+ # Commit parent POM change if anything changed
517+ if git diff --name-only | grep -q " google-cloud-jar-parent/pom.xml" ; then
518+ git add " google-cloud-jar-parent/pom.xml"
519+ git commit -n --no-gpg-sign -m " chore($SOURCE_REPO_NAME ): manage $aid in parent POM"
520+ COMMIT_COUNT=$(( COMMIT_COUNT + 1 ))
521+ fi
522+ done
523+ }
524+
326525# 7.11 Modernize root pom.xml
327526echo " Modernizing root pom.xml..."
328527PARENT_VERSION=$( grep -m 1 " <version>.*{x-version-update:google-cloud-java:current}" google-cloud-jar-parent/pom.xml | sed -E ' s/.*<version>(.*)<\/version>.*/\1/' )
329- python3 " $MODERNIZE_POM_SCRIPT " " $ SOURCE_REPO_NAME /pom.xml" " $PARENT_VERSION " " $SOURCE_REPO_NAME "
528+ modernize_and_extract " $SOURCE_REPO_NAME /pom.xml" " $PARENT_VERSION " --source-repo " $SOURCE_REPO_NAME "
330529
331530echo " Committing root pom.xml modernization..."
332531git add " $SOURCE_REPO_NAME /pom.xml"
@@ -340,18 +539,40 @@ echo "Modernizing BOM pom.xml..."
340539while read -r bom_pom; do
341540 echo " Modernizing BOM: $bom_pom "
342541 # BOMs should inherit from google-cloud-pom-parent
343- python3 " $MODERNIZE_POM_SCRIPT " " $ bom_pom" " $PARENT_VERSION " " $SOURCE_REPO_NAME " " google-cloud-pom-parent" " ../../google-cloud-pom-parent/pom.xml"
542+ modernize_and_extract " $bom_pom " " $PARENT_VERSION " --source-repo " $SOURCE_REPO_NAME " --parent-artifactId " google-cloud-pom-parent" --relative-path " ../../google-cloud-pom-parent/pom.xml"
344543
345544 echo " Committing BOM pom.xml modernization for $bom_pom ..."
346545 git add " $bom_pom "
347546 git commit -n --no-gpg-sign -m " chore($SOURCE_REPO_NAME ): modernize BOM pom.xml"
348547 COMMIT_COUNT=$(( COMMIT_COUNT + 1 ))
349548done < <( find " $SOURCE_REPO_NAME " -name " pom.xml" | grep " \-bom/pom.xml" | grep -v " samples" )
350549
550+ # 7.12b Modernize other pom.xml files
551+ echo " Modernizing other pom.xml files..."
552+ while read -r other_pom; do
553+ echo " Modernizing submodule POM: $other_pom "
554+ # Preserve the existing parent, but update everything else
555+ modernize_and_extract " $other_pom " " $PARENT_VERSION " --source-repo " $SOURCE_REPO_NAME " --keep-parent
556+
557+ echo " Committing submodule pom.xml modernization for $other_pom ..."
558+ git add " $other_pom " && git commit -n --no-gpg-sign -m " chore($SOURCE_REPO_NAME ): modernize submodule pom.xml" && COMMIT_COUNT=$(( COMMIT_COUNT + 1 )) || true
559+ done < <( find " $SOURCE_REPO_NAME " -name " pom.xml" | grep -v " \-bom/pom.xml" | grep -v " samples" | grep -v " test_data" )
560+
351561# 7.11 Verify compilation
352562echo " Verifying compilation..."
353- BUILD_SUBDIR=" ${SOURCE_REPO_NAME} " JOB_TYPE=test .kokoro/build.sh
354- # (cd "$SOURCE_REPO_NAME" && mvn compile -DskipTests -T 1C)
563+ if [[ " ${SKIP_TESTS:- false} " != " true" ]]; then
564+ BUILD_SUBDIR=" ${SOURCE_REPO_NAME} " JOB_TYPE=test .kokoro/build.sh
565+ fi
566+
567+ # 7.12 Apply manual changes
568+ if [[ -f " ~/${SOURCE_REPO_NAME} .diff" ]]; then
569+ echo " Applying diff from ${SOURCE_REPO_NAME} .diff..."
570+ git apply " ~/${SOURCE_REPO_NAME} .diff"
571+ echo " Committing diff..."
572+ git add .
573+ git commit -am " manual changes"
574+ COMMIT_COUNT=$(( COMMIT_COUNT + 1 ))
575+ fi
355576
356577# 7.13 Squash commits
357578if [ " ${SQUASH_COMMITS:- false} " = " true" ]; then
@@ -370,14 +591,14 @@ if [ "${SQUASH_COMMITS:-false}" = "true" ]; then
370591 # then commit --amend adds those staged changes to C1.
371592
372593 git reset --soft " HEAD~$(( COMMIT_COUNT - 1 )) "
373- git commit --amend --no-edit --no-gpg-sign
594+ git commit --amend --no-edit --no-gpg-sign -m " chore( $SOURCE_REPO_NAME ): migrate $SOURCE_REPO_NAME into monorepo "
374595 echo " Squashed everything into one commit."
375596 fi
376597fi
377598
378599# 8. Cleanup
379600echo " Cleaning up temporary source clone..."
380- rm -rf " $SOURCE_DIR "
601+ # rm -rf "$SOURCE_DIR"
381602
382603echo " Migration complete!"
383604echo " The migrated codebase is available in: $TARGET_DIR "
0 commit comments