diff --git a/.github/renovate.json5 b/.github/renovate.json5 index e85837c..4cc89a2 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -31,6 +31,13 @@ ], "allowedVersions": "< 1.11.0", }, + { + "description": "Stay on Java 17 compatible versions of google-java-format (2.0.0+ requires Java 21)", + "matchPackageNames": [ + "com.google.googlejavaformat:google-java-format", + ], + "allowedVersions": "< 2.0.0", + }, ], "rebaseWhen": "behind-base-branch", "semanticCommits": "enabled", diff --git a/.github/workflows/presubmit.yaml b/.github/workflows/presubmit.yaml index 2361f2d..a585eaf 100644 --- a/.github/workflows/presubmit.yaml +++ b/.github/workflows/presubmit.yaml @@ -23,6 +23,8 @@ jobs: uses: gradle/actions/setup-gradle@8da46b539cd8fe6ab27ca75128919a18d757604c # v6.4.1 with: cache-disabled: true - # TODO(jradcliff): Add a lint step. Currently blocked by https://github.com/abcxyz/actions/issues/107. + - name: Check formatting + run: ./gradlew spotlessCheck - name: Build with Gradle run: ./gradlew build + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ee758a2..9525635 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,10 +30,10 @@ accept your pull requests. you are contributing. Refer to the [Google Cloud Platform Samples Style Guide](https://github.com/GoogleCloudPlatform/Template/wiki/style.html) for the recommended coding standards for this organization. You can use the - [google-java-format tool](https://github.com/google/google-java-format) to - easily reformat your code to to comply with Google Style. In addition, please - leave comments in your code in a manner consistent with other code in this - repository. + [google-java-format tool](https://github.com/google/google-java-format) or + run `./gradlew spotlessApply` to easily reformat your code to comply with + Google Style. In addition, please leave comments in your code in a manner + consistent with other code in this repository. 1. Ensure that your code has an appropriate set of unit tests that all pass. Run tests using the command `./gradlew test`. 1. Submit a pull request. diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..a9b252a --- /dev/null +++ b/build.gradle @@ -0,0 +1,31 @@ +/* + * Copyright 2026 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 + * + * https://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. + */ + +plugins { + id 'com.diffplug.spotless' version '7.0.2' apply false +} + +subprojects { + apply plugin: 'com.diffplug.spotless' + + spotless { + java { + // Pin to 1.25.2 for Java 17 compatibility. Version 2.0.0+ requires + // Java 21. + googleJavaFormat('1.25.2') + } + } +} diff --git a/data-manager-samples/src/main/java/com/google/ads/datamanager/samples/CreateUserList.java b/data-manager-samples/src/main/java/com/google/ads/datamanager/samples/CreateUserList.java index 79a2759..d29e577 100644 --- a/data-manager-samples/src/main/java/com/google/ads/datamanager/samples/CreateUserList.java +++ b/data-manager-samples/src/main/java/com/google/ads/datamanager/samples/CreateUserList.java @@ -181,8 +181,7 @@ private void runExample(ParamsConfig params) throws IOException { // Use USER_ID for first-party user IDs assigned to logged-in users. // Note: Display & Video 360 does not support USER_ID lists. ingestedUserListInfoBuilder.setUserIdInfo( - UserIdInfo.newBuilder() - .setDataSourceType(DataSourceType.DATA_SOURCE_TYPE_FIRST_PARTY)); + UserIdInfo.newBuilder().setDataSourceType(DataSourceType.DATA_SOURCE_TYPE_FIRST_PARTY)); break; case MOBILE_ID: // Use MOBILE_ID for mobile advertising IDs. @@ -193,8 +192,7 @@ private void runExample(ParamsConfig params) throws IOException { .setAppId(params.appId)); break; default: - throw new IllegalArgumentException( - "Unsupported upload key type: " + params.uploadKeyType); + throw new IllegalArgumentException("Unsupported upload key type: " + params.uploadKeyType); } UserList userList = diff --git a/data-manager-util/src/main/java/com/google/ads/datamanager/util/UserDataFormatter.java b/data-manager-util/src/main/java/com/google/ads/datamanager/util/UserDataFormatter.java index 1cd079a..72a2825 100644 --- a/data-manager-util/src/main/java/com/google/ads/datamanager/util/UserDataFormatter.java +++ b/data-manager-util/src/main/java/com/google/ads/datamanager/util/UserDataFormatter.java @@ -290,8 +290,8 @@ private String formatLocationString(String value, String label) { * Returns the provided address line, normalized and formatted. * * @param addressLine the address line to format - * @throws IllegalArgumentException if {@code addressLine} is invalid. Examples of an invalid value - * include a {@code null}, blank, or empty string. + * @throws IllegalArgumentException if {@code addressLine} is invalid. Examples of an invalid + * value include a {@code null}, blank, or empty string. */ public String formatAddressLine(String addressLine) { return formatLocationString(addressLine, "address line"); @@ -312,8 +312,8 @@ public String formatCity(String city) { * Returns the provided administrative area, normalized and formatted. * * @param administrativeArea the administrative area to format - * @throws IllegalArgumentException if {@code administrativeArea} is invalid. Examples of an invalid value - * include a {@code null}, blank, or empty string. + * @throws IllegalArgumentException if {@code administrativeArea} is invalid. Examples of an + * invalid value include a {@code null}, blank, or empty string. */ public String formatAdministrativeArea(String administrativeArea) { return formatLocationString(administrativeArea, "administrative area"); @@ -533,8 +533,8 @@ public String processPostalCode(String postalCode) { * #hashString(String)}, and either {@link #hexEncode(byte[])} or {@link #base64Encode(byte[])} * into a single call. * - * @return the address line, formatted, hashed, and encoded for the {@code AddressInfo.address_line} - * field in the API. + * @return the address line, formatted, hashed, and encoded for the {@code + * AddressInfo.address_line} field in the API. * @throws IllegalArgumentException if the address line is invalid */ public String processAddressLine(String addressLine, Encoding encoding) { @@ -562,13 +562,13 @@ public String processAddressLine(String addressLine, Encoding encoding, Encrypte /** * Processes the city. * - *

This is a convenience method that simply calls {@link #formatCity(String)}. This - * method exists for consistency so that all data types have a {@code process...} method. + *

This is a convenience method that simply calls {@link #formatCity(String)}. This method + * exists for consistency so that all data types have a {@code process...} method. * *

Doesn't require an {@link Encoding} since cities shouldn't be encoded or hashed. * - *

There is no overloaded counterpart that takes an {@link Encrypter} since cities - * shouldn't be encrypted. + *

There is no overloaded counterpart that takes an {@link Encrypter} since cities shouldn't be + * encrypted. * * @return the city, formatted for the {@code AddressInfo.city} field in the API. * @throws IllegalArgumentException if the city is invalid @@ -580,15 +580,17 @@ public String processCity(String city) { /** * Processes the administrative area. * - *

This is a convenience method that simply calls {@link #formatAdministrativeArea(String)}. This - * method exists for consistency so that all data types have a {@code process...} method. + *

This is a convenience method that simply calls {@link #formatAdministrativeArea(String)}. + * This method exists for consistency so that all data types have a {@code process...} method. * - *

Doesn't require an {@link Encoding} since administrative areas shouldn't be encoded or hashed. + *

Doesn't require an {@link Encoding} since administrative areas shouldn't be encoded or + * hashed. * - *

There is no overloaded counterpart that takes an {@link Encrypter} since administrative areas - * shouldn't be encrypted. + *

There is no overloaded counterpart that takes an {@link Encrypter} since administrative + * areas shouldn't be encrypted. * - * @return the administrative area, formatted for the {@code AddressInfo.administrative_area} field in the API. + * @return the administrative area, formatted for the {@code AddressInfo.administrative_area} + * field in the API. * @throws IllegalArgumentException if the administrative area is invalid */ public String processAdministrativeArea(String administrativeArea) { diff --git a/data-manager-util/src/test/java/com/google/ads/datamanager/util/UserDataFormatterTest.java b/data-manager-util/src/test/java/com/google/ads/datamanager/util/UserDataFormatterTest.java index 7506e52..bdf13fb 100644 --- a/data-manager-util/src/test/java/com/google/ads/datamanager/util/UserDataFormatterTest.java +++ b/data-manager-util/src/test/java/com/google/ads/datamanager/util/UserDataFormatterTest.java @@ -267,18 +267,9 @@ public void testFormatCity_validInputs() { @Test public void testFormatCity_invalidInputs() { - assertThrows( - "Null city", - IllegalArgumentException.class, - () -> formatter.formatCity(null)); - assertThrows( - "Empty city", - IllegalArgumentException.class, - () -> formatter.formatCity("")); - assertThrows( - "Blank city", - IllegalArgumentException.class, - () -> formatter.formatCity(" ")); + assertThrows("Null city", IllegalArgumentException.class, () -> formatter.formatCity(null)); + assertThrows("Empty city", IllegalArgumentException.class, () -> formatter.formatCity("")); + assertThrows("Blank city", IllegalArgumentException.class, () -> formatter.formatCity(" ")); } @Test @@ -451,16 +442,14 @@ public void testProcessPostalCode_validInputs() { public void testProcessAddressLine_validInputs_hexEncoding() { final String encodedHash = "FF75E73A0E768CC1FA28A64FAEBBCECCB562D7C05F2FFCDD8D100ABAD73E4579"; assertEquals( - encodedHash, - formatter.processAddressLine(" 1800 Amphibious Blvd. ", Encoding.HEX)); + encodedHash, formatter.processAddressLine(" 1800 Amphibious Blvd. ", Encoding.HEX)); } @Test public void testProcessAddressLine_validInputs_base64Encoding() { final String encodedHash = "/3XnOg52jMH6KKZPrrvOzLVi18BfL/zdjRAKutc+RXk="; assertEquals( - encodedHash, - formatter.processAddressLine(" 1800 Amphibious Blvd. ", Encoding.BASE64)); + encodedHash, formatter.processAddressLine(" 1800 Amphibious Blvd. ", Encoding.BASE64)); } @Test