danger 8.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +94 -0
  4. data/bin/danger +5 -0
  5. data/lib/assets/DangerfileTemplate +13 -0
  6. data/lib/danger.rb +44 -0
  7. data/lib/danger/ci_source/appcenter.rb +55 -0
  8. data/lib/danger/ci_source/appveyor.rb +60 -0
  9. data/lib/danger/ci_source/azure_pipelines.rb +44 -0
  10. data/lib/danger/ci_source/bamboo.rb +41 -0
  11. data/lib/danger/ci_source/bitbucket_pipelines.rb +37 -0
  12. data/lib/danger/ci_source/bitrise.rb +65 -0
  13. data/lib/danger/ci_source/buddybuild.rb +62 -0
  14. data/lib/danger/ci_source/buildkite.rb +51 -0
  15. data/lib/danger/ci_source/ci_source.rb +37 -0
  16. data/lib/danger/ci_source/circle.rb +94 -0
  17. data/lib/danger/ci_source/circle_api.rb +51 -0
  18. data/lib/danger/ci_source/cirrus.rb +31 -0
  19. data/lib/danger/ci_source/code_build.rb +57 -0
  20. data/lib/danger/ci_source/codefresh.rb +53 -0
  21. data/lib/danger/ci_source/codeship.rb +44 -0
  22. data/lib/danger/ci_source/dotci.rb +52 -0
  23. data/lib/danger/ci_source/drone.rb +71 -0
  24. data/lib/danger/ci_source/github_actions.rb +43 -0
  25. data/lib/danger/ci_source/gitlab_ci.rb +86 -0
  26. data/lib/danger/ci_source/jenkins.rb +149 -0
  27. data/lib/danger/ci_source/local_git_repo.rb +119 -0
  28. data/lib/danger/ci_source/local_only_git_repo.rb +47 -0
  29. data/lib/danger/ci_source/screwdriver.rb +47 -0
  30. data/lib/danger/ci_source/semaphore.rb +37 -0
  31. data/lib/danger/ci_source/support/commits.rb +17 -0
  32. data/lib/danger/ci_source/support/find_repo_info_from_logs.rb +35 -0
  33. data/lib/danger/ci_source/support/find_repo_info_from_url.rb +42 -0
  34. data/lib/danger/ci_source/support/local_pull_request.rb +14 -0
  35. data/lib/danger/ci_source/support/no_pull_request.rb +7 -0
  36. data/lib/danger/ci_source/support/no_repo_info.rb +5 -0
  37. data/lib/danger/ci_source/support/pull_request_finder.rb +179 -0
  38. data/lib/danger/ci_source/support/remote_pull_request.rb +15 -0
  39. data/lib/danger/ci_source/support/repo_info.rb +10 -0
  40. data/lib/danger/ci_source/surf.rb +37 -0
  41. data/lib/danger/ci_source/teamcity.rb +159 -0
  42. data/lib/danger/ci_source/travis.rb +51 -0
  43. data/lib/danger/ci_source/vsts.rb +73 -0
  44. data/lib/danger/ci_source/xcode_server.rb +48 -0
  45. data/lib/danger/clients/rubygems_client.rb +14 -0
  46. data/lib/danger/commands/dangerfile/gem.rb +43 -0
  47. data/lib/danger/commands/dangerfile/init.rb +30 -0
  48. data/lib/danger/commands/dry_run.rb +54 -0
  49. data/lib/danger/commands/init.rb +297 -0
  50. data/lib/danger/commands/init_helpers/interviewer.rb +92 -0
  51. data/lib/danger/commands/local.rb +83 -0
  52. data/lib/danger/commands/local_helpers/http_cache.rb +36 -0
  53. data/lib/danger/commands/local_helpers/local_setup.rb +46 -0
  54. data/lib/danger/commands/local_helpers/pry_setup.rb +31 -0
  55. data/lib/danger/commands/plugins/plugin_json.rb +46 -0
  56. data/lib/danger/commands/plugins/plugin_lint.rb +54 -0
  57. data/lib/danger/commands/plugins/plugin_readme.rb +45 -0
  58. data/lib/danger/commands/pr.rb +92 -0
  59. data/lib/danger/commands/runner.rb +94 -0
  60. data/lib/danger/commands/staging.rb +53 -0
  61. data/lib/danger/commands/systems.rb +43 -0
  62. data/lib/danger/comment_generators/bitbucket_server.md.erb +20 -0
  63. data/lib/danger/comment_generators/bitbucket_server_inline.md.erb +15 -0
  64. data/lib/danger/comment_generators/bitbucket_server_message_group.md.erb +12 -0
  65. data/lib/danger/comment_generators/github.md.erb +55 -0
  66. data/lib/danger/comment_generators/github_inline.md.erb +26 -0
  67. data/lib/danger/comment_generators/gitlab.md.erb +40 -0
  68. data/lib/danger/comment_generators/gitlab_inline.md.erb +26 -0
  69. data/lib/danger/comment_generators/vsts.md.erb +20 -0
  70. data/lib/danger/core_ext/file_list.rb +18 -0
  71. data/lib/danger/core_ext/string.rb +20 -0
  72. data/lib/danger/danger_core/dangerfile.rb +341 -0
  73. data/lib/danger/danger_core/dangerfile_dsl.rb +29 -0
  74. data/lib/danger/danger_core/dangerfile_generator.rb +11 -0
  75. data/lib/danger/danger_core/environment_manager.rb +123 -0
  76. data/lib/danger/danger_core/executor.rb +92 -0
  77. data/lib/danger/danger_core/message_aggregator.rb +49 -0
  78. data/lib/danger/danger_core/message_group.rb +68 -0
  79. data/lib/danger/danger_core/messages/base.rb +56 -0
  80. data/lib/danger/danger_core/messages/markdown.rb +42 -0
  81. data/lib/danger/danger_core/messages/violation.rb +54 -0
  82. data/lib/danger/danger_core/plugins/dangerfile_bitbucket_cloud_plugin.rb +144 -0
  83. data/lib/danger/danger_core/plugins/dangerfile_bitbucket_server_plugin.rb +211 -0
  84. data/lib/danger/danger_core/plugins/dangerfile_danger_plugin.rb +248 -0
  85. data/lib/danger/danger_core/plugins/dangerfile_git_plugin.rb +158 -0
  86. data/lib/danger/danger_core/plugins/dangerfile_github_plugin.rb +254 -0
  87. data/lib/danger/danger_core/plugins/dangerfile_gitlab_plugin.rb +240 -0
  88. data/lib/danger/danger_core/plugins/dangerfile_local_only_plugin.rb +42 -0
  89. data/lib/danger/danger_core/plugins/dangerfile_messaging_plugin.rb +218 -0
  90. data/lib/danger/danger_core/plugins/dangerfile_vsts_plugin.rb +191 -0
  91. data/lib/danger/danger_core/standard_error.rb +143 -0
  92. data/lib/danger/helpers/array_subclass.rb +61 -0
  93. data/lib/danger/helpers/comment.rb +32 -0
  94. data/lib/danger/helpers/comments_helper.rb +178 -0
  95. data/lib/danger/helpers/comments_parsing_helper.rb +70 -0
  96. data/lib/danger/helpers/emoji_mapper.rb +41 -0
  97. data/lib/danger/helpers/find_max_num_violations.rb +31 -0
  98. data/lib/danger/helpers/message_groups_array_helper.rb +31 -0
  99. data/lib/danger/plugin_support/gems_resolver.rb +77 -0
  100. data/lib/danger/plugin_support/plugin.rb +49 -0
  101. data/lib/danger/plugin_support/plugin_file_resolver.rb +30 -0
  102. data/lib/danger/plugin_support/plugin_linter.rb +161 -0
  103. data/lib/danger/plugin_support/plugin_parser.rb +199 -0
  104. data/lib/danger/plugin_support/templates/readme_table.html.erb +26 -0
  105. data/lib/danger/request_sources/bitbucket_cloud.rb +171 -0
  106. data/lib/danger/request_sources/bitbucket_cloud_api.rb +181 -0
  107. data/lib/danger/request_sources/bitbucket_server.rb +105 -0
  108. data/lib/danger/request_sources/bitbucket_server_api.rb +117 -0
  109. data/lib/danger/request_sources/github/github.rb +530 -0
  110. data/lib/danger/request_sources/github/github_review.rb +126 -0
  111. data/lib/danger/request_sources/github/github_review_resolver.rb +19 -0
  112. data/lib/danger/request_sources/github/github_review_unsupported.rb +25 -0
  113. data/lib/danger/request_sources/gitlab.rb +525 -0
  114. data/lib/danger/request_sources/local_only.rb +53 -0
  115. data/lib/danger/request_sources/request_source.rb +85 -0
  116. data/lib/danger/request_sources/support/get_ignored_violation.rb +17 -0
  117. data/lib/danger/request_sources/vsts.rb +118 -0
  118. data/lib/danger/request_sources/vsts_api.rb +138 -0
  119. data/lib/danger/scm_source/git_repo.rb +181 -0
  120. data/lib/danger/version.rb +4 -0
  121. metadata +339 -0
@@ -0,0 +1,54 @@
1
+ require "danger/commands/local_helpers/pry_setup"
2
+ require "fileutils"
3
+
4
+ module Danger
5
+ class DryRun < Runner
6
+ self.summary = "Dry-Run the Dangerfile locally, so you could check some violations before sending real PR/MR."
7
+ self.command = "dry_run"
8
+
9
+ def self.options
10
+ [
11
+ ["--pry", "Drop into a Pry shell after evaluating the Dangerfile."]
12
+ ]
13
+ end
14
+
15
+ def initialize(argv)
16
+ show_help = true if argv.arguments == ["-h"]
17
+
18
+ # Currently CLAide doesn't support short option like -h https://github.com/CocoaPods/CLAide/pull/60
19
+ # when user pass in -h, mimic the behavior of passing in --help.
20
+ argv = CLAide::ARGV.new ["--help"] if show_help
21
+
22
+ super
23
+
24
+ if argv.flag?("pry", false)
25
+ @dangerfile_path = PrySetup.new(cork).setup_pry(@dangerfile_path)
26
+ end
27
+ end
28
+
29
+ def validate!
30
+ super
31
+ unless @dangerfile_path
32
+ help! "Could not find a Dangerfile."
33
+ end
34
+ end
35
+
36
+ def run
37
+ ENV["DANGER_USE_LOCAL_ONLY_GIT"] = "YES"
38
+ ENV["DANGER_LOCAL_HEAD"] = @head if @head
39
+ ENV["DANGER_LOCAL_BASE"] = @base if @base
40
+
41
+ env = EnvironmentManager.new(ENV, cork)
42
+ dm = Dangerfile.new(env, cork)
43
+
44
+ exit 1 if dm.run(
45
+ Danger::EnvironmentManager.danger_base_branch,
46
+ Danger::EnvironmentManager.danger_head_branch,
47
+ @dangerfile_path,
48
+ nil,
49
+ nil,
50
+ nil
51
+ )
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,297 @@
1
+ require "danger/commands/init_helpers/interviewer"
2
+ require "danger/danger_core/dangerfile_generator"
3
+ require "danger/ci_source/local_git_repo"
4
+ require "yaml"
5
+
6
+ module Danger
7
+ class Init < Runner
8
+ self.summary = "Helps you set up Danger."
9
+ self.command = "init"
10
+
11
+ attr_accessor :ui
12
+
13
+ def self.options
14
+ [
15
+ ["--impatient", "'I've not got all day here. Don't add any thematic delays please.'"],
16
+ ["--mousey", "'Don't make me press return to continue the adventure.'"]
17
+ ].concat(super)
18
+ end
19
+
20
+ def initialize(argv)
21
+ @bot_name = File.basename(Dir.getwd).split(".").first.capitalize + "Bot"
22
+ super
23
+ @ui = Interviewer.new(cork)
24
+ ui.no_delay = argv.flag?("impatient", false)
25
+ ui.no_waiting = argv.flag?("mousey", false)
26
+ end
27
+
28
+ def run
29
+ ui.say "\nOK, thanks #{ENV['LOGNAME']}, have a seat and we'll get you started.\n".yellow
30
+ ui.pause 1
31
+
32
+ show_todo_state
33
+ ui.pause 1.4
34
+
35
+ setup_dangerfile
36
+ setup_github_account
37
+ setup_access_token
38
+ setup_danger_ci
39
+
40
+ info
41
+ thanks
42
+ end
43
+
44
+ def show_todo_state
45
+ ui.say "We need to do the following:\n"
46
+ ui.pause 0.6
47
+ ui.say " - [ ] Create a Dangerfile and add a few simple rules."
48
+ ui.pause 0.6
49
+ ui.say " - [#{@account_created ? 'x' : ' '}] Create a GitHub account for Danger to use, for messaging."
50
+ ui.pause 0.6
51
+ ui.say " - [ ] Set up an access token for Danger."
52
+ ui.pause 0.6
53
+ ui.say " - [ ] Set up Danger to run on your CI.\n\n"
54
+ end
55
+
56
+ def setup_dangerfile
57
+ content = DangerfileGenerator.create_dangerfile(".", cork)
58
+ File.write("Dangerfile", content)
59
+
60
+ ui.header "Step 1: Creating a starter Dangerfile"
61
+ ui.say "I've set up an example Dangerfile for you in this folder.\n"
62
+ ui.pause 1
63
+
64
+ ui.say "cat #{Dir.pwd}/Dangerfile\n".blue
65
+ content.lines.each do |l|
66
+ ui.say " " + l.chomp.green
67
+ end
68
+ ui.say ""
69
+ ui.pause 2
70
+
71
+ ui.say "There's a collection of small, simple ideas in here, but Danger is about being able to easily"
72
+ ui.say "iterate. The power comes from you having the ability to codify fixes for some of the problems"
73
+ ui.say "that come up in day to day programming. It can be difficult to try and see those from day 1."
74
+
75
+ ui.say "\nIf you'd like to investigate the file, and make some changes - I'll wait here,"
76
+ ui.say "press return when you're ready to move on..."
77
+ ui.wait_for_return
78
+ end
79
+
80
+ def setup_github_account
81
+ ui.header "Step 2: Creating a GitHub account"
82
+
83
+ ui.say "In order to get the most out of Danger, I'd recommend giving her the ability to post in"
84
+ ui.say "the code-review comment section.\n\n"
85
+ ui.pause 1
86
+
87
+ ui.say "IMO, it's best to do this by using the private mode of your browser. Create an account like"
88
+ ui.say "#{@bot_name}, and don't forget a cool robot avatar.\n\n"
89
+ ui.pause 1
90
+ ui.say "Here are great resources for creative commons images of robots:"
91
+ ui.link "https://www.flickr.com/search/?text=robot&license=2%2C3%2C4%2C5%2C6%2C9"
92
+ ui.link "https://www.google.com/search?q=robot&tbs=sur:fmc&tbm=isch&tbo=u&source=univ&sa=X&ved=0ahUKEwjgy8-f95jLAhWI7hoKHV_UD00QsAQIMQ&biw=1265&bih=1359"
93
+ ui.pause 1
94
+
95
+ if considered_an_oss_repo?
96
+ ui.say "#{@bot_name} does not need privileged access to your repo or org. This is because Danger will only"
97
+ ui.say "be writing comments, and you do not need special access for that."
98
+ else
99
+ ui.say "#{@bot_name} will need access to your repo. Simply because the code is not available for the public"
100
+ ui.say "to read and comment on."
101
+ end
102
+
103
+ ui.say ""
104
+ note_about_clicking_links
105
+ ui.pause 1
106
+ ui.say "\nCool, please press return when you have your account ready (and you've verified the email...)"
107
+ ui.wait_for_return
108
+ end
109
+
110
+ def setup_access_token
111
+ ui.header "Step 3: Configuring a GitHub Personal Access Token"
112
+
113
+ ui.say "Here's the link, you should open this in the private session where you just created the new GitHub account"
114
+ ui.link "https://github.com/settings/tokens/new"
115
+ ui.pause 1
116
+
117
+ @is_open_source = ui.ask_with_answers("For token access rights, I need to know if this is for an Open Source or Closed Source project\n", ["Open", "Closed"])
118
+
119
+ if considered_an_oss_repo?
120
+ ui.say "For Open Source projects, I'd recommend giving the token the smallest scope possible."
121
+ ui.say "This means only providing access to " + "public_repo".yellow + " in the token.\n\n"
122
+ ui.pause 1
123
+ ui.say "This token limits Danger's abilities to just writing comments on OSS projects. I recommend"
124
+ ui.say "this because the token can quite easily be extracted from the environment via pull requests."
125
+
126
+ ui.say "\nIt is important that you do not store this token in your repository, as GitHub will automatically revoke it when pushed.\n"
127
+ elsif @is_open_source == "closed"
128
+ ui.say "For Closed Source projects, I'd recommend giving the token access to the whole repo scope."
129
+ ui.say "This means only providing access to " + "repo".yellow + ", and its children in the token.\n\n"
130
+ ui.pause 1
131
+ ui.say "It's worth noting that you " + "should not".bold.white + " re-use this token for OSS repos."
132
+ ui.say "Make a new one for those repos with just " + "public_repo".yellow + "."
133
+ ui.pause 1
134
+ ui.say "Additionally, don't forget to add your new GitHub account as a collaborator to your Closed Source project."
135
+ end
136
+
137
+ ui.say "\n👍, please press return when you have your token set up..."
138
+ ui.wait_for_return
139
+ end
140
+
141
+ def considered_an_oss_repo?
142
+ @is_open_source == "open"
143
+ end
144
+
145
+ def current_repo_slug
146
+ git = GitRepo.new
147
+
148
+ author_repo_regexp = %r{(?:[\/:])([^\/]+\/[^\/]+)(?:.git)?$}
149
+ last_git_regexp = /.git$/
150
+
151
+ matches = git.origins.match(author_repo_regexp)
152
+
153
+ matches ? matches[1].gsub(last_git_regexp, "").strip : "[Your/Repo]"
154
+ end
155
+
156
+ def setup_danger_ci
157
+ ui.header "Step 4: Add Danger for your CI"
158
+
159
+ uses_travis if File.exist? ".travis.yml"
160
+ uses_circle if File.exist? "circle.yml"
161
+ unsure_ci unless File.exist?(".travis.yml") || File.exist?(".circle.yml")
162
+
163
+ ui.say "\nOK, I'll give you a moment to do this..."
164
+ ui.wait_for_return
165
+
166
+ ui.header "Final step: exposing the GitHub token as an environment build variable."
167
+ ui.pause 0.4
168
+ if considered_an_oss_repo?
169
+ ui.say "As you have an Open Source repo, this token should be considered public, otherwise you cannot"
170
+ ui.say "run Danger on pull requests from forks, limiting its use.\n"
171
+ ui.pause 1
172
+ end
173
+
174
+ travis_token if File.exist? ".travis.yml"
175
+ circle_token if File.exist? "circle.yml"
176
+ unsure_token unless File.exist?(".travis.yml") || File.exist?(".circle.yml")
177
+
178
+ ui.pause 0.6
179
+ ui.say "This is the last step, I can give you a second..."
180
+ ui.wait_for_return
181
+ end
182
+
183
+ def uses_travis
184
+ danger = "bundle exec danger".yellow
185
+ config = YAML.load(File.read(".travis.yml"))
186
+ if config.kind_of?(Hash) && config["script"]
187
+ ui.say "Add " + "- ".yellow + danger + " as a new step in the " + "script".yellow + " section of your .travis.yml file."
188
+ else
189
+ ui.say "I'd recommend adding " + "before_script: ".yellow + danger + " to the script section of your .travis.yml file."
190
+ end
191
+
192
+ ui.pause 1
193
+ ui.say "You shouldn't use " + "after_success, after_failure, after_script".red + " as they cannot fail your builds."
194
+ end
195
+
196
+ def uses_circle
197
+ danger = "- bundle exec danger".yellow
198
+ config = YAML.load(File.read("circle.yml"))
199
+
200
+ if config.kind_of?(Hash) && config["test"]
201
+ if config["test"]["post"]
202
+ ui.say "Add " + danger + " as a new step in the " + "test:post:".yellow + " section of your circle.yml file."
203
+ else
204
+ ui.say "Add " + danger + " as a new step in the " + "test:override:".yellow + " section of your circle.yml file."
205
+ end
206
+ else
207
+ ui.say "Add this to the bottom of your circle.yml file:"
208
+ ui.say "test:".green
209
+ ui.say " post:".green
210
+ ui.say " #{danger}".green
211
+ end
212
+ end
213
+
214
+ def unsure_ci
215
+ danger = "bundle exec danger".yellow
216
+ ui.say "As I'm not sure what CI you want to run Danger on based on the files in your repo, I'll just offer some generic"
217
+ ui.say "advice. You want to run " + danger + " after your tests have finished running, it should still be during the testing"
218
+ ui.say "process so the build can fail."
219
+ end
220
+
221
+ def travis_token
222
+ # https://travis-ci.org/artsy/eigen/settings
223
+ ui.say "In order to add an environment variable, go to:"
224
+ ui.link "https://travis-ci.org/#{current_repo_slug}/settings"
225
+ ui.say "\nThe name is " + "DANGER_GITHUB_API_TOKEN".yellow + " and the value is the GitHub Personal Access Token."
226
+ if @is_open_source
227
+ ui.say 'Make sure to have "Display value in build log" enabled.'
228
+ end
229
+ end
230
+
231
+ def circle_token
232
+ # https://circleci.com/gh/artsy/eigen/edit#env-vars
233
+ if considered_an_oss_repo?
234
+ ui.say "Before we start, it's important to be up-front. CircleCI only really has one option to support running Danger"
235
+ ui.say "for forks on OSS repos. It is quite a drastic option, and I want to let you know the best place to understand"
236
+ ui.say "the ramifications of turning on a setting I'm about to advise.\n"
237
+ ui.link "https://circleci.com/docs/fork-pr-builds"
238
+ ui.say "TLDR: If you have anything other than Danger config settings in CircleCI, then you should not turn on the setting."
239
+ ui.say "I'll give you a minute to read it..."
240
+ ui.wait_for_return
241
+
242
+ ui.say "On danger/danger we turn on " + "Permissive building of fork pull requests".yellow + " this exposes the token to Danger"
243
+ ui.say "You can find this setting at:"
244
+ ui.link "https://circleci.com/gh/#{current_repo_slug}/edit#advanced-settings\n"
245
+ ui.say "I'll hold..."
246
+ ui.wait_for_return
247
+ end
248
+
249
+ ui.say "In order to expose an environment variable, go to:"
250
+ ui.link "https://circleci.com/gh/#{current_repo_slug}/edit#env-vars"
251
+ ui.say "The name is " + "DANGER_GITHUB_API_TOKEN".yellow + " and the value is the GitHub Personal Access Token."
252
+ end
253
+
254
+ def unsure_token
255
+ ui.say "You need to expose a token called " + "DANGER_GITHUB_API_TOKEN".yellow + " and the value is the GitHub Personal Access Token."
256
+ ui.say "Depending on the CI system, this may need to be done on the machine (in the " + "~/.bashprofile".yellow + ") or in a web UI somewhere."
257
+ ui.say "We have a guide for all supported CI systems on danger.systems:"
258
+ ui.link "https://danger.systems/guides/getting_started.html#setting-up-danger-to-run-on-your-ci"
259
+ end
260
+
261
+ def note_about_clicking_links
262
+ modifier_key = "ctrl"
263
+ clicks = "clicking"
264
+
265
+ modifier_key = "cmd ( ⌘ )" if darwin?
266
+ clicks = "double clicking" if darwin? && !ENV["ITERM_SESSION_ID"]
267
+
268
+ ui.say "Note: Holding #{modifier_key} and #{clicks} a link will open it in your browser."
269
+ end
270
+
271
+ def info
272
+ ui.header "Useful info"
273
+ ui.say "- One of the best ways to test out new rules locally is via " + "bundle exec danger pr".yellow + "."
274
+ ui.pause 0.6
275
+ ui.say "- You can have Danger output all of her variables to the console via the " + "--verbose".yellow + " option."
276
+ ui.pause 0.6
277
+ ui.say "- You can look at the following Dangerfiles to get some more ideas:"
278
+ ui.pause 0.6
279
+ ui.link "https://github.com/danger/danger/blob/master/Dangerfile"
280
+ ui.link "https://github.com/artsy/eigen/blob/master/Dangerfile"
281
+ ui.pause 1
282
+ end
283
+
284
+ def thanks
285
+ ui.say "\n\n🎉"
286
+ ui.pause 0.6
287
+
288
+ ui.say "And you're good to go. Danger is a collaboration between Orta Therox, Gem 'Danger' McShane and Felix Krause."
289
+ ui.say "If you like Danger, let others know. If you want to know more, follow " + "@orta".yellow + " and " + "@KrauseFx".yellow + " on Twitter."
290
+ ui.say "If you don't like Danger, help us improve the project! xxx"
291
+ end
292
+
293
+ def darwin?
294
+ Gem::Platform.local.os == "darwin"
295
+ end
296
+ end
297
+ end
@@ -0,0 +1,92 @@
1
+ module Danger
2
+ class Interviewer
3
+ attr_accessor :no_delay, :no_waiting, :ui
4
+
5
+ def initialize(cork_board)
6
+ @ui = cork_board
7
+ end
8
+
9
+ def show_prompt
10
+ ui.print "> ".bold.green
11
+ end
12
+
13
+ def yellow_bang
14
+ "! ".yellow
15
+ end
16
+
17
+ def green_bang
18
+ "! ".green
19
+ end
20
+
21
+ def red_bang
22
+ "! ".red
23
+ end
24
+
25
+ def say(output)
26
+ ui.puts output
27
+ end
28
+
29
+ def header(title)
30
+ say title.yellow
31
+ say ""
32
+ pause 0.6
33
+ end
34
+
35
+ def link(url)
36
+ say " -> " + url.underlined + "\n"
37
+ end
38
+
39
+ def pause(time)
40
+ sleep(time) unless @no_waiting
41
+ end
42
+
43
+ def wait_for_return
44
+ STDOUT.flush
45
+ STDIN.gets unless @no_delay
46
+ ui.puts
47
+ end
48
+
49
+ def run_command(command, output_command = nil)
50
+ output_command ||= command
51
+ ui.puts " " + output_command.magenta
52
+ system command
53
+ end
54
+
55
+ def ask_with_answers(question, possible_answers)
56
+ ui.print "\n#{question}? ["
57
+
58
+ print_info = proc do
59
+ possible_answers.each_with_index do |answer, i|
60
+ the_answer = i.zero? ? answer.underlined : answer
61
+ ui.print " " + the_answer
62
+ ui.print(" /") if i != possible_answers.length - 1
63
+ end
64
+ ui.print " ]\n"
65
+ end
66
+ print_info.call
67
+
68
+ answer = ""
69
+
70
+ loop do
71
+ show_prompt
72
+ answer = @no_waiting ? possible_answers[0].downcase : STDIN.gets.downcase.chomp
73
+
74
+ answer = "yes" if answer == "y"
75
+ answer = "no" if answer == "n"
76
+
77
+ # default to first answer
78
+ if answer == ""
79
+ answer = possible_answers[0].downcase
80
+ ui.puts "Using: " + answer.yellow
81
+ end
82
+
83
+ break if possible_answers.map(&:downcase).include? answer
84
+
85
+ ui.print "\nPossible answers are ["
86
+ print_info.call
87
+ end
88
+
89
+ answer
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,83 @@
1
+ require "danger/commands/local_helpers/http_cache"
2
+ require "danger/commands/local_helpers/local_setup"
3
+ require "danger/commands/local_helpers/pry_setup"
4
+ require "faraday/http_cache"
5
+ require "fileutils"
6
+ require "octokit"
7
+ require "tmpdir"
8
+
9
+ module Danger
10
+ class Local < Runner
11
+ self.summary = "Run the Dangerfile locally. This command is generally deprecated in favor of `danger pr`."
12
+ self.command = "local"
13
+
14
+ def self.options
15
+ [
16
+ ["--use-merged-pr=[#id]", "The ID of an already merged PR inside your history to use as a reference for the local run."],
17
+ ["--clear-http-cache", "Clear the local http cache before running Danger locally."],
18
+ ["--pry", "Drop into a Pry shell after evaluating the Dangerfile."]
19
+ ]
20
+ end
21
+
22
+ def initialize(argv)
23
+ show_help = true if argv.arguments == ["-h"]
24
+
25
+ @pr_num = argv.option("use-merged-pr")
26
+ @clear_http_cache = argv.flag?("clear-http-cache", false)
27
+
28
+ # Currently CLAide doesn't support short option like -h https://github.com/CocoaPods/CLAide/pull/60
29
+ # when user pass in -h, mimic the behavior of passing in --help.
30
+ argv = CLAide::ARGV.new ["--help"] if show_help
31
+
32
+ super
33
+
34
+ if argv.flag?("pry", false)
35
+ @dangerfile_path = PrySetup.new(cork).setup_pry(@dangerfile_path)
36
+ end
37
+ end
38
+
39
+ def validate!
40
+ super
41
+ unless @dangerfile_path
42
+ help! "Could not find a Dangerfile."
43
+ end
44
+ end
45
+
46
+ def run
47
+ ENV["DANGER_USE_LOCAL_GIT"] = "YES"
48
+ ENV["LOCAL_GIT_PR_ID"] = @pr_num if @pr_num
49
+
50
+ configure_octokit(ENV["DANGER_TMPDIR"] || Dir.tmpdir)
51
+
52
+ env = EnvironmentManager.new(ENV, cork)
53
+ dm = Dangerfile.new(env, cork)
54
+
55
+ LocalSetup.new(dm, cork).setup(verbose: verbose) do
56
+ dm.run(
57
+ Danger::EnvironmentManager.danger_base_branch,
58
+ Danger::EnvironmentManager.danger_head_branch,
59
+ @dangerfile_path,
60
+ nil,
61
+ nil,
62
+ nil
63
+ )
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ # this method is a duplicate of Commands::PR#configure_octokit
70
+ # - worth a refactor sometime?
71
+ def configure_octokit(cache_dir)
72
+ # setup caching for Github calls to hitting the API rate limit too quickly
73
+ cache_file = File.join(cache_dir, "danger_local_cache")
74
+ cache = HTTPCache.new(cache_file, clear_cache: @clear_http_cache)
75
+ Octokit.middleware = Faraday::RackBuilder.new do |builder|
76
+ builder.use Faraday::HttpCache, store: cache, serializer: Marshal, shared_cache: false
77
+ builder.use Octokit::Middleware::FollowRedirects
78
+ builder.use Octokit::Response::RaiseError
79
+ builder.adapter Faraday.default_adapter
80
+ end
81
+ end
82
+ end
83
+ end