Bitbucket is a code hosting site with unlimited public and private repositories. We're also free for small teams!

Close

Ringo-Kit

Ringo-Kit is an Atlassian Plugins 3 Universal Binary runtime "kit" that leverages RingoJS as its underlying web framework. Plugins 3 kits give Atlassian plugin developers a choice in frameworks and languages to use in building plugins. Plugins 3 kit projects are compiled into a JAR file that you can deploy remotely or inside an Atlassian application.

Here's what a simple Ringo-Kit plugin looks like:

var app = exports.app = require("atlassian/app").create();

app.configure({
  stylesheets: ["app"],
  scripts: ["app"]
});

app.get("/index", function (req, res) {
  res.send('Hello World!');
});

To get an overview of Plugins 3, visit the Plugins 3 Home where you'll find great documentation on getting started, core concepts, and an architectural overview.

Features

  • Bundles RingoJS for a mature set of libraries
  • Wrapping modules to expose services in idiomatic JavaScript
  • OSGi manifest generation assistance via a hard dependency on common packages
  • Automatic CoffeeScript support
  • Includes Handlebars and Underscore libraries

API Docs

You can access the Ringo-Kit API docs on developers.atlassian.com.

Getting Started

To build a Ringo-Kit plugin, you first need to install the AP3 developer tool. You can do so by running this in your console:

curl https://bitbucket.org/atlassian/ap3-sdk-bin/raw/master/ap3-setup.sh | sh

After installing AP3, enter the following command to create your first plugin:

ap3 new ringo-kit

AP3 first gathers information about your project with a few prompts. First it asks what template you want to use.

Choose the [basic] template and enter the name and namespace for your plugin. AP3 then creates your plugin project files inside a new directory: ./<name-of-your-plugin>.

Change to the new directory and have a look at the generated code with your favorite text editor or IDE.

cd <name-of-your-plugin>

Your directory should looks something like this:

.
├── README.md
├── atlassian-plugin.xml
├── lib
│   └── README.md
├── main.coffee
├── main.js
├── pom.xml
├── public
│   ├── css
│   │   └── app.css
│   └── js
│       └── app.js
└── views
    └── index.hbs

5 directories, 9 files

Choice between JavaScript or CoffeeScript

The basic template provides you with two ways to code your plugin: JavaScript or CoffeeScript.

In the root of your plugin directory, you'll find main.js and main.coffee. These files are the entry point for your plugin.

Ringo-Kit uses main.js if it exists, but looks for main.coffee if it doesn't. The template provides both so that you can choose between the two -- just delete the one you don't want.

Running your plugin

To run your plugin, you have a few choices. Ringo-Kit is a Universal Binary plugin kit. This means that you can deploy it remotely (from the OnDemand instance's perspective) on your own server, or you can install it directly on a JIRA or Confluence instance behind a firewall.

Deploying to RJC

The fastest way to get up and running is to just run your plugin against https://remoteapps.jira.com (RJC). This is the OnDemand instance for the Atlassian Plugins 3 project.

To deploy your plugin to this instance, you'll need to register for an account and then email developer-relations@atlassian.com. Once registered, you can deploy your test plugins to RJC.

Once you have access, running your plugin inside of RJC is as simple as:

ap3 start p3

The first time you run your plugin, a prompt asks if you would like to register the plugin with a remote host. It provides you a default ([rjc]). Select that and enter your username and password for RJC.

  .-. 
o(o_o)o AP3 SDK
( --- ) by Atlassian
--------------------
Downloading P3 container...
No local products are running and no remote hosts are configured!
Would you like to configure a remote host now? (Y/N) [Y]: 
Enter an id for the remote host entry [rjc]: 
Enter the url to the remote host [https://remoteapps.jira.com]: 
Enter your username for the remote host: you
Enter your password for the remote host: ********

AP3 then starts up your plugin inside the Plugins 3 container. In turn, it will do the following:

  1. Makes your local web server available on the internet by tunneling it through a "local tunnel" service running on lt39.info
  2. Registers your plugin into RJC
  3. Launches your browser and opens the RJC dashboard page

From the browser window, look for your plugin under the "More" menu in the header.

More menu

Your new plugin should look something like this:

Your new plugin

Deploying to a local JIRA or Confluence instance

You can use AP3 to start up a local JIRA or Confluence instance like so:

ap3 start [jira|confluence]

Once you've started JIRA or Confluence locally, you can start the P3 container in another console window:

ap3 start p3

AP3 detects that you have a local JIRA or Confluence instance running and automatically registers your plugin.

Building your plugin

One of the big benefits of Ringo-Kit over Servlet-Kit is that it's that it doesn't need to be compiled. JavaScript is a dynamic language and gets interpreted by the JVM at runtime. The end result is that you can change your code and refresh the page to see your changes immediately -- no need to wait around for your SDK or IDE to compile your changes, package it into a jar, then deploy it to the plugin system. With Ringo-Kit, your dev-loop is super fast.

main.js and main.coffee

In Ringo-Kit, you have a choice to write your plugin in JavaScript or CoffeeScript. Ringo-Kit determines what you're using through the existence of main.js or main.coffee. The [basic] Ringo-Kit template that's available through AP3 will have both files -- just pick the language you want to use and delete the other.

The main.(js|coffee) file is the entry point into your plugin. It's very similar to other micro web frameworks like Sinatra, Flask, and ExpressJS in that your controllers are defined through routes:

# I respond to GETs
app.get("/index", function (req, res) {
  res.send('Hello World!');
});

# I respond to POSTs
app.post("/index", function (req, res) {
  res.send('Hello World!');
});

# I respond to PUTs
app.put("/index", function (req, res) {
  res.send('Hello World!');
});

# I respond to DELETEs
app.delete("/index", function (req, res) {
  res.send('Hello World!');
});

# I respond to GETs, POSTs, PUTs, and DELETEs
app.all("/index", function (req, res) {
  res.send('Hello World!');
});

The second parameter in the methods above is a callback that has access to the Request and Response objects.

Layouts and Views

Ringo-Kit currently uses Handlebars for it's templating language on the server-side (you're free to use whatever you want on the client-side). At some point we'll support Google Closure templates (aka, Soy templates) as well.

Configuration

Ringo-Kit attempts to simplify things for you in most cases. One of these is how it uses layouts. By default, you don't need to create a layout for your pages. Ringo-Kit has a default layout that adds in the necessary JavaScript and CSS to that most plugins will need. If you want to use AUI in your plugin, all you have to do is specify it in your app.configure block:

app.configure({
  // Use AUI 5.0 (optional)
  aui: "5.0",

  // Array of stylesheets you want injected into your pages.
  // CSS are located in public/css/
  stylesheets: ["app"],

  // Array of scripts you want injected into your pages.
  // Scripts are located in public/js/
  scripts: ["app"],

  // Options for the AP client JavaScript that's loaded on
  // your page. The AP client JS has utilities for calling
  // REST and XMLRPC APIs through the parent as well as
  // resizing the iframe when the page dimensions change.
  clientOptions: {
    resize: "auto" // Enables auto resizing of your iframe
  }
});

If you want to override the default layout, you can do so by simply adding an overide layout*.hbs file in your views directory.

Rendering a view

Rendering a view from your route/controller is easy... just send execute one of the render* or send* methods available from the Response object. Most of the time, you'll just use the response.render() method like so:

// Render the "home" view passing a JSON object as context
// for the view
res.render("home", {
  message: "Hello World"
});

Here's what the corresponding view/home.view might look like:

<h1>{{message}}</h1>

In addition to passing local objects as context for the view, you also have access to a set of global context properties and methods that you can use at your disposal.

The plugin descriptor: atlassian-plugin.xml

Now that you've got the basics of rendering a page, you're probably wondering "what can I do with plugins?" The easiest way to answer that is to point you to the Interactive Plugin Descriptor Guide. This guide will allow you to see all of the plugin points available through the Atlassian Plugin platform.

Reporting issues

Issues are hosted on Bitbucket. If you find a bug, report it.

Contributing

The Ringo-Kit code is hosted at Bitbucket: https://bitbucket.org/atlassian/ringojs-kit

Pull requests are very welcome. All we ask is that if you add something to the API, please provide the documentation with it. Also, right now, tests are slim to none -- please add tests with your features.

Acknowledgments

License

Apache License v2. See LICENSE.txt

Recent activity

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.