
ããã«ã¡ã¯ã¼ï¼ããã²ã¨ã¡ã»ã¼ã®ãããã«ãã®ãã¬ã³ãº@Utmrerã ãã¼ï¼
ä»åã¯Pull Requestãèªåã§ãã§ãã¯ãã¦ãããDangerã«ã¤ãã¦ç´¹ä»ãã¾ãã
Pull Requestã§ã®ã³ãã¥ãã±ã¼ã·ã§ã³
Pull Requestã®ã¬ãã¥ã¼ã¯ä¸å ·åã®ææãã³ã¼ãã£ã³ã°ã¹ã¿ã¤ã«ã®çµ±ä¸ãããè¯ãã³ã¼ãã®ããã®ææ¡ãªã©ã®ããã«è¡ããã¾ãã ã§ãããæ¬¡ã®ãããªã³ãã¥ãã±ã¼ã·ã§ã³ããããã¨ã¯ããã¾ãããâ¦ï¼
- ã¿ã¤ãã«ã«Issue Idãå«ãã¦ãããã¾ããï¼
- WIPã¿ãããªãã§ããã¬ãã¥ã¼ãã¦å¤§ä¸å¤«ã§ããï¼
- Base branchãééã£ã¦ã¾ãã夿´ãã¦ãã ããã
- 夿´å±¥æ´ã®docsãæ´æ°ãã¦ãã ããã
ãã®ãããªãå®è£
ã¨ã¯é¢ä¿ã®ãªãææãã¯ã§ããã ãæ¸ãããèªååããããã®ã§ãããããå®ç¾ããã®ãDangerã§ãã
Dangerã¨ã¯
Dangerã®GitHubã«ã¯æ¬¡ã®ããã«æ¸ããã¦ãã¾ãã
Formalize your Pull Request etiquette.
Stop saying “you forgot to ⦔ in code review
ã¤ã¾ããPull Requestã®ä½æ³ãå½¢å¼åãã¦ææãèªååããããã¼ã«ã§ãã
Dangerããã§ãã¯ããã®ã¯Pull Requestã®ä½è£ãªã®ã§ãã®Pull RequestãSwiftã®ããã¸ã§ã¯ãã§ããããRubyã§ããããé¢ä¿ãªãããã¹ã¦ã®ããã¸ã§ã¯ãã«å°å ¥å¯è½ã§ãã å®éã«RxSwiftã¨ããSwiftã®ããã¸ã§ã¯ããcapistranoãsentryãªã©æ§ã ãªããã¸ã§ã¯ãã§å°å ¥ããã¦ãã¾ãã
Dangerã®å°å ¥
Travisä¸ã§Dangerãå®è¡ããGitHubã®Pull Requestã«ã³ã¡ã³ãããã¨ããã¾ã§ã説æãã¾ãã
Gemfileã®è¨å®
Gemfileã«Dangerã追å ãã¾ããããã ãã§Travisä¸ã§Dangerãå®è¡ã§ãã¾ãã
source 'https://rubygems.org' gem 'danger'
Dangerfileã®è¿½å
ããã¸ã§ã¯ãã®ã«ã¼ããã£ã¬ã¯ããªã«Dangerfileã¨ãããã¡ã¤ã«ã追å ãã¾ãã
ãã®ãã¡ã¤ã«ã«Dangerã«ã©ã®ãããªé ç®ããã§ãã¯ãã¦ãããããè¨è¿°ãã¦ããã¾ãã
warn('ãã¶ãªããã¼ï¼')
warn(message)ã¨æ¸ãã¨ãããã¯æ³¨æãå¿
è¦ã ããã¨GitHubã«ã³ã¡ã³ããã¾ãã
é常ã¯ç¹å®ã®æ¡ä»¶ã«ãã£ã¦ã³ã¡ã³ãããã®ã§ifãªã©ã§å²ã¿ã¾ããä»åã¯ãã®ã¾ã¾ã«ãã¦ããã¾ãã
.travis.ymlã®è¨å®
.travis.ymlã«Dangerãå®è¡ããããã«è¨å®ãã¾ãã
cache: - bundler before_script: - bundle exec danger
Cacheæ©è½ã使ãã°æ¯åbundle installãå®è¡ããå¿
è¦ãç¡ãã®ã§æéç¯ç´ã®ããã«ããããã§ãã
Travisç°å¢å¤æ°ã®è¨å®
TravisããGitHubã¸ã³ã¡ã³ããããããTravisã«GitHubã®ã¢ã¯ã»ã¹ãã¼ã¯ã³ãè¨å®ããå¿ è¦ãããã¾ãã ã¢ã¯ã»ã¹ãã¼ã¯ã³ã¯ãã¡ãã®ãã¼ã¸ãã使ã§ãã¾ãã
Dangerã§ã¯å
¬éããã¸ã§ã¯ãã§ã¯public_repoãéå
¬éããã¸ã§ã¯ãã§ã¯repoã®æ¨©éãæã£ãã¢ã¯ã»ã¹ãã¼ã¯ã³ãæ¨å¥¨ããã¦ãã¾ãã
ã¾ãããã®æã«ã¢ã¯ã»ã¹ãã¼ã¯ã³ãçºè¡ããGitHubã¢ã«ã¦ã³ãã¯æ®æ®µä½¿ã£ã¦ããå人ã¢ã«ã¦ã³ãã§ã¯ãªãBotç¨ã®Machineã¢ã«ã¦ã³ãã®æ¹ãè¯ãã§ããGitHubã¯1人1ã¢ã«ã¦ã³ãã®Machineã¢ã«ã¦ã³ãã®ä½æã許å¯ãã¦ãã¾ãã
çºè¡ããã¢ã¯ã»ã¹ãã¼ã¯ã³ã¯Travisã®åRepositoryã®settingsãã¼ã¸ã§è¨å®ãã¾ãã
Environment Variablesã«DANGER_GITHUB_API_TOKENã¨ããNameã§å
ç¨ã®ã¢ã¯ã»ã¹ãã¼ã¯ã³ã追å ãã¾ãã
Pull Requestã®ä½æ
以ä¸ã§Dangerã®æä½éã®è¨å®ã¯çµäºã§ããPull Requestã使ããã¨Dangerããã³ã¡ã³ããæ¥ã¾ãã

ããã¾ã§ã®å°å ¥æ¹æ³ã¯Dangerã®å ¬å¼HPã«ãè¼ã£ã¦ãã¾ãã GitLabãå©ç¨ãã¦ããæ¹ãCircle CIãå©ç¨ãã¦ããæ¹ã¯ãã¡ããããèªåã®ç°å¢ã«ãã£ãæ¹æ³ã§å°å ¥ãã¦ãã ããã
æ§æ
DSL
Dangerã«ã¯ã³ã¡ã³ããæ¸ãè¾¼ãDSLãããã¤ããããæããã使ãã§ããã3ã¤ã®DSLãç´¹ä»ãã¾ãã
ð message
messageã¯åç´ã«ã³ã¡ã³ããæ¸ãè¾¼ãDSLã§ããå®åæãè¿ãæãªã©ã«ä½¿ãããã§ããã
message('Pull Requestãããã¨ããããã¾ããã¬ãã¥ã¼ã¾ã§å°ã ãå¾ ã¡ä¸ããã')
â warn
warnã¯åºæ¥ãã°ä¿®æ£ãã¦æ¬²ãããããããããéåãã¦ããããã¨ããå ´åã«ä½¿ãã¾ããPull Requestã®ã¿ã¤ãã«ããã£ã¹ã¯ãªãã·ã§ã³ã«é¢ãããã®ã¯warnãããã§ãããã
warn('descriptionã300å以䏿¸ãã¦ä¸ãã')
ð« fail
failã¯è¨±å®¹ã§ããªãå 容ã®å ´åã«ä½¿ãã¾ãããããã®DSLãå©ç¨ããæãCommit stateã¯failureã«ãªãã¾ãã
fail('LICENSEãã¡ã¤ã«ã¯å¤æ´ããªãã§ä¸ããã')
夿°
ç°å¢ã«ãã£ã¦Dangerfileä¸ã§æ±ãã夿°ãããã¤ãããã¾ããããããçµã¿åããããã¨ã§ã«ã¼ã«ãä½ã£ã¦ããã¾ããä»åã¯GitHubç°å¢ã§ä½¿ããgitã¨githubã«ã¤ãã¦ç´¹ä»ãã¾ãã
git
gitã¨ãã夿°ã«ã¯Pull Requestã®å¯¾è±¡ã¨ãªã£ã¦ããCommitã®æ
å ±ãªã©ãå«ã¾ãã¦ãã¾ããä¾ãã°ãç·¨éãããã¡ã¤ã«ã®ä¸è¦§ããåé¤ããè¡æ°ããªã©ã§ãã
if git.deleted_files.include? "LICENSE" fail('LICENSEãã¡ã¤ã«ã¯å¤æ´ããªãã§ä¸ããã') end
github
githubã¨ãã夿°ããPull Requestã®æ
å ±ãåå¾ã§ãã¾ããgithub.pr_jsonããPull Requestå
¨ä½ã®æ
å ±ãåå¾ã§ããGitHubã®API Referenceãªã©ãèªãã¨github.pr_jsonã«ã©ã®ãããªå¤ãå
¥ã£ã¦ããããããã§ãããã
ãã使ããã¼ã¿ã«ã¯å°ç¨ã®é¢æ°ãç¨æããã¦ãã¦github.pr_titleãgithub.pr_bodyããã¿ã¤ãã«ããã£ã¹ã¯ãªãã·ã§ã³ããã·ã³ãã«ã«åå¾ã§ãã¾ãã
if !github.pr_json['mergeable'] fail('ãã¼ã¸ã§ãã¾ããã') end if !github.pr_title.include? "WIP" warn('ãã®Pull Requestã¯å®è£ éä¸ã§ãã') end
詳ããã¯Referenceãã覧ãã ããã
Dangerå°å ¥äºä¾
Dangerã®å°å ¥æ¹æ³ãããã£ãã¨ããã§ãOSSããã¸ã§ã¯ããDangerã§ã©ã®ãããªãã¨ãè¡ã£ã¦ãããè¦ã¦ã¿ã¾ãããã
capistrano
capistranoã§ã¯Dangerfileã§æ¬¡ã®ãããªãã¨ããã§ãã¯ãã¦ããããã§ãã
has_lib_changes = !git.modified_files.grep(/^lib/).empty? has_test_changes = !git.modified_files.grep(/^(features|spec)/).empty? has_changelog_changes = git.modified_files.include?("CHANGELOG.md") if has_lib_changes && !has_test_changes warn("There are code changes, but no corresponding tests. "\ "Please include tests if this PR introduces any modifications in "\ "#{project_name}'s behavior.", :sticky => false) end
ãLibraryã«å¤æ´ããã£ããªããã¹ããæ¸ãããã¨ãããã¨ããã§ãã¯ãã¦ãã¾ãããReviewerã«ææãããåã«Testãæ¸ããã°ã³ãã¥ãã±ã¼ã·ã§ã³ãæ¸ã£ã¦æéã®ç¯ç´ã«ãªãã¾ãã
if !has_changelog_changes && has_lib_changes markdown <<-MARKDOWN Here's an example of a CHANGELOG.md entry (place it immediately under the `* Your contribution here!` line): ```markdown * [##{pr_number}](#{pr_url}): #{github.pr_title} - [@#{github.pr_author}](https://github.com/#{github.pr_author}). ``` MARKDOWN warn("Please update CHANGELOG.md with a description of your changes. "\ "If this PR is not a user-facing change (e.g. just refactoring), "\ "you can disregard this.", :sticky => false) end
ã¾ãLibraryã«å¤æ´ããã£ããªãCHANGELOG.mdã«å¤æ´ç¹ãæ¸ãããã«ä¿ãã¦ãã¾ããããã¯åç¨ãããã¯ãã§ãHelpã®æ´æ°ã仿§æ¸ã®æ´æ°ãªã©ã«ä½¿ããããªãã¸ãã¯ã§ãã
Sentry
Sentryã§ã¯Pull Requestã®ä½è£ã«é¢ãããã®ãããã¤ãããã¾ãã
# Make it more obvious that a PR is a work in progress and shouldn"t be merged yet warn("PR is classed as Work in Progress") if github.pr_title.include? "[WIP]" || github.pr_body.include?("#wip")
ã¿ã¤ãã«ã¨ãã£ã¹ã¯ãªãã·ã§ã³ããã§ãã¯ãã¦Pull RequestãWIPãã©ãããå¤å®ãã¦ãã¾ããWIPãªã®ã«Reviewããé¡ããããã¨ãé²ãã¾ãããReviewerããWIPãªã®ã§è¦ãªãã¦å¤§ä¸å¤«ï¼ãã¨å¤æã§ãã¾ãã
@S_BIG_PR_LINES ||= 500 # Warn when there is a big PR warn("Big PR -- consider splitting it up into multiple changesets") if git.lines_of_code > @S_BIG_PR_LINES
Pull Requestã®å®è£ è¡æ°ã大ããããå ´åã¯åå²ããããã«ä¿ãã¦ãã¾ããå®è£ å 容ãè¨å¤§ãªPull Requestã¯Reviewã大å¤ã§ãããä¸å ·åãç´ãè¾¼ãå¯è½æ§ãé«ãã®ã§åå²ãã¦Pull Requestãä½ãã®ã¯è¯ããã¨ã§ããã
mamariQ
æå¾ã«ãå¼ç¤¾ã®ãããªQ iOSã¢ããªã®Dangerfileãå ¬éãã¾ãã
# -------------------- # test # -------------------- is_source_changed = !git.modified_files.grep(/^mamariQ\/Classes/).empty? is_test_changed = !git.modified_files.grep(/^mamariQTests\/Case/).empty? if is_source_changed && !is_test_changed warn('ã³ã¼ãã®å¤æ´ãããã¾ããããã¹ãã®å¤æ´ãããã¾ãããå¿ è¦ã§ããã°ãã¹ãã追å ã»ä¿®æ£ãã¾ãããã') end # -------------------- # base branch # -------------------- is_to_master = github.branch_for_base == 'master' is_to_release = !!github.branch_for_base.match(/release-[0-9]+\.[0-9]+\.[0-9]/) is_from_release = !!github.branch_for_head.match(/release-[0-9]+\.[0-9]+\.[0-9]/) if is_to_master && !is_from_release warn('masterã¸mergeåºæ¥ãã®ã¯release branchã®ã¿ã§ãã') end if is_to_release warn('release branchã«å¯¾ãã¦PRãåããªãã§ä¸ãããdevelop branchã«åãã¦PRã使ããdevelop branchãrelease branchã«mergeãã¦ãã ããã') end # -------------------- # pr title # -------------------- is_wip = github.pr_title.include? '[WIP]' if is_wip warn('ãã®PRã¯ä½æ¥ä¸ã§ãã') end is_to_develop = github.branch_for_base == 'develop' is_start_with_issue_id = !!github.pr_title.match(/^#[0-9]+/) if is_to_develop && !is_start_with_issue_id && !is_wip warn('PRã®ã¿ã¤ãã«ã¯<b>ã#XXX Foo bar...ã</b>ã¨Issue idããå§ãã¦ãã ããã') end # -------------------- # diff size # -------------------- is_big_pr = git.lines_of_code > 500 if is_big_pr warn('PRã®å¤æ´éãå¤ããã¾ããå¯è½ã§ããã°PRãåå²ãã¾ããããåå²ãé£ãããã°æ¬¡ããæ°ãã¤ããããã«ãã¾ãããã') end
å¼ç¤¾ã®iOSéçºã§ã¯git-flowãæ¡ç¨ãã¦ãã¦ãPull Requestã«ãããBase branchã®é¸æãã¡ãã£ã¨è¤éã§ãããã®ãããDangerã§Base branchã®ãã§ãã¯ãèªååãã¦ãã¾ãããã®Dangerfileãæ¸ããã®ã¯ç§ãªã®ã«èªåã§å¼ã£ããããã¨ããã£ã¦Dangerã«æè¬ææ¿ã§ãã
人ã¯äººã«ããåºæ¥ãªããã¨ã
Dangerã«ã¯Pluginæ©è½ããããæ©è½ãæ¡å¼µã§ããã®ã§å¯è½æ§ã¯âã§ããAndroid LintãSwiftLintã®Pluginãããã¾ãã(ç§ã®ç°å¢ã§ã¯SwiftLint Pluginåããªãã£ãã®ã§åä½ã¯ä¿è¨¼ã§ããªãã§ããâ¦)
ããããã°ãDangerãä½ã£ãOrtaããã¨KrauseFxããã¯try! Swiftã§è¬æ¼ãããããã§ãããtry! Swiftã«è¡ãããæ¹ã¯Dangerã®è©±ããã¦ã¿ã¦ã¯ã©ãã§ãããï¼ç§ãããã¾ãâº
æ©æ¢°ã«åºæ¥ããã¨ã¯æ©æ¢°ã«ä»»ãã¦ã人ã¯äººã«ããåºæ¥ãªããã¨ã«éä¸ãã¦ããã¾ãããã