Skip to content

Plan next release #2198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
SethTisue opened this issue Mar 30, 2021 · 58 comments
Closed

Plan next release #2198

SethTisue opened this issue Mar 30, 2021 · 58 comments

Comments

@SethTisue
Copy link
Member

SethTisue commented Mar 30, 2021

A lot of PRs have now been merged since 3.3.3.

I was thinking we might do 3.4.0-RC1 first, then 3.4.0? That's just a suggestion; @hvesalai and @nafg, you can handle this as you see fit. I can help pull publishing levers when the time comes. (I have no opinion about timing.)

One question that came up over at #1496 is binary compatibility. I enabled MiMa in the repo with the idea that at minimum, we would probably like to be notified by CI when something isn't binary compatible.

I have no position on whether the next version should be binary compatible or not. By semantic versioning (which I do suggest we follow), a 3.4.0 version should be backwards binary compatible. But if we call it 4.0.0 instead, then we're completely free to break bincompat.

@nafg
Copy link
Member

nafg commented Mar 31, 2021

Anyone know what the policy has been until now?

@hvesalai
Copy link
Member

We've followed the semantic versioning, i.e. kept thing binary compatible between minor versions.

Here's the specification for scala https://docs.scala-lang.org/overviews/core/binary-compatibility-for-library-authors.html

So 4.0.0 if you want to break binary compatibility.

@tarsa
Copy link

tarsa commented Apr 5, 2021

I vote to keep binary compatibility. I think that a lot of bug fixes can be done without breaking binary compatibility.

Maybe let's write 3 lists of pull requests that either:

  1. absolutely need breaking bincompat to work
  2. don't break bincompat at all
  3. want to break bincompat to make code clean(er), but can work without breaking bincompat

@hvesalai
Copy link
Member

hvesalai commented Apr 5, 2021

Naturally we can do both. We can have master be the branch for the breaking changes and then cherry-pick from there to a 3.3.x branch

@nafg
Copy link
Member

nafg commented Apr 5, 2021 via email

@nafg
Copy link
Member

nafg commented Apr 15, 2021

The Scala 3 PR breaks compatibility, right? If yes then it should be targeted to 4.0.0 but other things can get into 3.4.0. Should we branch 3.4.x off main and retarget applicable PRs to 3.4.x? Is it even possible to retarget an open PR?

Besides adding Scala 3 support that PR drops 2.12 support. I assume that dropping 2.12 also can't be done in 3.x.x? Or can it?

@nafg
Copy link
Member

nafg commented Apr 15, 2021

Also, a 3.3.4 is not relevant at all?

@nafg
Copy link
Member

nafg commented Apr 15, 2021

BTW should I convert this issue to a discussion?

@nafg
Copy link
Member

nafg commented Apr 15, 2021

@SethTisue @hvesalai what's involved in a release? Ideally any v* tag would automatically publish a release, from my experience. Maybe I should migrate to github actions before we deal with that though

@nafg
Copy link
Member

nafg commented Apr 15, 2021

https://github.com/slick/slick/milestones what are 'Future ideas,' 'Future fix release,' and 'Future feature release'? Which future?

How do we get from there to knowing what should be in what branch and in what tag and release?

@SethTisue
Copy link
Member Author

SethTisue commented Apr 15, 2021

re: publishing:

Let's figure out publishing when the time comes. I am committed to helping as needed to make that happen. Last time, @octonato did it. I'll either figure it out or ask him to help me, and then once I know what the existing setup is, we can discuss perhaps changing it. I'm relieved to see that Bintray isn't involved, so that means we aren't forced to redo everything — but we could still choose to make changes.

re: issue vs. discussion: doesn't matter to me either way.

no idea about the milestones. we needn't feel bound by how it was done in the past.

re: 3.3.4 vs 3.4.0 vs 4.0.0, I'm fine w/ whatever y'all decide. We don't need to bend over backwards to please users who aren't actively contributing to maintenance. And you don't need to worry about Lightbend there, either -- you can be bold (whatever that means to you) if the other maintainers agree. Our period of commercial support for Slick doesn't expire until later this year, so it's possible that if a customer reports a serious bug, we'd be forced to step in and do a release (3.3.4, presumably) from a branch. But I think that's unlikely to happen, so we don't need to plan for it or worry about it.

I haven't looked at the Scala 3 PR to see what the bincompat situation and/or the 2.12 situation is there.

@octonato
Copy link
Contributor

@SethTisue, there is a wiki page with the release steps: https://github.com/slick/slick/wiki/Release-steps. I have simply follow it each time.

Artifacts are published to stage repo and then you need to connect to sonatype and promote them.

The release process can be simplified with sbt-ci-release though. If I recall correct, it's using its own solution with a few hacks here and there for signing.

@nafg
Copy link
Member

nafg commented Apr 16, 2021

According to https://docs.scala-lang.org/overviews/core/binary-compatibility-for-library-authors.html, a binary incompatible change must go into 4.0.0, and a source incompatible change must go into 3.4.0.

Does that imply that a change that is binary and source compatible should go into 3.3.4? What are other reasons to bump the minor version number? Should we also bump it for "new features"? How is "new feature" defined exactly?

Also, where does forwards compatibility come in? Maybe the time to bump the minor version is when we break forward compatibility?

If that is how it should work then I propose:

  • main should be for unrestricted changes
  • There should be a branch 3.4.x with binaryCompatSlickVersion set to "3.3.0" or "3.3.3"
  • 3.3.x should have binaryCompatSlickVersion set to "3.3.0" or "3.3.3", and mimaCheckDirection set to "both"
  • Most changes should by default have a target branch of 3.3.x. If it fails MiMa then it should should be changed to target 3.4.x. If it still fails MiMa then it should be changed to target main. It seems like I can change the target branch of an existing PR.
  • Whenever a change is made on 3.3.x, 3.3.x should be merged into 3.4.x. Whenever a change is made on 3.4.x, 3.4.x should be merged into main. Initial merge commits can be created that will prevent such merges from overwriting the MiMa settings.

@nafg
Copy link
Member

nafg commented Apr 18, 2021

Thoughts?

@hvesalai
Copy link
Member

We don't need to put any changes to earlier versions, but we can.

The question is, are there any users of older versions who would require some of the changes that we are merging AND can't upgrade to the newest version when it will be released. If so, and we want to cater to them, then we need to cherry-pick the changes also to the older version. If not, then we can just put everything to master and cut a new release from there.

Our project is OK with the latter.

@nafg
Copy link
Member

nafg commented Apr 18, 2021

I've worked on this a bit but it's confusing that v3.3.3 is not an ancestor of main. And main reports compatibility with 3.3.0 but not 3.3.1, or something like that.

error] Slick: Failed binary compatibility check against com.typesafe.slick:slick_2.12:3.3.1! Found 4 potential problems (filtered 17)
[error]  * the type hierarchy of object slick.util.ConstArray is different in current version. Missing types {slick.util.ConstArrayCompat}
[error]    filter with: ProblemFilters.exclude[MissingTypesProblem]("slick.util.ConstArray$")
[error]  * interface slick.util.SQLBuilderCompat does not have a correspondent in current version
[error]    filter with: ProblemFilters.exclude[MissingClassProblem]("slick.util.SQLBuilderCompat")
[error]  * interface slick.util.ConstArrayCompat does not have a correspondent in current version
[error]    filter with: ProblemFilters.exclude[MissingClassProblem]("slick.util.ConstArrayCompat")
[error]  * the type hierarchy of class slick.util.SQLBuilder is different in current version. Missing types {slick.util.SQLBuilderCompat}
[error]    filter with: ProblemFilters.exclude[MissingTypesProblem]("slick.util.SQLBuilder")

Also, why is it disabled for 2.13? And why only for the main slick submodule?

@nafg
Copy link
Member

nafg commented Apr 18, 2021

But 3.3.1 is compatible with 3.3.0. Isn't binary compatibility transitive?

@nafg
Copy link
Member

nafg commented Apr 18, 2021

If I add commits to 3.3.x from main, does it matter if I rebase in a way that loses merge commits? If I preserve merges then I have to avoid testing commits that are only part of a PR and either don't build or don't have mima set up properly

@hvesalai
Copy link
Member

  • The first version we release for 2.13 doesn't have to be binary compatible with anything since it's a first.
  • main should be marked as binary compatible with the previous release (3.3.3)
  • what do you mean v3.3.3 is not an ancestor of main? Surely there must be some level where they are the same.
  • use cherry-pick to get changes from main to 3.3.x

In any case, a real merge commit is a very badly behaving operation and I don't use it my self ever. I use rebase & merge or cherry-pick

@nafg
Copy link
Member

nafg commented Apr 18, 2021

  • The first version we release for 2.13 doesn't have to be binary compatible with anything since it's a first.

But 3.3.3 was not the first release for 2.13. I think 3.3.1 was.

  • main should be marked as binary compatible with the previous release (3.3.3)

Why?

  • what do you mean v3.3.3 is not an ancestor of main? Surely there must be some level where they are the same.

Try merging 3.3.x into main. You'll get a lot of conflicts. AFAICT the common merge base is v3.3.0. I guess stuff was haphazardly cherry-picked across branches and no one ever did a merge?

  • use cherry-pick to get changes from main to 3.3.x

I mean rebase is basically scripting cherry picks. So that doesn't help, especially since cherry-pick can't copy commits, and there are a LOT of commits on main since 3.3.x.

In any case, a real merge commit is a very badly behaving operation and I don't use it my self ever. I use rebase & merge or cherry-pick

Not sure why you feel that way, but merges are a core idea in git and PRs generally produce them.

Anyway, because 3.3.x/v3.3.3 are not an ancestor of main, rebasing and merging produce lots of conflicts and git bisect doesn't help, both because it crashes, and because I can't find where main starts being binary compatible with 3.3.1.

@nafg
Copy link
Member

nafg commented Apr 19, 2021

So far, none of the commits in git log --first-parent 3.3.x...main --format=%H pass mimaCheckDirection := "both", as can be seen here: https://github.com/slick/slick/actions/runs/761991908 -- at least not with mimaPreviousArtifacts set to all (for 2.13, 3.3.1-3.3.3, and for 2.12., 3.3.0 as well)

@nafg
Copy link
Member

nafg commented Apr 19, 2021

Hmm, maybe it's partially because the sbt launcher doesn't work with older SBTs

@nafg
Copy link
Member

nafg commented Apr 19, 2021

A lot are failing with sbt.InvalidComponent: Could not find required component 'xsbti'

@SethTisue
Copy link
Member Author

SethTisue commented Apr 19, 2021

A lot are failing with sbt.InvalidComponent: Could not find required component 'xsbti'

sounds like sbt/sbt#6447 -- if so, you should be able to work around it by adding -Dsbt.launcher.coursier=false, until a fix lands in the next launcher script

@nafg
Copy link
Member

nafg commented Apr 19, 2021

Thanks, that worked! I removed the hashes that failed bincompat to focus on the rest, and it's running at https://github.com/slick/slick/runs/2377507689.

@nafg
Copy link
Member

nafg commented Apr 19, 2021

Well those failed. Not sure why. But then again that's taking commits in context. I don't know what broke compatibility but it doesn't need to invalidate all subsequent commits.

So I tried a different approach. I wrote a script to produce #2216

Basically, it uses git log --cherry-pick --right-only --no-merges to get a list of commits, then it tries to cherry pick each, and skips any commit that either won't apply or isn't backward and forward compatible.

@nafg
Copy link
Member

nafg commented Apr 19, 2021

Umm.... except now the same branch is failing.

$ psbt \
                               'project slick' \
                               ++2.12.13 \
                               'eval println("3.3.0")' \
                               'set Settings.binaryCompatSlickVersion in ThisBuild := Some("3.3.0")' \
                               'set mimaCheckDirection := "both"' \
                               slick/mimaReportBinaryIssues
[info] Loading global plugins from /home/naftoli/.sbt/0.13/plugins
[info] Loading project definition from /tmp/slick/project
[info] Set current project to root (in build file:/tmp/slick/)
[info] Set current project to Slick (in build file:/tmp/slick/)
[info] Setting version to 2.12.13
[info] Reapplying settings...
[info] Set current project to Slick (in build file:/tmp/slick/)
3.3.0
[info] ans: Unit = null
[info] Defining {.}/*:binaryCompatSlickVersion
[info] The new value will be used by slick/*:mimaPreviousArtifacts
[info] Reapplying settings...
[info] Set current project to Slick (in build file:/tmp/slick/)
[info] Defining slick/*:mimaCheckDirection
[info] The new value will be used by slick/*:mimaFindBinaryIssues, slick/*:mimaReportBinaryIssues
[info] Reapplying settings...
[info] Set current project to Slick (in build file:/tmp/slick/)
[info] Resolving org.reactivestreams#reactive-streams;1.0.2 ...
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetDouble does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetDouble.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in class slick.jdbc.SetTupleParameter does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetTupleParameter.contramap")
[error]  * method dropForeignKeyIfExists(slick.lifted.ForeignKey)java.lang.String in class slick.jdbc.JdbcStatementBuilderComponent#TableDDLBuilder does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.JdbcStatementBuilderComponent#TableDDLBuilder.dropForeignKeyIfExists")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetDate does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetDate.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetTimeOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetTimeOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetDateOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetDateOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetTimestamp does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetTimestamp.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetTime does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetTime.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetLongOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetLongOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetShortOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetShortOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetIntOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetIntOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetBigDecimal does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetBigDecimal.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetStringOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetStringOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetBoolean does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetBoolean.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetString does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetString.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetSimpleProduct does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetSimpleProduct.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetByte does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetByte.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetByteOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetByteOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetLong does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetLong.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetBooleanOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetBooleanOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in interface slick.jdbc.SetParameter does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetTimestampOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetTimestampOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetFloatOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetFloatOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetBigDecimalOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetBigDecimalOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetFloat does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetFloat.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetDoubleOption does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetDoubleOption.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetShort does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetShort.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetInt does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetInt.contramap")
[error]  * method contramap(scala.Function1)slick.jdbc.SetParameter in object slick.jdbc.SetParameter#SetUnit does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.jdbc.SetParameter#SetUnit.contramap")
[error]  * the type hierarchy of object slick.util.ConstArray is different in other version. Missing types {slick.util.ConstArrayCompat}
[error]    filter with: ProblemFilters.exclude[MissingTypesProblem]("slick.util.ConstArray$")
[error]  * interface slick.util.SQLBuilderCompat does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[MissingClassProblem]("slick.util.SQLBuilderCompat")
[error]  * interface slick.util.ConstArrayCompat does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[MissingClassProblem]("slick.util.ConstArrayCompat")
[error]  * the type hierarchy of class slick.util.SQLBuilder is different in other version. Missing types {slick.util.SQLBuilderCompat}
[error]    filter with: ProblemFilters.exclude[MissingTypesProblem]("slick.util.SQLBuilder")
[error]  * method rewriteFakeBoolean(slick.ast.Node)slick.ast.Node in object slick.compiler.RewriteBooleans does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.compiler.RewriteBooleans.rewriteFakeBoolean")
[error]  * method rewriteFakeBooleanEqOne(slick.ast.Node)slick.ast.Node in object slick.compiler.RewriteBooleans does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.compiler.RewriteBooleans.rewriteFakeBooleanEqOne")
[error]  * method rewriteFakeBooleanWithEquals(slick.ast.Node)slick.ast.Node in object slick.compiler.RewriteBooleans does not have a correspondent in other version
[error]    filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("slick.compiler.RewriteBooleans.rewriteFakeBooleanWithEquals")
java.lang.RuntimeException: Slick: Binary compatibility check failed!
	at scala.sys.package$.error(package.scala:27)
	at com.typesafe.tools.mima.plugin.SbtMima$.reportModuleErrors(SbtMima.scala:83)
	at com.typesafe.tools.mima.plugin.MimaPlugin$$anonfun$mimaReportSettings$7$$anonfun$apply$2.apply(MimaPlugin.scala:68)
	at com.typesafe.tools.mima.plugin.MimaPlugin$$anonfun$mimaReportSettings$7$$anonfun$apply$2.apply(MimaPlugin.scala:59)
	at scala.collection.immutable.Map$Map1.foreach(Map.scala:109)
	at com.typesafe.tools.mima.plugin.MimaPlugin$$anonfun$mimaReportSettings$7.apply(MimaPlugin.scala:59)
	at com.typesafe.tools.mima.plugin.MimaPlugin$$anonfun$mimaReportSettings$7.apply(MimaPlugin.scala:44)
	at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
	at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40)
	at sbt.std.Transform$$anon$4.work(System.scala:63)
	at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)
	at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)
	at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
	at sbt.Execute.work(Execute.scala:237)
	at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)
	at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)
	at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159)
	at sbt.CompletionService$$anon$2.call(CompletionService.scala:28)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
[error] (slick/*:mimaReportBinaryIssues) Slick: Binary compatibility check failed!
[error] Total time: 2 s, completed Apr 19, 2021 5:02:25 AM

I am so confused. Is this thing even supposed to be deterministic or is it just a throwing dice?

@nafg
Copy link
Member

nafg commented Apr 19, 2021

Hmm, after throwing in a show sbt command it started passing again...

@SethTisue
Copy link
Member Author

@nafg @hvesalai I'm curious, do either or both of you have a personal or a professional interest in maintaining 3.3.x and 3.4.x branches, or is it just that you feel the project has some kind of obligation to its users to provide them?

My own primary concerns are 1) make sure the Scala 3 PR has a place to land, 2) not overtax available maintainer effort.

Concern 2 implies: let's default to keeping it simple unless y'all are sure you're really motivated to do something more complicated. (But if you are motivated, then great!)

@nafg
Copy link
Member

nafg commented Apr 25, 2021

I don't have an attachment to PVP (the version scheme you're describing) or SemVer. My goal is to make the process of maintaining Slick as simple as possible. That means

  • The lifecycle of a release should not require changing SBT files, especially not in nonobvious ways. That means that
  1. Whatever version scheme we settle on, enforcing it should be as automated as possible.
  2. mimaBinaryIssueFilters should not be updated manually to "document" breaking changes; it should only be used to override false positives
  3. mimaPreviousArtifacts should not need to be updated manually and should not contain hardcoded exceptions for scala versions in a way that will need to be changed over time. Ideally we could use https://github.com/scalacenter/sbt-version-policy or https://github.com/isomarcte/sbt-version-scheme-enforcer. If not we could encode custom information in the build but in a way that doesn't include adding temporary code to build.sbt. For instance, there could be a variable specifying which version introduced scala 2.13 support and then if the version used by mimaPreviousArtifacts does before that and the scalaVersion is 2.13 then don't do the check. This is probably moot by now. Certainly binaryCompatSlickVersion should be computed automatically.
  4. The version should ideally not have to be set manually in the build. sbt-dynver is one approach. Another options is to compute it based other variables that do need to be updated, but in a less error-prone way.
  • As far as PVP vs. SemVer, since Slick has been doing PVP until now that is the status quo and shouldn't be changed without reason. But one argument in favor SemVer perhaps is that we have to be less fearful of bumping versions too often. That is, because bumping the epoch number signals extra-big changes, PVP seems to be better when changes are planned well in advance and a set of large changes can be grouped together. Often, multiple branches would be maintained for separate lines of development. However semver sounds like it would be better for a leaner, more "in-and-out" process, where any change can just go into the main line of development but what type of change it is affects what the next version number will be. Planning and coordinating is better for the community of users but having a simpler process is better when there isn't a proper team allocating time for such things. Concretely, if we stick with PVP then we plan to have 3.4.0 after some amount of time and/or 4.0.0 after however much time, and we try to figure out how much we can get into what release number. OTOH with semver we can do releases whenever, and if we end up with a Slick version 7.9.3 in a year from now it's no big deal.

@nafg
Copy link
Member

nafg commented Apr 25, 2021

(To recap, it seems so far we have consensus that we should not bother with making a binary compatible release by cherry-picking binary compatible changes since 3.3.3. The question right now is what exactly that makes the next (pre-)release since it doesn't seem like it should wait for Scala 3 support to land, and given that there may be important changes coming not that far off. If we go with PVP it could be 3.4.0, but if we go with semver then it could be either 4.0.0-M1, or 4.0.0 and it might not be long before a 5.0.0. That said, with PVP, scala 3 support might need to be a 4.0.0-M1 if there are other changes planned afterward, even if they won't be ready for another few months, IIUC)

@SethTisue
Copy link
Member Author

SethTisue commented Jun 18, 2021

The Scala 3 PR seems to have stalled, for now anyway. Should we go 3.4.0 or 4.0.0 anyway, and figure that if Scala 3 support ends up requiring another big bump, then so be it?

As for the 3.4.0 (PVP) vs / 4.0.0 (semver) question, I don't have a strong opinion. If forced to choose I guess I'd say fooey to precedent, let's switch to semver. But @nafg, you've been the most active maintainer recently, so I'm inclined to let you make the call.

I do feel like enough time has passed now that we ought to roll some kind of release before much longer.

@nafg
Copy link
Member

nafg commented Jun 21, 2021

Yeah, I've been cleaning up the build lately to prepare for figuring out how to make releasing more automated.

sbt-version-policy requires regularly updating versionPolicyIntention. And so far I haven't gotten sbt-version-scheme-enforcer to work. I might hand-code the logic.

I think my goal would be that if a PR includes breaking changes, then either it would automatically (dynamically?) compute the next version based on that, or else it give an error that forces you to update the version setting manually.

It would help to have someone to talk it through with.

@isomarcte
Copy link

@nafg What is the issue you are seeing with sbt-version-scheme-enforcer? Is it just isomarcte/sbt-version-scheme-enforcer#41?

@isomarcte
Copy link

@nafg So I took a look at this and here is why sbt-version-scheme-enforcer-plugin isn't workout out of the box for Slick. The most direct cause of the failure is that sbt-version-scheme-enforcer-plugin is failing to find some artifacts in Maven central at the derived previous version value.

[error] stack trace is suppressed; run last codegen / mimaPreviousClassfiles for the full output
[error] stack trace is suppressed; run last hikaricp / mimaPreviousClassfiles for the full output
[error] stack trace is suppressed; run last testkit / mimaPreviousClassfiles for the full output
[error] (codegen / mimaPreviousClassfiles) sbt.librarymanagement.ResolveException: Error downloading com.typesafe.slick:Slick-CodeGen_2.13:3.3.0
[error]   Not found
[error]   Not found
[error]   not found: /home/dstrawn/.ivy2/local/com.typesafe.slick/Slick-CodeGen_2.13/3.3.0/ivys/ivy.xml
[error]   not found: https://repo1.maven.org/maven2/com/typesafe/slick/Slick-CodeGen_2.13/3.3.0/Slick-CodeGen_2.13-3.3.0.pom
[error]   not found: https://oss.sonatype.org/content/repositories/snapshots/com/typesafe/slick/Slick-CodeGen_2.13/3.3.0/Slick-CodeGen_2.13-3.3.0.pom
[error] (hikaricp / mimaPreviousClassfiles) sbt.librarymanagement.ResolveException: Error downloading com.typesafe.slick:Slick-HikariCP_2.13:3.3.0
[error]   Not found
[error]   Not found
[error]   not found: /home/dstrawn/.ivy2/local/com.typesafe.slick/Slick-HikariCP_2.13/3.3.0/ivys/ivy.xml
[error]   not found: https://repo1.maven.org/maven2/com/typesafe/slick/Slick-HikariCP_2.13/3.3.0/Slick-HikariCP_2.13-3.3.0.pom
[error]   not found: https://oss.sonatype.org/content/repositories/snapshots/com/typesafe/slick/Slick-HikariCP_2.13/3.3.0/Slick-HikariCP_2.13-3.3.0.pom
[error] (testkit / mimaPreviousClassfiles) sbt.librarymanagement.ResolveException: Error downloading com.typesafe.slick:Slick-TestKit_2.13:3.3.0
[error]   Not found
[error]   Not found
[error]   not found: /home/dstrawn/.ivy2/local/com.typesafe.slick/Slick-TestKit_2.13/3.3.0/ivys/ivy.xml
[error]   not found: https://repo1.maven.org/maven2/com/typesafe/slick/Slick-TestKit_2.13/3.3.0/Slick-TestKit_2.13-3.3.0.pom
[error]   not found: https://oss.sonatype.org/content/repositories/snapshots/com/typesafe/slick/Slick-TestKit_2.13/3.3.0/Slick-TestKit_2.13-3.3.0.pom
[error] Total time: 11 s, completed Jun 29, 2021, 10:25:29 AM

sbt-version-scheme-enforcer-plugin thinks the previous version is 3.3.0.

sbt:root> show versionSchemeEnforcerPreviousVersion
[info] slick / versionSchemeEnforcerPreviousVersion
[info]  Some(3.3.0)
[info] codegen / versionSchemeEnforcerPreviousVersion
[info]  Some(3.3.0)
[info] hikaricp / versionSchemeEnforcerPreviousVersion
[info]  Some(3.3.0)
[info] testkit / versionSchemeEnforcerPreviousVersion
[info]  Some(3.3.0)
[info] versionSchemeEnforcerPreviousVersion
[info]  Some(3.3.0)

Looking at Maven central, I can see don't see these artifacts there, so I'm assuming that you only using them for testing. If so, then we simply add disablePlugins(SbtVersionSchemeEnforcerPlugin) to each project.

Attempting to run it still fails. This is because sbt-version-scheme-enforcer-plugin will never override settings which are explicitly set. As we can see mimaPreviousArtifacts is set here: https://github.com/slick/slick/blob/main/build.sbt#L139.

If we unset that, letting sbt-version-scheme-enforcer-plugin derive it, then it fails with this error.

[error] stack trace is suppressed; run last mimaPreviousClassfiles for the full output
[error] (mimaPreviousClassfiles) sbt.librarymanagement.ResolveException: Error downloading com.typesafe.slick:slick_2.13:3.3.0
[error]   Not found
[error]   not found: /home/dstrawn/.ivy2/local/com.typesafe.slick/slick_2.13/3.3.0/ivys/ivy.xml
[error]   not found: https://repo1.maven.org/maven2/com/typesafe/slick/slick_2.13/3.3.0/slick_2.13-3.3.0.pom
[error]   not found: https://oss.sonatype.org/content/repositories/snapshots/com/typesafe/slick/slick_2.13/3.3.0/slick_2.13-3.3.0.pom
[error] Total time: 1 s, completed Jun 29, 2021, 10:40:47 AM

It appears that version 3.3.0 is not on Maven central. I see versions 3.3.2 and 3.3.3 only (for 2.13): https://search.maven.org/artifact/com.typesafe.slick/slick_2.13

sbt-version-scheme-enforcer-plugin didn't infer the previous version to be 3.3.3, but rather 3.3.0. This is because at present we only look for tags which are ancestors of the current commit. This outputs the most recent tag which is an ancestor of the main branch

> git --no-pager tag --merged @ --sort=-creatordate | head -n 1
v3.3.0

Since 3.3.3 isn't an ancestor of the main branch it is not considered in the previous version derivation. This is an unfortunate edge case. The only solution using sbt-version-scheme-enforcer-plugin at version 2.1.0.2 is to either merge v3.3.3 back into main or to manually set the versionSchemeEnforcerPreviousVersion. In general I would recommend that released branches always get merged back into the main development branches, so that each release is truly an ancestor of the main branch.

That said, whether or not a branch is merged back into the main branch really has nothing to do with the notion of binary API compatibility and version numbers. I'm working on some changes to sbt-version-scheme-enforcer-plugin which will allow users to search all tags, whether or not they are an ancestor of the current commit, when deriving the versionSchemeEnforcerPreviousVersion. It complicates the logic a bit, but I expect it to be done in a few days.

In the meantime, if in the general case you intend to merge releases back into main, but just didn't do so for 3.3.2 and 3.3.3 as an exception, then you can set versionSchemeEnforcerPreviousVersion := Some("3.3.3") and everything should just work. Once make your next release and merge it into main you can just drop that setting, although I expect to have completed my updates to sbt-version-scheme-enforcer-plugin to support this edge case by then.

I hope that helps! Let me know if I can be any assistance or answer any questions.

If you're curious, you can see my branch were I tested all this out here: you release https://github.com/isomarcte/slick/tree/sbt-version-scheme-enforcer (here's the diff with main).

sbt:root> versionSchemeEnforcerCheck
...
[error] Slick: Failed binary compatibility check against com.typesafe.slick:slick_2.13:3.3.3! Found 4 potential problems (filtered 9)
[error]  * the type hierarchy of object slick.util.ConstArray is different in current version. Missing types {slick.util.ConstArrayCompat}
[error]    filter with: ProblemFilters.exclude[MissingTypesProblem]("slick.util.ConstArray$")
[error]  * interface slick.util.ConstArrayCompat does not have a correspondent in current version
[error]    filter with: ProblemFilters.exclude[MissingClassProblem]("slick.util.ConstArrayCompat")
[error]  * the type hierarchy of class slick.util.SQLBuilder is different in current version. Missing types {slick.util.SQLBuilderCompat}
[error]    filter with: ProblemFilters.exclude[MissingTypesProblem]("slick.util.SQLBuilder")
[error]  * interface slick.util.SQLBuilderCompat does not have a correspondent in current version
[error]    filter with: ProblemFilters.exclude[MissingClassProblem]("slick.util.SQLBuilderCompat")
[error] stack trace is suppressed; run last slick / mimaReportBinaryIssues for the full output
[error] stack trace is suppressed; run last mimaReportBinaryIssues for the full output
[error] (slick / mimaReportBinaryIssues) Failed binary compatibility check against com.typesafe.slick:slick_2.13:3.3.3! Found 4 potential problems (filtered 9)
[error] (mimaReportBinaryIssues) mimaPreviousArtifacts not set, not analyzing binary compatibility
[error] Total time: 11 s, completed Jun 29, 2021, 10:54:56 AM

@nafg
Copy link
Member

nafg commented Jul 11, 2021

I just opened #2275. If possible I would like to use sbt-dynver. Other than that I'm ready for a 3.4.0, unless we can get any more open PRs in, or there's any other part of the process that I can make more automated first.

@octonato @SethTisue @hvesalai any of you know that know how to do a release want to go over it on a call?

@nafg
Copy link
Member

nafg commented Jul 11, 2021

Open PRs and their status:

#2275 pending review
#2238 build failures
#2193 pending changes, but should be included in some form IIUC
#2190 pending response to comments
#2187 not done, should target 4.0.0
#2145 LGTM but needs rebase (I would prefer squash too). Fails for MiMa reasons. I want to see tests pass after rebase/squash are force-pushed -- after #2275 (or an alternative) is merged.

@nafg
Copy link
Member

nafg commented Jul 13, 2021

There are a few variables that normally change over the course of a project's releases. I want to minimize manual changes as much as possible.

  1. The current version.
  2. The previous version, which MiMa can be run against. This could be set manually, calculated from the current version, as sbt-mima-version-check and sbt-version-policy do, or determined from the previous git tag, as sbt-version-scheme-enforcer-plugin does.
  3. The change type, which determines whether to run MiMa and in what mode. This could be configured manually, more semantically via sbt-version-policy's versionPolicyIntention setting, or inferred from the versionScheme and the difference between the current version and the previous version, as sbt-version-scheme-enforcer-plugin does.

The issue is how to get all 3. If the current version automated via sbt-dynver, it's just the previous version plus some version tags, and there isn't enough information to compute the change type, seemingly necessitating something like versionPolicyIntention. Conversely, if the change type is inferred from the difference between the current version and the previous version, that requires setting the current version to something that implies said change type.

There is a possible solution: If we can tell from the changes themselves how major they are, we can automate setting the version and tagging based on that. I have seen two relevant ways to do that:

  1. sbt-autoversion checks commit messages for regexes. This could work with a convention like the Angular commit message format, or a convention I use in an app I develop where I prefix commit messages with ^, *, or + to indicate which part of the version they bump, if any. In order to use this at this point, we may have to add an empty commit just to signal the change type.
  2. Release Drafter (please chime in on Thoughts on Release Drafter #2276) uses GitHub PR labels to signal the change type. However it's certainly not trivial to configure version based on PR labels. That said, if we use it, it might be possible to use its action outputs to get the version it computed into sbt.

I still have no idea what the actual release process is like. But if we can't automate it then I guess after every release we should set version to nextPatchVersion + "-SNAPSHOT", e.g. after 3.4.0 it released we would change it to 3.4.1-SNAPSHOT, and then if someone opens a PR that fails MiMa, they either change their code or their PR changes the version to 3.5.0-SNAPSHOT.

@isomarcte
Copy link

@nafg

If the current version automated via sbt-dynver, it's just the previous version plus some version tags, and there isn't enough information to compute the change type, seemingly necessitating something like versionPolicyIntention.

I think it is a bit more complicated than that. If you only using sbt-dynver to calculate your version, you will need to provide additional information in some form or another to calculate the intended binary API change, but that is only because using sbt-dynver alone will not calculate valid versions based on your given version scheme.

For example,

If your last release is 1.0.0 and you add some commits which add new functions the sbt-dynver will infer a version value something like 1.0.0+3-1234abcd.

This is broken down into a version number of 1.0.0 with a metadata value of +3-1234abcd. By SemVer, EarlySemVer, and PVP, this version value is not correct. 1.0.0 and 1.0.0+3-1234abcd (or any version string starting with 1.0.0) must have the exact same API. A correct version value in terms of the version scheme must start with a value (assuming PVP) >= 1.0.1.

This isn't a problem with sbt-dynver, it's doing exactly what it intends to do, add git metadata into the version string.

If we remove sbt-dynver from the situation for a moment, then the situation becomes very simple. If we intend to add a new symbol or remove an existing symbol, we merely change the ThisBuild / version := component and then the intent is inferred correctly from the last tag and the current version.

That said, I'm not trying to argue you should remove sbt-dynver to make this work. There's no free lunch here, we have to communicate in some way what we intend to do. sbt-version-scheme-enforcer merely calculates this intent from the version string itself. Even with sbt-dynver managing the version string, there are still a few ways we can add our intent into the version string.

  1. One could introduce a tag to indicate the start of a API change.
    • For example, consider if the last release is version 3.3.0, using PVP. If we intend to add a new symbol, we can merely add a tag 3.3.1-M0 or similar. This tag doesn't need to be released, just present.
    • This approach is desirable because your version strings are always valid. That is, the version number for any commit will be in line with the SemVer, EarlySemVer, or PVP rules.
  2. Alternatively, during the release process, one could tag the commit before running versionSchemeEnforcerCheck in CI. If that fails, then discard the release, e.g. don't push the commit back to github, don't publish the artifacts.

For what it's worth, even without considering automatic mima calculations, I think using sbt-dynver without taking steps to ensure that the version number is in line with your version scheme communicates the wrong thing to users/developers. Given a version number like 1.0.0+3-1234abcd, if we aren't keeping the version number in line with the scheme, what are we actually communicating? Well, we communicate that there have been 3 commits to this branch since the last commit's hash started with 1234abcd. That's fine, but users/developers have no idea from the version value how this version relates to version 1.0.0 (is HEAD breaking, adding new symbols, or just bug fixes?), which I'd argue is much more important than how many commits have been made and what the hash is. Again, this isn't an sbt-dynver issue, just an interaction that it introduces if we don't account for it. You certainly can use sbt-dynver and still have your version number be valid by your version scheme for all commits.

Let me know if I can clarify things or help in anyway here.

@SethTisue
Copy link
Member Author

@octonato @SethTisue @hvesalai any of you know that know how to do a release want to go over it on a call?

let's cross that bridge once all PRs are merged and everything is actually good to go

@nafg
Copy link
Member

nafg commented Jul 13, 2021

@nafg

If the current version automated via sbt-dynver, it's just the previous version plus some version tags, and there isn't enough information to compute the change type, seemingly necessitating something like versionPolicyIntention.

If we remove sbt-dynver from the situation for a moment, then the situation becomes very simple. If we intend to add a new symbol or remove an existing symbol, we merely change the ThisBuild / version := component and then the intent is inferred correctly from the last tag and the current version.

That said, I'm not trying to argue you should remove sbt-dynver to make this work. There's no free lunch here, we have to communicate in some way what we intend to do. sbt-version-scheme-enforcer merely calculates this intent from the version string itself. Even with sbt-dynver managing the version string, there are still a few ways we can add our intent into the version string.

@isomarcte to clarify, Slick has not used sbt-dynver. I'm just trying to remove as many manual steps as possible that are required to maintain and release Slick. For however long I help with Slick, and whoever else does afterwards, the more automated it is, the quicker things can happen and the sooner changes can be released. If I can remove the need to manually set the version, that would be nice.

  1. One could introduce a tag to indicate the start of a API change.

    • For example, consider if the last release is version 3.3.0, using PVP. If we intend to add a new symbol, we can merely add a tag 3.3.1-M0 or similar. This tag doesn't need to be released, just present.

That doesn't solve the problem of: someone just opened a PR, what mode should CI run MiMa in?

I want that the "assumed" next version could be one thing, say a patch bump, but if a PR has breaking changes it should be easy for the PR author to either find out and refactor to avoid breaking changes, or indicate that breaking changes are desired and when merged everything should follow accordingly. This could be by:

  1. Updating version
  2. Updating versionPolicyIntention / versionSchemeEnforcerChangeType
  3. Using some special syntax in the commit message
  4. Adding a github label to the PR
  5. Another one I just thought of: assigning the PR to a milestone

But (1) it shouldn't be more than one of the above, and (2) everything else that needs to happen should happen automatically (e.g. by inferring versionSchemeEnforcerChangeType from version, or version from versionPolicyIntention or commit messages or PR label or milestone).

  1. Alternatively, during the release process, one could tag the commit before running versionSchemeEnforcerCheck in CI. If that fails, then discard the release, e.g. don't push the commit back to github, don't publish the artifacts.

I want to have the right MiMa settings on each PR.

@nafg
Copy link
Member

nafg commented Jul 13, 2021

@octonato @SethTisue @hvesalai any of you know that know how to do a release want to go over it on a call?

let's cross that bridge once all PRs are merged and everything is actually good to go

Up to you, but I like it better when I have more time to digest information

PRs are merged

@SethTisue any in particular that are important to you to make 3.4.0?

Also, if the author doesn't, will you be able to rebase #2145 ?

@SethTisue
Copy link
Member Author

SethTisue commented Jul 13, 2021

I like it better when I have more time to digest information

Okay, well here's what I can see from build.sbt: it looks like everything is all set up to publish to Sonatype, and publishing is done from the developer's individual machine. That developer needs Sonatype credentials that work for com.typesafe.slick, and apparently Renato has those and will be able to pass them on to me.

Going forward, it would be better to be on sbt-ci-release, IMO. (Note that sbt-ci-release includes sbt-dynver.) Perhaps you or another volunteer would like to PR that in the meantime. We could merge such a PR even before we have working publishing credentials; those can be added to the GitHub Actions config later.

any in particular that are important to you to make 3.4.0?

Nope, everything I cared about was merged already. It would have been nice if Scala 3 support had landed in time, but I feel pretty strongly that there's more value in releasing anyway than there is in waiting any longer.

if the author doesn't, will you be able to rebase #2145 ?

Sure

@nafg
Copy link
Member

nafg commented Jul 13, 2021

Hmm, so now I have an interesting idea which is probably overengineering but it sounds kind of nice I think:

So, we're talking about how sbt should know what version is being targeted, in a way that makes opening and testing a PR seamless. And GitHub already has a way to express what version a PR is targeting: milestones.

So here's the idea:

  1. It doesn't matter so much what the default value of version is. We could use sbt-dynver, set it manually, or anything else
  2. We set the github action to override the version based on the milestone of the PR. I believe we can do that using something like ${{ github.event.pull_request.pull_request.milestone.title }}. If it passes a regex would use it to override version, presumably concatenating to it "-SNAPSHOT".
  3. I think Release Drafter could be configured to use the milestone version.

Although, I do like Release Drafter's idea of labelling PRs with their level of breakage; this way if there are several open PRs, it can easily be seen which ones can be combined into a non-breaking release and which ones could be merged afterward for a subsequent breaking release.

@nafg
Copy link
Member

nafg commented Jul 13, 2021

I like it better when I have more time to digest information

Okay, well here's what I can see from build.sbt: it looks like everything is all set up to publish to Sonatype, and publishing is done from the developer's individual machine. That developer needs Sonatype credentials that work for com.typesafe.slick, and apparently Renato has those and will be able to pass them on to me.

Going forward, it would be better to be on sbt-ci-release, IMO. (Note that sbt-ci-release includes sbt-dynver.) Perhaps you or another volunteer would like to PR that in the meantime. We could merge such a PR even before we have working publishing credentials; those can be added to the GitHub Actions config later.

Right, so basically the credentials would go into github secrets. You can do that at any time.

I've used sbt-ci-release on my own OSS repos, since the bintray shutdown, but only via sbt-github-actions. That said, I based Slick's github actions code off that, so hopefully I'll be able to figure out how to configure it standalone.

publishing is done from the developer's individual machine

It's interesting. I assume you're saying that based on

slick/admin/build.sh

Lines 3 to 15 in fcf0e91

# Setup:
# - Copy keys to admin/secring.asc, admin/pubring.asc
# - Use a new key pair per repository
# - ssh-keygen -t rsa -b 4096 -C "<github-user-email>" #save as deploykey
# - Setup github deploy keys using generated keys, keep a copy of generated keys
# - cp deploykey deploykey.pub admin/
# - openssl rsa -in admin/deploykey -outform pem > admin/deploykey.pem
# - chmod 400 admin/deploykey.pem
# - cp ~/.sbt/sonatype.sbt ./
# - tar cvf secrets.tar admin/secring.asc sonatype.sbt admin/deploykey.pem
# - travis encrypt-file secrets.tar --add
# - rm sonatype.sbt admin/secring.asc admin/deploykey admin/deploykey.pub admin/deploykey.pem secrets.tar
# - Set passphrase in admin/publish-settings.sbt

However, at the same time, it seems to have been set up to publish based on the tag set in CI:

slick/admin/build.sh

Lines 18 to 19 in 070b33a

if [[ "$TRAVIS_TAG" =~ ^v[0-9]+\.[0-9]+(\.[0-9]+)?(-[A-Za-z0-9-]+)? ]]; then
echo "Going to release from tag $TRAVIS_TAG!"

Anyway, I would be happy to delete all that and related code, and just do a normal sbt-ci-release setup like I do in my other projects, if that's what you think makes the most sense.

@nafg
Copy link
Member

nafg commented Jul 13, 2021

Actually, interesting observation related to that and #2198 (comment): CI already works by overriding the sbt version setting, at least on release.

@SethTisue
Copy link
Member Author

Oh, weird, I didn't notice the TRAVIS_TAG thing. I don't know what to make of that.

But I guess it doesn't matter, because "a normal sbt-ci-release setup" is exactly what I would suggest, and I'm sure Renato won't object. Almost every repo I work in uses sbt-ci-release, these days.

@isomarcte
Copy link

@nafg

@isomarcte to clarify, Slick has not used sbt-dynver. I'm just trying to remove as many manual steps as possible that are required to maintain and release Slick

Ah I see. Well I completely understand that sentiment, that was a major reason I wrote sbt-version-scheme-enforcer. ;)

But (1) it shouldn't be more than one of the above, and (2) everything else that needs to happen should happen automatically (e.g. by inferring versionSchemeEnforcerChangeType from version, or version from versionPolicyIntention or commit messages or PR label or milestone).

Yeah, that makes perfect sense to me and I completely agree. FWIW, I've personally found that just using version sbt key is the easiest way to do this from all of the proposed solutions. If you aren't using sbt-dynver, then if someone making a PR wants to state that breaking changes are intentional, then it is usually a single character change.

Anyway, let me know if I can provide any more help.

@nafg
Copy link
Member

nafg commented Jul 13, 2021

Open PRs and their status:

#2275 pending review

Merged

#2238 build failures
#2193 pending changes, but should be included in some form IIUC
#2190 pending response to comments
#2187 not done, should target 4.0.0
#2145 LGTM but needs rebase (I would prefer squash too). Fails for MiMa reasons. I want to see tests pass after rebase/squash are force-pushed -- after #2275 (or an alternative) is merged.

Actually I didn't need to rebase it, closing and reopening synced it to main post-#2275. That's merged too.

I hope to focus on working to Scala 3 compatibility after 3.4.0, but I don't think it should come before because it would be best to have refactoring freedom. For instance the virtual classes pattern isn't allowed so lots of renames will be needed.

@nafg
Copy link
Member

nafg commented Jul 14, 2021

Another question is what tasks need to be done with a release besides the act of publishing to maven central. Some that come to mind are:

  1. Creating a github release
  2. Writing release notes, documenting changes, migration instructions (scalafix rules for bonus points), etc.
  3. Updating the docs site
  4. Announcing it

What else is there?

@nafg
Copy link
Member

nafg commented Oct 10, 2021

@isomarcte can we chat somehow?

@isomarcte
Copy link

@nafg Sure. Like an audio chat?

@nafg
Copy link
Member

nafg commented Oct 11, 2021

@isomarcte yeah. You can DM me on discord as nafg#1263 or gitter as nafg

@isomarcte
Copy link

@nafg I messaged you on discord.

@nafg nafg closed this as completed Dec 20, 2021
@nafg nafg unpinned this issue Dec 20, 2021
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

No branches or pull requests

6 participants