Python toolkit for the Rally REST API

Rally supports a REST API that enables you to retrieve representations of entities in Rally, create entities in Rally, update existing entities in Rally and with proper permissions, delete entities in Rally.

Once you have the pyral package installed, all you need is a valid subscription to Rally, working credentials and the name of the workspace and project you want to interact with and you’re on your way!

For more information on obtaining a Rally subscription, visit the Rally website.

For more information on how workspaces and projects in Rally are set up and configured, consult the Rally documentation available via the ‘Help’ link from the Rally landing page displayed after your initial login.

Simple Use

Here’s a prototype of simple use of the pyral package.:

import sys

from pyral import Rally, rallyWorkset

options = [opt for opt in sys.argv[1:] if opt.startswith('--')]
server, user, password, apikey, workspace, project = rallyWorkset(options)
rally = Rally(server, user, password, workspace=workspace, project=project)
rally.enableLogging('rally.simple-use.log')

response = rally.get('Release', fetch="Project,Name,ReleaseStartDate,ReleaseDate",
                     order="ReleaseDate")

for rls in response:
    rlsStart = rls.ReleaseStartDate.split('T')[0]  # just need the date part
    rlsDate  = rls.ReleaseDate.split('T')[0]       # ditto
    print("%-6.6s  %-16.16s   %s  -->  %s" % \
          (rls.Project.Name, rls.Name, rlsStart, rlsDate))

Rally Data Model

All Rally entities belong to a hierarchical data model and every Rally entity ultimately is a descendent of the PersistableObject class. There are several branches in the data model, and each branch has its own set of attributes differentiated according to the functional capabilities and information tracking needs that characterize the branch. For more information on the Rally data model, consult the Rally documentation available via the ‘Help’ link from the Rally page displayed after the initial login.

Rally Entities and Artifacts

In the Rally vernacular, a logical entity is called a type. Some examples of Rally types are UserStory, Defect, Release, UserProfile. There is a subset of types that are usually what a user of pyral will be interested in called artifacts. An artifact is either a UserStory, Defect, Task, DefectSuite, TestCase or TestSet. The Python toolkit for the Rally REST API (pyral) is primarily oriented towards operations with artifacts. But, it is not limited to those as it is very possible to view/operate on other Rally entities such as Workspace, Project, UserProfile, Release, Iteration, TestCaseResult, TestFolder, Tag and others.

Full CRUD capability

The Python toolkit for the Rally REST API offers the full spectrum of CRUD capabilities that the credentials supplied for your subscription/workspace/project permit. Rally REST API did not originally support bulk operations when this toolkit was written. Since the 2017/2018 timeframe the Rally REST WSAPI has provided some bulk operations, but this toolkit doesn’t use those or provide access to them. There are example usages of pyral that you can adapt to offer the end-user or scriptwriter the capability of specifying ranges of identifiers of artifacts for querying/updating/deleting.

Rally Introspection

The Python toolkit for the Rally REST API makes it easy to obtain the names of Rally types (entities) and the attributes associated with each type. You can also use pyral capabilities to obtain the list of allowed values for Rally type attributes that have a pre-allocated list of values.

Queries and Results

The Rally REST API has two interesting characteristics that the Python toolkit for the Rally REST API insulates the scriptwriter from having to deal with. The first is that the Rally REST API has a maximum “pagesize” to limit volume and prevent unwarranted hijacking of the Rally SaaS servers. But, having script writers deal with this directly to obtain further “pages” would be burdensome and out of character with the mainstream of Python interfaces to SaaS services. The Python toolkit for the Rally REST API (pyral) takes care of the paging transparently, allowing the scriptwriter to treat a result set as an iterator, merely looping through the results without any indication of any sequence of further requests on the Rally server.

The second characteristic is that the Rally REST API for some queries and results returns not a scalar value but a reference to yet another entity in the Rally system. A Project or a Release are good examples of these. Say your query specified the retrieval of some Stories, and you listed the Project as a field to return with these results. From an end-user perspective, seeing the project name as opposed to an URL with an ObjectID value would be far more intuitive.

The Python toolkit for the Rally REST API offers this sort of intuitive behavior by “chasing” the URL to obtain the more human friendly and intuitive information for display. This sort of behavior is also present in so-called “lazy-evaluation” of entity attributes that may be containers (collections) as well as references. The scriptwriter merely has to refer to the attribute with the dot (‘.’) notation and pyral takes care of the communication with the Rally server to obtain the value. There are two significant advantages to this, one being lightening the load on the server with the reduction of data returned and the other being easy and intuitive attribute access syntax.

The query relational operators that pyral supports are::

=  !=  >  <  >=  <=  contains  !contains  in  !in  between  !between

The contains and !contains relational operators are helpful in expressing a condition where you are looking for a field that does (or does not) contain a specific substring. For example ‘Name contains “Prior Art”’ or ‘ThermalPhase !contains “hot lava”’. The in and !in relational operators are commonly used for expressions involving subsets of a finite set of values. For example ‘Severity in High, Burning, Explosive’ or ‘Priority !in Moribund, Meh’. The between and !between relation operators are commonly used for expressions involving date ranges. For example ‘CreationDate between 2018 and 2022’ or ‘LastUpdated !between 2021-09-22T00:00:00.000Z and 2021-09-22T07:59:59.999Z’.

Custom Fields

Most Artifact types in Rally can be augmented with custom fields. As of Rally WSAPI v2.0, the ElementName for a custom field is prefixed with ‘c_’. The pyral toolkit allows you to reference these fields without having to use the ‘c_’ prefix. For example, if your custom field has a DisplayName of ‘Burnt Offerings Index’ you can use the String of ‘BurntOfferingsIndex’ in a fetch clause or a query clause or refer to the field directly on an artifact as artifact.BurntOfferingsIndex.

PortfolioItem tips

Rally has 4 standard PortfolioItem sub-types (Theme, Strategy, Initiative, and Feature). In this toolkit, for the primary methods (get, create, update, delete), you must supply a entity name (eg, ‘Story’, ‘Defect’, ‘Task’, etc). For a PortfolioItem sub-type you may specify just the name of the sub-type, ie., ‘Feature’ or you may fully qualify it as ‘PortfolioItem/Feature’.

Introduction of Dyna-Types

Prior to the release of Rally WebServices API v2.0, Rally introduced a modification of their data model, which is termed dyna-types. This modification offers a means of establishing and using a parent type and defining sub-types of that parent. The PortfolioItem type is now an “abstract” type from which there are some pre-defined sub-types (Theme, Strategy, Initiative, Feature). By convention, the preferred way to identify a PortfolioItem sub-type is via slashed naming, eg. ‘PortfolioItem/Feature’. While it is possible to identify a PortfolioItem sub-type by the sub-type name, eg, (Theme), this is not the preferred means. The reason for the latter statement is that with dyna-types it is possible to define new “abstract” types and define sub-types therefrom that may have names identical to a sub-type whose parent differs from your newly defined “abstract” type.

An example of this is a fictional “abstract” parent type named “Bogutrunk” (for a type that encompasses stories about requests for things you’ll never implement and aren’t bugs, but you want to track them anyway). Additionally, let’s say you define some sub-types whose parent type is “Bogutrunk” and are named “Outlandish”, “NonScalable”, “Theme” and “Feature”. Now, identifying a specific NonScalable Bogutrunk item is unambiguous; you’d just specify the entity in any pyral get/put/post/delete as a “NonScalable”. But, you cannot use that convention for a “Feature”. You’d need to specify one as a “Bogutrunk/Feature” to disambiguate from a “PortfolioItem/Feature”. The main take-away here is that if you don’t use PortfolioItem instances with pyral, you don’t have worry about this. If you use PortfolioItem instances with pyral or you’ve defined your own “abstract” parent types and specific sub-types thereof, you are strongly encouraged to use the slashed specification to avoid ambiguity in identifying the Rally entity type.

In the event your organization has created a sub-type with the same name as a standard Rally entity (eg, ‘Project’, ‘Release’, ‘Milestone’, etc.) you will be unable to use this toolkit to access those items. There will be no consideration given to supporting any custom PortfolioItem sub-type whose name conflicts with a Rally standard entity name.