Hamburger Cross Icon
Scala Project Guardrails - Lunar Policy for Devex Build And Ci

Scala Project Guardrails

Policy Beta Devex Build And Ci

Enforce Scala-specific project standards including build manifest presence, Scala version pinning, sbt version pinning, dependency lockfile commit, test source layout, and scalafmt configuration. Supports sbt, Mill, and Maven (via scala-maven-plugin).

Add scala to your lunar-config.yml:
uses: github://earthly/lunar-lib/policies/scala@v1.0.5

Included Guardrails

This policy includes 8 guardrails that enforce standards for your devex build and ci.

Guardrail

build-tool-manifest-exists

Ensures the project has a recognised Scala build manifest: build.sbt (sbt), build.sc (Mill), or pom.xml with the scala-maven-plugin. Required for any Scala project so that the build is reproducible and tooling-discoverable.

build.sbt build.sc pom.xml sbt mill manifest
View Guardrail
Guardrail

scala-version-pinned

Ensures the Scala compiler version is declared (scalaVersion := "..." in build.sbt, the equivalent in build.sc, or <scala.version> / <scala.binary.version> in pom.xml). Pinning the compiler version prevents drift between developers and CI.

scalaVersion scala compiler version pinning
View Guardrail
Guardrail

min-scala-version

Ensures the declared Scala compiler version meets the configured minimum (default: "2.12"). Reads .lang.scala.version (parsed from scalaVersion / <scala.version> / Mill def scalaVersion). Skips when the version is not detected — pair with scala-version-pinned if you want presence to be enforced too.

scalaVersion scala compiler version floor compatibility
View Guardrail
Guardrail

sbt-version-set

Ensures project/build.properties pins the sbt version (e.g. sbt.version=1.9.7) when sbt is the build tool. Skips for Mill-only and Maven-only projects.

sbt.version build.properties sbt
View Guardrail
Guardrail

min-sbt-version

Ensures the sbt version pinned in project/build.properties meets the configured minimum (default: "1.9"). Reads .lang.scala.sbt_version. Skips for Mill-only and Maven-only projects, and when the sbt version is not detected — pair with sbt-version-set if you want presence to be enforced too.

sbt.version build.properties sbt version floor compatibility
View Guardrail
Guardrail

dependencies-locked

Ensures dependencies are locked for reproducible builds — either via build.sbt.lock (sbt-lock plugin) or an equivalent Mill/Maven lock mechanism. Informational by default — most Scala projects do not lock dependencies, but doing so produces reproducible CI builds.

build.sbt.lock lockfile reproducibility sbt-lock
View Guardrail
Guardrail

test-module-exists

Ensures a src/test/scala directory (or a cross-version variant such as src/test/scala-2.13 / src/test/scala-3) exists with test sources. Skips on non-Scala projects.

src/test/scala scalatest munit testing test layout
View Guardrail
Guardrail

scalafmt-configured

Ensures .scalafmt.conf is committed at the repo root. scalafmt enforces consistent code formatting and is the de facto standard for Scala. Informational.

scalafmt formatting code style
View Guardrail

How Guardrails Fit into Lunar

Lunar guardrails define your engineering standards as code. They evaluate data collected by integrations and produce pass/fail checks with actionable feedback.

Policies support gradual enforcement—from silent scoring to blocking PRs or deployments—letting you roll out standards at your own pace without disrupting existing workflows.

Learn How Lunar Works
1
Integrations Gather Data
Collectors extract metadata from code, CI pipelines, tool outputs, and scans
2
{ } Centralized as JSON
All data merged into each component's unified metadata document
3
Guardrails Enforce Standards This Policy
Real-time feedback in PRs and AI workflows

Required Integrations

This policy evaluates data gathered by one or more of the following integration(s). Make sure to enable them in your lunar-config.yml.

Configuration

Configure this policy in your lunar-config.yml.

Inputs

Input Required Default Description
min_scala_version Optional 2.12 Minimum required Scala compiler version (e.g., "2.12", "2.13", "3.3.1"). Compared with semantic-version semantics — "2.13" matches 2.13.x and 3.x, but rejects 2.11.x.
min_sbt_version Optional 1.9 Minimum required sbt version (e.g., "1.9", "1.10.0"). Compared with semantic-version semantics. Skipped when the project does not use sbt.

Documentation

View on GitHub

Scala Project Guardrails

Enforce Scala-specific project standards including build manifest presence, version pinning, dependency locking, test layout, and scalafmt configuration.

Overview

This policy validates Scala projects against best practices for build configuration, version pinning, dependency reproducibility, testing conventions, and code formatting. All checks skip gracefully on non-Scala projects (i.e., .lang.scala missing). Supports sbt, Mill, and Maven (with scala-maven-plugin) build systems.

Policies

This plugin provides the following policies (use include to select a subset):

Policy Description Failure Meaning
build-tool-manifest-exists Validates build.sbt, build.sc, or pom.xml exists Project lacks a recognised Scala build manifest
scala-version-pinned Validates Scala compiler version is declared Missing scalaVersion declaration
min-scala-version Validates declared Scala version meets min_scala_version (default 2.12) Scala version below the configured minimum
sbt-version-set Validates project/build.properties pins sbt version Missing or empty sbt.version (sbt projects only)
min-sbt-version Validates pinned sbt version meets min_sbt_version (default 1.9) sbt version below the configured minimum (sbt projects only)
dependencies-locked Validates lockfile is present (sbt-lock or equivalent) No lockfile committed (informational)
test-module-exists Validates src/test/scala (or cross-version variant) exists No test sources detected
scalafmt-configured Validates .scalafmt.conf is committed scalafmt not configured (informational)

Required Data

This policy reads from the following Component JSON paths:

Path Type Provided By
.lang.scala object scala collector
.lang.scala.build_sbt_exists boolean scala collector
.lang.scala.build_sc_exists boolean scala collector
.lang.scala.pom_xml_exists boolean scala collector
.lang.scala.version string scala collector
.lang.scala.sbt_version string scala collector
.lang.scala.build_systems array scala collector
.lang.scala.lockfile_exists boolean scala collector
.lang.scala.test_directory_exists boolean scala collector
.lang.scala.scalafmt_configured boolean scala collector

Installation

Add to your lunar-config.yml:

policies:
  - uses: github://earthly/lunar-lib/policies/scala@main
    on: ["domain:your-domain"]  # replace with your own domain or tags
    enforcement: report-pr
    # include: [build-tool-manifest-exists, scala-version-pinned]  # Only run specific checks

Examples

Passing Example

{
  "lang": {
    "scala": {
      "build_sbt_exists": true,
      "build_properties_exists": true,
      "version": "2.13.12",
      "sbt_version": "1.9.7",
      "build_systems": ["sbt"],
      "lockfile_exists": true,
      "test_directory_exists": true,
      "scalafmt_configured": true
    }
  }
}

Failing Example

{
  "lang": {
    "scala": {
      "build_sbt_exists": false,
      "build_sc_exists": false,
      "pom_xml_exists": false,
      "version": "",
      "sbt_version": "",
      "build_systems": [],
      "lockfile_exists": false,
      "test_directory_exists": false,
      "scalafmt_configured": false
    }
  }
}

Failure messages:

  • "No Scala build manifest found. Add build.sbt (sbt), build.sc (Mill), or pom.xml with scala-maven-plugin."
  • "Scala compiler version not declared. Add 'scalaVersion := \"2.13.12\"' to build.sbt or set <scala.version> in pom.xml."
  • "Scala version 2.11.12 is below minimum 2.12. Update scalaVersion in build.sbt."
  • "sbt version not pinned. Create project/build.properties with 'sbt.version=1.9.7'."
  • "sbt version 1.6.2 is below minimum 1.9. Update project/build.properties."
  • "No dependency lockfile found. Run 'sbt lock' (with sbt-lock) or commit build.sbt.lock for reproducible builds."
  • "No test sources found. Create src/test/scala/ and add ScalaTest, MUnit, or Specs2 tests."
  • "scalafmt not configured. Add .scalafmt.conf at the repo root for consistent formatting."

Remediation

build-tool-manifest-exists

  1. For sbt: sbt new scala/scala-seed.g8 to scaffold a new project, or create build.sbt at the repo root
  2. For Mill: install Mill and create build.sc at the repo root
  3. For Maven: add pom.xml with the scala-maven-plugin plugin in <plugins>

scala-version-pinned

  1. In build.sbt, add at the top: scalaVersion := "2.13.12" (or your target version)
  2. In build.sc (Mill): set def scalaVersion = "2.13.12" on your module
  3. In pom.xml: set <scala.version>2.13.12</scala.version> and use it in the scala-maven-plugin config

min-scala-version

  1. Update scalaVersion in build.sbt (or the equivalent in build.sc / pom.xml) to a version at or above min_scala_version
  2. Run sbt clean test (or your equivalent) to verify the project still builds and passes tests on the new version
  3. For cross-builds, ensure every entry in crossScalaVersions also meets the minimum

sbt-version-set

  1. Create project/build.properties
  2. Add sbt.version=1.9.7 (or the desired version)
  3. Commit the file

min-sbt-version

  1. Update sbt.version in project/build.properties to a version at or above min_sbt_version
  2. Run sbt --version locally to confirm the launcher resolves the new version
  3. Re-run CI to confirm reproducibility

dependencies-locked

  1. Add the sbt-lock plugin to project/plugins.sbt:
    addSbtPlugin("software.purpledragon" % "sbt-dependency-lock" % "1.5.1")
    
  2. Run sbt lock to generate build.sbt.lock
  3. Commit build.sbt.lock to version control

test-module-exists

  1. Create src/test/scala/
  2. Add a test framework dependency (ScalaTest, MUnit, or Specs2)
  3. Add at least one test file under src/test/scala/

scalafmt-configured

  1. Add .scalafmt.conf at the repo root with at least:
    version = "3.7.17"
    runner.dialect = scala213
    
  2. Add the scalafmt plugin to project/plugins.sbt:
    addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2")
    
  3. Run sbt scalafmtAll to format the codebase

Open Source

This policy is open source and available on GitHub. Contribute improvements, report issues, or fork it for your own use.

View Repository

Ready to Automate Your Standards?

See how Lunar can turn your AGENTS.md, engineering wiki, compliance docs, or postmortem action items into automated guardrails with our 200+ built-in guardrails.

Works with any process
check AI agent rules & prompt files
check Post-mortem action items
check Security & compliance policies
check Testing & quality requirements
Automate Now
Paste your AGENTS.md or manual process doc and get guardrails in minutes
Book a Demo