sbt search maven plugin

What

This is a blog post about sbt plugin to query search.maven.org

tl;dr

show me the code

Why

Most development tasks can be done without leaving your favorite editor/ide nor console. Writing Scala code is no different: sbt gives you a lot of power to run code and tests, to package and publish application.

There is one small thing though, forcing you to leave that environment and go to a browser - to find the exact name of dependency for your project. Unless you have super memo powers you will probably have to check the group id for akka, or latest version for any other package that you would like to include in your project.

To make it even simpler, I created sbt-search-maven-plugin. Just type searchMaven something and everything is clear. This prints the same results as search.maven.org without leaving sbt.

Plugin development

In order to make this happen I had to get some knowledge on how to write a sbt plugin. There are three great sources you can check:

These are all great, but I wanted to create plugin that gets some user input from sbt shell, which is not covered in these references.

Input plugin

Plugin code is similar as in above examples, but main “entry” point for your code is different, as we need InputKey. There are some important places to look at:

build.sbt

The most important part for developing a plugin is

sbtPlugin := true

The whole build.sbt for this plugin.

extends AutoPlugin

The entry point for your code should be placed in an object that extends sbt.AutoPlugin. This in turn should have another object defined: autoImport with definition of task.

object autoImport {
  lazy val searchMaven = InputKey[Unit]("searchMaven", "Search maven")
}

Input key makes it possible to get input provided by user from sbt shell. To write some implementation we need one more thing:

override lazy val projectSettings = Seq(
  searchMaven := search(complete.DefaultParsers.spaceDelimited("<arg>").parsed, streams.value.log)
)

search from snippet above is a regular Scala function in which we can finally implement our new feature.

sbt.Keys._ contain a lot of useful things that we can use in our code, like scalaVersion defined in one’s project or streams.value.log, which we use in our plugin to print results to user.

The whole file can be found here

Additional sbt settings

There are two things that should be mentioned here.

To make your plugin be enabled by default you should add such override:

override def trigger = allRequirements
This simply says that this plugin will be activated when all required plugins are present. Plugins, that this plugin depends on, could be defined by overriding def requires (it’s empty by default)

This plugin doesn’t interact with code in project - it just searches for artifacts - so we don’t want our code to be run multiple times when it’s executed inside multimodule project. To avoid this, the additional setting has to be specified:

aggregate in searchMaven := false
This stops the task from running in submodules.

for testing

If you use version without SNAPSHOT suffix and you don’t want to get warnings about deprecation during packaging your plugin, just add isSnapshot := true to your build.sbt.

Testing sbt plugin

unit tests

Nothing fancy here, just simple unit test for code that’s not related to sbt.

scripted

Scripted is the default mechanism for testing sbt plugins by writing scripts for sbt. Search maven is not building anything, so we can just prepare basic script to check whether searchMaven command is available and executable with a success.

A special directory structure has to be used. Tests are placed in sbt-test in src. Under that directory another two directories have to be created for test group and test itself. The full path looks like this:

<projectHome>/src/sbt-test/<testGroup>/<testName>

In such a path test should be described as:

  • plugins.sbt inside of the project dir that adds plugin to the test project
  • test file that contains script (test scenario)
  • build.sbt file that describes the test build and an assertions for test. Assertions are written in form of the sbt tasks.

Compare the usage-help-test

Make it available for everyone

The best description can be found here. The screenshots are a bit outdated, but most of the content is still valid.

build.sbt can stay simple.

Contribution

You can pick a feature from the future work section in readme, implement issue with feature proposal (if any) or fix some bugs. Pull requests are very welcome!

Summary

This blog describes how to write a simple sbt plugin, test it and publish it.