danger-samsao 0.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.
@@ -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