chris_lib 2.2.1 → 2.2.2

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.
@@ -1,40 +1,89 @@
1
- # methods for bash ruby scripts
1
+ # Helpers for shell-friendly Ruby scripts and deployment utilities.
2
2
  module ShellMethods
3
3
  require 'dotenv'
4
4
  require 'bundler'
5
5
  require 'optparse'
6
6
  Dotenv.load
7
7
 
8
- # runs an R script from ruby
9
- # script_path is absolute path of R script
10
- # arg1 is an argument passed to script, can access in R by
11
- # arg1 <- commandArgs(trailingOnly=TRUE)[1]
8
+ # Run an R script via `Rscript --vanilla`
9
+ #
10
+ # @param script_path [String] absolute path to the R script
11
+ # @param arg1 [String] first argument passed to the script (accessible in R via `commandArgs(trailingOnly=TRUE)[1]`)
12
+ # @return [String] stdout from the R script
13
+ # @note Warns and returns `nil` when the script is missing.
12
14
  def r_runner(script_path, arg1)
13
- `Rscript --vanilla #{script_path} #{arg1}`
15
+ raise ArgumentError, 'script_path must be provided' unless script_path.respond_to?(:to_s)
16
+ path = script_path.to_s
17
+ unless File.exist?(path)
18
+ warn "r_runner: #{path} does not exist"
19
+ return nil
20
+ end
21
+ arg = arg1.to_s
22
+ `Rscript --vanilla #{path} #{arg}`
14
23
  end
15
24
 
25
+ # @param file_path [String]
26
+ # @return [Integer] file size in bytes
27
+ # @note Returns 0 and warns when the file is missing.
16
28
  def file_size(file_path)
17
- `stat -f%z #{file_path}`.to_i
29
+ raise ArgumentError, 'file_path must be provided' unless file_path.respond_to?(:to_s)
30
+ path = file_path.to_s
31
+ unless File.exist?(path)
32
+ warn "file_size: #{path} does not exist"
33
+ return 0
34
+ end
35
+ `stat -f%z #{path}`.to_i
18
36
  end
19
37
 
38
+ # Send an iMessage to the "admin" buddy on macOS.
39
+ # @param msg [String]
40
+ # @return [String]
41
+ # @note Warns and no-ops when `msg` is blank.
20
42
  def osx_imessage_admin(msg)
43
+ if msg.nil? || msg.strip.empty?
44
+ warn 'osx_imessage_admin called without a message; skipping'
45
+ return nil
46
+ end
21
47
  `osascript -e 'tell application "Messages" to send "#{msg}" to buddy "admin"'`
22
48
  end
23
49
 
50
+ # Trigger a macOS notification via AppleScript.
51
+ # @param msg [String]
52
+ # @param title [String]
53
+ # @return [String]
54
+ # @note Warns and no-ops when `msg` is blank. Supplies a default title when missing.
24
55
  def osx_notification(msg, title)
56
+ if msg.nil? || msg.strip.empty?
57
+ warn 'osx_notification called without a message; skipping'
58
+ return nil
59
+ end
60
+ if title.nil? || title.strip.empty?
61
+ warn 'osx_notification called without a title; using default'
62
+ title = 'Notification'
63
+ end
25
64
  `osascript -e 'display notification "#{msg}" with title "#{title}"'`
26
65
  end
27
66
 
67
+ # @return [String] hostname of the current machine
28
68
  def osx_hostname
29
69
  `hostname`
30
70
  end
31
71
 
32
- # mail to osx user
33
- # https://stackoverflow.com/q/41602984/1299362
72
+ # Mail the signed-in macOS user using the BSD `mail` command.
73
+ # @param subject [String]
74
+ # @param body [String]
75
+ # @return [String]
76
+ # @note Warns and no-ops when `subject` is blank.
34
77
  def osx_send_mail(subject, body = nil)
78
+ if subject.nil? || subject.strip.empty?
79
+ warn 'osx_send_mail called without a subject; skipping'
80
+ return nil
81
+ end
35
82
  `echo "#{body}" | mail -s "#{subject}" 'Chris'`
36
83
  end
37
84
 
85
+ # Parse CLI options for deployment scripts.
86
+ # @return [Hash] options hash with keys :skip_migration, :fast, :special_rake
38
87
  def parse_options
39
88
  @options = {}
40
89
  OptionParser.new do |opts|
@@ -51,16 +100,22 @@ module ShellMethods
51
100
  @options[:skip_migration] = true if @options[:fast]
52
101
  end
53
102
 
103
+ # Placeholder for future custom rake tasks.
104
+ # @raise [RuntimeError] always, prompting implementers to override
54
105
  def run_special_rake_task
55
106
  fail 'Need to implement by asking for name of rake task and
56
107
  also requiring confirmation'
57
108
  end
58
109
 
110
+ # Create a Postgres snapshot by delegating to `script/getSnapShot.sh`.
111
+ # @return [Boolean] command exit status
59
112
  def backup_database
60
113
  file_path = "../backups/prod#{time_hash}.dump"
61
114
  system('./script/getSnapShot.sh production ' + file_path)
62
115
  end
63
116
 
117
+ # Notify users of an impending deploy via Heroku and progress bar countdown.
118
+ # @return [void]
64
119
  def warn_users
65
120
  system('heroku run rake util:three_min_warning --remote production')
66
121
  # spend one minute precompiling
@@ -76,6 +131,8 @@ module ShellMethods
76
131
  system('heroku run rake util:warn_under_maintenance --remote production')
77
132
  end
78
133
 
134
+ # Timestamp helper used to build backup filenames.
135
+ # @return [String]
79
136
  def time_hash
80
137
  time = Time.now
81
138
  time.day.to_s + time.month.to_s + time.year.to_s + '-' + time.hour.to_s + time.min.to_s
@@ -84,6 +141,9 @@ module ShellMethods
84
141
  # change in response to
85
142
  #[DEPRECATED] `Bundler.with_clean_env` has been deprecated in favor of `Bundler.with_unbundled_env`. If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env`
86
143
  # remove this comment when clear that this works.
144
+ # Compare local and remote database schema versions.
145
+ # @param remote [String, nil] Heroku remote name
146
+ # @return [Boolean, nil] true when versions match, false when mismatched, nil when versions cannot be read
87
147
  def same_db_version(remote: nil)
88
148
  destination = (remote.nil? ? nil : "--remote #{remote}")
89
149
  lv = `rake db:version`
@@ -102,6 +162,7 @@ module ShellMethods
102
162
  l_version == h_version
103
163
  end
104
164
 
165
+ # Ensure git workspace is clean before deploying.
105
166
  def check_git_clean
106
167
  puts "Checking git status"
107
168
  gs = `git status`
@@ -110,6 +171,7 @@ module ShellMethods
110
171
  exit 1
111
172
  end
112
173
 
174
+ # Verify that `chris_lib` is up to date before deploying.
113
175
  def check_chris_lib_status
114
176
  gs=`cd ../chris_lib;git status`; lr=$?.successful?
115
177
  return unless gs['working tree clean'].nil? && gs['up-to-date'].nil?
@@ -118,6 +180,10 @@ module ShellMethods
118
180
  system('cd $OLDPWD')
119
181
  end
120
182
 
183
+ # Optionally run migrations if local and remote schema versions differ.
184
+ # @param remote [String, nil]
185
+ # @param skip_migration [Boolean]
186
+ # @return [void]
121
187
  def migrate_if_necessary(remote: nil, skip_migration: false)
122
188
  if skip_migration
123
189
  puts "No migration will be performed due to --fast or --skip_migration options"
@@ -137,7 +203,11 @@ module ShellMethods
137
203
  end
138
204
  end
139
205
 
206
+ # Notify Rollbar of a new deploy via its API.
207
+ # @param access_token [String, nil]
208
+ # @return [void]
140
209
  def notify_rollbar_of_deploy(access_token: nil)
210
+ warn 'notify_rollbar_of_deploy called without access token' if access_token.nil? || access_token.empty?
141
211
  system("ACCESS_TOKEN=#{access_token}")
142
212
  system("ENVIRONMENT=production")
143
213
  system("LOCAL_USERNAME=`whoami`")
@@ -158,4 +228,4 @@ module ShellMethods
158
228
  puts "Failure to notify Rollbar of deploy of v#{TGM_VERSION} with SHA #{sha[0..5]}", cr
159
229
  end
160
230
  end
161
- end
231
+ end
@@ -1,15 +1,30 @@
1
1
  module TestAccess
2
- # A rspec macro to test access security for controllers, call <tt>it_should_route_to(path,actions)</tt>
3
- # where path is a string of the form <tt>url_path</tt> and actions is a hash of symbols
4
- # that represent actions to be protected.
5
- # An example call is <tt>it_should_route_to('login_path',:edit,:update)</tt>. The call is
6
- # made in a describe or context block with a preceding <tt>require TestAccess</tt>.
2
+ # An RSpec helper that verifies protected controller actions redirect to a login path.
7
3
  #
4
+ # Include the module and call {.it_should_route_to} with the protected actions:
5
+ #
6
+ # it_should_route_to('login_path', [:edit, :update])
7
+ #
8
+ # Optionally provide a `flash_message` expectation.
9
+ # @!visibility private
8
10
  module ExampleMethods
9
11
  end
12
+
13
+ # @!visibility private
10
14
  module ExampleGroupMethods
15
+ # Define a set of expectations that each action redirects to the provided path.
16
+ # @param path [String] helper method name that resolves to the desired redirect URL
17
+ # @param actions [Array<Symbol>]
18
+ # @param flash_message [String, nil] text to match in `flash[:error]`
11
19
  def it_should_route_to(path,actions,flash_message=nil)
20
+ raise ArgumentError, 'path must respond to #to_s' unless path.respond_to?(:to_s)
21
+ actions = Array(actions)
22
+ if actions.empty?
23
+ warn 'it_should_route_to called with no actions; nothing to verify'
24
+ return
25
+ end
12
26
  actions.each do |a|
27
+ raise ArgumentError, "action #{a.inspect} must respond to #to_sym" unless a.respond_to?(:to_sym)
13
28
  it "should deny access to #{a}" do
14
29
  if Rails::VERSION::MAJOR >= 5
15
30
  get a.to_sym, params: { id: 1}
@@ -31,8 +46,12 @@ module TestAccess
31
46
  end
32
47
  end
33
48
  end
49
+ # @!visibility private
34
50
  def self.included(receiver)
51
+ unless receiver.respond_to?(:it)
52
+ warn 'TestAccess included into an object without RSpec example support'
53
+ end
35
54
  receiver.extend ExampleGroupMethods
36
55
  receiver.send :include, ExampleMethods
37
56
  end
38
- end
57
+ end
@@ -1,3 +1,3 @@
1
1
  module ChrisLib
2
- VERSION = '2.2.1'
2
+ VERSION = '2.2.2'
3
3
  end
data/lib/chris_lib.rb CHANGED
@@ -4,5 +4,8 @@ require "chris_lib/date_ext"
4
4
  require "chris_lib/test_access"
5
5
  require "chris_lib/chris_math"
6
6
  require "chris_lib/shell_methods"
7
+ require "chris_lib/for_chris_lib"
8
+
9
+ # Main namespace for helpers published by the chris_lib gem.
7
10
  module ChrisLib
8
11
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chris_lib
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-09-17 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: dotenv
@@ -39,19 +38,47 @@ dependencies:
39
38
  - !ruby/object:Gem::Version
40
39
  version: '0'
41
40
  - !ruby/object:Gem::Dependency
42
- name: rails
41
+ name: minimization
43
42
  requirement: !ruby/object:Gem::Requirement
44
43
  requirements:
45
44
  - - ">="
46
45
  - !ruby/object:Gem::Version
47
46
  version: '0'
48
- type: :development
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: ostruct
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :runtime
49
62
  prerelease: false
50
63
  version_requirements: !ruby/object:Gem::Requirement
51
64
  requirements:
52
65
  - - ">="
53
66
  - !ruby/object:Gem::Version
54
67
  version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: rails
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '8.0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '8.0'
55
82
  - !ruby/object:Gem::Dependency
56
83
  name: actionpack
57
84
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +177,34 @@ dependencies:
150
177
  - - ">="
151
178
  - !ruby/object:Gem::Version
152
179
  version: '0'
180
+ - !ruby/object:Gem::Dependency
181
+ name: yard
182
+ requirement: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ type: :development
188
+ prerelease: false
189
+ version_requirements: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ - !ruby/object:Gem::Dependency
195
+ name: webrick
196
+ requirement: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - ">="
199
+ - !ruby/object:Gem::Version
200
+ version: '0'
201
+ type: :development
202
+ prerelease: false
203
+ version_requirements: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - ">="
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
153
208
  description: It includes maths, datetime, and rspec access test libraries.
154
209
  email:
155
210
  - obromios@gmail.com
@@ -162,6 +217,7 @@ files:
162
217
  - lib/chris_lib.rb
163
218
  - lib/chris_lib/chris_math.rb
164
219
  - lib/chris_lib/date_ext.rb
220
+ - lib/chris_lib/for_chris_lib.rb
165
221
  - lib/chris_lib/shell_methods.rb
166
222
  - lib/chris_lib/test_access.rb
167
223
  - lib/chris_lib/version.rb
@@ -172,7 +228,6 @@ licenses:
172
228
  metadata:
173
229
  source_code_uri: https://github.com/obromios/chris_lib
174
230
  changelog_uri: https://github.com/obromios/chris_lib/blob/master/CHANGELOG.md
175
- post_install_message:
176
231
  rdoc_options: []
177
232
  require_paths:
178
233
  - lib
@@ -187,8 +242,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
187
242
  - !ruby/object:Gem::Version
188
243
  version: '0'
189
244
  requirements: []
190
- rubygems_version: 3.3.26
191
- signing_key:
245
+ rubygems_version: 3.7.2
192
246
  specification_version: 4
193
247
  summary: This an eclectic collection of methods. It include maths, datetime, and rspec
194
248
  access test libraries.