Fury introduces a number of concepts which it is useful to know about before using it, some of which will be new.
Fury always runs inside a layer. A layer represents a collection of
related projects you are working on, and is associated with a directory on your
filesystem which Fury has initialized. It is also a
The root directory of a layer will contain a file called
which stores all the information relating to the layer. The file is kept
git’s version control, and is modified directly by Fury.
Source files for the Fury build may reside in the same repository, or may be included from an external repository.
The file format is designed to be human-readable, particularly when viewing diffs between different versions, but not human-writable. While it may be possible to make changes to the file manually, the format is sensitive to whitespace and structural changes, and it is not recommended.
git commands can be used to manage changes to the
git reset --hard
will return the Fury layer to its last commited state.
A project should correspond to most people’s intuition of a project: it is
the same as a project in
sbt or on GitHub. A project
has a name, is composed of a number of modules (see below), and is associated
with a single license. A typical Fury project will be associated with a single
git source repository (though it may depend on several).
Example projects might be,
A module is a single phase of compilation; a single invocation of the Scala
compiler, or less often, running something other than a compiler (such as
code-generation). A module typically takes some source input and produces some
binary output. Fury manages a graph of dependencies between modules so that In
sbt, a module is called a “submodule”.
Four different module types are supported, and more may be added in the future.
library (the default),
Example modules may be,
A schema is Fury’s approach to handling builds of the same collection of projects (or mostly the same) for several different target versions of Scala, or different platforms (e.g. Scala Native). A project which only targets a single version of Scala should not need to worry about schemas. Variations between schemas are typically small, and Fury commands which change the build are designed to make global changes to all schemas the default, and introducing new variations the exceptions.
Fury makes it very easy to view the differences between pairs of schemas.
In future, schemas may also handle some other scenarios, for example, variants of a library with different dependencies, or creating variations of a build which have only binary dependencies, to make publishing to Maven Central possible.
Example schemas may be,
scala-2.12-cats or even
scala-2.12.3 for projects which
build differently between different minor versions of Scala.
Source repositories (repos)
Source repositories, being a particular commit hash of a
may be associated with a schema, which makes source code contained with that
repository available for modules to compile, and layers available to import
The layer itself is in a
git repository, so it is always available
alongside other repositories, and is called
An import allows an entire schema of projects defined in a different layer (which has been published online) to be made available in a schema in your layer, for use as dependencies to modules in that layer.
Imports are the means by which schemas within layers compose, and are specified recursively, forming a tree of dependencies.
Every module which invokes a compiler will need sources to compile. These are specified as a list of directories within source repositories.
Sources may come from the local repository (the one containing the layer), from an external repository which has been defined within the layer, or from a shared space where generated files may be placed.
A dependency is a link between two modules, and requires one module to be compiled (or run) as a prerequisite to the other. The binary output of the prerequisite will be passed to the classpath of the module which depends upon it.
Dependencies may be marked as “intransitive”, which means that its output will be passed to the classpath of the module which depends directly upon it, but not to downstream modules.
Additionally, a module may depend on specific binaries, which Fury will download
automatically from Maven Central using
Most entities, such as modules, projects, schemas and repositories have names. These identifiers permit only lower-case letters, digits and hyphens, and must start with a letter and cannot contain two or more adjacent hyphens.
At any time, a layer may or may not be consistent, which means that all its references resolve to valid entities. This is a requirement to run a build, or publish a layer. But it is possible for a layer to be in an inconsistent state while modifications are being made.
Users will be notified of any inconsistencies in the state of the layer when these prevent a certain operation, such as running the build, from completing.
The references between entities in a Fury layer must ultimately be consistent, but the same reference can point to different entities in different schemas.
For example, a reference to some sources in the repository with the name
magnolia will resolve to the repository that is specified for the current
scala-2.12, which may be (for example) commit hash
scala-2.11 schema may define the
magnolia repository to use a
different branch, with the commit hash
afb2860 instead. All the references to
magnolia:src/core would be unchanged across the two schemas, but would point
to a different set of files.
Another very common example may be references to the compiler called
scala/compiler. In your
scala-2.11 schemas, this would be
interpreted in the context of the the projects imported from the published
layer, and each import specifies not only a repository corresponding to a
published layer, but also a schema within that layer.
So if the published layer had schemas corresponding to every minor
published version of Scala, we might choose to import from
scala-2.12 schema, and from
scala-2.11.11 to our
Each external schema would contain a project called
scala, and each
project would contain a module called
compiler, defined differently for each.
What this means is that many modules could be defined in the same schema, all
with indentical references to
scala/compiler, but by making just a single
change to an import in other schemas, a different choice of compiler can be
Interaction with Fury is always through a command-line interface. This interface has a number of operations whose primary purpose is to manage the build file, and run builds.
No guarantees are made about the stability of the command-line API, and
although it would be possible to distribute builds as scripts of
commands to be run, there are no guarantees about their portability.
The current private beta release of Fury lacks certain features which will need to be implemented before a full public release can be made. These are documented on the issue tracker on GitHub.