Giter VIP home page Giter VIP logo

sbt-spiewak's Introduction

sbt-spiewak

This plugin basically just exists to allow me to more conveniently setup my baseline SBT configuration, which has evolved somewhat over the years, and is also becoming quite unwieldy when solely represented in giter8 format. If you want to use this plugin with a new project, you should probably start from that template.

If you generally agree with my opinions on how projects should be set up, though, then this is probably a really excellent plugin to base on! Between this plugin and my giter8 template, you can get a new Scala project up and running and publishing to Sonatype within about five minutes. As an example, check out this quick screencast:

sbt-spiewak demo

TLDR, it's really really easy.

Usage

Put one of the following into your plugins.sbt:

// for stock functionality (no publication defaults)
addSbtPlugin("com.codecommit" % "sbt-spiewak" % "<version>")

// publishing to sonatype
addSbtPlugin("com.codecommit" % "sbt-spiewak-sonatype" % "<version>")

Then, in your build.sbt, make sure you set a value for baseVersion, organization, publishGithubUser and publishFullName:

ThisBuild / organization := "com.codecommit"

ThisBuild / baseVersion  := "0.1"

ThisBuild / publishGithubUser := "djspiewak"
ThisBuild / publishFullName   := "Daniel Spiewak"

Or something like that.

If you have a multi-module build and need a subproject to not publish (as is commonly done with the root project), enable the NoPublishPlugin. For example:

lazy val root = project
  .aggregate(core, sonatype)
  .in(file("."))
  .settings(name := "root")
  .enablePlugins(NoPublishPlugin)

Release automatically with GitHub Actions CI

If you would like your releases to be published by your CI process in GitHub Actions, rather than locally, you will probably benefit from the SonatypeCiReleasePlugin plugin (part of sbt-spiewak-sonatype). This makes some assumptions about your secrets and general build configuration, applies the settings to the sbt-github-actions-generated workflow, and generally takes care of everything for you.

To use, add the following to the root level of your build.sbt:

enablePlugins(SonatypeCiReleasePlugin)

Then, generate the initial GitHub Actions in .github/workflows with the githubWorkflowGenerate SBT task (see tasks for sbt-github-actions).

After that, configure the following encrypted secrets within GitHub Actions (go to Settings -> Secrets -> New secret; see GitHub Encrypted Secrets documentation for more detail):

  • SONATYPE_USERNAME
  • SONATYPE_PASSWORD
  • PGP_SECRET

You can obtain the PGP_SECRET by running gpg --export-secret-keys | base64. Please make sure that this key is not password protected in the export (GitHub Actions itself will encrypt it).

Once this is done, decide whether you would like snapshots to be published on every master build. By default, releases will only be published on version tags. If you wish to override this, set the following:

ThisBuild / spiewakCiReleaseSnapshots := true

If you do set the above to true, you should probably also make sure to set your primary branch as below:

ThisBuild / spiewakMainBranches := Seq("main")

You can also simply add additional branches, if you're publishing snapshots on more than one at a time.

With all of these steps out of the way, you should have some nice, reliable, CI-driven releases going forward!

Caveat: If you are publishing snapshots on your primary branch, you will need to be careful to ensure that new tags are fully built on the primary branch before you push the tag to the upstream. The reason for this is the fact that tags are visible to the primary branch builds, meaning that if you push a new commit to master and a tag which points to it, that commit and tag will build and release under the same name simultaneously. The workaround is to push master, wait for the snapshot release to complete, and then push the tag. I'll get around to fixing this someday...

Features

  • Baseline plugin setup
    • coursier
    • sbt-travisci
    • sbt-git
      • With sensible git versioning settings
      • Also with fixed git-status stuff
    • sbt-header
      • Assumes Apache 2.0 license
    • sbt-sonatype
      • With fixed snapshot publication URLs
    • sbt-gpg
    • sbt-mima
      • Infers previous versions by using git tags
      • Automatically runs on ci and release
    • sbt-explicit-dependencies
      • unusedCompileDependenciesTest runs on ci
      • disabled by NoPublishPlugin
      • filters Scala.js and Dotty standard libraries
  • Sensibly opinionated scalac settings
    • Including -Ybackend-parallelism where supported
  • SI-2712 fix across scala versions (dating back to 2.10)
  • kind-projector (Scala 2 only)
  • better-monadic-for (Scala 2 only)
  • release and ci command aliases
    • Performs sonatype release steps
  • NowarnCompatPlugin
    • Adds support for @nowarn to Scala 2.11, 2.12, and 2.13.1 via Silencer.
    • Adds scala-collection-compat to the classpath for versions that need Silencer. Opt out by configuring nowarnCompatAnnotationProvider.
  • SonatypeCiReleasePlugin
    • Prescriptive defaults for projects which want CI releases

Sonatype Requirements

You will need to define the following settings:

ThisBuild / homepage := Some(url("https://github.com/djspiewak/sbt-spiewak"))

ThisBuild / scmInfo := Some(ScmInfo(url("https://github.com/djspiewak/sbt-spiewak"),
  "[email protected]:djspiewak/sbt-spiewak.git"))

Defaults Which You May Wish to Override...

You may consider overriding any of the following keys, which are hard-coded to defaults that I believe are reasonable:

  • licenses (defaults to Apache 2.0)
  • developers (defaults to just yourself, using the publishFullName and publishGithubUser)
  • startYear (defaults to 2020)
  • endYear (defaults to empty; set this if you want a range of years for your copyright headers)
  • strictSemVer (defaults to true)
    • When set to true, it disallows breaking binary compatibility in any release which does not increment the major component unless the major component is 0 (i.e. semantic versioning). Many Scala projects break binary compatibility in minor releases, such as Scala itself. This scheme is sometimes referred to as "scala ver". Setting ThisBuild / strictSemVer := false will relax the MiMa compatibility checks and allow you to perform such breakage if desired.

sbt-spiewak's People

Contributors

amesgen avatar armanbilge avatar bplommer avatar danicheg avatar dcsobral avatar djspiewak avatar fthomas avatar jorokr21 avatar larsrh avatar mpilquist avatar rintcius avatar rossabaker avatar scala-steward avatar scalawilliam avatar sethtisue avatar systemfw avatar vasilmkd avatar wemrysi avatar xuwei-k avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

sbt-spiewak's Issues

Add scala-2/scala-3 source directories

Maybe out of scope, but given the other functionality related to Dotty build config, it would be nice if src/{main,test}/scala-{2,3} were automatically added to the build.

Release new version without sbt-dotty

Currently, we can't remove sbt-dotty from projects that depend on this plugin, for scala 3.0.0, since this pulls in an older version, that is not compatible.

The plugin has been removed from here, but that has not been released yet.

Fatal warnings customization

Fatal warnings are currently enabled on CI only. It would be nice to have some more configurability as to (1) are they enabled on CI only or all the time and (2) for which Scala versions are they enabled.

Pain after retagging an RC commit as a final

https://github.com/typelevel/fs2-grpc/runs/2316215041?check_suite_focus=true

  1. fs2-grpc-1.1.0-RC3 was tagged, released
  2. Retagged the same commit as 1.1.0
  3. Locally, version number is still inferred as 1.1.0-RC3. This seems like a git versioning pitfall.
  4. mimaPreviousVersions includes 1.1.0, even though it's greater than version 1.1.0-RC3
  5. Tweet embarrassingly that something is there that isn't

I guess we're not supposed to put multiple tags on one commit? But even if we do, I wouldn't expect to mima against newer versions.

Default matrix exclusions

Several projects are building all the Scalas for one Java, and all the Javas for one Scala, instead of the cartesian product. Would this be a sensible default to keep build matrices under control?

http4s/sbt-http4s-org#110

Scaladoc backlink settings

It surprises me that I never did this:

scalacOptions in (Compile, doc) ++= {
    val isSnapshot = git.gitCurrentTags.value.map(git.gitTagToVersionNumber.value).flatten.isEmpty

    val path =
      if (isSnapshot)
        scmInfo.value.get.browseUrl + "/blob/" + git.gitHeadCommit.value.get + "€{FILE_PATH}.scala"
      else
        scmInfo.value.get.browseUrl + "/blob/v" + version.value + "€{FILE_PATH}.scala"

    Seq("-doc-source-url", path, "-sourcepath", baseDirectory.in(LocalRootProject).value.getAbsolutePath)
  },

Extract out a versioning plugin

I dig your versioning. I think it's better than sbt-dynver, or at the very least I'd like to try it out and compare them in real projects.

Do you mind if we extract it out, like sbt-travisci? Looks like sbt-semver isn't taken, so we could use that.

I don't know where all the pieces are, and exactly where to draw the line between the versioning and the integration with the other parts of this plugin. Any advice?

Consider POM cleanup before publishing

I typically include this POM post-processing in builds:

  pomPostProcess := { node =>
    import scala.xml._
    import scala.xml.transform._
    def stripIf(f: Node => Boolean) =
      new RewriteRule {
        override def transform(n: Node) =
          if (f(n)) NodeSeq.Empty else n
      }
    val stripTestScope = stripIf(n => n.label == "dependency" && (n \ "scope").text == "test")
    new RuleTransformer(stripTestScope).transform(node)(0)
  },

FullScalaVersion chokes on Scala nightlies

nightlies have version numbers of the form 2.13.2-bin-7bfe4c0 (the -bin- might instead be -pre-), but that isn't accepted

this came up as I tried to add cats-effect-testing to the Scala community build

sbt:cats-effect-testing> ++2.13.2-bin-7bfe4c0!
[info] Forcing Scala version to 2.13.2-bin-7bfe4c0 on all projects.
[info] Reapplying settings...
[error] scala.MatchError: 2.13.2-bin-7bfe4c0 (of class java.lang.String)
[error] Use 'last' for the full log.
sbt:cats-effect-testing> last
[debug] > Exec(++2.13.2-bin-7bfe4c0!, Some(28205be9-3231-4de5-a0ae-8f10cd463119), Some(CommandSource(console0)))
[debug] Evaluating tasks: checkBuildSources
[debug] Running task... Cancel: Signal, check cycles: false, forcegc: true
[info] Forcing Scala version to 2.13.2-bin-7bfe4c0 on all projects.
[debug] Switching Scala version on:
[debug]     scalatest (2.12.10, 2.13.1)
[debug]     scalatest-scalacheck (2.12.10, 2.13.1)
[debug]   * root (2.12.10, 2.13.1)
[debug]     minitest (2.12.10, 2.13.1)
[debug]     utest (2.12.10, 2.13.1)
[debug]     specs2 (2.12.10, 2.13.1)
[debug] Excluding projects:
[info] Reapplying settings...
[error] scala.MatchError: 2.13.2-bin-7bfe4c0 (of class java.lang.String)
[error] 	at sbtspiewak.FullScalaVersion$.unapply(FullScalaVersion.scala:28)
[error] 	at sbtspiewak.SpiewakPlugin$.$anonfun$projectSettings$11(SpiewakPlugin.scala:213)
[error] 	at sbt.internal.util.EvaluateSettings$MixedNode.evaluate0(INode.scala:223)
[error] 	at sbt.internal.util.EvaluateSettings$INode.evaluate(INode.scala:166)
[error] 	at sbt.internal.util.EvaluateSettings.$anonfun$submitEvaluate$1(INode.scala:87)
[error] 	at sbt.internal.util.EvaluateSettings.sbt$internal$util$EvaluateSettings$$run0(INode.scala:99)
[error] 	at sbt.internal.util.EvaluateSettings$$anon$3.run(INode.scala:94)
[error] 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error] 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error] 	at java.lang.Thread.run(Thread.java:748)
[error] scala.MatchError: 2.13.2-bin-7bfe4c0 (of class java.lang.String)
[error] Use 'last' for the full log.
[debug] > Exec(shell, None, None)
[debug] Evaluating tasks: checkBuildSources
[debug] Running task... Cancel: Signal, check cycles: false, forcegc: true
sbt:cats-effect-testing> 

First class support for Scala.js

So far I think there are two primary issues:

  1. Scala.js (and native) can use Mima, so actually enable that :)
  2. Don't assume that Scala.js only exists in cross-projects. If a project is Scala.js only, it is not detected and all your awesome Scala.js settings don't kick in. E.g. the -P:scalajs:mapSourceURI: stuff which as a result is broken for macrotask executor.

version missing -SNAPSHOT, isSnapshot always false

For example, for cats-effect-testing on series/0.x:

sbt:cats-effect-testing> show isSnapshot
[info] minitest / isSnapshot
[info] 	false
[info] scalatest-scalacheck / isSnapshot
[info] 	false
[info] scalatest / isSnapshot
[info] 	false
[info] utest / isSnapshot
[info] 	false
[info] specs2 / isSnapshot
[info] 	false
[info] isSnapshot
[info] 	false
sbt:cats-effect-testing> show version
[info] minitest / version
[info] 	0.5-3-78ce2ad
[info] scalatest-scalacheck / version
[info] 	0.5-3-78ce2ad
[info] scalatest / version
[info] 	0.5-3-78ce2ad
[info] utest / version
[info] 	0.5-3-78ce2ad
[info] specs2 / version
[info] 	0.5-3-78ce2ad
[info] version
[info] 	0.5-3-78ce2ad

Is this expected?


In http4s-jdk-http-client, we use isSnapshot to publish snapshot documentation in a specific directory:

https://github.com/http4s/http4s-jdk-http-client/blob/1910a08dfeddef8e30062fab7dd06b6c3e71fa59/build.sbt#L181-L183

Prepend commit numbers to version hashes

This doesn't give us true monotonicity, but it does define a semi-lattice which would hold in any case where snapshots are not published from a branch, and in cases where snapshots are published from a branch, the information would be no worse than it is today.

It might also be worth investigating if we should just rip out some of this machinery and replace it with an sbt-dynver dependency.

Explore sbt-explicit-dependencies

It provides two things: unused dependency checking and explicit dependency checking. The latter is something I really don't agree with, but the former (which is like stale imports) is actually really good. I'd like to incorporate the former by default but not the latter.

Support adding a crossScalaVersion without breaking binary compat

mimaPreviousVersions is generated based off the current version number. Let's say the versions 1.0 and 1.1 have been released for Scala 2.12 and then 2.13 support is added to the build. mimaPreviousVersions will assume 1.0 and 1.1 have been released for 2.13 and mima will fail as a result.

Expose a non-autoplugin for doing CI releases

Should be able to just do enablePlugin(CIReleasePlugin) and bring in the necessary settings to decrypt credentials and stuff. Should probably expose a single setting, ciReleaseMasterSnapshots, which controls whether or not it is exclusively tags which are released.

Can't add sbt-spiewak projects to the Scala 3 community build

This is because the isDotty setting added to sbt-spiewak in #54 conflicts with the one in the DottyPlugin used in the community build:

/__w/dotty/dotty/community-build/community-projects/http4s/build.sbt:1059: error: reference to isDotty is ambiguous;
it is imported twice in the same scope by
import _root_.sbtspiewak.SpiewakPlugin.autoImport._
and import _root_.dotty.tools.sbtplugin.DottyPlugin.autoImport._
    if (isDotty.value && githubIsWorkflowBuild.value)

Currently, all the projects in the CB using sbt-spiewak are using an old version of the plugin. But this means they cannot be updated.

I've asked in lampepfl/dotty#14071 (comment) if the DottyPlugin is still needed since it was merged into sbt. However, is the isDotty setting still necessary for sbt-spiewak? According to sbt/sbt#6080 isDotty has been renamed to isScala3 in sbt.

scala-2 and scala-3 source directories refer to project base directory, not module directory

2bce0b4#diff-4dd98e212dbd5661e10c547bdb06116eR460

sbt:root> project io
[info] set current project to fs2-io (in build file:/Users/MPilqu0037e/Development/oss/fs2/)
sbt:fs2-io> show unmanagedSourceDirectories
[info] * /.../oss/fs2/io/src/main/scala-0.27
[info] * /.../oss/fs2/io/src/main/scala
[info] * /.../oss/fs2/io/src/main/java
[info] * /.../oss/fs2/src/main/scala-3
[info] * /.../oss/fs2/shared/src/main/scala-3

Path should be /.../oss/fs2/io/src/main/scala-3

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.