Skip to content
Support for running native code by Arquillian
Java
Find file
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
spacelift-api
spacelift-impl
.gitignore
.travis.yml
README.asciidoc
pom.xml

README.asciidoc

Arquillian Spacelift Build Status

Arquillian process and package manager. Makes executing an external process or fetching platform depends dependencies an easier job.

Making it part of your extension

In your project, import following artifact:

<dependency>
    <groupId>org.arquillian.spacelift</groupId>
    <artifactId>arquillian-spacelift</artifactId>
    <version>${version.arquillian.spacelift}</version>
</dependency>

You can use Spacelift both with and without Arquillian.

How to use the extension

Arquillian Spacelift provides a set of tools (and tasks) that can be used to encapsulate execution of any command into block that can be executed asynchronously and repeated if needed. You reuse a set of existing tasks and implement your own tasks.

Task

Arquillian Spacelift provides you a concept of a task. Task is isolated amount of work, defined by its input, output and transition function that transforms input into output. Task is always executed asynchronously.

How do I create new tasks?

Task is defined by class that represents its payload. You prepare tasks by calling Spacelift utility

Spacelift.task(DownloadTool.class)

Once task is created, you get access to API defined by task class itself.

I have task created. How do I execute it?

Just call execute(). This will asynchronously send task to execution service that will be responsible for its execution.

How do I run more tasks together?

Task can be chained together by using then(NextTaskName.class) call. There is following rules for chaining tasks: Input of next task must much output of current task. If next task input is type of Object, it can be chained to any task. Object usually means that you don’t care about input of next task at all.

I already have input for a task. How do I pass it to the task?

Just call Spacelift.task(input, NextTaskName.class)

How do I create my own tasks?

Extend abstract class Task and implement process(INPUT) method.

Execution

Calling execute() on a task will create an execution. You can use this object to reference execution in future.

Blocking execution

You can run await() or awaitAtMost(long,TimeUnit) to block current thread and get the result. For latter call, if result in not computed within time limit, TimeoutExecutionException is thrown.

Scheduled execution

You can force Spacelift to re-execute a chain of task periodically until results satisfies a condition or timeout is met by calling until(long,TimeUnit,ExecutionCondition) call. By default, this will be schedule to re-execute every 500 ms. You can change this behavior by reexecuteEvery(long,TimeUnit) call.

Terminating execution

You can kill the execution by calling terminate() method. After terminating, you might be able to retrieve partial execution value by calling await() but this behavior cannot be guaranteed for all types of tasks, as execution might be atomic. In such circumstances, task should return null if it figures out if was forcefully terminated before it finished the work.

Current tasks are:

  • DownloadTool: Nothing → File, download can download anything to a file

  • UnzipTool: File → File, unzip can unzip an archive to a directory

  • CommandTool: Nothing → ProcessResult, run runs(spawns) an external command

Command tool provides following API:

Program name

Program name is defined by processName(String). It must be on system path or it must be a full path. Spacelift does not check for its validity.

Program parameters

Program parameters are defined by parameter(String), parameters(String...), parameters(List<String>) and splitToParameters(String). The last method splits a string into sequence of parameters according to non-escaped spaces.

Program command

Instead of setting program name and program parameters, you can use command(Command) and command(CommandBuilder) methods to define what will be executed. These methods will override any values set by prior program name and parameters calls.

Process exit value

Process is expected to exit with value 0. It it exits with different value, ExecutionException is thrown. However, you can override this behavior via shouldExitWith(int...) call.

Process interaction

You can consume process output and provide an input to the process execution. Use interaction(ProcessInteraction) or interaction(ProcessInteractionBuilder) call.

Working environment

By default, process inherits working directory and environment of currently running JVM process. If you are not happy with such behavior, you can use workingDir(String) and addEnvironment(Map) or addEnvironment(String...) methods to modify it.

Cleanup

By default, process is terminated with JVM shutdown. If you want to change that behavior, you can invoke runAsDaemon(true) method.

Command tool returns ProcessResult. You can use this object for instance to check output returned by the command.

CommandTool is nice but I want to have something platform independent. How do I achieve that?

Create your own tool or command and reuse existing CommandTool there.

ProcessInteraction

ProcessInteraction defines a way how to interact with and handle output of process executed by CommandTool. You have ProcessInteractionBuilder convenience builder available:

Input handling

Use when(String) and replyWith(String) or terminate() to define non-interactive handling of process input. Process output, split into separate lines is matched against pattern provided by when(String). Answer can either be a string to be typed or you can force process termination by using terminate()

Output/error printing

Use when(String) and printToOut() or printToErr(String) to define patterns that if matched against output line, are printed either to standard output or standard error output

Process name

By default, a process output is prefixed by process name, defined by first parameter of Command. Use outputPrefix(String) call to override this prefix. You can also set it to null or empty string if you want process output to be indistinguishable from other output

Initial input

Some commands might require you to provide input before the very first output is available. In such cases, you can use whenStarts() and typeIn(String) combination to provide text that will be written to process input right after process is started

TODO

Currently missing features:

  • support to get platform dependent bits automatically

  • provide metadata format to simplify platform dependent execution

Releasing new version

In order to release new version, execute following Maven command:

mvn clean release:prepare release:perform

Then:

  1. Verify the build from staging repository

  2. Make sure all JIRAs are closed

  3. Release version in JIRA and create next version if not available

  4. Promote the build to the stable Maven repository

  5. Push commits and tag created by maven-release-plugin to the repository.

Something went wrong with that request. Please try again.