Danger

Danger title image

Plugin creationa project from orta therox, Juanito Fatas and and others.

So, you want to make a Danger Plugin? This is awesome. We all have common issues, and this is a great way to share code with the world. We’ve found once a single rule becomes longer than 10-15 lines of code, converting it into a plugin makes a lot of sense.

The concept of a Plugin in Danger is very simple. It’s a subclass of Danger::Plugin.

If you don’t know about Ruby modules, then don’t worry, think of it as Ruby namespacing. That’s the Danger:: bit. You’ll have to create a class that is a subclass of Plugin inside a Danger module.

#Tech Specs

This subclass will be created automatically with a reference to the current Danger::Dangerfile ruby object. It will be created before the Dangerfile(s) are parsed by it.

There are no ways to automatically execute code with knowledge of the current status. A plugin should get told to do some work from the user’s Dangerfile(s).

Your plugin is added as an attribute to the user’s Dangerfile(s), this is based on your class name, but is editable.

def self.instance_name
  to_s.gsub("Danger", "").danger_underscore.split("/").last
end

# e.g. removes "Danger", converts camel case to snake case, and splits if there's any /s

# DangerProse -> prose
# DangerMyThing -> my_thing
# MyPlugin -> my_plugin

#Same Source

One of the great things about a Danger Plugin is that the code is exactly the same as it was in your Dangerfile. A plugin has access to all of the same methods and attributes as you had when it was being parsed inside a Dangerfile. This is because anything your plugin doesn’t understand gets passed to the current Dangerfile for it to have a chance to act.

This is useful mainly in two things:

#Creating the Plugin

Starting is pretty simple, we have a template. As well as a command to get you started. Your first step is the name: the Rubygems rule is [core_app]-[gem]_[name]. So, the first space is always a - then later spaces would be _. E.g. danger-wizard_hat.

Now that you know the rules, in your development folder run danger plugins create [name]. This will create a README similar to the one for danger-proselint.

$ danger plugins create guitar_lessons

-> Creating `danger-guitar_lessons` plugin

[!] using template 'https://github.com/danger/danger-plugin-template'
-> Configuring template
Configuring danger-guitar_lessons
user name:Orta Therox
user email:orta.therox@gmail.com
year:2016

This sets you up with this folder structure:

danger-guitar_lessons
├── .travis.yml
├── Gemfile
├── Guardfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── danger-guitar_lessons.gemspec
├── lib
│   ├── danger_guitar_lessons.rb
│   ├── danger_plugin.rb
│   └── guitar_lessons
│       ├── gem_version.rb
│       └── plugin.rb
└─  spec
    ├── guitar_lessons_spec.rb
    └── spec_helper.rb

Which covers a lot of the basics for you.

#Source

The template isn’t empty, it comes as an existing simple plugin based on our work in danger-prose. This is to make it easier to show how all of the plugin comes together, I’d recommend reading through these files in this order:

These are main places where you would be doing work.

You’ll want to move your code into the file at /lib/[NAME]/plugin.rb. Then you can write some tests to ensure nothing will break in the future.

#Tests

The template comes with some tests for the example plugin. It already comes with infrastructure to have a Danger::Dangerfile instantiate your plugin. You can start off by modifying that to work with your plugin.

To run all of the tests, you can use the command bundle exec rake spec. The testing infrastructure is RSpec, the template also comes with a Guardfile for use with guard with guard-rspec. This means you can run bundle exec guard and it will start a server which listens for test changes and re-runs your tests as you work.

If you’re new to testing on ruby, here are some examples that you can use as a reference:

#CI

This template comes with a .travis.yml file that lints your documentation, and offers advice on the syntax of your Ruby. If you want to quickly change the syntax, run bundle exec rubocop -a in the directory.

#Adding the Gem to your Project

To test your project back with the codebase you’ve extracted the code from, you’ll need to use a Gemfile. So many Thingfiles, right?

You should add a gem using the :path attribute. e.g. add a new line with:

gem "danger-guitar_lessons", :path => "../danger-guitar_lessons"

Then when you run bundle install your new gem is added to the project. You can then use bundle exec danger local to test inside you project. You can make changes to your plugin, then you only need to run bundle exec danger local.

#Automate your README

Danger can generate your README based on the inline documentation in your plugin. To do this, run bundle exec danger plugins readme. The markdown will be output into your terminal, then you can copy & paste it into README.md.

#Pushing to RubyGems

So you’re ready to ship now, you’ve got a few tests, and you’ve ran it inside your project using a :path gem.

You’re going to want to push it to RubyGems, here’s their guide on publishing a gem.

Once it’s on RubyGems, then you should change your application’s Gemfile to remove the :path and let it become the public gem. Awesome. That’s you ready for using your plugin in production.

#Getting it on Danger.Systems

Having a plugin available on RubyGems means anyone can use it.

This is entirely optional, however having your gem on this site means that it will be more visible!

In order to go on Danger.Systems you need to ensure the running bundle exec danger plugins lint passes.

This means that the plugin is well documented so that the site can generate a page for it. The linter will guide you through the process, and show you examples of how to use the documentation syntax.

Once you are all green, and ideally warning free in the linter. You should send a merge request to danger.systems/plugins.json. Please don’t add it as the first item.

#Extra Credit

If you want to make sure that your plugin’s docs are always up to date, you can follow the instructions here to set up a webhook which triggers this static site to update and with latest release.

#Supporting multiple platforms: E.g. GitHub, GitLab, etc

You can determine if another plugin exists (all Platforms are plugins) but doing defined? @dangerfile.[plugin_name]

Here is an example of GitLab and GitHub support in the same plugin: danger-mentions.

#10/10 WOULD PLUGIN AGAIN


Got improvements? Help improve this document via sending MRs.