danger 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,26 +1,32 @@
1
1
  # https://semaphoreci.com/docs/available-environment-variables.html
2
2
 
3
3
  module Danger
4
- module CISource
5
- # https://semaphoreci.com
6
- class Semaphore < CI
7
- def self.validates?(env)
8
- return false unless env["SEMAPHORE"]
9
- return false unless env["SEMAPHORE_REPO_SLUG"]
10
- return false unless env["PULL_REQUEST_NUMBER"].to_i > 0
4
+ ### CI Setup
5
+ #
6
+ # For Semaphor you will want to go to the settings page of the project. Inside "Build Settings"
7
+ # you should add `bundle exec danger` to the Setup thread.
8
+ #
9
+ # ### Token Setup
10
+ #
11
+ # You can add your `DANGER_GITHUB_API_TOKEN` inside the "Environment Variables" section in the settings.
12
+ #
13
+ class Semaphore < CI
14
+ def self.validates_as_ci?(env)
15
+ env.key? "SEMAPHORE"
16
+ end
11
17
 
12
- return true
13
- end
18
+ def self.validates_as_pr?(env)
19
+ ["SEMAPHORE_REPO_SLUG", "PULL_REQUEST_NUMBER"].all? { |x| env[x] }
20
+ end
14
21
 
15
- def supported_request_sources
16
- @supported_request_sources ||= [Danger::RequestSources::GitHub]
17
- end
22
+ def supported_request_sources
23
+ @supported_request_sources ||= [Danger::RequestSources::GitHub]
24
+ end
18
25
 
19
- def initialize(env)
20
- self.repo_slug = env["SEMAPHORE_REPO_SLUG"]
21
- self.pull_request_id = env["PULL_REQUEST_NUMBER"]
22
- self.repo_url = GitRepo.new.origins # Semaphore doesn't provide a repo url env variable :/
23
- end
26
+ def initialize(env)
27
+ self.repo_slug = env["SEMAPHORE_REPO_SLUG"]
28
+ self.pull_request_id = env["PULL_REQUEST_NUMBER"]
29
+ self.repo_url = GitRepo.new.origins # Semaphore doesn't provide a repo url env variable :/
24
30
  end
25
31
  end
26
32
  end
@@ -1,25 +1,36 @@
1
1
  # http://github.com/surf-build/surf
2
2
 
3
3
  module Danger
4
- module CISource
5
- # http://github.com/surf-build/surf
6
- class Surf < CI
7
- def self.validates?(env)
8
- return ["SURF_REPO", "SURF_NWO"].all? { |x| env[x] }
9
- end
4
+ # ### CI Setup
5
+ #
6
+ # You want to add `bundle exec danger` to your `build.sh` file to run Danger at the
7
+ # end of your build.
8
+ #
9
+ # ### Token Setup
10
+ #
11
+ # As this is self-hosted, you will need to add the `DANGER_GITHUB_API_TOKEN` to your build user's ENV. The alternative
12
+ # is to pass in the token as a prefix to the command `DANGER_GITHUB_API_TOKEN="123" bundle exec danger`.
13
+ #
14
+ class Surf < CI
15
+ def self.validates_as_ci?(env)
16
+ return ["SURF_REPO", "SURF_NWO"].all? { |x| env[x] }
17
+ end
10
18
 
11
- def supported_request_sources
12
- @supported_request_sources ||= [Danger::RequestSources::GitHub]
13
- end
19
+ def self.validates_as_pr?(_)
20
+ true
21
+ end
14
22
 
15
- def initialize(env)
16
- self.repo_slug = env["SURF_NWO"]
17
- if env["SURF_PR_NUM"].to_i > 0
18
- self.pull_request_id = env["SURF_PR_NUM"]
19
- end
23
+ def supported_request_sources
24
+ @supported_request_sources ||= [Danger::RequestSources::GitHub]
25
+ end
20
26
 
21
- self.repo_url = env["SURF_REPO"]
27
+ def initialize(env)
28
+ self.repo_slug = env["SURF_NWO"]
29
+ if env["SURF_PR_NUM"].to_i > 0
30
+ self.pull_request_id = env["SURF_PR_NUM"]
22
31
  end
32
+
33
+ self.repo_url = env["SURF_REPO"]
23
34
  end
24
35
  end
25
36
  end
@@ -1,23 +1,42 @@
1
1
  module Danger
2
- module CISource
3
- # https://www.jetbrains.com/teamcity/
4
- class TeamCity < CI
5
- def self.validates?(env)
6
- env.key? "TEAMCITY_VERSION"
7
- end
2
+ # https://www.jetbrains.com/teamcity/
8
3
 
9
- def supported_request_sources
10
- @supported_request_sources ||= [Danger::RequestSources::GitHub]
11
- end
4
+ ### CI Setup
5
+ #
6
+ # You need to go to your project settings. Then depending on the type of your build settings, you may need
7
+ # to add a new build step for Danger. You want to be able to run the command `bundle exec danger`, so
8
+ # the "Simple Command Runner" should be all you need to do that.
9
+ #
10
+ # ### Token + Environment Setup
11
+ #
12
+ # As this is self-hosted, you will need to add the `DANGER_GITHUB_API_TOKEN` to your build user's ENV. The alternative
13
+ # is to pass in the token as a prefix to the command `DANGER_GITHUB_API_TOKEN="123" bundle exec danger`.
14
+ #
15
+ # However, you will need to find a way to add the environment vars: `GITHUB_REPO_SLUG`, `GITHUB_PULL_REQUEST_ID` and
16
+ # `GITHUB_REPO_URL`. These are not added by default. You could do this via the GitHub API potentially.
17
+ #
18
+ # We would love some advice on improving this setup.
19
+ #
20
+ class TeamCity < CI
21
+ def self.validates_as_ci?(env)
22
+ env.key? "TEAMCITY_VERSION"
23
+ end
24
+
25
+ def self.validates_as_pr?(env)
26
+ ["GITHUB_PULL_REQUEST_ID", "GITHUB_REPO_URL", "GITHUB_REPO_SLUG"].all? { |x| env[x] }
27
+ end
28
+
29
+ def supported_request_sources
30
+ @supported_request_sources ||= [Danger::RequestSources::GitHub]
31
+ end
12
32
 
13
- def initialize(env)
14
- # NB: Unfortunately TeamCity doesn't provide these variables
15
- # automatically so you have to add these variables manually to your
16
- # project or build configuration
17
- self.repo_slug = env["GITHUB_REPO_SLUG"]
18
- self.pull_request_id = env["GITHUB_PULL_REQUEST_ID"].to_i
19
- self.repo_url = env["GITHUB_REPO_URL"]
20
- end
33
+ def initialize(env)
34
+ # NB: Unfortunately TeamCity doesn't provide these variables
35
+ # automatically so you have to add these variables manually to your
36
+ # project or build configuration
37
+ self.repo_slug = env["GITHUB_REPO_SLUG"]
38
+ self.pull_request_id = env["GITHUB_PULL_REQUEST_ID"].to_i
39
+ self.repo_url = env["GITHUB_REPO_URL"]
21
40
  end
22
41
  end
23
42
  end
@@ -2,28 +2,49 @@
2
2
  # http://docs.travis-ci.com/user/environment-variables/
3
3
 
4
4
  module Danger
5
- module CISource
6
- # https://travis-ci.com
7
- class Travis < CI
8
- def self.validates?(env)
9
- return false unless env["HAS_JOSH_K_SEAL_OF_APPROVAL"]
10
- return false unless env["TRAVIS_REPO_SLUG"]
11
- return false unless env["TRAVIS_PULL_REQUEST"]
5
+ ### CI Setup
6
+ # You need to edit your `.travis.yml` to include `bundle exec danger`. If you already have
7
+ # a `script:` section then we recommend adding this command at the end of the script step: `- bundle exec danger`.
8
+ #
9
+ # Otherwise, add a `before_script` step to the root of the `.travis.yml` with `bundle exec danger`
10
+ #
11
+ # ```ruby
12
+ # before_script:
13
+ # - bundle exec danger
14
+ # ```
15
+ #
16
+ # Adding this to your `.travis.yml` allows Danger to fail your build, both on the TravisCI website and within your Pull Request.
17
+ # With that set up, you can edit your job to add `bundle exec danger` at the build action.
18
+ #
19
+ # _Note:_ Travis CI defaults to using an older version of Ruby, so you may need to add `rvm: 2.0.0` to the root your `.travis.yml`.
20
+ #
21
+ # ### Token Setup
22
+ #
23
+ # You need to add the `DANGER_GITHUB_API_TOKEN` environment variable, to do this,
24
+ # go to your repo's settings, which should look like: `https://travis-ci.org/[user]/[repo]/settings`.
25
+ #
26
+ # If you have an open source project, you should ensure "Display value in build log" enabled, so that PRs from forks work.
27
+ #
28
+ class Travis < CI
29
+ def self.validates_as_ci?(env)
30
+ env.key? "HAS_JOSH_K_SEAL_OF_APPROVAL"
31
+ end
12
32
 
13
- return true
14
- end
33
+ def self.validates_as_pr?(env)
34
+ exists = ["TRAVIS_PULL_REQUEST", "TRAVIS_REPO_SLUG"].all? { |x| env[x] }
35
+ exists && env["TRAVIS_PULL_REQUEST"].to_i > 0
36
+ end
15
37
 
16
- def supported_request_sources
17
- @supported_request_sources ||= [Danger::RequestSources::GitHub]
18
- end
38
+ def supported_request_sources
39
+ @supported_request_sources ||= [Danger::RequestSources::GitHub]
40
+ end
19
41
 
20
- def initialize(env)
21
- self.repo_slug = env["TRAVIS_REPO_SLUG"]
22
- if env["TRAVIS_PULL_REQUEST"].to_i > 0
23
- self.pull_request_id = env["TRAVIS_PULL_REQUEST"]
24
- end
25
- self.repo_url = GitRepo.new.origins # Travis doesn't provide a repo url env variable :/
42
+ def initialize(env)
43
+ self.repo_slug = env["TRAVIS_REPO_SLUG"]
44
+ if env["TRAVIS_PULL_REQUEST"].to_i > 0
45
+ self.pull_request_id = env["TRAVIS_PULL_REQUEST"]
26
46
  end
47
+ self.repo_url = GitRepo.new.origins # Travis doesn't provide a repo url env variable :/
27
48
  end
28
49
  end
29
50
  end
@@ -1,29 +1,42 @@
1
1
  # Following the advice from @czechboy0 https://github.com/danger/danger/issues/171
2
2
 
3
3
  module Danger
4
- module CISource
5
- # https://github.com/czechboy0/Buildasaur
6
- class XcodeServer < CI
7
- def self.validates?(env)
8
- return false unless env["XCS_BOT_NAME"]
4
+ # https://github.com/czechboy0/Buildasaur
5
+ class XcodeServer < CI
6
+ ### CI Setup
7
+ #
8
+ # If you're bold enough to use Xcode Bots. You will need to use [Buildasaur](https://github.com/czechboy0/Buildasaur)
9
+ # in order to work with Danger. This will set up your build environment for you, as the name of the bot contains all
10
+ # of the environment variables that Danger needs to work.
11
+ #
12
+ # With Buildasaur set up, you can edit your job to add `bundle exec danger` as a post-actoin build script.
13
+ #
14
+ # ### Token Setup
15
+ #
16
+ # As this is self-hosted, you will need to add the `DANGER_GITHUB_API_TOKEN` to your build user's ENV. The alternative
17
+ # is to pass in the token as a prefix to the command `DANGER_GITHUB_API_TOKEN="123" bundle exec danger`.`.
18
+ #
19
+ def self.validates_as_ci?(env)
20
+ env.key? "XCS_BOT_NAME"
21
+ end
9
22
 
10
- return true
11
- end
23
+ def self.validates_as_pr?(env)
24
+ env["XCS_BOT_NAME"].include? "BuildaBot"
25
+ end
12
26
 
13
- def supported_request_sources
14
- @supported_request_sources ||= [Danger::RequestSources::GitHub]
15
- end
27
+ def supported_request_sources
28
+ @supported_request_sources ||= [Danger::RequestSources::GitHub]
29
+ end
16
30
 
17
- def initialize(env)
18
- bot_name = env["XCS_BOT_NAME"]
19
- return if bot_name.nil?
31
+ def initialize(env)
32
+ bot_name = env["XCS_BOT_NAME"]
33
+ return if bot_name.nil?
20
34
 
21
- repo_matches = bot_name.match(/\[(.+)\]/)
22
- self.repo_slug = repo_matches[1] unless repo_matches.nil?
23
- pull_request_id_matches = bot_name.match(/#(\d+)/)
24
- self.pull_request_id = pull_request_id_matches[1] unless pull_request_id_matches.nil?
25
- self.repo_url = GitRepo.new.origins # Xcode Server doesn't provide a repo url env variable :/
26
- end
35
+ repo_matches = bot_name.match(/\[(.+)\]/)
36
+ self.repo_slug = repo_matches[1] unless repo_matches.nil?
37
+ pull_request_id_matches = bot_name.match(/#(\d+)/)
38
+ self.pull_request_id = pull_request_id_matches[1] unless pull_request_id_matches.nil?
39
+ self.repo_url = GitRepo.new.origins # Xcode Server doesn't provide a repo url env variable :/
27
40
  end
28
41
  end
29
42
  end
@@ -2,6 +2,7 @@ module Danger
2
2
  class Runner < CLAide::Command
3
3
  require "danger/commands/init"
4
4
  require "danger/commands/local"
5
+ require "danger/commands/systems"
5
6
 
6
7
  # manually set claide plugins as a subcommand
7
8
  require "claide_plugin"
@@ -0,0 +1,41 @@
1
+ module Danger
2
+ class Systems < Runner
3
+ self.abstract_command = true
4
+ self.description = "For commands related to passing information from Danger to Danger.Systems."
5
+ self.summary = "Create data for Danger.Systems."
6
+ end
7
+
8
+ class CIDocs < Systems
9
+ self.command = "ci_docs"
10
+ self.summary = "Outputs the up-to-date CI documentation for Danger."
11
+
12
+ def run
13
+ here = File.dirname(__FILE__)
14
+ ci_source_paths = Dir.glob(here + "/../ci_source/*.rb")
15
+
16
+ require "yard"
17
+ # Pull out all the Danger::CI subclasses docs
18
+ registry = YARD::Registry.load(ci_source_paths, true)
19
+ ci_sources = registry.all(:class)
20
+ .select { |klass| klass.inheritance_tree.map(&:name).include? :CI }
21
+ .reject { |source| source.name == :CI }
22
+ .reject { |source| source.name == :LocalGitRepo }
23
+
24
+ # Fail if anything is added and not documented
25
+ cis_without_docs = ci_sources.select { |source| source.base_docstring.empty? }
26
+ unless cis_without_docs.empty?
27
+ cork.puts "Please add docs to: #{cis_without_docs.map(&:name).join(', ')}"
28
+ abort("Failed.".red)
29
+ end
30
+
31
+ # Output a JSON array of name and details
32
+ require "json"
33
+ cork.puts ci_sources.map { |ci|
34
+ {
35
+ name: ci.name,
36
+ docs: ci.docstring
37
+ }
38
+ }.to_json
39
+ end
40
+ end
41
+ end
@@ -5,31 +5,29 @@ module Danger
5
5
  class EnvironmentManager
6
6
  attr_accessor :ci_source, :request_source, :scm
7
7
 
8
- def initialize(env)
9
- CISource::CI.available_ci_sources.each do |klass|
10
- next unless klass.validates?(env)
11
-
12
- self.ci_source = klass.new(env)
13
- if self.ci_source.repo_slug and self.ci_source.pull_request_id
14
- break
15
- else
16
- self.ci_source = nil
17
- return nil
18
- end
19
- end
8
+ # Finds a Danger::CI class based on the ENV
9
+ def self.local_ci_source(env)
10
+ CI.available_ci_sources.find { |ci| ci.validates_as_ci? env }
11
+ end
20
12
 
21
- raise "Could not find a valid pull request within the known CI sources".red unless self.ci_source
13
+ # Uses the current Danger::CI subclass, and sees if it is a PR
14
+ def self.pr?(env)
15
+ local_ci_source(env).validates_as_pr?(env)
16
+ end
17
+
18
+ def initialize(env)
19
+ ci_klass = self.class.local_ci_source(env)
20
+ self.ci_source = ci_klass.new(env)
22
21
 
23
22
  RequestSources::RequestSource.available_request_sources.each do |klass|
24
23
  next unless self.ci_source.supports?(klass)
25
24
 
26
25
  request_source = klass.new(self.ci_source, ENV)
27
- next unless request_source.validates?
26
+ next unless request_source.validates_as_ci?
28
27
  self.request_source = request_source
29
28
  end
30
29
 
31
- raise "Could not find a Request Source".red unless self.request_source
32
-
30
+ raise "Could not find a Request Source for #{ci_klass}".red unless self.request_source
33
31
  self.scm = self.request_source.scm
34
32
  end
35
33
 
@@ -10,37 +10,46 @@ module Danger
10
10
 
11
11
  cork ||= Cork::Board.new(silent: false,
12
12
  verbose: false)
13
+
14
+ # Could we find a CI source at all?
15
+ unless EnvironmentManager.local_ci_source(ENV)
16
+ abort("Could not find the type of CI for Danger to run on.".red) unless ci_klass
17
+ end
18
+
19
+ # Could we determine that the CI source is inside a PR?
20
+ unless EnvironmentManager.pr?(ENV)
21
+ cork.puts "Not a Pull Request - skipping `danger` run".yellow
22
+ return
23
+ end
24
+
25
+ # OK, then we can have some
13
26
  env ||= EnvironmentManager.new(ENV)
14
27
  dm ||= Dangerfile.new(env, cork)
15
28
 
16
- if dm.env.pr?
17
- dm.init_plugins
18
-
19
- dm.env.fill_environment_vars
29
+ dm.init_plugins
20
30
 
21
- begin
22
- dm.env.ensure_danger_branches_are_setup
31
+ dm.env.fill_environment_vars
23
32
 
24
- # Offer the chance for a user to specify a branch through the command line
25
- ci_base = base || EnvironmentManager.danger_base_branch
26
- ci_head = head || EnvironmentManager.danger_head_branch
27
- dm.env.scm.diff_for_folder(".", from: ci_base, to: ci_head)
33
+ begin
34
+ dm.env.ensure_danger_branches_are_setup
28
35
 
29
- dm.parse(Pathname.new(dangerfile_path))
36
+ # Offer the chance for a user to specify a branch through the command line
37
+ ci_base = base || EnvironmentManager.danger_base_branch
38
+ ci_head = head || EnvironmentManager.danger_head_branch
39
+ dm.env.scm.diff_for_folder(".", from: ci_base, to: ci_head)
30
40
 
31
- if dm.env.request_source.organisation && !dm.env.request_source.danger_repo? && (danger_repo = dm.env.request_source.fetch_danger_repo)
32
- url = dm.env.request_source.file_url(repository: danger_repo.name, path: "Dangerfile")
33
- path = dm.plugin.download(url)
34
- dm.parse(Pathname.new(path))
35
- end
41
+ dm.parse(Pathname.new(dangerfile_path))
36
42
 
37
- post_results(dm, danger_id)
38
- dm.print_results
39
- ensure
40
- dm.env.clean_up
43
+ if dm.env.request_source.organisation && !dm.env.request_source.danger_repo? && (danger_repo = dm.env.request_source.fetch_danger_repo)
44
+ url = dm.env.request_source.file_url(repository: danger_repo.name, path: "Dangerfile")
45
+ path = dm.plugin.download(url)
46
+ dm.parse(Pathname.new(path))
41
47
  end
42
- else
43
- cork.puts "Not a Pull Request - skipping `danger` run"
48
+
49
+ post_results(dm, danger_id)
50
+ dm.print_results
51
+ ensure
52
+ dm.env.clean_up
44
53
  end
45
54
  end
46
55