safe_pusher 0.4.0 → 0.4.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c05663b02c0ccf6604a9e3054e8ea9456ffcb5694e25440db41edf4e087cb827
4
- data.tar.gz: edf3051adc55cd6492d35ae31f17c69f5444407e2f71a91a51239dad48f85f98
3
+ metadata.gz: ab33cda1facd75afc5f638e376520008a5ccd78ccfb12737d7518b4dbd65daf0
4
+ data.tar.gz: f654b9f9dbd1e5f1985f1c3d8e1f8ec40067f452bd88d9cc88fa2e3268fc7672
5
5
  SHA512:
6
- metadata.gz: d93caa5d43e32f373334afc458647266be8f4d505899d9f83c9ee23bfde83274c7f799b539630508818f11d708db84ffba46bd758989b4809c12031d79cd179c
7
- data.tar.gz: 88dff6746dbd6543e40152e856a5a0e6040bdf27eaaedaafe561805e435947e6d3aef472a93c64b9df7325c45c0dc85f9bd44b3d891e89c78d5a1f91279ce162
6
+ metadata.gz: c4f90a3d8ae6a56f485c041226b86127577465808d032fce4618cde458b9caf12e24341fb2b5010259841d89a6d8286493fe69afc9cd7fe5fa7cea9e9cdae61f
7
+ data.tar.gz: 7e1bfedcb25c89df9207752f1f9007d49facf1052d5b050ae5503dd924f838ad98ec27aeca46e8ec8eb88c63257f36e78a5582cb316329098e3833ca33e50948
@@ -2,6 +2,10 @@
2
2
 
3
3
  This project adheres to [Semantic Versioning](http://semver.org)
4
4
 
5
+ ## [0.4.1] - 2019-12-04
6
+ Improvement:
7
+ - Generate the folder of a spec, if not already existing
8
+
5
9
  ## [0.4.0] - 2019-11-29
6
10
  Features:
7
11
  - Add `add`, `commit` and `amend` commands to the cli
@@ -0,0 +1,33 @@
1
+ # Contributing
2
+
3
+ You can easily add a new client, or a new command.
4
+
5
+ ## To add a client
6
+ - create the client api under lib/safe_pusher/client/***.rb
7
+ - require it in lib/safe_pusher.rb
8
+ - write the specs for your client, then submit a PR
9
+
10
+ You will be able to specify in which command to use it, via the configuration !
11
+
12
+ ## To add a command
13
+ - configure your command and its client in config/commands.yml
14
+ - create your safepusher client api, as detailed above (if necessary)
15
+ - include your command's description in the help, in config/en.yml
16
+
17
+ # Guidelines
18
+
19
+ Bug reports and pull requests are welcome on GitHub at williampollet/safe_pusher. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
20
+
21
+ # Development
22
+ Setup development:
23
+ `$ bin/setup`
24
+
25
+ Open a console:
26
+ `$ bin/console`
27
+
28
+ Test the CLI:
29
+ `$ ruby -Ilib exe/safepush`
30
+
31
+ Launch specs and lint:
32
+
33
+ `$ rake`
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # SafePusher
6
6
 
7
- Run your favorite linters and specs on the files you touched, before pushing your branch.
7
+ Run your favorite linters and specs on the files you touched, before committing and pushing your branch.
8
8
 
9
9
  ## Installation
10
10
 
@@ -40,10 +40,18 @@ files_to_skip:
40
40
  base_branch: developement # default master
41
41
  app_base_directory: app
42
42
  repo_url: https://github.com/williampollet/safe_pusher
43
+ services:
44
+ test: rspec
45
+ lint: pronto
46
+ push: github
47
+ open: github
48
+ add: git
49
+ amend: git
50
+ commit: git
51
+ verbose: true
43
52
  ```
44
53
 
45
54
  ## Usage
46
-
47
55
  To see the commands available, type:
48
56
 
49
57
  $ safepush
@@ -64,8 +72,32 @@ or
64
72
 
65
73
  $ safepush t l p o
66
74
 
75
+ ### Available commands so far
76
+ - `test` (runs the tests only on the files you touched)
77
+ - `lint` (runs a linter only on the files you touched)
78
+ - `commit` (commit your changes)
79
+ - `add` (track your changes)
80
+ - `amend` (amend your tracked changes to your last commit)
81
+ - `push` (push and set upstream your local branch on github)
82
+ - `open` (open a pull request on github)
83
+
67
84
  ## Contributing
68
85
 
86
+ You can easily add a new client, or a new command.
87
+
88
+ ### To add a client
89
+ - create the client api under `lib/safe_pusher/client/***.rb`
90
+ - require it in `lib/safe_pusher.rb`
91
+ - write the specs for your client, then submit a PR
92
+ - You will be able to specify in which command to use it, via the configuration !
93
+
94
+ ### To add a command
95
+ - configure your command and its client in `config/commands.yml`
96
+ - create your safepusher client api, as detailed above (if necessary)
97
+ - include your command's description in the help, in `config/en.yml`
98
+
99
+ ### Guidelines
100
+
69
101
  Bug reports and pull requests are welcome on GitHub at https://github.com/williampollet/safe_pusher. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
70
102
 
71
103
  ## Development
@@ -0,0 +1,21 @@
1
+ test:
2
+ shortcut: t
3
+ default_client: rspec
4
+ lint:
5
+ shortcut: l
6
+ default_client: pronto
7
+ push:
8
+ shortcut: p
9
+ default_client: github
10
+ open:
11
+ shortcut: o
12
+ default_client: github
13
+ add:
14
+ shortcut: a
15
+ default_client: git
16
+ amend:
17
+ shortcut: m
18
+ default_client: git
19
+ commit:
20
+ shortcut: c
21
+ default_client: git
@@ -0,0 +1,37 @@
1
+ en:
2
+ help: |
3
+ Usage:
4
+ help (h) # show this usage message
5
+ --version # print SafePusher version
6
+ ##########################################################
7
+ # you can use any combination of theese commands
8
+ ##########################################################
9
+ test (t) # run the test suite
10
+ lint (l) # run the linters
11
+ amend (m) # amend your last commit
12
+ add (a) # add changes to be committed
13
+ commit (c) # commit your staged changes
14
+ push (p) # push on distant repository
15
+ open (o) # open a pull request on the distant repository
16
+ command:
17
+ add:
18
+ verbose: Testing new files...
19
+ commit:
20
+ verbose: Commiting last changes...
21
+ amend:
22
+ verbose: Amending last commit...
23
+ push:
24
+ verbose: Pushing to Github...
25
+ open:
26
+ verbose: Opening a pull request on Github...
27
+ lint:
28
+ verbose: Linting tracked changes...
29
+ test:
30
+ verbose: 'Testing new files...'
31
+ test_skipped: 'Alright, skipping the test for now!'
32
+ no_spec_found_for_file: 'No spec found for file %{file_matched}, would you like to add %{spec_path}? (Yn)'
33
+ spec_needs_to_be_written: 'A spec needs to be written!'
34
+ no_spec_analyzed: 'No spec found, going to the next step'
35
+ file_put_in_test_list: '%{file} modified, putting it in the list of specs to run'
36
+ spec_failing_or_missing: 'Oops, a spec seems to be red or empty, be sure to complete it before you push'
37
+ every_spec_operational: 'Every spec operational, going to the next step!'
@@ -1,12 +1,18 @@
1
1
  require 'safe_pusher/configuration'
2
2
  require 'thor'
3
3
  require 'colorize'
4
+ require 'English'
5
+ require 'i18n'
6
+ require 'yaml'
7
+ require 'fileutils'
4
8
  require 'safe_pusher/cli'
5
9
  require 'safe_pusher/version'
6
- require 'safe_pusher/git_runner'
7
- require 'safe_pusher/rspec_runner'
8
- require 'safe_pusher/pronto_runner'
9
- require 'safe_pusher/github_runner'
10
+ require 'safe_pusher/client/git'
11
+ require 'safe_pusher/client/rspec'
12
+ require 'safe_pusher/client/pronto'
13
+ require 'safe_pusher/client/github'
14
+
15
+ I18n.load_path << Dir[File.expand_path('config/locales/*.yml')]
10
16
 
11
17
  module SafePusher
12
18
  # Configuration setup
@@ -1,17 +1,5 @@
1
1
  module SafePusher
2
2
  class CLI
3
- SHORTCUTS = {
4
- 't' => 'test',
5
- 'l' => 'lint',
6
- 'p' => 'push',
7
- 'o' => 'open',
8
- 'm' => 'amend',
9
- 'a' => 'add',
10
- 'c' => 'commit',
11
- }.freeze
12
-
13
- private_constant :SHORTCUTS
14
-
15
3
  def initialize(arguments:)
16
4
  @arguments = arguments
17
5
  end
@@ -19,15 +7,9 @@ module SafePusher
19
7
  def start
20
8
  return version if arguments.first == '--version'
21
9
 
22
- unless arguments_valid?
23
- help
24
-
25
- return
26
- end
10
+ help if commands.include?(nil)
27
11
 
28
- arguments.each do |command|
29
- execute_command(command)
30
- end
12
+ commands.compact.each { |command| execute_command(command) }
31
13
  end
32
14
 
33
15
  private
@@ -35,111 +17,58 @@ module SafePusher
35
17
  attr_reader :arguments
36
18
 
37
19
  def execute_command(command)
38
- if SHORTCUTS[command]
39
- send(SHORTCUTS[command])
40
- else
41
- send(command)
42
- end
43
- end
44
-
45
- def test
46
- puts '##########################'.yellow
47
- puts '## Testing new files... ##'.yellow
48
- puts '##########################'.yellow
49
- results = SafePusher::RspecRunner.new.call
50
-
51
- exit results unless results == 0
52
- end
53
-
54
- def lint
55
- puts '#######################'.yellow
56
- puts '## Running linter... ##'.yellow
57
- puts '#######################'.yellow
20
+ explain(command) if verbose
58
21
 
59
- results = SafePusher::ProntoRunner.new.call
22
+ results = SafePusher::Client
23
+ .const_get(services[command].capitalize)
24
+ .new
25
+ .public_send(command)
60
26
 
61
27
  exit results unless results == 0
62
28
  end
63
29
 
64
- def push
65
- puts '##########################'.yellow
66
- puts '## Pushing to Github... ##'.yellow
67
- puts '##########################'.yellow
68
-
69
- results = SafePusher::GithubRunner.new.push
30
+ def commands
31
+ @commands ||= arguments.map do |arg|
32
+ next unless arg =~ valid_commands_regexp
70
33
 
71
- exit results unless results == 0
34
+ shortcut_to_command[arg] || arg
35
+ end
72
36
  end
73
37
 
74
- def amend
75
- puts '###################################'.yellow
76
- puts '## Amending your last commit... ###'.yellow
77
- puts '###################################'.yellow
78
-
79
- results = SafePusher::GitRunner.new.amend
80
-
81
- exit results unless results == 0
38
+ def version
39
+ puts SafePusher::VERSION
82
40
  end
83
41
 
84
- def add
85
- puts '######################'.yellow
86
- puts '## Adding files... ###'.yellow
87
- puts '######################'.yellow
88
-
89
- results = SafePusher::GitRunner.new.add
90
-
91
- exit results unless results == 0
42
+ def explain(command)
43
+ puts I18n.t("command.#{command}.verbose").yellow
92
44
  end
93
45
 
94
- def commit
95
- puts '################################'.yellow
96
- puts '## Commiting last changes... ###'.yellow
97
- puts '################################'.yellow
98
-
99
- results = SafePusher::GitRunner.new.commit
100
-
101
- exit results unless results == 0
46
+ def help
47
+ puts I18n.t('help')
102
48
  end
103
49
 
104
- def open
105
- puts '#########################################'.yellow
106
- puts '## Opening a pull request on Github... ##'.yellow
107
- puts '#########################################'.yellow
108
-
109
- results = SafePusher::GithubRunner.new.open
110
-
111
- exit results unless results == 0
50
+ def valid_commands_regexp
51
+ @valid_commands_regexp ||= /^(?!\s*$)(?:#{available_commands})$/
112
52
  end
113
53
 
114
- def arguments_valid?
115
- arguments.join(' ') =~ valid_commands_regexp
54
+ def available_commands
55
+ @available_commands ||= (
56
+ shortcut_to_command.keys + shortcut_to_command.values
57
+ ).join('|')
116
58
  end
117
59
 
118
- def valid_commands_regexp
119
- valid_commands = "#{SHORTCUTS.keys.join('|')}|"\
120
- "#{SHORTCUTS.values.join('|')}"
121
-
122
- /^(?!\s*$)(?:#{valid_commands}| )+$/
60
+ def verbose
61
+ @verbose ||= SafePusher.configuration.verbose
123
62
  end
124
63
 
125
- def help
126
- puts "Usage:\n"\
127
- " help (h) # show this usage message\n"\
128
- " --version # print SafePusher version\n"\
129
- " ##########################################################\n"\
130
- " # you can use any combination of theese commands \n"\
131
- " ##########################################################\n"\
132
- " test (t) # run the test suite\n"\
133
- " lint (l) # run the linters\n"\
134
- " amend (m) # amend your last commit \n"\
135
- " add (a) # add changes to be committed \n"\
136
- " commit (c) # commit your staged changes \n"\
137
- " push (p) # push on distant repository\n"\
138
- ' open (o) # open a pull request on the distant repository'
64
+ def services
65
+ @services ||= SafePusher.configuration.services
139
66
  end
140
67
 
141
- def version
142
- puts SafePusher::VERSION
68
+ def shortcut_to_command
69
+ @shortcut_to_command ||= YAML
70
+ .load_file('config/commands.yml')
71
+ .reduce({}) { |o, (k, v)| o.update(v['shortcut'] => k) }
143
72
  end
144
73
  end
145
74
  end
@@ -0,0 +1,27 @@
1
+ module SafePusher
2
+ module Client
3
+ class Git
4
+ def amend
5
+ system('git commit --amend')
6
+
7
+ $CHILD_STATUS.exitstatus
8
+ end
9
+
10
+ def add
11
+ system('git add --interactive')
12
+
13
+ $CHILD_STATUS.exitstatus
14
+ end
15
+
16
+ def commit
17
+ puts 'Enter a message for your commit:'
18
+
19
+ result = STDIN.gets.chomp
20
+
21
+ system("git commit -m '#{result}'")
22
+
23
+ $CHILD_STATUS.exitstatus
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ module SafePusher
2
+ module Client
3
+ class Github
4
+ def push
5
+ system('git push origin')
6
+
7
+ exit_status = $CHILD_STATUS.exitstatus
8
+
9
+ if exit_status == 128
10
+ puts 'Syncing with github...'.green
11
+
12
+ push_and_set_upstream
13
+
14
+ exit_status = $CHILD_STATUS.exitstatus
15
+ end
16
+
17
+ exit_status
18
+ end
19
+
20
+ def open
21
+ system(
22
+ "open '#{SafePusher.configuration.repo_url}/pull/new/#{branch}'",
23
+ )
24
+ end
25
+
26
+ private
27
+
28
+ def push_and_set_upstream
29
+ system("git push --set-upstream origin #{branch}")
30
+ end
31
+
32
+ def branch
33
+ `git rev-parse --symbolic-full-name --abbrev-ref HEAD`.delete("\n")
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ module SafePusher
2
+ module Client
3
+ class Pronto
4
+ def lint
5
+ run_pronto
6
+ exit_status = $CHILD_STATUS.exitstatus
7
+
8
+ if exit_status != 0
9
+ warn 'Pronto found somme errors… ' \
10
+ 'Fix them before pushing to GitHub!'.red
11
+ else
12
+ puts 'No errors found by pronto, go for next step!'.green
13
+ end
14
+
15
+ exit_status
16
+ end
17
+
18
+ private
19
+
20
+ def run_pronto
21
+ system("bin/pronto run --exit-code -c #{base_branch}")
22
+ end
23
+
24
+ def base_branch
25
+ SafePusher.configuration.base_branch
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,136 @@
1
+ module SafePusher
2
+ module Client
3
+ class Rspec
4
+ def initialize
5
+ @specs_to_execute = []
6
+ end
7
+
8
+ def test
9
+ return 1 if list_files_to_execute == 1
10
+
11
+ run_specs
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :specs_to_execute
17
+
18
+ def list_files_to_execute
19
+ modified_files.map do |f|
20
+ return 1 if analyze_file(f) == 1
21
+ end.compact
22
+ end
23
+
24
+ def modified_files
25
+ diff = 'git diff --diff-filter=A --diff-filter=M --name-only'
26
+
27
+ `#{diff} $(git merge-base #{branch} #{base_branch}) #{branch}`
28
+ .split("\n")
29
+ .uniq
30
+ end
31
+
32
+ def analyze_file(file)
33
+ if file.match(app_base_directory) &&
34
+ !file.match(files_to_skip)
35
+ search_or_create_spec(file)
36
+ elsif file.match(/spec/) &&
37
+ !specs_to_execute.include?(file) &&
38
+ !file.match(files_to_skip)
39
+ index_file(file)
40
+ end
41
+ end
42
+
43
+ def search_or_create_spec(file)
44
+ spec_path = file.gsub(
45
+ "#{SafePusher.configuration.app_base_directory}/",
46
+ 'spec/',
47
+ ).gsub('.rb', '_spec.rb')
48
+
49
+ return create_new_spec(spec_path, file) unless File.exist?(spec_path)
50
+
51
+ puts spec_path
52
+
53
+ specs_to_execute << spec_path
54
+ end
55
+
56
+ def index_file(file)
57
+ puts I18n.t('command.test.file_put_in_test_list', file: file)
58
+ specs_to_execute << file
59
+ end
60
+
61
+ def files_to_skip
62
+ Regexp.new(
63
+ SafePusher.configuration.files_to_skip.join('|').gsub('/', '\/'),
64
+ )
65
+ end
66
+
67
+ def run_specs
68
+ if specs_to_execute.empty?
69
+ puts I18n.t('command.test.no_spec_analyzed').green
70
+ return 0
71
+ end
72
+
73
+ system("bin/rspec #{specs_to_execute.join(' ')}")
74
+
75
+ exit_status = $CHILD_STATUS.exitstatus
76
+
77
+ if exit_status != 0
78
+ puts spec_failing_or_missing
79
+ else
80
+ puts every_spec_operational
81
+ end
82
+
83
+ exit_status
84
+ end
85
+
86
+ def create_new_spec(spec_path, file_matched)
87
+ puts I18n.t(
88
+ 'command.test.no_spec_found_for_file',
89
+ file_matched: file_matched,
90
+ spec_path: spec_path,
91
+ )
92
+
93
+ result = STDIN.gets.chomp
94
+
95
+ if result.casecmp('n') == 0
96
+ puts I18n.t('command.test.test_skipped')
97
+
98
+ 0
99
+ else
100
+ create_new_file(spec_path)
101
+
102
+ warn I18n.t('command.test.spec_needs_to_be_written').red
103
+
104
+ 1
105
+ end
106
+ end
107
+
108
+ def branch
109
+ `git rev-parse --abbrev-ref HEAD`.delete("\n")
110
+ end
111
+
112
+ def create_new_file(path)
113
+ parent_directory = File.dirname(path)
114
+
115
+ FileUtils.mkdir_p(parent_directory) unless File.exist?(parent_directory)
116
+ FileUtils.touch(path)
117
+ end
118
+
119
+ def app_base_directory
120
+ %r{#{SafePusher.configuration.app_base_directory}\/.*\.rb$}
121
+ end
122
+
123
+ def base_branch
124
+ SafePusher.configuration.base_branch
125
+ end
126
+
127
+ def spec_failing_or_missing
128
+ I18n.t('command.test.spec_failing_or_missing').red
129
+ end
130
+
131
+ def every_spec_operational
132
+ I18n.t('command.test.every_spec_operational').green
133
+ end
134
+ end
135
+ end
136
+ end
@@ -1,25 +1,34 @@
1
- require 'yaml'
2
- # Configuration variables and defaults
3
1
  module SafePusher
4
2
  class Configuration
5
- # The configuration singleton
6
3
  attr_accessor :files_to_skip,
7
4
  :app_base_directory,
8
5
  :repo_url,
9
- :base_branch
6
+ :base_branch,
7
+ :verbose,
8
+ :services
10
9
 
11
10
  def initialize
12
- application_config =
13
- if File.exist?('safe_pusher.yml')
14
- YAML.load_file('safe_pusher.yml')
15
- else
16
- {}
17
- end
18
-
11
+ @verbose = application_config['verbose'] || true
19
12
  @base_branch = application_config['base_branch'] || 'master'
20
13
  @files_to_skip = application_config['files_to_skip'] || []
21
14
  @app_base_directory = application_config['app_base_directory']
22
15
  @repo_url = application_config['repo_url']
16
+ @services = load_services
17
+ end
18
+
19
+ private
20
+
21
+ def load_services
22
+ YAML
23
+ .load_file('config/commands.yml')
24
+ .reduce({}) { |o, (k, v)| o.update(k => v['default_client']) }
25
+ .merge(application_config['services'] || {})
26
+ end
27
+
28
+ def application_config
29
+ return YAML.load_file('safe_pusher.yml') if File.exist?('safe_pusher.yml')
30
+
31
+ {}
23
32
  end
24
33
  end
25
34
  end
@@ -1,3 +1,3 @@
1
1
  module SafePusher
2
- VERSION = '0.4.0'.freeze
2
+ VERSION = '0.4.1'.freeze
3
3
  end
@@ -37,6 +37,7 @@ Gem::Specification.new do |spec|
37
37
  spec.require_paths = ['lib']
38
38
 
39
39
  spec.add_dependency 'colorize', '~> 0.8.1'
40
+ spec.add_dependency 'i18n', '~> 1.6.0'
40
41
 
41
42
  spec.add_development_dependency 'bundler', '>= 1.16'
42
43
  spec.add_development_dependency 'fashion_police', '~> 1.2'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: safe_pusher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Pollet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-29 00:00:00.000000000 Z
11
+ date: 2019-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.8.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: i18n
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.6.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.6.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -181,20 +195,23 @@ files:
181
195
  - ".travis.yml"
182
196
  - CHANGELOG.md
183
197
  - CODE_OF_CONDUCT.md
198
+ - CONTRIBUTING.md
184
199
  - Gemfile
185
200
  - LICENSE.txt
186
201
  - README.md
187
202
  - Rakefile
188
203
  - bin/console
189
204
  - bin/setup
205
+ - config/commands.yml
206
+ - config/locales/en.yml
190
207
  - exe/safepush
191
208
  - lib/safe_pusher.rb
192
209
  - lib/safe_pusher/cli.rb
210
+ - lib/safe_pusher/client/git.rb
211
+ - lib/safe_pusher/client/github.rb
212
+ - lib/safe_pusher/client/pronto.rb
213
+ - lib/safe_pusher/client/rspec.rb
193
214
  - lib/safe_pusher/configuration.rb
194
- - lib/safe_pusher/git_runner.rb
195
- - lib/safe_pusher/github_runner.rb
196
- - lib/safe_pusher/pronto_runner.rb
197
- - lib/safe_pusher/rspec_runner.rb
198
215
  - lib/safe_pusher/version.rb
199
216
  - safe_pusher.gemspec
200
217
  homepage: https://github.com/williampollet/safe_pusher
@@ -217,7 +234,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
217
234
  - !ruby/object:Gem::Version
218
235
  version: '0'
219
236
  requirements: []
220
- rubygems_version: 3.0.4
237
+ rubygems_version: 3.0.6
221
238
  signing_key:
222
239
  specification_version: 4
223
240
  summary: a small CLI that lints your code and run your tests before you push
@@ -1,28 +0,0 @@
1
- require 'colorize'
2
- require 'English'
3
-
4
- module SafePusher
5
- class GitRunner
6
- def amend
7
- system('git commit --amend')
8
-
9
- $CHILD_STATUS.exitstatus
10
- end
11
-
12
- def add
13
- system('git add --interactive')
14
-
15
- $CHILD_STATUS.exitstatus
16
- end
17
-
18
- def commit
19
- puts 'Enter a message for your commit:'
20
-
21
- result = STDIN.gets.chomp
22
-
23
- system("git commit -m '#{result}'")
24
-
25
- $CHILD_STATUS.exitstatus
26
- end
27
- end
28
- end
@@ -1,38 +0,0 @@
1
- require 'colorize'
2
- require 'English'
3
-
4
- module SafePusher
5
- class GithubRunner
6
- def push
7
- system('git push origin')
8
-
9
- exit_status = $CHILD_STATUS.exitstatus
10
-
11
- if exit_status == 128
12
- puts 'Syncing with github...'.green
13
-
14
- push_and_set_upstream
15
-
16
- exit_status = $CHILD_STATUS.exitstatus
17
- end
18
-
19
- exit_status
20
- end
21
-
22
- def open
23
- system(
24
- "open '#{SafePusher.configuration.repo_url}/pull/new/#{branch}'",
25
- )
26
- end
27
-
28
- private
29
-
30
- def push_and_set_upstream
31
- system("git push --set-upstream origin #{branch}")
32
- end
33
-
34
- def branch
35
- `git rev-parse --symbolic-full-name --abbrev-ref HEAD`.delete("\n")
36
- end
37
- end
38
- end
@@ -1,30 +0,0 @@
1
- require 'colorize'
2
- require 'English'
3
-
4
- module SafePusher
5
- class ProntoRunner
6
- def call
7
- run_pronto
8
- exit_status = $CHILD_STATUS.exitstatus
9
-
10
- if exit_status != 0
11
- warn 'Pronto found somme errors… ' \
12
- 'Fix them before pushing to GitHub!'.red
13
- else
14
- puts 'No errors found by pronto, go for next step!'.green
15
- end
16
-
17
- exit_status
18
- end
19
-
20
- private
21
-
22
- def run_pronto
23
- system("bin/pronto run --exit-code -c #{base_branch}")
24
- end
25
-
26
- def base_branch
27
- SafePusher.configuration.base_branch
28
- end
29
- end
30
- end
@@ -1,117 +0,0 @@
1
- require 'colorize'
2
- require 'English'
3
-
4
- module SafePusher
5
- class RspecRunner
6
- def initialize
7
- @specs_to_execute = []
8
- end
9
-
10
- def call
11
- return 1 if list_files_to_execute == 1
12
-
13
- run_specs
14
- end
15
-
16
- private
17
-
18
- attr_reader :specs_to_execute
19
-
20
- def list_files_to_execute
21
- modified_files.map do |f|
22
- return 1 if analyze_file(f) == 1
23
- end.compact
24
- end
25
-
26
- def modified_files
27
- diff = 'git diff --diff-filter=A --diff-filter=M --name-only'
28
-
29
- `#{diff} $(git merge-base #{branch} #{base_branch}) #{branch}`
30
- .split("\n")
31
- .uniq
32
- end
33
-
34
- def analyze_file(file)
35
- if file.match(app_base_directory) &&
36
- !file.match(files_to_skip)
37
- search_or_create_spec(file)
38
- elsif file.match(/spec/) &&
39
- !specs_to_execute.include?(file) &&
40
- !file.match(files_to_skip)
41
- index_file(file)
42
- end
43
- end
44
-
45
- def search_or_create_spec(file)
46
- spec_path = file.gsub(
47
- "#{SafePusher.configuration.app_base_directory}/",
48
- 'spec/',
49
- ).gsub('.rb', '_spec.rb')
50
-
51
- return create_new_spec(spec_path, file) unless File.exist?(spec_path)
52
-
53
- puts spec_path
54
-
55
- specs_to_execute << spec_path
56
- end
57
-
58
- def index_file(file)
59
- puts "#{file} modified, putting it in the list of specs to run"
60
- specs_to_execute << file
61
- end
62
-
63
- def files_to_skip
64
- Regexp.new(
65
- SafePusher.configuration.files_to_skip.join('|').gsub('/', '\/'),
66
- )
67
- end
68
-
69
- def run_specs
70
- if specs_to_execute.empty?
71
- puts 'no spec analyzed, passing to the next step'.green
72
- return 0
73
- end
74
-
75
- system("bin/rspec #{specs_to_execute.join(' ')}")
76
-
77
- exit_status = $CHILD_STATUS.exitstatus
78
-
79
- if exit_status != 0
80
- puts 'Oops, a spec seems to be red or empty, '\
81
- 'be sure to complete it before you push'.red
82
- else
83
- puts 'Every spec operational, '\
84
- 'passing to the next step!'.green
85
- end
86
-
87
- exit_status
88
- end
89
-
90
- def create_new_spec(spec_path, file_matched)
91
- puts "no spec found for file #{file_matched},"\
92
- " would you like to add #{spec_path}? (Yn)"
93
- result = STDIN.gets.chomp
94
-
95
- if result.casecmp('n') == 0
96
- puts 'Alright, skipping the test for now!'
97
- return 0
98
- else
99
- File.open(spec_path, 'w') {}
100
- warn 'A spec needs to be written!'.red
101
- return 1
102
- end
103
- end
104
-
105
- def branch
106
- `git rev-parse --abbrev-ref HEAD`.delete("\n")
107
- end
108
-
109
- def app_base_directory
110
- %r{#{SafePusher.configuration.app_base_directory}\/.*\.rb$}
111
- end
112
-
113
- def base_branch
114
- SafePusher.configuration.base_branch
115
- end
116
- end
117
- end