# Upgrade Deps

> Upgrade Gradle dependencies and Gradle wrapper version

- Skill: `line/upgrade-deps` (Agent Skill)
- Install (CLI): `npx skillmds@latest add line/upgrade-deps`
- Raw SKILL.md: https://api.skillmd.com/api/skills/line/upgrade-deps/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: line (https://skillmd.com/u/line)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/line/upgrade-deps

---


# Dependency Upgrade Workflow

This skill performs a full Gradle dependency upgrade for the Armeria project step by step.

## Background: Minimum Java Version Per Module

Armeria is a multi-module project with different minimum Java version requirements.
Before upgrading a dependency, always verify that the new version supports the minimum
Java version required by the modules that use it.

| Java Version | Modules |
|-------------|---------|
| **8**  | `core`, `brave5`, `brave6`, `eureka`, `grpc`, `grpc-kotlin`, `graphql-protocol`, `jetty9`, `junit4`, `junit5`, `kafka`, `kotlin`, `logback`, `logback12`, `logback13`, `micrometer-context`, `oauth2`, `prometheus1`, `protobuf`, `reactor3`, `resteasy`, `retrofit2`, `rxjava2`, `rxjava3`, `sangria`, `scala*`, `spring:boot2-*`, `dropwizard2`, `thrift0.9`–`thrift0.17`, `tomcat8`, `tomcat9`, `xds`, `zookeeper3`, `saml`, `bucket4j`, `consul`, `nacos` |
| **11** | `athenz`, `graphql`, `jetty10`, `jetty11`, `kubernetes`, `logback14`, `thrift0.18`–`thrift0.22`, `tomcat10` |
| **17** | `ai:mcp`, `jetty12`, `resilience4j2`, `spring:boot3-*`, `spring:spring6`, `spring:boot4-*`, `spring:spring7` |

When in doubt, check `settings.gradle` for the `java`, `java11`, or `java17` flag on each subproject.

**The table above lists published modules only.** Integration-test (`:it:*`) and example (`:examples:*`)
modules carry their own flags in `settings.gradle` and are frequently `java17` already. A dependency
consumed *only* by those modules is not held back by the Java 8 baseline at all — always resolve the
actual consumer before assuming a Java constraint applies.

## Step 1: Run dependencyUpdates

```
./gradlew dependencyUpdates --no-parallel
```

The report is saved to `build/dependencyUpdates/report.txt`.

## Step 2: Parse the Report

Read `build/dependencyUpdates/report.txt` to identify all outdated dependencies.
For each dependency, note the current version and the available latest version.

If a version looks ambiguous (unexpected format, major version bump, unusual naming),
verify on Maven Central before proceeding:
  https://central.sonatype.com/artifact/{groupId}/{artifactId}

## Step 3: Check Skip Hints and Java Version Compatibility

Before upgrading any dependency, check `dependencies.toml` for a comment directly above
its version entry. Many pinned versions have an explicit reason, for example:

```toml
# Don't upgrade Caffeine to 3.x that requires Java 11.
caffeine = "2.9.3"

# Upgrade once https://github.com/ronmamo/reflections/issues/279 is fixed.
reflections = "0.9.11"

# Ensure that we use the same ZooKeeper version as what Curator depends on.
zookeeper = "3.9.3"
```

### Step 3.1: Validate the comment before trusting it

A hold comment is a claim about this repository, and claims go stale. **Never treat a comment as
proof — re-derive its reason every upgrade.** For each held entry:

1. Find the aliases for the version key in the `[libraries.*]` / `[plugins]` sections.
2. Grep the build scripts for each alias accessor (`libs.foo.bar` for alias `foo-bar`):
   `git grep -n 'libs\.foo\.bar' -- '*.gradle' '*.gradle.kts'`
3. Map each hit's build file to its project, and read that project's flags in `settings.gradle`.
4. Compare the *consumer's* Java level against the new version's requirement — **not** the library's
   requirement in isolation. "Library X requires Java 17" is not a blocker when every consumer is
   already `java17`.

If the reason no longer holds, **remove the comment and upgrade**. If it still holds, keep both.

Two comments were found stale this way (`dgs` and `graphql-kotlin`, both consumed only by `java17`
modules), so treat this step as mandatory rather than a spot check.

### Step 3.2: Never write a hold reason you have not verified

When you add a comment, the reason must be something you confirmed, with the evidence to hand:

- **Java constraint** — confirmed against the consumer module's flag, per Step 3.1.
- **Runtime/API breakage** — confirmed by actually building and running the affected module's tests,
  and the comment names the concrete blocker (e.g. `# Don't upgrade graphql-kotlin to 10.x that
  migrated to Jackson 3`), not a vague "major upgrade deferred".
- **Version-sync constraint** — confirmed from the other project's POM *and* from this repo's history
  (`git log -p -- dependencies.toml`). Do not invent a sync rule: check whether the two versions have
  ever actually moved independently before claiming they must move together.

A plausible-sounding reason that nobody verified is worse than no comment, because the next upgrade
will trust it.

If no comment exists, proceed with the Java version compatibility check:
1. Find which modules use this dependency in `dependencies.toml`
2. Determine the minimum Java version required by those modules (see table above)
3. Check the new library version's minimum Java requirement (Maven Central / release notes)
4. If the library's required Java > module's minimum Java → **skip the upgrade** and add a
   comment above the version entry explaining why (e.g. `# X.Y requires Java 11`)
5. If compatible → proceed with the upgrade

## Step 4: Update dependencies.toml

Edit the `[versions]` section in `dependencies.toml` to update the version strings.
The file is located at the root of the repository: `dependencies.toml`.

## Step 5: Cross-check Updated Versions

After editing `dependencies.toml`, re-read the full diff (`git diff dependencies.toml`) and
cross-check every changed entry against the `dependencyUpdates` report:

1. **No entry was accidentally skipped** — compare the report's "The following dependencies
   have later milestone versions" list against your edits. If a dependency appears in the
   report but not in the diff, either upgrade it or document why it was skipped.
2. **Versions match the report** — confirm each new version in the diff matches the latest
   version from the report, not a typo or intermediate version.
3. **Pinned-version comments were respected** — verify you did not upgrade a dependency whose
   comment says to skip it, and that you did not remove or contradict an existing comment.
4. **Linked-version constraints are satisfied** — some dependencies must stay in sync with
   others (e.g. ZooKeeper with Curator, Protobuf with gRPC). Read the comments above those
   entries and verify the constraint still holds after the upgrade.

## Step 6: Upgrade Gradle Wrapper

Check the latest stable Gradle release at https://gradle.org/releases/ and update
`gradle/wrapper/gradle-wrapper.properties`:

```properties
distributionUrl=https\://services.gradle.org/distributions/gradle-X.Y.Z-all.zip
```

## Step 7: Verify the Build

Run the full build including tests to catch both compilation errors and runtime regressions:

```
./gradlew build --no-daemon
```

If there are compilation errors, API breaking changes, or test failures caused by the upgrade,
fix them before proceeding.

## Step 8: Commit

Create a commit with the **exact** message format below. Follow it strictly — do not add extra
sections, reorder bullets, or change the structure:

```
Update dependencies

- {library-name} {old-version} -> {new-version}
- {library-name} {old-version} -> {new-version}
- Build
   - {library-name} {old-version} -> {new-version}
   - {library-name} {old-version} -> {new-version}
```

Rules:
- Each production dependency (api/implementation scope) gets one bullet: `- {name} {old} -> {new}`
- The `- Build` bullet groups build-only dependencies (testImplementation, annotationProcessor,
  relocated libs, non-transitive deps); nest them as sub-bullets with 3-space indent
- Use the library's official name if one exists (e.g. `gRPC-Java`, `Jackson`, `Netty`, `Kotlin`,
  `Reactor`, `Logback`, `Micrometer`); otherwise use the key name as-is from `dependencies.toml`
- Sort entries **alphabetically (A → Z)** within each section
- If no build-only deps were upgraded, omit the `- Build` section entirely
- If any dependencies were **not upgraded** (due to Java version constraints, pinned-version
  comments, or linked-version constraints), list them under a `- Unupdated` section with the
  reason. This helps reviewers know which upgrades were intentionally skipped.

Example:
```
Update dependencies

- gRPC-Java 1.63.0 -> 1.64.0
- Jackson 2.17.0 -> 2.18.0
- Build
   - checkstyle 10.14.0 -> 10.17.0
   - ErrorProne 2.27.0 -> 2.28.0
- Unupdated
   - Caffeine 2.9.3 -> 3.2.0 (requires Java 11)
   - ZooKeeper 3.9.3 (pinned to Curator's version)
```

