netsoft-danger 0.3.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.
- checksums.yaml +7 -0
- data/.circleci/config.yml +130 -0
- data/.gitignore +5 -0
- data/Dangerfile +105 -0
- data/Gemfile +3 -0
- data/README.md +4 -0
- data/Rakefile +5 -0
- data/bin/netsoft-circle +86 -0
- data/bin/tag_check.sh +17 -0
- data/dangerfiles/issue.js +3 -0
- data/dangerfiles/pr.js +49 -0
- data/lib/netsoft-danger/cops/netsoft/auth_http_positional_arguments.rb +142 -0
- data/lib/netsoft-danger/cops.rb +1 -0
- data/lib/netsoft-danger/version.rb +3 -0
- data/lib/netsoft-danger.rb +3 -0
- data/netsoft-danger.gemspec +25 -0
- data/package.json +5 -0
- data/rubocop/config-2019-08-12.yml +46 -0
- data/settings-peril.json +10 -0
- data/yarn.lock +677 -0
- metadata +160 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ed4179318732a96ccb2143ed81c4883f5b3d09b510430dc90444e30d5884bb6d
|
4
|
+
data.tar.gz: 960344a9abbf87cf2822b69df41732f1e4f656c496e3e2b7397c82b6995bcf7d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d55935c5a579644f9fc95cb649a51ab00d200fecea37ef19cb7e30ca88cb672bb90e37bfa74f256507cb4e07fd6e3af9260851d9d95e6ca012bc108968f16ff2
|
7
|
+
data.tar.gz: 8ec910b5a74b6b419cfb1bbac8ab87d0eab232c97f3e0550257a0957e01282dff2e2f42c9cb20f9385586f7a5dffb19c88480b6656f58e12ce72eea04674e99d
|
@@ -0,0 +1,130 @@
|
|
1
|
+
version: 2
|
2
|
+
|
3
|
+
defaults: &defaults
|
4
|
+
docker: &ruby_image
|
5
|
+
- &ruby_image
|
6
|
+
image: circleci/ruby:2.4.4-stretch
|
7
|
+
environment:
|
8
|
+
RUBYOPT: '-KU -E utf-8:utf-8'
|
9
|
+
BUNDLE_PATH: vendor/bundle
|
10
|
+
BUNDLE_VERSION: 1.15.2
|
11
|
+
BUNDLE_JOBS: 4
|
12
|
+
BUNDLE_RETRY: 3
|
13
|
+
|
14
|
+
filters:
|
15
|
+
test: &filter_test
|
16
|
+
filters:
|
17
|
+
tags:
|
18
|
+
ignore: /^v.*/
|
19
|
+
beta: &filter_beta
|
20
|
+
filters:
|
21
|
+
branches:
|
22
|
+
ignore: /.*/
|
23
|
+
tags:
|
24
|
+
only: /^v[0-9]+(\.[0-9]+)+(\.[a-z].+).*/
|
25
|
+
release: &filter_release
|
26
|
+
filters:
|
27
|
+
branches:
|
28
|
+
ignore: /.*/
|
29
|
+
tags:
|
30
|
+
only: /^v[0-9]+(\.[0-9]+)+/
|
31
|
+
|
32
|
+
workflows:
|
33
|
+
version: 2
|
34
|
+
build_test:
|
35
|
+
jobs:
|
36
|
+
- "Checkout":
|
37
|
+
<<: *filter_test
|
38
|
+
context: org-global
|
39
|
+
- "Build":
|
40
|
+
<<: *filter_test
|
41
|
+
context: org-global
|
42
|
+
requires:
|
43
|
+
- "Checkout"
|
44
|
+
build_test_beta:
|
45
|
+
jobs:
|
46
|
+
- "Checkout":
|
47
|
+
<<: *filter_beta
|
48
|
+
context: org-global
|
49
|
+
- "Build":
|
50
|
+
<<: *filter_beta
|
51
|
+
context: org-global
|
52
|
+
requires:
|
53
|
+
- "Checkout"
|
54
|
+
- "Publish":
|
55
|
+
<<: *filter_beta
|
56
|
+
context: org-global
|
57
|
+
requires:
|
58
|
+
- "Build"
|
59
|
+
build_test_release:
|
60
|
+
jobs:
|
61
|
+
- "Checkout":
|
62
|
+
<<: *filter_release
|
63
|
+
context: org-global
|
64
|
+
- "Build":
|
65
|
+
<<: *filter_release
|
66
|
+
context: org-global
|
67
|
+
requires:
|
68
|
+
- "Checkout"
|
69
|
+
- "Publish":
|
70
|
+
<<: *filter_release
|
71
|
+
context: org-global
|
72
|
+
requires:
|
73
|
+
- "Build"
|
74
|
+
|
75
|
+
jobs:
|
76
|
+
"Checkout":
|
77
|
+
<<: *defaults
|
78
|
+
steps:
|
79
|
+
- attach_workspace:
|
80
|
+
at: .
|
81
|
+
- checkout
|
82
|
+
|
83
|
+
- restore_cache:
|
84
|
+
keys:
|
85
|
+
- netsoft-danger-bundle-v2-{{ checksum "Gemfile" }}-{{ checksum "netsoft-danger.gemspec" }}
|
86
|
+
- run:
|
87
|
+
name: Install bundler
|
88
|
+
command: gem install bundler --version=$BUNDLE_VERSION
|
89
|
+
- run:
|
90
|
+
name: Bundle Install
|
91
|
+
command: |-
|
92
|
+
bundle _${BUNDLE_VERSION}_ check || bundle _${BUNDLE_VERSION}_ install --retry=$BUNDLE_RETRY
|
93
|
+
- save_cache:
|
94
|
+
key: netsoft-danger-bundle-v2-{{ checksum "Gemfile" }}-{{ checksum "netsoft-danger.gemspec" }}
|
95
|
+
paths:
|
96
|
+
- vendor/bundle
|
97
|
+
- Gemfile.lock
|
98
|
+
|
99
|
+
- persist_to_workspace:
|
100
|
+
root: .
|
101
|
+
paths: .
|
102
|
+
"Build":
|
103
|
+
<<: *defaults
|
104
|
+
steps:
|
105
|
+
- attach_workspace:
|
106
|
+
at: .
|
107
|
+
- run:
|
108
|
+
name: Install bundler
|
109
|
+
command: gem install bundler --version=$BUNDLE_VERSION
|
110
|
+
- run:
|
111
|
+
name: Build gem
|
112
|
+
command: |-
|
113
|
+
gem build *.gemspec
|
114
|
+
- run:
|
115
|
+
name: Run Danger
|
116
|
+
command: |-
|
117
|
+
bundle exec danger
|
118
|
+
"Publish":
|
119
|
+
<<: *defaults
|
120
|
+
steps:
|
121
|
+
- attach_workspace:
|
122
|
+
at: .
|
123
|
+
- run:
|
124
|
+
name: Deploy to gem server
|
125
|
+
command: |-
|
126
|
+
./bin/tag_check.sh
|
127
|
+
rm -rf pkg
|
128
|
+
gem install geminabox
|
129
|
+
rake build
|
130
|
+
gem inabox -g ${HUBSTAFF_GEM_SERVER} pkg/*
|
data/.gitignore
ADDED
data/Dangerfile
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# Don't let testing shortcuts get into master by accident
|
2
|
+
if Dir.exists?('spec')
|
3
|
+
fail("fdescribe left in tests") if `grep -r -e '\\bfdescribe\\b' spec/ |grep -v 'danger ok' `.length > 1
|
4
|
+
fail("fcontext left in tests") if `grep -r -e '\\bfcontext\\b' spec/ |grep -v 'danger ok' `.length > 1
|
5
|
+
fail("fit left in tests") if `grep -r -e '\\bfit\\b' spec/ | grep -v 'danger ok' `.length > 1
|
6
|
+
fail("ap left in tests") if `grep -r -e '\\bap\\b' spec/ | grep -v 'danger ok' `.length > 1
|
7
|
+
fail("puts left in tests") if `grep -r -e '\\bputs\\b' spec/ | grep -v 'danger ok' `.length > 1
|
8
|
+
end
|
9
|
+
|
10
|
+
if File.exists?('Gemfile')
|
11
|
+
if `grep -r -e "^ *gem 'hubstaff_[a-z]\\+" Gemfile | grep -e ",.\\+[a-zA-Z]" `.length > 1
|
12
|
+
fail("[gemfile] Beta hubstaff_* gems are not allowed in master/production")
|
13
|
+
end
|
14
|
+
if `grep -r -e "^ *gem 'hubstaff_[a-z]\\+" Gemfile | grep -e ",.\\+'[~>=]\\+.\\+[a-zA-Z]" `.length > 1
|
15
|
+
fail("[gemfile] Beta hubstaff_* gems should be the exact version")
|
16
|
+
end
|
17
|
+
if `grep -r -e "^ *gem 'hubstaff_[a-z]\\+" Gemfile | grep -e ",.\\+[' ][0-9.]\\+'" | grep -v '~>' `.length > 1
|
18
|
+
fail("[gemfile] Release hubstaff_* gems should be using a ~> version")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
git.commits.each do |c|
|
23
|
+
short = " ( #{c.sha[0..7]} )"
|
24
|
+
has_migrations = c.diff_parent.any? {|f| f.path =~ /db\/migrate\// }
|
25
|
+
has_schema_changes = c.diff_parent.any? {|f| f.path =~ /db\/schema\.rb/ }
|
26
|
+
has_migration_msg = c.message =~ /^\[migration\]/
|
27
|
+
no_schema_ok = ENV['DANGER_NO_SCHEMA_OK'] || false
|
28
|
+
if has_migrations || has_schema_changes
|
29
|
+
unless has_migration_msg
|
30
|
+
fail '[migration] Schema migration commits need to be prefixed with [migration]' + short
|
31
|
+
end
|
32
|
+
if has_migrations && !has_schema_changes && !no_schema_ok
|
33
|
+
fail '[migration] Please checkin your schema.rb changes with your migration' + short
|
34
|
+
end
|
35
|
+
if !has_migrations && has_schema_changes
|
36
|
+
warn '[migration] Please checkin your migrations with your schema.rb changes' + short
|
37
|
+
end
|
38
|
+
if c.diff_parent.any? {|f| !( f.path =~ /db\/migrate\// or f.path =~ /db\/schema.rb/ ) }
|
39
|
+
fail '[migration] Migration commit contains non-migration changes' + short
|
40
|
+
end
|
41
|
+
elsif has_migration_msg
|
42
|
+
fail '[migration] Migration commit with no migrations!' + short
|
43
|
+
end
|
44
|
+
|
45
|
+
has_hubstaff_icon_changes = c.diff_parent.any? {|f| f.path =~ /hubstaff(icons|font)/ || f.path =~ /fontcustom-manifest/ }
|
46
|
+
if has_hubstaff_icon_changes
|
47
|
+
if c.diff_parent.any? {|f| !( f.path =~ /hubstaff-(icons|font)/ || f.path =~ /fontcustom-manifest/ ) }
|
48
|
+
fail '[hubstaff-icons] Put hubstaff-icon changes into their own commit' + short
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
has_gemfile_changes = c.diff_parent.any? {|f| f.path =~ /Gemfile/ || f.path =~ /gemspec/ }
|
53
|
+
has_gemfile_msg = c.message =~ /^\[gemfile\]/
|
54
|
+
if has_gemfile_changes
|
55
|
+
unless has_gemfile_msg
|
56
|
+
fail '[gemfile] Gemfile commits need to be prefixed with [gemfile] ' + short
|
57
|
+
end
|
58
|
+
if c.diff_parent.any? {|f| !( f.path =~ /Gemfile/ || f.path =~ /gemspec/ ) }
|
59
|
+
fail '[gemfile] Gemfile commit contains non-gemfile changes' + short
|
60
|
+
end
|
61
|
+
if c.diff_parent.any? {|f| f.path == 'Gemfile.lock' }
|
62
|
+
unless `grep -e '^ 1.15.2$' Gemfile.lock`.length > 1
|
63
|
+
fail("[gemfile] Gemfile not bundled with bundler 1.15.2")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
elsif has_gemfile_msg
|
67
|
+
fail '[gemfile] Gemfile commit has no gemfile changes!' + short
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
require 'open-uri'
|
72
|
+
|
73
|
+
artifact_url = "https://circleci.com/api/v1.1/project/github/#{ENV['CIRCLE_PROJECT_USERNAME']}/#{ENV["CIRCLE_PROJECT_REPONAME"]}/#{ENV['CIRCLE_BUILD_NUM']}/artifacts?circle-token=#{ENV['CIRCLE_TOKEN']}"
|
74
|
+
artifacts = JSON.load(open(artifact_url).read).map{|a| a["url"]}
|
75
|
+
|
76
|
+
jest = artifacts.find{ |artifact| artifact.end_with?('jest/index.html') }
|
77
|
+
coverage = artifacts.find{ |artifact| artifact.end_with?('coverage/index.html') }
|
78
|
+
rubocop = artifacts.find{ |artifact| artifact.end_with?('rubocop/report.html') }
|
79
|
+
eslint = artifacts.find{ |artifact| artifact.end_with?('eslint/report.html') }
|
80
|
+
rspec_files = artifacts.select{ |artifact| artifact =~ /rspec-(.+)\.html$/ }
|
81
|
+
|
82
|
+
{}.tap do |hash|
|
83
|
+
hash['Ruby coverage report'] = coverage if coverage
|
84
|
+
hash['RSpec test report'] = rspec_files unless rspec_files.empty?
|
85
|
+
hash['RuboCop inspection report'] = rubocop if rubocop
|
86
|
+
hash['ESLint inspection report'] = eslint if eslint
|
87
|
+
hash['Jest coverage report'] = jest if jest
|
88
|
+
end.each do |msg, links|
|
89
|
+
links = [*links]
|
90
|
+
if links.size == 1
|
91
|
+
message("[#{msg}](#{links[0]})")
|
92
|
+
else
|
93
|
+
r = /rspec-(.+)\.html$/
|
94
|
+
the_links = links.map do |l|
|
95
|
+
m = r.match(l)
|
96
|
+
if m
|
97
|
+
"[#{m[1]}](#{l})"
|
98
|
+
else
|
99
|
+
"[link](#{l})"
|
100
|
+
end
|
101
|
+
end.join(', ')
|
102
|
+
|
103
|
+
message("#{msg} - #{the_links}")
|
104
|
+
end
|
105
|
+
end
|
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
data/bin/netsoft-circle
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
class NetsoftCircle < Thor
|
7
|
+
desc 'setup', 'Setup Heroku for deployment'
|
8
|
+
def setup
|
9
|
+
|
10
|
+
File.open("#{ENV['HOME']}/.netrc", 'a+') do |file|
|
11
|
+
file << <<-EOF
|
12
|
+
|
13
|
+
machine api.heroku.com
|
14
|
+
login #{ENV['HEROKU_LOGIN']}
|
15
|
+
password #{ENV['HEROKU_API_KEY']}
|
16
|
+
machine git.heroku.com
|
17
|
+
login #{ENV['HEROKU_LOGIN']}
|
18
|
+
password #{ENV['HEROKU_API_KEY']}
|
19
|
+
EOF
|
20
|
+
end
|
21
|
+
|
22
|
+
Dir.mkdir("#{ENV['HOME']}/.ssh") unless Dir.exists?("#{ENV['HOME']}/.ssh")
|
23
|
+
File.open("#{ENV['HOME']}/.ssh/config", 'a+') do |file|
|
24
|
+
file << <<-EOF
|
25
|
+
|
26
|
+
VerifyHostKeyDNS yes
|
27
|
+
StrictHostKeyChecking no
|
28
|
+
EOF
|
29
|
+
end
|
30
|
+
|
31
|
+
system('git config --global url."https://git.heroku.com/".insteadOf heroku:')
|
32
|
+
exit(1) unless $?.success?
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'merge', 'Merges several simplecov json result files'
|
36
|
+
option :output, type: :string, aliases: '-o', desc: 'Specify an alternate output directory for the produced coverage data'
|
37
|
+
def merge(*files)
|
38
|
+
require 'simplecov'
|
39
|
+
return if files.empty?
|
40
|
+
results = []
|
41
|
+
|
42
|
+
files.each do |file|
|
43
|
+
json = JSON.parse(File.read(file))
|
44
|
+
json.each do |command_name, data|
|
45
|
+
result = SimpleCov::Result.from_hash(command_name => data)
|
46
|
+
results << result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
merged_result = SimpleCov::ResultMerger.merge_results(*results)
|
51
|
+
SimpleCov.coverage_dir options[:output] unless options[:output].nil?
|
52
|
+
SimpleCov::Formatter::HTMLFormatter.new.format(merged_result)
|
53
|
+
end
|
54
|
+
|
55
|
+
desc 'rspec', 'Run rspec'
|
56
|
+
def rspec
|
57
|
+
system <<-EOF
|
58
|
+
bundle _${BUNDLE_VERSION}_ exec rspec \
|
59
|
+
--color \
|
60
|
+
--format RspecJunitFormatter \
|
61
|
+
--out $CIRCLE_TEST_REPORTS/rspec/junit.xml \
|
62
|
+
--format html \
|
63
|
+
--out $CIRCLE_ARTIFACTS/rspec.html \
|
64
|
+
--format progress \
|
65
|
+
$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
|
66
|
+
EOF
|
67
|
+
exit(1) unless $?.success?
|
68
|
+
end
|
69
|
+
|
70
|
+
desc 'rubocop', 'Run rubocop'
|
71
|
+
def rubocop
|
72
|
+
system <<-EOF
|
73
|
+
bundle _${BUNDLE_VERSION}_ exec rubocop \
|
74
|
+
--format progress \
|
75
|
+
--format html \
|
76
|
+
--out $CIRCLE_ARTIFACTS/rubocop/report.html
|
77
|
+
EOF
|
78
|
+
exit(1) unless $?.success?
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.exit_on_failure?
|
82
|
+
true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
NetsoftCircle.start
|
data/bin/tag_check.sh
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
tag=`git describe --tags --exact-match HEAD 2> /dev/null`
|
4
|
+
|
5
|
+
if [ $? -eq 0 ]; then
|
6
|
+
version=`grep VERSION lib/netsoft-danger/version.rb | sed -e "s/.*'\([^']*\)'.*/\1/"`
|
7
|
+
|
8
|
+
if [ "v$version" = "$tag" ]; then
|
9
|
+
echo "Revision $tag Matches $version"
|
10
|
+
else
|
11
|
+
echo "Revision $tag does not match $version"
|
12
|
+
exit 2
|
13
|
+
fi
|
14
|
+
else
|
15
|
+
echo "No tag found"
|
16
|
+
exit 1
|
17
|
+
fi
|
data/dangerfiles/pr.js
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
import {danger, warn, fail, message} from "danger";
|
2
|
+
|
3
|
+
if (!danger.github.issue.labels.length) {
|
4
|
+
fail('Please add labels to this PR');
|
5
|
+
}
|
6
|
+
|
7
|
+
var labels = danger.github.issue.labels.map(l => l.name);
|
8
|
+
|
9
|
+
// Make it more obvious that a PR is a work in progress and shouldn't be merged yet
|
10
|
+
if (labels.includes('work in progress') || danger.git.commits.find(c => c && c.message.includes('WIP'))) {
|
11
|
+
fail("PR is a Work in Progress");
|
12
|
+
}
|
13
|
+
|
14
|
+
if ((danger.github.pr.body || '').length < 5) {
|
15
|
+
fail("Please provide a summary in the Pull Request description");
|
16
|
+
}
|
17
|
+
|
18
|
+
if (!labels.includes('review passed')) {
|
19
|
+
fail("Has not passed code-review");
|
20
|
+
}
|
21
|
+
|
22
|
+
if (!labels.includes('QA passed')) {
|
23
|
+
fail("Has not passed QA");
|
24
|
+
}
|
25
|
+
|
26
|
+
if (!danger.github.pr.base.ref.includes('master')) {
|
27
|
+
warn("PR base is not set to master!");
|
28
|
+
}
|
29
|
+
|
30
|
+
// Warn when there is a big PR
|
31
|
+
if (500 < (danger.github.pr.additions + danger.github.pr.deletions)) {
|
32
|
+
warn(':exclamation: Big PR');
|
33
|
+
}
|
34
|
+
|
35
|
+
if (danger.git.commits.find(c => c && c.message.match(/Merge branch/))) {
|
36
|
+
fail('Please rebase to remove merge commits in this PR');
|
37
|
+
}
|
38
|
+
|
39
|
+
if (danger.git.commits.find(c => c && c.message.match(/(fixup|squash)!/))) {
|
40
|
+
fail("Contains a fixup or squash commit");
|
41
|
+
}
|
42
|
+
|
43
|
+
if (!danger.github.pr.milestone) {
|
44
|
+
fail('Requires a milestone before merging!');
|
45
|
+
} else {
|
46
|
+
// we can do additional checks on the milestone name if we want.
|
47
|
+
// e.g. inspect milestone.title or milestone.description
|
48
|
+
}
|
49
|
+
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rubocop/cop/mixin/target_rails_version'
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Cop
|
7
|
+
module Netsoft
|
8
|
+
# This cop is used to identify usages of http methods like `get`, `post`,
|
9
|
+
# `put`, `patch` without the usage of keyword arguments in your tests and
|
10
|
+
# change them to use keyword args. This cop only applies to Rails >= 5.
|
11
|
+
# If you are running Rails < 5 you should disable the
|
12
|
+
# Netsoft/HttpPositionalArguments cop or set your TargetRailsVersion in your
|
13
|
+
# .rubocop.yml file to 4.0, etc.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# # bad
|
17
|
+
# get :new, { user_id: 1}
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# get :new, params: { user_id: 1 }
|
21
|
+
class AuthHttpPositionalArguments < Cop
|
22
|
+
extend RuboCop::Cop::TargetRailsVersion
|
23
|
+
|
24
|
+
MSG = 'Use keyword arguments instead of ' \
|
25
|
+
'positional arguments for http call: `%<verb>s`.'.freeze
|
26
|
+
KEYWORD_ARGS = %i[
|
27
|
+
method params session body flash xhr as headers env
|
28
|
+
].freeze
|
29
|
+
HTTP_METHODS = %i[get post put patch delete head].freeze
|
30
|
+
HTTP_AUTH_METHODS = %i[get_with post_with put_with patch_with delete_with].freeze
|
31
|
+
|
32
|
+
minimum_target_rails_version 5.0
|
33
|
+
|
34
|
+
def_node_matcher :http_request?, <<-PATTERN
|
35
|
+
(send nil? {#{HTTP_METHODS.map(&:inspect).join(' ')}} !nil? $_ ...)
|
36
|
+
PATTERN
|
37
|
+
|
38
|
+
def_node_matcher :http_auth_request?, <<-PATTERN
|
39
|
+
(send nil? {#{HTTP_AUTH_METHODS.map(&:inspect).join(' ')}} !nil? !nil? $_ ...)
|
40
|
+
PATTERN
|
41
|
+
|
42
|
+
def on_send(node)
|
43
|
+
http_request?(node) do |data|
|
44
|
+
return unless needs_conversion?(data)
|
45
|
+
|
46
|
+
add_offense(node, location: :selector,
|
47
|
+
message: format(MSG, verb: node.method_name))
|
48
|
+
end
|
49
|
+
|
50
|
+
http_auth_request?(node) do |data|
|
51
|
+
return unless auth_needs_conversion?(data)
|
52
|
+
|
53
|
+
add_offense(node, location: :selector,
|
54
|
+
message: format(MSG, verb: node.method_name))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# given a pre Rails 5 method: get :new, {user_id: @user.id}, {}
|
59
|
+
#
|
60
|
+
# @return lambda of auto correct procedure
|
61
|
+
# the result should look like:
|
62
|
+
# get :new, params: { user_id: @user.id }, session: {}
|
63
|
+
# the http_method is the method used to call the controller
|
64
|
+
# the controller node can be a symbol, method, object or string
|
65
|
+
# that represents the path/action on the Rails controller
|
66
|
+
# the data is the http parameters and environment sent in
|
67
|
+
# the Rails 5 http call
|
68
|
+
def autocorrect(node)
|
69
|
+
has_auth = HTTP_AUTH_METHODS.include?(node.method_name.to_sym)
|
70
|
+
if has_auth
|
71
|
+
user, http_path, *data = *node.arguments
|
72
|
+
else
|
73
|
+
http_path, *data = *node.arguments
|
74
|
+
end
|
75
|
+
|
76
|
+
controller_action = http_path.source
|
77
|
+
params = convert_hash_data(data.first, 'params')
|
78
|
+
session = convert_hash_data(data.last, 'session') if data.size > 1
|
79
|
+
# the range of the text to replace, which is the whole line
|
80
|
+
code_to_replace = node.loc.expression
|
81
|
+
# what to replace with
|
82
|
+
format = parentheses_format(node)
|
83
|
+
new_code = format(format, name: node.method_name,
|
84
|
+
action: has_auth ? [user.source, controller_action].join(',') : controller_action,
|
85
|
+
params: params, session: session)
|
86
|
+
->(corrector) { corrector.replace(code_to_replace, new_code) }
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def needs_conversion?(data)
|
92
|
+
return true unless data.hash_type?
|
93
|
+
|
94
|
+
data.each_pair.none? do |pair|
|
95
|
+
special_keyword_arg?(pair.key) ||
|
96
|
+
format_arg?(pair.key) && data.pairs.one?
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def auth_needs_conversion?(data)
|
101
|
+
return true unless data.hash_type?
|
102
|
+
|
103
|
+
data.each_pair.none? do |pair|
|
104
|
+
special_keyword_arg?(pair.key) ||
|
105
|
+
format_arg?(pair.key) && data.pairs.one?
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def special_keyword_arg?(node)
|
110
|
+
node.sym_type? && KEYWORD_ARGS.include?(node.value)
|
111
|
+
end
|
112
|
+
|
113
|
+
def format_arg?(node)
|
114
|
+
node.sym_type? && node.value == :format
|
115
|
+
end
|
116
|
+
|
117
|
+
def convert_hash_data(data, type)
|
118
|
+
return '' if data.hash_type? && data.empty?
|
119
|
+
|
120
|
+
hash_data = if data.hash_type?
|
121
|
+
format('{ %<data>s }',
|
122
|
+
data: data.pairs.map(&:source).join(', '))
|
123
|
+
else
|
124
|
+
# user supplies an object,
|
125
|
+
# no need to surround with braces
|
126
|
+
data.source
|
127
|
+
end
|
128
|
+
|
129
|
+
format(', %<type>s: %<hash_data>s', type: type, hash_data: hash_data)
|
130
|
+
end
|
131
|
+
|
132
|
+
def parentheses_format(node)
|
133
|
+
if parentheses?(node)
|
134
|
+
'%<name>s(%<action>s%<params>s%<session>s)'
|
135
|
+
else
|
136
|
+
'%<name>s %<action>s%<params>s%<session>s'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'cops/netsoft/auth_http_positional_arguments'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'netsoft-danger/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'netsoft-danger'
|
7
|
+
s.version = NetsoftDanger::VERSION
|
8
|
+
s.authors = ['urkle']
|
9
|
+
s.email = []
|
10
|
+
s.homepage = 'https://github.com/NetsoftHoldings/danger'
|
11
|
+
s.summary = 'Danger.systems conventions for Netsoft projects.'
|
12
|
+
s.description = 'Packages a Dangerfile to be used with Danger.'
|
13
|
+
s.executables << 'netsoft-circle'
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.require_paths = ['lib']
|
17
|
+
|
18
|
+
s.add_development_dependency 'rake'
|
19
|
+
s.add_runtime_dependency 'danger', '~> 5.0'
|
20
|
+
s.add_runtime_dependency 'rubocop', '~> 0.74.0'
|
21
|
+
s.add_runtime_dependency 'rubocop-rails', '~> 2.2.1'
|
22
|
+
s.add_runtime_dependency 'rubocop-performance', '~> 1.4.1'
|
23
|
+
s.add_runtime_dependency 'rubocop-rspec', '~> 1.35.0'
|
24
|
+
s.add_runtime_dependency 'thor'
|
25
|
+
end
|
data/package.json
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require:
|
2
|
+
- netsoft-danger
|
3
|
+
- rubocop-rails
|
4
|
+
- rubocop-performance
|
5
|
+
- rubocop-rspec
|
6
|
+
|
7
|
+
AllCops:
|
8
|
+
TargetRubyVersion: 2.4
|
9
|
+
TargetRailsVersion: 5.2
|
10
|
+
DisplayStyleGuide: true
|
11
|
+
StyleGuideBaseURL: https://rubystyle.guide
|
12
|
+
Exclude:
|
13
|
+
- 'db/**/*'
|
14
|
+
- 'coverage/**/*'
|
15
|
+
- 'log/**/*'
|
16
|
+
- 'public/**/*'
|
17
|
+
- 'tmp/**/*'
|
18
|
+
- 'spec/dummy/**/*'
|
19
|
+
Rails:
|
20
|
+
Enabled: true
|
21
|
+
Rails/HttpPositionalArguments:
|
22
|
+
Enabled: false
|
23
|
+
Netsoft/AuthHttpPositionalArguments:
|
24
|
+
Enabled: true
|
25
|
+
Include:
|
26
|
+
- 'spec/controllers/**/*'
|
27
|
+
RSpec/NotToNot:
|
28
|
+
EnforcedStyle: to_not
|
29
|
+
RSpec/ExpectChange:
|
30
|
+
EnforcedStyle: block
|
31
|
+
Style/TrailingCommaInArrayLiteral:
|
32
|
+
EnforcedStyleForMultiline: comma
|
33
|
+
Style/TrailingCommaInHashLiteral:
|
34
|
+
EnforcedStyleForMultiline: comma
|
35
|
+
Layout/SpaceInsideBlockBraces:
|
36
|
+
EnforcedStyle: no_space
|
37
|
+
SpaceBeforeBlockParameters: false
|
38
|
+
Layout/AlignHash:
|
39
|
+
EnforcedHashRocketStyle: table
|
40
|
+
EnforcedColonStyle: table
|
41
|
+
Layout/IndentFirstHashElement:
|
42
|
+
IndentationWidth: 4
|
43
|
+
Layout/SpaceInsideHashLiteralBraces:
|
44
|
+
EnforcedStyle: no_space
|
45
|
+
Layout/IndentAssignment:
|
46
|
+
IndentationWidth: 4
|