renuo-cli 4.5.0 → 4.5.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/Gemfile +1 -1
- data/Rakefile +3 -3
- data/lib/renuo/cli/app/command_helper.rb +4 -4
- data/lib/renuo/cli/app/commit_leaderboard_stage.rb +109 -0
- data/lib/renuo/cli/app/commit_leaderboard_sync.rb +20 -20
- data/lib/renuo/cli/app/configure_semaphore.rb +8 -8
- data/lib/renuo/cli/app/configure_sentry.rb +5 -5
- data/lib/renuo/cli/app/create_aws_project.rb +23 -23
- data/lib/renuo/cli/app/create_heroku_app.rb +2 -3
- data/lib/renuo/cli/app/create_new_logins.rb +5 -5
- data/lib/renuo/cli/app/create_slidev_presentation.rb +11 -11
- data/lib/renuo/cli/app/environments.rb +3 -3
- data/lib/renuo/cli/app/fetch_emails.rb +6 -6
- data/lib/renuo/cli/app/generate_password.rb +2 -2
- data/lib/renuo/cli/app/heroku_apps.rb +1 -1
- data/lib/renuo/cli/app/heroku_users.rb +3 -3
- data/lib/renuo/cli/app/local_storage.rb +5 -5
- data/lib/renuo/cli/app/name_display.rb +11 -11
- data/lib/renuo/cli/app/redmine/csv_base_service.rb +5 -5
- data/lib/renuo/cli/app/redmine/issue.rb +3 -3
- data/lib/renuo/cli/app/release_project.rb +25 -25
- data/lib/renuo/cli/app/release_xing.rb +5 -5
- data/lib/renuo/cli/app/renuo_version.rb +2 -2
- data/lib/renuo/cli/app/secrets_fetcher.rb +18 -18
- data/lib/renuo/cli/app/services/cloudfront_config_service.rb +13 -13
- data/lib/renuo/cli/app/services/markdown_parser_service.rb +3 -3
- data/lib/renuo/cli/app/services/renuo_cli_config.rb +4 -4
- data/lib/renuo/cli/app/setup_uptimerobot.rb +17 -17
- data/lib/renuo/cli/app/toggl/detail.rb +4 -4
- data/lib/renuo/cli/app/toggl/time_entry.rb +4 -4
- data/lib/renuo/cli/app/toggl/user.rb +3 -3
- data/lib/renuo/cli/app/toggl/workspace.rb +3 -3
- data/lib/renuo/cli/app/toggl_redmine_comparator.rb +26 -26
- data/lib/renuo/cli/app/upgrade_laptop/upgrade_laptop_execution.rb +4 -4
- data/lib/renuo/cli/app/upgrade_laptop/upgrade_mac_os.rb +4 -4
- data/lib/renuo/cli/app/upgrade_laptop.rb +4 -4
- data/lib/renuo/cli/app/work.rb +12 -12
- data/lib/renuo/cli/version.rb +2 -2
- data/lib/renuo/cli.rb +148 -146
- data/renuo-cli.gemspec +33 -33
- metadata +3 -3
- data/lib/renuo/cli/app/commit_leaderboard.rb +0 -130
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative "command_helper"
|
|
4
4
|
|
|
5
5
|
class NameDisplay
|
|
6
6
|
include CommandHelper
|
|
@@ -8,28 +8,28 @@ class NameDisplay
|
|
|
8
8
|
def run(args, options)
|
|
9
9
|
return open_path(SLIDES) if options.monitor
|
|
10
10
|
return display_name(nil) if options.delete
|
|
11
|
-
return say(
|
|
11
|
+
return say("empty argument") if args.empty?
|
|
12
12
|
|
|
13
|
-
return run_heroku_command(args.join(
|
|
13
|
+
return run_heroku_command(args.join(" ")) if options.override
|
|
14
14
|
|
|
15
|
-
display_name(args.join(
|
|
15
|
+
display_name(args.join(" "))
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
private
|
|
19
19
|
|
|
20
|
-
HEROKU_APP_NAME =
|
|
21
|
-
HEROKU_CLI =
|
|
22
|
-
RENUO_CLI =
|
|
23
|
-
SLIDES =
|
|
24
|
-
WELCOME_MESSAGE =
|
|
20
|
+
HEROKU_APP_NAME = "-a renuo-dashboard-main"
|
|
21
|
+
HEROKU_CLI = "heroku run"
|
|
22
|
+
RENUO_CLI = "rails renuo:welcome"
|
|
23
|
+
SLIDES = "https://docs.google.com/presentation/d/1mPhQjArZnlUWUa2ik5R9IlGmdCKCwc2_H8Qq-AWgV-A/edit"
|
|
24
|
+
WELCOME_MESSAGE = "Welcome to Renuo"
|
|
25
25
|
|
|
26
26
|
def display_name(name)
|
|
27
|
-
text_message = [WELCOME_MESSAGE, name,
|
|
27
|
+
text_message = [WELCOME_MESSAGE, name, "🥳🔥"].compact.join(" ")
|
|
28
28
|
run_heroku_command(text_message)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def run_heroku_command(text_message)
|
|
32
32
|
rails_command = "\"#{RENUO_CLI}['#{text_message}']\""
|
|
33
|
-
run_command([HEROKU_CLI, rails_command, HEROKU_APP_NAME].join(
|
|
33
|
+
run_command([HEROKU_CLI, rails_command, HEROKU_APP_NAME].join(" "))
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "csv"
|
|
4
4
|
|
|
5
5
|
module Redmine
|
|
6
6
|
class CsvBaseService
|
|
7
|
-
API_LOCATION =
|
|
7
|
+
API_LOCATION = "https://redmine.renuo.ch"
|
|
8
8
|
|
|
9
9
|
def initialize(token)
|
|
10
10
|
@token = token
|
|
@@ -12,7 +12,7 @@ module Redmine
|
|
|
12
12
|
|
|
13
13
|
def get
|
|
14
14
|
http_response = http_request(generate_url)
|
|
15
|
-
encoded_body = http_response.body.force_encoding(
|
|
15
|
+
encoded_body = http_response.body.force_encoding("ISO-8859-1").encode("UTF-8")
|
|
16
16
|
csv = parse_csv(encoded_body)
|
|
17
17
|
parse_results(csv)
|
|
18
18
|
end
|
|
@@ -39,7 +39,7 @@ module Redmine
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def parse_csv(body)
|
|
42
|
-
separated_csv_entries = CSV.parse(body, col_sep:
|
|
42
|
+
separated_csv_entries = CSV.parse(body, col_sep: ",")
|
|
43
43
|
keys = separated_csv_entries.shift[1..-2]
|
|
44
44
|
entries = separated_csv_entries.shift[1..-2]
|
|
45
45
|
keys.zip(entries).to_h
|
|
@@ -48,7 +48,7 @@ module Redmine
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def raise_bad_data_error
|
|
51
|
-
error =
|
|
51
|
+
error = "Malformed CSV, please use comma delimiters (Redmine language setting?)"
|
|
52
52
|
Rails.logger.error error
|
|
53
53
|
raise Redmine::BadData, error
|
|
54
54
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "active_resource"
|
|
4
4
|
|
|
5
5
|
module Redmine
|
|
6
6
|
class Issue < ActiveResource::Base
|
|
@@ -11,11 +11,11 @@ module Redmine
|
|
|
11
11
|
qa: 12
|
|
12
12
|
}.freeze
|
|
13
13
|
|
|
14
|
-
self.site =
|
|
14
|
+
self.site = "https://redmine.renuo.ch"
|
|
15
15
|
self.include_root_in_json = true
|
|
16
16
|
|
|
17
17
|
def self.headers
|
|
18
|
-
{
|
|
18
|
+
{ "X-Redmine-API-Key" => RenuoCliConfig.redmine_api_key }
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def html_url
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative "command_helper"
|
|
4
4
|
|
|
5
5
|
# rubocop:disable Metrics/ClassLength
|
|
6
6
|
class ReleaseProject
|
|
@@ -31,20 +31,20 @@ class ReleaseProject
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def validate_project_name
|
|
34
|
-
abort(
|
|
34
|
+
abort(">> No project name given.") unless @project_name
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def validate_update_type
|
|
38
38
|
unless valid_update_type?
|
|
39
|
-
abort(
|
|
40
|
-
|
|
39
|
+
abort(">> Please provide the desired update type: major, minor, patch or custom. " \
|
|
40
|
+
"If you are unsure about the type please read https://semver.org")
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
if !custom_version? && @version
|
|
44
|
-
abort(
|
|
44
|
+
abort(">> Do not specify a version for a non-custom release. Given version will be ignored.")
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
abort(
|
|
47
|
+
abort(">> Please enter your desired version for the custom release.") if custom_version? && @version.nil?
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def valid_update_type?
|
|
@@ -58,20 +58,20 @@ class ReleaseProject
|
|
|
58
58
|
def validate_custom_version_format
|
|
59
59
|
return if @version.nil? || @version =~ RenuoVersion::SEMVER_SCHEMA
|
|
60
60
|
|
|
61
|
-
abort(
|
|
61
|
+
abort(">> Invalid Version Number. Use format X.Y.Z for your version.")
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def veto_comparison
|
|
65
|
-
abort unless agree(
|
|
65
|
+
abort unless agree("Are you fine with the changes you just reviewed in your browser?")
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def open_comparison_page
|
|
69
|
-
puts
|
|
69
|
+
puts "Opening browser to double-check what is going to be deployed…"
|
|
70
70
|
open_path "https://github.com/#{@project_name}/compare/#{main_branch}...develop"
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def checkout_project
|
|
74
|
-
abort(
|
|
74
|
+
abort(">> Project not found on Github.") unless system("#{MOVE_TO_TMP_FOLDER} && gh repo clone #{@project_name}")
|
|
75
75
|
|
|
76
76
|
system(cmd_in_folder("git checkout #{main_branch} && git pull origin #{main_branch} &&" \
|
|
77
77
|
"git checkout #{develop_branch} && git pull origin #{develop_branch}"))
|
|
@@ -92,10 +92,10 @@ class ReleaseProject
|
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
def current_version
|
|
95
|
-
@current_version ||= if `#{cmd_in_folder(
|
|
96
|
-
|
|
95
|
+
@current_version ||= if `#{cmd_in_folder("git tag")}` == ""
|
|
96
|
+
"0.0.0"
|
|
97
97
|
else
|
|
98
|
-
sorted_tags = `#{cmd_in_folder(
|
|
98
|
+
sorted_tags = `#{cmd_in_folder("git tag --sort=taggerdate")}`.split("\n").reverse
|
|
99
99
|
sorted_tags.find { |tag| tag =~ RenuoVersion::SEMVER_SCHEMA }.strip
|
|
100
100
|
end
|
|
101
101
|
end
|
|
@@ -105,14 +105,14 @@ class ReleaseProject
|
|
|
105
105
|
|
|
106
106
|
return unless version_bumped
|
|
107
107
|
|
|
108
|
-
system(cmd_in_folder(%(git add #{find_files_with_version.join(
|
|
108
|
+
system(cmd_in_folder(%(git add #{find_files_with_version.join(" ")} && git commit -m "Bump version")))
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
def find_and_replace_version
|
|
112
112
|
find_files_with_version.any? do |file_name|
|
|
113
113
|
puts "Replace the version in #{file_name}?"
|
|
114
114
|
print_version_found(file_name)
|
|
115
|
-
if agree(
|
|
115
|
+
if agree("confirm?")
|
|
116
116
|
bump_version_in_file(file_name)
|
|
117
117
|
true
|
|
118
118
|
else
|
|
@@ -122,7 +122,7 @@ class ReleaseProject
|
|
|
122
122
|
end
|
|
123
123
|
|
|
124
124
|
def find_files_with_version
|
|
125
|
-
excluded_dirs = %w[.git node_modules tmp].map { |dir| "--exclude-dir=#{dir}" }.join(
|
|
125
|
+
excluded_dirs = %w[.git node_modules tmp].map { |dir| "--exclude-dir=#{dir}" }.join(" ")
|
|
126
126
|
grep_current_version = "grep -rl -F #{excluded_dirs} --include='*.rb' #{current_version} ."
|
|
127
127
|
`#{cmd_in_folder(grep_current_version)}`.split("\n")
|
|
128
128
|
end
|
|
@@ -133,7 +133,7 @@ class ReleaseProject
|
|
|
133
133
|
|
|
134
134
|
def bump_version_in_file(file_name)
|
|
135
135
|
# Use `-i ''` for OS X and `-i` for GNU
|
|
136
|
-
args = "''" unless system(
|
|
136
|
+
args = "''" unless system("sed --version > /dev/null 2>&1")
|
|
137
137
|
|
|
138
138
|
system(cmd_in_folder("sed -i #{args} 's|#{current_version}|#{@version}|g' #{file_name}"))
|
|
139
139
|
end
|
|
@@ -150,7 +150,7 @@ class ReleaseProject
|
|
|
150
150
|
"GIT_MERGE_AUTOEDIT=no git checkout #{main_branch}",
|
|
151
151
|
"git merge #{develop_branch} --no-edit",
|
|
152
152
|
"git tag -a #{@version} -m \"Release with version: #{@version}\""
|
|
153
|
-
].join(
|
|
153
|
+
].join(" && ")
|
|
154
154
|
)
|
|
155
155
|
)
|
|
156
156
|
end
|
|
@@ -168,14 +168,14 @@ class ReleaseProject
|
|
|
168
168
|
def ask_for_final_confirmation
|
|
169
169
|
unless agree(">> Are you sure you wish to deploy '#{@project_name}' " \
|
|
170
170
|
"as a #{@update_type} release (#{current_version} => #{@version})?")
|
|
171
|
-
abort(
|
|
171
|
+
abort(">> Cancelling Release.")
|
|
172
172
|
end
|
|
173
173
|
|
|
174
174
|
return unless Time.current.friday? && Time.current.hour >= 16
|
|
175
175
|
|
|
176
|
-
unless agree(
|
|
177
|
-
|
|
178
|
-
abort(
|
|
176
|
+
unless agree(">> Are you sure you want to deploy on late Friday afternoon? " \
|
|
177
|
+
"Did you think about your family...waiting for you at home?")
|
|
178
|
+
abort(">> Very good. Go home now.")
|
|
179
179
|
end
|
|
180
180
|
end
|
|
181
181
|
|
|
@@ -188,7 +188,7 @@ class ReleaseProject
|
|
|
188
188
|
end
|
|
189
189
|
|
|
190
190
|
def folder_name
|
|
191
|
-
@project_name.split(
|
|
191
|
+
@project_name.split("/").last
|
|
192
192
|
end
|
|
193
193
|
|
|
194
194
|
def cleanup
|
|
@@ -197,11 +197,11 @@ class ReleaseProject
|
|
|
197
197
|
|
|
198
198
|
def main_branch
|
|
199
199
|
remote_repo = "git@github.com:#{@project_name}.git"
|
|
200
|
-
@main_branch ||= `git ls-remote --heads #{remote_repo} main`.empty? ?
|
|
200
|
+
@main_branch ||= `git ls-remote --heads #{remote_repo} main`.empty? ? "master" : "main"
|
|
201
201
|
end
|
|
202
202
|
|
|
203
203
|
def develop_branch
|
|
204
|
-
|
|
204
|
+
"develop"
|
|
205
205
|
end
|
|
206
206
|
end
|
|
207
207
|
# rubocop:enable Metrics/ClassLength
|
|
@@ -6,11 +6,11 @@ class ReleaseXing
|
|
|
6
6
|
|
|
7
7
|
def run
|
|
8
8
|
checkout_project
|
|
9
|
-
cmd_in_folder
|
|
10
|
-
cmd_in_folder
|
|
11
|
-
cmd_in_folder
|
|
12
|
-
cmd_in_folder
|
|
13
|
-
cmd_in_folder
|
|
9
|
+
cmd_in_folder "git remote add -f renuo git@github.com:renuo/xing-campaign.git"
|
|
10
|
+
cmd_in_folder "git pull"
|
|
11
|
+
cmd_in_folder "git fetch renuo develop"
|
|
12
|
+
cmd_in_folder "git subtree pull --prefix public renuo develop --squash"
|
|
13
|
+
cmd_in_folder "git push"
|
|
14
14
|
ensure
|
|
15
15
|
cleanup
|
|
16
16
|
end
|
|
@@ -7,7 +7,7 @@ class RenuoVersion
|
|
|
7
7
|
def self.create(str)
|
|
8
8
|
raise "Invalid segments (#{str} =~ #{SEMVER_SCHEMA})" unless SEMVER_SCHEMA.match?(str)
|
|
9
9
|
|
|
10
|
-
new(*str.split(
|
|
10
|
+
new(*str.split("."))
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
attr_reader :segments
|
|
@@ -30,7 +30,7 @@ class RenuoVersion
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def to_s
|
|
33
|
-
@segments.join(
|
|
33
|
+
@segments.join(".")
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
private
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
3
|
+
require "yaml"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
require "json"
|
|
6
6
|
|
|
7
|
-
CONFIG_FILE =
|
|
7
|
+
CONFIG_FILE = "config/1password-secrets.yml"
|
|
8
8
|
|
|
9
9
|
class SecretsFetcher
|
|
10
10
|
def run
|
|
11
|
-
system(
|
|
11
|
+
system("which op > /dev/null") || abort("op is not installed. Please install it (e.g. brew install 1password-cli).")
|
|
12
12
|
|
|
13
13
|
abort("Config file #{CONFIG_FILE} not found.") unless File.exist?(CONFIG_FILE)
|
|
14
14
|
config = YAML.load_file(CONFIG_FILE).deep_symbolize_keys
|
|
@@ -23,10 +23,10 @@ class SecretsFetcher
|
|
|
23
23
|
def elaborate_item(item) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
24
24
|
private_link = item[:private_link]
|
|
25
25
|
if private_link.nil?
|
|
26
|
-
warn
|
|
26
|
+
warn "Private link not found in your config file."
|
|
27
27
|
return
|
|
28
|
-
elsif private_link.
|
|
29
|
-
warn
|
|
28
|
+
elsif private_link.include?("share.1password.com")
|
|
29
|
+
warn "Please use a private link, not a share link."
|
|
30
30
|
return
|
|
31
31
|
end
|
|
32
32
|
|
|
@@ -44,13 +44,13 @@ class SecretsFetcher
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def process_env_variable(name, item_id, item_json)
|
|
47
|
-
env_json = item_json[
|
|
47
|
+
env_json = item_json["fields"].find { |field| field["label"] == name }
|
|
48
48
|
if env_json.nil?
|
|
49
49
|
warn "Field `#{name}` not found in item #{item_id}. Check the field name in your #{CONFIG_FILE} file."
|
|
50
50
|
else
|
|
51
|
-
value = env_json[
|
|
52
|
-
update_or_add_variable(
|
|
53
|
-
update_or_add_variable(
|
|
51
|
+
value = env_json["value"]
|
|
52
|
+
update_or_add_variable(".env", name, /^#{name}=/, "#{name}=#{value}")
|
|
53
|
+
update_or_add_variable("config/application.yml", name, /^#{name}:.*$/, "#{name}: \"#{value}\"")
|
|
54
54
|
|
|
55
55
|
end
|
|
56
56
|
end
|
|
@@ -62,7 +62,7 @@ class SecretsFetcher
|
|
|
62
62
|
updated_contents = file_contents
|
|
63
63
|
|
|
64
64
|
if file_contents.match(pattern)
|
|
65
|
-
if ask("Do you want to update the value of #{name} in #{file_path}? (y/n)",
|
|
65
|
+
if ask("Do you want to update the value of #{name} in #{file_path}? (y/n)", "y") == "y"
|
|
66
66
|
updated_contents = file_contents.gsub(pattern, replacement)
|
|
67
67
|
end
|
|
68
68
|
else
|
|
@@ -75,7 +75,7 @@ class SecretsFetcher
|
|
|
75
75
|
|
|
76
76
|
def get_item(item_id)
|
|
77
77
|
output = execute_command(command: "op item get #{item_id} --format json",
|
|
78
|
-
success_message:
|
|
78
|
+
success_message: "",
|
|
79
79
|
error_message: "Error fetching item #{item_id}." \
|
|
80
80
|
"Check `private_link` in your #{CONFIG_FILE} file.")
|
|
81
81
|
JSON.parse(output) if output
|
|
@@ -99,18 +99,18 @@ class SecretsFetcher
|
|
|
99
99
|
FileUtils.mkdir_p(output_folder)
|
|
100
100
|
output_path = File.join(output_folder, filename)
|
|
101
101
|
|
|
102
|
-
vault_id = item.dig(
|
|
103
|
-
download_file_from_item(item[
|
|
102
|
+
vault_id = item.dig("vault", "id")
|
|
103
|
+
download_file_from_item(item["files"], vault_id, item_id, filename, output_path)
|
|
104
104
|
puts "\n\n"
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
def download_file_from_item(files, vault_id, item_id, filename, output_path)
|
|
108
|
-
item_file = files&.find { |tmp_file_config| tmp_file_config[
|
|
108
|
+
item_file = files&.find { |tmp_file_config| tmp_file_config["name"].eql?(filename) }
|
|
109
109
|
if item_file.nil?
|
|
110
110
|
warn "File `#{filename}` not found in item #{item_id}. Check the file name in your #{CONFIG_FILE} file."
|
|
111
111
|
return
|
|
112
112
|
end
|
|
113
|
-
execute_command(command: "op read \"op://#{vault_id}/#{item_id}/#{item_file[
|
|
113
|
+
execute_command(command: "op read \"op://#{vault_id}/#{item_id}/#{item_file["id"]}\" --out-file #{output_path}",
|
|
114
114
|
success_message: "Successfully fetched #{filename} and saved to #{output_path}",
|
|
115
115
|
error_message: "Error fetching #{filename}.")
|
|
116
116
|
end
|
|
@@ -22,12 +22,12 @@ class CloudfrontConfigService
|
|
|
22
22
|
{
|
|
23
23
|
Id: "S3-#{@bucket}",
|
|
24
24
|
DomainName: "#{@bucket}.s3.amazonaws.com",
|
|
25
|
-
OriginPath:
|
|
25
|
+
OriginPath: "",
|
|
26
26
|
CustomHeaders: {
|
|
27
27
|
Quantity: 0
|
|
28
28
|
},
|
|
29
29
|
S3OriginConfig: {
|
|
30
|
-
OriginAccessIdentity:
|
|
30
|
+
OriginAccessIdentity: ""
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
]
|
|
@@ -37,7 +37,7 @@ class CloudfrontConfigService
|
|
|
37
37
|
ForwardedValues: {
|
|
38
38
|
QueryString: false,
|
|
39
39
|
Cookies: {
|
|
40
|
-
Forward:
|
|
40
|
+
Forward: "none"
|
|
41
41
|
},
|
|
42
42
|
Headers: {
|
|
43
43
|
Quantity: 0
|
|
@@ -50,7 +50,7 @@ class CloudfrontConfigService
|
|
|
50
50
|
Enabled: false,
|
|
51
51
|
Quantity: 0
|
|
52
52
|
},
|
|
53
|
-
ViewerProtocolPolicy:
|
|
53
|
+
ViewerProtocolPolicy: "redirect-to-https",
|
|
54
54
|
MinTTL: 0,
|
|
55
55
|
AllowedMethods: {
|
|
56
56
|
Quantity: 2,
|
|
@@ -80,28 +80,28 @@ class CloudfrontConfigService
|
|
|
80
80
|
CustomErrorResponses: {
|
|
81
81
|
Quantity: 0
|
|
82
82
|
},
|
|
83
|
-
Comment:
|
|
83
|
+
Comment: "",
|
|
84
84
|
Logging: {
|
|
85
85
|
Enabled: false,
|
|
86
86
|
IncludeCookies: false,
|
|
87
|
-
Bucket:
|
|
88
|
-
Prefix:
|
|
87
|
+
Bucket: "",
|
|
88
|
+
Prefix: ""
|
|
89
89
|
},
|
|
90
|
-
PriceClass:
|
|
90
|
+
PriceClass: "PriceClass_100",
|
|
91
91
|
Enabled: true,
|
|
92
92
|
ViewerCertificate: {
|
|
93
93
|
CloudFrontDefaultCertificate: true,
|
|
94
|
-
MinimumProtocolVersion:
|
|
95
|
-
CertificateSource:
|
|
94
|
+
MinimumProtocolVersion: "TLSv1.2_2018",
|
|
95
|
+
CertificateSource: "cloudfront"
|
|
96
96
|
},
|
|
97
97
|
Restrictions: {
|
|
98
98
|
GeoRestriction: {
|
|
99
|
-
RestrictionType:
|
|
99
|
+
RestrictionType: "none",
|
|
100
100
|
Quantity: 0
|
|
101
101
|
}
|
|
102
102
|
},
|
|
103
|
-
WebACLId:
|
|
104
|
-
HttpVersion:
|
|
103
|
+
WebACLId: "",
|
|
104
|
+
HttpVersion: "http2",
|
|
105
105
|
IsIPV6Enabled: true
|
|
106
106
|
},
|
|
107
107
|
Tags: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "redcarpet"
|
|
4
4
|
|
|
5
5
|
class MarkdownParserService
|
|
6
6
|
class ListExtractor < Redcarpet::Render::Base
|
|
@@ -8,7 +8,7 @@ class MarkdownParserService
|
|
|
8
8
|
|
|
9
9
|
def list(_contents, _list_type)
|
|
10
10
|
@next_is_hint = true
|
|
11
|
-
|
|
11
|
+
""
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def list_item(text, _list_type)
|
|
@@ -19,7 +19,7 @@ class MarkdownParserService
|
|
|
19
19
|
else
|
|
20
20
|
@files << [text.strip]
|
|
21
21
|
end
|
|
22
|
-
|
|
22
|
+
""
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "yaml"
|
|
4
4
|
|
|
5
5
|
class RenuoCliConfig
|
|
6
|
-
CONFIG_FILE_PATH = "#{File.expand_path(
|
|
6
|
+
CONFIG_FILE_PATH = "#{File.expand_path("~")}/.renuo_cli".freeze
|
|
7
7
|
|
|
8
8
|
class << self
|
|
9
9
|
def redmine_api_key
|
|
10
|
-
get_config_value(
|
|
10
|
+
get_config_value("REDMINE_API_KEY", "https://redmine.renuo.ch/my/account")
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def toggl_api_token
|
|
14
|
-
get_config_value(
|
|
14
|
+
get_config_value("TOGGL_API_TOKEN", "https://toggl.com/app/profile")
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
private
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "net/http"
|
|
4
|
+
require "json"
|
|
5
5
|
|
|
6
6
|
class SetupUptimerobot
|
|
7
|
-
CONTACT_GROUP_IDS =
|
|
7
|
+
CONTACT_GROUP_IDS = "2811620_0_0-2806053_0_0"
|
|
8
8
|
HTTPS_MONITORING = 1
|
|
9
9
|
STATUS_PAUSED = 0
|
|
10
10
|
|
|
11
11
|
def initialize(args)
|
|
12
|
-
abort(
|
|
12
|
+
abort("No project name given.") if args.nil?
|
|
13
13
|
@api_key = ask_for_api_key
|
|
14
14
|
@url = validate_url(args)
|
|
15
15
|
end
|
|
@@ -17,21 +17,21 @@ class SetupUptimerobot
|
|
|
17
17
|
def run
|
|
18
18
|
robot_obj = monitoring_call(:new, create_robot_params)
|
|
19
19
|
validate_new_project(robot_obj)
|
|
20
|
-
response = monitoring_call(:edit, edit_robot_params(robot_obj[
|
|
20
|
+
response = monitoring_call(:edit, edit_robot_params(robot_obj["monitor"]["id"]))
|
|
21
21
|
final_command_status(response)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
private
|
|
25
25
|
|
|
26
26
|
def ask_for_api_key
|
|
27
|
-
say
|
|
28
|
-
say
|
|
29
|
-
ask(
|
|
27
|
+
say "This command will configure uptimerobot for your project."
|
|
28
|
+
say "Please give in the api_key for uptimerobot"
|
|
29
|
+
ask("API-key: ")
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def validate_url(args)
|
|
33
|
-
abort(
|
|
34
|
-
abort(
|
|
33
|
+
abort("The url to be monitored was not given") if args.first.nil?
|
|
34
|
+
abort("The url is invalid") unless args.first&.match?(URI::DEFAULT_PARSER.make_regexp)
|
|
35
35
|
URI.parse(args.first)
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -50,19 +50,19 @@ class SetupUptimerobot
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def final_command_status(response)
|
|
53
|
-
if response[
|
|
54
|
-
say
|
|
55
|
-
say
|
|
56
|
-
say
|
|
53
|
+
if response["stat"] == "ok"
|
|
54
|
+
say "Successfully configured uptimerobot 🤩😎👍"
|
|
55
|
+
say "The status for the monitored project has paused for now..."
|
|
56
|
+
say "You can start it once your app is ready to go live 🤠"
|
|
57
57
|
else
|
|
58
|
-
say "Something went wrong during the configuration...😕. Uptimerobot returned '#{response[
|
|
58
|
+
say "Something went wrong during the configuration...😕. Uptimerobot returned '#{response["error"]["message"]}'"
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
def validate_new_project(robot_obj)
|
|
63
|
-
return if robot_obj[
|
|
63
|
+
return if robot_obj["stat"] == "ok"
|
|
64
64
|
|
|
65
|
-
abort("An error occoured. Uptimerobot returned '#{robot_obj[
|
|
65
|
+
abort("An error occoured. Uptimerobot returned '#{robot_obj["error"]["message"]}'")
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def https_request(path, params = {})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "active_resource"
|
|
4
4
|
|
|
5
5
|
module Toggl
|
|
6
6
|
module CustomJsonFormat
|
|
@@ -11,13 +11,13 @@ module Toggl
|
|
|
11
11
|
# rubocop:enable Style/ModuleFunction
|
|
12
12
|
|
|
13
13
|
def decode(json)
|
|
14
|
-
ActiveSupport::JSON.decode(json)[
|
|
14
|
+
ActiveSupport::JSON.decode(json)["data"]
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
class Detail < ActiveResource::Base
|
|
19
19
|
self.format = CustomJsonFormat
|
|
20
|
-
self.site =
|
|
20
|
+
self.site = "https://toggl.com/reports/api/v2"
|
|
21
21
|
self.include_root_in_json = true
|
|
22
22
|
self.include_format_in_path = false
|
|
23
23
|
|
|
@@ -26,7 +26,7 @@ module Toggl
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def self.password
|
|
29
|
-
|
|
29
|
+
"api_token"
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
end
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "active_resource"
|
|
4
4
|
|
|
5
5
|
module Toggl
|
|
6
6
|
class TimeEntry < ActiveResource::Base
|
|
7
|
-
self.site =
|
|
7
|
+
self.site = "https://www.toggl.com/api/v8/"
|
|
8
8
|
self.include_root_in_json = true
|
|
9
9
|
self.include_format_in_path = false
|
|
10
10
|
|
|
@@ -13,11 +13,11 @@ module Toggl
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def self.password
|
|
16
|
-
|
|
16
|
+
"api_token"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def self.current
|
|
20
|
-
data = get(:current)[
|
|
20
|
+
data = get(:current)["data"]
|
|
21
21
|
data ? new(data) : nil
|
|
22
22
|
end
|
|
23
23
|
|