Index

zipx generates GitHub Actions from your sbt build. You keep writing build.sbt. zipx writes the workflow, so you do not maintain a second copy in YAML.

Day one is Aggregate: parallel Verify (test, fmt, workflow-check, advisories) and a publish job on a version tag. Add the plugin, run zipxWorkflowGenerate, commit, open a PR. zipxWorkflowCheck fails the PR if you forgot to regenerate. Versions live in a ZipxVersions catalog you extend (Lib / Plugin / Pin / Action inbound vals, no second list); drop MyVersions.settings in build.sbt. Multi-artifact repos add outbound Ship / ShipGroup rows (Independent versions); zipx itself is one ShipGroup released from zipx-release.yml.

Later pages cover extra jobs (Graph, docker, deploy), packs (Central, Pages, AWS), and the local bump loop. Skip them until you need them. CI for a busy monorepo is the one to read when a large repo's CI turns slow or blocks merges. Extending Versions is for sbt plugins that sit on zipx (splice, a company catalog). If you already maintain painful CI YAML, Why zipx is the recovery story.

Guide: Why zipx → Quick start → Versions → Independent versions → Snapshots and releases → Extending Versions → Execution modes → CI for a busy monorepo → Matrix collapse → Capabilities → Custom capabilities → Composing sbt commands → Shell and steps → Verify → Affected → Caching → Remote cache for teams → From Bazel → Action pins → Dependency updates → Pin feeds → Docker and deploy → Job conditions → Validation → Packs → Settings.

Install

// project/plugins.sbt
addSbtPlugin("rocks.earlyeffect" % "sbt-zipx" % "0.22.2")

Generate & check

sbt zipxWorkflowGenerate
git add .github/workflows/ci.yml .github/actions/
sbt zipxWorkflowCheck   # fails CI when the committed YAML drifts

Versions catalog

// project/ZipxVersions.scala
import zipx.*
object MyVersions extends ZipxVersions:
  val sbt   = SbtVersion("2.1.0-RC1")
  val scala = ScalaVersion("3.9.0")
  val zio   = Lib("dev.zio", "zio", "2.1.26")
  val slf4j = Lib("org.slf4j", "slf4j-simple", "2.0.18").java
  def libraries = library(zio)
  def service   = library(zio, slf4j)

// build.sbt
MyVersions.settings
lazy val lib     = project.settings(MyVersions.libraries)
lazy val service = project.settings(MyVersions.service)

Action pins (optional)

# Action vals in ZipxVersions; see Action pins docs
sbt "zipxActionUpdate yes"
sbt reload
sbt zipxWorkflowGenerate

Documentation

Continue with: