Brown Bag: Service Lint

Walkthrough of Service Lint, a code-quality and release-readiness linting tool that replaces the retired Ready Check. The tool was built as a Java Maven project with a focus on extensibility, covering release-readiness checks across multiple services and contracts.

TL;DR

Service Lint replaces Ready Check. Ready Check was a Ruby script that ensured code was check-in/release ready (changelog entries, version consistency, etc.). After retirement, missing these small details became the #1 peer-review issue.

Rewrite from Ruby → Java as a standard multi-module Maven project: * Rules module (rule definitions) * Maven plugin module (build integration) * Command-line jar module (standalone execution)

Each rule is self-contained; adding/changing rules won’t break others.

~15 rules implemented: base image, changelog, dependencies, deployment images, SRVDD template version, Dynatrace labels, Maven Tiles, parent/pom version consistency, Swagger contract version, and self-version checks.

Two run modes: * Maven plugin (goal service-lint:check) where errors fail the build * Command-line jar against any branch/repo

Version data is pulled from multiple live sources: SRVDD (via git clone/pull of code repo), and dependency versions (via Maven dependency plugin → Nexus).

Adoption is currently opt-in per product owner (add plugin config to pom). Consensus: should become a standard tool, but per-environment rule control needs leadership decision before implementation.

What It Is / Why It Exists

Ready Check was a Ruby script ensuring code was ready to check in/release. It caught easy-to-overlook details like missing changelog entries — easy to forget across many services with many moving parts.

After Ready Check was retired, its absence became a significant pain point. The missing checks became the #1 category of peer-review comments.

Service Lint was written to restore this capability with better architecture and extensibility.

Architecture

Simple Java project with standard Maven multi-module layout:

  • Rules module — rule definitions

  • Maven plugin module — Maven integration

  • Command-line jar module — standalone CLI

Design philosophy: Make it trivial for anyone to add new rules, since many projects and contracts may have contract-specific rules.

Each rule is self-contained — change or add a rule without touching others.

Contrast with Ready Check: One giant imperative Ruby file that was hard to extend without breaking something.

Rule Model

Each rule extends an abstract Rule class with two methods:

shouldExecute()

Returns true/false. The rule runs only if it is both enabled AND shouldExecute() returns true.

Use cases:

  • Single-module project with no Swagger/client → skip Swagger version and client rules

  • Contract-scoped rules → self-gate to only applicable components (e.g., rules specific to a particular contract)

Inside shouldExecute() you can inspect files or values to decide whether the rule applies.

apply()

Contains the rule logic; returns a list of RuleViolation objects.

Violation severity: info, warning, or error. If there’s an error and Service Lint is wired into Maven, it fails the build.

Key difference from Ready Check: shouldExecute() lets rules self-gate based on project shape or contract, avoiding hard-coded logic that breaks with project diversity.

There’s also a utility class that knows whether Service Lint is running as a command-line tool vs. inside Maven for future sandbox/staging tweaks.

Rules Implemented

Approximately 15 rules ask questions about your code and build state:

  • AppDynamics base-image rule — if still using an AppD base image, emit error and fail build

  • Base image version rule — connects with credentials, pulls latest base image, verifies yours is current

  • Changelog version rule — if pom version (e.g., service bumped to 1.11.0) has no matching changelog entry, error

  • Dependency updates rule — checks for available dependency updates; tries to ignore mobile-framework-managed versions so new hires aren’t pushed to override framework versions

  • Deployment image version rule — if pom has new version, verifies service was built and Kubernetes files updated; catches PR version bumps without corresponding kubernetes/ directory updates

  • SRVDD/SD version rule — pulls start-documents repo (git clone/pull), checks whether service documentation template version is out of date. Warning only (awareness, not a blocker)

  • Dynatrace label rule — checks that Dynatrace labels in deployment YAML match and flags if missing. Labels are per-contract, not global

  • Maven Tiles version rule — checks for latest Maven Tiles version

  • Parent version consistency rule — ensures mobile-framework version is consistent everywhere; client/database submodules often drift behind

  • Pom version rule — checks service/component version matches across parent and submodules. Special case: submodules ending in -client match service name (e.g., mobile-facility-client) and only check major.minor (not patch) version

  • Service Lint version rule — checks whether your Service Lint version is out of date (awareness only)

  • Swagger contract version rule — ensures Swagger version (client dependency) is latest

Behavior note: Rules are verbose — if something is missing or can’t be found, they tell you.

Configuration / Controlling Rules

Three ways to disable rules:

  • Drop service-lint-config.yaml into component root directory

  • Pass a YAML file into command-line jar

  • Specify disabled rules in Maven plugin configuration (coming soon)

Demo Results

Artificially broken service generated from archetype:

  • Maven run: flags SRVDD out of date, service.yaml problems, AppD image, broken Dynatrace labels, incorrect deployment images, out-of-date base image, Tiles updates, dependency updates — comprehensive output

  • Command-line run against real feature branch: clean except Service Lint version 1.0.0 vs 1.0.1 available; otherwise all versions correct/up to date

Output verbosity: Output is noisy. As feature development wraps up, teams will want to reduce build-log output. A story for output reduction is in the backlog.

Integration Questions and Answers

Code Repo Access / Credentials

Q: Does Service Lint pull anything from the code repo directly (credential/Jenkins implications)?

A: Only the SRVDD version rule pulls from code repo (start-documents clone/pull). That rule probably shouldn’t run in sandbox/staging Jenkins builds — it’s warning-only and Jenkins cares about build-failing errors.

Similar to document-generation steps that are disabled in Jenkins due to missing credentials — expect trial and error turning rules off once live in Jenkins.

Build Lifecycle Integration

Q: Plan to integrate into core build (Maven verify/install) and where in lifecycle?

A: Yes, it’ll be part of builds for any product owner who wants it (add plugin config). Exact lifecycle phase is TBD.

Recommendation: run it last, alongside SpotBugs/PMD/Checkstyle, since the build is already noisy.

Version Source: Code Repo vs Nexus

Q: Where does version data come from?

A: Both. SRVDD → code repo (git clone, or pull if already present). Dependency checks (mobile-framework, Tiles) → Maven dependency plugin → Nexus.

Also building a rule to check dev-dependencies.yaml for dependent services.

Real failure mode: A version can exist in code repo but not yet deployed to Nexus, which could fail builds while waiting on Nexus publish.

Per-Environment Rule Control

Q: Need for rule groups/profiles per environment?

A: Suggestion is to define profiles (e.g., default/local vs. Jenkins/remote-build) that turn rule sets on/off with overlap, instead of pure include/exclude.

Include/exclude still matters for per-project control.

Recommendation: Before implementing profile logic, an offline conversation is needed on how to handle profiles (local vs. Jenkins, maybe sandbox vs. SQA) so implementation doesn’t need ripping out later.

This should be discussed in the VA dev channel.

Mandatory vs. Opt-In

Q: Should Service Lint be mandatory across all repos?

A: Currently stays per-product-owner opt-in. Standardizing across all repos is a leadership decision to be made offline.

Consensus: longer-term, it should be a standard tool in every repo.

Known Issues

  • Bug affecting projects with starters — needs investigation and fix

Why This Is in the Knowledge Base

Service Lint is the replacement for Ready Check and is on track to become a release-readiness gate in the Maven/Jenkins build pipeline across services.

Relevant to release reliability:

  • Can fail builds on errors (AppD base image, changelog, deployment/K8s drift, Dynatrace labels)

  • Pulls version truth from both code repo and Nexus (build-fragility risk if Nexus lags)

  • Per-environment rule control affects what runs in Jenkins vs. local

Worth tracking adoption, whether it becomes mandatory, and how per-environment profiles are handled.