Repository: googleapis/java-storage
Pull request #2544 (2024-05-09 22:29:39)

chore(deps): update dependency com.google.cloud:libraries-bom to v26.39.0
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [com.google.cloud:libraries-bom](https://cloud.google.com/java/docs/bom) ([source](https://togithub.com/googleapis/java-cloud-bom)) | `26.38.0` -> `26.39.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.39.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.39.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.38.0/26.39.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.38.0/26.39.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>googleapis/java-cloud-bom (com.google.cloud:libraries-bom)</summary>

### [`v26.39.0`](https://togithub.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26390-2024-05-09)

[Compare Source](https://togithub.com/googleapis/java-cloud-bom/compare/v26.38.0...v26.39.0)

##### Dependencies

-   update actions/checkout action to v4 ([#&#8203;6557](https://togithub.com/googleapis/java-cloud-bom/issues/6557)) ([ccf746b](https://togithub.com/googleapis/java-cloud-bom/commit/ccf746b48d9fcaa80dd427594215d0a360c133b0))
-   update actions/github-script action to v7 ([#&#8203;6558](https://togithub.com/googleapis/java-cloud-bom/issues/6558)) ([9f3d444](https://togithub.com/googleapis/java-cloud-bom/commit/9f3d4444c6d7e05c95ef544b10b3fc2a9c9c9f29))
-   update actions/setup-java action to v4 ([#&#8203;6561](https://togithub.com/googleapis/java-cloud-bom/issues/6561)) ([461a963](https://togithub.com/googleapis/java-cloud-bom/commit/461a96367d19552014d07f036f6c65b3b975fd53))
-   update actions/setup-node action to v4 ([#&#8203;6562](https://togithub.com/googleapis/java-cloud-bom/issues/6562)) ([15014fa](https://togithub.com/googleapis/java-cloud-bom/commit/15014fa870dd50119eed40e53b81f39e1176209e))
-   update dependency com.google.cloud:first-party-dependencies to v3.30.0 ([#&#8203;6567](https://togithub.com/googleapis/java-cloud-bom/issues/6567)) ([1f8fbe0](https://togithub.com/googleapis/java-cloud-bom/commit/1f8fbe09eb8fb26b7548c4dff12b1d46e570e84e))
-   update dependency com.google.cloud:gapic-libraries-bom to v1.37.0 ([#&#8203;6578](https://togithub.com/googleapis/java-cloud-bom/issues/6578)) ([a8a51bf](https://togithub.com/googleapis/java-cloud-bom/commit/a8a51bf6798fe5b0375f50c025d488bbd57e0101))
-   update dependency com.google.cloud:google-cloud-bigquery to v2.40.1 ([#&#8203;6579](https://togithub.com/googleapis/java-cloud-bom/issues/6579)) ([d118387](https://togithub.com/googleapis/java-cloud-bom/commit/d1183874887d0a09b26d9b7fd7c8ffaac700ac06))
-   update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.5.1 ([#&#8203;6570](https://togithub.com/googleapis/java-cloud-bom/issues/6570)) ([2fbb407](https://togithub.com/googleapis/java-cloud-bom/commit/2fbb407ceb0c9720151e7dc5e31977ae5afea3f8))
-   update dependency com.google.cloud:google-cloud-bigtable-bom to v2.39.1 ([#&#8203;6574](https://togithub.com/googleapis/java-cloud-bom/issues/6574)) ([23c12df](https://togithub.com/googleapis/java-cloud-bom/commit/23c12dfa5e01e54219d60c078189292b0e51bb8e))
-   update dependency com.google.cloud:google-cloud-bigtable-bom to v2.39.2 ([#&#8203;6582](https://togithub.com/googleapis/java-cloud-bom/issues/6582)) ([54c33f0](https://togithub.com/googleapis/java-cloud-bom/commit/54c33f02fc6dac0fad17925f8a480f990cd94bc1))
-   update dependency com.google.cloud:google-cloud-datastore-bom to v2.19.2 ([#&#8203;6571](https://togithub.com/googleapis/java-cloud-bom/issues/6571)) ([3fadbe1](https://togithub.com/googleapis/java-cloud-bom/commit/3fadbe17043a896e23137d3b16222bd231065705))
-   update dependency com.google.cloud:google-cloud-firestore-bom to v3.21.1 ([#&#8203;6569](https://togithub.com/googleapis/java-cloud-bom/issues/6569)) ([802739c](https://togithub.com/googleapis/java-cloud-bom/commit/802739ca070707428200920eabf9831e70480ece))
-   update dependency com.google.cloud:google-cloud-logging-bom to v3.17.1 ([#&#8203;6575](https://togithub.com/googleapis/java-cloud-bom/issues/6575)) ([1557cf9](https://togithub.com/googleapis/java-cloud-bom/commit/1557cf9b15bfe589286fd3839b442659294db30a))
-   update dependency com.google.cloud:google-cloud-logging-logback to v0.131.6-alpha ([#&#8203;6576](https://togithub.com/googleapis/java-cloud-bom/issues/6576)) ([db2e1d7](https://togithub.com/googleapis/java-cloud-bom/commit/db2e1d705cfe65ec0180be70613fdc49fc64dccb))
-   update dependency com.google.cloud:google-cloud-nio to v0.127.17 ([#&#8203;6583](https://togithub.com/googleapis/java-cloud-bom/issues/6583)) ([ca0fe00](https://togithub.com/googleapis/java-cloud-bom/commit/ca0fe00e4d2a85dca2971f549bb1e6c00b4a4ac7))
-   update dependency com.google.cloud:google-cloud-pubsub-bom to v1.129.3 ([#&#8203;6565](https://togithub.com/googleapis/java-cloud-bom/issues/6565)) ([dd7920f](https://togithub.com/googleapis/java-cloud-bom/commit/dd7920f479c26b999fff5b31aa685e24a5458844))
-   update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.13.5 ([#&#8203;6577](https://togithub.com/googleapis/java-cloud-bom/issues/6577)) ([637b303](https://togithub.com/googleapis/java-cloud-bom/commit/637b3031a25caea28ba1b7feb2ada67eb735fa9e))
-   update dependency com.google.cloud:google-cloud-spanner-bom to v6.66.0 ([#&#8203;6568](https://togithub.com/googleapis/java-cloud-bom/issues/6568)) ([1fe64e6](https://togithub.com/googleapis/java-cloud-bom/commit/1fe64e6a1be49ac15db2ac94f98a2dcedca2e733))
-   update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.18.0 ([#&#8203;6566](https://togithub.com/googleapis/java-cloud-bom/issues/6566)) ([5c459c4](https://togithub.com/googleapis/java-cloud-bom/commit/5c459c446b1df1ff295cb0c0a0d5731506fc20d7))
-   update dependency com.google.cloud:google-cloud-storage-bom to v2.38.0 ([#&#8203;6581](https://togithub.com/googleapis/java-cloud-bom/issues/6581)) ([eb1590f](https://togithub.com/googleapis/java-cloud-bom/commit/eb1590f05eb21cec095bef7929095ba88993b3d7))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/googleapis/java-storage).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNTEuMiIsInVwZGF0ZWRJblZlciI6IjM3LjM1MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->


forking-renovate[bot]: ### Edited/Blocked Notification

Renovate will not automatically rebase this PR, because it does not recognize the last commit author and assumes somebody else may have edited the PR.

You can manually request rebase by checking the rebase/retry box above.

 ⚠️ **Warning**: custom changes will be lost.

Patch:
diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml
index 6983bb26..5db36a5f 100644
--- a/.github/.OwlBot.lock.yaml
+++ b/.github/.OwlBot.lock.yaml
@@ -13,5 +13,5 @@
 # limitations under the License.
 docker:
   image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest
-  digest: sha256:25b384ee1674eda3984ec41c15b514a63bbeb5eda4d57c73c7e6f5adef2fd2f1
-# created: 2024-04-05T19:12:34.133475268Z
+  digest: sha256:68ba5f5164a4b55529d358bb262feaa000536a0c62980727dd05a91bbb47ea5e
+# created: 2024-05-09T16:31:37.168667071Z
diff --git a/.github/trusted-contribution.yml b/.github/trusted-contribution.yml
index a0ba1f7d..88d3ac9b 100644
--- a/.github/trusted-contribution.yml
+++ b/.github/trusted-contribution.yml
@@ -1,3 +1,9 @@
 trustedContributors:
 - renovate-bot
 - gcf-owl-bot[bot]
+
+annotations:
+- type: comment
+  text: "/gcbrun"
+- type: label
+  text: "kokoro:force-run"
diff --git a/.github/workflows/approve-readme.yaml b/.github/workflows/approve-readme.yaml
index f5fc7d51..59f00b8e 100644
--- a/.github/workflows/approve-readme.yaml
+++ b/.github/workflows/approve-readme.yaml
@@ -21,7 +21,7 @@ jobs:
     runs-on: ubuntu-latest
     if: github.repository_owner == 'googleapis' && github.head_ref == 'autosynth-readme'
     steps:
-      - uses: actions/github-script@v6
+      - uses: actions/github-script@v7
         with:
           github-token: ${{secrets.YOSHI_APPROVER_TOKEN}}
           script: |
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index ae66b197..b91fa381 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -27,8 +27,8 @@ jobs:
       matrix:
         java: [11, 17, 21]
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: ${{matrix.java}}
@@ -41,8 +41,8 @@ jobs:
     name: "units (8)"
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
-      - uses: actions/setup-java@v3
+      - uses: actions/checkout@v4
+      - uses: actions/setup-java@v4
         with:
           java-version: 8
           distribution: temurin
@@ -51,7 +51,7 @@ jobs:
         # https://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#jvm
         run: echo "SUREFIRE_JVM_OPT=-Djvm=${JAVA_HOME}/bin/java" >> $GITHUB_ENV
         shell: bash
-      - uses: actions/setup-java@v3
+      - uses: actions/setup-java@v4
         with:
           java-version: 17
           distribution: temurin
@@ -63,8 +63,8 @@ jobs:
     steps:
     - name: Support longpaths
       run: git config --system core.longpaths true
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: 8
@@ -78,8 +78,8 @@ jobs:
       matrix:
         java: [17]
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: ${{matrix.java}}
@@ -88,8 +88,8 @@ jobs:
   javadoc:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: 17
@@ -100,8 +100,8 @@ jobs:
   lint:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: 11
@@ -112,8 +112,8 @@ jobs:
   clirr:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: 8
diff --git a/.github/workflows/renovate_config_check.yaml b/.github/workflows/renovate_config_check.yaml
index 87d8eb2b..7c5ec786 100644
--- a/.github/workflows/renovate_config_check.yaml
+++ b/.github/workflows/renovate_config_check.yaml
@@ -14,7 +14,7 @@ jobs:
       uses: actions/checkout@v4
 
     - name: Set up Node.js
-      uses: actions/setup-node@v3
+      uses: actions/setup-node@v4
       with:
         node-version: '20'
 
diff --git a/.github/workflows/samples.yaml b/.github/workflows/samples.yaml
index 10d252d7..03b29395 100644
--- a/.github/workflows/samples.yaml
+++ b/.github/workflows/samples.yaml
@@ -20,8 +20,8 @@ jobs:
   checkstyle:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
-      - uses: actions/setup-java@v3
+      - uses: actions/checkout@v4
+      - uses: actions/setup-java@v4
         with:
           distribution: temurin
           java-version: 8
diff --git a/.readme-partials.yaml b/.readme-partials.yaml
index 76167f0e..3858d893 100644
--- a/.readme-partials.yaml
+++ b/.readme-partials.yaml
@@ -32,7 +32,7 @@ custom_content: |
   <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-storage-control</artifactId>
-      <version>2.38.0-beta</version><!-- {x-version-update:google-cloud-storage-control:current} -->
+      <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage-control:current} -->
   </dependency>
   ```
   
@@ -44,7 +44,7 @@ custom_content: |
   If you are using Gradle without BOM, add this to your dependencies:
   
   ```Groovy
-  implementation 'com.google.cloud:google-cloud-storage-control:2.38.0-beta' <!-- {x-version-update:google-cloud-storage-control:current} -->
+  implementation 'com.google.cloud:google-cloud-storage-control:2.38.1-beta-SNAPSHOT' <!-- {x-version-update:google-cloud-storage-control:current} -->
   ```
   
   #### Creating an authorized service object
diff --git a/README.md b/README.md
index 00cc75f2..d825e20e 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file:
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>libraries-bom</artifactId>
-      <version>26.38.0</version>
+      <version>26.39.0</version>
       <type>pom</type>
       <scope>import</scope>
     </dependency>
@@ -51,7 +51,7 @@ If you are using Maven without the BOM, add this to your dependencies:
 <dependency>
   <groupId>com.google.cloud</groupId>
   <artifactId>google-cloud-storage-control</artifactId>
-  <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+  <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
 </dependency>
 
 ```
@@ -59,20 +59,20 @@ If you are using Maven without the BOM, add this to your dependencies:
 If you are using Gradle 5.x or later, add this to your dependencies:
 
 ```Groovy
-implementation platform('com.google.cloud:libraries-bom:26.38.0')
+implementation platform('com.google.cloud:libraries-bom:26.39.0')
 
 implementation 'com.google.cloud:google-cloud-storage'
 ```
 If you are using Gradle without BOM, add this to your dependencies:
 
 ```Groovy
-implementation 'com.google.cloud:google-cloud-storage:2.37.0'
+implementation 'com.google.cloud:google-cloud-storage:2.38.0'
 ```
 
 If you are using SBT, add this to your dependencies:
 
 ```Scala
-libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "2.37.0"
+libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "2.38.0"
 ```
 <!-- {x-version-update-end} -->
 
@@ -141,7 +141,7 @@ If you are using Maven without the BOM, add this to your dependencies:
 <dependency>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-storage-control</artifactId>
-    <version>2.38.0-beta</version><!-- {x-version-update:google-cloud-storage-control:current} -->
+    <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage-control:current} -->
 </dependency>
 ```
 
@@ -153,7 +153,7 @@ implementation 'com.google.cloud:google-cloud-storage-control'
 If you are using Gradle without BOM, add this to your dependencies:
 
 ```Groovy
-implementation 'com.google.cloud:google-cloud-storage-control:2.38.0-beta' <!-- {x-version-update:google-cloud-storage-control:current} -->
+implementation 'com.google.cloud:google-cloud-storage-control:2.38.1-beta-SNAPSHOT' <!-- {x-version-update:google-cloud-storage-control:current} -->
 ```
 
 #### Creating an authorized service object
@@ -494,7 +494,7 @@ Java is a registered trademark of Oracle and/or its affiliates.
 [kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-storage/java11.html
 [stability-image]: https://img.shields.io/badge/stability-stable-green
 [maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-storage.svg
-[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-storage/2.37.0
+[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-storage/2.38.0
 [authentication]: https://github.com/googleapis/google-cloud-java#authentication
 [auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes
 [predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles
diff --git a/gapic-google-cloud-storage-v2/pom.xml b/gapic-google-cloud-storage-v2/pom.xml
index daba1cb0..605cdd06 100644
--- a/gapic-google-cloud-storage-v2/pom.xml
+++ b/gapic-google-cloud-storage-v2/pom.xml
@@ -4,13 +4,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.api.grpc</groupId>
   <artifactId>gapic-google-cloud-storage-v2</artifactId>
-  <version>2.38.0-alpha</version><!-- {x-version-update:gapic-google-cloud-storage-v2:current} -->
+  <version>2.38.1-alpha-SNAPSHOT</version><!-- {x-version-update:gapic-google-cloud-storage-v2:current} -->
   <name>gapic-google-cloud-storage-v2</name>
   <description>GRPC library for gapic-google-cloud-storage-v2</description>
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-storage-parent</artifactId>
-    <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+    <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
   </parent>
   <dependencies>
     <dependency>
diff --git a/google-cloud-storage-bom/pom.xml b/google-cloud-storage-bom/pom.xml
index 902ca466..c2e8f527 100644
--- a/google-cloud-storage-bom/pom.xml
+++ b/google-cloud-storage-bom/pom.xml
@@ -19,7 +19,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.cloud</groupId>
   <artifactId>google-cloud-storage-bom</artifactId>
-  <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+  <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
   <packaging>pom</packaging>
   <parent>
     <groupId>com.google.cloud</groupId>
@@ -69,37 +69,37 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>google-cloud-storage</artifactId>
-        <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+        <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>gapic-google-cloud-storage-v2</artifactId>
-        <version>2.38.0-alpha</version><!-- {x-version-update:gapic-google-cloud-storage-v2:current} -->
+        <version>2.38.1-alpha-SNAPSHOT</version><!-- {x-version-update:gapic-google-cloud-storage-v2:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>grpc-google-cloud-storage-v2</artifactId>
-        <version>2.38.0-alpha</version><!-- {x-version-update:grpc-google-cloud-storage-v2:current} -->
+        <version>2.38.1-alpha-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-storage-v2:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>proto-google-cloud-storage-v2</artifactId>
-        <version>2.38.0-alpha</version><!-- {x-version-update:proto-google-cloud-storage-v2:current} -->
+        <version>2.38.1-alpha-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-storage-v2:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>google-cloud-storage-control</artifactId>
-        <version>2.38.0-beta</version><!-- {x-version-update:google-cloud-storage-control:current} -->
+        <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage-control:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>grpc-google-cloud-storage-control-v2</artifactId>
-        <version>2.38.0-beta</version><!-- {x-version-update:grpc-google-cloud-storage-control-v2:current} -->
+        <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-storage-control-v2:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>proto-google-cloud-storage-control-v2</artifactId>
-        <version>2.38.0-beta</version><!-- {x-version-update:proto-google-cloud-storage-control-v2:current} -->
+        <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-storage-control-v2:current} -->
       </dependency>
     </dependencies>
   </dependencyManagement>
diff --git a/google-cloud-storage-control/pom.xml b/google-cloud-storage-control/pom.xml
index 19f972ca..c131e66b 100644
--- a/google-cloud-storage-control/pom.xml
+++ b/google-cloud-storage-control/pom.xml
@@ -5,13 +5,13 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-storage-control</artifactId>
-    <version>2.38.0-beta</version><!-- {x-version-update:google-cloud-storage-control:current} -->
+    <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage-control:current} -->
     <name>google-cloud-storage-control</name>
     <description>GRPC library for google-cloud-storage-control</description>
     <parent>
         <groupId>com.google.cloud</groupId>
         <artifactId>google-cloud-storage-parent</artifactId>
-        <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+        <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
     </parent>
 
     <dependencies>
diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml
index 0ad98424..416f0172 100644
--- a/google-cloud-storage/pom.xml
+++ b/google-cloud-storage/pom.xml
@@ -2,7 +2,7 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <artifactId>google-cloud-storage</artifactId>
-  <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+  <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
   <packaging>jar</packaging>
   <name>Google Cloud Storage</name>
   <url>https://github.com/googleapis/java-storage</url>
@@ -12,11 +12,11 @@
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-storage-parent</artifactId>
-    <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+    <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
   </parent>
   <properties>
     <site.installationModule>google-cloud-storage</site.installationModule>
-    <pubsub-proto.version>1.111.3</pubsub-proto.version>
+    <pubsub-proto.version>1.111.5</pubsub-proto.version>
     <junit-platform.version>5.10.2</junit-platform.version>
   </properties>
   <dependencies>
@@ -181,13 +181,13 @@
     <dependency>
       <groupId>com.google.api.grpc</groupId>
       <artifactId>proto-google-cloud-kms-v1</artifactId>
-      <version>0.136.0</version>
+      <version>0.137.0</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-kms</artifactId>
-      <version>2.45.0</version>
+      <version>2.46.0</version>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/ChunkSegmenter.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/ChunkSegmenter.java
index 50e3d7e6..774c1e0a 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/ChunkSegmenter.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/ChunkSegmenter.java
@@ -18,7 +18,10 @@ package com.google.cloud.storage;
 
 import com.google.cloud.storage.Crc32cValue.Crc32cLengthKnown;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.math.IntMath;
 import com.google.protobuf.ByteString;
+import java.math.RoundingMode;
 import java.nio.ByteBuffer;
 import java.util.ArrayDeque;
 import java.util.Deque;
@@ -40,6 +43,13 @@ final class ChunkSegmenter {
 
   @VisibleForTesting
   ChunkSegmenter(Hasher hasher, ByteStringStrategy bss, int maxSegmentSize, int blockSize) {
+    int mod = maxSegmentSize % blockSize;
+    Preconditions.checkArgument(
+        mod == 0,
+        "maxSegmentSize % blockSize == 0 (%s % %s == %s)",
+        maxSegmentSize,
+        blockSize,
+        mod);
     this.hasher = hasher;
     this.bss = bss;
     this.maxSegmentSize = maxSegmentSize;
@@ -79,32 +89,92 @@ final class ChunkSegmenter {
   }
 
   ChunkSegment[] segmentBuffers(ByteBuffer[] bbs, int offset, int length) {
+    return segmentBuffers(bbs, offset, length, true);
+  }
+
+  ChunkSegment[] segmentBuffers(
+      ByteBuffer[] bbs, int offset, int length, boolean allowUnalignedBlocks) {
+    // turn this into a single branch, rather than multiple that would need to be checked each
+    // element of the iteration
+    if (allowUnalignedBlocks) {
+      return segmentWithUnaligned(bbs, offset, length);
+    } else {
+      return segmentWithoutUnaligned(bbs, offset, length);
+    }
+  }
+
+  private ChunkSegment[] segmentWithUnaligned(ByteBuffer[] bbs, int offset, int length) {
+    Deque<ChunkSegment> data = new ArrayDeque<>();
+
+    for (int i = offset; i < length; i++) {
+      ByteBuffer buffer = bbs[i];
+      int remaining;
+      while ((remaining = buffer.remaining()) > 0) {
+        consumeBytes(data, remaining, buffer);
+      }
+    }
+
+    return data.toArray(new ChunkSegment[0]);
+  }
+
+  private ChunkSegment[] segmentWithoutUnaligned(ByteBuffer[] bbs, int offset, int length) {
     Deque<ChunkSegment> data = new ArrayDeque<>();
 
+    final long totalRemaining = Buffers.totalRemaining(bbs, offset, length);
+    long consumedSoFar = 0;
+
+    int currentBlockPending = blockSize;
+
     for (int i = offset; i < length; i++) {
       ByteBuffer buffer = bbs[i];
       int remaining;
       while ((remaining = buffer.remaining()) > 0) {
-        // either no chunk or most recent chunk is full, start a new one
-        ChunkSegment peekLast = data.peekLast();
-        if (peekLast == null || peekLast.b.size() == maxSegmentSize) {
-          int limit = Math.min(remaining, maxSegmentSize);
-          ChunkSegment datum = newSegment(buffer, limit);
-          data.addLast(datum);
+        long overallRemaining = totalRemaining - consumedSoFar;
+        if (overallRemaining < blockSize && currentBlockPending == blockSize) {
+          break;
+        }
+
+        int numBytesConsumable;
+        if (remaining >= blockSize) {
+          int blockCount = IntMath.divide(remaining, blockSize, RoundingMode.DOWN);
+          numBytesConsumable = blockCount * blockSize;
+        } else if (currentBlockPending < blockSize) {
+          numBytesConsumable = currentBlockPending;
+          currentBlockPending = blockSize;
         } else {
-          ChunkSegment chunkSoFar = data.pollLast();
-          //noinspection ConstantConditions -- covered by peekLast check above
-          int limit = Math.min(remaining, maxSegmentSize - chunkSoFar.b.size());
-          ChunkSegment datum = newSegment(buffer, limit);
-          ChunkSegment plus = chunkSoFar.concat(datum);
-          data.addLast(plus);
+          numBytesConsumable = remaining;
+          currentBlockPending = currentBlockPending - remaining;
+        }
+        if (numBytesConsumable <= 0) {
+          continue;
         }
+
+        consumedSoFar += consumeBytes(data, numBytesConsumable, buffer);
       }
     }
 
     return data.toArray(new ChunkSegment[0]);
   }
 
+  private long consumeBytes(Deque<ChunkSegment> data, int numBytesConsumable, ByteBuffer buffer) {
+    // either no chunk or most recent chunk is full, start a new one
+    ChunkSegment peekLast = data.peekLast();
+    if (peekLast == null || peekLast.b.size() == maxSegmentSize) {
+      int limit = Math.min(numBytesConsumable, maxSegmentSize);
+      ChunkSegment datum = newSegment(buffer, limit);
+      data.addLast(datum);
+      return limit;
+    } else {
+      ChunkSegment chunkSoFar = data.pollLast();
+      //noinspection ConstantConditions -- covered by peekLast check above
+      int limit = Math.min(numBytesConsumable, maxSegmentSize - chunkSoFar.b.size());
+      ChunkSegment datum = newSegment(buffer, limit);
+      ChunkSegment plus = chunkSoFar.concat(datum);
+      data.addLast(plus);
+      return limit;
+    }
+  }
+
   private ChunkSegment newSegment(ByteBuffer buffer, int limit) {
     final ByteBuffer slice = buffer.slice();
     slice.limit(limit);
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicUnbufferedChunkedResumableWritableByteChannel.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicUnbufferedChunkedResumableWritableByteChannel.java
index c3c3cd09..6acac1e6 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicUnbufferedChunkedResumableWritableByteChannel.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicUnbufferedChunkedResumableWritableByteChannel.java
@@ -121,7 +121,10 @@ final class GapicUnbufferedChunkedResumableWritableByteChannel
 
     long begin = writeCtx.getConfirmedBytes().get();
     RewindableContent content = RewindableContent.of(srcs, srcsOffset, srcsLength);
-    ChunkSegment[] data = chunkSegmenter.segmentBuffers(srcs, srcsOffset, srcsLength);
+    ChunkSegment[] data = chunkSegmenter.segmentBuffers(srcs, srcsOffset, srcsLength, finalize);
+    if (data.length == 0) {
+      return 0;
+    }
 
     List<WriteObjectRequest> messages = new ArrayList<>();
 
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/transfermanager/TransferManagerConfig.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/transfermanager/TransferManagerConfig.java
index 3ffae091..208c16fc 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/transfermanager/TransferManagerConfig.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/transfermanager/TransferManagerConfig.java
@@ -16,6 +16,9 @@
 
 package com.google.cloud.storage.transfermanager;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartNamingStrategy;
 import com.google.cloud.storage.StorageOptions;
 import com.google.common.base.MoreObjects;
 import java.util.Objects;
@@ -31,6 +34,8 @@ public final class TransferManagerConfig {
   private final boolean allowDivideAndConquerDownload;
   private final boolean allowParallelCompositeUpload;
 
+  private final PartNamingStrategy partNamingStrategy;
+
   private final StorageOptions storageOptions;
 
   TransferManagerConfig(
@@ -38,11 +43,13 @@ public final class TransferManagerConfig {
       int perWorkerBufferSize,
       boolean allowDivideAndConquerDownload,
       boolean allowParallelCompositeUpload,
+      PartNamingStrategy partNamingStrategy,
       StorageOptions storageOptions) {
     this.maxWorkers = maxWorkers;
     this.perWorkerBufferSize = perWorkerBufferSize;
     this.allowDivideAndConquerDownload = allowDivideAndConquerDownload;
     this.allowParallelCompositeUpload = allowParallelCompositeUpload;
+    this.partNamingStrategy = partNamingStrategy;
     this.storageOptions = storageOptions;
   }
 
@@ -101,6 +108,15 @@ public final class TransferManagerConfig {
     return storageOptions;
   }
 
+  /**
+   * Part Naming Strategy to be used during Parallel Composite Uploads
+   *
+   * @see Builder#setParallelCompositeUploadPartNamingStrategy(PartNamingStrategy)
+   */
+  public PartNamingStrategy getParallelCompositeUploadPartNamingStrategy() {
+    return partNamingStrategy;
+  }
+
   /** The service object for {@link TransferManager} */
   public TransferManager getService() {
     return new TransferManagerImpl(this, DefaultQos.of(this));
@@ -169,6 +185,7 @@ public final class TransferManagerConfig {
     private boolean allowParallelCompositeUpload;
 
     private StorageOptions storageOptions;
+    private PartNamingStrategy partNamingStrategy;
 
     private Builder() {
       this.perWorkerBufferSize = 16 * 1024 * 1024;
@@ -176,6 +193,7 @@ public final class TransferManagerConfig {
       this.allowDivideAndConquerDownload = false;
       this.allowParallelCompositeUpload = false;
       this.storageOptions = StorageOptions.getDefaultInstance();
+      this.partNamingStrategy = PartNamingStrategy.noPrefix();
     }
 
     /**
@@ -246,6 +264,21 @@ public final class TransferManagerConfig {
       return this;
     }
 
+    /**
+     * Part Naming Strategy that Transfer Manager will use during Parallel Composite Upload
+     *
+     * <p><i>Default Value:</i> {@link PartNamingStrategy#noPrefix()}
+     *
+     * @return the instance of Builder with the value for PartNamingStrategy modified.
+     * @see TransferManagerConfig#getParallelCompositeUploadPartNamingStrategy()
+     */
+    public Builder setParallelCompositeUploadPartNamingStrategy(
+        PartNamingStrategy partNamingStrategy) {
+      checkNotNull(partNamingStrategy);
+      this.partNamingStrategy = partNamingStrategy;
+      return this;
+    }
+
     /**
      * Creates a TransferManagerConfig object.
      *
@@ -257,6 +290,7 @@ public final class TransferManagerConfig {
           perWorkerBufferSize,
           allowDivideAndConquerDownload,
           allowParallelCompositeUpload,
+          partNamingStrategy,
           storageOptions);
     }
   }
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/transfermanager/TransferManagerImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/transfermanager/TransferManagerImpl.java
index 6f3d8025..57e56ea2 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/transfermanager/TransferManagerImpl.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/transfermanager/TransferManagerImpl.java
@@ -86,7 +86,9 @@ final class TransferManagerImpl implements TransferManager {
               .withBufferAllocationStrategy(
                   BufferAllocationStrategy.fixedPool(
                       transferManagerConfig.getMaxWorkers(),
-                      transferManagerConfig.getPerWorkerBufferSize()));
+                      transferManagerConfig.getPerWorkerBufferSize()))
+              .withPartNamingStrategy(
+                  transferManagerConfig.getParallelCompositeUploadPartNamingStrategy());
       storageOptions = storageOptions.toBuilder().setBlobWriteSessionConfig(pcuConfig).build();
     }
     this.pcuQueue = new ConcurrentLinkedDeque<>();
diff --git a/grpc-google-cloud-storage-control-v2/pom.xml b/grpc-google-cloud-storage-control-v2/pom.xml
index 0520d454..f7abf20d 100644
--- a/grpc-google-cloud-storage-control-v2/pom.xml
+++ b/grpc-google-cloud-storage-control-v2/pom.xml
@@ -4,13 +4,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.api.grpc</groupId>
   <artifactId>grpc-google-cloud-storage-control-v2</artifactId>
-  <version>2.38.0-beta</version><!-- {x-version-update:grpc-google-cloud-storage-control-v2:current} -->
+  <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-storage-control-v2:current} -->
   <name>grpc-google-cloud-storage-control-v2</name>
   <description>GRPC library for google-cloud-storage</description>
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-storage-parent</artifactId>
-    <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+    <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
   </parent>
   <dependencies>
     <dependency>
diff --git a/grpc-google-cloud-storage-v2/pom.xml b/grpc-google-cloud-storage-v2/pom.xml
index ad206e87..509018e2 100644
--- a/grpc-google-cloud-storage-v2/pom.xml
+++ b/grpc-google-cloud-storage-v2/pom.xml
@@ -4,13 +4,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.api.grpc</groupId>
   <artifactId>grpc-google-cloud-storage-v2</artifactId>
-  <version>2.38.0-alpha</version><!-- {x-version-update:grpc-google-cloud-storage-v2:current} -->
+  <version>2.38.1-alpha-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-storage-v2:current} -->
   <name>grpc-google-cloud-storage-v2</name>
   <description>GRPC library for grpc-google-cloud-storage-v2</description>
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-storage-parent</artifactId>
-    <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+    <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
   </parent>
   <dependencies>
     <dependency>
diff --git a/owlbot.py b/owlbot.py
index c6f9044a..b88da7d2 100644
--- a/owlbot.py
+++ b/owlbot.py
@@ -37,6 +37,7 @@ java.common_templates(excludes=[
   '.kokoro/presubmit/graalvm-native-17.cfg',
   '.kokoro/requirements.in',
   '.kokoro/requirements.txt',
+  '.github/trusted-contribution.yml',
   '.github/workflows/auto-release.yaml',
   'CONTRIBUTING.md',
   'renovate.json'
diff --git a/pom.xml b/pom.xml
index 5059940c..a9f96e29 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
   <groupId>com.google.cloud</groupId>
   <artifactId>google-cloud-storage-parent</artifactId>
   <packaging>pom</packaging>
-  <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+  <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
   <name>Storage Parent</name>
   <url>https://github.com/googleapis/java-storage</url>
   <description>
@@ -76,7 +76,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>google-cloud-storage</artifactId>
-        <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+        <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.apis</groupId>
@@ -86,7 +86,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>google-cloud-pubsub</artifactId>
-        <version>1.129.3</version>
+        <version>1.129.5</version>
         <scope>test</scope>
       </dependency>
       <dependency>
@@ -98,32 +98,32 @@
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>proto-google-cloud-storage-v2</artifactId>
-        <version>2.38.0-alpha</version><!-- {x-version-update:proto-google-cloud-storage-v2:current} -->
+        <version>2.38.1-alpha-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-storage-v2:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>grpc-google-cloud-storage-v2</artifactId>
-        <version>2.38.0-alpha</version><!-- {x-version-update:grpc-google-cloud-storage-v2:current} -->
+        <version>2.38.1-alpha-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-storage-v2:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>gapic-google-cloud-storage-v2</artifactId>
-        <version>2.38.0-alpha</version><!-- {x-version-update:grpc-google-cloud-storage-v2:current} -->
+        <version>2.38.1-alpha-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-storage-v2:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>grpc-google-cloud-storage-control-v2</artifactId>
-        <version>2.38.0-beta</version><!-- {x-version-update:grpc-google-cloud-storage-control-v2:current} -->
+        <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-storage-control-v2:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>proto-google-cloud-storage-control-v2</artifactId>
-        <version>2.38.0-beta</version><!-- {x-version-update:proto-google-cloud-storage-control-v2:current} -->
+        <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-storage-control-v2:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>google-cloud-storage-control</artifactId>
-        <version>2.38.0-beta</version><!-- {x-version-update:google-cloud-storage-control:current} -->
+        <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage-control:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.cloud</groupId>
diff --git a/proto-google-cloud-storage-control-v2/pom.xml b/proto-google-cloud-storage-control-v2/pom.xml
index 1554bcec..c20dc636 100644
--- a/proto-google-cloud-storage-control-v2/pom.xml
+++ b/proto-google-cloud-storage-control-v2/pom.xml
@@ -4,13 +4,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.api.grpc</groupId>
   <artifactId>proto-google-cloud-storage-control-v2</artifactId>
-  <version>2.38.0-beta</version><!-- {x-version-update:proto-google-cloud-storage-control-v2:current} -->
+  <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-storage-control-v2:current} -->
   <name>proto-google-cloud-storage-control-v2</name>
   <description>Proto library for  proto-google-cloud-storage-control-v2</description>
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-storage-parent</artifactId>
-    <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+    <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
   </parent>
   <dependencies>
     <dependency>
diff --git a/proto-google-cloud-storage-v2/pom.xml b/proto-google-cloud-storage-v2/pom.xml
index 298d6995..9b0942c2 100644
--- a/proto-google-cloud-storage-v2/pom.xml
+++ b/proto-google-cloud-storage-v2/pom.xml
@@ -4,13 +4,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.api.grpc</groupId>
   <artifactId>proto-google-cloud-storage-v2</artifactId>
-  <version>2.38.0-alpha</version><!-- {x-version-update:proto-google-cloud-storage-v2:current} -->
+  <version>2.38.1-alpha-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-storage-v2:current} -->
   <name>proto-google-cloud-storage-v2</name>
   <description>PROTO library for proto-google-cloud-storage-v2</description>
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-storage-parent</artifactId>
-    <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+    <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
   </parent>
   <dependencies>
     <dependency>
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 1b57ebdc..72f49dac 100644
--- a/samples/install-without-bom/pom.xml
+++ b/samples/install-without-bom/pom.xml
@@ -35,7 +35,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-storage-control</artifactId>
-      <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+      <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
     </dependency>
     <!-- [END storage_install_without_bom] -->
 
@@ -66,7 +66,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-pubsub</artifactId>
-      <version>1.129.3</version>
+      <version>1.129.5</version>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml
index ebd85760..a51f5913 100644
--- a/samples/native-image-sample/pom.xml
+++ b/samples/native-image-sample/pom.xml
@@ -29,7 +29,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>libraries-bom</artifactId>
-        <version>26.38.0</version>
+        <version>26.39.0</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
@@ -61,13 +61,13 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-pubsub</artifactId>
-      <version>1.129.3</version>
+      <version>1.129.5</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-storage-control</artifactId>
-      <version>2.38.0-beta</version><!-- {x-version-update:google-cloud-storage-control:current} -->
+      <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage-control:current} -->
       <scope>compile</scope>
     </dependency>
   </dependencies>
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index 70a16009..2138ca5d 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,12 +28,12 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-storage</artifactId>
-      <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+      <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
     </dependency>
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-storage-control</artifactId>
-      <version>2.38.0-beta</version><!-- {x-version-update:google-cloud-storage-control:current} -->
+      <version>2.38.1-beta-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage-control:current} -->
       <scope>compile</scope>
     </dependency>
 
@@ -58,7 +58,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-pubsub</artifactId>
-      <version>1.129.3</version>
+      <version>1.129.5</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index d27887a4..7be5d0f9 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -31,7 +31,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>libraries-bom</artifactId>
-        <version>26.38.0</version>
+        <version>26.39.0</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
@@ -76,7 +76,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-pubsub</artifactId>
-      <version>1.129.3</version>
+      <version>1.129.5</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
diff --git a/storage-shared-benchmarking/pom.xml b/storage-shared-benchmarking/pom.xml
index 31cde044..2314abf3 100644
--- a/storage-shared-benchmarking/pom.xml
+++ b/storage-shared-benchmarking/pom.xml
@@ -10,7 +10,7 @@
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-storage-parent</artifactId>
-    <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+    <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
   </parent>
 
   <properties>
@@ -31,7 +31,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-storage</artifactId>
-      <version>2.38.0</version><!-- {x-version-update:google-cloud-storage:current} -->
+      <version>2.38.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-storage:current} -->
       <classifier>tests</classifier>
     </dependency>
     <dependency>
diff --git a/versions.txt b/versions.txt
index a4a072c2..bb209224 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,10 +1,10 @@
 # Format:
 # module:released-version:current-version
 
-google-cloud-storage:2.38.0:2.38.0
-gapic-google-cloud-storage-v2:2.38.0-alpha:2.38.0-alpha
-grpc-google-cloud-storage-v2:2.38.0-alpha:2.38.0-alpha
-proto-google-cloud-storage-v2:2.38.0-alpha:2.38.0-alpha
-google-cloud-storage-control:2.38.0-beta:2.38.0-beta
-proto-google-cloud-storage-control-v2:2.38.0-beta:2.38.0-beta
-grpc-google-cloud-storage-control-v2:2.38.0-beta:2.38.0-beta
+google-cloud-storage:2.38.0:2.38.1-SNAPSHOT
+gapic-google-cloud-storage-v2:2.38.0-alpha:2.38.1-alpha-SNAPSHOT
+grpc-google-cloud-storage-v2:2.38.0-alpha:2.38.1-alpha-SNAPSHOT
+proto-google-cloud-storage-v2:2.38.0-alpha:2.38.1-alpha-SNAPSHOT
+google-cloud-storage-control:2.38.0-beta:2.38.1-beta-SNAPSHOT
+proto-google-cloud-storage-control-v2:2.38.0-beta:2.38.1-beta-SNAPSHOT
+grpc-google-cloud-storage-control-v2:2.38.0-beta:2.38.1-beta-SNAPSHOT


Test patch:
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ChunkSegmenterTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ChunkSegmenterTest.java
index f8fd2283..3a34c2f5 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/ChunkSegmenterTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ChunkSegmenterTest.java
@@ -16,18 +16,24 @@
 
 package com.google.cloud.storage;
 
+import static com.google.cloud.storage.TestUtils.assertAll;
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.cloud.storage.ChunkSegmenter.ChunkSegment;
 import com.google.cloud.storage.Crc32cValue.Crc32cLengthKnown;
+import com.google.common.collect.ImmutableList;
 import com.google.common.hash.HashCode;
 import com.google.common.hash.Hashing;
+import com.google.protobuf.ByteString;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.stream.Collectors;
 import net.jqwik.api.Arbitraries;
 import net.jqwik.api.Arbitrary;
+import net.jqwik.api.Example;
 import net.jqwik.api.ForAll;
 import net.jqwik.api.Property;
 import net.jqwik.api.Provide;
@@ -58,6 +64,113 @@ final class ChunkSegmenterTest {
     assertThat(reduce).isAnyOf(Optional.empty(), Optional.of(Crc32cValue.of(td.allCrc32c.asInt())));
   }
 
+  /**
+   *
+   *
+   * <pre>
+   * Given 64 bytes, maxSegmentSize: 10, blockSize: 5
+   * 0                                                              64
+   * |---------------------------------------------------------------|
+   *   Produce 6 10-byte segments
+   * |---------|---------|---------|---------|---------|---------|
+   * </pre>
+   */
+  @Example
+  void allowUnalignedBlocks_false_1() {
+    ChunkSegmenter segmenter =
+        new ChunkSegmenter(Hasher.noop(), ByteStringStrategy.noCopy(), 10, 5);
+
+    byte[] bytes = DataGenerator.base64Characters().genBytes(64);
+    List<ByteString> expected =
+        ImmutableList.of(
+            ByteString.copyFrom(bytes, 0, 10),
+            ByteString.copyFrom(bytes, 10, 10),
+            ByteString.copyFrom(bytes, 20, 10),
+            ByteString.copyFrom(bytes, 30, 10),
+            ByteString.copyFrom(bytes, 40, 10),
+            ByteString.copyFrom(bytes, 50, 10));
+
+    ByteBuffer buf = ByteBuffer.wrap(bytes);
+
+    ChunkSegment[] segments = segmenter.segmentBuffers(new ByteBuffer[] {buf}, 0, 1, false);
+    assertThat(buf.remaining()).isEqualTo(4);
+    List<ByteString> actual =
+        Arrays.stream(segments).map(ChunkSegment::getB).collect(Collectors.toList());
+    assertThat(actual).isEqualTo(expected);
+  }
+
+  /**
+   *
+   *
+   * <pre>
+   * Given 64 bytes, maxSegmentSize: 14, blockSize: 7
+   * 0                                                              64
+   * |---------------------------------------------------------------|
+   *   Produce 4 14-byte segments, and one 7 byte segment
+   * |-------------|-------------|-------------|-------------|------|
+   * </pre>
+   */
+  @Example
+  void allowUnalignedBlocks_false_2() throws Exception {
+    ChunkSegmenter segmenter =
+        new ChunkSegmenter(Hasher.noop(), ByteStringStrategy.noCopy(), 14, 7);
+
+    byte[] bytes = DataGenerator.base64Characters().genBytes(64);
+    List<ByteString> expected =
+        ImmutableList.of(
+            ByteString.copyFrom(bytes, 0, 14),
+            ByteString.copyFrom(bytes, 14, 14),
+            ByteString.copyFrom(bytes, 28, 14),
+            ByteString.copyFrom(bytes, 42, 14),
+            ByteString.copyFrom(bytes, 56, 7));
+
+    ByteBuffer buf = ByteBuffer.wrap(bytes);
+
+    ChunkSegment[] segments = segmenter.segmentBuffers(new ByteBuffer[] {buf}, 0, 1, false);
+    List<ByteString> actual =
+        Arrays.stream(segments).map(ChunkSegment::getB).collect(Collectors.toList());
+    assertAll(
+        () -> assertThat(buf.remaining()).isEqualTo(1),
+        () -> assertThat(actual).isEqualTo(expected));
+  }
+
+  /**
+   *
+   *
+   * <pre>
+   * Given 60 bytes in one buffer and 4 bytes in a second buffer, maxSegmentSize: 14, blockSize: 7
+   * 0                                                          60   4
+   * |-----------------------------------------------------------|---|
+   *   Produce 4 14-byte segments, and one 7 byte segment
+   * |-------------|-------------|-------------|-------------|------|
+   * </pre>
+   */
+  @Example
+  void allowUnalignedBlocks_false_3() throws Exception {
+    ChunkSegmenter segmenter =
+        new ChunkSegmenter(Hasher.noop(), ByteStringStrategy.noCopy(), 14, 7);
+
+    byte[] bytes = DataGenerator.base64Characters().genBytes(64);
+    List<ByteString> expected =
+        ImmutableList.of(
+            ByteString.copyFrom(bytes, 0, 14),
+            ByteString.copyFrom(bytes, 14, 14),
+            ByteString.copyFrom(bytes, 28, 14),
+            ByteString.copyFrom(bytes, 42, 14),
+            ByteString.copyFrom(bytes, 56, 7));
+
+    ByteBuffer buf1 = ByteBuffer.wrap(bytes, 0, 60);
+    ByteBuffer buf2 = ByteBuffer.wrap(bytes, 60, 4);
+
+    ChunkSegment[] segments = segmenter.segmentBuffers(new ByteBuffer[] {buf1, buf2}, 0, 2, false);
+    List<ByteString> actual =
+        Arrays.stream(segments).map(ChunkSegment::getB).collect(Collectors.toList());
+    assertAll(
+        () -> assertThat(buf1.remaining()).isEqualTo(0),
+        () -> assertThat(buf2.remaining()).isEqualTo(1),
+        () -> assertThat(actual).isEqualTo(expected));
+  }
+
   @Provide("TestData")
   static Arbitrary<TestData> arbitraryTestData() {
     return Arbitraries.lazyOf(
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITUnbufferedResumableUploadTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITUnbufferedResumableUploadTest.java
index cf1b0d67..34b600d7 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITUnbufferedResumableUploadTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITUnbufferedResumableUploadTest.java
@@ -18,7 +18,9 @@ package com.google.cloud.storage;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.api.core.ApiFuture;
 import com.google.api.core.ApiFutures;
+import com.google.api.gax.grpc.GrpcCallContext;
 import com.google.api.services.storage.model.StorageObject;
 import com.google.cloud.storage.ITUnbufferedResumableUploadTest.ObjectSizes;
 import com.google.cloud.storage.TransportCompatibility.Transport;
@@ -36,6 +38,11 @@ import com.google.cloud.storage.it.runner.annotations.Parameterized.ParametersPr
 import com.google.cloud.storage.it.runner.registry.Generator;
 import com.google.cloud.storage.spi.v1.StorageRpc;
 import com.google.common.collect.ImmutableList;
+import com.google.storage.v2.Object;
+import com.google.storage.v2.StorageClient;
+import com.google.storage.v2.WriteObjectRequest;
+import com.google.storage.v2.WriteObjectResponse;
+import com.google.storage.v2.WriteObjectSpec;
 import java.io.IOException;
 import java.math.BigInteger;
 import java.nio.ByteBuffer;
@@ -103,8 +110,13 @@ public final class ITUnbufferedResumableUploadTest {
     ByteBuffer b = DataGenerator.base64Characters().genByteBuffer(size);
 
     UnbufferedWritableByteChannel open = session.open();
-    int written = open.write(b);
-    assertThat(written).isEqualTo(objectSize);
+    int written1 = open.write(b);
+    assertThat(written1).isEqualTo(objectSize);
+    assertThat(b.remaining()).isEqualTo(additional);
+
+    // no bytes should be consumed if less than 256KiB
+    int written2 = open.write(b);
+    assertThat(written2).isEqualTo(0);
     assertThat(b.remaining()).isEqualTo(additional);
 
     int writtenAndClose = open.writeAndClose(b);
@@ -114,4 +126,70 @@ public final class ITUnbufferedResumableUploadTest {
     StorageObject storageObject = session.getResult().get(2, TimeUnit.SECONDS);
     assertThat(storageObject.getSize()).isEqualTo(BigInteger.valueOf(size));
   }
+
+  @Test
+  @Exclude(transports = Transport.HTTP)
+  public void grpc() throws Exception {
+    BlobInfo blobInfo = BlobInfo.newBuilder(bucket, generator.randomObjectName()).build();
+    Opts<ObjectTargetOpt> opts = Opts.empty();
+    BlobInfo.Builder builder = blobInfo.toBuilder().setMd5(null).setCrc32c(null);
+    BlobInfo updated = opts.blobInfoMapper().apply(builder).build();
+
+    Object object = Conversions.grpc().blobInfo().encode(updated);
+    Object.Builder objectBuilder =
+        object
+            .toBuilder()
+            // required if the data is changing
+            .clearChecksums()
+            // trimmed to shave payload size
+            .clearGeneration()
+            .clearMetageneration()
+            .clearSize()
+            .clearCreateTime()
+            .clearUpdateTime();
+    WriteObjectSpec.Builder specBuilder = WriteObjectSpec.newBuilder().setResource(objectBuilder);
+
+    WriteObjectRequest.Builder requestBuilder =
+        WriteObjectRequest.newBuilder().setWriteObjectSpec(specBuilder);
+
+    WriteObjectRequest request = opts.writeObjectRequest().apply(requestBuilder).build();
+
+    GrpcCallContext merge = Retrying.newCallContext();
+    StorageClient storageClient = PackagePrivateMethodWorkarounds.maybeGetStorageClient(storage);
+    assertThat(storageClient).isNotNull();
+    ApiFuture<ResumableWrite> start =
+        ResumableMedia.gapic()
+            .write()
+            .resumableWrite(
+                storageClient.startResumableWriteCallable().withDefaultCallContext(merge), request);
+
+    UnbufferedWritableByteChannelSession<WriteObjectResponse> session =
+        ResumableMedia.gapic()
+            .write()
+            .byteChannel(storageClient.writeObjectCallable())
+            .resumable()
+            .unbuffered()
+            .setStartAsync(start)
+            .build();
+
+    int additional = 13;
+    long size = objectSize + additional;
+    ByteBuffer b = DataGenerator.base64Characters().genByteBuffer(size);
+
+    UnbufferedWritableByteChannel open = session.open();
+    int written1 = open.write(b);
+    assertThat(written1).isEqualTo(objectSize);
+    assertThat(b.remaining()).isEqualTo(additional);
+
+    // no bytes should be consumed if less than 256KiB
+    int written2 = open.write(b);
+    assertThat(written2).isEqualTo(0);
+    assertThat(b.remaining()).isEqualTo(additional);
+
+    int writtenAndClose = open.writeAndClose(b);
+    assertThat(writtenAndClose).isEqualTo(additional);
+    open.close();
+    WriteObjectResponse resp = session.getResult().get(2, TimeUnit.SECONDS);
+    assertThat(resp.getResource().getSize()).isEqualTo(size);
+  }
 }
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/PackagePrivateMethodWorkarounds.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/PackagePrivateMethodWorkarounds.java
index 23b7f371..66df95a8 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/PackagePrivateMethodWorkarounds.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/PackagePrivateMethodWorkarounds.java
@@ -21,6 +21,7 @@ import com.google.api.core.ApiFutures;
 import com.google.cloud.ReadChannel;
 import com.google.cloud.WriteChannel;
 import com.google.common.collect.ImmutableList;
+import com.google.storage.v2.StorageClient;
 import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Consumer;
@@ -79,6 +80,19 @@ public final class PackagePrivateMethodWorkarounds {
     }
   }
 
+  @Nullable
+  public static StorageClient maybeGetStorageClient(Storage s) {
+    if (s instanceof GrpcStorageImpl) {
+      return ((GrpcStorageImpl) s).storageClient;
+    }
+    // handle instances of AbstractStorageProxy
+    Storage service = s.getOptions().getService();
+    if (service instanceof GrpcStorageImpl) {
+      return ((GrpcStorageImpl) service).storageClient;
+    }
+    return null;
+  }
+
   public static <T> void ifNonNull(@Nullable T t, Consumer<T> c) {
     Utils.ifNonNull(t, c);
   }
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/GrpcPlainRequestLoggingInterceptor.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/GrpcPlainRequestLoggingInterceptor.java
new file mode 100644
index 00000000..7116108d
--- /dev/null
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/GrpcPlainRequestLoggingInterceptor.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.storage.it;
+
+import com.google.api.gax.grpc.GrpcInterceptorProvider;
+import com.google.common.collect.ImmutableList;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.MessageOrBuilder;
+import com.google.storage.v2.WriteObjectRequest;
+import io.grpc.CallOptions;
+import io.grpc.Channel;
+import io.grpc.ClientCall;
+import io.grpc.ClientInterceptor;
+import io.grpc.ForwardingClientCall.SimpleForwardingClientCall;
+import io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener;
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+import io.grpc.Status;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+/**
+ * Client side interceptor which will log gRPC request, response and status messages in plain text,
+ * rather than the byte encoded text io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler does.
+ *
+ * <p>This interceptor does not include the other useful information that NettyClientHandler
+ * provides such as headers, method names, peers etc.
+ */
+public final class GrpcPlainRequestLoggingInterceptor implements ClientInterceptor {
+
+  private static final Logger LOGGER =
+      Logger.getLogger(GrpcPlainRequestLoggingInterceptor.class.getName());
+
+  private static final GrpcPlainRequestLoggingInterceptor INSTANCE =
+      new GrpcPlainRequestLoggingInterceptor();
+
+  private GrpcPlainRequestLoggingInterceptor() {}
+
+  public static GrpcPlainRequestLoggingInterceptor getInstance() {
+    return INSTANCE;
+  }
+
+  public static GrpcInterceptorProvider getInterceptorProvider() {
+    return InterceptorProvider.INSTANCE;
+  }
+
+  @Override
+  public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
+      MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
+    ClientCall<ReqT, RespT> call = next.newCall(method, callOptions);
+    return new SimpleForwardingClientCall<ReqT, RespT>(call) {
+      @Override
+      public void start(Listener<RespT> responseListener, Metadata headers) {
+        SimpleForwardingClientCallListener<RespT> listener =
+            new SimpleForwardingClientCallListener<RespT>(responseListener) {
+              @Override
+              public void onMessage(RespT message) {
+                LOGGER.log(
+                    Level.CONFIG,
+                    () ->
+                        String.format(
+                            "<<< %s{%n%s}", message.getClass().getSimpleName(), fmtProto(message)));
+                super.onMessage(message);
+              }
+
+              @Override
+              public void onClose(Status status, Metadata trailers) {
+                LOGGER.log(
+                    Level.CONFIG,
+                    () ->
+                        String.format(
+                            "<<< status = %s, trailers = %s",
+                            status.toString(), trailers.toString()));
+                super.onClose(status, trailers);
+              }
+            };
+        super.start(listener, headers);
+      }
+
+      @Override
+      public void sendMessage(ReqT message) {
+        LOGGER.log(
+            Level.CONFIG,
+            () ->
+                String.format(
+                    ">>> %s{%n%s}", message.getClass().getSimpleName(), fmtProto(message)));
+        super.sendMessage(message);
+      }
+    };
+  }
+
+  @NonNull
+  static String fmtProto(@NonNull Object obj) {
+    if (obj instanceof WriteObjectRequest) {
+      return fmtProto((WriteObjectRequest) obj);
+    } else if (obj instanceof MessageOrBuilder) {
+      return fmtProto((MessageOrBuilder) obj);
+    } else {
+      return obj.toString();
+    }
+  }
+
+  @NonNull
+  static String fmtProto(@NonNull final MessageOrBuilder msg) {
+    return msg.toString();
+  }
+
+  @NonNull
+  static String fmtProto(@NonNull WriteObjectRequest msg) {
+    if (msg.hasChecksummedData()) {
+      ByteString content = msg.getChecksummedData().getContent();
+      if (content.size() > 20) {
+        WriteObjectRequest.Builder b = msg.toBuilder();
+        ByteString snip = ByteString.copyFromUtf8(String.format("<snip (%d)>", content.size()));
+        ByteString trim = content.substring(0, 20).concat(snip);
+        b.getChecksummedDataBuilder().setContent(trim);
+
+        return b.build().toString();
+      }
+    }
+    return msg.toString();
+  }
+
+  private static final class InterceptorProvider implements GrpcInterceptorProvider {
+    private static final InterceptorProvider INSTANCE = new InterceptorProvider();
+
+    private final List<ClientInterceptor> interceptors;
+
+    private InterceptorProvider() {
+      this.interceptors = ImmutableList.of(GrpcPlainRequestLoggingInterceptor.INSTANCE);
+    }
+
+    @Override
+    public List<ClientInterceptor> getInterceptors() {
+      return interceptors;
+    }
+  }
+}
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITTransferManagerTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITTransferManagerTest.java
index 5c1feed6..504de716 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITTransferManagerTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITTransferManagerTest.java
@@ -23,6 +23,7 @@ import com.google.cloud.storage.BlobId;
 import com.google.cloud.storage.BlobInfo;
 import com.google.cloud.storage.BucketInfo;
 import com.google.cloud.storage.DataGenerator;
+import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartNamingStrategy;
 import com.google.cloud.storage.Storage;
 import com.google.cloud.storage.Storage.BlobSourceOption;
 import com.google.cloud.storage.Storage.BlobWriteOption;
@@ -141,6 +142,28 @@ public class ITTransferManagerTest {
     }
   }
 
+  @Test
+  public void uploadFilesPartNaming() throws Exception {
+    TransferManagerConfig config =
+        TransferManagerConfigTestingInstances.defaults(storage.getOptions())
+            .toBuilder()
+            .setAllowParallelCompositeUpload(true)
+            .setPerWorkerBufferSize(128 * 1024)
+            .setParallelCompositeUploadPartNamingStrategy(PartNamingStrategy.prefix("not-root"))
+            .build();
+    long size = CHUNK_THRESHOLD + 100L;
+    try (TransferManager transferManager = config.getService();
+        TmpFile tmpFile = DataGenerator.base64Characters().tempFile(baseDir, size)) {
+      ParallelUploadConfig parallelUploadConfig =
+          ParallelUploadConfig.newBuilder().setBucketName(bucket.getName()).build();
+      UploadJob job =
+          transferManager.uploadFiles(
+              Collections.singletonList(tmpFile.getPath()), parallelUploadConfig);
+      List<UploadResult> uploadResults = job.getUploadResults();
+      assertThat(uploadResults.get(0).getStatus()).isEqualTo(TransferStatus.SUCCESS);
+    }
+  }
+
   @Test
   public void uploadFilesWithOpts() throws Exception {
     TransferManagerConfig config =
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/BackendResources.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/BackendResources.java
index 5f307c76..8aab9ba6 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/BackendResources.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/BackendResources.java
@@ -26,6 +26,7 @@ import com.google.cloud.storage.BucketInfo;
 import com.google.cloud.storage.Storage;
 import com.google.cloud.storage.StorageOptions;
 import com.google.cloud.storage.TransportCompatibility.Transport;
+import com.google.cloud.storage.it.GrpcPlainRequestLoggingInterceptor;
 import com.google.cloud.storage.it.runner.annotations.Backend;
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableList;
@@ -119,12 +120,17 @@ final class BackendResources implements ManagedLifecycle {
                 new StorageInstance(
                     backend == Backend.TEST_BENCH
                         ? StorageOptions.grpc()
+                            .setGrpcInterceptorProvider(
+                                GrpcPlainRequestLoggingInterceptor.getInterceptorProvider())
                             .setCredentials(NoCredentials.getInstance())
                             // TODO: improve this
                             .setHost(Registry.getInstance().testBench().getGRPCBaseUri())
                             .setProjectId("test-project-id")
                             .build()
-                        : StorageOptions.grpc().build(),
+                        : StorageOptions.grpc()
+                            .setGrpcInterceptorProvider(
+                                GrpcPlainRequestLoggingInterceptor.getInterceptorProvider())
+                            .build(),
                     protectedBucketNames));
     TestRunScopedInstance<BucketInfoShim> bucket =
         TestRunScopedInstance.of(