Skip to content

Commit

Permalink
Merge pull request #40 from danger/local_test
Browse files Browse the repository at this point in the history
Support a `danger local` command
  • Loading branch information
orta committed Feb 12, 2016
2 parents ebf78ff + 41a5939 commit a9f9b3b
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Master

* Add a `danger local` command to test your current Dangerfile against the last PR merged on the repo - orta
* Calling CircleCI API when `CI_PULL_REQUEST` is not set - marcelofabri
* Look inside PR JSON for the commit range (instead of getting from CI providers) - marcelofabri
* Adds `pr_labels` to DSL - marcelofabri
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ You can access more detailed information by accessing the following variables
`env.scm.diff` | The full [GitDiff](https://github.com/schacon/ruby-git/blob/master/lib/git/diff.rb) file for the diff.
`env.ci_source` | To get information like the repo slug or pull request ID

## Test locally with `danger local`

Using `danger local` will look for the last merged pull request in your git history, and apply your current
`Dangerfile` against that Pull Request. Useful when editing.

## Useful bits of knowledge ATM

* You can set the base branch in the command line arguments see: `bundle exec danger --help`.
Expand Down
3 changes: 1 addition & 2 deletions lib/danger.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
require "danger/version"
require "danger/dangerfile"
require "danger/environment_manager"
require "danger/runner"
require "danger/init"
require "danger/commands/runner"
require "danger/available_values"

require "claide"
Expand Down
42 changes: 42 additions & 0 deletions lib/danger/ci_source/local_git_repo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# For more info see: https://github.com/schacon/ruby-git

require 'git'
require 'uri'

module Danger
module CISource
class LocalGitRepo < CI
attr_accessor :base_commit, :head_commit

def self.validates?(env)
return !env["DANGER_USE_LOCAL_GIT"].nil?
end

def initialize(*)
git = Git.open(".")
if git.remote("origin")
url = git.remote("origin").url
# deal with https://
if url.start_with? "https://github.com/"
self.repo_slug = url.gsub("https://github.com/", "").gsub(".git", '')

# deal with SSH origin
elsif url.start_with? "git@github.com:"
self.repo_slug = url.gsub("git@github.com:", "").gsub(".git", '')
end
end

logs = git.log.since('2 weeks ago')
# Look for something like
# "Merge pull request #38 from KrauseFx/funky_circles\n\nAdd support for GitHub compare URLs that don't conform
pr_merge = logs.detect { |log| (/Merge pull request #[0-9]* from/ =~ log.message) == 0 }
if pr_merge
# then pull out the 38, to_i
self.pull_request_id = pr_merge.message.gsub("Merge pull request #", "").to_i
self.base_commit = pr_merge.parents[0].sha
self.head_commit = pr_merge.parents[1].sha
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/danger/init.rb → lib/danger/commands/init.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Danger
class Init < Danger::Runner
class Init < Runner
self.description = 'Creates a Dangerfile.'
self.command = 'init'

Expand Down
52 changes: 52 additions & 0 deletions lib/danger/commands/local.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module Danger
class Local < Runner
self.description = 'Run the Dangerfile locally.'
self.command = 'local'

def initialize(argv)
@dangerfile_path = "Dangerfile" if File.exist? "Dangerfile"
super
end

def validate!
super
unless @dangerfile_path
help! "Could not find a Dangerfile."
end
end

def run
ENV["DANGER_USE_LOCAL_GIT"] = "YES"

dm = Dangerfile.new
dm.env = EnvironmentManager.new(ENV)

source = dm.env.ci_source
unless source.repo_slug
puts "danger local".red " failed because it only works with GitHub projects at the moment. Sorry."
exit 0
end

puts "Running your Dangerfile against this PR - https://github.com/#{source.repo_slug}/pulls/#{source.pull_request_id}"

if verbose != true
puts "Turning on --verbose"
dm.verbose = true
end

puts ""

gh = GitHub.new(dm.env.ci_source, ENV)
# We can use tokenless here, as it's running on someone's computer
# and is IP locked, as opposed to on the CI.
gh.support_tokenless_auth = true
gh.fetch_details

dm.env.request_source = gh

dm.env.scm = GitRepo.new
dm.env.scm.diff_for_folder(".", dm.env.ci_source.base_commit, dm.env.ci_source.head_commit)
dm.parse Pathname.new(@dangerfile_path)
end
end
end
4 changes: 4 additions & 0 deletions lib/danger/runner.rb → lib/danger/commands/runner.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
module Danger
class Runner < CLAide::Command
require 'danger/commands/init'
require 'danger/commands/local'

self.description = 'Run the Dangerfile.'
self.command = 'danger'

Expand Down Expand Up @@ -27,6 +30,7 @@ def self.options
def run
# The order of the following commands is *really* important
dm = Dangerfile.new
dm.verbose = verbose
dm.env = EnvironmentManager.new(ENV)
return unless dm.env.ci_source # if it's not a PR
dm.env.fill_environment_vars
Expand Down
26 changes: 25 additions & 1 deletion lib/danger/dangerfile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Danger
class Dangerfile
include Danger::Dangerfile::DSL

attr_accessor :env, :warnings, :errors, :messages
attr_accessor :env, :warnings, :errors, :messages, :verbose

# @return [Pathname] the path where the Dangerfile was loaded from. It is nil
# if the Dangerfile was generated programmatically.
Expand All @@ -21,9 +21,33 @@ def to_s
'Dangerfile'
end

# Iterates through the DSL's attributes, and table's the output
def print_known_info
puts "Danger v#{Danger::VERSION}"
width = AvailableValues.all.map(&:to_s).map(&:length).max
puts "DSL Attributes:"
puts "-" * (width + 4)
AvailableValues.all.each do |value|
spaces = (width - value.to_s.length)
puts "| #{value.to_s.blue}#{' ' * spaces} | #{self.send(value)}"
end
puts "-" * (width + 4)

puts "Metadata:"
puts "#{'SCM'.blue} : #{env.scm.class}"
puts "#{'Source'.blue} : #{env.ci_source.class}"
puts "#{'Requests'.blue} : #{env.request_source.class}"
puts " #{'Base commit'.blue} : #{env.request_source.base_commit}"
puts " #{'HEAD commit'.blue} : #{env.request_source.head_commit}"
puts " git diff #{env.request_source.base_commit} #{env.request_source.head_commit}".yellow
puts "\n\n"
end

# Parses the file at a path, optionally takes the content of the file for DI
#
def parse(path, contents = nil)
print_known_info if verbose

contents ||= File.open(path, 'r:utf-8', &:read)

# Work around for Rubinius incomplete encoding in 1.9 mode
Expand Down
3 changes: 3 additions & 0 deletions lib/danger/dangerfile_dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ def message(message)
puts "Printing message '#{message}'"
end

# When an undefined method is called, we check to see if it's something
# that either the `scm` or the `request_source` can handle.
# This opens us up to letting those object extend themselves naturally.
def method_missing(method_sym, *_arguments, &_block)
unless AvailableValues.all.include?(method_sym)
raise "Unknown method '#{method_sym}', please check out the documentation for available variables".red
Expand Down
5 changes: 3 additions & 2 deletions lib/danger/request_sources/github.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@

module Danger
class GitHub
attr_accessor :ci_source, :pr_json, :issue_json, :environment, :base_commit, :head_commit
attr_accessor :ci_source, :pr_json, :issue_json, :environment, :base_commit, :head_commit, :support_tokenless_auth

def initialize(ci_source, environment)
self.ci_source = ci_source
self.environment = environment
self.support_tokenless_auth = false

Octokit.auto_paginate = true
end

def client
token = @environment["DANGER_GITHUB_API_TOKEN"]
raise "No API given, please provide one using `DANGER_GITHUB_API_TOKEN`" unless token
raise "No API given, please provide one using `DANGER_GITHUB_API_TOKEN`" if !token && !support_tokenless_auth

@client ||= Octokit::Client.new(
access_token: token
Expand Down
18 changes: 18 additions & 0 deletions spec/dangerfile_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,22 @@ def make_temp_file(contents)
dm.parse Pathname.new(""), code
end.to raise_error(Danger::DSLError)
end

describe "verbose" do
it 'outputs metadata when verbose' do
file = make_temp_file ""
dm = Danger::Dangerfile.new
dm.verbose = true

expect(dm).to receive(:print_known_info)
dm.parse file.path
end
it 'does not print metadata by default' do
file = make_temp_file ""
dm = Danger::Dangerfile.new

expect(dm).to_not receive(:print_known_info)
dm.parse file.path
end
end
end

0 comments on commit a9f9b3b

Please sign in to comment.