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 +4 -4
- data/CHANGELOG.md +4 -0
- data/CONTRIBUTING.md +33 -0
- data/README.md +34 -2
- data/config/commands.yml +21 -0
- data/config/locales/en.yml +37 -0
- data/lib/safe_pusher.rb +10 -4
- data/lib/safe_pusher/cli.rb +32 -103
- data/lib/safe_pusher/client/git.rb +27 -0
- data/lib/safe_pusher/client/github.rb +37 -0
- data/lib/safe_pusher/client/pronto.rb +29 -0
- data/lib/safe_pusher/client/rspec.rb +136 -0
- data/lib/safe_pusher/configuration.rb +20 -11
- data/lib/safe_pusher/version.rb +1 -1
- data/safe_pusher.gemspec +1 -0
- metadata +24 -7
- data/lib/safe_pusher/git_runner.rb +0 -28
- data/lib/safe_pusher/github_runner.rb +0 -38
- data/lib/safe_pusher/pronto_runner.rb +0 -30
- data/lib/safe_pusher/rspec_runner.rb +0 -117
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab33cda1facd75afc5f638e376520008a5ccd78ccfb12737d7518b4dbd65daf0
|
4
|
+
data.tar.gz: f654b9f9dbd1e5f1985f1c3d8e1f8ec40067f452bd88d9cc88fa2e3268fc7672
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4f90a3d8ae6a56f485c041226b86127577465808d032fce4618cde458b9caf12e24341fb2b5010259841d89a6d8286493fe69afc9cd7fe5fa7cea9e9cdae61f
|
7
|
+
data.tar.gz: 7e1bfedcb25c89df9207752f1f9007d49facf1052d5b050ae5503dd924f838ad98ec27aeca46e8ec8eb88c63257f36e78a5582cb316329098e3833ca33e50948
|
data/CHANGELOG.md
CHANGED
@@ -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
|
data/CONTRIBUTING.md
ADDED
@@ -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
|
data/config/commands.yml
ADDED
@@ -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!'
|
data/lib/safe_pusher.rb
CHANGED
@@ -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/
|
7
|
-
require 'safe_pusher/
|
8
|
-
require 'safe_pusher/
|
9
|
-
require 'safe_pusher/
|
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
|
data/lib/safe_pusher/cli.rb
CHANGED
@@ -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
|
-
|
23
|
-
help
|
24
|
-
|
25
|
-
return
|
26
|
-
end
|
10
|
+
help if commands.include?(nil)
|
27
11
|
|
28
|
-
|
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
|
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::
|
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
|
65
|
-
|
66
|
-
|
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
|
-
|
34
|
+
shortcut_to_command[arg] || arg
|
35
|
+
end
|
72
36
|
end
|
73
37
|
|
74
|
-
def
|
75
|
-
puts
|
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
|
85
|
-
puts
|
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
|
95
|
-
puts '
|
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
|
105
|
-
|
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
|
115
|
-
|
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
|
119
|
-
|
120
|
-
"#{SHORTCUTS.values.join('|')}"
|
121
|
-
|
122
|
-
/^(?!\s*$)(?:#{valid_commands}| )+$/
|
60
|
+
def verbose
|
61
|
+
@verbose ||= SafePusher.configuration.verbose
|
123
62
|
end
|
124
63
|
|
125
|
-
def
|
126
|
-
|
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
|
142
|
-
|
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
|
data/lib/safe_pusher/version.rb
CHANGED
data/safe_pusher.gemspec
CHANGED
@@ -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.
|
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
|
+
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.
|
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
|