Tutorial¶
Avast! Welcome to the rever tutorial! This document will teach you the ropes of releasing software with rever. Let’s go sailing!
Writing Custom Activities¶
In your rever.xsh
file, you have the ability to provide additional, custom activies that
are specific to your project. Each activity is composed of a few different components:
A string name that uniquely identifies the activity
A callable that performs the actions for the release activity
A set of strings that specify the dependencies for this activity, by default this is an empty set.
A callable that is able to undo the action of the activity (optional)
A description of the activity
There are a couple of ways to write activities. The easiest is to use the activity decorator.
from rever.activity import activity
Simply use this on a function to create an activity of the name of the function. For example, let’s write a simple activity that runs the test suite with pytest:
from rever.activity import activity
@activity
def run_tests():
cd tests
pytest
cd ..
$ACTIVITIES = ['run_tests']
Furthermore, like with other activities, custom activities can accept arguments and keyword arguments. These are then settable by environment variables. Let’s say that we only want to test specific files, but by default we want to test all of them. We could instead write the following,
from rever.activity import activity
@activity
def run_tests(files=()):
"""Running the test suite."""
cd tests
pytest @(files)
cd ..
$ACTIVITIES = ['run_tests']
# by default, the environment variable $RUN_TESTS_FILES will be mapped
# to the files kwarg of the run_tests() function.
$RUN_TESTS_FILES = ['test_me.py', 'test_you.py']
Also note that in the above, the docstring of the function becomes the description for the
activity automatically! You can also set the name
, deps
, undo
, and desc
. For
example, if you want to make the tests depenendent on another install activity, you could write:
@activity(deps={'install'})
def run_tests(files=()):
"""Running the test suite."""
cd tests
pytest @(files)
cd ..
In certain situations, it is also useful for activities to know how to undo themselves. For example,
consider the case where you want to build a source tarball. If the user rewinds this activity,
the tarball should be deleted from the filesystem. Activities have an undoer()
decorator
(like setter()
and deleter()
for properties) that registers an undo function. Thus, our
source tarball activity could be implemented as:
from rever.activity import activity
$ACTIVITIES = ['tarball']
@activity
def tarball():
"""Creates a source tarball"""
tar czf project.tar.gz src/
@tarball.undoer
def tarball():
rm -f project.tar.gz
Alternatively, if you really need a lot of fine grained control or encapsulation, you can also
import the Activity
class and subclass it. Note that when you define an activity this way,
it does not register an instance of this activity for you in the $DAG
. You have to take
care of this bookeeping yourself. For example, the tarball activity can be implemented as
follows:
from rever.activity import Activity
class Tarball(Activity):
def __init__(self, **kwargs):
super().__init__()
self.name = 'tarball'
self.deps = {'install'}
self.desc = "Creates a source tarball"
self.requires = {"commands": {"tar": "tar"}}
def __call__(self, filename='project.tar.gz'):
tar czf @(filename) src/
return True
def undo(self):
rm -f *.tar.gz
$DAG['tarball'] = Tarball() # register the activity
$ACTIVITIES = ['tarball']