Conscript 

Conscript is a distribution mechanism for Scala apps using GitHub and Maven repositories as the infrastructure. You can use it to install and update apps similar to APT or Home Brew.

It does less than you think, because the sbt launcher does more than you think. More on that later.

Installing conscript 

Set up environment variables 

Depending on your OS the format might be different, but set up the following three environment variables.

export CONSCRIPT_HOME="$HOME/.conscript"
export CONSCRIPT_OPTS="-XX:MaxPermSize=512M -Dfile.encoding=UTF-8"
export PATH=$CONSCRIPT_HOME/bin:$PATH

There are three methods of installation available

Cross platform 

Download the conscript runnable jar. On most OSes you can run it by double-clicking, but if that doesn’t work you can also run it from the command line.

$ java -jar conscript_2.11-0.5.2-proguard.jar

A “splash screen” will appear during installation. Don’t close it until you see a message that cs was installed, or that something went wrong.

Linux, Mac 

If you prefer, you can install conscript by piping this shell script.

wget https://raw.githubusercontent.com/foundweekends/conscript/master/setup.sh -O - | sh

Windows 

If you prefer, you can download the PowerShell script and run it.

Using conscript 

The main thing you do with conscript is install and update commands based on launchconfig. launchconfig files are stored in GitHub projects, which you pass into the cs command. For example, this installs the giter8 templating system:

$ cs foundweekends/giter8

launchconfigs specify a version of the app to use, but you can override that by specifying an explicit version with another slash:

$ cs foundweekends/giter8/0.2.1

Project owners may also decide to push pre-release or other alternate launchconfig to different branches on GitHub. Use can tell conscript read launchconfigs from another branch with the --branch or -b option.

$ cs foundweekends/giter8 --branch staging

Cleaning boot directory 

If at some point your conscript boot directory contains stale/suspect artifacts such as snapshot releases, you can clean it:

$ cs --clean-boot

When you next run any conscripted app (such as cs) it will fetch its cleaned dependencies back into the shared boot directory; generally it only has to look as far as the local ivy cache to find them.

How does conscript work? 

Conscript does less than you think, because the sbt launcher does more than you think. What?


What conscript does:

What sbt launcher does:

So conscript just assumes a convention and helps you adhere to it. Suppose you’ve configured $CONSCRIPT_HOME to $HOME/.conscript.

Then $CONSCRIPT_HOME/boot is used as a boot directory for all. App launchconfigs are stored according to the GitHub project name and the script name, such as:

$CONSCRIPT_HOME/foundweekends/conscript/cs/launchconfig

And finally, shell scripts are created in $CONSCRIPT_BIN (default: $CONSCRIPT_HOME/bin) that reference launchconfigs, for example, ~/.conscript/bin/cs. This is how the shell script looks like on Mac:

#!/bin/sh
java -jar /Users/foo/.conscript/sbt-launch.jar \
  @/Users/foo/.conscript/foundweekends/conscript/cs/launchconfig "$@"

Once the shell script is created, now it’s up to the sbt launcher to carry out the actual work of fetching artifacts and running the app.

Private repositories 

Conscript supports private github repos using github’s oauth flow for non-web apps.

To authenticate and store a permanent token, use the --auth parameter:

$ cs --auth yourname:yourpass

This stores an access token in ~/.conscript/config which is used for all future cs invocations. You can revoke tokens at any time in your GitHub account settings.

The sbt launcher can access private Maven/Ivy repos just as sbt itself can. Specify a credentials properties file, such as ~/.ivy2/.credentials, in the sbt.boot.credentials JVM property or SBT_CREDENTIALS environment variable. The launcher will use these credentials when accessing protected resources in the specified realm.

Making a conscripted app 

We hope you’ll make your own apps that use conscript.

ConscriptPlugin 

The ConscriptPlugin makes these easier to build and test. Add this to the following project/conscript.sbt:

addSbtPlugin("org.foundweekends.conscript" % "sbt-conscript" % "0.5.2")

Next enable ConscriptPlugin on the app subproject in build.sbt:

lazy val root = (project in file(".")).
  enablePlugins(ConscriptPlugin).
  settings(
    // other settings here
  )

The plugin brings in a “provided” dependency to sbt launcher-interface.

Entry point 

Make the entry point to your app by implementing xsbti.AppMain.

package example

class HelloApp extends xsbti.AppMain {
  def run(configuration: xsbti.AppConfiguration): xsbti.MainResult = {
    // get the version of Scala used to launch the application
    val scalaVersion = configuration.provider.scalaProvider.version

    // Print a message and the arguments to the application
    println("Hello world!  Running Scala " + scalaVersion)
    configuration.arguments.foreach(println)

    new Exit(0)
  }
  class Exit(val code: Int) extends xsbti.Exit
}

After one or two command line options, you might want to take a look at scopt to do commandline parsing.

launchconfig 

Next, add your sbt launchconfig file to src/main/conscript/XYZ/launchconfig (substitue XYZ with your script name such as g8 and cs):

[app]
  version: 0.1.0
  org: com.example
  name: hello
  class: example.HelloApp
[scala]
  version: 2.11.12
[repositories]
  local
  maven-central
  sonatype-releases: https://oss.sonatype.org/content/repositories/releases/

To learn more about the launchconfig, see sbt Launcher section of the sbt Reference Manual.

Bintray 

You can add arbitrary repositories to the repositories section, including a Bintray Maven repo. Here is the Bintray repo for foundweekends for example.

  foundweekends-maven-releases: https://dl.bintray.com/foundweekends/maven-releases/

csRun 

You can test the app by calling csRun XYZ command.

Conscripted apps 

Because conscipt uses a known path /src/main/conscript/ on GitHub, we can search the GitHub repos to discover conscripted apps.

Let us know if you’ve written a conscripted app.