Build server REST API¶
This is a proposed standard for a REST API for build clients to use to communicate with a build server. It’s inspired by pony-build, and generally rather Python-oriented, but the goal is language-agnostic.
Contents
API Usage¶
Registering a new project¶
-> PUT /{project} {Project} <- 201 Created Location: /{project}/builds/{build-id}
If a project already exists, a 403 Forbidden will be returned.
Users may register with authentication via HTTP Basic:
-> PUT /{project}
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
{Project_}
<- 201 Created
Location: /{project}/builds/{build-id}
If this is done, then that authorization may be repeated in the future to update/delete the project or to delete builds. No explicit user registration step is needed; users will be created on the fly.
Warning
Since the authorization uses HTTP Basic, build servers should probably support SSL for the security-conscious.
Reporting a build¶
-> POST /{project}/builds {Build} <- 201 Created Location: /{project}/builds/{build-id}
Incremental build reporting¶
-> POST /{project}/builds {Incremental build} <- 201 Created Location: /{project}/builds/{build-id}/progress -> POST /{project}/builds/{build-id}/progress {Build step} <- 204 No Content Location: /{project}/builds/{build-id} -> POST /{project}/builds/{build-id}/progress {Build step} <- 204 No Content Location: /{project}/builds/{build-id} ... -> DELETE /{project}/builds/{build-id}/progress <- 204 No Content Location: /{project}/builds/{build-id}
API Reference¶
Representation formats¶
- JSON.
- UTF-8.
- All datetimes in RFC 2822.
URIs¶
URI | Resource | Methods | Notes |
---|---|---|---|
/ | Project list | GET | |
/{project} | Project | GET, PUT, DELETE | Only the user that created a project may update (PUT) or delete it. |
/{project}/builds | Build list | GET, POST | |
/{project}/builds/latest | – | GET | 302 redirect to latest build. |
/{project}/builds/{build-id} | Build | GET, PUT, DELETE | Builds may not be updated; PUT only exists if clients wish for some reason to use a predetermined build id. Only the user that created a build or the project owner may delete a build. |
/{project}/builds/{build-id}/progress | Build progress | GET, POST, DELETE | |
/{project}/tags | Tag list | GET | |
/{project}/tags/{-listjoin|-|tags} | Build list | GET | |
/{project}/tags/{-listjoin|-|tags}/latest | – | GET | 302 redirect to latest build given tags |
/users | User list | GET | |
/users/{username} | User | GET, PUT, DELETE | Authentication required to PUT or DELETE. |
/users/{username}/builds | Build list | GET | |
/users/{username}/builds/latest | – | GET | 302 redirect to latest build by user |
All resources support OPTIONS which will return a list of allowed methods in the Allow header. This is particularly useful to check authentication for methods that require it.
Resources¶
Build¶
Representation:
{ 'success': true, # did the build succeed? 'started': 'Tue, 20 Oct 2009 10:20:00 -0500', 'finished': 'Tue, 20 Oct 2009 10:22:00 -0500, 'tags': ['list', 'of', 'tags'], 'client': { 'host': 'example.com', # host that ran the build 'user': 'http://example.com/' # user to credit for build. 'arch': 'macosx-10.5-i386' # architecture the build was done on. ... [1] }, 'results': [{Build step}, ...], 'links': [{Link}, ...] }
Notes:
[1] | Clients may include arbitrary extra client info in the client record. |
Links:
Rel | Links to |
---|---|
self | This build |
project | The project this is a builds of. |
tag | A tag this build is tagged with. There’ll probably be many tag links. |
Build list¶
Representation:
{ 'builds': [{Build}, ...], 'count': 100, # total number of builds available 'num_pages': 4, # total number of pages 'page': 1 # current page number 'paginated': true # is this list paginated? 'per_page': 25, # number of builds per page 'links': [{Link, ...}] }
Links:
Rel | Links to |
---|---|
self | This build list |
project | The project this is a list of builds for (if applicable). |
user | The user this is a list of builds for (if applicable). |
tag | The tag this is a list of builds for (if applicable). |
latest-build | URI for the redirect to this project’s latest build. |
next | The next page of builds (if applicable). |
previous | The previous page of builds (if applicable). |
first | The first page of builds. |
last | The last page of builds. |
Build progress¶
Used as an entry point for incremental build reporting
Empty representation – the existence of the resource indicates an in-progress build. When the build is done, the resource will return 410 Gone.
Build step¶
Representation:
{ 'success': true, # did this step succeed? 'started': 'Tue, 20 Oct 2009 10:20:00 -0500', 'finished': 'Tue, 20 Oct 2009 10:22:00 -0500, 'name': 'checkout', # human-readable name for the step 'output': '...' # stdout for this step 'errout': '...' # stderr for this step ... [2] }
Notes:
[2] | Build steps may include arbitrary extra build info in the record. |
Incremental build¶
POST this resource to a build list to signal the start of an incremental build.
Representation
{ 'incremental': true, # never false 'started': 'Tue, 20 Oct 2009 10:20:00 -0500', # when the build started on # the client (not when the # packet was posted!) 'client': { 'host': 'example.com', # host that ran the build 'user': 'username' # user to credit for build. 'arch': 'macosx-10.5-i386' # architecture the build was done on. ... [3] }, 'tags': ['list', 'of', 'tags'], }
Notes:
[3] | Clients may include arbitrary extra client info in the client record. |
Link¶
Used all over the damn place to knit resources together.
Representation:
{
'rel': 'self', # identifier for the type of link this is
'href': 'http://example.com/', # full URL href
'allowed_methods': ['GET'], # list of methods this client can perform on said resource
}
Project¶
Representation:
{ 'name': 'Project Name', 'owner': 'username', # the user who created the project, if applicable. 'links': [{Link}, ...] }
Links:
Rel | Links to |
---|---|
self | This project. |
build-list | This project’s build list. |
latest-build | URI for the redirect to this project’s latest build. |
tag-list | This project’s tag list. |
Project list¶
{ 'projects': [{Project}, ...], 'links': [{Link}, ...] }
Links:
Rel | Links to |
---|---|
self | This server. |
Tag¶
Tag detail.
{ 'tags': ['list', 'of', 'tags'], # Or just a single ['tag'] if this # is one tag. 'builds': [{Build}, ...], 'count': 100, # total number of builds w/this tag 'num_pages': 4, # total number of pages 'page': 1 # current page number 'paginated': true # is this list paginated? 'per_page': 25, # number of builds per page 'links': [{Link, ...}] }
Links:
Tag list¶
Representation:
{ 'tags': ['tag1', 'tag2', 'tag3'], 'links': [{Link, ...}] }
Links:
Rel | Links to |
---|---|
self | This tag list |
project | The project in question. |
tag | Each tag used by the project gets a link. |
User¶
Representation:
{ 'username': 'username', 'links': [{Link}, ...] }
Links:
Rel | Links to |
---|---|
self | This user |
builds | Build list for this user. |
User list¶
Representation:
{ 'users': [{User}, ...], 'count': 100, # total number of users available 'num_pages': 4, # total number of pages 'page': 1 # current page number 'paginated': true # is this list paginated? 'per_page': 25, # number of users per page 'links': [{Link, ...}] }
Links:
Rel | Links to |
---|---|
self | This user |