Skip to main content

Templates & Inheritance

Templates in bleep reduce duplication by allowing projects to inherit common configuration.

Why Templates?

Consider a build with multiple projects sharing the same Scala version and compiler options:

# Without templates - lots of repetition
projects:
core:
scala:
version: 3.8.3
options: -deprecation -feature

app:
scala:
version: 3.8.3
options: -deprecation -feature
dependsOn: core

utils:
scala:
version: 3.8.3
options: -deprecation -feature

With templates:

# With templates - configuration in one place
templates:
common:
scala:
version: 3.8.3
options: -deprecation -feature

projects:
core:
extends: common

app:
extends: common
dependsOn: core

utils:
extends: common

Defining Templates

Templates are defined in the templates: section:

templates:
template-name:
# Any project configuration can go here
scala:
version: 3.8.3
dependencies:
- com.lihaoyi::fansi:0.5.0

Using Templates

Projects reference templates with extends::

projects:
myapp:
extends: template-name

Multiple templates:

projects:
myapp:
extends:
- common
- with-logging

Templates are applied in order, with later templates overriding earlier ones.

Template Inheritance

Templates can extend other templates:

templates:
base:
scala:
version: 3.8.3

with-testing:
extends: base
dependencies:
- org.scalameta::munit:1.0.0

with-logging:
extends: base
dependencies:
- com.typesafe.scala-logging::scala-logging:3.9.5

Override Behavior

When a project extends a template, values are merged:

Scalars (strings, numbers)

Project values override template values:

templates:
common:
scala:
version: 3.8.3

projects:
legacy:
extends: common
scala:
version: 2.13.12 # Overrides 3.8.3

Lists (dependencies, sources)

Lists are merged by default:

templates:
common:
dependencies:
- com.lihaoyi::fansi:0.5.0

projects:
app:
extends: common
dependencies:
- org.http4s::http4s-core:0.23.23
# Final dependencies: fansi + http4s-core

Objects (nested config)

Objects are recursively merged:

templates:
common:
scala:
version: 3.8.3
options: -deprecation

projects:
app:
extends: common
scala:
options: -feature # Replaces options, keeps version

Common Template Patterns

Scala Version Templates

templates:
scala-3:
scala:
version: 3.8.3

scala-2.13:
scala:
version: 2.13.12

Test Project Template

templates:
test:
isTestProject: true
dependencies:
- org.scalameta::munit:1.0.0

projects:
app-test:
extends: test
dependsOn: app

Platform Templates

templates:
jvm:
platform:
name: jvm

js:
platform:
name: js
jsVersion: 1.14.0

native:
platform:
name: native
nativeVersion: 0.4.16

Automatic Template Generation

Bleep can analyze your build and suggest templates:

bleep build templates-generate-new

This identifies common patterns and proposes templates to reduce duplication.

Reapplying Templates

After editing templates, you can redistribute configuration:

bleep build templates-reapply

This recalculates what should be in templates vs projects.

Viewing Resolved Configuration

To see the final configuration after template resolution:

bleep build show

This shows each project with all inherited values expanded.

Best Practices

  1. Name templates descriptively - template-scala-3 is clearer than t1
  2. Keep templates focused - One purpose per template
  3. Don't over-abstract - Some duplication is okay
  4. Document complex inheritance - Add comments explaining template hierarchies