danger-samsao 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ # rubocop:disable Style/HashSyntax
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ task default: :check
8
+
9
+ task :check => [:lint, :tests]
10
+
11
+ task :lint => [:lint_ruby, :lint_danger]
12
+
13
+ desc 'Run RuboCop on the lib/specs directory'
14
+ RuboCop::RakeTask.new(:lint_ruby)
15
+
16
+ desc 'Ensure that the plugin passes `danger plugins lint`'
17
+ task :lint_danger do
18
+ sh 'bundle exec danger plugins lint --warnings-as-errors'
19
+ end
20
+
21
+ task :test => [:tests]
22
+ RSpec::Core::RakeTask.new(:tests)
@@ -0,0 +1,51 @@
1
+ ---
2
+ format_version: 1.4.0
3
+ default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
4
+ description: |-
5
+ This wrapper is configure in bitrise.io editor as the script to run. What it
6
+ does mainly is to simply clone the repository and forward the execution of the
7
+ workflow to the real build file (bitrise.yml) which is hosted in this repository.
8
+
9
+ To work, main workflow here must also be present in bitrise.yml, so main workflows
10
+ must be kept synchronized between the two.
11
+
12
+ Also, any change made to this file must be **manually** added to bitrise.io editor.
13
+ Simply copy/paste the content of this file into the web editor and press save.
14
+
15
+ To test locally using bitrise CLI, while at project root directory, simply do:
16
+
17
+ bitrise run <workflow> -c bitrise.wrapper.yml
18
+
19
+ See http://devcenter.bitrise.io/tips-and-tricks/use-bitrise-yml-from-repository/
20
+ for details on the technique.
21
+
22
+ trigger_map:
23
+ - push_branch: "develop"
24
+ workflow: "develop"
25
+ - pull_request_target_branch: "*"
26
+ pull_request_source_branch: "*"
27
+ workflow: "pr"
28
+
29
+ workflows:
30
+ _run_from_repo:
31
+ steps:
32
+ - activate-ssh-key@3.1.1:
33
+ title: Activate SSH credentials
34
+ run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
35
+ - git-clone@3.4.2:
36
+ title: Clone repository
37
+ - script@1.1.3:
38
+ title: Continue using repository bitrise.yml
39
+ inputs:
40
+ - content: |-
41
+ #!/bin/bash
42
+ set -ex
43
+ bitrise run "${BITRISE_TRIGGERED_WORKFLOW_ID}"
44
+
45
+ develop:
46
+ after_run:
47
+ - _run_from_repo
48
+
49
+ pr:
50
+ after_run:
51
+ - _run_from_repo
@@ -0,0 +1,70 @@
1
+ ---
2
+ format_version: 1.4.0
3
+ default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
4
+
5
+ workflows:
6
+ # Main Workflows
7
+
8
+ develop:
9
+ before_run:
10
+ - _setup
11
+
12
+ after_run:
13
+ - _teardown
14
+
15
+ pr:
16
+ before_run:
17
+ - _setup
18
+
19
+ after_run:
20
+ - _teardown
21
+
22
+ # Composite Workflows
23
+
24
+ _setup:
25
+ before_run:
26
+ - _cache_pull
27
+ - _prepare
28
+ - _lint
29
+ - _test
30
+
31
+ _teardown:
32
+ after_run:
33
+ - _cache_push
34
+
35
+ # Private workflows
36
+
37
+ _cache_push:
38
+ steps:
39
+ - cache-push@0.9.4:
40
+ title: Push cache
41
+ run_if: .IsCI
42
+ inputs:
43
+ - cache_paths: |-
44
+ $HOME/.bundle
45
+
46
+ _cache_pull:
47
+ steps:
48
+ - cache-pull@0.9.2:
49
+ title: Pull cache
50
+
51
+ _lint:
52
+ steps:
53
+ - script@1.1.3:
54
+ title: Linting
55
+ inputs:
56
+ - content: bundle exec rake lint
57
+
58
+ _prepare:
59
+ steps:
60
+ - script@1.1.3:
61
+ title: Prepare (installing dependencies)
62
+ inputs:
63
+ - content: bundle install
64
+
65
+ _test:
66
+ steps:
67
+ - script@1.1.3:
68
+ title: Tests
69
+ inputs:
70
+ - content: bundle exec rake tests
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'samsao/gem_version.rb'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'danger-samsao'
9
+ spec.version = Samsao::VERSION
10
+ spec.authors = ['Samsao Development Inc.']
11
+ spec.email = ['mvachon@samsao.co']
12
+ spec.description = 'Danger plugin for Samsao PR guidelines.'
13
+ spec.summary = 'A longer description of danger-samsao.'
14
+ spec.homepage = 'https://github.com/samsao/danger-samsao'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_runtime_dependency 'danger-plugin-api', '~> 1.0'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.3'
25
+ spec.add_development_dependency 'guard', '~> 2.14'
26
+ spec.add_development_dependency 'guard-rubocop', '~> 1.2'
27
+ spec.add_development_dependency 'guard-rspec', '~> 4.7'
28
+ spec.add_development_dependency 'pry', '~> 0.11.0.pre2'
29
+ spec.add_development_dependency 'rake', '~> 10.0'
30
+ spec.add_development_dependency 'rubocop', '~> 0.41'
31
+ spec.add_development_dependency 'rspec', '~> 3.4'
32
+ spec.add_development_dependency 'yard', '~> 0.8'
33
+ end
@@ -0,0 +1 @@
1
+ require 'samsao/plugin'
@@ -0,0 +1 @@
1
+ require 'samsao/gem_version'
@@ -0,0 +1,53 @@
1
+ module Samsao
2
+ # Actions mixin module
3
+ module Actions
4
+ # Fails when git branching model is not respected for PR branch name.
5
+ #
6
+ # @return [void]
7
+ def fail_when_wrong_branching_model
8
+ message = 'Your branch should be prefixed with feature/, fix/, trivial/ or release/!'
9
+
10
+ fail message unless respects_branching_model
11
+ end
12
+
13
+ # Fails when a feature branch have than one commit
14
+ #
15
+ # @return [void]
16
+ def fail_when_non_single_commit_feature
17
+ commit_count = git.commits.size
18
+ message = "Your feature branch should have a single commit but found #{commit_count}, squash them together!"
19
+
20
+ fail message if feature_branch? && commit_count > 1
21
+ end
22
+
23
+ # Fails when CHANGELOG is not updated on feature or fix branches
24
+ #
25
+ # @return [void]
26
+ def fail_when_changelog_update_missing
27
+ return if trivial_change?
28
+
29
+ message = 'You did a fix or a feature without updating CHANGELOG file!'
30
+
31
+ fail message unless changelog_modified?
32
+ end
33
+
34
+ # Fails when one or more merge commit is detected.
35
+ #
36
+ # @return [void]
37
+ def fail_when_merge_commit_detected
38
+ message = 'Some merge commits were detected, you must use rebase to sync with base branch.'
39
+ merge_commit_detector = /^Merge branch '#{github.branch_for_base}'/
40
+
41
+ fail message if git.commits.any? { |commit| commit.message =~ merge_commit_detector }
42
+ end
43
+
44
+ # Fails when CHANGELOG is not updated on feature or fix branches
45
+ #
46
+ # @return [void]
47
+ def warn_when_work_in_progess_pr
48
+ message = 'Do not merge, PR is a work in progess [WIP]!'
49
+
50
+ warn message if github.pr_title.include?('[WIP]')
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ module Danger
2
+ # Samsao's config class
3
+ class SamsaoConfig
4
+ def initialize
5
+ @changelogs = ['CHANGELOG.md']
6
+ @sources = []
7
+ end
8
+
9
+ def changelogs(*entries)
10
+ return @changelogs if entries.nil? || entries.empty?
11
+
12
+ @changelogs = entries
13
+ end
14
+
15
+ def sources(*entries)
16
+ return @sources if entries.nil? || entries.empty?
17
+
18
+ @sources = entries
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module Samsao
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,79 @@
1
+ # rubocop:disable Style/PredicateName
2
+
3
+ module Samsao
4
+ # Helpers mixin module
5
+ module Helpers
6
+ # Check if any changelog were modified. When the helper receives nothing,
7
+ # changelogs defined by the config are used.
8
+ #
9
+ # @return [Boolean] True if any changelogs were modified in this commit
10
+ def changelog_modified?(*changelogs)
11
+ changelogs = config.changelogs if changelogs.nil? || changelogs.empty?
12
+
13
+ changelogs.any? { |changelog| git.modified_files.include?(changelog) }
14
+ end
15
+
16
+ # Return true if the current PR branch is a feature branch
17
+ #
18
+ # @return [void]
19
+ def feature_branch?
20
+ git_branch.start_with?('feature/')
21
+ end
22
+
23
+ # Return true if the current PR branch is a feature branch
24
+ #
25
+ # @return [void]
26
+ def fix_branch?
27
+ git_branch.start_with?('fix/')
28
+ end
29
+
30
+ # Return true if the current PR branch is a release branch
31
+ #
32
+ # @return [void]
33
+ def release_branch?
34
+ git_branch.start_with?('release/')
35
+ end
36
+
37
+ # Return true if the current PR branch is a trivial branch
38
+ #
39
+ # @return [void]
40
+ def trivial_branch?
41
+ git_branch.start_with?('trivial/')
42
+ end
43
+
44
+ # Return true if the current PR is a trivial change (branch is `trivial_branch?`)
45
+ # or PR title contains #trivial or #typo markers.
46
+ #
47
+ # @return [void]
48
+ def trivial_change?
49
+ trivial_branch? || ['#trivial', '#typo'].any? { |modifier| github.pr_title.include?(modifier) }
50
+ end
51
+
52
+ # Return true if any source files are in the git modified files list.
53
+ #
54
+ # @return [void]
55
+ def has_app_changes?(*sources)
56
+ sources = config.sources if sources.nil? || sources.empty?
57
+
58
+ sources.any? do |source|
59
+ pattern = Samsao::Regexp.from_matcher(source, when_string_pattern_prefix_with: '^')
60
+
61
+ modified_file?(pattern)
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def git_branch
68
+ github.branch_for_head
69
+ end
70
+
71
+ def modified_file?(matcher)
72
+ !git.modified_files.grep(matcher).empty?
73
+ end
74
+
75
+ def respects_branching_model
76
+ feature_branch? || fix_branch? || release_branch? || trivial_branch?
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,28 @@
1
+ require 'samsao/actions'
2
+ require 'samsao/config'
3
+ require 'samsao/helpers'
4
+ require 'samsao/regexp'
5
+
6
+ module Danger
7
+ # Samsao's Danger plugin.
8
+ #
9
+ # @example See README.md
10
+ #
11
+ # @see samsao/danger-samsao
12
+ # @tags internal, private, enterprise
13
+ #
14
+ class DangerSamsao < Plugin
15
+ include Samsao::Actions
16
+ include Samsao::Helpers
17
+
18
+ # Enable to configure the plugin configuration object.
19
+ #
20
+ # @return [Array<String>] (if no block given)
21
+ def config(&block)
22
+ @config = Danger::SamsaoConfig.new if @config.nil?
23
+ return @config unless block_given?
24
+
25
+ @config.instance_eval(&block)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ module Samsao
2
+ # Regexp utility methods
3
+ module Regexp
4
+ # Turns a source entry input into a Regexp. Uses rules from [from_matcher](#from_matcher)
5
+ # function and append a `^` to final regexp when the source if a pure String.
6
+ #
7
+ # @param matcher The source entry to transform into a Regexp
8
+ #
9
+ # @return [Regexp] The source entry as a regexp
10
+ def self.from_source(source)
11
+ from_matcher(source, when_string_pattern_prefix_with: '^')
12
+ end
13
+
14
+ # Turns an input into a Regexp. If the input is a String, it turns it
15
+ # into a Regexp and escape all special characters. If the input is already
16
+ # a Regexp, it returns it without modification.
17
+ #
18
+ # @param matcher The input matcher to transform into a Regexp
19
+ # @keyword when_string_pattern_prefix_with (Default: '') The prefix that should be added to
20
+ # final regexp when the input matcher is a string type
21
+ #
22
+ # @return [Regexp] The input as a regexp
23
+ def self.from_matcher(matcher, when_string_pattern_prefix_with: '')
24
+ return matcher if matcher.is_a?(::Regexp)
25
+
26
+ /#{when_string_pattern_prefix_with}#{::Regexp.quote(matcher)}/
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ require 'rspec/expectations'
2
+
3
+ RSpec::Matchers.define :have_error do |expected|
4
+ match do |actual|
5
+ actual.status_report[:errors].any? do |error|
6
+ expected.is_a?(Regexp) ? error =~ matcher : error.start_with?(expected)
7
+ end
8
+ end
9
+
10
+ failure_message do |actual|
11
+ message = "expected that #{Danger} would have error '#{expected}'"
12
+
13
+ errors = actual.status_report[:errors]
14
+ if errors.empty?
15
+ message += ' but there is none'
16
+ return message
17
+ end
18
+
19
+ actual.status_report[:errors].each do |error|
20
+ message += "\n * #{error}"
21
+ end
22
+
23
+ message
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ require 'rspec/expectations'
2
+
3
+ RSpec::Matchers.define :have_no_error do
4
+ match do |actual|
5
+ actual.status_report[:errors].empty?
6
+ end
7
+
8
+ failure_message do |actual|
9
+ message = "expected that #{Danger} would have no error but found '#{actual.status_report[:errors].size}'"
10
+ actual.status_report[:errors].each do |error|
11
+ message += "\n * #{error}"
12
+ end
13
+ end
14
+ end