danger 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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