Merge "AbstractPushForReview: Add a test for pushing a merge commit for review"
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index b37ee73..2e90cff 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -551,29 +551,46 @@
 [[category_owner]]
 === Owner
 
-The `Owner` category controls which groups can modify the project's
-configuration.  Users who are members of an owner group can:
+The `Owner` category on `refs/*` controls which groups own the project,
+i.e. the users who are members of an owner group are called the
+`project owners`.
 
-* Change the project description
-* Grant/revoke any access rights, including `Owner`
+Project owners can change the link:config-project-config.html[project
+configuration], including:
 
-To get SSH branch access project owners must grant an access right to a group
-they are a member of, just like for any other user.
+* Granting/revoking any access rights (including the `Owner` access
+  right)
+* Changing the project description
+* Changing the link to the parent project
+* Changing the project options
+* Changing link:config-labels.html[labels]
+* Changing link:config-submit-requirements.html[submit requirements]
 
-Ownership over a particular branch subspace may be delegated by
-entering a branch pattern.  To delegate control over all branches
-that begin with `qa/` to the QA group, add `Owner` category
-for reference `+refs/heads/qa/*+`.  Members of the QA group can
-further refine access, but only for references that begin with
-`refs/heads/qa/`. See <<project_owners,project owners>> to find
-out more about this role.
+[NOTE]
+Access rights that are assigned to the magic
+link:#project_owners[Project Owners] group are resolved to the users
+that are project owners by having the `Owner` permission assigned on
+`refs/*`.
 
+[NOTE]
+To get branch access via Git project owners must grant an access right
+to a group they are a member of, just like for any other user.
+
+[NOTE]
 For the `All-Projects` root project any `Owner` access right on
 'refs/*' is ignored since this permission would allow users to edit the
 global capabilities, which is the same as being able to administrate
 the Gerrit server (e.g. the user could assign the `Administrate Server`
 capability to the own account).
 
+Ownership over a particular branch subspace may be delegated by
+entering a branch pattern. E.g. to delegate control over all branches
+that begin with `qa/` to the QA group, add the `Owner` category
+for reference `+refs/heads/qa/*+`. Members of the QA group can
+further refine access, but only for references that begin with
+`refs/heads/qa/`. See <<project_owners,project owners>> to find
+out more about this role.
+
 
 [[category_push]]
 === Push
diff --git a/Documentation/config-submit-requirements.txt b/Documentation/config-submit-requirements.txt
index bfd2d48..e461446 100644
--- a/Documentation/config-submit-requirements.txt
+++ b/Documentation/config-submit-requirements.txt
@@ -157,7 +157,7 @@
 
 link:config-labels.html[Labels] define voting categories for reviewers to score
 changes. Often a label is accompanied by a submit requirement to check the votes
-on the label, e.g. with link:#submit_requirement_submittable_if[submittableIf]
+on the label, e.g. with a link:#submit_requirement_submittable_if[submittableIf]
 expression that checks that:
 
 * the label was approved: `label:My-Label=MAX`
@@ -213,11 +213,13 @@
 link:config-labels.html#AnyWithBlock[AnyWithBlock],
 link:config-labels.html#MaxNoBlock[MaxNoBlock]). These functions are deprecated
 and setting them is no longer allowed, however if they are (already) set for
-existing label definitions they are still respected. For new labels submit
-requirements should be used instead (using `submittableIf = label:My-Label=MAX
-AND -label:My-Label=MIN` is equivalent to `MaxWithBlock`, using
-`submittableIf = -label:My-Label=MIN` is equivalent to `AnyWithBlock`, using
-`submittableIf = label:My-Label=MAX` is equivalent to using `MaxNoBlock`).
+existing label definitions they are still respected. For new labels the
+function should be set to link:config-labels.html#NoBlock[NoBlock] and then
+submit requirements should be used to control when changes can be submitted
+(using `submittableIf = label:My-Label=MAX AND -label:My-Label=MIN` is
+equivalent to `MaxWithBlock`, using `submittableIf = -label:My-Label=MIN` is
+equivalent to `AnyWithBlock`, using `submittableIf = label:My-Label=MAX` is
+equivalent to using `MaxNoBlock`).
 
 [[ignoreSelfApproval]]
 * `ignoreSelfApproval` flag on labels:
diff --git a/WORKSPACE b/WORKSPACE
index e340eda..1c168c6 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -26,52 +26,11 @@
 
 load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
-load("//tools/bzl:maven_jar.bzl", "GERRIT", "MAVEN_LOCAL", "maven_jar")
 load("//plugins:external_plugin_deps.bzl", "external_plugin_deps")
 load("//tools:nongoogle.bzl", "declare_nongoogle_deps")
 load("//tools:deps.bzl", "CAFFEINE_VERS", "java_dependencies")
 
 http_archive(
-    name = "rules_java",
-    sha256 = "4018e97c93f97680f1650ffd2a7530245b864ac543fd24fae8c02ba447cb2864",
-    urls = [
-        "https://github.com/bazelbuild/rules_java/releases/download/7.3.1/rules_java-7.3.1.tar.gz",
-    ],
-)
-
-http_archive(
-    name = "platforms",
-    sha256 = "3a561c99e7bdbe9173aa653fd579fe849f1d8d67395780ab4770b1f381431d51",
-    urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz",
-        "https://github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz",
-    ],
-)
-
-http_archive(
-    name = "ubuntu2204_jdk17",
-    sha256 = "8ea82b81c9707e535ff93ef5349d11e55b2a23c62bcc3b0faaec052144aed87d",
-    strip_prefix = "rbe_autoconfig-5.1.0",
-    urls = [
-        "https://gerrit-bazel.storage.googleapis.com/rbe_autoconfig/v5.1.0.tar.gz",
-        "https://github.com/davido/rbe_autoconfig/releases/download/v5.1.0/v5.1.0.tar.gz",
-    ],
-)
-
-http_archive(
-    name = "com_google_protobuf",
-    sha256 = "75be42bd736f4df6d702a0e4e4d30de9ee40eac024c4b845d17ae4cc831fe4ae",
-    strip_prefix = "protobuf-21.7",
-    urls = [
-        "https://github.com/protocolbuffers/protobuf/archive/v21.7.tar.gz",
-    ],
-)
-
-load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
-
-protobuf_deps()
-
-http_archive(
     name = "rules_nodejs",
     patch_args = ["-p1"],
     patches = ["//tools:rules_nodejs-5.8.4-node_versions.bzl.patch"],
@@ -115,11 +74,11 @@
     firefox = True,
 )
 
-register_toolchains("//tools:error_prone_warnings_toolchain_java11_definition")
+declare_nongoogle_deps()
 
-register_toolchains("//tools:error_prone_warnings_toolchain_java17_definition")
+load("//tools:defs.bzl", "gerrit_init")
 
-register_toolchains("//tools:error_prone_warnings_toolchain_java21_definition")
+gerrit_init()
 
 # Java-Prettify external repository consumed from git submodule
 local_repository(
@@ -155,8 +114,6 @@
     ],
 )
 
-declare_nongoogle_deps()
-
 load("@build_bazel_rules_nodejs//:index.bzl", "node_repositories", "yarn_install")
 
 node_repositories(
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index b69f110..f92eeee 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -49,6 +49,7 @@
 import com.google.common.collect.Lists;
 import com.google.common.primitives.Chars;
 import com.google.common.testing.FakeTicker;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.AcceptanceTestRequestScope.Context;
 import com.google.gerrit.acceptance.PushOneCommit.Result;
 import com.google.gerrit.acceptance.config.ConfigAnnotationParser;
@@ -776,6 +777,7 @@
     return resourcePrefix + name;
   }
 
+  @CanIgnoreReturnValue
   protected Project.NameKey createProjectOverAPI(
       String nameSuffix,
       @Nullable Project.NameKey parent,
@@ -925,10 +927,12 @@
     return b;
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result createChange() throws Exception {
     return createChange("refs/for/master");
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result createChange(String ref) throws Exception {
     PushOneCommit push = pushFactory.create(admin.newIdent(), testRepo);
     PushOneCommit.Result result = push.to(ref);
@@ -936,6 +940,7 @@
     return result;
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result createChange(TestRepository<InMemoryRepository> repo)
       throws Exception {
     PushOneCommit push = pushFactory.create(admin.newIdent(), repo);
@@ -944,10 +949,12 @@
     return result;
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result createMergeCommitChange(String ref) throws Exception {
     return createMergeCommitChange(ref, "foo");
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result createMergeCommitChange(String ref, String file) throws Exception {
     ObjectId initial = repo().exactRef(HEAD).getLeaf().getObjectId();
 
@@ -981,6 +988,7 @@
     return result;
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result createNParentsMergeCommitChange(String ref, List<String> fileNames)
       throws Exception {
     // This method creates n different commits and creates a merge commit pointing to all n parents.
@@ -1032,6 +1040,7 @@
     return result;
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result createCommitAndPush(
       TestRepository<InMemoryRepository> repo,
       String ref,
@@ -1045,6 +1054,7 @@
     return result;
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result createChangeWithTopic(
       TestRepository<InMemoryRepository> repo,
       String topic,
@@ -1057,12 +1067,14 @@
         repo, "refs/for/master%topic=" + name(topic), commitMsg, fileName, content);
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result createChange(String subject, String fileName, String content)
       throws Exception {
     PushOneCommit push = pushFactory.create(admin.newIdent(), testRepo, subject, fileName, content);
     return push.to("refs/for/master");
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result createChange(
       TestRepository<?> repo,
       String branch,
@@ -1076,6 +1088,7 @@
         "refs/for/" + branch + (Strings.isNullOrEmpty(topic) ? "" : "%topic=" + name(topic)));
   }
 
+  @CanIgnoreReturnValue
   protected BranchApi createBranch(BranchNameKey branch) throws Exception {
     return gApi.projects()
         .name(branch.project().get())
@@ -1083,6 +1096,7 @@
         .create(new BranchInput());
   }
 
+  @CanIgnoreReturnValue
   protected BranchApi createBranchWithRevision(BranchNameKey branch, String revision)
       throws Exception {
     BranchInput in = new BranchInput();
@@ -1093,6 +1107,7 @@
   private static final List<Character> RANDOM =
       Chars.asList('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h');
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result amendChangeWithUploader(
       PushOneCommit.Result change, Project.NameKey projectName, TestAccount account)
       throws Exception {
@@ -1111,10 +1126,12 @@
     return result;
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result amendChange(String changeId) throws Exception {
     return amendChange(changeId, "refs/for/master", admin, testRepo);
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result amendChange(
       String changeId, String ref, TestAccount testAccount, TestRepository<?> repo)
       throws Exception {
@@ -1129,11 +1146,13 @@
         new String(Chars.toArray(RANDOM)));
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result amendChange(
       String changeId, String subject, String fileName, String content) throws Exception {
     return amendChange(changeId, "refs/for/master", admin, testRepo, subject, fileName, content);
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result amendChange(
       String changeId,
       String ref,
@@ -1259,6 +1278,7 @@
         .update();
   }
 
+  @CanIgnoreReturnValue
   protected PushOneCommit.Result pushTo(String ref) throws Exception {
     PushOneCommit push = pushFactory.create(admin.newIdent(), testRepo);
     return push.to(ref);
@@ -1755,6 +1775,7 @@
     assertThat(res).isEqualTo(expectedContent);
   }
 
+  @CanIgnoreReturnValue
   protected RevCommit createNewCommitWithoutChangeId(String branch, String file, String content)
       throws Exception {
     try (Repository repo = repoManager.openRepository(project);
@@ -1971,12 +1992,14 @@
     }
 
     /** Switches to system ticker */
+    @CanIgnoreReturnValue
     public Ticker useDefaultTicker() {
       this.actualTicker = Ticker.systemTicker();
       return actualTicker;
     }
 
     /** Switches to {@link FakeTicker} */
+    @CanIgnoreReturnValue
     public FakeTicker useFakeTicker() {
       if (!(this.actualTicker instanceof FakeTicker)) {
         this.actualTicker = new FakeTicker();
diff --git a/java/com/google/gerrit/acceptance/AbstractDynamicOptionsTest.java b/java/com/google/gerrit/acceptance/AbstractDynamicOptionsTest.java
index 4e8d20d..11f2a41 100644
--- a/java/com/google/gerrit/acceptance/AbstractDynamicOptionsTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDynamicOptionsTest.java
@@ -82,6 +82,10 @@
   }
 
   public static class PluginOneSshModule extends CommandModule {
+    public PluginOneSshModule() {
+      super(/* slaveMode= */ false);
+    }
+
     @Override
     public void configure() {
       command(LS_SAMPLES).to(ListSamplesCommand.class);
diff --git a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
index 8a9e56a..296103a 100644
--- a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
@@ -26,6 +26,7 @@
 import com.google.common.truth.FailureMetadata;
 import com.google.common.truth.Subject;
 import com.google.common.truth.Truth;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.Address;
@@ -109,14 +110,14 @@
       fakeEmailSender = target;
     }
 
-    public FakeEmailSenderSubject didNotSend() {
+    public void didNotSend() {
       Message message = fakeEmailSender.peekMessage();
       if (message != null) {
         failWithoutActual(fact("expected no message", message));
       }
-      return this;
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject sent(String messageType, StagedUsers users) {
       message = fakeEmailSender.nextMessage();
       if (message == null) {
@@ -183,18 +184,22 @@
       return addrList.getAddressList().stream().map(Address::email).collect(toList());
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject to(String... emails) {
       return rcpt(users.supportReviewersByEmail ? TO : null, emails);
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject cc(String... emails) {
       return rcpt(users.supportReviewersByEmail ? CC : null, emails);
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject bcc(String... emails) {
       return rcpt(users.supportReviewersByEmail ? BCC : null, emails);
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject title(String expectedEmailTitle) {
       if (!emailTitle.equals(expectedEmailTitle)) {
         failWithoutActual(
@@ -204,6 +209,7 @@
       return this;
     }
 
+    @CanIgnoreReturnValue
     private FakeEmailSenderSubject rcpt(@Nullable RecipientType type, String[] emails) {
       for (String email : emails) {
         rcpt(type, email);
@@ -230,6 +236,7 @@
       }
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject noOneElse() {
       for (Map.Entry<NotifyType, TestAccount> watchEntry : users.watchers.entrySet()) {
         if (!accountedFor.contains(watchEntry.getValue().email())) {
@@ -257,22 +264,27 @@
       return this;
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject notTo(String... emails) {
       return rcpt(null, emails);
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject to(TestAccount... accounts) {
       return rcpt(TO, accounts);
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject cc(TestAccount... accounts) {
       return rcpt(CC, accounts);
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject bcc(TestAccount... accounts) {
       return rcpt(BCC, accounts);
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject notTo(TestAccount... accounts) {
       return rcpt(null, accounts);
     }
@@ -288,18 +300,22 @@
       rcpt(type, account.email());
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject to(NotifyType... watches) {
       return rcpt(TO, watches);
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject cc(NotifyType... watches) {
       return rcpt(CC, watches);
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject bcc(NotifyType... watches) {
       return rcpt(BCC, watches);
     }
 
+    @CanIgnoreReturnValue
     public FakeEmailSenderSubject notTo(NotifyType... watches) {
       return rcpt(null, watches);
     }
@@ -491,10 +507,12 @@
     }
   }
 
+  @CanIgnoreReturnValue
   protected StagedPreChange stagePreChange(String ref) throws Exception {
     return new StagedPreChange(ref);
   }
 
+  @CanIgnoreReturnValue
   protected StagedPreChange stagePreChange(
       String ref, @Nullable PushOptionGenerator pushOptionGenerator) throws Exception {
     return new StagedPreChange(ref, pushOptionGenerator);
diff --git a/java/com/google/gerrit/acceptance/AcceptanceTestRequestScope.java b/java/com/google/gerrit/acceptance/AcceptanceTestRequestScope.java
index fa3a066..cac8c73 100644
--- a/java/com/google/gerrit/acceptance/AcceptanceTestRequestScope.java
+++ b/java/com/google/gerrit/acceptance/AcceptanceTestRequestScope.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.acceptance;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.RequestCleanup;
 import com.google.gerrit.server.util.RequestContext;
@@ -134,6 +135,7 @@
     return new Context(ctx, ctx.getSession(), ctx.getUser());
   }
 
+  @CanIgnoreReturnValue
   public Context set(Context ctx) {
     Context old = current.get();
     current.set(ctx);
diff --git a/java/com/google/gerrit/acceptance/EventRecorder.java b/java/com/google/gerrit/acceptance/EventRecorder.java
index 1618573..702b3b4 100644
--- a/java/com/google/gerrit/acceptance/EventRecorder.java
+++ b/java/com/google/gerrit/acceptance/EventRecorder.java
@@ -172,7 +172,8 @@
   }
 
   public void assertNoRefUpdatedEvents(String project, String branch) throws Exception {
-    getRefUpdatedEvents(project, branch, 0);
+    @SuppressWarnings("unused")
+    var unused = getRefUpdatedEvents(project, branch, 0);
   }
 
   public void assertRefUpdatedEvents(String project, String branch, String... expected)
diff --git a/java/com/google/gerrit/acceptance/ExtensionRegistry.java b/java/com/google/gerrit/acceptance/ExtensionRegistry.java
index f3527f0..067ba8c 100644
--- a/java/com/google/gerrit/acceptance/ExtensionRegistry.java
+++ b/java/com/google/gerrit/acceptance/ExtensionRegistry.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.acceptance;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.entities.SubmitRequirement;
 import com.google.gerrit.extensions.api.changes.ActionVisitor;
 import com.google.gerrit.extensions.config.CapabilityDefinition;
@@ -205,172 +206,214 @@
   public class Registration implements AutoCloseable {
     private final List<RegistrationHandle> registrationHandles = new ArrayList<>();
 
+    @CanIgnoreReturnValue
     public Registration add(AccountIndexedListener accountIndexedListener) {
       return add(accountIndexedListeners, accountIndexedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ChangeIndexedListener changeIndexedListener) {
       return add(changeIndexedListeners, changeIndexedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(GroupIndexedListener groupIndexedListener) {
       return add(groupIndexedListeners, groupIndexedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ProjectIndexedListener projectIndexedListener) {
       return add(projectIndexedListeners, projectIndexedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(CommitValidationListener commitValidationListener) {
       return add(commitValidationListeners, commitValidationListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(TopicEditedListener topicEditedListener) {
       return add(topicEditedListeners, topicEditedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ExceptionHook exceptionHook) {
       return add(exceptionHooks, exceptionHook);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(PerformanceLogger performanceLogger) {
       return add(performanceLoggers, performanceLogger);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ProjectCreationValidationListener projectCreationListener) {
       return add(projectCreationValidationListeners, projectCreationListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(SubmitRule submitRule) {
       return add(submitRules, submitRule);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(SubmitRequirement submitRequirement) {
       return add(submitRequirements, submitRequirement);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ChangeHasOperandFactory hasOperand, String exportName) {
       return add(hasOperands, hasOperand, exportName);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ChangeIsOperandFactory isOperand, String exportName) {
       return add(isOperands, isOperand, exportName);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ChangeMessageModifier changeMessageModifier) {
       return add(changeMessageModifiers, changeMessageModifier);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ChangeMessageModifier changeMessageModifier, String exportName) {
       return add(changeMessageModifiers, changeMessageModifier, exportName);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ChangeETagComputation changeETagComputation) {
       return add(changeETagComputations, changeETagComputation);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ActionVisitor actionVisitor) {
       return add(actionVisitors, actionVisitor);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(DownloadScheme downloadScheme, String exportName) {
       return add(downloadSchemes, downloadScheme, exportName);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(RefOperationValidationListener refOperationValidationListener) {
       return add(refOperationValidationListeners, refOperationValidationListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(CommentAddedListener commentAddedListener) {
       return add(commentAddedListeners, commentAddedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(GitReferenceUpdatedListener refUpdatedListener) {
       return add(refUpdatedListeners, refUpdatedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(GitBatchRefUpdateListener batchRefUpdateListener) {
       return add(batchRefUpdateListeners, batchRefUpdateListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(FileHistoryWebLink fileHistoryWebLink) {
       return add(fileHistoryWebLinks, fileHistoryWebLink);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(PatchSetWebLink patchSetWebLink) {
       return add(patchSetWebLinks, patchSetWebLink);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ResolveConflictsWebLink resolveConflictsWebLink) {
       return add(resolveConflictsWebLinks, resolveConflictsWebLink);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(EditWebLink editWebLink) {
       return add(editWebLinks, editWebLink);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(FileWebLink fileWebLink) {
       return add(fileWebLinks, fileWebLink);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(RevisionCreatedListener revisionCreatedListener) {
       return add(revisionCreatedListeners, revisionCreatedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(GroupBackend groupBackend) {
       return add(groupBackends, groupBackend);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(
         AccountActivationValidationListener accountActivationValidationListener) {
       return add(accountActivationValidationListeners, accountActivationValidationListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(AccountActivationListener accountDeactivatedListener) {
       return add(accountActivationListeners, accountDeactivatedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(OnSubmitValidationListener onSubmitValidationListener) {
       return add(onSubmitValidationListeners, onSubmitValidationListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(WorkInProgressStateChangedListener workInProgressStateChangedListener) {
       return add(workInProgressStateChangedListeners, workInProgressStateChangedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(AttentionSetListener attentionSetListener) {
       return add(attentionSetListeners, attentionSetListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(CapabilityDefinition capabilityDefinition, String exportName) {
       return add(capabilityDefinitions, capabilityDefinition, exportName);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(
         PluginProjectPermissionDefinition pluginProjectPermissionDefinition, String exportName) {
       return add(pluginProjectPermissionDefinitions, pluginProjectPermissionDefinition, exportName);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ProjectConfigEntry pluginConfigEntry, String exportName) {
       return add(pluginConfigEntries, pluginConfigEntry, exportName);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(PluginPushOption pluginPushOption) {
       return add(pluginPushOptions, pluginPushOption);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(OnPostReview onPostReview) {
       return add(onPostReviews, onPostReview);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ReviewerAddedListener reviewerAddedListener) {
       return add(reviewerAddedListeners, reviewerAddedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ReviewerDeletedListener reviewerDeletedListener) {
       return add(reviewerDeletedListeners, reviewerDeletedListener);
     }
 
+    @CanIgnoreReturnValue
     public Registration add(ReviewerSuggestion reviewerSuggestion, String exportName) {
       return add(reviewerSuggestions, reviewerSuggestion, exportName);
     }
diff --git a/java/com/google/gerrit/acceptance/FakeGroupAuditService.java b/java/com/google/gerrit/acceptance/FakeGroupAuditService.java
index a1c28b9..433c149 100644
--- a/java/com/google/gerrit/acceptance/FakeGroupAuditService.java
+++ b/java/com/google/gerrit/acceptance/FakeGroupAuditService.java
@@ -19,6 +19,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.primitives.Ints;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.httpd.GitOverHttpServlet;
 import com.google.gerrit.server.AuditEvent;
@@ -77,6 +78,7 @@
     }
   }
 
+  @CanIgnoreReturnValue
   public ImmutableList<HttpAuditEvent> drainHttpAuditEvents() throws Exception {
     // Assumes that all HttpAuditEvents are produced by GitOverHttpServlet.
     int expectedSize = Ints.checkedCast(httpMetrics.getRequestsStarted() - drainedSoFar.get());
diff --git a/java/com/google/gerrit/acceptance/GitUtil.java b/java/com/google/gerrit/acceptance/GitUtil.java
index 94d329d..335e97c 100644
--- a/java/com/google/gerrit/acceptance/GitUtil.java
+++ b/java/com/google/gerrit/acceptance/GitUtil.java
@@ -20,6 +20,7 @@
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.primitives.Ints;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.FooterConstants;
 import com.google.gerrit.entities.Project;
 import java.io.IOException;
@@ -98,6 +99,7 @@
     return testRepo;
   }
 
+  @CanIgnoreReturnValue
   public static Ref createAnnotatedTag(TestRepository<?> testRepo, String name, PersonIdent tagger)
       throws GitAPIException {
     TagCommand cmd =
@@ -105,6 +107,7 @@
     return cmd.call();
   }
 
+  @CanIgnoreReturnValue
   public static Ref updateAnnotatedTag(TestRepository<?> testRepo, String name, PersonIdent tagger)
       throws GitAPIException {
     TagCommand tc = testRepo.git().tag().setName(name);
@@ -117,21 +120,25 @@
     fetch.call();
   }
 
+  @CanIgnoreReturnValue
   public static PushResult pushHead(TestRepository<?> testRepo, String ref) throws GitAPIException {
     return pushHead(testRepo, ref, false);
   }
 
+  @CanIgnoreReturnValue
   public static PushResult pushHead(TestRepository<?> testRepo, String ref, boolean pushTags)
       throws GitAPIException {
     return pushHead(testRepo, ref, pushTags, false);
   }
 
+  @CanIgnoreReturnValue
   public static PushResult pushHead(
       TestRepository<?> testRepo, String ref, boolean pushTags, boolean force)
       throws GitAPIException {
     return pushOne(testRepo, "HEAD", ref, pushTags, force, null);
   }
 
+  @CanIgnoreReturnValue
   public static PushResult pushHead(
       TestRepository<?> testRepo,
       String ref,
@@ -142,11 +149,13 @@
     return pushOne(testRepo, "HEAD", ref, pushTags, force, pushOptions);
   }
 
+  @CanIgnoreReturnValue
   public static PushResult deleteRef(TestRepository<?> testRepo, String ref)
       throws GitAPIException {
     return pushOne(testRepo, "", ref, false, true, null);
   }
 
+  @CanIgnoreReturnValue
   public static PushResult pushOne(
       TestRepository<?> testRepo,
       String source,
diff --git a/java/com/google/gerrit/acceptance/PushOneCommit.java b/java/com/google/gerrit/acceptance/PushOneCommit.java
index 3651193..00d4e43 100644
--- a/java/com/google/gerrit/acceptance/PushOneCommit.java
+++ b/java/com/google/gerrit/acceptance/PushOneCommit.java
@@ -302,6 +302,7 @@
     commitBuilder.message(subject).author(i).committer(new PersonIdent(i, testRepo.getDate()));
   }
 
+  @CanIgnoreReturnValue
   public PushOneCommit setParents(List<RevCommit> parents) throws Exception {
     commitBuilder.noParents();
     for (RevCommit p : parents) {
@@ -316,17 +317,20 @@
     return this;
   }
 
+  @CanIgnoreReturnValue
   public PushOneCommit setParent(RevCommit parent) throws Exception {
     commitBuilder.noParents();
     commitBuilder.parent(parent);
     return this;
   }
 
+  @CanIgnoreReturnValue
   public PushOneCommit noParent() {
     commitBuilder.noParents();
     return this;
   }
 
+  @CanIgnoreReturnValue
   public PushOneCommit addFile(String path, String content, int fileMode) throws Exception {
     RevBlob blobId = testRepo.blob(content);
     commitBuilder.edit(
@@ -340,6 +344,7 @@
     return this;
   }
 
+  @CanIgnoreReturnValue
   public PushOneCommit addSymlink(String path, String target) throws Exception {
     RevBlob blobId = testRepo.blob(target);
     commitBuilder.edit(
@@ -353,6 +358,7 @@
     return this;
   }
 
+  @CanIgnoreReturnValue
   public PushOneCommit addGitSubmodule(String modulePath, ObjectId commitId) {
     commitBuilder.edit(
         new PathEdit(modulePath) {
@@ -365,11 +371,13 @@
     return this;
   }
 
+  @CanIgnoreReturnValue
   public PushOneCommit rmFile(String filename) {
     commitBuilder.rm(filename);
     return this;
   }
 
+  @CanIgnoreReturnValue
   public Result to(String ref) throws Exception {
     for (Map.Entry<String, String> e : files.entrySet()) {
       commitBuilder.add(e.getKey(), e.getValue());
@@ -377,6 +385,7 @@
     return execute(ref);
   }
 
+  @CanIgnoreReturnValue
   public Result rm(String ref) throws Exception {
     for (String fileName : files.keySet()) {
       commitBuilder.rm(fileName);
@@ -384,6 +393,7 @@
     return execute(ref);
   }
 
+  @CanIgnoreReturnValue
   public Result execute(String ref) throws Exception {
     RevCommit c = commitBuilder.create();
     if (changeId == null) {
diff --git a/java/com/google/gerrit/acceptance/SshSession.java b/java/com/google/gerrit/acceptance/SshSession.java
index 23bfd0b..ac1a73d 100644
--- a/java/com/google/gerrit/acceptance/SshSession.java
+++ b/java/com/google/gerrit/acceptance/SshSession.java
@@ -17,6 +17,7 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.testsuite.account.TestAccount;
 import com.google.gerrit.acceptance.testsuite.account.TestSshKeys;
 import java.io.Reader;
@@ -38,6 +39,7 @@
 
   public abstract void close();
 
+  @CanIgnoreReturnValue
   public abstract String exec(String command) throws Exception;
 
   public abstract int execAndReturnStatus(String command) throws Exception;
diff --git a/java/com/google/gerrit/acceptance/SshSessionMina.java b/java/com/google/gerrit/acceptance/SshSessionMina.java
index 89096e4..bac4ed6 100644
--- a/java/com/google/gerrit/acceptance/SshSessionMina.java
+++ b/java/com/google/gerrit/acceptance/SshSessionMina.java
@@ -79,7 +79,8 @@
 
   @Override
   public void open() throws Exception {
-    getMinaSession();
+    @SuppressWarnings("unused")
+    var unused = getMinaSession();
   }
 
   @Override
diff --git a/java/com/google/gerrit/acceptance/StandaloneSiteTest.java b/java/com/google/gerrit/acceptance/StandaloneSiteTest.java
index dcb49a5..01e705c 100644
--- a/java/com/google/gerrit/acceptance/StandaloneSiteTest.java
+++ b/java/com/google/gerrit/acceptance/StandaloneSiteTest.java
@@ -24,6 +24,7 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Streams;
 import com.google.common.io.ByteStreams;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.api.GerritApi;
 import com.google.gerrit.extensions.api.groups.GroupInput;
@@ -75,7 +76,8 @@
 
       try {
         // ServerContext ctor is called multiple times but the group can be only created once
-        gApi.groups().id("Group");
+        @SuppressWarnings("unused")
+        var unused = gApi.groups().id("Group");
       } catch (ResourceNotFoundException e) {
         GroupInput in = new GroupInput();
         in.members = Collections.singletonList("admin");
@@ -211,11 +213,13 @@
     runGerrit(Arrays.stream(multiArgs).flatMap(Streams::stream).toArray(String[]::new));
   }
 
+  @CanIgnoreReturnValue
   protected static String execute(
       ImmutableList<String> cmd, File dir, ImmutableMap<String, String> env) throws IOException {
     return execute(cmd, dir, env, null);
   }
 
+  @CanIgnoreReturnValue
   protected static String execute(
       ImmutableList<String> cmd,
       File dir,
diff --git a/java/com/google/gerrit/acceptance/config/BUILD b/java/com/google/gerrit/acceptance/config/BUILD
index 0da68b0..1da975f 100644
--- a/java/com/google/gerrit/acceptance/config/BUILD
+++ b/java/com/google/gerrit/acceptance/config/BUILD
@@ -12,5 +12,6 @@
         "//lib:jgit",
         "//lib/auto:auto-value",
         "//lib/auto:auto-value-annotations",
+        "//lib/errorprone:annotations",
     ],
 )
diff --git a/java/com/google/gerrit/acceptance/config/package-info.java b/java/com/google/gerrit/acceptance/config/package-info.java
new file mode 100644
index 0000000..753b75a
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/config/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.acceptance.config;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/acceptance/package-info.java b/java/com/google/gerrit/acceptance/package-info.java
new file mode 100644
index 0000000..428b5fb
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.acceptance;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/acceptance/rest/package-info.java b/java/com/google/gerrit/acceptance/rest/package-info.java
new file mode 100644
index 0000000..923b0c5
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/rest/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.acceptance.rest;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/acceptance/ssh/TestSshCommandModule.java b/java/com/google/gerrit/acceptance/ssh/TestSshCommandModule.java
index 626092b..f20851c 100644
--- a/java/com/google/gerrit/acceptance/ssh/TestSshCommandModule.java
+++ b/java/com/google/gerrit/acceptance/ssh/TestSshCommandModule.java
@@ -17,6 +17,10 @@
 import com.google.gerrit.sshd.CommandModule;
 
 public class TestSshCommandModule extends CommandModule {
+  public TestSshCommandModule() {
+    super(/* slaveMode= */ false);
+  }
+
   @Override
   protected void configure() {
     command("graceful").to(GracefulCommand.class);
diff --git a/java/com/google/gerrit/acceptance/ssh/package-info.java b/java/com/google/gerrit/acceptance/ssh/package-info.java
new file mode 100644
index 0000000..940b42e
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/ssh/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.acceptance.ssh;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java b/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java
index 5295b8f..577cda8 100644
--- a/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java
+++ b/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java
@@ -19,6 +19,7 @@
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.server.Sequences;
 import com.google.gerrit.server.ServerInitiated;
@@ -160,6 +161,7 @@
       checkState(updatedAccount.isPresent(), "Tried to update non-existing test account");
     }
 
+    @CanIgnoreReturnValue
     private Optional<AccountState> updateAccount(ConfigureDeltaFromState configureDeltaFromState)
         throws IOException, ConfigInvalidException {
       return accountsUpdate.update("Update Test Account", accountId, configureDeltaFromState);
diff --git a/java/com/google/gerrit/acceptance/testsuite/account/TestAccountCreation.java b/java/com/google/gerrit/acceptance/testsuite/account/TestAccountCreation.java
index 16f8903..5d40517 100644
--- a/java/com/google/gerrit/acceptance/testsuite/account/TestAccountCreation.java
+++ b/java/com/google/gerrit/acceptance/testsuite/account/TestAccountCreation.java
@@ -18,6 +18,7 @@
 
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableSet;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.testsuite.ThrowingFunction;
 import com.google.gerrit.entities.Account;
 import java.util.Optional;
@@ -56,40 +57,47 @@
   public abstract static class Builder {
     public abstract Builder fullname(String fullname);
 
+    @CanIgnoreReturnValue
     public Builder clearFullname() {
       return fullname("");
     }
 
     public abstract Builder httpPassword(String httpPassword);
 
+    @CanIgnoreReturnValue
     public Builder clearHttpPassword() {
       return httpPassword("");
     }
 
     public abstract Builder preferredEmail(String preferredEmail);
 
+    @CanIgnoreReturnValue
     public Builder clearPreferredEmail() {
       return preferredEmail("");
     }
 
     public abstract Builder username(String username);
 
+    @CanIgnoreReturnValue
     public Builder clearUsername() {
       return username("");
     }
 
     public abstract Builder status(String status);
 
+    @CanIgnoreReturnValue
     public Builder clearStatus() {
       return status("");
     }
 
     abstract Builder active(boolean active);
 
+    @CanIgnoreReturnValue
     public Builder active() {
       return active(true);
     }
 
+    @CanIgnoreReturnValue
     public Builder inactive() {
       return active(false);
     }
@@ -98,6 +106,7 @@
 
     abstract ImmutableSet.Builder<String> secondaryEmailsBuilder();
 
+    @CanIgnoreReturnValue
     public Builder addSecondaryEmail(String secondaryEmail) {
       secondaryEmailsBuilder().add(secondaryEmail);
       return this;
@@ -108,6 +117,7 @@
 
     abstract TestAccountCreation autoBuild();
 
+    @CanIgnoreReturnValue
     public Account.Id create() {
       TestAccountCreation accountCreation = autoBuild();
       if (accountCreation.preferredEmail().isPresent()) {
diff --git a/java/com/google/gerrit/acceptance/testsuite/account/package-info.java b/java/com/google/gerrit/acceptance/testsuite/account/package-info.java
new file mode 100644
index 0000000..e211ecd
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/testsuite/account/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.acceptance.testsuite.account;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/acceptance/testsuite/change/TestCommentCreation.java b/java/com/google/gerrit/acceptance/testsuite/change/TestCommentCreation.java
index 2031bde..9828e6c 100644
--- a/java/com/google/gerrit/acceptance/testsuite/change/TestCommentCreation.java
+++ b/java/com/google/gerrit/acceptance/testsuite/change/TestCommentCreation.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.acceptance.testsuite.change;
 
 import com.google.auto.value.AutoValue;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.testsuite.ThrowingFunction;
 import com.google.gerrit.acceptance.testsuite.change.TestRange.Position;
 import com.google.gerrit.common.Nullable;
@@ -68,6 +69,7 @@
   @AutoValue.Builder
   public abstract static class Builder {
 
+    @CanIgnoreReturnValue
     public Builder noMessage() {
       return message("");
     }
@@ -76,11 +78,13 @@
     public abstract Builder message(String message);
 
     /** Indicates a patchset-level comment. */
+    @CanIgnoreReturnValue
     public Builder onPatchsetLevel() {
       return file(Patch.PATCHSET_LEVEL);
     }
 
     /** Indicates a file comment. The comment will be on the specified file. */
+    @CanIgnoreReturnValue
     public Builder onFileLevelOf(String filePath) {
       return file(filePath).line(null).range(null);
     }
@@ -122,6 +126,7 @@
      * <p>On the UI, such comments are shown on the right side of a diff view when a diff against
      * base is selected. See {@link #onParentCommit()} for comments shown on the left side.
      */
+    @CanIgnoreReturnValue
     public Builder onPatchsetCommit() {
       return side(CommentSide.PATCHSET_COMMIT);
     }
@@ -135,11 +140,13 @@
      *
      * <p>For merge commits, this indicates the first parent commit.
      */
+    @CanIgnoreReturnValue
     public Builder onParentCommit() {
       return side(CommentSide.PARENT_COMMIT);
     }
 
     /** Like {@link #onParentCommit()} but for the second parent of a merge commit. */
+    @CanIgnoreReturnValue
     public Builder onSecondParentCommit() {
       return side(CommentSide.SECOND_PARENT_COMMIT);
     }
@@ -148,6 +155,7 @@
      * Like {@link #onParentCommit()} but for the AutoMerge commit created from the parents of a
      * merge commit.
      */
+    @CanIgnoreReturnValue
     public Builder onAutoMergeCommit() {
       return side(CommentSide.AUTO_MERGE_COMMIT);
     }
@@ -155,11 +163,13 @@
     abstract Builder side(CommentSide side);
 
     /** Indicates a resolved comment. */
+    @CanIgnoreReturnValue
     public Builder resolved() {
       return unresolved(false);
     }
 
     /** Indicates an unresolved comment. */
+    @CanIgnoreReturnValue
     public Builder unresolved() {
       return unresolved(true);
     }
@@ -211,6 +221,7 @@
      *
      * @return the UUID of the created comment
      */
+    @CanIgnoreReturnValue
     public String create() {
       TestCommentCreation commentCreation = autoBuild();
       return commentCreation.commentCreator().applyAndThrowSilently(commentCreation);
diff --git a/java/com/google/gerrit/acceptance/testsuite/change/TestPatchsetCreation.java b/java/com/google/gerrit/acceptance/testsuite/change/TestPatchsetCreation.java
index f8ca977..d9ac490 100644
--- a/java/com/google/gerrit/acceptance/testsuite/change/TestPatchsetCreation.java
+++ b/java/com/google/gerrit/acceptance/testsuite/change/TestPatchsetCreation.java
@@ -18,6 +18,7 @@
 
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableList;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.testsuite.ThrowingFunction;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.PatchSet;
@@ -181,6 +182,7 @@
      *
      * @return the {@code PatchSet.Id} of the created patchset
      */
+    @CanIgnoreReturnValue
     public PatchSet.Id create() {
       TestPatchsetCreation patchsetCreation = build();
       return patchsetCreation.patchsetCreator().applyAndThrowSilently(patchsetCreation);
diff --git a/java/com/google/gerrit/acceptance/testsuite/change/package-info.java b/java/com/google/gerrit/acceptance/testsuite/change/package-info.java
new file mode 100644
index 0000000..3863f72
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/testsuite/change/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.acceptance.testsuite.change;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/acceptance/testsuite/group/BUILD b/java/com/google/gerrit/acceptance/testsuite/group/BUILD
index 2052105..2bc2b62 100644
--- a/java/com/google/gerrit/acceptance/testsuite/group/BUILD
+++ b/java/com/google/gerrit/acceptance/testsuite/group/BUILD
@@ -21,6 +21,7 @@
         "//lib/auto:auto-value",
         "//lib/auto:auto-value-annotations",
         "//lib/commons:lang3",
+        "//lib/errorprone:annotations",
         "//lib/guice",
     ],
 )
diff --git a/java/com/google/gerrit/acceptance/testsuite/group/TestGroupCreation.java b/java/com/google/gerrit/acceptance/testsuite/group/TestGroupCreation.java
index 99899cf..7549c84 100644
--- a/java/com/google/gerrit/acceptance/testsuite/group/TestGroupCreation.java
+++ b/java/com/google/gerrit/acceptance/testsuite/group/TestGroupCreation.java
@@ -19,6 +19,7 @@
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.testsuite.ThrowingFunction;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.AccountGroup;
@@ -54,6 +55,7 @@
 
     public abstract Builder description(String description);
 
+    @CanIgnoreReturnValue
     public Builder clearDescription() {
       return description("");
     }
@@ -62,10 +64,12 @@
 
     public abstract Builder visibleToAll(boolean visibleToAll);
 
+    @CanIgnoreReturnValue
     public Builder clearMembers() {
       return members(ImmutableSet.of());
     }
 
+    @CanIgnoreReturnValue
     public Builder members(Account.Id member1, Account.Id... otherMembers) {
       return members(Sets.union(ImmutableSet.of(member1), ImmutableSet.copyOf(otherMembers)));
     }
@@ -74,15 +78,18 @@
 
     abstract ImmutableSet.Builder<Account.Id> membersBuilder();
 
+    @CanIgnoreReturnValue
     public Builder addMember(Account.Id member) {
       membersBuilder().add(member);
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder clearSubgroups() {
       return subgroups(ImmutableSet.of());
     }
 
+    @CanIgnoreReturnValue
     public Builder subgroups(AccountGroup.UUID subgroup1, AccountGroup.UUID... otherSubgroups) {
       return subgroups(Sets.union(ImmutableSet.of(subgroup1), ImmutableSet.copyOf(otherSubgroups)));
     }
@@ -91,6 +98,7 @@
 
     abstract ImmutableSet.Builder<AccountGroup.UUID> subgroupsBuilder();
 
+    @CanIgnoreReturnValue
     public Builder addSubgroup(AccountGroup.UUID subgroup) {
       subgroupsBuilder().add(subgroup);
       return this;
@@ -106,6 +114,7 @@
      *
      * @return the UUID of the created group
      */
+    @CanIgnoreReturnValue
     public AccountGroup.UUID create() {
       TestGroupCreation groupCreation = autoBuild();
       return testRefAction(() -> groupCreation.groupCreator().applyAndThrowSilently(groupCreation));
diff --git a/java/com/google/gerrit/acceptance/testsuite/group/TestGroupUpdate.java b/java/com/google/gerrit/acceptance/testsuite/group/TestGroupUpdate.java
index 47c7117..e375760 100644
--- a/java/com/google/gerrit/acceptance/testsuite/group/TestGroupUpdate.java
+++ b/java/com/google/gerrit/acceptance/testsuite/group/TestGroupUpdate.java
@@ -17,6 +17,7 @@
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.testsuite.ThrowingConsumer;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.AccountGroup;
@@ -56,6 +57,7 @@
 
     public abstract Builder description(String description);
 
+    @CanIgnoreReturnValue
     public Builder clearDescription() {
       return description("");
     }
@@ -69,10 +71,12 @@
 
     abstract Function<ImmutableSet<Account.Id>, Set<Account.Id>> memberModification();
 
+    @CanIgnoreReturnValue
     public Builder clearMembers() {
       return memberModification(originalMembers -> ImmutableSet.of());
     }
 
+    @CanIgnoreReturnValue
     public Builder addMember(Account.Id member) {
       Function<ImmutableSet<Account.Id>, Set<Account.Id>> previousModification =
           memberModification();
@@ -82,6 +86,7 @@
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder removeMember(Account.Id member) {
       Function<ImmutableSet<Account.Id>, Set<Account.Id>> previousModification =
           memberModification();
@@ -98,10 +103,12 @@
     abstract Function<ImmutableSet<AccountGroup.UUID>, Set<AccountGroup.UUID>>
         subgroupModification();
 
+    @CanIgnoreReturnValue
     public Builder clearSubgroups() {
       return subgroupModification(originalMembers -> ImmutableSet.of());
     }
 
+    @CanIgnoreReturnValue
     public Builder addSubgroup(AccountGroup.UUID subgroup) {
       Function<ImmutableSet<AccountGroup.UUID>, Set<AccountGroup.UUID>> previousModification =
           subgroupModification();
@@ -111,6 +118,7 @@
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder removeSubgroup(AccountGroup.UUID subgroup) {
       Function<ImmutableSet<AccountGroup.UUID>, Set<AccountGroup.UUID>> previousModification =
           subgroupModification();
diff --git a/java/com/google/gerrit/acceptance/testsuite/group/package-info.java b/java/com/google/gerrit/acceptance/testsuite/group/package-info.java
new file mode 100644
index 0000000..78778e1
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/testsuite/group/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.acceptance.testsuite.group;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/acceptance/testsuite/package-info.java b/java/com/google/gerrit/acceptance/testsuite/package-info.java
new file mode 100644
index 0000000..2f43e09
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/testsuite/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.acceptance.testsuite;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/BUILD b/java/com/google/gerrit/acceptance/testsuite/project/BUILD
index 4ac2705..be51a64 100644
--- a/java/com/google/gerrit/acceptance/testsuite/project/BUILD
+++ b/java/com/google/gerrit/acceptance/testsuite/project/BUILD
@@ -21,6 +21,7 @@
         "//lib/auto:auto-value",
         "//lib/auto:auto-value-annotations",
         "//lib/commons:lang3",
+        "//lib/errorprone:annotations",
         "//lib/guice",
     ],
 )
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/TestProjectCreation.java b/java/com/google/gerrit/acceptance/testsuite/project/TestProjectCreation.java
index 3337fc3..e8df7ed 100644
--- a/java/com/google/gerrit/acceptance/testsuite/project/TestProjectCreation.java
+++ b/java/com/google/gerrit/acceptance/testsuite/project/TestProjectCreation.java
@@ -19,6 +19,7 @@
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.testsuite.ThrowingFunction;
 import com.google.gerrit.entities.AccountGroup;
 import com.google.gerrit.entities.Project;
@@ -66,6 +67,7 @@
      * "refs/heads/" prefix of the branch name can be omitted. The specified branches are ignored if
      * {@link #noEmptyCommit()} is used.
      */
+    @CanIgnoreReturnValue
     public TestProjectCreation.Builder branches(String branch1, String... otherBranches) {
       return branches(Sets.union(ImmutableSet.of(branch1), ImmutableSet.copyOf(otherBranches)));
     }
@@ -77,10 +79,12 @@
     public abstract TestProjectCreation.Builder permissionOnly(boolean value);
 
     /** Skips the empty commit on creation. This means that project's branches will not exist. */
+    @CanIgnoreReturnValue
     public TestProjectCreation.Builder noEmptyCommit() {
       return createEmptyCommit(false);
     }
 
+    @CanIgnoreReturnValue
     public TestProjectCreation.Builder addOwner(AccountGroup.UUID owner) {
       ownersBuilder().add(requireNonNull(owner, "owner"));
       return this;
@@ -98,6 +102,7 @@
      *
      * @return the name of the created project
      */
+    @CanIgnoreReturnValue
     public Project.NameKey create() {
       TestProjectCreation creation = autoBuild();
       return creation.projectCreator().applyAndThrowSilently(creation);
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/TestProjectUpdate.java b/java/com/google/gerrit/acceptance/testsuite/project/TestProjectUpdate.java
index 5634c78..cc57ba6 100644
--- a/java/com/google/gerrit/acceptance/testsuite/project/TestProjectUpdate.java
+++ b/java/com/google/gerrit/acceptance/testsuite/project/TestProjectUpdate.java
@@ -21,6 +21,7 @@
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.testsuite.ThrowingConsumer;
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.entities.AccountGroup;
@@ -75,6 +76,7 @@
       abstract Optional<Integer> max();
 
       /** Sets the minimum and maximum values for the capability. */
+      @CanIgnoreReturnValue
       public Builder range(int min, int max) {
         checkNonInvertedRange(min, max);
         return min(min).max(max);
@@ -353,61 +355,72 @@
      * Removes all access sections. Useful when testing against a specific set of access sections or
      * permissions.
      */
+    @CanIgnoreReturnValue
     public Builder removeAllAccessSections() {
       return removeAllAccessSections(true);
     }
 
     /** Adds a permission to be included in this update. */
+    @CanIgnoreReturnValue
     public Builder add(TestPermission testPermission) {
       addedPermissionsBuilder().add(testPermission);
       return this;
     }
 
     /** Adds a permission to be included in this update. */
+    @CanIgnoreReturnValue
     public Builder add(TestPermission.Builder testPermissionBuilder) {
       return add(testPermissionBuilder.build());
     }
 
     /** Adds a label permission to be included in this update. */
+    @CanIgnoreReturnValue
     public Builder add(TestLabelPermission testLabelPermission) {
       addedLabelPermissionsBuilder().add(testLabelPermission);
       return this;
     }
 
     /** Adds a label permission to be included in this update. */
+    @CanIgnoreReturnValue
     public Builder add(TestLabelPermission.Builder testLabelPermissionBuilder) {
       return add(testLabelPermissionBuilder.build());
     }
 
     /** Adds a capability to be included in this update. */
+    @CanIgnoreReturnValue
     public Builder add(TestCapability testCapability) {
       addedCapabilitiesBuilder().add(testCapability);
       return this;
     }
 
     /** Adds a capability to be included in this update. */
+    @CanIgnoreReturnValue
     public Builder add(TestCapability.Builder testCapabilityBuilder) {
       return add(testCapabilityBuilder.build());
     }
 
     /** Removes a permission, label permission, or capability as part of this update. */
+    @CanIgnoreReturnValue
     public Builder remove(TestPermissionKey testPermissionKey) {
       removedPermissionsBuilder().add(testPermissionKey);
       return this;
     }
 
     /** Removes a permission, label permission, or capability as part of this update. */
+    @CanIgnoreReturnValue
     public Builder remove(TestPermissionKey.Builder testPermissionKeyBuilder) {
       return remove(testPermissionKeyBuilder.build());
     }
 
     /** Sets the exclusive bit bit for the given permission key. */
+    @CanIgnoreReturnValue
     public Builder setExclusiveGroup(
         TestPermissionKey.Builder testPermissionKeyBuilder, boolean exclusive) {
       return setExclusiveGroup(testPermissionKeyBuilder.build(), exclusive);
     }
 
     /** Sets the exclusive bit bit for the given permission key. */
+    @CanIgnoreReturnValue
     public Builder setExclusiveGroup(TestPermissionKey testPermissionKey, boolean exclusive) {
       checkArgument(
           !testPermissionKey.group().isPresent(),
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/package-info.java b/java/com/google/gerrit/acceptance/testsuite/project/package-info.java
new file mode 100644
index 0000000..dfe56d6
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/testsuite/project/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.acceptance.testsuite.project;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/acceptance/testsuite/request/RequestScopeOperations.java b/java/com/google/gerrit/acceptance/testsuite/request/RequestScopeOperations.java
index a9914b3..97826dc 100644
--- a/java/com/google/gerrit/acceptance/testsuite/request/RequestScopeOperations.java
+++ b/java/com/google/gerrit/acceptance/testsuite/request/RequestScopeOperations.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.acceptance.testsuite.request;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.AcceptanceTestRequestScope;
 import com.google.gerrit.acceptance.testsuite.account.TestAccount;
 import com.google.gerrit.entities.Account;
@@ -35,6 +36,7 @@
    * @param accountId account ID. Must exist; throws an unchecked exception otherwise.
    * @return the previous request scope.
    */
+  @CanIgnoreReturnValue
   AcceptanceTestRequestScope.Context setApiUser(Account.Id accountId);
 
   /**
@@ -48,6 +50,7 @@
    * @param testAccount test account from {@code AccountOperations}.
    * @return the previous request scope.
    */
+  @CanIgnoreReturnValue
   AcceptanceTestRequestScope.Context setApiUser(TestAccount testAccount);
 
   /**
@@ -60,6 +63,7 @@
    *
    * @return the previous request scope.
    */
+  @CanIgnoreReturnValue
   AcceptanceTestRequestScope.Context resetCurrentApiUser();
 
   /**
@@ -67,6 +71,7 @@
    *
    * @return the previous request scope.
    */
+  @CanIgnoreReturnValue
   AcceptanceTestRequestScope.Context setApiUserAnonymous();
 
   /**
@@ -74,5 +79,6 @@
    *
    * @return the previous request scope.
    */
+  @CanIgnoreReturnValue
   AcceptanceTestRequestScope.Context setApiUserInternal();
 }
diff --git a/java/com/google/gerrit/acceptance/testsuite/request/RequestScopeOperationsImpl.java b/java/com/google/gerrit/acceptance/testsuite/request/RequestScopeOperationsImpl.java
index 895c7a0..a10ece6 100644
--- a/java/com/google/gerrit/acceptance/testsuite/request/RequestScopeOperationsImpl.java
+++ b/java/com/google/gerrit/acceptance/testsuite/request/RequestScopeOperationsImpl.java
@@ -17,6 +17,7 @@
 import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.acceptance.AcceptanceTestRequestScope;
 import com.google.gerrit.acceptance.GerritServer.TestSshServerAddress;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
@@ -73,11 +74,13 @@
   }
 
   @Override
+  @CanIgnoreReturnValue
   public AcceptanceTestRequestScope.Context setApiUser(Account.Id accountId) {
     return setApiUser(accountOperations.account(accountId).get());
   }
 
   @Override
+  @CanIgnoreReturnValue
   public AcceptanceTestRequestScope.Context setApiUser(TestAccount testAccount) {
     return atrScope.set(
         atrScope.newContext(
@@ -86,6 +89,7 @@
   }
 
   @Override
+  @CanIgnoreReturnValue
   public AcceptanceTestRequestScope.Context resetCurrentApiUser() {
     CurrentUser user = atrScope.get().getUser();
     // More special cases for anonymous users etc. can be added as needed.
@@ -94,11 +98,13 @@
   }
 
   @Override
+  @CanIgnoreReturnValue
   public AcceptanceTestRequestScope.Context setApiUserAnonymous() {
     return atrScope.set(atrScope.newContext(null, anonymousUserProvider.get()));
   }
 
   @Override
+  @CanIgnoreReturnValue
   public AcceptanceTestRequestScope.Context setApiUserInternal() {
     return atrScope.set(atrScope.newContext(null, internalUserFactory.create()));
   }
diff --git a/java/com/google/gerrit/acceptance/testsuite/request/package-info.java b/java/com/google/gerrit/acceptance/testsuite/request/package-info.java
new file mode 100644
index 0000000..943bd21
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/testsuite/request/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.acceptance.testsuite.request;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/asciidoctor/package-info.java b/java/com/google/gerrit/asciidoctor/package-info.java
new file mode 100644
index 0000000..504c3f5
--- /dev/null
+++ b/java/com/google/gerrit/asciidoctor/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.asciidoctor;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/auth/ldap/LdapRealm.java b/java/com/google/gerrit/auth/ldap/LdapRealm.java
index 7dc2b1b..e33e5cb 100644
--- a/java/com/google/gerrit/auth/ldap/LdapRealm.java
+++ b/java/com/google/gerrit/auth/ldap/LdapRealm.java
@@ -331,7 +331,10 @@
     final DirContext ctx = helper.open();
     try {
       Helper.LdapSchema schema = helper.getSchema(ctx);
-      helper.findAccount(schema, ctx, username, false);
+
+      @SuppressWarnings("unused")
+      var unused = helper.findAccount(schema, ctx, username, false);
+
       return true;
     } catch (NoSuchUserException e) {
       return false;
diff --git a/java/com/google/gerrit/auth/ldap/package-info.java b/java/com/google/gerrit/auth/ldap/package-info.java
new file mode 100644
index 0000000..45e1bc2
--- /dev/null
+++ b/java/com/google/gerrit/auth/ldap/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.auth.ldap;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/auth/oauth/package-info.java b/java/com/google/gerrit/auth/oauth/package-info.java
new file mode 100644
index 0000000..53c6829
--- /dev/null
+++ b/java/com/google/gerrit/auth/oauth/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.auth.oauth;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/auth/openid/package-info.java b/java/com/google/gerrit/auth/openid/package-info.java
new file mode 100644
index 0000000..2b6f77d
--- /dev/null
+++ b/java/com/google/gerrit/auth/openid/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.auth.openid;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/auth/package-info.java b/java/com/google/gerrit/auth/package-info.java
new file mode 100644
index 0000000..6538de4
--- /dev/null
+++ b/java/com/google/gerrit/auth/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.auth;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/common/BUILD b/java/com/google/gerrit/common/BUILD
index 8f930bb..8f85311 100644
--- a/java/com/google/gerrit/common/BUILD
+++ b/java/com/google/gerrit/common/BUILD
@@ -30,6 +30,7 @@
         "//lib:servlet-api",
         "//lib/auto:auto-value",
         "//lib/auto:auto-value-annotations",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
     ],
 )
diff --git a/java/com/google/gerrit/common/FileUtil.java b/java/com/google/gerrit/common/FileUtil.java
index 5b0925e..35cf848 100644
--- a/java/com/google/gerrit/common/FileUtil.java
+++ b/java/com/google/gerrit/common/FileUtil.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.common;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -84,6 +85,7 @@
     }
   }
 
+  @CanIgnoreReturnValue
   public static Path mkdirsOrDie(Path p, String errMsg) {
     try {
       if (!Files.isDirectory(p)) {
diff --git a/java/com/google/gerrit/common/auth/openid/package-info.java b/java/com/google/gerrit/common/auth/openid/package-info.java
new file mode 100644
index 0000000..931ed56
--- /dev/null
+++ b/java/com/google/gerrit/common/auth/openid/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.common.auth.openid;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/common/data/package-info.java b/java/com/google/gerrit/common/data/package-info.java
new file mode 100644
index 0000000..9f3539c
--- /dev/null
+++ b/java/com/google/gerrit/common/data/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.common.data;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/common/data/testing/BUILD b/java/com/google/gerrit/common/data/testing/BUILD
index d39d05c..a580c77 100644
--- a/java/com/google/gerrit/common/data/testing/BUILD
+++ b/java/com/google/gerrit/common/data/testing/BUILD
@@ -7,6 +7,7 @@
     visibility = ["//visibility:public"],
     deps = [
         "//java/com/google/gerrit/entities",
+        "//lib/errorprone:annotations",
         "//lib/truth",
     ],
 )
diff --git a/java/com/google/gerrit/common/data/testing/package-info.java b/java/com/google/gerrit/common/data/testing/package-info.java
new file mode 100644
index 0000000..24c3708
--- /dev/null
+++ b/java/com/google/gerrit/common/data/testing/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.common.data.testing;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/common/package-info.java b/java/com/google/gerrit/common/package-info.java
new file mode 100644
index 0000000..5f97d56
--- /dev/null
+++ b/java/com/google/gerrit/common/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.common;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/entities/AccessSection.java b/java/com/google/gerrit/entities/AccessSection.java
index 8ae0a5d..7dca72e 100644
--- a/java/com/google/gerrit/entities/AccessSection.java
+++ b/java/com/google/gerrit/entities/AccessSection.java
@@ -20,6 +20,7 @@
 import com.google.auto.value.AutoValue;
 import com.google.auto.value.extension.memoized.Memoized;
 import com.google.common.collect.ImmutableList;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import java.util.ArrayList;
 import java.util.List;
@@ -121,27 +122,32 @@
 
     public abstract String getName();
 
+    @CanIgnoreReturnValue
     public Builder modifyPermissions(Consumer<List<Permission.Builder>> modification) {
       modification.accept(permissionBuilders);
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder addPermission(Permission.Builder permission) {
       requireNonNull(permission, "permission must be non-null");
       return modifyPermissions(p -> p.add(permission));
     }
 
+    @CanIgnoreReturnValue
     public Builder remove(Permission.Builder permission) {
       requireNonNull(permission, "permission must be non-null");
       return removePermission(permission.getName());
     }
 
+    @CanIgnoreReturnValue
     public Builder removePermission(String name) {
       requireNonNull(name, "name must be non-null");
       return modifyPermissions(
           p -> p.removeIf(permissionBuilder -> name.equalsIgnoreCase(permissionBuilder.getName())));
     }
 
+    @CanIgnoreReturnValue
     public Permission.Builder upsertPermission(String permissionName) {
       requireNonNull(permissionName, "permissionName must be non-null");
 
diff --git a/java/com/google/gerrit/entities/Account.java b/java/com/google/gerrit/entities/Account.java
index fdd4405..767e68e 100644
--- a/java/com/google/gerrit/entities/Account.java
+++ b/java/com/google/gerrit/entities/Account.java
@@ -21,6 +21,7 @@
 import com.google.auto.value.AutoValue;
 import com.google.common.base.MoreObjects;
 import com.google.common.primitives.Ints;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.client.DiffPreferencesInfo;
 import java.time.Instant;
@@ -262,6 +263,7 @@
 
     public abstract Builder setInactive(boolean inactive);
 
+    @CanIgnoreReturnValue
     public Builder setActive(boolean active) {
       return setInactive(!active);
     }
diff --git a/java/com/google/gerrit/entities/AccountGroupByIdAudit.java b/java/com/google/gerrit/entities/AccountGroupByIdAudit.java
index 0ef51e5..5db5af5 100644
--- a/java/com/google/gerrit/entities/AccountGroupByIdAudit.java
+++ b/java/com/google/gerrit/entities/AccountGroupByIdAudit.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.entities;
 
 import com.google.auto.value.AutoValue;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import java.time.Instant;
 import java.util.Optional;
 
@@ -39,6 +40,7 @@
 
     abstract Builder removedOn(Instant removedOn);
 
+    @CanIgnoreReturnValue
     public Builder removed(Account.Id removedBy, Instant removedOn) {
       return removedBy(removedBy).removedOn(removedOn);
     }
diff --git a/java/com/google/gerrit/entities/AccountGroupMemberAudit.java b/java/com/google/gerrit/entities/AccountGroupMemberAudit.java
index 913956e..0cb1c62 100644
--- a/java/com/google/gerrit/entities/AccountGroupMemberAudit.java
+++ b/java/com/google/gerrit/entities/AccountGroupMemberAudit.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.entities;
 
 import com.google.auto.value.AutoValue;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import java.time.Instant;
 import java.util.Optional;
 
@@ -43,10 +44,12 @@
 
     abstract Builder removedOn(Instant removedOn);
 
+    @CanIgnoreReturnValue
     public Builder removed(Account.Id removedBy, Instant removedOn) {
       return removedBy(removedBy).removedOn(removedOn);
     }
 
+    @CanIgnoreReturnValue
     public Builder removedLegacy() {
       return removed(addedBy(), addedOn());
     }
diff --git a/java/com/google/gerrit/entities/CachedProjectConfig.java b/java/com/google/gerrit/entities/CachedProjectConfig.java
index be4a1cf..6dc9e32 100644
--- a/java/com/google/gerrit/entities/CachedProjectConfig.java
+++ b/java/com/google/gerrit/entities/CachedProjectConfig.java
@@ -20,6 +20,7 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSortedMap;
 import com.google.common.flogger.FluentLogger;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -148,31 +149,37 @@
 
     public abstract Builder setBranchOrderSection(Optional<BranchOrderSection> value);
 
+    @CanIgnoreReturnValue
     public Builder addGroup(GroupReference groupReference) {
       groupsBuilder().put(groupReference.getUUID(), groupReference);
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder addAccessSection(AccessSection accessSection) {
       accessSectionsBuilder().put(accessSection.getName(), accessSection);
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder addContributorAgreement(ContributorAgreement contributorAgreement) {
       contributorAgreementsBuilder().put(contributorAgreement.getName(), contributorAgreement);
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder addNotifySection(NotifyConfig notifyConfig) {
       notifySectionsBuilder().put(notifyConfig.getName(), notifyConfig);
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder addLabelSection(LabelType labelType) {
       labelSectionsBuilder().put(labelType.getName(), labelType);
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder addSubmitRequirementSection(SubmitRequirement submitRequirement) {
       submitRequirementSectionsBuilder().put(submitRequirement.name(), submitRequirement);
       return this;
@@ -180,11 +187,13 @@
 
     public abstract Builder setMimeTypes(ConfiguredMimeTypes value);
 
+    @CanIgnoreReturnValue
     public Builder addSubscribeSection(SubscribeSection subscribeSection) {
       subscribeSectionsBuilder().put(subscribeSection.project(), subscribeSection);
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder addCommentLinkSection(StoredCommentLinkInfo storedCommentLinkInfo) {
       commentLinkSectionsBuilder().put(storedCommentLinkInfo.getName(), storedCommentLinkInfo);
       return this;
@@ -213,6 +222,7 @@
 
     abstract ImmutableMap.Builder<String, String> pluginConfigsBuilder();
 
+    @CanIgnoreReturnValue
     public Builder addPluginConfig(String pluginName, String pluginConfig) {
       pluginConfigsBuilder().put(pluginName, pluginConfig);
       return this;
@@ -222,6 +232,7 @@
 
     abstract ImmutableMap.Builder<String, ImmutableConfig> parsedProjectLevelConfigsBuilder();
 
+    @CanIgnoreReturnValue
     public Builder addProjectLevelConfig(String configFileName, String config) {
       projectLevelConfigsBuilder().put(configFileName, config);
       try {
diff --git a/java/com/google/gerrit/entities/LabelType.java b/java/com/google/gerrit/entities/LabelType.java
index 7a3266ecc..c6709dc 100644
--- a/java/com/google/gerrit/entities/LabelType.java
+++ b/java/com/google/gerrit/entities/LabelType.java
@@ -20,6 +20,7 @@
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import java.util.ArrayList;
 import java.util.List;
@@ -39,6 +40,7 @@
     return create(name, values);
   }
 
+  @CanIgnoreReturnValue
   public static String checkName(String name) throws IllegalArgumentException {
     checkNameInternal(name);
     if ("SUBM".equals(name)) {
@@ -47,6 +49,7 @@
     return name;
   }
 
+  @CanIgnoreReturnValue
   public static String checkNameInternal(String name) throws IllegalArgumentException {
     if (name == null || name.isEmpty()) {
       throw new IllegalArgumentException("Empty label name");
diff --git a/java/com/google/gerrit/entities/NotifyConfig.java b/java/com/google/gerrit/entities/NotifyConfig.java
index 5c0a3db..d3123c4 100644
--- a/java/com/google/gerrit/entities/NotifyConfig.java
+++ b/java/com/google/gerrit/entities/NotifyConfig.java
@@ -18,6 +18,7 @@
 import com.google.auto.value.extension.memoized.Memoized;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableSet;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import java.util.EnumSet;
 import java.util.Set;
@@ -74,11 +75,13 @@
 
     public abstract Builder setHeader(Header hdr);
 
+    @CanIgnoreReturnValue
     public Builder addGroup(GroupReference group) {
       groupsBuilder().add(group);
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder addAddress(Address address) {
       addressesBuilder().add(address);
       return this;
diff --git a/java/com/google/gerrit/entities/Permission.java b/java/com/google/gerrit/entities/Permission.java
index 0e959e7..1f2f151 100644
--- a/java/com/google/gerrit/entities/Permission.java
+++ b/java/com/google/gerrit/entities/Permission.java
@@ -18,6 +18,7 @@
 
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableList;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -274,15 +275,18 @@
 
     public abstract Builder setExclusiveGroup(boolean value);
 
+    @CanIgnoreReturnValue
     public Builder modifyRules(Consumer<List<PermissionRule.Builder>> modification) {
       modification.accept(rulesBuilders);
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder add(PermissionRule.Builder rule) {
       return modifyRules(r -> r.add(rule));
     }
 
+    @CanIgnoreReturnValue
     public Builder remove(PermissionRule rule) {
       if (rule != null) {
         return removeRule(rule.getGroup());
@@ -290,10 +294,12 @@
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder removeRule(GroupReference group) {
       return modifyRules(rules -> rules.removeIf(rule -> sameGroup(rule.build(), group)));
     }
 
+    @CanIgnoreReturnValue
     public Builder clearRules() {
       return modifyRules(r -> r.clear());
     }
diff --git a/java/com/google/gerrit/entities/PermissionRule.java b/java/com/google/gerrit/entities/PermissionRule.java
index 1665c1c..706091f 100644
--- a/java/com/google/gerrit/entities/PermissionRule.java
+++ b/java/com/google/gerrit/entities/PermissionRule.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.entities;
 
 import com.google.auto.value.AutoValue;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 
 @AutoValue
 public abstract class PermissionRule implements Comparable<PermissionRule> {
@@ -239,14 +240,17 @@
 
   @AutoValue.Builder
   public abstract static class Builder {
+    @CanIgnoreReturnValue
     public Builder setDeny() {
       return setAction(Action.DENY);
     }
 
+    @CanIgnoreReturnValue
     public Builder setBlock() {
       return setAction(Action.BLOCK);
     }
 
+    @CanIgnoreReturnValue
     public Builder setRange(int newMin, int newMax) {
       if (newMax < newMin) {
         setMin(newMax);
diff --git a/java/com/google/gerrit/entities/Project.java b/java/com/google/gerrit/entities/Project.java
index 72ca6a9..9c2866c 100644
--- a/java/com/google/gerrit/entities/Project.java
+++ b/java/com/google/gerrit/entities/Project.java
@@ -18,6 +18,7 @@
 
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableMap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.errorprone.annotations.Immutable;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.client.InheritableBoolean;
@@ -195,6 +196,7 @@
   public abstract static class Builder {
     public abstract Builder setDescription(String description);
 
+    @CanIgnoreReturnValue
     public Builder setBooleanConfig(BooleanProjectConfig config, InheritableBoolean val) {
       Map<BooleanProjectConfig, InheritableBoolean> map = new HashMap<>(getBooleanConfigs());
       map.replace(config, val);
@@ -214,6 +216,7 @@
 
     public abstract Builder setParent(NameKey n);
 
+    @CanIgnoreReturnValue
     public Builder setParent(String n) {
       return setParent(n != null ? nameKey(n) : null);
     }
diff --git a/java/com/google/gerrit/entities/SubmitRequirementExpressionResult.java b/java/com/google/gerrit/entities/SubmitRequirementExpressionResult.java
index fbb2fd7..f9a5aeb 100644
--- a/java/com/google/gerrit/entities/SubmitRequirementExpressionResult.java
+++ b/java/com/google/gerrit/entities/SubmitRequirementExpressionResult.java
@@ -16,6 +16,7 @@
 
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableList;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gson.Gson;
 import com.google.gson.TypeAdapter;
 import java.util.Optional;
@@ -203,6 +204,7 @@
 
       public abstract Builder status(boolean value);
 
+      @CanIgnoreReturnValue
       public Builder addChildPredicateResult(PredicateResult result) {
         childPredicateResultsBuilder().add(result);
         return this;
diff --git a/java/com/google/gerrit/entities/SubscribeSection.java b/java/com/google/gerrit/entities/SubscribeSection.java
index 574cae8..7751907 100644
--- a/java/com/google/gerrit/entities/SubscribeSection.java
+++ b/java/com/google/gerrit/entities/SubscribeSection.java
@@ -20,6 +20,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.flogger.FluentLogger;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
@@ -51,12 +52,14 @@
 
     abstract ImmutableList.Builder<RefSpec> multiMatchRefSpecsBuilder();
 
+    @CanIgnoreReturnValue
     public Builder addMatchingRefSpec(String matchingRefSpec) {
       matchingRefSpecsBuilder()
           .add(new RefSpec(matchingRefSpec, RefSpec.WildcardMode.REQUIRE_MATCH));
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder addMultiMatchRefSpec(String multiMatchRefSpec) {
       multiMatchRefSpecsBuilder()
           .add(new RefSpec(multiMatchRefSpec, RefSpec.WildcardMode.ALLOW_MISMATCH));
diff --git a/java/com/google/gerrit/entities/converter/package-info.java b/java/com/google/gerrit/entities/converter/package-info.java
new file mode 100644
index 0000000..51ea401
--- /dev/null
+++ b/java/com/google/gerrit/entities/converter/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.entities.converter;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/entities/package-info.java b/java/com/google/gerrit/entities/package-info.java
new file mode 100644
index 0000000..f1cde1b
--- /dev/null
+++ b/java/com/google/gerrit/entities/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.entities;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/exceptions/BUILD b/java/com/google/gerrit/exceptions/BUILD
index 873b659..b31d12e 100644
--- a/java/com/google/gerrit/exceptions/BUILD
+++ b/java/com/google/gerrit/exceptions/BUILD
@@ -7,5 +7,6 @@
     deps = [
         "//java/com/google/gerrit/entities",
         "//lib:jgit",
+        "//lib/errorprone:annotations",
     ],
 )
diff --git a/java/com/google/gerrit/exceptions/package-info.java b/java/com/google/gerrit/exceptions/package-info.java
new file mode 100644
index 0000000..ce52b4a
--- /dev/null
+++ b/java/com/google/gerrit/exceptions/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.exceptions;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/annotations/package-info.java b/java/com/google/gerrit/extensions/annotations/package-info.java
new file mode 100644
index 0000000..f338b5b
--- /dev/null
+++ b/java/com/google/gerrit/extensions/annotations/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.annotations;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/api/access/package-info.java b/java/com/google/gerrit/extensions/api/access/package-info.java
new file mode 100644
index 0000000..65e2d75
--- /dev/null
+++ b/java/com/google/gerrit/extensions/api/access/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.api.access;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/api/accounts/AccountApi.java b/java/com/google/gerrit/extensions/api/accounts/AccountApi.java
index 0d019aa..e40f82e 100644
--- a/java/com/google/gerrit/extensions/api/accounts/AccountApi.java
+++ b/java/com/google/gerrit/extensions/api/accounts/AccountApi.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.accounts;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.client.DiffPreferencesInfo;
 import com.google.gerrit.extensions.client.EditPreferencesInfo;
 import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
@@ -44,18 +45,22 @@
 
   GeneralPreferencesInfo getPreferences() throws RestApiException;
 
+  @CanIgnoreReturnValue
   GeneralPreferencesInfo setPreferences(GeneralPreferencesInfo in) throws RestApiException;
 
   DiffPreferencesInfo getDiffPreferences() throws RestApiException;
 
+  @CanIgnoreReturnValue
   DiffPreferencesInfo setDiffPreferences(DiffPreferencesInfo in) throws RestApiException;
 
   EditPreferencesInfo getEditPreferences() throws RestApiException;
 
+  @CanIgnoreReturnValue
   EditPreferencesInfo setEditPreferences(EditPreferencesInfo in) throws RestApiException;
 
   List<ProjectWatchInfo> getWatchedProjects() throws RestApiException;
 
+  @CanIgnoreReturnValue
   List<ProjectWatchInfo> setWatchedProjects(List<ProjectWatchInfo> in) throws RestApiException;
 
   void deleteWatchedProjects(List<ProjectWatchInfo> in) throws RestApiException;
@@ -72,6 +77,7 @@
 
   void deleteEmail(String email) throws RestApiException;
 
+  @CanIgnoreReturnValue
   EmailApi createEmail(EmailInput emailInput) throws RestApiException;
 
   EmailApi email(String email) throws RestApiException;
@@ -82,12 +88,14 @@
 
   List<SshKeyInfo> listSshKeys() throws RestApiException;
 
+  @CanIgnoreReturnValue
   SshKeyInfo addSshKey(String key) throws RestApiException;
 
   void deleteSshKey(int seq) throws RestApiException;
 
   Map<String, GpgKeyInfo> listGpgKeys() throws RestApiException;
 
+  @CanIgnoreReturnValue
   Map<String, GpgKeyInfo> putGpgKeys(List<String> add, List<String> remove) throws RestApiException;
 
   GpgKeyApi gpgKey(String id) throws RestApiException;
@@ -102,6 +110,7 @@
 
   void deleteExternalIds(List<String> externalIds) throws RestApiException;
 
+  @CanIgnoreReturnValue
   List<DeletedDraftCommentInfo> deleteDraftComments(DeleteDraftCommentsInput input)
       throws RestApiException;
 
@@ -122,6 +131,7 @@
    * @param httpPassword the new password, {@code null} to remove the password.
    * @return the new password, {@code null} if the password was removed.
    */
+  @CanIgnoreReturnValue
   String setHttpPassword(String httpPassword) throws RestApiException;
 
   void delete() throws RestApiException;
diff --git a/java/com/google/gerrit/extensions/api/accounts/Accounts.java b/java/com/google/gerrit/extensions/api/accounts/Accounts.java
index 285b385..ad0d385 100644
--- a/java/com/google/gerrit/extensions/api/accounts/Accounts.java
+++ b/java/com/google/gerrit/extensions/api/accounts/Accounts.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.accounts;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.client.ListAccountsOption;
 import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
@@ -53,9 +54,11 @@
   AccountApi self() throws RestApiException;
 
   /** Create a new account with the given username and default options. */
+  @CanIgnoreReturnValue
   AccountApi create(String username) throws RestApiException;
 
   /** Create a new account. */
+  @CanIgnoreReturnValue
   AccountApi create(AccountInput input) throws RestApiException;
 
   /**
diff --git a/java/com/google/gerrit/extensions/api/accounts/package-info.java b/java/com/google/gerrit/extensions/api/accounts/package-info.java
new file mode 100644
index 0000000..5bd477a
--- /dev/null
+++ b/java/com/google/gerrit/extensions/api/accounts/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.api.accounts;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
index 7761a65..a663e25 100644
--- a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
@@ -17,6 +17,7 @@
 import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Sets;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.client.ListChangesOption;
 import com.google.gerrit.extensions.client.ReviewerState;
@@ -131,22 +132,28 @@
   }
 
   /** Create a new change that reverts this change. */
+  @CanIgnoreReturnValue
   default ChangeApi revert() throws RestApiException {
     return revert(new RevertInput());
   }
 
   /** Create a new change that reverts this change. */
+  @CanIgnoreReturnValue
   ChangeApi revert(RevertInput in) throws RestApiException;
 
+  @CanIgnoreReturnValue
   default RevertSubmissionInfo revertSubmission() throws RestApiException {
     return revertSubmission(new RevertInput());
   }
 
+  @CanIgnoreReturnValue
   RevertSubmissionInfo revertSubmission(RevertInput in) throws RestApiException;
 
   /** Create a merge patch set for the change. */
+  @CanIgnoreReturnValue
   ChangeInfo createMergePatchSet(MergePatchSetInput in) throws RestApiException;
 
+  @CanIgnoreReturnValue
   ChangeInfo applyPatch(ApplyPatchPatchSetInput in) throws RestApiException;
 
   default List<ChangeInfo> submittedTogether() throws RestApiException {
@@ -179,6 +186,7 @@
    * @return a {@code RebaseChainInfo} contains the {@code ChangeInfo} data for the rebased the
    *     chain
    */
+  @CanIgnoreReturnValue
   default Response<RebaseChainInfo> rebaseChain() throws RestApiException {
     return rebaseChain(new RebaseInput());
   }
@@ -189,6 +197,7 @@
    * @return a {@code RebaseChainInfo} contains the {@code ChangeInfo} data for the rebased the
    *     chain
    */
+  @CanIgnoreReturnValue
   Response<RebaseChainInfo> rebaseChain(RebaseInput in) throws RestApiException;
 
   /** Deletes a change. */
@@ -200,12 +209,14 @@
 
   IncludedInInfo includedIn() throws RestApiException;
 
+  @CanIgnoreReturnValue
   default ReviewerResult addReviewer(String reviewer) throws RestApiException {
     ReviewerInput in = new ReviewerInput();
     in.reviewer = reviewer;
     return addReviewer(in);
   }
 
+  @CanIgnoreReturnValue
   ReviewerResult addReviewer(ReviewerInput in) throws RestApiException;
 
   SuggestedReviewersRequest suggestReviewers() throws RestApiException;
@@ -348,6 +359,7 @@
   AttentionSetApi attention(String id) throws RestApiException;
 
   /** Adds a user to the attention set. */
+  @CanIgnoreReturnValue
   AccountInfo addToAttentionSet(AttentionSetInput input) throws RestApiException;
 
   /**
@@ -462,9 +474,11 @@
   void index() throws RestApiException;
 
   /** Check if this change is a pure revert of the change stored in revertOf. */
+  @CanIgnoreReturnValue
   PureRevertInfo pureRevert() throws RestApiException;
 
   /** Check if this change is a pure revert of claimedOriginal (SHA1 in 40 digit hex). */
+  @CanIgnoreReturnValue
   PureRevertInfo pureRevert(String claimedOriginal) throws RestApiException;
 
   /**
diff --git a/java/com/google/gerrit/extensions/api/changes/Changes.java b/java/com/google/gerrit/extensions/api/changes/Changes.java
index ea2a158..5e3d08c 100644
--- a/java/com/google/gerrit/extensions/api/changes/Changes.java
+++ b/java/com/google/gerrit/extensions/api/changes/Changes.java
@@ -16,6 +16,7 @@
 
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ListMultimap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.UsedAt;
 import com.google.gerrit.extensions.client.ListChangesOption;
 import com.google.gerrit.extensions.common.ChangeInfo;
@@ -73,6 +74,7 @@
    */
   ChangeApi id(String project, int id) throws RestApiException;
 
+  @CanIgnoreReturnValue
   ChangeApi create(ChangeInput in) throws RestApiException;
 
   ChangeInfo createAsInfo(ChangeInput in) throws RestApiException;
diff --git a/java/com/google/gerrit/extensions/api/changes/CommentApi.java b/java/com/google/gerrit/extensions/api/changes/CommentApi.java
index 889175e..9b5e1da 100644
--- a/java/com/google/gerrit/extensions/api/changes/CommentApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/CommentApi.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.changes;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.common.CommentInfo;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
 import com.google.gerrit.extensions.restapi.RestApiException;
@@ -30,6 +31,7 @@
    *
    * @return the comment with its message updated.
    */
+  @CanIgnoreReturnValue
   CommentInfo delete(DeleteCommentInput input) throws RestApiException;
 
   /**
diff --git a/java/com/google/gerrit/extensions/api/changes/DraftApi.java b/java/com/google/gerrit/extensions/api/changes/DraftApi.java
index fa663a5..50816b7 100644
--- a/java/com/google/gerrit/extensions/api/changes/DraftApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/DraftApi.java
@@ -14,11 +14,13 @@
 
 package com.google.gerrit.extensions.api.changes;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.common.CommentInfo;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 
 public interface DraftApi extends CommentApi {
+  @CanIgnoreReturnValue
   CommentInfo update(DraftInput in) throws RestApiException;
 
   void delete() throws RestApiException;
diff --git a/java/com/google/gerrit/extensions/api/changes/RevisionApi.java b/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
index 73fc170..69cf25d 100644
--- a/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.extensions.api.changes;
 
 import com.google.common.collect.ListMultimap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.client.ArchiveFormat;
 import com.google.gerrit.extensions.client.SubmitType;
@@ -44,24 +45,30 @@
 
   void description(String description) throws RestApiException;
 
+  @CanIgnoreReturnValue
   ReviewResult review(ReviewInput in) throws RestApiException;
 
+  @CanIgnoreReturnValue
   default ChangeInfo submit() throws RestApiException {
     SubmitInput in = new SubmitInput();
     return submit(in);
   }
 
+  @CanIgnoreReturnValue
   ChangeInfo submit(SubmitInput in) throws RestApiException;
 
+  @CanIgnoreReturnValue
   ChangeApi cherryPick(CherryPickInput in) throws RestApiException;
 
   ChangeInfo cherryPickAsInfo(CherryPickInput in) throws RestApiException;
 
+  @CanIgnoreReturnValue
   default ChangeApi rebase() throws RestApiException {
     RebaseInput in = new RebaseInput();
     return rebase(in);
   }
 
+  @CanIgnoreReturnValue
   ChangeApi rebase(RebaseInput in) throws RestApiException;
 
   ChangeInfo rebaseAsInfo(RebaseInput in) throws RestApiException;
@@ -117,6 +124,7 @@
    * @param fixId the ID of the fix which should be applied
    * @throws RestApiException if the fix couldn't be applied
    */
+  @CanIgnoreReturnValue
   EditInfo applyFix(String fixId) throws RestApiException;
 
   /**
@@ -126,6 +134,7 @@
    * @param applyProvidedFixInput The fix(es) to apply to a new change edit.
    * @throws RestApiException if the fix couldn't be applied.
    */
+  @CanIgnoreReturnValue
   EditInfo applyFix(ApplyProvidedFixInput applyProvidedFixInput) throws RestApiException;
 
   Map<String, DiffInfo> getFixPreview(String fixId) throws RestApiException;
@@ -133,6 +142,7 @@
   Map<String, DiffInfo> getFixPreview(ApplyProvidedFixInput applyProvidedFixInput)
       throws RestApiException;
 
+  @CanIgnoreReturnValue
   DraftApi createDraft(DraftInput in) throws RestApiException;
 
   DraftApi draft(String id) throws RestApiException;
diff --git a/java/com/google/gerrit/extensions/api/changes/package-info.java b/java/com/google/gerrit/extensions/api/changes/package-info.java
new file mode 100644
index 0000000..f548212
--- /dev/null
+++ b/java/com/google/gerrit/extensions/api/changes/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.api.changes;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/api/config/Server.java b/java/com/google/gerrit/extensions/api/config/Server.java
index 8b69ded..0fe09c6 100644
--- a/java/com/google/gerrit/extensions/api/config/Server.java
+++ b/java/com/google/gerrit/extensions/api/config/Server.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.config;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.client.DiffPreferencesInfo;
 import com.google.gerrit.extensions.client.EditPreferencesInfo;
 import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
@@ -31,14 +32,17 @@
 
   GeneralPreferencesInfo getDefaultPreferences() throws RestApiException;
 
+  @CanIgnoreReturnValue
   GeneralPreferencesInfo setDefaultPreferences(GeneralPreferencesInfo in) throws RestApiException;
 
   DiffPreferencesInfo getDefaultDiffPreferences() throws RestApiException;
 
+  @CanIgnoreReturnValue
   DiffPreferencesInfo setDefaultDiffPreferences(DiffPreferencesInfo in) throws RestApiException;
 
   EditPreferencesInfo getDefaultEditPreferences() throws RestApiException;
 
+  @CanIgnoreReturnValue
   EditPreferencesInfo setDefaultEditPreferences(EditPreferencesInfo in) throws RestApiException;
 
   ConsistencyCheckInfo checkConsistency(ConsistencyCheckInput in) throws RestApiException;
diff --git a/java/com/google/gerrit/extensions/api/config/package-info.java b/java/com/google/gerrit/extensions/api/config/package-info.java
new file mode 100644
index 0000000..2ee371c
--- /dev/null
+++ b/java/com/google/gerrit/extensions/api/config/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.api.config;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/api/groups/Groups.java b/java/com/google/gerrit/extensions/api/groups/Groups.java
index 1a46930..8d53af0 100644
--- a/java/com/google/gerrit/extensions/api/groups/Groups.java
+++ b/java/com/google/gerrit/extensions/api/groups/Groups.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.groups;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.client.ListGroupsOption;
 import com.google.gerrit.extensions.common.GroupInfo;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
@@ -42,9 +43,11 @@
   GroupApi id(String id) throws RestApiException;
 
   /** Create a new group with the given name and default options. */
+  @CanIgnoreReturnValue
   GroupApi create(String name) throws RestApiException;
 
   /** Create a new group. */
+  @CanIgnoreReturnValue
   GroupApi create(GroupInput input) throws RestApiException;
 
   /** Returns new request for listing groups. */
diff --git a/java/com/google/gerrit/extensions/api/groups/package-info.java b/java/com/google/gerrit/extensions/api/groups/package-info.java
new file mode 100644
index 0000000..3322f5c
--- /dev/null
+++ b/java/com/google/gerrit/extensions/api/groups/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.api.groups;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/api/lfs/package-info.java b/java/com/google/gerrit/extensions/api/lfs/package-info.java
new file mode 100644
index 0000000..2246f8d
--- /dev/null
+++ b/java/com/google/gerrit/extensions/api/lfs/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.api.lfs;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/api/package-info.java b/java/com/google/gerrit/extensions/api/package-info.java
new file mode 100644
index 0000000..b7ad7da
--- /dev/null
+++ b/java/com/google/gerrit/extensions/api/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.api;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/api/plugins/Plugins.java b/java/com/google/gerrit/extensions/api/plugins/Plugins.java
index 6c2d6db..fed8507 100644
--- a/java/com/google/gerrit/extensions/api/plugins/Plugins.java
+++ b/java/com/google/gerrit/extensions/api/plugins/Plugins.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.plugins;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.common.PluginInfo;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
 import com.google.gerrit.extensions.restapi.RestApiException;
@@ -29,9 +30,11 @@
   PluginApi name(String name) throws RestApiException;
 
   @Deprecated
+  @CanIgnoreReturnValue
   PluginApi install(String name, com.google.gerrit.extensions.common.InstallPluginInput input)
       throws RestApiException;
 
+  @CanIgnoreReturnValue
   PluginApi install(String name, InstallPluginInput input) throws RestApiException;
 
   abstract class ListRequest {
diff --git a/java/com/google/gerrit/extensions/api/plugins/package-info.java b/java/com/google/gerrit/extensions/api/plugins/package-info.java
new file mode 100644
index 0000000..c5324d6
--- /dev/null
+++ b/java/com/google/gerrit/extensions/api/plugins/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.api.plugins;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/api/projects/BranchApi.java b/java/com/google/gerrit/extensions/api/projects/BranchApi.java
index 90f1f3f..a410205 100644
--- a/java/com/google/gerrit/extensions/api/projects/BranchApi.java
+++ b/java/com/google/gerrit/extensions/api/projects/BranchApi.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.projects;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.api.changes.ChangeApi.SuggestedReviewersRequest;
 import com.google.gerrit.extensions.restapi.BinaryResult;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
@@ -21,6 +22,7 @@
 import java.util.List;
 
 public interface BranchApi {
+  @CanIgnoreReturnValue
   BranchApi create(BranchInput in) throws RestApiException;
 
   BranchInfo get() throws RestApiException;
diff --git a/java/com/google/gerrit/extensions/api/projects/LabelApi.java b/java/com/google/gerrit/extensions/api/projects/LabelApi.java
index 975a57e..a5e23f2 100644
--- a/java/com/google/gerrit/extensions/api/projects/LabelApi.java
+++ b/java/com/google/gerrit/extensions/api/projects/LabelApi.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.projects;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.common.LabelDefinitionInfo;
 import com.google.gerrit.extensions.common.LabelDefinitionInput;
@@ -21,10 +22,12 @@
 import com.google.gerrit.extensions.restapi.RestApiException;
 
 public interface LabelApi {
+  @CanIgnoreReturnValue
   LabelApi create(LabelDefinitionInput input) throws RestApiException;
 
   LabelDefinitionInfo get() throws RestApiException;
 
+  @CanIgnoreReturnValue
   LabelDefinitionInfo update(LabelDefinitionInput input) throws RestApiException;
 
   default void delete() throws RestApiException {
diff --git a/java/com/google/gerrit/extensions/api/projects/ProjectApi.java b/java/com/google/gerrit/extensions/api/projects/ProjectApi.java
index 370068e..1169364 100644
--- a/java/com/google/gerrit/extensions/api/projects/ProjectApi.java
+++ b/java/com/google/gerrit/extensions/api/projects/ProjectApi.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.projects;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.api.access.ProjectAccessInfo;
 import com.google.gerrit.extensions.api.access.ProjectAccessInput;
 import com.google.gerrit.extensions.api.config.AccessCheckInfo;
@@ -43,6 +44,7 @@
 
   ProjectAccessInfo access() throws RestApiException;
 
+  @CanIgnoreReturnValue
   ProjectAccessInfo access(ProjectAccessInput p) throws RestApiException;
 
   ChangeInfo accessChange(ProjectAccessInput p) throws RestApiException;
@@ -53,6 +55,7 @@
 
   ConfigInfo config() throws RestApiException;
 
+  @CanIgnoreReturnValue
   ConfigInfo config(ConfigInput in) throws RestApiException;
 
   Map<String, Set<String>> commitsIn(Collection<String> commits, Collection<String> refs)
diff --git a/java/com/google/gerrit/extensions/api/projects/Projects.java b/java/com/google/gerrit/extensions/api/projects/Projects.java
index 34ca7d4..7c8ecca 100644
--- a/java/com/google/gerrit/extensions/api/projects/Projects.java
+++ b/java/com/google/gerrit/extensions/api/projects/Projects.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.projects;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.client.ProjectState;
 import com.google.gerrit.extensions.common.ProjectInfo;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
@@ -46,6 +47,7 @@
    * @return API for accessing the newly-created project.
    * @throws RestApiException if an error occurred.
    */
+  @CanIgnoreReturnValue
   ProjectApi create(String name) throws RestApiException;
 
   /**
@@ -55,6 +57,7 @@
    * @return API for accessing the newly-created project.
    * @throws RestApiException if an error occurred.
    */
+  @CanIgnoreReturnValue
   ProjectApi create(ProjectInput in) throws RestApiException;
 
   ListRequest list();
diff --git a/java/com/google/gerrit/extensions/api/projects/SubmitRequirementApi.java b/java/com/google/gerrit/extensions/api/projects/SubmitRequirementApi.java
index a6e79db..29765c0 100644
--- a/java/com/google/gerrit/extensions/api/projects/SubmitRequirementApi.java
+++ b/java/com/google/gerrit/extensions/api/projects/SubmitRequirementApi.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.projects;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.common.SubmitRequirementInfo;
 import com.google.gerrit.extensions.common.SubmitRequirementInput;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
@@ -21,12 +22,14 @@
 
 public interface SubmitRequirementApi {
   /** Create a new submit requirement. */
+  @CanIgnoreReturnValue
   SubmitRequirementApi create(SubmitRequirementInput input) throws RestApiException;
 
   /** Get existing submit requirement. */
   SubmitRequirementInfo get() throws RestApiException;
 
   /** Update existing submit requirement. */
+  @CanIgnoreReturnValue
   SubmitRequirementInfo update(SubmitRequirementInput input) throws RestApiException;
 
   /** Delete existing submit requirement. */
diff --git a/java/com/google/gerrit/extensions/api/projects/TagApi.java b/java/com/google/gerrit/extensions/api/projects/TagApi.java
index 39efeac..69c29df 100644
--- a/java/com/google/gerrit/extensions/api/projects/TagApi.java
+++ b/java/com/google/gerrit/extensions/api/projects/TagApi.java
@@ -14,10 +14,12 @@
 
 package com.google.gerrit.extensions.api.projects;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 
 public interface TagApi {
+  @CanIgnoreReturnValue
   TagApi create(TagInput input) throws RestApiException;
 
   TagInfo get() throws RestApiException;
diff --git a/java/com/google/gerrit/extensions/api/projects/package-info.java b/java/com/google/gerrit/extensions/api/projects/package-info.java
new file mode 100644
index 0000000..4fcfc28
--- /dev/null
+++ b/java/com/google/gerrit/extensions/api/projects/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.api.projects;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/auth/oauth/package-info.java b/java/com/google/gerrit/extensions/auth/oauth/package-info.java
new file mode 100644
index 0000000..591ea67
--- /dev/null
+++ b/java/com/google/gerrit/extensions/auth/oauth/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.auth.oauth;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/client/package-info.java b/java/com/google/gerrit/extensions/client/package-info.java
new file mode 100644
index 0000000..75bbfda
--- /dev/null
+++ b/java/com/google/gerrit/extensions/client/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.client;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/common/package-info.java b/java/com/google/gerrit/extensions/common/package-info.java
new file mode 100644
index 0000000..40f03b2
--- /dev/null
+++ b/java/com/google/gerrit/extensions/common/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.common;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/common/testing/BUILD b/java/com/google/gerrit/extensions/common/testing/BUILD
index 33cbb99..c126928 100644
--- a/java/com/google/gerrit/extensions/common/testing/BUILD
+++ b/java/com/google/gerrit/extensions/common/testing/BUILD
@@ -13,6 +13,7 @@
         "//lib:jgit",
         "//lib/auto:auto-value",
         "//lib/auto:auto-value-annotations",
+        "//lib/errorprone:annotations",
         "//lib/truth",
     ],
 )
diff --git a/java/com/google/gerrit/extensions/common/testing/package-info.java b/java/com/google/gerrit/extensions/common/testing/package-info.java
new file mode 100644
index 0000000..869891a
--- /dev/null
+++ b/java/com/google/gerrit/extensions/common/testing/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.common.testing;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/conditions/package-info.java b/java/com/google/gerrit/extensions/conditions/package-info.java
new file mode 100644
index 0000000..8a6b726
--- /dev/null
+++ b/java/com/google/gerrit/extensions/conditions/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.conditions;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/config/package-info.java b/java/com/google/gerrit/extensions/config/package-info.java
new file mode 100644
index 0000000..2ddb32c
--- /dev/null
+++ b/java/com/google/gerrit/extensions/config/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.config;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/events/package-info.java b/java/com/google/gerrit/extensions/events/package-info.java
new file mode 100644
index 0000000..e0a454c
--- /dev/null
+++ b/java/com/google/gerrit/extensions/events/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.events;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/package-info.java b/java/com/google/gerrit/extensions/package-info.java
new file mode 100644
index 0000000..f886030
--- /dev/null
+++ b/java/com/google/gerrit/extensions/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/registration/DynamicItem.java b/java/com/google/gerrit/extensions/registration/DynamicItem.java
index 3f848cb..4464af7 100644
--- a/java/com/google/gerrit/extensions/registration/DynamicItem.java
+++ b/java/com/google/gerrit/extensions/registration/DynamicItem.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.registration;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.inject.Binder;
 import com.google.inject.Key;
@@ -159,6 +160,7 @@
    * @param pluginName the name of the plugin providing the item.
    * @return handle to remove the item at a later point in time.
    */
+  @CanIgnoreReturnValue
   public RegistrationHandle set(T item, String pluginName) {
     return set(Providers.of(item), pluginName);
   }
@@ -170,6 +172,7 @@
    * @param pluginName name of the source providing the implementation.
    * @return handle to remove the item at a later point in time.
    */
+  @CanIgnoreReturnValue
   public RegistrationHandle set(Provider<T> impl, String pluginName) {
     final Extension<T> item = new Extension<>(pluginName, impl);
     Extension<T> old = null;
@@ -197,6 +200,7 @@
    * @param pluginName the name of the plugin providing the item.
    * @return a handle that can remove this item later, or hot-swap the item.
    */
+  @CanIgnoreReturnValue
   public ReloadableRegistrationHandle<T> set(Key<T> key, Provider<T> impl, String pluginName) {
     final Extension<T> item = new Extension<>(pluginName, impl);
     Extension<T> old = null;
diff --git a/java/com/google/gerrit/extensions/registration/DynamicSet.java b/java/com/google/gerrit/extensions/registration/DynamicSet.java
index 6dc8c6a..9925a66 100644
--- a/java/com/google/gerrit/extensions/registration/DynamicSet.java
+++ b/java/com/google/gerrit/extensions/registration/DynamicSet.java
@@ -20,6 +20,7 @@
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSortedSet;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.inject.Binder;
 import com.google.inject.Key;
@@ -249,6 +250,7 @@
    * @param item the item to add to the collection. Must not be null.
    * @return handle to remove the item at a later point in time.
    */
+  @CanIgnoreReturnValue
   public RegistrationHandle add(String pluginName, T item) {
     return add(pluginName, Providers.of(item));
   }
@@ -259,6 +261,7 @@
    * @param item the item to add to the collection. Must not be null.
    * @return handle to remove the item at a later point in time.
    */
+  @CanIgnoreReturnValue
   public RegistrationHandle add(String pluginName, Provider<T> item) {
     final AtomicReference<Extension<T>> ref =
         new AtomicReference<>(new Extension<>(pluginName, item));
@@ -281,6 +284,7 @@
    * @return a handle that can remove this item later, or hot-swap the item without it ever leaving
    *     the collection.
    */
+  @CanIgnoreReturnValue
   public ReloadableRegistrationHandle<T> add(String pluginName, Key<T> key, Provider<T> item) {
     AtomicReference<Extension<T>> ref = new AtomicReference<>(new Extension<>(pluginName, item));
     items.add(ref);
diff --git a/java/com/google/gerrit/extensions/registration/PrivateInternals_DynamicMapImpl.java b/java/com/google/gerrit/extensions/registration/PrivateInternals_DynamicMapImpl.java
index 67fc068..994a8fb 100644
--- a/java/com/google/gerrit/extensions/registration/PrivateInternals_DynamicMapImpl.java
+++ b/java/com/google/gerrit/extensions/registration/PrivateInternals_DynamicMapImpl.java
@@ -16,6 +16,7 @@
 
 import static java.util.Objects.requireNonNull;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.annotations.Export;
 import com.google.inject.Key;
@@ -51,6 +52,7 @@
    * @return a handle that can remove this item later, or hot-swap the item without it ever leaving
    *     the collection.
    */
+  @CanIgnoreReturnValue
   public ReloadableRegistrationHandle<T> put(String pluginName, Key<T> key, Provider<T> item) {
     requireNonNull(item);
     String exportName = ((Export) key.getAnnotation()).value();
diff --git a/java/com/google/gerrit/extensions/registration/package-info.java b/java/com/google/gerrit/extensions/registration/package-info.java
new file mode 100644
index 0000000..bcd5880
--- /dev/null
+++ b/java/com/google/gerrit/extensions/registration/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.registration;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/restapi/BinaryResult.java b/java/com/google/gerrit/extensions/restapi/BinaryResult.java
index 2ee376e..905c0db 100644
--- a/java/com/google/gerrit/extensions/restapi/BinaryResult.java
+++ b/java/com/google/gerrit/extensions/restapi/BinaryResult.java
@@ -16,6 +16,7 @@
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
 import java.io.IOException;
@@ -73,6 +74,7 @@
   }
 
   /** Set the MIME type of the result, and return {@code this}. */
+  @CanIgnoreReturnValue
   public BinaryResult setContentType(String contentType) {
     this.contentType = contentType != null ? contentType : OCTET_STREAM;
     return this;
@@ -84,6 +86,7 @@
   }
 
   /** Set the character set used to encode text data and return {@code this}. */
+  @CanIgnoreReturnValue
   public BinaryResult setCharacterEncoding(Charset encoding) {
     characterEncoding = encoding;
     return this;
@@ -95,6 +98,7 @@
   }
 
   /** Set the attachment file name and return {@code this}. */
+  @CanIgnoreReturnValue
   public BinaryResult setAttachmentName(String attachmentName) {
     this.attachmentName = attachmentName;
     return this;
@@ -106,6 +110,7 @@
   }
 
   /** Set the content length of the result; -1 if not known. */
+  @CanIgnoreReturnValue
   public BinaryResult setContentLength(long len) {
     this.contentLength = len;
     return this;
@@ -117,6 +122,7 @@
   }
 
   /** Disable gzip compression for already compressed responses. */
+  @CanIgnoreReturnValue
   public BinaryResult disableGzip() {
     this.gzip = false;
     return this;
@@ -128,6 +134,7 @@
   }
 
   /** Wrap the binary data in base64 encoding. */
+  @CanIgnoreReturnValue
   public BinaryResult base64() {
     base64 = true;
     return this;
diff --git a/java/com/google/gerrit/extensions/restapi/Response.java b/java/com/google/gerrit/extensions/restapi/Response.java
index 3ebae8d..85dd643 100644
--- a/java/com/google/gerrit/extensions/restapi/Response.java
+++ b/java/com/google/gerrit/extensions/restapi/Response.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.extensions.restapi;
 
 import com.google.common.collect.ImmutableMultimap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import java.util.concurrent.TimeUnit;
 
 /** Special return value to mean specific HTTP status codes in a REST API. */
@@ -90,6 +91,7 @@
 
   public abstract CacheControl caching();
 
+  @CanIgnoreReturnValue
   public abstract Response<T> caching(CacheControl c);
 
   @Override
diff --git a/java/com/google/gerrit/extensions/restapi/RestApiModule.java b/java/com/google/gerrit/extensions/restapi/RestApiModule.java
index 85bd5a1..6d0191e 100644
--- a/java/com/google/gerrit/extensions/restapi/RestApiModule.java
+++ b/java/com/google/gerrit/extensions/restapi/RestApiModule.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.restapi;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.annotations.Export;
 import com.google.gerrit.extensions.annotations.Exports;
 import com.google.gerrit.extensions.config.FactoryModule;
@@ -128,6 +129,7 @@
       this.binder = binder;
     }
 
+    @CanIgnoreReturnValue
     public <T extends RestReadView<P>> ScopedBindingBuilder to(Class<T> impl) {
       return binder.to(impl);
     }
@@ -136,11 +138,13 @@
       binder.toInstance(impl);
     }
 
+    @CanIgnoreReturnValue
     public <T extends RestReadView<P>> ScopedBindingBuilder toProvider(
         Class<? extends Provider<? extends T>> providerType) {
       return binder.toProvider(providerType);
     }
 
+    @CanIgnoreReturnValue
     public <T extends RestReadView<P>> ScopedBindingBuilder toProvider(
         Provider<? extends T> provider) {
       return binder.toProvider(provider);
@@ -154,6 +158,7 @@
       this.binder = binder;
     }
 
+    @CanIgnoreReturnValue
     public <T extends RestModifyView<P, ?>> ScopedBindingBuilder to(Class<T> impl) {
       return binder.to(impl);
     }
@@ -162,11 +167,13 @@
       binder.toInstance(impl);
     }
 
+    @CanIgnoreReturnValue
     public <T extends RestModifyView<P, ?>> ScopedBindingBuilder toProvider(
         Class<? extends Provider<? extends T>> providerType) {
       return binder.toProvider(providerType);
     }
 
+    @CanIgnoreReturnValue
     public <T extends RestModifyView<P, ?>> ScopedBindingBuilder toProvider(
         Provider<? extends T> provider) {
       return binder.toProvider(provider);
@@ -180,6 +187,7 @@
       this.binder = binder;
     }
 
+    @CanIgnoreReturnValue
     public <P extends RestResource, T extends RestCollectionModifyView<P, C, ?>>
         ScopedBindingBuilder to(Class<T> impl) {
       return binder.to(impl);
@@ -190,11 +198,13 @@
       binder.toInstance(impl);
     }
 
+    @CanIgnoreReturnValue
     public <P extends RestResource, T extends RestCollectionModifyView<P, C, ?>>
         ScopedBindingBuilder toProvider(Class<? extends Provider<? extends T>> providerType) {
       return binder.toProvider(providerType);
     }
 
+    @CanIgnoreReturnValue
     public <P extends RestResource, T extends RestCollectionModifyView<P, C, ?>>
         ScopedBindingBuilder toProvider(Provider<? extends T> provider) {
       return binder.toProvider(provider);
@@ -208,6 +218,7 @@
       this.binder = binder;
     }
 
+    @CanIgnoreReturnValue
     public <P extends RestResource, T extends RestCollectionCreateView<P, C, ?>>
         ScopedBindingBuilder to(Class<T> impl) {
       return binder.to(impl);
@@ -218,11 +229,13 @@
       binder.toInstance(impl);
     }
 
+    @CanIgnoreReturnValue
     public <P extends RestResource, T extends RestCollectionCreateView<P, C, ?>>
         ScopedBindingBuilder toProvider(Class<? extends Provider<? extends T>> providerType) {
       return binder.toProvider(providerType);
     }
 
+    @CanIgnoreReturnValue
     public <P extends RestResource, T extends RestCollectionCreateView<P, C, ?>>
         ScopedBindingBuilder toProvider(Provider<? extends T> provider) {
       return binder.toProvider(provider);
@@ -236,6 +249,7 @@
       this.binder = binder;
     }
 
+    @CanIgnoreReturnValue
     public <P extends RestResource, T extends RestCollectionDeleteMissingView<P, C, ?>>
         ScopedBindingBuilder to(Class<T> impl) {
       return binder.to(impl);
@@ -246,11 +260,13 @@
       binder.toInstance(impl);
     }
 
+    @CanIgnoreReturnValue
     public <P extends RestResource, T extends RestCollectionDeleteMissingView<P, C, ?>>
         ScopedBindingBuilder toProvider(Class<? extends Provider<? extends T>> providerType) {
       return binder.toProvider(providerType);
     }
 
+    @CanIgnoreReturnValue
     public <P extends RestResource, T extends RestCollectionDeleteMissingView<P, C, ?>>
         ScopedBindingBuilder toProvider(Provider<? extends T> provider) {
       return binder.toProvider(provider);
@@ -264,6 +280,7 @@
       this.binder = binder;
     }
 
+    @CanIgnoreReturnValue
     public <C extends RestResource, T extends ChildCollection<P, C>> ScopedBindingBuilder to(
         Class<T> impl) {
       return binder.to(impl);
@@ -273,11 +290,13 @@
       binder.toInstance(impl);
     }
 
+    @CanIgnoreReturnValue
     public <C extends RestResource, T extends ChildCollection<P, C>>
         ScopedBindingBuilder toProvider(Class<? extends Provider<? extends T>> providerType) {
       return binder.toProvider(providerType);
     }
 
+    @CanIgnoreReturnValue
     public <C extends RestResource, T extends ChildCollection<P, C>>
         ScopedBindingBuilder toProvider(Provider<? extends T> provider) {
       return binder.toProvider(provider);
diff --git a/java/com/google/gerrit/extensions/restapi/package-info.java b/java/com/google/gerrit/extensions/restapi/package-info.java
new file mode 100644
index 0000000..f3762e5
--- /dev/null
+++ b/java/com/google/gerrit/extensions/restapi/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.restapi;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/restapi/testing/BUILD b/java/com/google/gerrit/extensions/restapi/testing/BUILD
index da11ce8..a86edb8 100644
--- a/java/com/google/gerrit/extensions/restapi/testing/BUILD
+++ b/java/com/google/gerrit/extensions/restapi/testing/BUILD
@@ -9,6 +9,7 @@
         "//java/com/google/gerrit/entities",
         "//java/com/google/gerrit/extensions:api",
         "//java/com/google/gerrit/truth",
+        "//lib/errorprone:annotations",
         "//lib/truth",
     ],
 )
diff --git a/java/com/google/gerrit/extensions/restapi/testing/package-info.java b/java/com/google/gerrit/extensions/restapi/testing/package-info.java
new file mode 100644
index 0000000..74e31e7
--- /dev/null
+++ b/java/com/google/gerrit/extensions/restapi/testing/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.restapi.testing;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/systemstatus/package-info.java b/java/com/google/gerrit/extensions/systemstatus/package-info.java
new file mode 100644
index 0000000..ed9a8cc
--- /dev/null
+++ b/java/com/google/gerrit/extensions/systemstatus/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.systemstatus;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/validators/package-info.java b/java/com/google/gerrit/extensions/validators/package-info.java
new file mode 100644
index 0000000..076519a
--- /dev/null
+++ b/java/com/google/gerrit/extensions/validators/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.validators;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/extensions/webui/UiAction.java b/java/com/google/gerrit/extensions/webui/UiAction.java
index 9da0642..6c1d01d 100644
--- a/java/com/google/gerrit/extensions/webui/UiAction.java
+++ b/java/com/google/gerrit/extensions/webui/UiAction.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.extensions.webui;
 
 import com.google.common.collect.ImmutableList;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.conditions.BooleanCondition;
 import com.google.gerrit.extensions.restapi.RestResource;
@@ -68,6 +69,7 @@
     }
 
     /** Set the label to appear on the button to activate this action. */
+    @CanIgnoreReturnValue
     public Description setLabel(String label) {
       this.label = label;
       return this;
@@ -78,6 +80,7 @@
     }
 
     /** Set the tool-tip text to appear when the mouse hovers on the button. */
+    @CanIgnoreReturnValue
     public Description setTitle(String title) {
       this.title = title;
       return this;
@@ -95,6 +98,7 @@
      * Set if the action's button is visible on screen for the current client. If not visible the
      * action description may not be sent to the client.
      */
+    @CanIgnoreReturnValue
     public Description setVisible(boolean visible) {
       return setVisible(BooleanCondition.valueOf(visible));
     }
@@ -103,6 +107,7 @@
      * Set if the action's button is visible on screen for the current client. If not visible the
      * action description may not be sent to the client.
      */
+    @CanIgnoreReturnValue
     public Description setVisible(BooleanCondition visible) {
       this.visible = visible;
       return this;
@@ -117,11 +122,13 @@
     }
 
     /** Set if the button should be invokable (true), or greyed out (false). */
+    @CanIgnoreReturnValue
     public Description setEnabled(boolean enabled) {
       return setEnabled(BooleanCondition.valueOf(enabled));
     }
 
     /** Set if the button should be invokable (true), or greyed out (false). */
+    @CanIgnoreReturnValue
     public Description setEnabled(BooleanCondition enabled) {
       this.enabled = enabled;
       return this;
@@ -135,6 +142,7 @@
       return ImmutableList.copyOf(enabledOptions);
     }
 
+    @CanIgnoreReturnValue
     public Description setOption(String optionName, boolean enabled) {
       if (enabled) {
         enabledOptions.add(optionName);
diff --git a/java/com/google/gerrit/extensions/webui/package-info.java b/java/com/google/gerrit/extensions/webui/package-info.java
new file mode 100644
index 0000000..bc520f8
--- /dev/null
+++ b/java/com/google/gerrit/extensions/webui/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.extensions.webui;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/git/package-info.java b/java/com/google/gerrit/git/package-info.java
new file mode 100644
index 0000000..8c4d4b1
--- /dev/null
+++ b/java/com/google/gerrit/git/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.git;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/git/testing/BUILD b/java/com/google/gerrit/git/testing/BUILD
index fda9aff..63bcfba 100644
--- a/java/com/google/gerrit/git/testing/BUILD
+++ b/java/com/google/gerrit/git/testing/BUILD
@@ -10,6 +10,7 @@
         "//java/com/google/gerrit/common:annotations",
         "//lib:guava",
         "//lib:jgit",
+        "//lib/errorprone:annotations",
         "//lib/truth",
         "//lib/truth:truth-java8-extension",
     ],
diff --git a/java/com/google/gerrit/git/testing/package-info.java b/java/com/google/gerrit/git/testing/package-info.java
new file mode 100644
index 0000000..7ed8c4d
--- /dev/null
+++ b/java/com/google/gerrit/git/testing/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.git.testing;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/gpg/BUILD b/java/com/google/gerrit/gpg/BUILD
index 3958821..fb24f13 100644
--- a/java/com/google/gerrit/gpg/BUILD
+++ b/java/com/google/gerrit/gpg/BUILD
@@ -19,6 +19,7 @@
         "//lib/auto:auto-factory",
         "//lib/bouncycastle:bcpg-neverlink",
         "//lib/bouncycastle:bcprov-neverlink",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
         "//lib/guice:guice-assistedinject",
diff --git a/java/com/google/gerrit/gpg/Fingerprint.java b/java/com/google/gerrit/gpg/Fingerprint.java
index c12ff8b..a0212ca 100644
--- a/java/com/google/gerrit/gpg/Fingerprint.java
+++ b/java/com/google/gerrit/gpg/Fingerprint.java
@@ -16,6 +16,7 @@
 
 import static com.google.common.base.Preconditions.checkArgument;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -53,6 +54,7 @@
     return Collections.unmodifiableMap(result);
   }
 
+  @CanIgnoreReturnValue
   private static byte[] checkLength(byte[] fp) {
     checkArgument(fp.length == 20, "fingerprint must be 20 bytes, got %s", fp.length);
     return fp;
diff --git a/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java b/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java
index fff4045..3940cc9 100644
--- a/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java
+++ b/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java
@@ -22,6 +22,7 @@
 import com.google.common.collect.Maps;
 import com.google.common.flogger.FluentLogger;
 import com.google.common.io.BaseEncoding;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.registration.DynamicItem;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountState;
@@ -129,6 +130,7 @@
    * user. (Other keys checked in the course of verifying the web of trust are checked against the
    * set of identities in the database belonging to the same user as the key.)
    */
+  @CanIgnoreReturnValue
   public GerritPublicKeyChecker setExpectedUser(IdentifiedUser expectedUser) {
     this.expectedUser = expectedUser;
     return this;
diff --git a/java/com/google/gerrit/gpg/PublicKeyChecker.java b/java/com/google/gerrit/gpg/PublicKeyChecker.java
index 946fee3..2f8f7e9 100644
--- a/java/com/google/gerrit/gpg/PublicKeyChecker.java
+++ b/java/com/google/gerrit/gpg/PublicKeyChecker.java
@@ -30,6 +30,7 @@
 import static org.bouncycastle.openpgp.PGPSignature.KEY_REVOCATION;
 
 import com.google.common.flogger.FluentLogger;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.common.GpgKeyInfo.Status;
 import java.io.IOException;
@@ -77,6 +78,7 @@
    *     construct a map, see {@link Fingerprint#byId(Iterable)}.
    * @return a reference to this object.
    */
+  @CanIgnoreReturnValue
   public PublicKeyChecker enableTrust(int maxTrustDepth, Map<Long, Fingerprint> trusted) {
     if (maxTrustDepth <= 0) {
       throw new IllegalArgumentException("maxTrustDepth must be positive, got: " + maxTrustDepth);
@@ -90,12 +92,14 @@
   }
 
   /** Disable web-of-trust checks. */
+  @CanIgnoreReturnValue
   public PublicKeyChecker disableTrust() {
     trusted = null;
     return this;
   }
 
   /** Set the public key store for reading keys referenced in signatures. */
+  @CanIgnoreReturnValue
   public PublicKeyChecker setStore(PublicKeyStore store) {
     if (store == null) {
       throw new IllegalArgumentException("PublicKeyStore is required");
@@ -112,6 +116,7 @@
    * @param effectiveTime effective time.
    * @return a reference to this object.
    */
+  @CanIgnoreReturnValue
   public PublicKeyChecker setEffectiveTime(Instant effectiveTime) {
     this.effectiveTime = effectiveTime;
     return this;
diff --git a/java/com/google/gerrit/gpg/api/GpgKeyApiImpl.java b/java/com/google/gerrit/gpg/api/GpgKeyApiImpl.java
index 2a05f35..713db48 100644
--- a/java/com/google/gerrit/gpg/api/GpgKeyApiImpl.java
+++ b/java/com/google/gerrit/gpg/api/GpgKeyApiImpl.java
@@ -55,7 +55,8 @@
   @Override
   public void delete() throws RestApiException {
     try {
-      delete.apply(rsrc, new Input());
+      @SuppressWarnings("unused")
+      var unused = delete.apply(rsrc, new Input());
     } catch (RestApiException e) {
       throw e;
     } catch (PGPException | IOException | ConfigInvalidException e) {
diff --git a/java/com/google/gerrit/gpg/api/package-info.java b/java/com/google/gerrit/gpg/api/package-info.java
new file mode 100644
index 0000000..524dc1c
--- /dev/null
+++ b/java/com/google/gerrit/gpg/api/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.gpg.api;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/gpg/package-info.java b/java/com/google/gerrit/gpg/package-info.java
new file mode 100644
index 0000000..6e56395
--- /dev/null
+++ b/java/com/google/gerrit/gpg/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.gpg;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/gpg/server/package-info.java b/java/com/google/gerrit/gpg/server/package-info.java
new file mode 100644
index 0000000..5379c44
--- /dev/null
+++ b/java/com/google/gerrit/gpg/server/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.gpg.server;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/gpg/testing/BUILD b/java/com/google/gerrit/gpg/testing/BUILD
index dc39071..d55360b 100644
--- a/java/com/google/gerrit/gpg/testing/BUILD
+++ b/java/com/google/gerrit/gpg/testing/BUILD
@@ -10,5 +10,6 @@
         "//lib:guava",
         "//lib:jgit",
         "//lib/bouncycastle:bcpg-neverlink",
+        "//lib/errorprone:annotations",
     ],
 )
diff --git a/java/com/google/gerrit/gpg/testing/package-info.java b/java/com/google/gerrit/gpg/testing/package-info.java
new file mode 100644
index 0000000..d9606c3
--- /dev/null
+++ b/java/com/google/gerrit/gpg/testing/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.gpg.testing;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/AllRequestFilter.java b/java/com/google/gerrit/httpd/AllRequestFilter.java
index 1c3cafe..0422655 100644
--- a/java/com/google/gerrit/httpd/AllRequestFilter.java
+++ b/java/com/google/gerrit/httpd/AllRequestFilter.java
@@ -70,7 +70,7 @@
      * Initializes a filter if needed
      *
      * @param filter The filter that should get initialized
-     * @return {@code true} iff filter is now initialized
+     * @return {@code true} if filter is now initialized
      * @throws ServletException if filter itself fails to init
      */
     private synchronized boolean initFilterIfNeeded(AllRequestFilter filter)
@@ -150,7 +150,8 @@
       filterConfig = config;
 
       for (AllRequestFilter f : filters) {
-        initFilterIfNeeded(f);
+        @SuppressWarnings("unused")
+        var unused = initFilterIfNeeded(f);
       }
     }
 
diff --git a/java/com/google/gerrit/httpd/UrlModule.java b/java/com/google/gerrit/httpd/UrlModule.java
index aad6b57..0f0a3ab 100644
--- a/java/com/google/gerrit/httpd/UrlModule.java
+++ b/java/com/google/gerrit/httpd/UrlModule.java
@@ -43,7 +43,7 @@
 import org.eclipse.jgit.lib.Constants;
 
 class UrlModule extends ServletModule {
-  private AuthConfig authConfig;
+  private final AuthConfig authConfig;
 
   UrlModule(AuthConfig authConfig) {
     this.authConfig = authConfig;
diff --git a/java/com/google/gerrit/httpd/auth/become/package-info.java b/java/com/google/gerrit/httpd/auth/become/package-info.java
new file mode 100644
index 0000000..6887673
--- /dev/null
+++ b/java/com/google/gerrit/httpd/auth/become/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.auth.become;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/auth/container/package-info.java b/java/com/google/gerrit/httpd/auth/container/package-info.java
new file mode 100644
index 0000000..ca1c89f
--- /dev/null
+++ b/java/com/google/gerrit/httpd/auth/container/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.auth.container;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/auth/ldap/package-info.java b/java/com/google/gerrit/httpd/auth/ldap/package-info.java
new file mode 100644
index 0000000..2a81cc9
--- /dev/null
+++ b/java/com/google/gerrit/httpd/auth/ldap/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.auth.ldap;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/auth/oauth/BUILD b/java/com/google/gerrit/httpd/auth/oauth/BUILD
index 2bc65de4..3ced4ab 100644
--- a/java/com/google/gerrit/httpd/auth/oauth/BUILD
+++ b/java/com/google/gerrit/httpd/auth/oauth/BUILD
@@ -17,6 +17,7 @@
         "//lib:guava",
         "//lib:jgit",
         "//lib:servlet-api",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
         "//lib/guice:guice-servlet",
diff --git a/java/com/google/gerrit/httpd/auth/oauth/OAuthWebFilter.java b/java/com/google/gerrit/httpd/auth/oauth/OAuthWebFilter.java
index 935762f..453dc0b 100644
--- a/java/com/google/gerrit/httpd/auth/oauth/OAuthWebFilter.java
+++ b/java/com/google/gerrit/httpd/auth/oauth/OAuthWebFilter.java
@@ -102,7 +102,9 @@
         service = findService(provider);
       }
       oauthSession.setServiceProvider(service);
-      oauthSession.login(httpRequest, httpResponse, service);
+
+      @SuppressWarnings("unused")
+      var unused = oauthSession.login(httpRequest, httpResponse, service);
     } else {
       chain.doFilter(httpRequest, response);
     }
diff --git a/java/com/google/gerrit/httpd/auth/oauth/package-info.java b/java/com/google/gerrit/httpd/auth/oauth/package-info.java
new file mode 100644
index 0000000..4f8c601
--- /dev/null
+++ b/java/com/google/gerrit/httpd/auth/oauth/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.auth.oauth;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/auth/openid/BUILD b/java/com/google/gerrit/httpd/auth/openid/BUILD
index 29841aa..7afb8ac 100644
--- a/java/com/google/gerrit/httpd/auth/openid/BUILD
+++ b/java/com/google/gerrit/httpd/auth/openid/BUILD
@@ -17,6 +17,7 @@
         "//java/com/google/gerrit/server",
         "//lib:guava",
         "//lib:servlet-api",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
         "//lib/guice:guice-servlet",
diff --git a/java/com/google/gerrit/httpd/auth/openid/LoginForm.java b/java/com/google/gerrit/httpd/auth/openid/LoginForm.java
index e7057ad..4ed9078 100644
--- a/java/com/google/gerrit/httpd/auth/openid/LoginForm.java
+++ b/java/com/google/gerrit/httpd/auth/openid/LoginForm.java
@@ -174,7 +174,9 @@
       if ((isGerritLogin(req) || oauthSession.isOAuthFinal(req))) {
         oauthSession.setServiceProvider(oauthProvider);
         oauthSession.setLinkMode(link);
-        oauthSession.login(req, res, oauthProvider);
+
+        @SuppressWarnings("unused")
+        var unused = oauthSession.login(req, res, oauthProvider);
       }
     }
   }
diff --git a/java/com/google/gerrit/httpd/auth/openid/OAuthWebFilterOverOpenID.java b/java/com/google/gerrit/httpd/auth/openid/OAuthWebFilterOverOpenID.java
index 3d9c819..043b7a1 100644
--- a/java/com/google/gerrit/httpd/auth/openid/OAuthWebFilterOverOpenID.java
+++ b/java/com/google/gerrit/httpd/auth/openid/OAuthWebFilterOverOpenID.java
@@ -72,7 +72,9 @@
         throw new IllegalStateException("service is unknown");
       }
       oauthSession.setServiceProvider(service);
-      oauthSession.login(httpRequest, httpResponse, service);
+
+      @SuppressWarnings("unused")
+      var unused = oauthSession.login(httpRequest, httpResponse, service);
     } else {
       chain.doFilter(httpRequest, response);
     }
diff --git a/java/com/google/gerrit/httpd/auth/openid/package-info.java b/java/com/google/gerrit/httpd/auth/openid/package-info.java
new file mode 100644
index 0000000..5e597da
--- /dev/null
+++ b/java/com/google/gerrit/httpd/auth/openid/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.auth.openid;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/auth/restapi/BUILD b/java/com/google/gerrit/httpd/auth/restapi/BUILD
index 9ab51c5..a85fd5e 100644
--- a/java/com/google/gerrit/httpd/auth/restapi/BUILD
+++ b/java/com/google/gerrit/httpd/auth/restapi/BUILD
@@ -9,6 +9,7 @@
         "//java/com/google/gerrit/common:annotations",
         "//java/com/google/gerrit/extensions:api",
         "//java/com/google/gerrit/server",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
     ],
diff --git a/java/com/google/gerrit/httpd/auth/restapi/package-info.java b/java/com/google/gerrit/httpd/auth/restapi/package-info.java
new file mode 100644
index 0000000..a56dbde
--- /dev/null
+++ b/java/com/google/gerrit/httpd/auth/restapi/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.auth.restapi;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/gitweb/package-info.java b/java/com/google/gerrit/httpd/gitweb/package-info.java
new file mode 100644
index 0000000..614388e
--- /dev/null
+++ b/java/com/google/gerrit/httpd/gitweb/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.gitweb;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/init/BUILD b/java/com/google/gerrit/httpd/init/BUILD
index 990b5d7..e6fc53c 100644
--- a/java/com/google/gerrit/httpd/init/BUILD
+++ b/java/com/google/gerrit/httpd/init/BUILD
@@ -31,6 +31,7 @@
         "//lib:jgit",
         "//lib:jgit-ssh-apache",
         "//lib:servlet-api",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
         "//lib/guice:guice-servlet",
diff --git a/java/com/google/gerrit/httpd/init/SiteInitializer.java b/java/com/google/gerrit/httpd/init/SiteInitializer.java
index 04a0ddd..c59a8ed 100644
--- a/java/com/google/gerrit/httpd/init/SiteInitializer.java
+++ b/java/com/google/gerrit/httpd/init/SiteInitializer.java
@@ -47,7 +47,10 @@
       if (sitePath != null) {
         Path site = Paths.get(sitePath);
         logger.atInfo().log("Initializing site at %s", site.toRealPath().normalize());
-        new BaseInit(site, false, pluginsDistribution, pluginsToInstall).run();
+
+        @SuppressWarnings("unused")
+        var unused = new BaseInit(site, false, pluginsDistribution, pluginsToInstall).run();
+
         return;
       }
 
@@ -62,7 +65,9 @@
       }
       if (site != null) {
         logger.atInfo().log("Initializing site at %s", site.toRealPath().normalize());
-        new BaseInit(site, false, pluginsDistribution, pluginsToInstall).run();
+
+        @SuppressWarnings("unused")
+        var unused = new BaseInit(site, false, pluginsDistribution, pluginsToInstall).run();
       }
     } catch (Exception e) {
       logger.atSevere().withCause(e).log("Site init failed");
diff --git a/java/com/google/gerrit/httpd/init/package-info.java b/java/com/google/gerrit/httpd/init/package-info.java
new file mode 100644
index 0000000..8ca6c9f
--- /dev/null
+++ b/java/com/google/gerrit/httpd/init/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.init;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/package-info.java b/java/com/google/gerrit/httpd/package-info.java
new file mode 100644
index 0000000..e0bb8e0
--- /dev/null
+++ b/java/com/google/gerrit/httpd/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/plugins/HttpAutoRegisterModuleGenerator.java b/java/com/google/gerrit/httpd/plugins/HttpAutoRegisterModuleGenerator.java
index 9ab2d72..3d0a139 100644
--- a/java/com/google/gerrit/httpd/plugins/HttpAutoRegisterModuleGenerator.java
+++ b/java/com/google/gerrit/httpd/plugins/HttpAutoRegisterModuleGenerator.java
@@ -30,6 +30,7 @@
 import java.util.Map;
 import javax.servlet.http.HttpServlet;
 
+@SuppressWarnings("MutableGuiceModule")
 class HttpAutoRegisterModuleGenerator extends ServletModule implements ModuleGenerator {
   private final Map<String, Class<HttpServlet>> serve = new HashMap<>();
   private final ListMultimap<TypeLiteral<?>, Class<?>> listeners = LinkedListMultimap.create();
diff --git a/java/com/google/gerrit/httpd/plugins/package-info.java b/java/com/google/gerrit/httpd/plugins/package-info.java
new file mode 100644
index 0000000..1149405
--- /dev/null
+++ b/java/com/google/gerrit/httpd/plugins/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.plugins;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/raw/StaticModule.java b/java/com/google/gerrit/httpd/raw/StaticModule.java
index 37b4b59..e056587 100644
--- a/java/com/google/gerrit/httpd/raw/StaticModule.java
+++ b/java/com/google/gerrit/httpd/raw/StaticModule.java
@@ -88,19 +88,17 @@
   private static final String ROBOTS_TXT_SERVLET = "RobotsTxtServlet";
 
   private final GerritOptions options;
-  private Paths paths;
+  private final Paths paths;
 
   @Inject
   public StaticModule(GerritOptions options) {
     this.options = options;
+    this.paths = new Paths(options);
   }
 
   @Provides
   @Singleton
   private Paths getPaths() {
-    if (paths == null) {
-      paths = new Paths(options);
-    }
     return paths;
   }
 
diff --git a/java/com/google/gerrit/httpd/raw/package-info.java b/java/com/google/gerrit/httpd/raw/package-info.java
new file mode 100644
index 0000000..6505062
--- /dev/null
+++ b/java/com/google/gerrit/httpd/raw/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.raw;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/resources/package-info.java b/java/com/google/gerrit/httpd/resources/package-info.java
new file mode 100644
index 0000000..94d35f6
--- /dev/null
+++ b/java/com/google/gerrit/httpd/resources/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.resources;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
index d9b15b4..03a0b42 100644
--- a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
+++ b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
@@ -51,6 +51,7 @@
 import com.google.common.io.CountingOutputStream;
 import com.google.common.math.IntMath;
 import com.google.common.net.HttpHeaders;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.RawInputUtil;
 import com.google.gerrit.entities.Project;
@@ -1306,6 +1307,7 @@
    * @param result the object that should be formatted as JSON
    * @return the length of the response
    */
+  @CanIgnoreReturnValue
   public static long replyJson(
       @Nullable HttpServletRequest req,
       HttpServletResponse res,
@@ -1397,6 +1399,7 @@
   }
 
   @SuppressWarnings("resource")
+  @CanIgnoreReturnValue
   static long replyBinaryResult(
       @Nullable HttpServletRequest req, HttpServletResponse res, BinaryResult bin)
       throws IOException {
@@ -1840,6 +1843,7 @@
     return uri;
   }
 
+  @CanIgnoreReturnValue
   public static long replyError(
       HttpServletRequest req,
       HttpServletResponse res,
@@ -1850,6 +1854,7 @@
     return replyError(req, res, statusCode, msg, CacheControl.NONE, err);
   }
 
+  @CanIgnoreReturnValue
   public static long replyError(
       HttpServletRequest req,
       HttpServletResponse res,
@@ -1878,6 +1883,7 @@
    * @param text the text reply
    * @return the length of the response
    */
+  @CanIgnoreReturnValue
   static long replyText(
       @Nullable HttpServletRequest req, HttpServletResponse res, boolean allowTracing, String text)
       throws IOException {
diff --git a/java/com/google/gerrit/httpd/restapi/package-info.java b/java/com/google/gerrit/httpd/restapi/package-info.java
new file mode 100644
index 0000000..b38188f
--- /dev/null
+++ b/java/com/google/gerrit/httpd/restapi/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.restapi;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/httpd/template/package-info.java b/java/com/google/gerrit/httpd/template/package-info.java
new file mode 100644
index 0000000..374cc91
--- /dev/null
+++ b/java/com/google/gerrit/httpd/template/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.httpd.template;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/index/IndexCollection.java b/java/com/google/gerrit/index/IndexCollection.java
index c61e6c7..66a9fba 100644
--- a/java/com/google/gerrit/index/IndexCollection.java
+++ b/java/com/google/gerrit/index/IndexCollection.java
@@ -16,6 +16,7 @@
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Lists;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.events.LifecycleListener;
 import java.util.Collection;
 import java.util.Collections;
@@ -53,6 +54,7 @@
     return Collections.unmodifiableCollection(writeIndexes);
   }
 
+  @CanIgnoreReturnValue
   public synchronized I addWriteIndex(I index) {
     int version = index.getSchema().getVersion();
     for (int i = 0; i < writeIndexes.size(); i++) {
diff --git a/java/com/google/gerrit/index/IndexedField.java b/java/com/google/gerrit/index/IndexedField.java
index 94943d6..d1aaff6 100644
--- a/java/com/google/gerrit/index/IndexedField.java
+++ b/java/com/google/gerrit/index/IndexedField.java
@@ -23,6 +23,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.reflect.TypeToken;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.converter.ProtoConverter;
 import com.google.gerrit.exceptions.StorageException;
@@ -211,6 +212,7 @@
       return IndexedField.this;
     }
 
+    @CanIgnoreReturnValue
     private String checkName(String name) {
       CharMatcher m = CharMatcher.anyOf("abcdefghijklmnopqrstuvwxyz0123456789_");
       checkArgument(name != null && m.matchesAllOf(name), "illegal field name: %s", name);
@@ -350,6 +352,7 @@
       return this.getter(getter).fieldSetter(Optional.empty()).build();
     }
 
+    @CanIgnoreReturnValue
     private static String checkName(String name) {
       String allowedCharacters = "abcdefghijklmnopqrstuvwxyz0123456789_";
       CharMatcher m =
diff --git a/java/com/google/gerrit/index/Schema.java b/java/com/google/gerrit/index/Schema.java
index ab10d9e..dcd7591 100644
--- a/java/com/google/gerrit/index/Schema.java
+++ b/java/com/google/gerrit/index/Schema.java
@@ -26,6 +26,7 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 import com.google.common.flogger.FluentLogger;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.exceptions.StorageException;
 import com.google.gerrit.index.SchemaFieldDefs.SchemaField;
@@ -48,11 +49,13 @@
 
     private Optional<Integer> version = Optional.empty();
 
+    @CanIgnoreReturnValue
     public Builder<T> version(int version) {
       this.version = Optional.of(version);
       return this;
     }
 
+    @CanIgnoreReturnValue
     public Builder<T> add(Schema<T> schema) {
       this.indexedFields.addAll(schema.getIndexFields().values());
       this.searchFields.addAll(schema.getSchemaFields().values());
@@ -63,10 +66,12 @@
     }
 
     @SafeVarargs
+    @CanIgnoreReturnValue
     public final Builder<T> addSearchSpecs(IndexedField<T, ?>.SearchSpec... searchSpecs) {
       return addSearchSpecs(ImmutableList.copyOf(searchSpecs));
     }
 
+    @CanIgnoreReturnValue
     public Builder<T> addSearchSpecs(ImmutableList<IndexedField<T, ?>.SearchSpec> searchSpecs) {
       for (IndexedField<T, ?>.SearchSpec searchSpec : searchSpecs) {
         checkArgument(
@@ -80,22 +85,26 @@
     }
 
     @SafeVarargs
+    @CanIgnoreReturnValue
     public final Builder<T> addIndexedFields(IndexedField<T, ?>... fields) {
       return addIndexedFields(ImmutableList.copyOf(fields));
     }
 
+    @CanIgnoreReturnValue
     public Builder<T> addIndexedFields(ImmutableList<IndexedField<T, ?>> indexedFields) {
       this.indexedFields.addAll(indexedFields);
       return this;
     }
 
     @SafeVarargs
+    @CanIgnoreReturnValue
     public final Builder<T> remove(IndexedField<T, ?>.SearchSpec... searchSpecs) {
       this.searchFields.removeAll(Arrays.asList(searchSpecs));
       return this;
     }
 
     @SafeVarargs
+    @CanIgnoreReturnValue
     public final Builder<T> remove(IndexedField<T, ?>... indexedFields) {
       for (IndexedField<T, ?> field : indexedFields) {
         ImmutableMap<String, ? extends IndexedField<T, ?>.SearchSpec> searchSpecs =
@@ -134,6 +143,7 @@
     }
   }
 
+  @CanIgnoreReturnValue
   private static <T> SchemaField<T, ?> checkSame(SchemaField<T, ?> f1, SchemaField<T, ?> f2) {
     checkState(f1 == f2, "Mismatched %s fields: %s != %s", f1.getName(), f1, f2);
     return f1;
diff --git a/java/com/google/gerrit/index/package-info.java b/java/com/google/gerrit/index/package-info.java
new file mode 100644
index 0000000..9c652fe
--- /dev/null
+++ b/java/com/google/gerrit/index/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.index;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/index/project/BUILD b/java/com/google/gerrit/index/project/BUILD
index b423f84..b029513 100644
--- a/java/com/google/gerrit/index/project/BUILD
+++ b/java/com/google/gerrit/index/project/BUILD
@@ -9,6 +9,7 @@
         "//java/com/google/gerrit/index",
         "//java/com/google/gerrit/index:query_exception",
         "//lib:guava",
+        "//lib/errorprone:annotations",
         "//lib/guice",
     ],
 )
diff --git a/java/com/google/gerrit/index/project/package-info.java b/java/com/google/gerrit/index/project/package-info.java
new file mode 100644
index 0000000..8965ed5
--- /dev/null
+++ b/java/com/google/gerrit/index/project/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.index.project;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/index/query/InternalQuery.java b/java/com/google/gerrit/index/query/InternalQuery.java
index f40d38e..24ce0fe 100644
--- a/java/com/google/gerrit/index/query/InternalQuery.java
+++ b/java/com/google/gerrit/index/query/InternalQuery.java
@@ -20,6 +20,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.exceptions.StorageException;
 import com.google.gerrit.index.Index;
@@ -61,22 +62,26 @@
     return (Q) this;
   }
 
+  @CanIgnoreReturnValue
   final Q setStart(int start) {
     queryProcessor.setStart(start);
     return self();
   }
 
+  @CanIgnoreReturnValue
   public final Q setLimit(int n) {
     queryProcessor.setUserProvidedLimit(n, /* applyDefaultLimit */ false);
     return self();
   }
 
+  @CanIgnoreReturnValue
   public final Q enforceVisibility(boolean enforce) {
     queryProcessor.enforceVisibility(enforce);
     return self();
   }
 
   @SafeVarargs
+  @CanIgnoreReturnValue
   public final Q setRequestedFields(SchemaField<T, ?>... fields) {
     checkArgument(fields.length > 0, "requested field list is empty");
     queryProcessor.setRequestedFields(
@@ -84,6 +89,7 @@
     return self();
   }
 
+  @CanIgnoreReturnValue
   public final Q noFields() {
     queryProcessor.setRequestedFields(ImmutableSet.of());
     return self();
diff --git a/java/com/google/gerrit/index/query/QueryProcessor.java b/java/com/google/gerrit/index/query/QueryProcessor.java
index 4a230bd..b8eb8bb 100644
--- a/java/com/google/gerrit/index/query/QueryProcessor.java
+++ b/java/com/google/gerrit/index/query/QueryProcessor.java
@@ -122,6 +122,7 @@
             .build();
   }
 
+  @CanIgnoreReturnValue
   public QueryProcessor<T> setStart(int n) {
     start = n;
     return this;
@@ -141,6 +142,7 @@
    * @param enforce whether to enforce visibility.
    * @return this.
    */
+  @CanIgnoreReturnValue
   public QueryProcessor<T> enforceVisibility(boolean enforce) {
     enforceVisibility = enforce;
     return this;
diff --git a/java/com/google/gerrit/index/query/package-info.java b/java/com/google/gerrit/index/query/package-info.java
new file mode 100644
index 0000000..ab99f47
--- /dev/null
+++ b/java/com/google/gerrit/index/query/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.index.query;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/index/query/testing/BUILD b/java/com/google/gerrit/index/query/testing/BUILD
index 1785f49..1e61988 100644
--- a/java/com/google/gerrit/index/query/testing/BUILD
+++ b/java/com/google/gerrit/index/query/testing/BUILD
@@ -12,6 +12,7 @@
         "//antlr3:query_parser",
         "//lib:guava",
         "//lib/antlr:java-runtime",
+        "//lib/errorprone:annotations",
         "//lib/truth",
     ],
 )
diff --git a/java/com/google/gerrit/index/query/testing/package-info.java b/java/com/google/gerrit/index/query/testing/package-info.java
new file mode 100644
index 0000000..20604ad
--- /dev/null
+++ b/java/com/google/gerrit/index/query/testing/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.index.query.testing;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/index/testing/AbstractFakeIndex.java b/java/com/google/gerrit/index/testing/AbstractFakeIndex.java
index 86d062b2..a181df6 100644
--- a/java/com/google/gerrit/index/testing/AbstractFakeIndex.java
+++ b/java/com/google/gerrit/index/testing/AbstractFakeIndex.java
@@ -288,7 +288,10 @@
                   Integer.valueOf((String) doc.get(ChangeField.NUMERIC_ID_STR_SPEC.getName()))));
       for (SchemaField<ChangeData, ?> field : getSchema().getSchemaFields().values()) {
         boolean isProtoField = SchemaFieldDefs.isProtoField(field);
-        field.setIfPossible(cd, new FakeStoredValue(doc.get(field.getName()), isProtoField));
+
+        @SuppressWarnings("unused")
+        var unused =
+            field.setIfPossible(cd, new FakeStoredValue(doc.get(field.getName()), isProtoField));
       }
       return cd;
     }
diff --git a/java/com/google/gerrit/index/testing/BUILD b/java/com/google/gerrit/index/testing/BUILD
index 44bf70d..c9f1994 100644
--- a/java/com/google/gerrit/index/testing/BUILD
+++ b/java/com/google/gerrit/index/testing/BUILD
@@ -16,6 +16,7 @@
         "//lib:guava",
         "//lib:jgit",
         "//lib:protobuf",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
         "//lib/guice:guice-assistedinject",
diff --git a/java/com/google/gerrit/index/testing/FakeIndexModule.java b/java/com/google/gerrit/index/testing/FakeIndexModule.java
index 126ff10..b4d5315 100644
--- a/java/com/google/gerrit/index/testing/FakeIndexModule.java
+++ b/java/com/google/gerrit/index/testing/FakeIndexModule.java
@@ -21,7 +21,6 @@
 import com.google.gerrit.server.index.account.AccountIndex;
 import com.google.gerrit.server.index.change.ChangeIndex;
 import com.google.gerrit.server.index.group.GroupIndex;
-import java.util.Map;
 
 /** Module to bind {@link FakeIndexModule}. */
 public class FakeIndexModule extends AbstractIndexModule {
@@ -30,15 +29,16 @@
   }
 
   public static FakeIndexModule singleVersionWithExplicitVersions(
-      Map<String, Integer> versions, int threads, boolean secondary) {
+      ImmutableMap<String, Integer> versions, int threads, boolean secondary) {
     return new FakeIndexModule(versions, threads, secondary);
   }
 
   public static FakeIndexModule latestVersion(boolean secondary) {
-    return new FakeIndexModule(null, -1 /* direct executor */, secondary);
+    return new FakeIndexModule(/* singleVersions= */ null, -1 /* direct executor */, secondary);
   }
 
-  private FakeIndexModule(Map<String, Integer> singleVersions, int threads, boolean secondary) {
+  private FakeIndexModule(
+      ImmutableMap<String, Integer> singleVersions, int threads, boolean secondary) {
     super(singleVersions, threads, secondary);
   }
 
diff --git a/java/com/google/gerrit/index/testing/package-info.java b/java/com/google/gerrit/index/testing/package-info.java
new file mode 100644
index 0000000..0f6e5b2
--- /dev/null
+++ b/java/com/google/gerrit/index/testing/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.index.testing;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/jgit/BUILD b/java/com/google/gerrit/jgit/BUILD
index 1041f1f..04f2220 100644
--- a/java/com/google/gerrit/jgit/BUILD
+++ b/java/com/google/gerrit/jgit/BUILD
@@ -9,5 +9,6 @@
     deps = [
         "//lib:gson",
         "//lib:jgit",
+        "//lib/errorprone:annotations",
     ],
 )
diff --git a/java/com/google/gerrit/jgit/diff/package-info.java b/java/com/google/gerrit/jgit/diff/package-info.java
new file mode 100644
index 0000000..ba04b82
--- /dev/null
+++ b/java/com/google/gerrit/jgit/diff/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.jgit.diff;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/json/BUILD b/java/com/google/gerrit/json/BUILD
index 7b2fe2f..601a7b4 100644
--- a/java/com/google/gerrit/json/BUILD
+++ b/java/com/google/gerrit/json/BUILD
@@ -9,6 +9,7 @@
         "//java/com/google/gerrit/entities",
         "//lib:gson",
         "//lib:guava",
+        "//lib/errorprone:annotations",
         "//lib/guice",
     ],
 )
diff --git a/java/com/google/gerrit/json/package-info.java b/java/com/google/gerrit/json/package-info.java
new file mode 100644
index 0000000..000b667
--- /dev/null
+++ b/java/com/google/gerrit/json/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.json;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/launcher/BUILD b/java/com/google/gerrit/launcher/BUILD
index 15fa0ce..309d1dd 100644
--- a/java/com/google/gerrit/launcher/BUILD
+++ b/java/com/google/gerrit/launcher/BUILD
@@ -6,4 +6,7 @@
     name = "launcher",
     srcs = ["GerritLauncher.java"],
     visibility = ["//visibility:public"],
+    deps = [
+        "//lib/errorprone:annotations",
+    ],
 )
diff --git a/java/com/google/gerrit/launcher/package-info.java b/java/com/google/gerrit/launcher/package-info.java
new file mode 100644
index 0000000..b30810c
--- /dev/null
+++ b/java/com/google/gerrit/launcher/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.launcher;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/lifecycle/BUILD b/java/com/google/gerrit/lifecycle/BUILD
index a3f3d81..fa3c2a3 100644
--- a/java/com/google/gerrit/lifecycle/BUILD
+++ b/java/com/google/gerrit/lifecycle/BUILD
@@ -7,6 +7,7 @@
     deps = [
         "//java/com/google/gerrit/extensions:api",
         "//lib:guava",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
     ],
diff --git a/java/com/google/gerrit/lifecycle/package-info.java b/java/com/google/gerrit/lifecycle/package-info.java
new file mode 100644
index 0000000..753cc8b
--- /dev/null
+++ b/java/com/google/gerrit/lifecycle/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.lifecycle;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/lucene/BUILD b/java/com/google/gerrit/lucene/BUILD
index a90ed67..6584bfd 100644
--- a/java/com/google/gerrit/lucene/BUILD
+++ b/java/com/google/gerrit/lucene/BUILD
@@ -10,6 +10,7 @@
         "//java/com/google/gerrit/index",
         "//java/com/google/gerrit/index:query_exception",
         "//lib:guava",
+        "//lib/errorprone:annotations",
         "//lib/lucene:lucene-core",
     ],
 )
@@ -35,6 +36,7 @@
         "//lib:guava",
         "//lib:jgit",
         "//lib:protobuf",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
         "//lib/guice:guice-assistedinject",
diff --git a/java/com/google/gerrit/lucene/LuceneChangeIndex.java b/java/com/google/gerrit/lucene/LuceneChangeIndex.java
index 45288d5..9fcf5ae 100644
--- a/java/com/google/gerrit/lucene/LuceneChangeIndex.java
+++ b/java/com/google/gerrit/lucene/LuceneChangeIndex.java
@@ -583,7 +583,8 @@
 
     for (SchemaField<ChangeData, ?> field : getSchema().getSchemaFields().values()) {
       if (fields.contains(field.getName())) {
-        field.setIfPossible(cd, new LuceneStoredValue(doc.get(field.getName())));
+        @SuppressWarnings("unused")
+        var unused = field.setIfPossible(cd, new LuceneStoredValue(doc.get(field.getName())));
       }
     }
     return cd;
diff --git a/java/com/google/gerrit/lucene/LuceneIndexModule.java b/java/com/google/gerrit/lucene/LuceneIndexModule.java
index 3aa9c6e..89b83a4 100644
--- a/java/com/google/gerrit/lucene/LuceneIndexModule.java
+++ b/java/com/google/gerrit/lucene/LuceneIndexModule.java
@@ -26,7 +26,6 @@
 import com.google.gerrit.server.index.change.ChangeIndex;
 import com.google.gerrit.server.index.group.GroupIndex;
 import com.google.gerrit.server.index.options.AutoFlush;
-import java.util.Map;
 import org.apache.lucene.search.BooleanQuery;
 import org.eclipse.jgit.lib.Config;
 
@@ -41,17 +40,17 @@
 
   @VisibleForTesting
   public static LuceneIndexModule singleVersionWithExplicitVersions(
-      Map<String, Integer> versions, int threads, boolean slave) {
+      ImmutableMap<String, Integer> versions, int threads, boolean slave) {
     return new LuceneIndexModule(versions, threads, slave, AutoFlush.ENABLED);
   }
 
   public static LuceneIndexModule singleVersionWithExplicitVersions(
-      Map<String, Integer> versions, int threads, boolean slave, AutoFlush autoFlush) {
+      ImmutableMap<String, Integer> versions, int threads, boolean slave, AutoFlush autoFlush) {
     return new LuceneIndexModule(versions, threads, slave, autoFlush);
   }
 
   public static LuceneIndexModule latestVersion(boolean slave, AutoFlush autoFlush) {
-    return new LuceneIndexModule(null, 0, slave, autoFlush);
+    return new LuceneIndexModule(/* singleVersions= */ null, 0, slave, autoFlush);
   }
 
   static boolean isInMemoryTest(Config cfg) {
@@ -59,7 +58,10 @@
   }
 
   private LuceneIndexModule(
-      Map<String, Integer> singleVersions, int threads, boolean slave, AutoFlush autoFlush) {
+      ImmutableMap<String, Integer> singleVersions,
+      int threads,
+      boolean slave,
+      AutoFlush autoFlush) {
     super(singleVersions, threads, slave);
     this.autoFlush = autoFlush;
   }
diff --git a/java/com/google/gerrit/lucene/package-info.java b/java/com/google/gerrit/lucene/package-info.java
new file mode 100644
index 0000000..fb5f8ec
--- /dev/null
+++ b/java/com/google/gerrit/lucene/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.lucene;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/mail/BUILD b/java/com/google/gerrit/mail/BUILD
index 0fe6c43..8830a66 100644
--- a/java/com/google/gerrit/mail/BUILD
+++ b/java/com/google/gerrit/mail/BUILD
@@ -10,6 +10,7 @@
         "//lib:guava",
         "//lib/auto:auto-value",
         "//lib/auto:auto-value-annotations",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/jsoup",
         "//lib/mime4j:core",
diff --git a/java/com/google/gerrit/mail/MailMessage.java b/java/com/google/gerrit/mail/MailMessage.java
index 2ce6cbb..b2385a7 100644
--- a/java/com/google/gerrit/mail/MailMessage.java
+++ b/java/com/google/gerrit/mail/MailMessage.java
@@ -16,6 +16,7 @@
 
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableList;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.Address;
 import java.time.Instant;
@@ -72,6 +73,7 @@
 
     public abstract ImmutableList.Builder<Address> toBuilder();
 
+    @CanIgnoreReturnValue
     public Builder addTo(Address val) {
       toBuilder().add(val);
       return this;
@@ -79,6 +81,7 @@
 
     public abstract ImmutableList.Builder<Address> ccBuilder();
 
+    @CanIgnoreReturnValue
     public Builder addCc(Address val) {
       ccBuilder().add(val);
       return this;
@@ -88,6 +91,7 @@
 
     public abstract ImmutableList.Builder<String> additionalHeadersBuilder();
 
+    @CanIgnoreReturnValue
     public Builder addAdditionalHeader(String val) {
       additionalHeadersBuilder().add(val);
       return this;
diff --git a/java/com/google/gerrit/mail/package-info.java b/java/com/google/gerrit/mail/package-info.java
new file mode 100644
index 0000000..5db0133
--- /dev/null
+++ b/java/com/google/gerrit/mail/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.mail;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/metrics/Description.java b/java/com/google/gerrit/metrics/Description.java
index f5963af..d4d3bb3 100644
--- a/java/com/google/gerrit/metrics/Description.java
+++ b/java/com/google/gerrit/metrics/Description.java
@@ -17,6 +17,7 @@
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
@@ -73,6 +74,7 @@
    * @param unitName name of the unit, e.g. "requests", "seconds", etc.
    * @return this
    */
+  @CanIgnoreReturnValue
   public Description setUnit(String unitName) {
     annotations.put(UNIT, unitName);
     return this;
@@ -84,6 +86,7 @@
    *
    * @return this
    */
+  @CanIgnoreReturnValue
   public Description setConstant() {
     annotations.put(CONSTANT, TRUE_VALUE);
     return this;
@@ -95,6 +98,7 @@
    *
    * @return this
    */
+  @CanIgnoreReturnValue
   public Description setRate() {
     annotations.put(RATE, TRUE_VALUE);
     return this;
@@ -106,6 +110,7 @@
    *
    * @return this
    */
+  @CanIgnoreReturnValue
   public Description setGauge() {
     annotations.put(GAUGE, TRUE_VALUE);
     return this;
@@ -117,6 +122,7 @@
    *
    * @return this
    */
+  @CanIgnoreReturnValue
   public Description setCumulative() {
     annotations.put(CUMULATIVE, TRUE_VALUE);
     return this;
@@ -128,6 +134,7 @@
    * @param ordering field ordering
    * @return this
    */
+  @CanIgnoreReturnValue
   public Description setFieldOrdering(FieldOrdering ordering) {
     annotations.put(FIELD_ORDERING, ordering.name());
     return this;
diff --git a/java/com/google/gerrit/metrics/MetricMaker.java b/java/com/google/gerrit/metrics/MetricMaker.java
index 3f9bab1..00f0792 100644
--- a/java/com/google/gerrit/metrics/MetricMaker.java
+++ b/java/com/google/gerrit/metrics/MetricMaker.java
@@ -140,15 +140,18 @@
    * @param trigger trigger to connect
    * @return registration handle
    */
+  @CanIgnoreReturnValue
   public RegistrationHandle newTrigger(CallbackMetric<?> metric1, Runnable trigger) {
     return newTrigger(ImmutableSet.of(metric1), trigger);
   }
 
+  @CanIgnoreReturnValue
   public RegistrationHandle newTrigger(
       CallbackMetric<?> metric1, CallbackMetric<?> metric2, Runnable trigger) {
     return newTrigger(ImmutableSet.of(metric1, metric2), trigger);
   }
 
+  @CanIgnoreReturnValue
   public RegistrationHandle newTrigger(
       CallbackMetric<?> metric1,
       CallbackMetric<?> metric2,
@@ -157,6 +160,7 @@
     return newTrigger(ImmutableSet.of(metric1, metric2, metric3), trigger);
   }
 
+  @CanIgnoreReturnValue
   public abstract RegistrationHandle newTrigger(Set<CallbackMetric<?>> metrics, Runnable trigger);
 
   /**
diff --git a/java/com/google/gerrit/metrics/TimerContext.java b/java/com/google/gerrit/metrics/TimerContext.java
index a3754c5..0e01de0 100644
--- a/java/com/google/gerrit/metrics/TimerContext.java
+++ b/java/com/google/gerrit/metrics/TimerContext.java
@@ -14,6 +14,8 @@
 
 package com.google.gerrit.metrics;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+
 abstract class TimerContext implements AutoCloseable {
   private final long startNanos;
   private boolean stopped;
@@ -40,6 +42,7 @@
    * @return the elapsed time in nanoseconds.
    * @throws IllegalStateException if the timer is already stopped.
    */
+  @CanIgnoreReturnValue
   public long stop() {
     if (!stopped) {
       stopped = true;
diff --git a/java/com/google/gerrit/metrics/dropwizard/BUILD b/java/com/google/gerrit/metrics/dropwizard/BUILD
index dbb8f5e..130eb8b 100644
--- a/java/com/google/gerrit/metrics/dropwizard/BUILD
+++ b/java/com/google/gerrit/metrics/dropwizard/BUILD
@@ -12,6 +12,7 @@
         "//lib:args4j",
         "//lib:guava",
         "//lib/dropwizard:dropwizard-core",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
     ],
diff --git a/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java b/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java
index da9ec70..fdfe129 100644
--- a/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java
+++ b/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java
@@ -19,6 +19,7 @@
 import com.codahale.metrics.MetricRegistry;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.metrics.Description;
 import com.google.gerrit.metrics.Field;
 import java.util.Iterator;
@@ -85,14 +86,17 @@
     }
   }
 
+  @CanIgnoreReturnValue
   ValueGauge getOrCreate(Object f1, Object f2) {
     return getOrCreate(ImmutableList.of(f1, f2));
   }
 
+  @CanIgnoreReturnValue
   ValueGauge getOrCreate(Object f1, Object f2, Object f3) {
     return getOrCreate(ImmutableList.of(f1, f2, f3));
   }
 
+  @CanIgnoreReturnValue
   ValueGauge getOrCreate(Object key) {
     ValueGauge c = cells.get(key);
     if (c != null) {
diff --git a/java/com/google/gerrit/metrics/dropwizard/package-info.java b/java/com/google/gerrit/metrics/dropwizard/package-info.java
new file mode 100644
index 0000000..e91c94d
--- /dev/null
+++ b/java/com/google/gerrit/metrics/dropwizard/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.metrics.dropwizard;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/metrics/package-info.java b/java/com/google/gerrit/metrics/package-info.java
new file mode 100644
index 0000000..7d691d9
--- /dev/null
+++ b/java/com/google/gerrit/metrics/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.metrics;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/metrics/proc/package-info.java b/java/com/google/gerrit/metrics/proc/package-info.java
new file mode 100644
index 0000000..0136afd
--- /dev/null
+++ b/java/com/google/gerrit/metrics/proc/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.metrics.proc;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/pgm/BUILD b/java/com/google/gerrit/pgm/BUILD
index 8523e8a..0967130 100644
--- a/java/com/google/gerrit/pgm/BUILD
+++ b/java/com/google/gerrit/pgm/BUILD
@@ -51,6 +51,7 @@
         "//lib/auto:auto-value",
         "//lib/auto:auto-value-annotations",
         "//lib/commons:lang3",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
         "//lib/guice:guice-assistedinject",
diff --git a/java/com/google/gerrit/pgm/Daemon.java b/java/com/google/gerrit/pgm/Daemon.java
index b3815b7..9a65a60 100644
--- a/java/com/google/gerrit/pgm/Daemon.java
+++ b/java/com/google/gerrit/pgm/Daemon.java
@@ -273,7 +273,8 @@
     }
     if (doInit) {
       try {
-        new Init(getSitePath()).run();
+        @SuppressWarnings("unused")
+        var unused = new Init(getSitePath()).run();
       } catch (Exception e) {
         throw die("Init failed", e);
       }
diff --git a/java/com/google/gerrit/pgm/Init.java b/java/com/google/gerrit/pgm/Init.java
index c05bff5..f6bfd69 100644
--- a/java/com/google/gerrit/pgm/Init.java
+++ b/java/com/google/gerrit/pgm/Init.java
@@ -302,7 +302,9 @@
         .message(String.format("Init complete, reindexing %s with:", String.join(",", indices)));
     getConsoleUI().message(" reindex " + reindexArgs.stream().collect(joining(" ")));
     Reindex reindexPgm = new Reindex();
-    reindexPgm.main(reindexArgs.stream().toArray(String[]::new));
+
+    @SuppressWarnings("unused")
+    var unused = reindexPgm.main(reindexArgs.stream().toArray(String[]::new));
   }
 
   private static boolean nullOrEmpty(List<?> list) {
diff --git a/java/com/google/gerrit/pgm/JythonShell.java b/java/com/google/gerrit/pgm/JythonShell.java
index d85bdc0..dcd89dc 100644
--- a/java/com/google/gerrit/pgm/JythonShell.java
+++ b/java/com/google/gerrit/pgm/JythonShell.java
@@ -70,12 +70,14 @@
     pyObject = findClass("org.python.core.PyObject");
     pySystemState = findClass("org.python.core.PySystemState");
 
-    runMethod(
-        pySystemState,
-        pySystemState,
-        "initialize",
-        new Class<?>[] {Properties.class, Properties.class},
-        new Object[] {null, env});
+    @SuppressWarnings("unused")
+    var unused =
+        runMethod(
+            pySystemState,
+            pySystemState,
+            "initialize",
+            new Class<?>[] {Properties.class, Properties.class},
+            new Object[] {null, env});
 
     try {
       shell = console.getConstructor(new Class<?>[] {}).newInstance();
@@ -125,10 +127,12 @@
   }
 
   protected void printInjectedVariable(String id) {
-    runInterpreter(
-        "exec",
-        new Class<?>[] {String.class},
-        new Object[] {"print '\"%s\" is \"%s\"' % (\"" + id + "\", " + id + ")"});
+    @SuppressWarnings("unused")
+    var unused =
+        runInterpreter(
+            "exec",
+            new Class<?>[] {String.class},
+            new Object[] {"print '\"%s\" is \"%s\"' % (\"" + id + "\", " + id + ")"});
   }
 
   public void run() {
@@ -136,19 +140,26 @@
       printInjectedVariable(key);
     }
     reload();
-    runInterpreter(
-        "interact",
-        new Class<?>[] {String.class, pyObject},
-        new Object[] {
-          getDefaultBanner()
-              + " running for Gerrit "
-              + com.google.gerrit.common.Version.getVersion(),
-          null,
-        });
+
+    @SuppressWarnings("unused")
+    var unused =
+        runInterpreter(
+            "interact",
+            new Class<?>[] {String.class, pyObject},
+            new Object[] {
+              getDefaultBanner()
+                  + " running for Gerrit "
+                  + com.google.gerrit.common.Version.getVersion(),
+              null,
+            });
   }
 
   public void set(String key, Object content) {
-    runInterpreter("set", new Class<?>[] {String.class, Object.class}, new Object[] {key, content});
+    @SuppressWarnings("unused")
+    var unused =
+        runInterpreter(
+            "set", new Class<?>[] {String.class, Object.class}, new Object[] {key, content});
+
     injectedVariables.add(key);
   }
 
@@ -181,12 +192,14 @@
     try {
       File script = new File(parent, p);
       if (script.canExecute()) {
-        runMethod0(
-            console,
-            shell,
-            "execfile",
-            new Class<?>[] {String.class},
-            new Object[] {script.getAbsolutePath()});
+        @SuppressWarnings("unused")
+        var unused =
+            runMethod0(
+                console,
+                shell,
+                "execfile",
+                new Class<?>[] {String.class},
+                new Object[] {script.getAbsolutePath()});
       } else {
         logger.atInfo().log(
             "User initialization file %s is not found or not executable", script.getAbsolutePath());
@@ -200,12 +213,14 @@
 
   protected void execStream(InputStream in, String p) {
     try {
-      runMethod0(
-          console,
-          shell,
-          "execfile",
-          new Class<?>[] {InputStream.class, String.class},
-          new Object[] {in, p});
+      @SuppressWarnings("unused")
+      var unused =
+          runMethod0(
+              console,
+              shell,
+              "execfile",
+              new Class<?>[] {InputStream.class, String.class},
+              new Object[] {in, p});
     } catch (InvocationTargetException e) {
       logger.atSevere().withCause(e).log("Exception occurred while loading %s", p);
     }
diff --git a/java/com/google/gerrit/pgm/Reindex.java b/java/com/google/gerrit/pgm/Reindex.java
index a2e780d..fe44934 100644
--- a/java/com/google/gerrit/pgm/Reindex.java
+++ b/java/com/google/gerrit/pgm/Reindex.java
@@ -18,6 +18,7 @@
 import static java.util.stream.Collectors.toSet;
 
 import com.google.common.cache.Cache;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Sets;
 import com.google.gerrit.common.Die;
 import com.google.gerrit.extensions.config.FactoryModule;
@@ -59,9 +60,7 @@
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.TimeUnit;
@@ -173,10 +172,10 @@
   }
 
   private Injector createSysInjector() {
-    Map<String, Integer> versions = new HashMap<>();
-    if (changesVersion != null) {
-      versions.put(ChangeSchemaDefinitions.INSTANCE.getName(), changesVersion);
-    }
+    ImmutableMap<String, Integer> versions =
+        changesVersion != null
+            ? ImmutableMap.of(ChangeSchemaDefinitions.INSTANCE.getName(), changesVersion)
+            : ImmutableMap.of();
     boolean replica = ReplicaUtil.isReplica(globalConfig);
     List<Module> modules = new ArrayList<>();
     modules.add(new WorkQueueModule());
@@ -194,7 +193,7 @@
         Class<?> clazz = Class.forName("com.google.gerrit.index.testing.FakeIndexModule");
         Method m =
             clazz.getMethod(
-                "singleVersionWithExplicitVersions", Map.class, int.class, boolean.class);
+                "singleVersionWithExplicitVersions", ImmutableMap.class, int.class, boolean.class);
         indexModule = (Module) m.invoke(null, versions, threads, replica);
       } catch (NoSuchMethodException
           | ClassNotFoundException
diff --git a/java/com/google/gerrit/pgm/http/jetty/BUILD b/java/com/google/gerrit/pgm/http/jetty/BUILD
index cd188f5..e006c91 100644
--- a/java/com/google/gerrit/pgm/http/jetty/BUILD
+++ b/java/com/google/gerrit/pgm/http/jetty/BUILD
@@ -18,6 +18,7 @@
         "//lib:guava",
         "//lib:jgit",
         "//lib:servlet-api",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
         "//lib/guice:guice-assistedinject",
diff --git a/java/com/google/gerrit/pgm/http/jetty/package-info.java b/java/com/google/gerrit/pgm/http/jetty/package-info.java
new file mode 100644
index 0000000..45a3b4f
--- /dev/null
+++ b/java/com/google/gerrit/pgm/http/jetty/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.pgm.http.jetty;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/pgm/init/BUILD b/java/com/google/gerrit/pgm/init/BUILD
index 0c0d937..73c3760 100644
--- a/java/com/google/gerrit/pgm/init/BUILD
+++ b/java/com/google/gerrit/pgm/init/BUILD
@@ -25,6 +25,7 @@
         "//lib:guava",
         "//lib:jgit",
         "//lib/commons:validator",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
         "//lib/guice:guice-assistedinject",
diff --git a/java/com/google/gerrit/pgm/init/VersionedAuthorizedKeysOnInit.java b/java/com/google/gerrit/pgm/init/VersionedAuthorizedKeysOnInit.java
index acde91f..34f6615 100644
--- a/java/com/google/gerrit/pgm/init/VersionedAuthorizedKeysOnInit.java
+++ b/java/com/google/gerrit/pgm/init/VersionedAuthorizedKeysOnInit.java
@@ -17,6 +17,7 @@
 import static com.google.common.base.Preconditions.checkState;
 
 import com.google.common.base.Strings;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.pgm.init.api.AllUsersNameOnInitProvider;
@@ -63,6 +64,7 @@
     keys = AuthorizedKeys.parse(accountId, readUTF8(AuthorizedKeys.FILE_NAME));
   }
 
+  @CanIgnoreReturnValue
   public AccountSshKey addKey(String pub) {
     checkState(keys != null, "SSH keys not loaded yet");
     int seq = keys.isEmpty() ? 1 : keys.size() + 1;
diff --git a/java/com/google/gerrit/pgm/init/api/AllProjectsConfig.java b/java/com/google/gerrit/pgm/init/api/AllProjectsConfig.java
index abd7d43..226f12b 100644
--- a/java/com/google/gerrit/pgm/init/api/AllProjectsConfig.java
+++ b/java/com/google/gerrit/pgm/init/api/AllProjectsConfig.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.pgm.init.api;
 
 import com.google.common.flogger.FluentLogger;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.server.config.AllProjectsConfigProvider;
@@ -58,6 +59,7 @@
   }
 
   @Override
+  @CanIgnoreReturnValue
   public AllProjectsConfig load() throws IOException, ConfigInvalidException {
     super.load();
     return this;
diff --git a/java/com/google/gerrit/pgm/init/api/GitRepositoryManagerOnInit.java b/java/com/google/gerrit/pgm/init/api/GitRepositoryManagerOnInit.java
index fabad49..dd29783 100644
--- a/java/com/google/gerrit/pgm/init/api/GitRepositoryManagerOnInit.java
+++ b/java/com/google/gerrit/pgm/init/api/GitRepositoryManagerOnInit.java
@@ -44,7 +44,8 @@
   @Override
   public Status getRepositoryStatus(NameKey name) {
     try {
-      openRepository(name);
+      @SuppressWarnings("unused")
+      var unused = openRepository(name);
     } catch (RepositoryNotFoundException e) {
       return Status.NON_EXISTENT;
     } catch (IOException e) {
diff --git a/java/com/google/gerrit/pgm/init/api/Section.java b/java/com/google/gerrit/pgm/init/api/Section.java
index 5cc4b5d..720c1f8 100644
--- a/java/com/google/gerrit/pgm/init/api/Section.java
+++ b/java/com/google/gerrit/pgm/init/api/Section.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.pgm.init.api;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.securestore.SecureStore;
@@ -100,10 +101,12 @@
     set(name, (String) null);
   }
 
+  @CanIgnoreReturnValue
   public String string(String title, String name, String dv) {
     return string(title, name, dv, false);
   }
 
+  @CanIgnoreReturnValue
   public String string(final String title, String name, String dv, boolean nullIfDefault) {
     final String ov = get(name);
     String nv = ui.readString(ov != null ? ov : dv, "%s", title);
@@ -120,11 +123,13 @@
     return site.resolve(string(title, name, defValue));
   }
 
+  @CanIgnoreReturnValue
   public <T extends Enum<?>, E extends EnumSet<? extends T>> T select(
       String title, String name, T defValue) {
     return select(title, name, defValue, false);
   }
 
+  @CanIgnoreReturnValue
   public <T extends Enum<?>, E extends EnumSet<? extends T>> T select(
       String title, String name, T defValue, boolean nullIfDefault) {
     @SuppressWarnings("rawtypes")
@@ -134,11 +139,13 @@
     return select(title, name, defValue, allowedValues, nullIfDefault);
   }
 
+  @CanIgnoreReturnValue
   public <T extends Enum<?>, E extends EnumSet<? extends T>> T select(
       String title, String name, T defValue, E allowedValues) {
     return select(title, name, defValue, allowedValues, false);
   }
 
+  @CanIgnoreReturnValue
   public <T extends Enum<?>, A extends EnumSet<? extends T>> T select(
       String title, String name, T defValue, A allowedValues, boolean nullIfDefault) {
     final boolean set = get(name) != null;
@@ -167,6 +174,7 @@
   }
 
   @Nullable
+  @CanIgnoreReturnValue
   public String password(String username, String password) {
     final String ov = getSecure(password);
 
@@ -196,6 +204,7 @@
     return nv;
   }
 
+  @CanIgnoreReturnValue
   public String passwordForKey(String prompt, String passwordKey) {
     String ov = getSecure(passwordKey);
     if (ov != null) {
diff --git a/java/com/google/gerrit/pgm/init/api/VersionedMetaDataOnInit.java b/java/com/google/gerrit/pgm/init/api/VersionedMetaDataOnInit.java
index e05b1ba..0a82c98 100644
--- a/java/com/google/gerrit/pgm/init/api/VersionedMetaDataOnInit.java
+++ b/java/com/google/gerrit/pgm/init/api/VersionedMetaDataOnInit.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.pgm.init.api;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.server.GerritPersonIdentProvider;
 import com.google.gerrit.server.config.SitePaths;
@@ -54,6 +55,7 @@
     return ref;
   }
 
+  @CanIgnoreReturnValue
   public VersionedMetaDataOnInit load() throws IOException, ConfigInvalidException {
     File path = getPath();
     if (path != null) {
diff --git a/java/com/google/gerrit/pgm/init/api/package-info.java b/java/com/google/gerrit/pgm/init/api/package-info.java
new file mode 100644
index 0000000..ef26020
--- /dev/null
+++ b/java/com/google/gerrit/pgm/init/api/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.pgm.init.api;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/pgm/init/index/lucene/package-info.java b/java/com/google/gerrit/pgm/init/index/lucene/package-info.java
new file mode 100644
index 0000000..e72368b
--- /dev/null
+++ b/java/com/google/gerrit/pgm/init/index/lucene/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.pgm.init.index.lucene;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/pgm/init/index/package-info.java b/java/com/google/gerrit/pgm/init/index/package-info.java
new file mode 100644
index 0000000..cb32880
--- /dev/null
+++ b/java/com/google/gerrit/pgm/init/index/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.pgm.init.index;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/pgm/init/package-info.java b/java/com/google/gerrit/pgm/init/package-info.java
new file mode 100644
index 0000000..f4f4945
--- /dev/null
+++ b/java/com/google/gerrit/pgm/init/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.pgm.init;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/pgm/package-info.java b/java/com/google/gerrit/pgm/package-info.java
new file mode 100644
index 0000000..3e7920f
--- /dev/null
+++ b/java/com/google/gerrit/pgm/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.pgm;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/pgm/rules/package-info.java b/java/com/google/gerrit/pgm/rules/package-info.java
new file mode 100644
index 0000000..5ac4176
--- /dev/null
+++ b/java/com/google/gerrit/pgm/rules/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.pgm.rules;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/pgm/util/BUILD b/java/com/google/gerrit/pgm/util/BUILD
index 5b01c9c..ad4ce88 100644
--- a/java/com/google/gerrit/pgm/util/BUILD
+++ b/java/com/google/gerrit/pgm/util/BUILD
@@ -23,6 +23,7 @@
         "//lib:gson",
         "//lib:guava",
         "//lib:jgit",
+        "//lib/errorprone:annotations",
         "//lib/flogger:api",
         "//lib/guice",
         "//lib/log:log4j",
diff --git a/java/com/google/gerrit/pgm/util/BatchProgramModule.java b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
index 21ae8e1..409a001 100644
--- a/java/com/google/gerrit/pgm/util/BatchProgramModule.java
+++ b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
@@ -74,7 +74,9 @@
 import com.google.gerrit.server.git.PureRevertCache;
 import com.google.gerrit.server.git.TagCache;
 import com.google.gerrit.server.notedb.ChangeDraftNotesUpdate;
+import com.google.gerrit.server.notedb.NoteDbDraftCommentsModule;
 import com.google.gerrit.server.notedb.NoteDbModule;
+import com.google.gerrit.server.notedb.NoteDbStarredChangesModule;
 import com.google.gerrit.server.patch.DiffExecutorModule;
 import com.google.gerrit.server.patch.DiffOperationsImpl;
 import com.google.gerrit.server.patch.PatchListCacheImpl;
@@ -114,7 +116,7 @@
 
 /** Module for programs that perform batch operations on a site. */
 public class BatchProgramModule extends FactoryModule {
-  private Injector parentInjector;
+  private final Injector parentInjector;
 
   public BatchProgramModule(Injector parentInjector) {
     this.parentInjector = parentInjector;
@@ -183,7 +185,9 @@
     modules.add(new H2CacheModule());
     modules.add(new ExternalIdCacheModule());
     modules.add(new GroupModule());
+    modules.add(new NoteDbDraftCommentsModule());
     modules.add(new NoteDbModule());
+    modules.add(new NoteDbStarredChangesModule());
     modules.add(AccountCacheImpl.module());
     modules.add(ConflictsCacheImpl.module());
     modules.add(DefaultPreferencesCacheImpl.module());
diff --git a/java/com/google/gerrit/pgm/util/package-info.java b/java/com/google/gerrit/pgm/util/package-info.java
new file mode 100644
index 0000000..3bd1fd9
--- /dev/null
+++ b/java/com/google/gerrit/pgm/util/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.pgm.util;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/prettify/BUILD b/java/com/google/gerrit/prettify/BUILD
index a5c8b77..5b07849 100644
--- a/java/com/google/gerrit/prettify/BUILD
+++ b/java/com/google/gerrit/prettify/BUILD
@@ -10,5 +10,6 @@
         "//lib:jgit",
         "//lib/auto:auto-value",
         "//lib/auto:auto-value-annotations",
+        "//lib/errorprone:annotations",
     ],
 )
diff --git a/java/com/google/gerrit/prettify/common/package-info.java b/java/com/google/gerrit/prettify/common/package-info.java
new file mode 100644
index 0000000..5f70f74
--- /dev/null
+++ b/java/com/google/gerrit/prettify/common/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.prettify.common;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/prettify/common/testing/BUILD b/java/com/google/gerrit/prettify/common/testing/BUILD
index 5057fdb..ecc28ff 100644
--- a/java/com/google/gerrit/prettify/common/testing/BUILD
+++ b/java/com/google/gerrit/prettify/common/testing/BUILD
@@ -9,6 +9,7 @@
     deps = [
         "//java/com/google/gerrit/prettify:server",
         "//lib:guava",
+        "//lib/errorprone:annotations",
         "//lib/truth",
     ],
 )
diff --git a/java/com/google/gerrit/prettify/common/testing/package-info.java b/java/com/google/gerrit/prettify/common/testing/package-info.java
new file mode 100644
index 0000000..430ba69
--- /dev/null
+++ b/java/com/google/gerrit/prettify/common/testing/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.prettify.common.testing;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/proto/BUILD b/java/com/google/gerrit/proto/BUILD
index 98558c5..82af646 100644
--- a/java/com/google/gerrit/proto/BUILD
+++ b/java/com/google/gerrit/proto/BUILD
@@ -6,5 +6,6 @@
     visibility = ["//visibility:public"],
     deps = [
         "//lib:protobuf",
+        "//lib/errorprone:annotations",
     ],
 )
diff --git a/java/com/google/gerrit/proto/package-info.java b/java/com/google/gerrit/proto/package-info.java
new file mode 100644
index 0000000..8c4522f
--- /dev/null
+++ b/java/com/google/gerrit/proto/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.proto;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/proto/testing/BUILD b/java/com/google/gerrit/proto/testing/BUILD
index 069bb46..17a2eaf 100644
--- a/java/com/google/gerrit/proto/testing/BUILD
+++ b/java/com/google/gerrit/proto/testing/BUILD
@@ -9,6 +9,7 @@
     deps = [
         "//lib:guava",
         "//lib/commons:lang3",
+        "//lib/errorprone:annotations",
         "//lib/guice",
         "//lib/truth",
     ],
diff --git a/java/com/google/gerrit/proto/testing/package-info.java b/java/com/google/gerrit/proto/testing/package-info.java
new file mode 100644
index 0000000..6f19454
--- /dev/null
+++ b/java/com/google/gerrit/proto/testing/package-info.java
@@ -0,0 +1,18 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// 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.
+
+@CheckReturnValue
+package com.google.gerrit.proto.testing;
+
+import com.google.errorprone.annotations.CheckReturnValue;
diff --git a/java/com/google/gerrit/server/CommentsUtil.java b/java/com/google/gerrit/server/CommentsUtil.java
index a204920..2633a03 100644
--- a/java/com/google/gerrit/server/CommentsUtil.java
+++ b/java/com/google/gerrit/server/CommentsUtil.java
@@ -18,7 +18,6 @@
 import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Comparator.comparing;
 import static java.util.stream.Collectors.toCollection;
-import static java.util.stream.Collectors.toList;
 
 import com.google.common.collect.ComparisonChain;
 import com.google.common.collect.Lists;
@@ -28,7 +27,6 @@
 import com.google.gerrit.entities.ChangeMessage;
 import com.google.gerrit.entities.Comment;
 import com.google.gerrit.entities.HumanComment;
-import com.google.gerrit.entities.Patch;
 import com.google.gerrit.entities.PatchSet;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.entities.RobotComment;
@@ -209,13 +207,8 @@
     return robotCommentsByChange(notes).stream().filter(c -> c.key.uuid.equals(uuid)).findFirst();
   }
 
-  public List<HumanComment> publishedByChangeFile(ChangeNotes notes, String file) {
-    return commentsOnFile(notes.load().getHumanComments().values(), file);
-  }
-
   public List<HumanComment> publishedByPatchSet(ChangeNotes notes, PatchSet.Id psId) {
-    return removeCommentsOnAncestorOfCommitMessage(
-        commentsOnPatchSet(notes.load().getHumanComments().values(), psId));
+    return commentsOnPatchSet(notes.load().getHumanComments().values(), psId);
   }
 
   public List<RobotComment> robotCommentsByPatchSet(ChangeNotes notes, PatchSet.Id psId) {
@@ -296,18 +289,6 @@
         Optional.ofNullable(cm.getAuthor()).map(a -> a.get()),
         Optional.ofNullable(comment.author).map(a -> a._accountId));
   }
-  /**
-   * For the commit message the A side in a diff view is always empty when a comparison against an
-   * ancestor is done, so there can't be any comments on this ancestor. However earlier we showed
-   * the auto-merge commit message on side A when for a merge commit a comparison against the
-   * auto-merge was done. From that time there may still be comments on the auto-merge commit
-   * message and those we want to filter out.
-   */
-  private List<HumanComment> removeCommentsOnAncestorOfCommitMessage(List<HumanComment> list) {
-    return list.stream()
-        .filter(c -> c.side != 0 || !Patch.COMMIT_MSG.equals(c.key.filename))
-        .collect(toList());
-  }
 
   public void putHumanComments(
       ChangeUpdate update, Comment.Status status, Iterable<HumanComment> comments) {
@@ -333,18 +314,6 @@
     update.deleteCommentByRewritingHistory(commentKey.uuid, newMessage);
   }
 
-  private static List<HumanComment> commentsOnFile(
-      Collection<HumanComment> allComments, String file) {
-    List<HumanComment> result = new ArrayList<>(allComments.size());
-    for (HumanComment c : allComments) {
-      String currentFilename = c.key.filename;
-      if (currentFilename.equals(file)) {
-        result.add(c);
-      }
-    }
-    return sort(result);
-  }
-
   private static <T extends Comment> List<T> commentsOnPatchSet(
       Collection<T> allComments, PatchSet.Id psId) {
     List<T> result = new ArrayList<>(allComments.size());
diff --git a/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java b/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
index fc6087b..914bdd2 100644
--- a/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
+++ b/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
@@ -38,10 +38,9 @@
 import com.google.gerrit.server.logging.Metadata;
 import com.google.gerrit.server.logging.TraceContext;
 import com.google.gerrit.server.logging.TraceContext.TraceTimer;
-import com.google.gerrit.server.query.group.InternalGroupQuery;
+import com.google.gerrit.server.update.RetryHelper;
 import com.google.inject.Inject;
 import com.google.inject.Module;
-import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import com.google.inject.TypeLiteral;
 import com.google.inject.name.Named;
@@ -191,11 +190,11 @@
 
   static class GroupsWithMemberLoader
       extends CacheLoader<Account.Id, ImmutableSet<AccountGroup.UUID>> {
-    private final Provider<InternalGroupQuery> groupQueryProvider;
+    private final RetryHelper retryHelper;
 
     @Inject
-    GroupsWithMemberLoader(Provider<InternalGroupQuery> groupQueryProvider) {
-      this.groupQueryProvider = groupQueryProvider;
+    GroupsWithMemberLoader(RetryHelper retryHelper) {
+      this.retryHelper = retryHelper;
     }
 
     @Override
@@ -203,9 +202,14 @@
       try (TraceTimer timer =
           TraceContext.newTimer(
               "Loading groups with member", Metadata.builder().accountId(memberId.get()).build())) {
-        return groupQueryProvider.get().byMember(memberId).stream()
-            .map(InternalGroup::getGroupUUID)
-            .collect(toImmutableSet());
+        return retryHelper
+            .groupIndexQuery(
+                "loadGroupWithMember",
+                q ->
+                    q.byMember(memberId).stream()
+                        .map(InternalGroup::getGroupUUID)
+                        .collect(toImmutableSet()))
+            .call();
       }
     }
   }
@@ -215,11 +219,11 @@
     // Be conservative with batching: We don't want to exhaust the number of
     // results per page and maximum terms per query. Both are usually 1000+.
     private static final int MAX_BATCH_SIZE = 100;
-    private final Provider<InternalGroupQuery> groupQueryProvider;
+    private final RetryHelper retryHelper;
 
     @Inject
-    ParentGroupsLoader(Provider<InternalGroupQuery> groupQueryProvider) {
-      this.groupQueryProvider = groupQueryProvider;
+    ParentGroupsLoader(RetryHelper retryHelper) {
+      this.retryHelper = retryHelper;
     }
 
     @Override
@@ -238,10 +242,12 @@
       Map<AccountGroup.UUID, ImmutableSet<AccountGroup.UUID>> result =
           Maps.newHashMapWithExpectedSize(numKeys);
       try (TraceTimer timer = TraceContext.newTimer("Loading " + numKeys + " parent groups")) {
+        Map<AccountGroup.UUID, ImmutableSet<AccountGroup.UUID>> bySubgroups =
+            retryHelper
+                .groupIndexQuery("loadParentGroups", q -> q.bySubgroups(ImmutableSet.copyOf(keys)))
+                .call();
         Iterables.partition(keys, MAX_BATCH_SIZE)
-            .forEach(
-                keyPartition ->
-                    result.putAll(groupQueryProvider.get().bySubgroups(ImmutableSet.copyOf(keys))));
+            .forEach(keyPartition -> result.putAll(bySubgroups));
         return result;
       }
     }
diff --git a/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java b/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java
index c1d2901..38510e3 100644
--- a/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java
+++ b/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java
@@ -339,7 +339,9 @@
       } else {
         view = deleteReviewed;
       }
-      view.apply(files.parse(revision, IdString.fromDecoded(path)), new Input());
+
+      @SuppressWarnings("unused")
+      var unused = view.apply(files.parse(revision, IdString.fromDecoded(path)), new Input());
     } catch (Exception e) {
       throw asRestApiException("Cannot update reviewed flag", e);
     }
diff --git a/java/com/google/gerrit/server/change/RevisionResource.java b/java/com/google/gerrit/server/change/RevisionResource.java
index e5a57b2..4a10158 100644
--- a/java/com/google/gerrit/server/change/RevisionResource.java
+++ b/java/com/google/gerrit/server/change/RevisionResource.java
@@ -41,22 +41,22 @@
     return new RevisionResource(change, ps, Optional.empty(), false);
   }
 
-  private final ChangeResource change;
+  private final ChangeResource changeResource;
   private final PatchSet ps;
   private final Optional<ChangeEdit> edit;
   private final boolean cacheable;
 
-  public RevisionResource(ChangeResource change, PatchSet ps) {
-    this(change, ps, Optional.empty());
+  public RevisionResource(ChangeResource changeResource, PatchSet ps) {
+    this(changeResource, ps, Optional.empty());
   }
 
-  public RevisionResource(ChangeResource change, PatchSet ps, Optional<ChangeEdit> edit) {
-    this(change, ps, edit, true);
+  public RevisionResource(ChangeResource changeResource, PatchSet ps, Optional<ChangeEdit> edit) {
+    this(changeResource, ps, edit, true);
   }
 
   private RevisionResource(
-      ChangeResource change, PatchSet ps, Optional<ChangeEdit> edit, boolean cacheable) {
-    this.change = change;
+      ChangeResource changeResource, PatchSet ps, Optional<ChangeEdit> edit, boolean cacheable) {
+    this.changeResource = changeResource;
     this.ps = ps;
     this.edit = edit;
     this.cacheable = cacheable;
@@ -67,15 +67,15 @@
   }
 
   public PermissionBackend.ForChange permissions() {
-    return change.permissions();
+    return changeResource.permissions();
   }
 
   public ChangeResource getChangeResource() {
-    return change;
+    return changeResource;
   }
 
   public Change getChange() {
-    return getChangeResource().getChange();
+    return changeResource.getChange();
   }
 
   public Project.NameKey getProject() {
@@ -83,7 +83,7 @@
   }
 
   public ChangeNotes getNotes() {
-    return getChangeResource().getNotes();
+    return changeResource.getNotes();
   }
 
   public PatchSet getPatchSet() {
@@ -96,9 +96,9 @@
         TraceContext.newTimer(
             "Compute revision ETag",
             Metadata.builder()
-                .changeId(change.getId().get())
+                .changeId(changeResource.getId().get())
                 .patchSetId(ps.number())
-                .projectName(change.getProject().get())
+                .projectName(changeResource.getProject().get())
                 .build())) {
       Hasher h = Hashing.murmur3_128().newHasher();
       prepareETag(h, getUser());
@@ -109,7 +109,7 @@
   public void prepareETag(Hasher h, CurrentUser user) {
     // Conservative estimate: refresh the revision if its parent change has changed, so we don't
     // have to check whether a given modification affected this revision specifically.
-    change.prepareETag(h, user);
+    changeResource.prepareETag(h, user);
   }
 
   public Account.Id getAccountId() {
@@ -117,7 +117,7 @@
   }
 
   public CurrentUser getUser() {
-    return getChangeResource().getUser();
+    return changeResource.getUser();
   }
 
   public Optional<ChangeEdit> getEdit() {
diff --git a/java/com/google/gerrit/server/config/GerritGlobalModule.java b/java/com/google/gerrit/server/config/GerritGlobalModule.java
index fe82a88..acc481a 100644
--- a/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -173,7 +173,9 @@
 import com.google.gerrit.server.mime.MimeUtilFileTypeRegistry;
 import com.google.gerrit.server.notedb.ChangeDraftNotesUpdate;
 import com.google.gerrit.server.notedb.DeleteZombieCommentsRefs;
+import com.google.gerrit.server.notedb.NoteDbDraftCommentsModule;
 import com.google.gerrit.server.notedb.NoteDbModule;
+import com.google.gerrit.server.notedb.NoteDbStarredChangesModule;
 import com.google.gerrit.server.notedb.StoreSubmitRequirementsOp;
 import com.google.gerrit.server.patch.DiffFileSizeValidator;
 import com.google.gerrit.server.patch.DiffOperationsImpl;
@@ -282,7 +284,9 @@
     install(new GitModule());
     install(new GroupDbModule());
     install(new GroupModule());
+    install(new NoteDbDraftCommentsModule());
     install(new NoteDbModule());
+    install(new NoteDbStarredChangesModule());
     install(new PrologModule(cfg));
     install(new DefaultSubmitRuleModule());
     install(new IgnoreSelfApprovalRuleModule());
diff --git a/java/com/google/gerrit/server/events/StreamEventsApiListener.java b/java/com/google/gerrit/server/events/StreamEventsApiListener.java
index 53682d5..89aebde 100644
--- a/java/com/google/gerrit/server/events/StreamEventsApiListener.java
+++ b/java/com/google/gerrit/server/events/StreamEventsApiListener.java
@@ -104,8 +104,7 @@
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
   public static class StreamEventsApiListenerModule extends AbstractModule {
-
-    private Config config;
+    private final Config config;
 
     public StreamEventsApiListenerModule(Config config) {
       this.config = config;
diff --git a/java/com/google/gerrit/server/git/ChangesByProjectCache.java b/java/com/google/gerrit/server/git/ChangesByProjectCache.java
index df91891..1e71497 100644
--- a/java/com/google/gerrit/server/git/ChangesByProjectCache.java
+++ b/java/com/google/gerrit/server/git/ChangesByProjectCache.java
@@ -30,8 +30,8 @@
   }
 
   public static class Module extends AbstractModule {
-    private UseIndex useIndex;
-    private @GerritServerConfig Config config;
+    private final UseIndex useIndex;
+    private final Config config;
 
     public Module(UseIndex useIndex, @GerritServerConfig Config config) {
       this.useIndex = useIndex;
diff --git a/java/com/google/gerrit/server/git/WorkQueue.java b/java/com/google/gerrit/server/git/WorkQueue.java
index 02b898c..444b5fe 100644
--- a/java/com/google/gerrit/server/git/WorkQueue.java
+++ b/java/com/google/gerrit/server/git/WorkQueue.java
@@ -675,7 +675,7 @@
         try {
           executor.onStart(this);
           runningState.set(State.RUNNING);
-          Thread.currentThread().setName(oldThreadName + "[" + task.toString() + "]");
+          Thread.currentThread().setName(oldThreadName + "[" + this + "]");
           task.run();
         } finally {
           Thread.currentThread().setName(oldThreadName);
diff --git a/java/com/google/gerrit/server/index/AbstractIndexModule.java b/java/com/google/gerrit/server/index/AbstractIndexModule.java
index 9e9da91..e24a2b1 100644
--- a/java/com/google/gerrit/server/index/AbstractIndexModule.java
+++ b/java/com/google/gerrit/server/index/AbstractIndexModule.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.server.index;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.index.IndexConfig;
 import com.google.gerrit.index.project.ProjectIndex;
 import com.google.gerrit.lifecycle.LifecycleModule;
@@ -25,7 +26,6 @@
 import com.google.inject.Provides;
 import com.google.inject.Singleton;
 import com.google.inject.assistedinject.FactoryModuleBuilder;
-import java.util.Map;
 import org.eclipse.jgit.lib.Config;
 
 /**
@@ -37,10 +37,11 @@
   public static final String INDEX_MODULE = "index-module";
 
   private final int threads;
-  private final Map<String, Integer> singleVersions;
+  private final ImmutableMap<String, Integer> singleVersions;
   private final boolean slave;
 
-  protected AbstractIndexModule(Map<String, Integer> singleVersions, int threads, boolean slave) {
+  protected AbstractIndexModule(
+      ImmutableMap<String, Integer> singleVersions, int threads, boolean slave) {
     this.singleVersions = singleVersions;
     this.threads = threads;
     this.slave = slave;
diff --git a/java/com/google/gerrit/server/index/SingleVersionModule.java b/java/com/google/gerrit/server/index/SingleVersionModule.java
index 50dc4e9..4b65e6e 100644
--- a/java/com/google/gerrit/server/index/SingleVersionModule.java
+++ b/java/com/google/gerrit/server/index/SingleVersionModule.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.server.index;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.extensions.events.LifecycleListener;
 import com.google.gerrit.index.Index;
@@ -41,9 +42,9 @@
 public class SingleVersionModule extends LifecycleModule {
   public static final String SINGLE_VERSIONS = "IndexModule/SingleVersions";
 
-  private final Map<String, Integer> singleVersions;
+  private final ImmutableMap<String, Integer> singleVersions;
 
-  public SingleVersionModule(Map<String, Integer> singleVersions) {
+  public SingleVersionModule(ImmutableMap<String, Integer> singleVersions) {
     this.singleVersions = singleVersions;
   }
 
diff --git a/java/com/google/gerrit/server/notedb/NoteDbDraftCommentsModule.java b/java/com/google/gerrit/server/notedb/NoteDbDraftCommentsModule.java
new file mode 100644
index 0000000..a15eaf04
--- /dev/null
+++ b/java/com/google/gerrit/server/notedb/NoteDbDraftCommentsModule.java
@@ -0,0 +1,34 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// 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.gerrit.server.notedb;
+
+import com.google.gerrit.extensions.config.FactoryModule;
+import com.google.gerrit.server.ChangeDraftUpdateExecutor;
+import com.google.gerrit.server.DraftCommentsReader;
+import com.google.inject.Singleton;
+
+public class NoteDbDraftCommentsModule extends FactoryModule {
+  @Override
+  public void configure() {
+    factory(ChangeDraftNotesUpdate.Factory.class);
+    factory(ChangeDraftNotesUpdate.Executor.Factory.class);
+    factory(DraftCommentNotes.Factory.class);
+
+    bind(DraftCommentsReader.class).to(DraftCommentsNotesReader.class).in(Singleton.class);
+    bind(ChangeDraftUpdateExecutor.AbstractFactory.class)
+        .to(ChangeDraftNotesUpdate.Executor.Factory.class)
+        .in(Singleton.class);
+  }
+}
diff --git a/java/com/google/gerrit/server/notedb/NoteDbModule.java b/java/com/google/gerrit/server/notedb/NoteDbModule.java
index 8a73f7b..cf3fad6 100644
--- a/java/com/google/gerrit/server/notedb/NoteDbModule.java
+++ b/java/com/google/gerrit/server/notedb/NoteDbModule.java
@@ -17,11 +17,6 @@
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
 import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.server.ChangeDraftUpdateExecutor;
-import com.google.gerrit.server.DraftCommentsReader;
-import com.google.gerrit.server.StarredChangesReader;
-import com.google.gerrit.server.StarredChangesWriter;
-import com.google.inject.Singleton;
 import com.google.inject.TypeLiteral;
 import com.google.inject.name.Names;
 
@@ -42,20 +37,11 @@
 
   @Override
   public void configure() {
-    factory(ChangeDraftNotesUpdate.Factory.class);
-    factory(ChangeDraftNotesUpdate.Executor.Factory.class);
     factory(ChangeUpdate.Factory.class);
     factory(DeleteCommentRewriter.Factory.class);
-    factory(DraftCommentNotes.Factory.class);
     factory(NoteDbUpdateManager.Factory.class);
     factory(RobotCommentNotes.Factory.class);
     factory(RobotCommentUpdate.Factory.class);
-    bind(StarredChangesReader.class).to(StarredChangesUtilNoteDbImpl.class).in(Singleton.class);
-    bind(StarredChangesWriter.class).to(StarredChangesUtilNoteDbImpl.class).in(Singleton.class);
-    bind(DraftCommentsReader.class).to(DraftCommentsNotesReader.class).in(Singleton.class);
-    bind(ChangeDraftUpdateExecutor.AbstractFactory.class)
-        .to(ChangeDraftNotesUpdate.Executor.Factory.class)
-        .in(Singleton.class);
 
     if (!useTestBindings) {
       install(ChangeNotesCache.module());
diff --git a/java/com/google/gerrit/server/notedb/NoteDbStarredChangesModule.java b/java/com/google/gerrit/server/notedb/NoteDbStarredChangesModule.java
new file mode 100644
index 0000000..733c3cf
--- /dev/null
+++ b/java/com/google/gerrit/server/notedb/NoteDbStarredChangesModule.java
@@ -0,0 +1,28 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// 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.gerrit.server.notedb;
+
+import com.google.gerrit.extensions.config.FactoryModule;
+import com.google.gerrit.server.StarredChangesReader;
+import com.google.gerrit.server.StarredChangesWriter;
+import com.google.inject.Singleton;
+
+public class NoteDbStarredChangesModule extends FactoryModule {
+  @Override
+  public void configure() {
+    bind(StarredChangesReader.class).to(StarredChangesUtilNoteDbImpl.class).in(Singleton.class);
+    bind(StarredChangesWriter.class).to(StarredChangesUtilNoteDbImpl.class).in(Singleton.class);
+  }
+}
diff --git a/java/com/google/gerrit/server/patch/DiffOperations.java b/java/com/google/gerrit/server/patch/DiffOperations.java
index a53660a..658cfc5 100644
--- a/java/com/google/gerrit/server/patch/DiffOperations.java
+++ b/java/com/google/gerrit/server/patch/DiffOperations.java
@@ -81,7 +81,6 @@
       Project.NameKey project,
       ObjectId newCommit,
       int parentNum,
-      DiffOptions diffOptions,
       RevWalk revWalk,
       Config repoConfig)
       throws DiffNotAvailableException;
@@ -121,7 +120,6 @@
       Project.NameKey project,
       ObjectId oldCommit,
       ObjectId newCommit,
-      DiffOptions diffOptions,
       RevWalk revWalk,
       Config repoConfig)
       throws DiffNotAvailableException;
diff --git a/java/com/google/gerrit/server/patch/DiffOperationsImpl.java b/java/com/google/gerrit/server/patch/DiffOperationsImpl.java
index 4d0bcc8..be33a90 100644
--- a/java/com/google/gerrit/server/patch/DiffOperationsImpl.java
+++ b/java/com/google/gerrit/server/patch/DiffOperationsImpl.java
@@ -130,7 +130,6 @@
       Project.NameKey project,
       ObjectId newCommit,
       int parentNum,
-      DiffOptions diffOptions,
       RevWalk revWalk,
       Config repoConfig)
       throws DiffNotAvailableException {
@@ -165,7 +164,6 @@
       Project.NameKey project,
       ObjectId oldCommit,
       ObjectId newCommit,
-      DiffOptions diffOptions,
       RevWalk revWalk,
       Config repoConfig)
       throws DiffNotAvailableException {
diff --git a/java/com/google/gerrit/server/patch/gitdiff/GitModifiedFilesCacheImpl.java b/java/com/google/gerrit/server/patch/gitdiff/GitModifiedFilesCacheImpl.java
index b70f6e1..7cc2dc3 100644
--- a/java/com/google/gerrit/server/patch/gitdiff/GitModifiedFilesCacheImpl.java
+++ b/java/com/google/gerrit/server/patch/gitdiff/GitModifiedFilesCacheImpl.java
@@ -130,9 +130,10 @@
         if (key.renameDetection()) {
           df.setDetectRenames(true);
           df.getRenameDetector().setRenameScore(key.renameScore());
+
+          // Skip detecting content renames for binary files.
+          df.getRenameDetector().setSkipContentRenamesForBinaryFiles(true);
         }
-        // Skip detecting content renames for binary files.
-        df.getRenameDetector().setSkipContentRenamesForBinaryFiles(true);
         // The scan method only returns the file paths that are different. Callers may choose to
         // format these paths themselves.
         return df.scan(key.aTree().equals(ObjectId.zeroId()) ? null : key.aTree(), key.bTree());
diff --git a/java/com/google/gerrit/server/plugins/CopyConfigModule.java b/java/com/google/gerrit/server/plugins/CopyConfigModule.java
index c495721..2764675 100644
--- a/java/com/google/gerrit/server/plugins/CopyConfigModule.java
+++ b/java/com/google/gerrit/server/plugins/CopyConfigModule.java
@@ -44,7 +44,37 @@
 @SuppressWarnings("ProvidesMethodOutsideOfModule")
 @Singleton
 class CopyConfigModule extends AbstractModule {
-  @Inject @SitePath private Path sitePath;
+  private final Path sitePath;
+  private final SitePaths sitePaths;
+  private final TrackingFooters trackingFooters;
+  private final Config gerritServerConfig;
+  private final GitRepositoryManager gitRepositoryManager;
+  private final String anonymousCowardName;
+  private final GerritPersonIdentProvider serverIdentProvider;
+  private final SecureStore secureStore;
+  private final GerritIsReplicaProvider isReplicaProvider;
+
+  @Inject
+  CopyConfigModule(
+      @SitePath Path sitePath,
+      SitePaths sitePaths,
+      TrackingFooters trackingFooters,
+      @GerritServerConfig Config gerritServerConfig,
+      GitRepositoryManager gitRepositoryManager,
+      @AnonymousCowardName String anonymousCowardName,
+      GerritPersonIdentProvider serverIdentProvider,
+      SecureStore secureStore,
+      GerritIsReplicaProvider isReplicaProvider) {
+    this.sitePath = sitePath;
+    this.sitePaths = sitePaths;
+    this.trackingFooters = trackingFooters;
+    this.gerritServerConfig = gerritServerConfig;
+    this.gitRepositoryManager = gitRepositoryManager;
+    this.anonymousCowardName = anonymousCowardName;
+    this.serverIdentProvider = serverIdentProvider;
+    this.secureStore = secureStore;
+    this.isReplicaProvider = isReplicaProvider;
+  }
 
   @Provides
   @SitePath
@@ -52,69 +82,50 @@
     return sitePath;
   }
 
-  @Inject private SitePaths sitePaths;
-
   @Provides
   SitePaths getSitePaths() {
     return sitePaths;
   }
 
-  @Inject private TrackingFooters trackingFooters;
-
   @Provides
   TrackingFooters getTrackingFooters() {
     return trackingFooters;
   }
 
-  @Inject @GerritServerConfig private Config gerritServerConfig;
-
   @Provides
   @GerritServerConfig
   Config getGerritServerConfig() {
     return gerritServerConfig;
   }
 
-  @Inject private GitRepositoryManager gitRepositoryManager;
-
   @Provides
   GitRepositoryManager getGitRepositoryManager() {
     return gitRepositoryManager;
   }
 
-  @Inject @AnonymousCowardName private String anonymousCowardName;
-
   @Provides
   @AnonymousCowardName
   String getAnonymousCowardName() {
     return anonymousCowardName;
   }
 
-  @Inject private GerritPersonIdentProvider serverIdentProvider;
-
   @Provides
   @GerritPersonIdent
   PersonIdent getServerIdent() {
     return serverIdentProvider.get();
   }
 
-  @Inject private SecureStore secureStore;
-
   @Provides
   SecureStore getSecureStore() {
     return secureStore;
   }
 
-  @Inject private GerritIsReplicaProvider isReplicaProvider;
-
   @Provides
   @GerritIsReplica
   boolean getIsReplica() {
     return isReplicaProvider.get();
   }
 
-  @Inject
-  CopyConfigModule() {}
-
   @Override
   protected void configure() {}
 }
diff --git a/java/com/google/gerrit/server/plugins/ServerPluginInfoModule.java b/java/com/google/gerrit/server/plugins/ServerPluginInfoModule.java
index 0f7e87e..8386b4c 100644
--- a/java/com/google/gerrit/server/plugins/ServerPluginInfoModule.java
+++ b/java/com/google/gerrit/server/plugins/ServerPluginInfoModule.java
@@ -33,10 +33,11 @@
 class ServerPluginInfoModule extends AbstractModule {
   private final ServerPlugin plugin;
   private final Path dataDir;
-
-  private volatile boolean ready;
   private final MetricMaker serverMetrics;
 
+  @SuppressWarnings("MutableGuiceModule")
+  private volatile boolean ready;
+
   ServerPluginInfoModule(ServerPlugin plugin, MetricMaker serverMetrics) {
     this.plugin = plugin;
     this.dataDir = plugin.getDataDir();
diff --git a/java/com/google/gerrit/server/project/SubmitRequirementsEvaluatorImpl.java b/java/com/google/gerrit/server/project/SubmitRequirementsEvaluatorImpl.java
index 7777678..09a232a 100644
--- a/java/com/google/gerrit/server/project/SubmitRequirementsEvaluatorImpl.java
+++ b/java/com/google/gerrit/server/project/SubmitRequirementsEvaluatorImpl.java
@@ -83,7 +83,8 @@
   public void validateExpression(SubmitRequirementExpression expression)
       throws QueryParseException {
     try (ManualRequestContext ignored = requestContext.open()) {
-      queryBuilder.get().parse(expression.expressionString());
+      @SuppressWarnings("unused")
+      var unused = queryBuilder.get().parse(expression.expressionString());
     }
   }
 
diff --git a/java/com/google/gerrit/server/query/approval/ListOfFilesUnchangedPredicate.java b/java/com/google/gerrit/server/query/approval/ListOfFilesUnchangedPredicate.java
index 958011c..bbbd849 100644
--- a/java/com/google/gerrit/server/query/approval/ListOfFilesUnchangedPredicate.java
+++ b/java/com/google/gerrit/server/query/approval/ListOfFilesUnchangedPredicate.java
@@ -23,7 +23,6 @@
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.patch.DiffNotAvailableException;
 import com.google.gerrit.server.patch.DiffOperations;
-import com.google.gerrit.server.patch.DiffOptions;
 import com.google.gerrit.server.patch.gitdiff.ModifiedFile;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -63,7 +62,6 @@
               ctx.changeNotes().getProjectName(),
               targetPatchSet.commitId(),
               parentNum,
-              DiffOptions.DEFAULTS,
               ctx.revWalk(),
               ctx.repoConfig());
       Map<String, ModifiedFile> baseVsPrior =
@@ -71,7 +69,6 @@
               ctx.changeNotes().getProjectName(),
               sourcePatchSet.commitId(),
               parentNum,
-              DiffOptions.DEFAULTS,
               ctx.revWalk(),
               ctx.repoConfig());
       Map<String, ModifiedFile> priorVsCurrent =
@@ -79,7 +76,6 @@
               ctx.changeNotes().getProjectName(),
               sourcePatchSet.commitId(),
               targetPatchSet.commitId(),
-              DiffOptions.DEFAULTS,
               ctx.revWalk(),
               ctx.repoConfig());
       return match(baseVsCurrent, baseVsPrior, priorVsCurrent);
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index da14d45..2d5aea7 100644
--- a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -111,6 +111,7 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
@@ -144,6 +145,7 @@
   public interface ChangeIsOperandFactory extends ChangeOperandFactory {}
 
   private static final Pattern PAT_LEGACY_ID = Pattern.compile("^[1-9][0-9]*$");
+  private static final Pattern PAT_PROJECT_CHANGE_NUM = Pattern.compile("^([^~]+)~([1-9][0-9]*)$");
   private static final Pattern PAT_CHANGE_ID = Pattern.compile(CHANGE_ID_PATTERN);
   private static final Pattern DEF_CHANGE =
       Pattern.compile("^(?:[1-9][0-9]*|(?:[^~]+~[^~]+~)?[iI][0-9a-f]{4,}.*)$");
@@ -593,7 +595,14 @@
           branch(triplet.get().branch().branch()),
           ChangePredicates.idPrefix(parseChangeId(triplet.get().id().get())));
     }
-    if (PAT_LEGACY_ID.matcher(query).matches()) {
+
+    Matcher projectChangeNumber = PAT_PROJECT_CHANGE_NUM.matcher(query);
+    if (projectChangeNumber.matches()) {
+      return Predicate.and(
+          project(projectChangeNumber.group(1)),
+          ChangePredicates.idStr(projectChangeNumber.group(2)));
+
+    } else if (PAT_LEGACY_ID.matcher(query).matches()) {
       Integer id = Ints.tryParse(query);
       if (id != null) {
         return ChangePredicates.idStr(Change.id(id));
diff --git a/java/com/google/gerrit/server/restapi/account/PostWatchedProjects.java b/java/com/google/gerrit/server/restapi/account/PostWatchedProjects.java
index 2131070..3f543af 100644
--- a/java/com/google/gerrit/server/restapi/account/PostWatchedProjects.java
+++ b/java/com/google/gerrit/server/restapi/account/PostWatchedProjects.java
@@ -100,7 +100,8 @@
 
       if (!Strings.isNullOrEmpty(info.filter)) {
         try {
-          QueryParser.parse(info.filter);
+          @SuppressWarnings("unused")
+          var unused = QueryParser.parse(info.filter);
         } catch (QueryParseException e) {
           throw new BadRequestException(
               String.format(
diff --git a/java/com/google/gerrit/server/restapi/config/SnapshotIndex.java b/java/com/google/gerrit/server/restapi/config/SnapshotIndex.java
index b5f1baf..72af97f 100644
--- a/java/com/google/gerrit/server/restapi/config/SnapshotIndex.java
+++ b/java/com/google/gerrit/server/restapi/config/SnapshotIndex.java
@@ -45,7 +45,8 @@
     }
     for (Index<?, ?> index : indexes) {
       try {
-        index.snapshot(id);
+        @SuppressWarnings("unused")
+        var unused = index.snapshot(id);
       } catch (FileAlreadyExistsException e) {
         return Response.withStatusCode(SC_CONFLICT, "Snapshot with same ID already exists.");
       }
diff --git a/java/com/google/gerrit/server/restapi/project/CreateLabel.java b/java/com/google/gerrit/server/restapi/project/CreateLabel.java
index ad32f4f..7b15350 100644
--- a/java/com/google/gerrit/server/restapi/project/CreateLabel.java
+++ b/java/com/google/gerrit/server/restapi/project/CreateLabel.java
@@ -175,7 +175,8 @@
 
     if (input.copyCondition != null) {
       try {
-        approvalQueryBuilder.parse(input.copyCondition);
+        @SuppressWarnings("unused")
+        var unused = approvalQueryBuilder.parse(input.copyCondition);
       } catch (QueryParseException e) {
         throw new BadRequestException(
             "unable to parse copy condition. got: " + input.copyCondition + ". " + e.getMessage(),
diff --git a/java/com/google/gerrit/server/restapi/project/SetLabel.java b/java/com/google/gerrit/server/restapi/project/SetLabel.java
index 10589cc..b5c9bba 100644
--- a/java/com/google/gerrit/server/restapi/project/SetLabel.java
+++ b/java/com/google/gerrit/server/restapi/project/SetLabel.java
@@ -189,7 +189,8 @@
     input.copyCondition = Strings.emptyToNull(input.copyCondition);
     if (input.copyCondition != null) {
       try {
-        approvalQueryBuilder.parse(input.copyCondition);
+        @SuppressWarnings("unused")
+        var unused = approvalQueryBuilder.parse(input.copyCondition);
       } catch (QueryParseException e) {
         throw new BadRequestException(
             "unable to parse copy condition. got: " + input.copyCondition + ". " + e.getMessage(),
diff --git a/java/com/google/gerrit/server/update/RetryHelper.java b/java/com/google/gerrit/server/update/RetryHelper.java
index 7e6974c..713417d 100644
--- a/java/com/google/gerrit/server/update/RetryHelper.java
+++ b/java/com/google/gerrit/server/update/RetryHelper.java
@@ -45,6 +45,7 @@
 import com.google.gerrit.server.plugincontext.PluginSetContext;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.InternalChangeQuery;
+import com.google.gerrit.server.query.group.InternalGroupQuery;
 import com.google.gerrit.server.update.RetryableAction.Action;
 import com.google.gerrit.server.update.RetryableAction.ActionType;
 import com.google.gerrit.server.update.RetryableChangeAction.ChangeAction;
@@ -188,6 +189,7 @@
   private final BatchUpdate.Factory updateFactory;
   private final Provider<InternalAccountQuery> internalAccountQuery;
   private final Provider<InternalChangeQuery> internalChangeQuery;
+  private final Provider<InternalGroupQuery> internalGroupQuery;
   private final PluginSetContext<ExceptionHook> exceptionHooks;
   private final Duration defaultTimeout;
   private final Map<String, Duration> defaultTimeouts;
@@ -202,13 +204,15 @@
       PluginSetContext<ExceptionHook> exceptionHooks,
       BatchUpdate.Factory updateFactory,
       Provider<InternalAccountQuery> internalAccountQuery,
-      Provider<InternalChangeQuery> internalChangeQuery) {
+      Provider<InternalChangeQuery> internalChangeQuery,
+      Provider<InternalGroupQuery> internalGroupQuery) {
     this(
         cfg,
         metrics,
         updateFactory,
         internalAccountQuery,
         internalChangeQuery,
+        internalGroupQuery,
         exceptionHooks,
         null);
   }
@@ -220,6 +224,7 @@
       BatchUpdate.Factory updateFactory,
       Provider<InternalAccountQuery> internalAccountQuery,
       Provider<InternalChangeQuery> internalChangeQuery,
+      Provider<InternalGroupQuery> internalGroupQuery,
       PluginSetContext<ExceptionHook> exceptionHooks,
       @Nullable Consumer<RetryerBuilder<?>> overwriteDefaultRetryerStrategySetup) {
     this.cfg = cfg;
@@ -227,6 +232,7 @@
     this.updateFactory = updateFactory;
     this.internalAccountQuery = internalAccountQuery;
     this.internalChangeQuery = internalChangeQuery;
+    this.internalGroupQuery = internalGroupQuery;
     this.exceptionHooks = exceptionHooks;
     this.defaultTimeout =
         Duration.ofMillis(
@@ -386,6 +392,22 @@
   }
 
   /**
+   * Creates an action for querying the group index that is executed with retrying when called.
+   *
+   * <p>The index query action gets a {@link InternalGroupQuery} provided that can be used to query
+   * the account index.
+   *
+   * @param actionName the name of the action, used as metric bucket
+   * @param indexQueryAction the action that should be executed
+   * @return the retryable action, callers need to call {@link RetryableIndexQueryAction#call()} to
+   *     execute the action
+   */
+  public <T> RetryableIndexQueryAction<InternalGroupQuery, T> groupIndexQuery(
+      String actionName, IndexQueryAction<T, InternalGroupQuery> indexQueryAction) {
+    return new RetryableIndexQueryAction<>(this, internalGroupQuery, actionName, indexQueryAction);
+  }
+
+  /**
    * Returns the default timeout for an action type.
    *
    * <p>The default timeout for an action type is defined by the 'retry.<action-type>.timeout'
diff --git a/java/com/google/gerrit/sshd/CommandModule.java b/java/com/google/gerrit/sshd/CommandModule.java
index 4242c71..7becc2b 100644
--- a/java/com/google/gerrit/sshd/CommandModule.java
+++ b/java/com/google/gerrit/sshd/CommandModule.java
@@ -21,7 +21,11 @@
 
 /** Module to register commands in the SSH daemon. */
 public abstract class CommandModule extends LifecycleModule {
-  protected boolean slaveMode;
+  protected final boolean slaveMode;
+
+  protected CommandModule(boolean slaveMode) {
+    this.slaveMode = slaveMode;
+  }
 
   /**
    * Configure a command to be invoked by name.
diff --git a/java/com/google/gerrit/sshd/PluginCommandModule.java b/java/com/google/gerrit/sshd/PluginCommandModule.java
index f0dc17a..9fd068c 100644
--- a/java/com/google/gerrit/sshd/PluginCommandModule.java
+++ b/java/com/google/gerrit/sshd/PluginCommandModule.java
@@ -14,24 +14,19 @@
 
 package com.google.gerrit.sshd;
 
-import static com.google.common.base.Preconditions.checkState;
-
-import com.google.gerrit.extensions.annotations.PluginName;
-import com.google.inject.Inject;
 import com.google.inject.binder.LinkedBindingBuilder;
 import org.apache.sshd.server.command.Command;
 
 public abstract class PluginCommandModule extends CommandModule {
-  private CommandName command;
+  private final CommandName command;
 
-  @Inject
-  void setPluginName(@PluginName String name) {
-    this.command = Commands.named(name);
+  public PluginCommandModule(String pluginName) {
+    super(/* slaveMode= */ false);
+    this.command = Commands.named(pluginName);
   }
 
   @Override
   protected final void configure() {
-    checkState(command != null, "@PluginName must be provided");
     bind(Commands.key(command)).toProvider(new DispatchCommandProvider(command));
     configureCommands();
   }
diff --git a/java/com/google/gerrit/sshd/SingleCommandPluginModule.java b/java/com/google/gerrit/sshd/SingleCommandPluginModule.java
index edc797c..4e16fbc 100644
--- a/java/com/google/gerrit/sshd/SingleCommandPluginModule.java
+++ b/java/com/google/gerrit/sshd/SingleCommandPluginModule.java
@@ -14,10 +14,6 @@
 
 package com.google.gerrit.sshd;
 
-import static com.google.common.base.Preconditions.checkState;
-
-import com.google.gerrit.extensions.annotations.PluginName;
-import com.google.inject.Inject;
 import com.google.inject.binder.LinkedBindingBuilder;
 import org.apache.sshd.server.command.Command;
 
@@ -27,16 +23,15 @@
  * <p>Cannot be combined with {@link PluginCommandModule}.
  */
 public abstract class SingleCommandPluginModule extends CommandModule {
-  private CommandName command;
+  private final CommandName command;
 
-  @Inject
-  void setPluginName(@PluginName String name) {
-    this.command = Commands.named(name);
+  public SingleCommandPluginModule(String pluginName) {
+    super(/* slaveMode= */ false);
+    this.command = Commands.named(pluginName);
   }
 
   @Override
   protected final void configure() {
-    checkState(command != null, "@PluginName must be provided");
     configure(bind(Commands.key(command)));
   }
 
diff --git a/java/com/google/gerrit/sshd/SshAutoRegisterModuleGenerator.java b/java/com/google/gerrit/sshd/SshAutoRegisterModuleGenerator.java
index 7adcd24..8c37ca3 100644
--- a/java/com/google/gerrit/sshd/SshAutoRegisterModuleGenerator.java
+++ b/java/com/google/gerrit/sshd/SshAutoRegisterModuleGenerator.java
@@ -31,6 +31,7 @@
 import java.util.Map;
 import org.apache.sshd.server.command.Command;
 
+@SuppressWarnings("MutableGuiceModule")
 class SshAutoRegisterModuleGenerator extends AbstractModule implements ModuleGenerator {
   private final Map<String, Class<Command>> commands = new HashMap<>();
   private final ListMultimap<TypeLiteral<?>, Class<?>> listeners = LinkedListMultimap.create();
diff --git a/java/com/google/gerrit/sshd/SshModule.java b/java/com/google/gerrit/sshd/SshModule.java
index ca452c1..ca15ba7 100644
--- a/java/com/google/gerrit/sshd/SshModule.java
+++ b/java/com/google/gerrit/sshd/SshModule.java
@@ -19,6 +19,7 @@
 
 import com.google.common.base.CharMatcher;
 import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.extensions.events.AccountActivationListener;
 import com.google.gerrit.extensions.registration.DynamicItem;
 import com.google.gerrit.extensions.registration.DynamicSet;
@@ -39,7 +40,6 @@
 import com.google.inject.internal.UniqueAnnotations;
 import com.google.inject.servlet.RequestScoped;
 import java.net.SocketAddress;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
@@ -50,14 +50,15 @@
 
 /** Configures standard dependencies for {@link SshDaemon}. */
 public class SshModule extends LifecycleModule {
-  private final Map<String, String> aliases;
+  private final ImmutableMap<String, String> aliases;
 
   @Inject
   SshModule(@GerritServerConfig Config cfg) {
-    aliases = new HashMap<>();
+    ImmutableMap.Builder<String, String> aliasesBuilder = ImmutableMap.builder();
     for (String name : cfg.getNames("ssh-alias", true)) {
-      aliases.put(name, cfg.getString("ssh-alias", null, name));
+      aliasesBuilder.put(name, cfg.getString("ssh-alias", null, name));
     }
+    this.aliases = aliasesBuilder.build();
   }
 
   @Override
diff --git a/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java b/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
index 42e7c0f..ce8c265 100644
--- a/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
+++ b/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
@@ -29,8 +29,8 @@
   private final LfsPluginAuthCommandModule lfsPluginAuthModule;
 
   public DefaultCommandModule(
-      boolean slave, DownloadConfig downloadCfg, LfsPluginAuthCommandModule module) {
-    slaveMode = slave;
+      boolean slaveMode, DownloadConfig downloadCfg, LfsPluginAuthCommandModule module) {
+    super(slaveMode);
     downloadConfig = downloadCfg;
     lfsPluginAuthModule = module;
   }
diff --git a/java/com/google/gerrit/sshd/commands/ExternalIdCommandsModule.java b/java/com/google/gerrit/sshd/commands/ExternalIdCommandsModule.java
index 8b025d3..b0ecdfc 100644
--- a/java/com/google/gerrit/sshd/commands/ExternalIdCommandsModule.java
+++ b/java/com/google/gerrit/sshd/commands/ExternalIdCommandsModule.java
@@ -24,6 +24,9 @@
 import java.util.concurrent.ExecutorService;
 
 public class ExternalIdCommandsModule extends CommandModule {
+  public ExternalIdCommandsModule() {
+    super(/* slaveMode= */ false);
+  }
 
   @Override
   protected void configure() {
diff --git a/java/com/google/gerrit/sshd/commands/IndexCommandsModule.java b/java/com/google/gerrit/sshd/commands/IndexCommandsModule.java
index 332ed69..b3268c5 100644
--- a/java/com/google/gerrit/sshd/commands/IndexCommandsModule.java
+++ b/java/com/google/gerrit/sshd/commands/IndexCommandsModule.java
@@ -27,6 +27,7 @@
   private final Injector injector;
 
   public IndexCommandsModule(Injector injector) {
+    super(/* slaveMode= */ false);
     this.injector = injector;
   }
 
diff --git a/java/com/google/gerrit/sshd/commands/SequenceCommandsModule.java b/java/com/google/gerrit/sshd/commands/SequenceCommandsModule.java
index e716240..48147a5 100644
--- a/java/com/google/gerrit/sshd/commands/SequenceCommandsModule.java
+++ b/java/com/google/gerrit/sshd/commands/SequenceCommandsModule.java
@@ -20,6 +20,9 @@
 import com.google.gerrit.sshd.DispatchCommandProvider;
 
 public class SequenceCommandsModule extends CommandModule {
+  public SequenceCommandsModule() {
+    super(/* slaveMode= */ false);
+  }
 
   @Override
   protected void configure() {
diff --git a/java/com/google/gerrit/sshd/plugin/LfsPluginAuthCommand.java b/java/com/google/gerrit/sshd/plugin/LfsPluginAuthCommand.java
index 8ba673a..197354c 100644
--- a/java/com/google/gerrit/sshd/plugin/LfsPluginAuthCommand.java
+++ b/java/com/google/gerrit/sshd/plugin/LfsPluginAuthCommand.java
@@ -41,6 +41,7 @@
 
     @Inject
     LfsPluginAuthCommandModule(@GerritServerConfig Config cfg) {
+      super(/* slaveMode= */ false);
       pluginProvided = cfg.getString("lfs", null, "plugin") != null;
     }
 
diff --git a/java/com/google/gerrit/testing/InMemoryModule.java b/java/com/google/gerrit/testing/InMemoryModule.java
index 3f0f8b7..b699050 100644
--- a/java/com/google/gerrit/testing/InMemoryModule.java
+++ b/java/com/google/gerrit/testing/InMemoryModule.java
@@ -21,6 +21,7 @@
 
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.acceptance.testsuite.group.GroupOperationsImpl;
@@ -381,7 +382,8 @@
     try {
       Class<?> clazz = Class.forName(moduleClassName);
       Method m =
-          clazz.getMethod("singleVersionWithExplicitVersions", Map.class, int.class, boolean.class);
+          clazz.getMethod(
+              "singleVersionWithExplicitVersions", ImmutableMap.class, int.class, boolean.class);
       return (Module) m.invoke(null, getSingleSchemaVersions(), 0, ReplicaUtil.isReplica(cfg));
     } catch (ClassNotFoundException
         | SecurityException
@@ -394,13 +396,13 @@
     }
   }
 
-  private Map<String, Integer> getSingleSchemaVersions() {
+  private ImmutableMap<String, Integer> getSingleSchemaVersions() {
     Map<String, Integer> singleVersions = new HashMap<>();
     putSchemaVersion(singleVersions, AccountSchemaDefinitions.INSTANCE);
     putSchemaVersion(singleVersions, ChangeSchemaDefinitions.INSTANCE);
     putSchemaVersion(singleVersions, GroupSchemaDefinitions.INSTANCE);
     putSchemaVersion(singleVersions, ProjectSchemaDefinitions.INSTANCE);
-    return singleVersions;
+    return ImmutableMap.copyOf(singleVersions);
   }
 
   private void putSchemaVersion(
diff --git a/javatests/com/google/gerrit/acceptance/ProjectResetterTest.java b/javatests/com/google/gerrit/acceptance/ProjectResetterTest.java
index 33e6692..f0705a4 100644
--- a/javatests/com/google/gerrit/acceptance/ProjectResetterTest.java
+++ b/javatests/com/google/gerrit/acceptance/ProjectResetterTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.AccountGroup;
 import com.google.gerrit.entities.Project;
@@ -283,10 +284,12 @@
     verifyNoMoreInteractions(cache, indexer, includeCache);
   }
 
+  @CanIgnoreReturnValue
   private Ref createRef(String ref) throws IOException {
     return createRef(repo, ref);
   }
 
+  @CanIgnoreReturnValue
   private Ref createRef(Repository repo, String ref) throws IOException {
     try (RefUpdateContext ctx = openTestRefUpdateContext()) {
       try (ObjectInserter oi = repo.newObjectInserter();
@@ -301,10 +304,12 @@
     }
   }
 
+  @CanIgnoreReturnValue
   private Ref updateRef(Ref ref) throws IOException {
     return updateRef(repo, ref);
   }
 
+  @CanIgnoreReturnValue
   private Ref updateRef(Repository repo, Ref ref) throws IOException {
     try (RefUpdateContext ctx = openTestRefUpdateContext()) {
       try (ObjectInserter oi = repo.newObjectInserter();
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index e93b889..73ec8b3 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -623,7 +623,8 @@
       accountIndexedCounter.assertReindexOf(activatableAccountId, 1);
     }
 
-    gApi.changes().query("owner:foo@activatable.com").get();
+    @SuppressWarnings("unused")
+    var unused = gApi.changes().query("owner:foo@activatable.com").get();
   }
 
   @Test
@@ -636,7 +637,8 @@
       accountIndexedCounter.assertReindexOf(activatableAccountId, 1);
     }
 
-    gApi.changes().query("owner:foo").get();
+    @SuppressWarnings("unused")
+    var unused = gApi.changes().query("owner:foo").get();
   }
 
   @Test
@@ -2236,6 +2238,7 @@
                 null,
                 null,
                 null,
+                null,
                 exceptionHooks,
                 r ->
                     r.withStopStrategy(StopStrategies.stopAfterAttempt(status.size()))
@@ -3657,6 +3660,7 @@
             null,
             null,
             null,
+            null,
             exceptionHooks,
             r -> r.withBlockStrategy(noSleepBlockStrategy)));
   }
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
index b55a535..01e0bd4 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
@@ -187,8 +187,11 @@
   public void listAgreementPermission() throws Exception {
     assume().that(isContributorAgreementsEnabled()).isTrue();
     requestScopeOperations.setApiUser(admin.id());
+
     // Allowed.
-    gApi.accounts().id(user.id().get()).listAgreements();
+    @SuppressWarnings("unused")
+    var unused = gApi.accounts().id(user.id().get()).listAgreements();
+
     requestScopeOperations.setApiUser(user.id());
 
     // Not allowed.
@@ -391,7 +394,9 @@
   @GerritConfig(name = "auth.contributorAgreements", value = "true")
   public void anonymousAccessServerInfoEvenWithCLAs() throws Exception {
     requestScopeOperations.setApiUserAnonymous();
-    gApi.config().server().getInfo();
+
+    @SuppressWarnings("unused")
+    var unused = gApi.config().server().getInfo();
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index cab92aa..79bf840 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -306,7 +306,9 @@
     String triplet = project.get() + "~master~" + result.getChangeId();
     CacheStats startIntra = cloneStats(intraCache.stats());
     CacheStats startSummary = cloneStats(diffSummaryCache.stats());
-    gApi.changes().id(triplet).get(ImmutableList.of(ListChangesOption.SKIP_DIFFSTAT));
+
+    @SuppressWarnings("unused")
+    var unused = gApi.changes().id(triplet).get(ImmutableList.of(ListChangesOption.SKIP_DIFFSTAT));
 
     assertThat(intraCache.stats()).since(startIntra).hasMissCount(0);
     assertThat(intraCache.stats()).since(startIntra).hasHitCount(0);
@@ -821,7 +823,9 @@
   public void getAmbiguous() throws Exception {
     PushOneCommit.Result r1 = createChange();
     String changeId = r1.getChangeId();
-    gApi.changes().id(changeId).get();
+
+    @SuppressWarnings("unused")
+    var unused = gApi.changes().id(changeId).get();
 
     BranchInput b = new BranchInput();
     b.revision = repo().exactRef("HEAD").getObjectId().name();
@@ -3738,7 +3742,6 @@
 
   @Test
   public void uploadingRulesPlIsNotAllowed() throws Exception {
-    projectOperations.project(project).getHead("master");
     GitUtil.fetch(testRepo, RefNames.REFS_CONFIG + ":config");
     testRepo.reset("config");
     PushOneCommit.Result pushResult =
@@ -4746,7 +4749,8 @@
 
   private ThrowableSubject assertThatQueryException(String query) throws Exception {
     try {
-      query(query);
+      @SuppressWarnings("unused")
+      var unused = query(query);
     } catch (BadRequestException e) {
       return assertThat(e);
     }
diff --git a/javatests/com/google/gerrit/acceptance/api/change/QueryChangesIT.java b/javatests/com/google/gerrit/acceptance/api/change/QueryChangesIT.java
index 465a19a..ed349d3 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/QueryChangesIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/QueryChangesIT.java
@@ -97,7 +97,7 @@
   public void moreChangesIndicatorDoesNotWronglyCopyToUnrelatedChanges() throws Exception {
     String queryWithMoreChanges = "is:wip limit:1 repo:" + project.get();
     String queryWithNoMoreChanges = "is:open limit:10 repo:" + project.get();
-    createChange().getChangeId();
+    createChange();
     String cId2 = createChange().getChangeId();
     String cId3 = createChange().getChangeId();
     gApi.changes().id(cId2).setWorkInProgress();
@@ -160,8 +160,8 @@
   @SuppressWarnings("unchecked")
   public void withPagedResults() throws Exception {
     // Create 4 visible changes.
-    createChange(testRepo).getChange().getId().get();
-    createChange(testRepo).getChange().getId().get();
+    createChange(testRepo);
+    createChange(testRepo);
     int changeId3 = createChange(testRepo).getChange().getId().get();
     int changeId4 = createChange(testRepo).getChange().getId().get();
 
@@ -311,7 +311,7 @@
   @Test
   @SuppressWarnings("unchecked")
   public void skipVisibility_noReadPermission() throws Exception {
-    createChange().getChangeId();
+    createChange();
     requestScopeOperations.setApiUser(admin.id());
     QueryChanges queryChanges = queryChangesProvider.get();
 
diff --git a/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java b/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java
index 7c50e93..3506404 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java
@@ -335,7 +335,7 @@
     // If notify input not specified, the endpoint overrides it to NONE
     RevertInput revertInput = createWipRevertInput();
     revertInput.notify = null;
-    gApi.changes().id(r.getChangeId()).revert(revertInput).get();
+    gApi.changes().id(r.getChangeId()).revert(revertInput);
     assertThat(sender.getMessages()).isEmpty();
   }
 
@@ -350,7 +350,7 @@
     revertInput.notify = NotifyHandling.NONE;
 
     sender.clear();
-    gApi.changes().id(r.getChangeId()).revert(revertInput).get();
+    gApi.changes().id(r.getChangeId()).revert(revertInput);
     assertThat(sender.getMessages()).isEmpty();
   }
 
diff --git a/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementCustomRuleIT.java b/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementCustomRuleIT.java
index 5584c2b..2c376fc 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementCustomRuleIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementCustomRuleIT.java
@@ -178,9 +178,12 @@
     String changeId = r.getChangeId();
 
     rule.numberOfEvaluations.set(0);
-    gApi.changes()
-        .id(changeId)
-        .get(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_ACTIONS);
+
+    @SuppressWarnings("unused")
+    var unused =
+        gApi.changes()
+            .id(changeId)
+            .get(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_ACTIONS);
 
     // Submit rules are computed freshly, but only once.
     assertThat(rule.numberOfEvaluations.get()).isEqualTo(1);
@@ -192,10 +195,13 @@
     String changeId = r.getChangeId();
 
     rule.numberOfEvaluations.set(0);
-    gApi.changes()
-        .query(changeId)
-        .withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_ACTIONS)
-        .get();
+
+    @SuppressWarnings("unused")
+    var unused =
+        gApi.changes()
+            .query(changeId)
+            .withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_ACTIONS)
+            .get();
 
     // Submit rule evaluation results from the change index are reused
     assertThat(rule.numberOfEvaluations.get()).isEqualTo(0);
diff --git a/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementIT.java b/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementIT.java
index ab2f358..c7d1c5e 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementIT.java
@@ -1134,7 +1134,7 @@
     LabelDefinitionInput input = new LabelDefinitionInput();
     input.function = "NoOp";
     input.values = ImmutableMap.of("+1", "Override", " 0", "No Override");
-    gApi.projects().name(project.get()).label("Code-Review-Override").create(input).get();
+    gApi.projects().name(project.get()).label("Code-Review-Override").create(input);
 
     // Allow to vote on the Code-Review-Override label.
     projectOperations
@@ -1300,7 +1300,7 @@
     LabelDefinitionInput input = new LabelDefinitionInput();
     input.function = "NoOp";
     input.values = ImmutableMap.of("+1", "Override", " 0", "No Override");
-    gApi.projects().name(project.get()).label("build-cop-override").create(input).get();
+    gApi.projects().name(project.get()).label("build-cop-override").create(input);
 
     // Allow to vote on the build-cop-override label.
     projectOperations
@@ -1325,7 +1325,7 @@
             .build());
 
     // Create Code-Review-Override label
-    gApi.projects().name(project.get()).label("Code-Review-Override").create(input).get();
+    gApi.projects().name(project.get()).label("Code-Review-Override").create(input);
 
     // Allow to vote on the Code-Review-Override label.
     projectOperations
diff --git a/javatests/com/google/gerrit/acceptance/api/change/SubmitTypeRuleIT.java b/javatests/com/google/gerrit/acceptance/api/change/SubmitTypeRuleIT.java
index 8e11f70..7d9895c 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/SubmitTypeRuleIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/SubmitTypeRuleIT.java
@@ -79,7 +79,8 @@
       TestSubmitRuleInput in = new TestSubmitRuleInput();
       in.rule = rule;
       try {
-        gApi.changes().id(testChangeId.get()).current().testSubmitType(in);
+        @SuppressWarnings("unused")
+        var unused = gApi.changes().id(testChangeId.get()).current().testSubmitType(in);
       } catch (RestApiException e) {
         throw new ConfigInvalidException("Invalid submit type rule", e);
       }
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index f074e29..bdb6ded 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -657,7 +657,7 @@
   @Test
   public void groupCannotBeCreatedWithNameOfAnotherGroup() throws Exception {
     String name = name("Users");
-    gApi.groups().create(name).get();
+    gApi.groups().create(name);
 
     assertThrows(ResourceConflictException.class, () -> gApi.groups().create(name));
   }
@@ -1485,7 +1485,7 @@
     GroupInput groupInput = new GroupInput();
     groupInput.name = name("contributors");
     groupInput.members = ImmutableList.of(user.username());
-    gApi.groups().create(groupInput).get();
+    gApi.groups().create(groupInput);
     restartAsSlave();
 
     requestScopeOperations.setApiUser(user.id());
diff --git a/javatests/com/google/gerrit/acceptance/api/plugin/PluginIT.java b/javatests/com/google/gerrit/acceptance/api/plugin/PluginIT.java
index 462d0a5..dbd1fb8 100644
--- a/javatests/com/google/gerrit/acceptance/api/plugin/PluginIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/plugin/PluginIT.java
@@ -145,7 +145,9 @@
         new com.google.gerrit.extensions.common.InstallPluginInput();
     input.raw = JS_PLUGIN_CONTENT;
     gApi.plugins().install("legacy.js", input);
-    gApi.plugins().name("legacy").get();
+
+    @SuppressWarnings("unused")
+    var unused = gApi.plugins().name("legacy").get();
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/project/AccessIT.java b/javatests/com/google/gerrit/acceptance/api/project/AccessIT.java
index a2f1f46..6c740ae 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/AccessIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/AccessIT.java
@@ -244,7 +244,8 @@
       testRefAction(() -> assertThat(u.delete()).isEqualTo(Result.FORCED));
 
       // This should not crash.
-      pApi().access();
+      @SuppressWarnings("unused")
+      var unused = pApi().access();
     }
   }
 
@@ -465,9 +466,11 @@
         .forUpdate()
         .add(allow(Permission.READ).ref(RefNames.REFS_CONFIG).group(REGISTERED_USERS))
         .update();
+
     // User can see the branch
     requestScopeOperations.setApiUser(user.id());
-    pApi().branch("refs/heads/master").get();
+    @SuppressWarnings("unused")
+    var unused = pApi().branch("refs/heads/master").get();
 
     ProjectAccessInput accessInput = newProjectAccessInput();
 
@@ -516,7 +519,7 @@
 
     // Now it works again.
     requestScopeOperations.setApiUser(user.id());
-    pApi().branch("refs/heads/master").get();
+    unused = pApi().branch("refs/heads/master").get();
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/project/CheckProjectIT.java b/javatests/com/google/gerrit/acceptance/api/project/CheckProjectIT.java
index 4163e17..02f6784 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/CheckProjectIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/CheckProjectIT.java
@@ -253,7 +253,9 @@
   @Test
   public void branchPrefixCanBeOmitted() throws Exception {
     CheckProjectInput input = checkProjectInputForAutoCloseableCheck("master");
-    gApi.projects().name(project.get()).check(input);
+
+    @SuppressWarnings("unused")
+    var unused = gApi.projects().name(project.get()).check(input);
   }
 
   @Test
@@ -261,7 +263,9 @@
     CheckProjectInput input = checkProjectInputForAutoCloseableCheck("refs/heads/master");
     input.autoCloseableChangesCheck.maxCommits =
         ProjectsConsistencyChecker.AUTO_CLOSE_MAX_COMMITS_LIMIT;
-    gApi.projects().name(project.get()).check(input);
+
+    @SuppressWarnings("unused")
+    var unused = gApi.projects().name(project.get()).check(input);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/project/DashboardIT.java b/javatests/com/google/gerrit/acceptance/api/project/DashboardIT.java
index a22b558..b9cbbcd 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/DashboardIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/DashboardIT.java
@@ -38,7 +38,6 @@
 import java.util.List;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevCommit;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -219,8 +218,7 @@
         }
       }
       cb.add(info.path, content.toString());
-      RevCommit c = cb.create();
-      project().commit(c.name());
+      cb.create();
     }
     return info;
   }
diff --git a/javatests/com/google/gerrit/acceptance/api/project/SubmitRequirementsAPIIT.java b/javatests/com/google/gerrit/acceptance/api/project/SubmitRequirementsAPIIT.java
index 97a2d2b..e388dd1 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/SubmitRequirementsAPIIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/SubmitRequirementsAPIIT.java
@@ -58,7 +58,7 @@
     input.name = "code-review";
     input.applicabilityExpression = "topic:foo";
     input.submittabilityExpression = "label:code-review=+2";
-    gApi.projects().name(project.get()).submitRequirement("code-review").create(input).get();
+    gApi.projects().name(project.get()).submitRequirement("code-review").create(input);
 
     SubmitRequirementInfo info =
         gApi.projects().name(project.get()).submitRequirement("code-review").get();
@@ -74,7 +74,7 @@
     input.name = "code-review";
     input.applicabilityExpression = "topic:foo";
     input.submittabilityExpression = "label:code-review=+2";
-    gApi.projects().name(project.get()).submitRequirement("code-review").create(input).get();
+    gApi.projects().name(project.get()).submitRequirement("code-review").create(input);
 
     input.submittabilityExpression = "label:code-review=+1";
     SubmitRequirementInfo info =
@@ -88,7 +88,7 @@
     input.name = "code-review";
     input.applicabilityExpression = "topic:foo";
     input.submittabilityExpression = "label:code-review=+2";
-    gApi.projects().name(project.get()).submitRequirement("code-review").create(input).get();
+    gApi.projects().name(project.get()).submitRequirement("code-review").create(input);
 
     input.applicabilityExpression = null;
     SubmitRequirementInfo info =
@@ -102,7 +102,7 @@
     input.name = "code-review";
     input.overrideExpression = "topic:foo";
     input.submittabilityExpression = "label:code-review=+2";
-    gApi.projects().name(project.get()).submitRequirement("code-review").create(input).get();
+    gApi.projects().name(project.get()).submitRequirement("code-review").create(input);
 
     input.overrideExpression = null;
     SubmitRequirementInfo info =
@@ -115,7 +115,7 @@
     SubmitRequirementInput input = new SubmitRequirementInput();
     input.name = "code-review";
     input.submittabilityExpression = "label:code-review=+2";
-    gApi.projects().name(project.get()).submitRequirement("code-review").create(input).get();
+    gApi.projects().name(project.get()).submitRequirement("code-review").create(input);
 
     input.overrideExpression = "topic:foo";
     SubmitRequirementInfo info =
@@ -129,7 +129,7 @@
     input.name = "code-review";
     input.submittabilityExpression = "label:code-review=+2";
 
-    gApi.projects().name(project.get()).submitRequirement("code-review").create(input).get();
+    gApi.projects().name(project.get()).submitRequirement("code-review").create(input);
     input.submittabilityExpression = "label:code-review=+1";
     requestScopeOperations.setApiUserAnonymous();
     AuthException thrown =
@@ -166,7 +166,7 @@
     input.name = "code-review";
     input.submittabilityExpression = "project:foo AND branch:refs/heads/main";
 
-    gApi.projects().name(project.get()).submitRequirement("code-review").create(input).get();
+    gApi.projects().name(project.get()).submitRequirement("code-review").create(input);
     input.submittabilityExpression = null;
     BadRequestException thrown =
         assertThrows(
@@ -183,7 +183,7 @@
     input.name = "code-review";
     input.submittabilityExpression = "project:foo AND branch:refs/heads/main";
 
-    gApi.projects().name(project.get()).submitRequirement("code-review").create(input).get();
+    gApi.projects().name(project.get()).submitRequirement("code-review").create(input);
     input.submittabilityExpression = "invalid_field:invalid_value";
     BadRequestException thrown =
         assertThrows(
@@ -207,7 +207,7 @@
     input.name = "code-review";
     input.submittabilityExpression = "project:foo AND branch:refs/heads/main";
 
-    gApi.projects().name(project.get()).submitRequirement("code-review").create(input).get();
+    gApi.projects().name(project.get()).submitRequirement("code-review").create(input);
     input.overrideExpression = "invalid_field:invalid_value";
     BadRequestException thrown =
         assertThrows(
@@ -231,7 +231,7 @@
     input.name = "code-review";
     input.submittabilityExpression = "project:foo AND branch:refs/heads/main";
 
-    gApi.projects().name(project.get()).submitRequirement("code-review").create(input).get();
+    gApi.projects().name(project.get()).submitRequirement("code-review").create(input);
     input.applicabilityExpression = "invalid_field:invalid_value";
     BadRequestException thrown =
         assertThrows(
@@ -531,8 +531,11 @@
         .forUpdate()
         .add(allow(Permission.READ).ref("refs/meta/config").group(REGISTERED_USERS))
         .update();
+
     requestScopeOperations.setApiUser(user.id());
-    gApi.projects().name(project.get()).submitRequirements().get();
+
+    @SuppressWarnings("unused")
+    var unused = gApi.projects().name(project.get()).submitRequirements().get();
   }
 
   @Test
@@ -547,8 +550,12 @@
         .forUpdate()
         .add(block(Permission.READ).ref("refs/meta/config").group(REGISTERED_USERS))
         .update();
+
     requestScopeOperations.setApiUser(user.id());
-    gApi.projects().name(project.get()).submitRequirements().withInherited(false).get();
+
+    @SuppressWarnings("unused")
+    var unused =
+        gApi.projects().name(project.get()).submitRequirements().withInherited(false).get();
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
index 4a5c3dd..5b51ed3 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
@@ -800,7 +800,7 @@
     TestCommitValidationListener testCommitValidationListener = new TestCommitValidationListener();
     try (Registration registration =
         extensionRegistry.newRegistration().add(testCommitValidationListener)) {
-      gApi.changes().id(r.getChangeId()).current().cherryPickAsInfo(in);
+      gApi.changes().id(r.getChangeId()).current().cherryPick(in);
       assertThat(testCommitValidationListener.receiveEvent.pushOptions)
           .containsExactly("key", "value");
     }
diff --git a/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java b/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
index 67b6e5b..62a095f 100644
--- a/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
+++ b/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
@@ -142,10 +142,11 @@
     createArbitraryEditFor(changeId);
 
     // check that '0' is parsed as edit revision
-    gApi.changes().id(changeId).revision(0).comments();
+    @SuppressWarnings("unused")
+    var unused = gApi.changes().id(changeId).revision(0).comments();
 
     // check that 'edit' is parsed as edit revision
-    gApi.changes().id(changeId).revision("edit").comments();
+    unused = gApi.changes().id(changeId).revision("edit").comments();
   }
 
   @Test
@@ -517,7 +518,6 @@
     in.email = "test@example.com";
     in.type = ChangeEditIdentityType.COMMITTER;
     adminRestSession.put(urlEditIdentity(changeId), in).assertNoContent();
-    adminRestSession.getJsonAccept(urlEditIdentity(changeId));
     adminRestSession.post(urlPublish(changeId)).assertNoContent();
     ChangeInfo info =
         get(changeId, ListChangesOption.CURRENT_COMMIT, ListChangesOption.CURRENT_REVISION);
@@ -533,7 +533,6 @@
     in.type = ChangeEditIdentityType.COMMITTER;
     in.email = "test@example.com";
     adminRestSession.put(urlEditIdentity(changeId), in).assertNoContent();
-    adminRestSession.getJsonAccept(urlEditIdentity(changeId));
     adminRestSession.post(urlPublish(changeId)).assertNoContent();
     ChangeInfo info =
         get(changeId, ListChangesOption.CURRENT_COMMIT, ListChangesOption.CURRENT_REVISION);
@@ -549,7 +548,6 @@
     in.type = ChangeEditIdentityType.COMMITTER;
     in.name = "John Doe";
     adminRestSession.put(urlEditIdentity(changeId), in).assertNoContent();
-    adminRestSession.getJsonAccept(urlEditIdentity(changeId));
     adminRestSession.post(urlPublish(changeId)).assertNoContent();
     ChangeInfo info =
         get(changeId, ListChangesOption.CURRENT_COMMIT, ListChangesOption.CURRENT_REVISION);
@@ -603,7 +601,6 @@
     in.type = ChangeEditIdentityType.AUTHOR;
     in.email = "test@example.com";
     adminRestSession.put(urlEditIdentity(changeId), in).assertNoContent();
-    adminRestSession.getJsonAccept(urlEditIdentity(changeId));
     adminRestSession.post(urlPublish(changeId)).assertNoContent();
     ChangeInfo info =
         get(changeId, ListChangesOption.CURRENT_COMMIT, ListChangesOption.CURRENT_REVISION);
@@ -619,7 +616,6 @@
     in.type = ChangeEditIdentityType.AUTHOR;
     in.email = "test@example.com";
     adminRestSession.put(urlEditIdentity(changeId), in).assertNoContent();
-    adminRestSession.getJsonAccept(urlEditIdentity(changeId));
     adminRestSession.post(urlPublish(changeId)).assertNoContent();
     ChangeInfo info =
         get(changeId, ListChangesOption.CURRENT_COMMIT, ListChangesOption.CURRENT_REVISION);
@@ -635,7 +631,6 @@
     in.type = ChangeEditIdentityType.AUTHOR;
     in.name = "John Doe";
     adminRestSession.put(urlEditIdentity(changeId), in).assertNoContent();
-    adminRestSession.getJsonAccept(urlEditIdentity(changeId));
     adminRestSession.post(urlPublish(changeId)).assertNoContent();
     ChangeInfo info =
         get(changeId, ListChangesOption.CURRENT_COMMIT, ListChangesOption.CURRENT_REVISION);
@@ -759,6 +754,7 @@
     assertThat(updatedCommitMessage).isEqualTo(in.message);
 
     r = adminRestSession.getJsonAccept(urlEditMessage(changeId, true));
+    r.assertOK();
     try (Repository repo = repoManager.openRepository(project);
         RevWalk rw = new RevWalk(repo)) {
       RevCommit commit = rw.parseCommit(ObjectId.fromString(ps.commitId().name()));
@@ -1275,10 +1271,12 @@
     String editCommitId = edit.get().commit.commit;
 
     RestResponse r = adminRestSession.getJsonAccept(urlRevisionFiles(changeId, editCommitId));
+    r.assertOK();
     Map<String, FileInfo> files = readContentFromJson(r, new TypeToken<Map<String, FileInfo>>() {});
     assertThat(files).containsKey(FILE_NAME);
 
     r = adminRestSession.getJsonAccept(urlRevisionFiles(changeId));
+    r.assertOK();
     files = readContentFromJson(r, new TypeToken<Map<String, FileInfo>>() {});
     assertThat(files).containsKey(FILE_NAME);
   }
@@ -1292,10 +1290,12 @@
     String editCommitId = edit.get().commit.commit;
 
     RestResponse r = adminRestSession.getJsonAccept(urlDiff(changeId, editCommitId, FILE_NAME));
+    r.assertOK();
     DiffInfo diff = readContentFromJson(r, DiffInfo.class);
     assertThat(diff.diffHeader.get(0)).contains(FILE_NAME);
 
     r = adminRestSession.getJsonAccept(urlDiff(changeId, FILE_NAME));
+    r.assertOK();
     diff = readContentFromJson(r, DiffInfo.class);
     assertThat(diff.diffHeader.get(0)).contains(FILE_NAME);
   }
diff --git a/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitByCherryPickOrRebaseAlwaysIT.java b/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitByCherryPickOrRebaseAlwaysIT.java
index 764854f..ed0fa43 100644
--- a/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitByCherryPickOrRebaseAlwaysIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitByCherryPickOrRebaseAlwaysIT.java
@@ -67,8 +67,7 @@
     RevCommit masterBranchTip =
         pushTo("refs/heads/master", ImmutableMap.of("master-content", "master-first-line\n"), base)
             .getCommit();
-    pushTo("refs/heads/stable", ImmutableMap.of("stable-content", "stable-first-line\n"), base)
-        .getCommit();
+    pushTo("refs/heads/stable", ImmutableMap.of("stable-content", "stable-first-line\n"), base);
     implicitMergeChangeId =
         pushTo(
                 "refs/for/stable",
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java
index c9607f5..42c239b 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java
@@ -418,7 +418,6 @@
     Project.NameKey config2Key =
         projectOperations.newProject().parent(configKey).submitType(getSubmitType()).create();
     grantPush(config2Key);
-    cloneProject(config2Key);
 
     subKey = projectOperations.newProject().parent(config2Key).submitType(getSubmitType()).create();
     grantPush(subKey);
@@ -734,8 +733,7 @@
     gApi.projects()
         .name(allProjects.get())
         .submitRequirement("Block-Submodule-Change")
-        .create(input)
-        .get();
+        .create(input);
   }
 
   private boolean getStatus(ChangeData cd) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/rest/RestApiServletIT.java b/javatests/com/google/gerrit/acceptance/rest/RestApiServletIT.java
index 0393f2b..94b83cb 100644
--- a/javatests/com/google/gerrit/acceptance/rest/RestApiServletIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/RestApiServletIT.java
@@ -473,13 +473,10 @@
     return change.getChange().notes().getRevision();
   }
 
-  private RestResponse assertRestResponseWithParameters(int status, String k, String v)
-      throws Exception {
+  private void assertRestResponseWithParameters(int status, String k, String v) throws Exception {
     RestResponse response =
         adminRestSession.getWithHeaders(ANY_REST_API + "?" + k + "=" + v, ACCEPT_STAR_HEADER);
     assertThat(response.getStatusCode()).isEqualTo(status);
-
-    return response;
   }
 
   private RestResponse prettyJsonRestResponse(String ppArgument, int ppValue) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
index 6a5441c..75f335a 100644
--- a/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
@@ -471,7 +471,10 @@
     RestApiCallHelper.execute(
         adminRestSession,
         CHANGE_EDIT_CREATE_ENDPOINTS,
-        () -> adminRestSession.delete("/changes/" + changeId + "/edit"),
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = adminRestSession.delete("/changes/" + changeId + "/edit");
+        },
         changeId,
         FILENAME);
   }
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java b/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
index cbc3f9d..a23b939 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
@@ -1835,7 +1835,8 @@
     setEmailStrategyForUser(EmailStrategy.ATTENTION_SET_ONLY);
 
     // Ensure emails that don't relate to changes are still sent.
-    gApi.accounts().id(user.id().get()).generateHttpPassword();
+    @SuppressWarnings("unused")
+    var unused = gApi.accounts().id(user.id().get()).generateHttpPassword();
     assertThat(sender.getMessages()).isNotEmpty();
   }
 
diff --git a/javatests/com/google/gerrit/acceptance/rest/config/FlushCacheIT.java b/javatests/com/google/gerrit/acceptance/rest/config/FlushCacheIT.java
index 164f683..03c17cf 100644
--- a/javatests/com/google/gerrit/acceptance/rest/config/FlushCacheIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/config/FlushCacheIT.java
@@ -33,7 +33,8 @@
   @Test
   public void flushCache() throws Exception {
     // access the admin group once so that it is loaded into the group cache
-    adminGroup();
+    @SuppressWarnings("unused")
+    var unused = adminGroup();
 
     RestResponse r = adminRestSession.get("/config/server/caches/groups_byname");
     CacheInfo result = newGson().fromJson(r.getReader(), CacheInfo.class);
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java b/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
index 59e23a9..9eb5ecd 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
@@ -351,7 +351,7 @@
   @GerritConfig(name = "gerrit.defaultBranch", value = "main")
   public void createProject_WhenDefaultBranchIsSet() throws Exception {
     String newProjectName = name("newProject");
-    gApi.projects().create(newProjectName).get();
+    gApi.projects().create(newProjectName);
     ImmutableMap<String, BranchInfo> branches = getProjectBranches(newProjectName);
     // HEAD symbolic ref is set to the default, but the actual ref is not created.
     assertThat(branches.keySet()).containsExactly("HEAD", "refs/meta/config");
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java b/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
index d8b0cb1..f7fa8d9 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
@@ -113,7 +113,9 @@
     RestResponse r =
         userRestSession.delete("/projects/" + project.get() + "/branches/" + testBranch.branch());
     r.assertNotFound();
-    branch(testBranch).get();
+
+    @SuppressWarnings("unused")
+    var unused = branch(testBranch).get();
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/DeleteLabelIT.java b/javatests/com/google/gerrit/acceptance/rest/project/DeleteLabelIT.java
index 491a0d5..6a8c9d8 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/DeleteLabelIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/DeleteLabelIT.java
@@ -120,6 +120,7 @@
     amendChange(changeId);
 
     // Assert no throws.
-    gApi.changes().id(changeId).get(DETAILED_LABELS);
+    @SuppressWarnings("unused")
+    var unused = gApi.changes().id(changeId).get(DETAILED_LABELS);
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/ListLabelsIT.java b/javatests/com/google/gerrit/acceptance/rest/project/ListLabelsIT.java
index 7a717d1..463f9cf 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/ListLabelsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/ListLabelsIT.java
@@ -192,7 +192,8 @@
     requestScopeOperations.setApiUser(user.id());
 
     // can list labels without inheritance
-    gApi.projects().name(project.get()).labels().get();
+    @SuppressWarnings("unused")
+    var unused = gApi.projects().name(project.get()).labels().get();
 
     // cannot list labels with inheritance
     AuthException thrown =
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java b/javatests/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java
index de9b579..0a13935 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java
@@ -350,7 +350,8 @@
     assertThat(info.state).isEqualTo(input.state);
 
     // Project is still accessible directly
-    gApi.projects().name(hidden.get()).get();
+    @SuppressWarnings("unused")
+    var unused = gApi.projects().name(hidden.get()).get();
 
     // Hidden project is not included in the list
     assertThatNameList(gApi.projects().list().get())
diff --git a/javatests/com/google/gerrit/acceptance/server/project/ReflogIT.java b/javatests/com/google/gerrit/acceptance/server/project/ReflogIT.java
index df668a5..9093412 100644
--- a/javatests/com/google/gerrit/acceptance/server/project/ReflogIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/project/ReflogIT.java
@@ -144,12 +144,16 @@
         .update();
 
     requestScopeOperations.setApiUser(user.id());
-    gApi.projects().name(project.get()).branch("master").reflog();
+
+    @SuppressWarnings("unused")
+    var unused = gApi.projects().name(project.get()).branch("master").reflog();
   }
 
   @Test
   public void adminUserIsAllowedToGetReflog() throws Exception {
     requestScopeOperations.setApiUser(admin.id());
-    gApi.projects().name(project.get()).branch("master").reflog();
+
+    @SuppressWarnings("unused")
+    var unused = gApi.projects().name(project.get()).branch("master").reflog();
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/ssh/CreateProjectIT.java b/javatests/com/google/gerrit/acceptance/ssh/CreateProjectIT.java
index 5429131..2b0b92f 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/CreateProjectIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/CreateProjectIT.java
@@ -31,7 +31,7 @@
   @Test
   public void withValidGroupName() throws Exception {
     String newGroupName = "newGroup";
-    adminRestSession.put("/groups/" + newGroupName);
+    adminRestSession.put("/groups/" + newGroupName).assertCreated();
     String newProjectName = "newProject";
     adminSshSession.exec(
         "gerrit create-project --branch master --owner " + newGroupName + " " + newProjectName);
@@ -43,7 +43,7 @@
   @Test
   public void withInvalidGroupName() throws Exception {
     String newGroupName = "newGroup";
-    adminRestSession.put("/groups/" + newGroupName);
+    adminRestSession.put("/groups/" + newGroupName).assertCreated();
     String wrongGroupName = "newG";
     String newProjectName = "newProject";
     adminSshSession.exec(
@@ -56,7 +56,7 @@
   @Test
   public void withDotGit() throws Exception {
     String newGroupName = "newGroup";
-    adminRestSession.put("/groups/" + newGroupName);
+    adminRestSession.put("/groups/" + newGroupName).assertCreated();
     String newProjectName = name("newProject");
     adminSshSession.exec(
         "gerrit create-project --branch master --owner "
@@ -73,7 +73,7 @@
   @Test
   public void withTrailingSlash() throws Exception {
     String newGroupName = "newGroup";
-    adminRestSession.put("/groups/" + newGroupName);
+    adminRestSession.put("/groups/" + newGroupName).assertCreated();
     String newProjectName = name("newProject");
     adminSshSession.exec(
         "gerrit create-project --branch master --owner "
diff --git a/javatests/com/google/gerrit/acceptance/ssh/CustomIndexIT.java b/javatests/com/google/gerrit/acceptance/ssh/CustomIndexIT.java
index fee413a..7fead5c 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/CustomIndexIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/CustomIndexIT.java
@@ -16,6 +16,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.index.IndexType;
 import com.google.gerrit.index.Schema;
 import com.google.gerrit.index.project.ProjectIndex;
@@ -34,7 +35,6 @@
 import com.google.inject.Inject;
 import com.google.inject.Module;
 import com.google.inject.assistedinject.Assisted;
-import java.util.Map;
 import org.eclipse.jgit.lib.Config;
 import org.junit.Test;
 
@@ -67,10 +67,11 @@
 class CustomIndexModule extends AbstractIndexModule {
 
   public static CustomIndexModule latestVersion(boolean secondary) {
-    return new CustomIndexModule(null, -1 /* direct executor */, secondary);
+    return new CustomIndexModule(/* singleVersions= */ null, -1 /* direct executor */, secondary);
   }
 
-  private CustomIndexModule(Map<String, Integer> singleVersions, int threads, boolean secondary) {
+  private CustomIndexModule(
+      ImmutableMap<String, Integer> singleVersions, int threads, boolean secondary) {
     super(singleVersions, threads, secondary);
   }
 
diff --git a/javatests/com/google/gerrit/acceptance/ssh/StreamEventsIT.java b/javatests/com/google/gerrit/acceptance/ssh/StreamEventsIT.java
index 2bfc072..8bc457b 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/StreamEventsIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/StreamEventsIT.java
@@ -194,7 +194,7 @@
     draftInput.message = reviewMessage;
     draftInput.path = path;
     ChangeApi changeApi = gApi.changes().id(change.getId().get());
-    changeApi.current().createDraft(draftInput).get();
+    changeApi.current().createDraft(draftInput);
   }
 
   private void publishDraftReviews() throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImplTest.java b/javatests/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImplTest.java
index 661802e..8e2dfdd 100644
--- a/javatests/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImplTest.java
+++ b/javatests/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImplTest.java
@@ -67,8 +67,11 @@
   @Test
   public void defaultName() throws Exception {
     Project.NameKey name = projectOperations.newProject().create();
+
     // check that the project was created (throws exception if not found.)
-    gApi.projects().name(name.get());
+    @SuppressWarnings("unused")
+    var unused = gApi.projects().name(name.get());
+
     Project.NameKey name2 = projectOperations.newProject().create();
     assertThat(name2).isNotEqualTo(name);
   }
diff --git a/javatests/com/google/gerrit/entities/PatchSetTest.java b/javatests/com/google/gerrit/entities/PatchSetTest.java
index 7e04fe8..e2718c5 100644
--- a/javatests/com/google/gerrit/entities/PatchSetTest.java
+++ b/javatests/com/google/gerrit/entities/PatchSetTest.java
@@ -65,7 +65,11 @@
 
   @Test
   public void testSplitGroups() {
-    assertRuntimeException(() -> splitGroups(null));
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = splitGroups(null);
+        });
     assertThat(splitGroups("")).containsExactly("");
     assertThat(splitGroups("abcd")).containsExactly("abcd");
     assertThat(splitGroups("ab,cd")).containsExactly("ab", "cd").inOrder();
@@ -76,8 +80,16 @@
 
   @Test
   public void testJoinGroups() {
-    assertRuntimeException(() -> joinGroups(null));
-    assertRuntimeException(() -> joinGroups(ImmutableList.of("a,", "b")));
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = joinGroups(null);
+        });
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = joinGroups(ImmutableList.of("a,", "b"));
+        });
     assertThat(joinGroups(ImmutableList.of(""))).isEqualTo("");
     assertThat(joinGroups(ImmutableList.of("abcd"))).isEqualTo("abcd");
     assertThat(joinGroups(ImmutableList.of("ab", "cd"))).isEqualTo("ab,cd");
@@ -126,7 +138,11 @@
   }
 
   private static void assertInvalidId(String str) {
-    assertRuntimeException(() -> PatchSet.Id.parse(str));
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = PatchSet.Id.parse(str);
+        });
   }
 
   private static void assertRuntimeException(Runnable runnable) {
diff --git a/javatests/com/google/gerrit/extensions/common/ChangeInfoDifferTest.java b/javatests/com/google/gerrit/extensions/common/ChangeInfoDifferTest.java
index 3704969..f8e7d80 100644
--- a/javatests/com/google/gerrit/extensions/common/ChangeInfoDifferTest.java
+++ b/javatests/com/google/gerrit/extensions/common/ChangeInfoDifferTest.java
@@ -584,7 +584,8 @@
 
   @Test
   public void getDiff_assertCanConstructAllChangeInfoReferences() throws Exception {
-    buildObjectWithFullFields(ChangeInfo.class);
+    @SuppressWarnings("unused")
+    var unused = buildObjectWithFullFields(ChangeInfo.class);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/git/ObjectIdsTest.java b/javatests/com/google/gerrit/git/ObjectIdsTest.java
index b254d6f..a011bba 100644
--- a/javatests/com/google/gerrit/git/ObjectIdsTest.java
+++ b/javatests/com/google/gerrit/git/ObjectIdsTest.java
@@ -41,7 +41,11 @@
 
   @Test
   public void abbreviateNameDefaultLength() throws Exception {
-    assertRuntimeException(() -> abbreviateName(null));
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = abbreviateName(null);
+        });
     assertThat(abbreviateName(ID)).isEqualTo("0000000");
     assertThat(abbreviateName(AMBIGUOUS_BLOB_ID)).isEqualTo(abbreviateName(ID));
     assertThat(abbreviateName(AMBIGUOUS_TREE_ID)).isEqualTo(abbreviateName(ID));
@@ -49,17 +53,37 @@
 
   @Test
   public void abbreviateNameCustomLength() throws Exception {
-    assertRuntimeException(() -> abbreviateName(null, 1));
-    assertRuntimeException(() -> abbreviateName(ID, -1));
-    assertRuntimeException(() -> abbreviateName(ID, 0));
-    assertRuntimeException(() -> abbreviateName(ID, 41));
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = abbreviateName(null, 1);
+        });
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = abbreviateName(ID, -1);
+        });
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = abbreviateName(ID, 0);
+        });
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = abbreviateName(ID, 41);
+        });
     assertThat(abbreviateName(ID, 5)).isEqualTo("00000");
     assertThat(abbreviateName(ID, 40)).isEqualTo(ID.name());
   }
 
   @Test
   public void abbreviateNameDefaultLengthWithReader() throws Exception {
-    assertRuntimeException(() -> abbreviateName(ID, null));
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = abbreviateName(ID, null);
+        });
 
     ObjectReader reader = newReaderWithAmbiguousIds();
     assertThat(abbreviateName(ID, reader)).isEqualTo("00000000001");
@@ -68,10 +92,26 @@
   @Test
   public void abbreviateNameCustomLengthWithReader() throws Exception {
     ObjectReader reader = newReaderWithAmbiguousIds();
-    assertRuntimeException(() -> abbreviateName(ID, -1, reader));
-    assertRuntimeException(() -> abbreviateName(ID, 0, reader));
-    assertRuntimeException(() -> abbreviateName(ID, 41, reader));
-    assertRuntimeException(() -> abbreviateName(ID, 5, null));
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = abbreviateName(ID, -1, reader);
+        });
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = abbreviateName(ID, 0, reader);
+        });
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = abbreviateName(ID, 41, reader);
+        });
+    assertRuntimeException(
+        () -> {
+          @SuppressWarnings("unused")
+          var unused = abbreviateName(ID, 5, null);
+        });
 
     String shortest = "00000000001";
     assertThat(abbreviateName(ID, 1, reader)).isEqualTo(shortest);
diff --git a/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java b/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
index bcd2785..1f6259f 100644
--- a/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
+++ b/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
@@ -28,6 +28,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterators;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.extensions.common.GpgKeyInfo.Status;
 import com.google.gerrit.gpg.testing.TestKey;
@@ -131,6 +132,7 @@
     return userFactory.create(id);
   }
 
+  @CanIgnoreReturnValue
   private IdentifiedUser reloadUser() {
     user = userFactory.create(userId);
     return user;
@@ -390,6 +392,7 @@
     accountsUpdateProvider.get().update("Add External IDs", id, u -> u.addExternalIds(newExtIds));
   }
 
+  @CanIgnoreReturnValue
   private TestKey add(TestKey k, IdentifiedUser user) throws Exception {
     add(k.getPublicKeyRing(), user);
     return k;
diff --git a/javatests/com/google/gerrit/gpg/PublicKeyCheckerTest.java b/javatests/com/google/gerrit/gpg/PublicKeyCheckerTest.java
index c360b2f..6faebab 100644
--- a/javatests/com/google/gerrit/gpg/PublicKeyCheckerTest.java
+++ b/javatests/com/google/gerrit/gpg/PublicKeyCheckerTest.java
@@ -37,6 +37,7 @@
 import static org.bouncycastle.openpgp.PGPSignature.DIRECT_KEY;
 import static org.junit.Assert.assertEquals;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.gpg.testing.TestKey;
 import java.time.Instant;
 import java.time.ZoneId;
@@ -298,6 +299,7 @@
     return new PublicKeyChecker().enableTrust(maxTrustDepth, fps).setStore(store);
   }
 
+  @CanIgnoreReturnValue
   private TestKey add(TestKey k) {
     store.add(k.getPublicKeyRing());
     return k;
diff --git a/javatests/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java b/javatests/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java
index 4932248..41b2b9f 100644
--- a/javatests/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java
+++ b/javatests/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
 import com.google.gerrit.server.plugins.Plugin;
@@ -76,6 +77,7 @@
    * <p>This method adds the given filter to all {@link AllRequestFilter.FilterProxy} instances
    * created by {@link #getFilterProxy()}.
    */
+  @CanIgnoreReturnValue
   private ReloadableRegistrationHandle<AllRequestFilter> addFilter(AllRequestFilter filter) {
     Key<AllRequestFilter> key = Key.get(AllRequestFilter.class);
     return filters.add("gerrit", key, Providers.of(filter));
diff --git a/javatests/com/google/gerrit/index/query/QueryBuilderTest.java b/javatests/com/google/gerrit/index/query/QueryBuilderTest.java
index eb3358d..42148da 100644
--- a/javatests/com/google/gerrit/index/query/QueryBuilderTest.java
+++ b/javatests/com/google/gerrit/index/query/QueryBuilderTest.java
@@ -114,7 +114,8 @@
 
   private static ThrowableSubject assertThatParseException(String query) {
     try {
-      new TestQueryBuilder().parse(query);
+      @SuppressWarnings("unused")
+      var unused = new TestQueryBuilder().parse(query);
       throw new AssertionError("expected QueryParseException for " + query);
     } catch (QueryParseException e) {
       return assertThat(e);
diff --git a/javatests/com/google/gerrit/metrics/dropwizard/DropWizardMetricMakerTest.java b/javatests/com/google/gerrit/metrics/dropwizard/DropWizardMetricMakerTest.java
index a50520ac..359f915 100644
--- a/javatests/com/google/gerrit/metrics/dropwizard/DropWizardMetricMakerTest.java
+++ b/javatests/com/google/gerrit/metrics/dropwizard/DropWizardMetricMakerTest.java
@@ -85,9 +85,13 @@
   public void shouldRequestForReservoirForNewTimer() throws Exception {
     when(reservoirConfigMock.reservoirType()).thenReturn(ReservoirType.ExponentiallyDecaying);
 
-    metrics.newTimer(
-        "foo",
-        new Description("foo description").setCumulative().setUnit(Description.Units.MILLISECONDS));
+    @SuppressWarnings("unused")
+    var unused =
+        metrics.newTimer(
+            "foo",
+            new Description("foo description")
+                .setCumulative()
+                .setUnit(Description.Units.MILLISECONDS));
 
     verify(reservoirConfigMock).reservoirType();
   }
diff --git a/javatests/com/google/gerrit/server/index/IndexedFieldTest.java b/javatests/com/google/gerrit/server/index/IndexedFieldTest.java
index 5029334..2c3584b 100644
--- a/javatests/com/google/gerrit/server/index/IndexedFieldTest.java
+++ b/javatests/com/google/gerrit/server/index/IndexedFieldTest.java
@@ -113,7 +113,10 @@
     IndexedField<TestIndexedData, StoredValue>.SearchSpec searchSpec = fieldToStoredValue.getKey();
     StoredValue storedValue = new FakeStoredValue(fieldToStoredValue.getValue());
     TestIndexedData testIndexedData = new TestIndexedData();
-    searchSpec.setIfPossible(testIndexedData, storedValue);
+
+    @SuppressWarnings("unused")
+    var unused = searchSpec.setIfPossible(testIndexedData, storedValue);
+
     assertThat(testIndexedData.getTestField()).isEqualTo(docValue);
   }
 
@@ -122,7 +125,10 @@
     Entities.Change changeProto = TestIndexedFields.createChangeProto(12345);
     StoredValue storedValue = new FakeStoredValue(Protos.toByteArray(changeProto));
     TestIndexedData testIndexedData = new TestIndexedData();
-    STORED_PROTO_FIELD_SPEC.setIfPossible(testIndexedData, storedValue);
+
+    @SuppressWarnings("unused")
+    var unused = STORED_PROTO_FIELD_SPEC.setIfPossible(testIndexedData, storedValue);
+
     assertThat(testIndexedData.getTestField()).isEqualTo(changeProto);
   }
 
@@ -137,7 +143,10 @@
                 .map(proto -> Protos.toByteArray(proto))
                 .collect(toImmutableList()));
     TestIndexedData testIndexedData = new TestIndexedData();
-    ITERABLE_STORED_PROTO_FIELD.setIfPossible(testIndexedData, storedValue);
+
+    @SuppressWarnings("unused")
+    var unused = ITERABLE_STORED_PROTO_FIELD.setIfPossible(testIndexedData, storedValue);
+
     assertThat(testIndexedData.getTestField()).isEqualTo(changeProtos);
   }
 
@@ -150,7 +159,10 @@
     IndexedField<TestIndexedData, StoredValue>.SearchSpec searchSpec = fieldToStoredValue.getKey();
     StoredValue storedValue = new FakeStoredValue(fieldToStoredValue.getValue(), /*isProto=*/ true);
     TestIndexedData testIndexedData = new TestIndexedData();
-    searchSpec.setIfPossible(testIndexedData, storedValue);
+
+    @SuppressWarnings("unused")
+    var unused = searchSpec.setIfPossible(testIndexedData, storedValue);
+
     assertThat(testIndexedData.getTestField()).isEqualTo(docValue);
   }
 
diff --git a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
index c374c05..8b17d94 100644
--- a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
@@ -186,6 +186,8 @@
             install(new GitModule());
 
             install(new DefaultUrlFormatterModule());
+            install(new NoteDbDraftCommentsModule());
+            install(new NoteDbStarredChangesModule());
             install(NoteDbModule.forTest());
             install(new DefaultRefLogIdentityProvider.Module());
             bind(AllUsersName.class).toProvider(AllUsersNameProvider.class);
diff --git a/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java b/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java
index 1c28690..d11c92b 100644
--- a/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java
+++ b/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java
@@ -132,24 +132,25 @@
             new FileEntity(fileName2, fileContent2 + "\nnew line here"));
     ObjectId newCommitId = createCommit(repo, oldCommitId, newFiles);
 
-    Repository repository = repoManager.openRepository(testProjectName);
-    ObjectReader objectReader = repository.newObjectReader();
-    RevWalk rw = new RevWalk(objectReader);
-    StoredConfig repoConfig = repository.getConfig();
+    try (Repository repository = repoManager.openRepository(testProjectName);
+        ObjectReader objectReader = repository.newObjectReader();
+        RevWalk rw = new RevWalk(objectReader)) {
+      StoredConfig repoConfig = repository.getConfig();
 
-    // This call loads modified files directly without going through the diff cache.
-    Map<String, ModifiedFile> modifiedFiles =
-        diffOperations.loadModifiedFiles(
-            testProjectName, newCommitId, oldCommitId, DiffOptions.DEFAULTS, rw, repoConfig);
+      // This call loads modified files directly without going through the diff cache.
+      Map<String, ModifiedFile> modifiedFiles =
+          diffOperations.loadModifiedFiles(
+              testProjectName, newCommitId, oldCommitId, rw, repoConfig);
 
-    assertThat(modifiedFiles)
-        .containsExactly(
-            fileName2,
-            ModifiedFile.builder()
-                .changeType(ChangeType.MODIFIED)
-                .oldPath(Optional.of(fileName2))
-                .newPath(Optional.of(fileName2))
-                .build());
+      assertThat(modifiedFiles)
+          .containsExactly(
+              fileName2,
+              ModifiedFile.builder()
+                  .changeType(ChangeType.MODIFIED)
+                  .oldPath(Optional.of(fileName2))
+                  .newPath(Optional.of(fileName2))
+                  .build());
+    }
   }
 
   @Test
@@ -163,26 +164,23 @@
         ImmutableList.of(new FileEntity(fileName1, "target", FileType.SYMLINK));
     ObjectId newCommitId = createCommit(repo, oldCommitId, newFiles);
 
-    Repository repository = repoManager.openRepository(testProjectName);
-    ObjectReader objectReader = repository.newObjectReader();
+    try (Repository repository = repoManager.openRepository(testProjectName);
+        ObjectReader objectReader = repository.newObjectReader();
+        RevWalk rw = new RevWalk(objectReader)) {
 
-    Map<String, ModifiedFile> modifiedFiles =
-        diffOperations.loadModifiedFiles(
-            testProjectName,
-            newCommitId,
-            oldCommitId,
-            DiffOptions.DEFAULTS,
-            new RevWalk(objectReader),
-            repository.getConfig());
+      Map<String, ModifiedFile> modifiedFiles =
+          diffOperations.loadModifiedFiles(
+              testProjectName, newCommitId, oldCommitId, rw, repository.getConfig());
 
-    assertThat(modifiedFiles)
-        .containsExactly(
-            fileName1,
-            ModifiedFile.builder()
-                .changeType(ChangeType.REWRITE)
-                .oldPath(Optional.empty())
-                .newPath(Optional.of(fileName1))
-                .build());
+      assertThat(modifiedFiles)
+          .containsExactly(
+              fileName1,
+              ModifiedFile.builder()
+                  .changeType(ChangeType.REWRITE)
+                  .oldPath(Optional.empty())
+                  .newPath(Optional.of(fileName1))
+                  .build());
+    }
   }
 
   @Test
@@ -198,24 +196,25 @@
             new FileEntity(fileName2, fileContent2 + "\nnew line here"));
     ObjectId newCommitId = createCommit(repo, oldCommitId, newFiles);
 
-    Repository repository = repoManager.openRepository(testProjectName);
-    ObjectReader objectReader = repository.newObjectReader();
-    RevWalk rw = new RevWalk(objectReader);
-    StoredConfig repoConfig = repository.getConfig();
+    try (Repository repository = repoManager.openRepository(testProjectName);
+        ObjectReader objectReader = repository.newObjectReader();
+        RevWalk rw = new RevWalk(objectReader)) {
+      StoredConfig repoConfig = repository.getConfig();
 
-    // This call loads modified files directly without going through the diff cache.
-    Map<String, ModifiedFile> modifiedFiles =
-        diffOperations.loadModifiedFilesAgainstParent(
-            testProjectName, newCommitId, /* parentNum=*/ 0, DiffOptions.DEFAULTS, rw, repoConfig);
+      // This call loads modified files directly without going through the diff cache.
+      Map<String, ModifiedFile> modifiedFiles =
+          diffOperations.loadModifiedFilesAgainstParent(
+              testProjectName, newCommitId, /* parentNum=*/ 0, rw, repoConfig);
 
-    assertThat(modifiedFiles)
-        .containsExactly(
-            fileName2,
-            ModifiedFile.builder()
-                .changeType(ChangeType.MODIFIED)
-                .oldPath(Optional.of(fileName2))
-                .newPath(Optional.of(fileName2))
-                .build());
+      assertThat(modifiedFiles)
+          .containsExactly(
+              fileName2,
+              ModifiedFile.builder()
+                  .changeType(ChangeType.MODIFIED)
+                  .oldPath(Optional.of(fileName2))
+                  .newPath(Optional.of(fileName2))
+                  .build());
+    }
   }
 
   static class FileEntity {
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index 7b69dcf..e7ce972 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -3889,8 +3889,8 @@
     for (int i = 0; i < expected.length; i++) {
       ids[i] = expected[i].id;
     }
-    QueryRequest queryRequest = newQuery(query.replaceAll("\\$\\{user}", viewedUser));
-    queryRequest.withStart(start);
+    QueryRequest queryRequest =
+        newQuery(query.replaceAll("\\$\\{user}", viewedUser)).withStart(start);
     return assertQueryByIds(queryRequest, ids);
   }
 
@@ -4660,7 +4660,8 @@
 
   protected ThrowableSubject assertThatQueryException(QueryRequest query) throws Exception {
     try {
-      query.get();
+      @SuppressWarnings("unused")
+      var unused = query.get();
       throw new AssertionError("expected BadRequestException for query: " + query);
     } catch (BadRequestException e) {
       return assertThat(e);
@@ -4669,7 +4670,8 @@
 
   protected ThrowableSubject assertThatAuthException(Object query) throws Exception {
     try {
-      newQuery(query).get();
+      @SuppressWarnings("unused")
+      var unused = newQuery(query).get();
       throw new AssertionError("expected AuthException for query: " + query);
     } catch (AuthException e) {
       return assertThat(e);
@@ -4690,14 +4692,14 @@
   }
 
   protected void createProject(Project.NameKey project) throws Exception {
-    gApi.projects().create(project.get()).get();
+    gApi.projects().create(project.get());
   }
 
   protected void createProject(Project.NameKey project, Project.NameKey parent) throws Exception {
     ProjectInput input = new ProjectInput();
     input.name = project.get();
     input.parent = parent.get();
-    gApi.projects().create(input).get();
+    gApi.projects().create(input);
   }
 
   protected QueryRequest newQuery(Object query) {
diff --git a/javatests/com/google/gerrit/server/query/change/FakeQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/FakeQueryChangesTest.java
index 6279e67..a86a7a6 100644
--- a/javatests/com/google/gerrit/server/query/change/FakeQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/FakeQueryChangesTest.java
@@ -85,7 +85,10 @@
 
     AbstractFakeIndex<?, ?, ?> idx =
         (AbstractFakeIndex<?, ?, ?>) changeIndexCollection.getSearchIndex();
-    newQuery("status:new").withLimit(5).get();
+
+    @SuppressWarnings("unused")
+    var unused = newQuery("status:new").withLimit(5).get();
+
     assertThatSearchQueryWasNotPaginated(idx.getQueryCount());
   }
 
@@ -114,7 +117,9 @@
     // 2 index searches are expected. The first index search will run with size 3 (i.e.
     // the configured query-limit+1), and then we will paginate to get the remaining
     // changes with the second index search.
-    newQuery("status:new").withNoLimit().get();
+    @SuppressWarnings("unused")
+    var unused = newQuery("status:new").withNoLimit().get();
+
     assertThatSearchQueryWasPaginated(idx.getQueryCount(), 2);
   }
 
@@ -122,8 +127,12 @@
   @UseClockStep
   public void noLimitQueryDoesNotPaginatesWithNonePaginationType() throws Exception {
     assumeTrue(PaginationType.NONE == getCurrentPaginationType());
+
     AbstractFakeIndex<?, ?, ?> idx = setupRepoWithFourChanges();
-    newQuery("status:new").withNoLimit().get();
+
+    @SuppressWarnings("unused")
+    var unused = newQuery("status:new").withNoLimit().get();
+
     assertThatSearchQueryWasNotPaginated(idx.getQueryCount());
   }
 
diff --git a/javatests/com/google/gerrit/server/query/change/LuceneQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/LuceneQueryChangesTest.java
index 7f88c72..987a87e 100644
--- a/javatests/com/google/gerrit/server/query/change/LuceneQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/LuceneQueryChangesTest.java
@@ -61,6 +61,23 @@
   }
 
   @Test
+  public void byChangeId() throws Exception {
+    Project.NameKey project = Project.nameKey("repo");
+    repo = createAndOpenProject(project);
+    RevCommit commit1 = repo.parseBody(repo.commit().message("foo_bar_foo").create());
+    Change change1 = insert(project, newChangeForCommit(repo, commit1));
+
+    assertQuery(String.format("change:%s", change1.getChangeId()), change1);
+    assertQuery(String.format("change:%s", change1.getId()), change1);
+    assertQuery(
+        String.format("change:%s~%s", change1.getProject(), change1.getChangeId()), change1);
+    assertQuery(
+        String.format(
+            "change:%s~%s~%s", change1.getProject(), change1.getDest().branch(), change1.getKey()),
+        change1);
+  }
+
+  @Test
   public void invalidQuery() throws Exception {
     BadRequestException thrown =
         assertThrows(BadRequestException.class, () -> newQuery("\\").get());
diff --git a/plugins/delete-project b/plugins/delete-project
index c9894f6..01a35c8 160000
--- a/plugins/delete-project
+++ b/plugins/delete-project
@@ -1 +1 @@
-Subproject commit c9894f60c6fa55bf4a93f6aaf9ea35f1e08f7486
+Subproject commit 01a35c85680bda3bb724f9bf0b266ad36c6dd0e9
diff --git a/plugins/replication b/plugins/replication
index 5e76935..f2bcb41 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit 5e76935f1c5b23cd849c68952e72a16563225ca5
+Subproject commit f2bcb4111b9597345b855c397754c3dbde626021
diff --git a/plugins/reviewnotes b/plugins/reviewnotes
index ebddab7..18c867b 160000
--- a/plugins/reviewnotes
+++ b/plugins/reviewnotes
@@ -1 +1 @@
-Subproject commit ebddab74f75316aa2cabb6697b8d97d73c97d8e0
+Subproject commit 18c867b6a957b3ddeb7a9e9789819fc60bdcd99a
diff --git a/plugins/webhooks b/plugins/webhooks
index 1dc0a71..192cb07 160000
--- a/plugins/webhooks
+++ b/plugins/webhooks
@@ -1 +1 @@
-Subproject commit 1dc0a718839f8872a59c189da7243ee77a4fe782
+Subproject commit 192cb079f4fcb93f307792913e9f8ee54d266306
diff --git a/polygerrit-ui/app/services/shortcuts/shortcuts-service.ts b/polygerrit-ui/app/services/shortcuts/shortcuts-service.ts
index db9d8fe..a352f68 100644
--- a/polygerrit-ui/app/services/shortcuts/shortcuts-service.ts
+++ b/polygerrit-ui/app/services/shortcuts/shortcuts-service.ts
@@ -175,6 +175,12 @@
       if (optPreventDefault) e.preventDefault();
       if (optPreventDefault) e.stopPropagation();
       this.reportTriggered(e);
+      if (shortcut.combo) {
+        // Do not reset immediately, otherwise other shortcut might be triggered.
+        setTimeout(() => {
+          this.comboKeyLastPressed = {};
+        });
+      }
       listener(e);
     };
     element.addEventListener('keydown', wrappedListener);
diff --git a/tools/BUILD b/tools/BUILD
index 182e4dc1..5f8783f 100644
--- a/tools/BUILD
+++ b/tools/BUILD
@@ -294,6 +294,7 @@
         "-Xep:MultipleUnaryOperatorsInMethodCall:ERROR",
         "-Xep:MustBeClosedChecker:ERROR",
         "-Xep:MutableConstantField:WARN",
+        "-Xep:MutableGuiceModule:ERROR",
         "-Xep:MutablePublicArray:ERROR",
         "-Xep:NCopiesOfChar:ERROR",
         "-Xep:NarrowingCompoundAssignment:ERROR",
diff --git a/tools/defs.bzl b/tools/defs.bzl
new file mode 100644
index 0000000..ff207b3
--- /dev/null
+++ b/tools/defs.bzl
@@ -0,0 +1,13 @@
+load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
+
+def gerrit_init():
+    """
+    Initialize the WORKSPACE for gerrit targets
+    """
+    protobuf_deps()
+
+    native.register_toolchains("//tools:error_prone_warnings_toolchain_java11_definition")
+
+    native.register_toolchains("//tools:error_prone_warnings_toolchain_java17_definition")
+
+    native.register_toolchains("//tools:error_prone_warnings_toolchain_java21_definition")
diff --git a/tools/deps.bzl b/tools/deps.bzl
index 571648e..cd5aafb 100644
--- a/tools/deps.bzl
+++ b/tools/deps.bzl
@@ -13,7 +13,7 @@
 AUTO_VALUE_GSON_VERSION = "1.3.1"
 PROLOG_VERS = "1.4.4"
 PROLOG_REPO = GERRIT
-GITILES_VERS = "1.3.0"
+GITILES_VERS = "1.4.0"
 GITILES_REPO = GERRIT
 
 # When updating Bouncy Castle, also update it in bazlets.
@@ -391,14 +391,14 @@
         artifact = "com.google.gitiles:blame-cache:" + GITILES_VERS,
         attach_source = False,
         repository = GITILES_REPO,
-        sha1 = "d0f5c98207648503b225501e84f529fa88651ebe",
+        sha1 = "005e9a8cfcfc15f232c796dbf1c8fb5499abff9c",
     )
 
     maven_jar(
         name = "gitiles-servlet",
         artifact = "com.google.gitiles:gitiles-servlet:" + GITILES_VERS,
         repository = GITILES_REPO,
-        sha1 = "b4ce5bc26e6a2674728d0d3c72c21e0b3443666d",
+        sha1 = "6fa0fe70154d09799ff7dc616727fec7342bb755",
     )
 
     maven_jar(
diff --git a/tools/nongoogle.bzl b/tools/nongoogle.bzl
index 2c2a53a..4482751 100644
--- a/tools/nongoogle.bzl
+++ b/tools/nongoogle.bzl
@@ -1,4 +1,6 @@
 load("//tools/bzl:maven_jar.bzl", "maven_jar")
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
 
 GUAVA_VERSION = "32.1.2-jre"
 
@@ -8,6 +10,42 @@
 
 GUAVA_DOC_URL = "https://google.github.io/guava/releases/" + GUAVA_VERSION + "/api/docs/"
 
+def archive_dependencies():
+    return [
+        {
+            "name": "com_google_protobuf",
+            "sha256": "9bd87b8280ef720d3240514f884e56a712f2218f0d693b48050c836028940a42",
+            "strip_prefix": "protobuf-25.1",
+            "urls": [
+                "https://github.com/protocolbuffers/protobuf/archive/v25.1.tar.gz",
+            ],
+        },
+        {
+            "name": "platforms",
+            "urls": [
+                "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz",
+                "https://github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz",
+            ],
+            "sha256": "3a561c99e7bdbe9173aa653fd579fe849f1d8d67395780ab4770b1f381431d51",
+        },
+        {
+            "name": "rules_java",
+            "urls": [
+                "https://github.com/bazelbuild/rules_java/releases/download/7.3.1/rules_java-7.3.1.tar.gz",
+            ],
+            "sha256": "4018e97c93f97680f1650ffd2a7530245b864ac543fd24fae8c02ba447cb2864",
+        },
+        {
+            "name": "ubuntu2204_jdk17",
+            "strip_prefix": "rbe_autoconfig-5.1.0",
+            "urls": [
+                "https://gerrit-bazel.storage.googleapis.com/rbe_autoconfig/v5.1.0.tar.gz",
+                "https://github.com/davido/rbe_autoconfig/releases/download/v5.1.0/v5.1.0.tar.gz",
+            ],
+            "sha256": "8ea82b81c9707e535ff93ef5349d11e55b2a23c62bcc3b0faaec052144aed87d",
+        },
+    ]
+
 def declare_nongoogle_deps():
     """loads dependencies that are not used at Google.
 
@@ -16,6 +54,11 @@
     enforced by //lib:nongoogle_test.
     """
 
+    for dependency in archive_dependencies():
+        params = {}
+        params.update(**dependency)
+        maybe(http_archive, params.pop("name"), **params)
+
     maven_jar(
         name = "log4j",
         artifact = "ch.qos.reload4j:reload4j:1.2.19",