Using the Release API

Kyle Adams ♞

Intended Audience

Level: Advanced

The release API is a tool for project admins and release techs. We will be using the command line tool curl and discussing basic HTTP and REST API concepts.

Purpose

The typical release process on SourceForge used to look like this:

  1. Upload your new files via SFTP, SCP, or rsync.
  2. Use the web interface to set the new files as the default downloads for their appropriate platforms.

The first step was easily scriptable as part of a release process. The second step was manual, which was a problem. One of Larry Wall's programmer virtues is laziness and having to take a manual step is a violation of that virtue. Here's the good news: that second step is now also automatable via a RESTful API. Here is how you can use that API to automate your entire release process.

Making the Request

We will walk through using curl to interact with the API, but you should be able to adapt this process to a variety of release scripts. Here is the full command; we will look at each part in detail:

curl -H "Accept: application/json" -X PUT -d "default=windows&default=mac&default=linux&default=bsd&default=solaris&default=others" -d "api_key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" https://sourceforge.net/projects/[PROJECT NAME]/files/[FILE PATH]

The API uses JSON, so the first step is to let SourceForge know that you will accept a JSON response by sending the appropriate Accept header:

-H "Accept: application/json"

Note that while the header is optional, it ensures you will always get a JSON response.


RESTful Grammar

RESTful APIs always pair an action (the verb) with a resource (the noun). For HTTP, the verbs are the HTTP methods POST, GET, PUT, and DELETE. These verbs correspond with Create, Read, Update, and Delete operations (CRUD).


Since we're updating information about a file, we need to specify the HTTP method PUT:

-X PUT

Next comes that data, the new information with which we want to update our file. For curl, this data is specified as a URL-encoded string, like so:

-d "default=windows&default=mac&default=linux&default=bsd&default=solaris&default=others"

In our case we want to set the default property (i.e., the default download) to a selection of different OSes. Your own data may vary depending on your situation; for example, you may only need to specify Windows for .exe or .msi files.

The next piece of data could have been included above, but it is important enough to examine separately. The API key is how we know this request is coming from you. Once we have the API key, we will use your permissions in determining whether or not the file can be updated.


Keep It Secret

Please treat the API key as a password. Don't share it with others. Don't include it in your script. Have your script read the password from a local config file. If you have multiple people in your project with the ability to do a release, they should each have their own API key. Finally: make sure you're always transmitting your API key over a secured connection, i.e., HTTPS.


Here is how to get your API key:

  1. Go to your account page.
  2. Click on the "Generate" button under the API Key field.
  3. Copy and paste the key that appears into your script's config file, etc.

Once you have the API key, pass it along with the rest of the data as the api_key parameter:

-d "api_key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

The last piece of the puzzle is to specify the REST noun: the file we're updating. SourceForge files follow a predictable URL pattern: https://sourceforge.net/projects/[PROJECT NAME]/files/[FILE PATH]. You can also get the URL by right-clicking on the file in the Files web interface and selecting Copy Link. You will get the download URL, which is actually https://sourceforge.net/projects/[PROJECT NAME]/files/[FILE PATH]/download, so remove the /download string at the end and you will have the correct URL:

https://sourceforge.net/projects/[PROJECT NAME]/files/[FILE PATH]

Note the "https": keep your API key safe!

We are back to the full command:

curl -H "Accept: application/json" -X PUT -d "default=windows&default=mac&default=linux&default=bsd&default=solaris&default=others" -d "api_key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" https://sourceforge.net/projects/[PROJECT NAME]/files/[FILE PATH]

Once you make that request, you will get JSON in response.

The Response

There are two basic responses: success and error. Here is what the JSON response looks like when there is an error:

{ "error": "You are not authorized for this operation." }

The actual error message may vary, but the error attribute will be present and set to a truthy value in the JSON object.

Here is what you will see when everything works:

{
  "result": {
    "file_type": "C program text (Zip archive data)",
    "explicitly_staged": false,
    "date": "Fri, 01 Jan 2000 12:00:00 GMT",
    "mtime": 100000000,
    "id": 1,
    "size": 10000,
    "x_sf": {
      "default": "windows,mac,linux,bsd,solaris,others"
    },
    "x_stage": 0,
    "downloadable": true,
    "stage": 0,
    "type": "f",
    "mime_type": "application\/x-zip",
    "staged_dir": 0,
    "vscan": "OK",
    "path": "",
    "crtime": 1262354489,
    "md5": "...",
    "sha1": "...",
    "name": "foo-1.0.0.zip",
    "staged": false,
    "modified": "Fri, 01 Jan 2000 12:00:00 GMT",
    "project": "example",
    "vscan_prog": null,
    "vscan_when": null
  }
}

In this case the JSON object is the file object, with all of its attributes, including the updated data. You can see the default attribute above now lists all the OSes we submitted in our PUT request.


Related

Community Docs: staff-tips
Documentation: API

  • Florian Haag
    Florian Haag
    2012-09-24

    This worked very well, though the docs are a little bit sparse: A list of which properties (beside the default download) can be set would be nice (e.g. download_label seems to be the human-readable file title that is used on the green download button).

    And of course, the alternative possibility of getting an Xml response rather than Json would come in handy for my build system that I use for deploying, which has built-in tasks to check parts of Xml documents, but none for Json (Nant).