Skip to content

ISS-3819: align the four lib-* build.sbt files; drop two dead settings - #23

Merged
mbryzek merged 1 commit into
mainfrom
i3819
Aug 19, 2026
Merged

ISS-3819: align the four lib-* build.sbt files; drop two dead settings#23
mbryzek merged 1 commit into
mainfrom
i3819

Conversation

@mbryzek

@mbryzek mbryzek commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Closes ISS-3819.

The four lib-* repos publish through four build.sbt files that are the same file four
times. This aligns the shared part and removes two lines that are dead in all four. No
published artifact changes: the generated POM is byte-identical before and after, in every
repo (see Verification).

What changed

  • -feature is now in all four. It was in lib-util and lib-cipher only. -Werror fails
    the build either way, so this is not a gate two repos lacked — it is what makes the failure
    name the construct, the file and the line instead of there was 1 feature warning; re-run with -feature. That lands where it is worth most: a ci run whose log is the only artifact
    and which nobody can re-run interactively.

  • One canonical option order, in all four: the two general flags, then the -W set
    alphabetically. The four lists held the same options in three different orders for no
    reason. The convention is stated in a comment above the list so a new option has one
    obvious place to go — an order nobody can state is one that drifts back.

  • ThisBuild / publishMavenStyle := true deleted from all four. sbt's lintUnused
    reported it on every single build of every repo (there's a key that's not used by any other settings/tasks). It is also the default, so removing it changes nothing:
    show publishMavenStyle still answers true in all four, and the POMs are unchanged.

  • resolvers += "scalaz-bintray" deleted from all four. Bintray was sunset in 2021 and
    the host now answers 404 for every path — measured, not assumed:

    https://dl.bintray.com/scalaz/releases/                                       -> 404
    https://dl.bintray.com/scalaz/releases/org/scalaz/scalaz-core_2.13/7.3.8/...   -> 404
    

    No lib depends on scalaz, and every dependency in all four resolves from Maven Central —
    verified by a green sbt update after the removal. This is one of the four lines ISS-3819
    enumerates as duplicated; it is dead in all four copies rather than merely repeated.

  • The groupId comment is now in all four, byte-identical. It records why
    ThisBuild / organization must not be removed (lib-util 0.0.34 published under a default
    groupId no consumer resolves). It was in lib-util and lib-cipher only — so the half of the
    fleet most likely to be edited by somebody who has not seen that incident was the half not
    warned about it.

  • lib-ai's -Wconf:src=.*/generated/.*:s now says why it is there (only, in lib-ai). It
    is justified divergence, and an unexplained divergence is indistinguishable from drift —
    which is the whole subject of this issue.

After this, the POM/publish block is byte-identical across all four repos modulo the repo
name in three URLs.

Alternatives considered

ISS-3819 proposes three homes for the shared block and asks for the decision to be a
decision. I chose neither shared home, and the three cheap fixes above are the whole
change. Reasoning, with what it is measured on:

(1) A published sbt AutoPlugin (sbt-bryzek-lib). Rejected. The issue's own cost
estimate — a new repo, a publish path, four version bumps, a bootstrapping order — is real,
and three things make it larger than it reads:

  • All four repos are on sbt 1.12.11, so the plugin is a Scala 2.12 artifact
    cross-published as _2.12_1.0. That is a different artifact shape from these Scala 3
    libraries, and the fleet's release machinery models the lib shape specifically —
    ocaml/test/test_maven_central.ml asserts artifact ids lib-util_2.13 / lib-util_3, and
    Agent::LibraryPin::LIBRARY_REPO is /\Alib-/, so a repo named sbt-bryzek-lib is
    invisible to the mechanism that tracks library pins in consumers.
  • dev release lib is interactive — it prompts and shells out to GPG, so no autonomous
    session can run it. Every future change to publish metadata would become: a human GPG
    session to publish the plugin, then four version bumps. Today it is four edits anyone can
    make.
  • lib-query/project/plugins.sbt records a planned sbt 2 migration ("Staying on sbt 1 until
    sbt-pgp / sbt-sonatype publish final sbt 2.x builds"). The plugin would need re-cross-building
    for sbt 2 at exactly the moment the four build.sbt files need one edit each anyway.

And it does not deliver what it promises. A published plugin converts content drift into
version drift across four addSbtPlugin pins, and the plugin's own build.sbt still
carries the publish block it exports — so four copies become two, not one.

(2) A devops template plus a drift check. Rejected, and the precedent it cites argues
against it. templates/ci/build.sh is a copy-and-adapt reference, not a synced artifact:
all four lib-*/ci/build.sh differ today, deliberately, each carrying its own reasoning about
why it has no database block. So a block-comparing drift check over build.sbt would be a
new mechanism rather than the existing one — and it would have to tolerate lib-ai's
-Wconf, its Test / javaOptions += "-Xmx4g" and its enablePlugins(PlayScala), which are
legitimate per-repo divergence. It buys detection at most of the cost of ownership.

(3) Deriving homepage / licenses / scmInfo from the repo name, so the block becomes
literally byte-identical. Rejected: it removes no lines, adds cleverness to a build file, and
the remaining variance is three URLs that cannot go wrong silently — a wrong repo name in
scmInfo is visible in the published POM.

What is actually at stake. The duplicated content is near-frozen config: publish metadata
changes when Sonatype changes, the -W set when Scala does, the ISS-356 testOptions block
once. The drift measured over that period cost diagnostics, not correctness. The part that
would cost correctness if it drifted — the shared dependency pins — is already held together
by the nightly dependency-upgrade-app runs (ISS-3469), which is why ISS-3819 records version
skew as absent. Paying for a fifth repo and a human-gated publish path to own 45 lines of
frozen config is a worse trade than four edits, and I would rather this be revisited when
something in the block actually changes than pre-empted now.

Verification

dev agent build -- sbt "show publishMavenStyle" "show scalacOptions" update Test/compile test makePom,
run in each of the four repos. Real output is in the PR checks and was pasted into the issue.

The load-bearing check is that publishing is unaffected: the POM generated by makePom
before the change was saved, and diffed against the POM generated after. Empty in all four —
which is the whole test of "these settings were dead or default".

diff <baseline pom> <post-change pom>     # empty, all four repos
show publishMavenStyle                    # true, all four repos, after the line was deleted
sbt update                                # green, all four, after the resolver was deleted

Decisions & assumptions

  • Deleted publishMavenStyle rather than adding it to Global / excludeLintKeys. The POM
    diff is the evidence it is redundant; suppressing the warning for a setting that does
    nothing keeps the line and loses the signal.
  • Removing the dead bintray resolver goes beyond the three items ISS-3819 lists, but the
    resolver is one of the duplicated lines the issue enumerates and it is dead in every copy.
    It is verified by sbt update rather than assumed.
  • Chose alphabetical-after-the-general-flags for the option order. No order was better; the
    one that stops drift recurring is the one written down.
  • lib-ai keeps -Wconf, Test / javaOptions += "-Xmx4g" and enablePlugins(PlayScala)
    ISS-3819 names these as justified divergence and they are untouched.
  • Config-only, no published artifact change, so no library release and no consumer bump.

One change across four repos, one behaviour, reviewed together:
lib-util#21, lib-query#23, lib-cipher#23, lib-ai#53.

- `-feature` in all four repos, so a `-Werror` failure names the construct, the
  file and the line instead of "re-run with -feature" in a `ci` log nobody can
  re-run interactively.
- One canonical scalac option order, stated in a comment so a new option has one
  obvious place to go.
- Delete `ThisBuild / publishMavenStyle := true`: it is sbt's default and
  `lintUnused` reported it as unused on every build. `show publishMavenStyle`
  still answers true and the generated POM is byte-identical.
- Delete the `scalaz-bintray` resolver: Bintray was sunset in 2021 and the host
  answers 404 for every path. No lib depends on scalaz and `sbt update` is green
  without it.
- The groupId comment, byte-identical in all four, so the repos most likely to be
  edited by somebody who has not seen lib-util 0.0.34 are warned too.
@mbryzek
mbryzek marked this pull request as ready for review August 19, 2026 07:02
@mbryzek

mbryzek commented Aug 19, 2026

Copy link
Copy Markdown
Owner Author

@mbryzek
mbryzek merged commit 59aaba6 into main Aug 19, 2026
2 checks passed
@mbryzek
mbryzek deleted the i3819 branch August 19, 2026 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant