Reset the webhooks for Drone – Open Source CI Server

Drone is a useful Open Source CI Server. You can host the private and dedicate CI environement.

Once you delete or modify the webhooks on the github (enterprise), never reset the setting from Web UI. NOT YET IMPLEMENTED.

But, we have APIs.

First of all, get the api key from


Let’s curl


API Reference:

Deactivate is also available.


Custom Docker Image for Open Source

Have you tried open source edition of
You can get your own private CI server through the use of the open source edition. It’s really awesome.

Drone provides a lot of docker images

# these two are base images. all Drone images are built on top of these
# these are BIG (~3GB) so make sure you have a FAST internet connection
docker pull bradrydzewski/ubuntu
docker pull bradrydzewski/base

# clojure images
docker pull bradrydzewski/lein             # image: lein

** snip **

# ruby images
docker pull bradrydzewski/ruby:2.0.0       # image: ruby2.0.0
docker pull bradrydzewski/ruby:1.9.3       # image: ruby1.9.3

# scala images
docker pull bradrydzewski/scala:2.10.3     # image: scala2.10.3
docker pull bradrydzewski/scala:2.9.3      # image: scala2.9.3

However, there are many variations of image, drone supports a custom image.
For example, you can create the custom images what have any distribution, any language, any version, any databases, and any libraries you want to link. It also saves the test time, because drone doesn’t cache the test environment (except cache section on .drone.yml), build all from the scratch each test phase.

This article describe how to create a docker image for drone.

Setup Development Environment

Drone uses docker for building a sandbox for each test. While you are in Linux, install from the packager. If not use Boot2Docker. On this section, uses drone development environment on Vagrant.

Before you enter the setup process, install VirtualBox and Vagrant.

$ git clone
$ cd drone
$ vagrant up default
$ vagrant ssh default

Take a coffee break to wait for building.

$ vagrant ssh default
vagrant@precise64: $ make run

Go http://localhost:8080/install If you see the installation page, drone works fine.

Building custom image from Dockerfile

Put a Dockerfile which is instructions to build an image like this.
This is an exmaple of ruby on CentOS 6

FROM centos:centos6
MAINTAINER Kazuki Hamasaki <>

USER root

# packages
RUN yum groupinstall -y "Development Tools"
RUN yum -y install openssl openssl-devel readline-devel readline libxml2-devel libxslt-devel libyaml-devel zlib zlib-devel git --enablerepo=centosplus

# rbenv
RUN git clone /usr/local/rbenv
RUN git clone /usr/local/rbenv/plugins/ruby-build
ADD /etc/drone.d/

# ruby install
RUN bash -lc 'rbenv install 2.1.2'

# bundler
RUN bash -lc 'rbenv global 2.1.2; gem install rbenv-rehash'
RUN bash -lc 'rbenv global 2.1.2; gem install bundler'
RUN bash -lc 'rbenv rehash'

Be aware of the difference of the image conditions between official and unofficial image.

the default user for all official Drone image is the “ubuntu” user, since all build images inherit from the ubuntu cloud ISO

All other images are assumed to use the root user.

You can use the bradrydzewski/base for your base image, but it doesn’t work by this handling of unofficial images.

If you want to run the script before a test, put the script to /etc/drone.d
The drone will kick this. Drone’s shell doesn’t load /etc/profile, .bash_profile, and .bashrc.

Building image

I recommend setting the repository name with ‘-t’ option for easy reference.

$ sudo docker build --rm -t ashphy/centos6-ruby:2.1.2 .
Sending build context to Docker daemon 75.26 kB
Sending build context to Docker daemon
Step 0 : FROM ashphy/centos6-ruby:base
 ---> d793989a9b8a
Step 1 : MAINTAINER Kazuki Hamasaki <>
 ---> Using cache
 ---> 30578dc14bd9
** snip **
Step 8 : RUN bash -lc 'rbenv rehash'
 ---> Using cache
 ---> 491d71171a33
Successfully built 491d71171a33
build success

Got a special image for you.

Testing your image on the drone

Now let’s check your image if it works well on the drone.

Prepare the test repository, you want to test. Set the image name you build at the image section on .drone.yml file like below.

image: ashphy/centos6-ruby:2.1.2
  - bundle install
  - rspec

Test on the drone with following command.

$ /opt/go/src/ build .

Uploading your image to the docker hub

If the image specified by .drone.yml is missing, drone will do ‘docker pull’, This means that the image will be downloaded from docker hub.
So that your private image that cannot be upload to public is needed to build on the drone server.

Please register in advance at

$ sudo docker publish ashphy/centos6-ruby

CentOS6 + ruby image

I created custom images with CentOS6 + rbenv + ruby.
Put images to centos6-ruby. And Dockerfiles to

I hope you find it informative.

Modern Pubsubhubbub Implementation

I modified pubsubhubbub implementation. No longer original impl does not work, because it has no update from 2011.

My forked impl will works fine with Python 2.7 and Google App Engine for Python 1.8.9.

I’m unfamiliar with Python and GAE. Any improvements are welcome.

How to Run the servers

$ git clone


$ hub


$ --port=8081 --admin_port=8001 publisher


$ --port=8082 --admin_port=8002 subscriber

[Vagrant] object failure: RPC_S_SERVER_UNAVAILABLE error on Windows7

If you see error like this on Vagrant 1.2.2 and VirtualBox 4.2.14, when you do ‘vagrant up’

C:\Users\kazuki-h>vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'hogehoge'...
There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["import", "C:/Users/kazuki-h/.vagrant.d/boxes/hogehoge/virtualbox/box.ovf"]

Stderr: 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Interpreting C:\Users\kazuki-h\.vagrant.d\boxes\hogehoge\virtualbox\box.ovf...

Progress object failure: RPC_S_SERVER_UNAVAILABLE 0x800706BA
Downgrade VirtualBox to 4.2.12, it will works fine.
It could raise again on Mac OS X or Linux, because VirtualBox’s changes might be directly responsible for this error.



This problem has been fixed in the version 4.2.16.

rbenv does not work in aptana terminal for Mac OS X

rbenv is the best solution to to pick a ruby version for your specific environment.
However, even if rbenv has been installed successfully, the “Terminal” in Aptana Studio cannot stop choose the system default ruby version.

Because aptana terminal does not load ~/.bash_profile



My Environments

  • Mac OS X Mountain Lion
  • Aptana Studio 3
  • rbenv 0.4.0

Aptana terminal load the .aptanarc instead of .bashrc when start up. You can insert a path configurations for rbenv on it like this

$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.aptanarc
$ echo 'eval "$(rbenv init -)"' >> ~/.aptanarc

Enjoy, rubymongers!

Media Plugin of CakePHP Tutorial

Media plugin by David Persson is the easiest way to handle the attached file in CakePHP. However, this plugin has few documents on the web, and its wiki was removed.

This is a tutorial of media plugin.  I’m happy if this article helps you.


This turorial used following versions.

  • CakePHP 1.3.6 Stable
  • Media plugin 1.3 Beta

Plugin Initial Setup

After the CakePHP initial setup, download the plugin , and move to the app/plugin, rename the folder to ‘media’. You need to type only this command using git.

git clone git:// app/plugins/media

Add this line to the core.php or bootstrap.php.


Media plugin needs the folders for storing the files. Plugin provides the cake shell. Type this command.

cake media init
chmod -R a+rwX app/webroot/media/{transfar,filter}

Make Table

Sample Table is located at plugins/media/config/sql/media.php . Type command to create this table.

cake/console/cake schema create media -path app/plugins/media/config/sql/

Table structure is

    `id` int(10) unsigned NOT NULL auto_increment,
    `model` varchar(255) NOT NULL,
    `foreign_key` int(10) NOT NULL,
    `dirname` varchar(255) default NULL,
    `basename` varchar(255) NOT NULL,
    `checksum` varchar(255) NOT NULL,
    `alternative` varchar(50) default NULL,
    `group` varchar(255) default NULL,
    `created` datetime default NULL,
    `modified` datetime default NULL,
    PRIMARY KEY  (`id`)

You can use other table you defined insted of plugin’s sample.


Sample model is located at plugins/media/models/attachement.php , and you can copy this. Media.Transfer Behavior is need to transfer files to the server.

class Attachment extends AppModel {

  var $name = 'Attachment';
  var $useTable = 'attachments';
  var $actsAs = array(
    'Media.Transfer' => array(
      'trustClient' => false,
      'transferDirectory' => MEDIA_TRANSFER,
      'createDirectory' => true,
      'alternativeFile' => 100
    'Media.Generator' => array(
      'baseDirectory' => MEDIA_TRANSFER,
      'filterDirectory' => MEDIA_FILTER,
      'createDirectory' => true,
      'Media.Coupler' => array(
      'baseDirectory' => MEDIA_TRANSFER
    'Media.Meta' => array(
      'level' => 2

  var $validate = array(
    'file' => array(
      'resource'   => array('rule' => 'checkResource'),
      'access'     => array('rule' => 'checkAccess'),
      'location'   => array('rule' => array('checkLocation', array(
      MEDIA_TRANSFER, '/tmp/'
    'permission' => array('rule' => array('checkPermission', '*')),
    'size'       => array('rule' => array('checkSize', '5M')),
    'pixels'     => array('rule' => array('checkPixels', '1600x1600')),
    'extension'  => array('rule' => array('checkExtension', false, array(
      'jpg', 'jpeg', 'png', 'tif', 'tiff', 'gif', 'pdf', 'tmp'
    'mimeType'   => array('rule' => array('checkMimeType', false, array(
      'image/jpeg', 'image/png', 'image/tiff', 'image/gif', 'application/pdf'
    'alternative' => array(
    'rule'       => 'checkRepresent',
    'on'         => 'create',
    'required'   => false,
    'allowEmpty' => true,

Controller and View

I created base controller and view with bake command.

Upload Form

Replace default form with following code at view/add.ctp

<?php echo $this->Form->create('Attachment', array('type' => 'file'));?>
    <legend><?php __('Add Attachment'); ?></legend>
        echo $form->input('file', array('type' => 'file'));
<?php echo $this->Form->end(__('Submit', true));?>
File Upload Form

File Upload Form

Show the attached file at the view

Add MediaHelper to AttachmentsController

    var $helpers = array('Media.Media');

Add this code to show the attached file at the views/attachments/view.ctp.

<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Attached File'); ?></dt>
 <dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $media->embed($media->file(

‘s’ means a type of filter. Filter setting is written in plugins/media/config/core.php

$s = array('convert' => 'image/png', 'zoomCrop' => array(100, 100));
$m = array('convert' => 'image/png', 'fitCrop' => array(300, 300));
$l = array('convert' => 'image/png', 'fit' => array(600, 440));

If you want a no conversion filter which doesn’t convert size and image type, you can define like this

$org = array('convert' => 'original');

Configure::write('Media.filter', array(
    'audio' => compact('s', 'm'),
    'document' => compact('s', 'm'),
    'generic' => array(),
    'image' => compact('s', 'm', 'l', 'org'),
    'video' => compact('s', 'm')

Have a nice cake!