hephaestus 0.8.11 → 0.8.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/CHANGELOG.md +12 -0
  4. data/README.md +3 -1
  5. data/bin/hephaestus +37 -19
  6. data/lib/hephaestus/app_builder.rb +23 -145
  7. data/lib/hephaestus/app_name.rb +33 -0
  8. data/lib/hephaestus/generators/app_generator.rb +79 -75
  9. data/lib/hephaestus/generators/base.rb +0 -1
  10. data/lib/hephaestus/generators/config_generator.rb +3 -114
  11. data/lib/hephaestus/generators/core_generator.rb +18 -58
  12. data/lib/hephaestus/generators/db_generator.rb +12 -0
  13. data/lib/hephaestus/generators/deployment_generator.rb +3 -8
  14. data/lib/hephaestus/generators/lib_generator.rb +0 -10
  15. data/lib/hephaestus/generators/license_generator.rb +4 -1
  16. data/lib/hephaestus/generators/rubocop_generator.rb +1 -1
  17. data/lib/hephaestus/version.rb +1 -1
  18. data/lib/hephaestus.rb +2 -1
  19. data/templates/Dockerfile +7 -75
  20. data/templates/Gemfile +73 -0
  21. data/templates/Procfile +2 -0
  22. data/templates/app/controllers/app_controller.rb.tt +35 -0
  23. data/templates/app/controllers/application_controller.rb +1 -7
  24. data/templates/app/controllers/concerns/authable.rb.tt +50 -0
  25. data/templates/app/controllers/settings_controller.rb +5 -28
  26. data/templates/app/controllers/yetto_controller.rb +9 -10
  27. data/templates/app/lib/body_parameter/yetto_parameters.rb +8 -29
  28. data/templates/app/lib/{constants/app.rb → constants.rb} +1 -3
  29. data/templates/app/services/{http_service.rb → app_service.rb.tt} +6 -6
  30. data/templates/app/views/settings/new.json.jbuilder.tt +18 -0
  31. data/templates/bin/bundle +115 -0
  32. data/templates/bin/docker-entrypoint +20 -10
  33. data/templates/bin/foreman +27 -0
  34. data/templates/bin/jobs +7 -0
  35. data/templates/bin/rails +6 -0
  36. data/templates/bin/rake +6 -0
  37. data/templates/bin/setup +28 -0
  38. data/templates/bin/tapioca +27 -0
  39. data/templates/config/application.rb.tt +36 -0
  40. data/templates/config/boot.rb +7 -0
  41. data/templates/config/environment.rb +8 -0
  42. data/templates/config/environments/blank.rb +7 -0
  43. data/templates/config/initializers/environment.rb +2 -36
  44. data/templates/config/locales/en.yml +5 -31
  45. data/templates/config/puma.rb +5 -0
  46. data/templates/config/routes.rb.tt +28 -0
  47. data/templates/config.ru +9 -0
  48. data/templates/db/queue_schema.rb +132 -0
  49. data/templates/db/schema.rb +17 -0
  50. data/templates/hephaestus_env.sample +12 -0
  51. data/templates/hephaestus_github/dependabot.yml +27 -0
  52. data/templates/hephaestus_github/workflows/automerge.yml +14 -0
  53. data/templates/hephaestus_github/workflows/deploy.yml +30 -0
  54. data/templates/hephaestus_github/workflows/licenses.yml +17 -0
  55. data/templates/hephaestus_github/workflows/lint.yml +17 -0
  56. data/templates/hephaestus_github/workflows/security.yml +19 -0
  57. data/templates/hephaestus_github/workflows/sorbet.yml +19 -0
  58. data/templates/hephaestus_github/workflows/test.yml.tt +21 -0
  59. data/templates/hephaestus_github/workflows/updater.yml +18 -0
  60. data/templates/hephaestus_vscode/extensions.json +9 -0
  61. data/templates/hephaestus_vscode/launch.json +13 -0
  62. data/templates/hephaestus_vscode/settings.json +58 -0
  63. data/templates/lib/schemas/api/2023-03-06/components/parameters/headers/yetto.json +42 -0
  64. data/templates/lib/schemas/api/2023-03-06/components/parameters/plugInstallation.json +12 -0
  65. data/templates/lib/schemas/api/2023-03-06/components/schemas/plug.json +9 -0
  66. data/templates/lib/schemas/api/2023-03-06/components/schemas/responses.json +64 -0
  67. data/templates/lib/schemas/api/2023-03-06/components/schemas/yetto.json +116 -0
  68. data/templates/lib/schemas/api/2023-03-06/openapi.json +30 -0
  69. data/templates/lib/schemas/api/2023-03-06/paths/app.json +90 -0
  70. data/templates/lib/schemas/api/2023-03-06/paths/yetto/message_created.json +51 -0
  71. data/templates/lib/schemas/api/2023-03-06/paths/yetto/plug_installation_created.json +51 -0
  72. data/templates/script/docker-build-prod.tt +11 -0
  73. data/templates/script/docker-run.tt +8 -0
  74. data/templates/script/edit-credentials +12 -3
  75. data/templates/script/hmac_text +1 -1
  76. data/templates/script/ngrok.tt +7 -0
  77. data/templates/script/server +6 -45
  78. data/templates/test/controllers/app_controller_test.rb.tt +188 -0
  79. data/templates/test/controllers/settings_controller_test.rb.tt +125 -0
  80. data/templates/test/controllers/yetto_controller_test.rb +100 -71
  81. data/templates/test/fixtures/files/plug_installation_settings/valid.json +1 -1
  82. data/templates/test/support/rails.rb +16 -36
  83. data/templates/test/support/webmocks/app_webmock.rb.tt +29 -0
  84. data/templates/test/test_helper.rb +1 -31
  85. data/templates/vendor/fly/{fly-production.toml → fly-production.toml.tt} +24 -11
  86. data/templates/vendor/fly/{fly-staging.toml → fly-staging.toml.tt} +18 -15
  87. metadata +59 -72
  88. data/lib/hephaestus/exit_on_failure.rb +0 -22
  89. data/templates/Gemfile.erb +0 -120
  90. data/templates/Procfile.debug +0 -2
  91. data/templates/Procfile.dev +0 -2
  92. data/templates/app/controllers/app_controller.rb +0 -72
  93. data/templates/app/controllers/concerns/authable.rb +0 -50
  94. data/templates/app/controllers/staff_controller.rb +0 -15
  95. data/templates/app/jobs/update_yetto_job.rb +0 -26
  96. data/templates/app/lib/headers/yetto.rb +0 -19
  97. data/templates/app/lib/headers.rb +0 -5
  98. data/templates/app/lib/path_parameter/settings_parameters.rb +0 -22
  99. data/templates/app/lib/path_parameter/yetto_parameters.rb +0 -28
  100. data/templates/app/lib/path_parameter.rb +0 -8
  101. data/templates/app/lib/plug_app/http.rb +0 -37
  102. data/templates/app/lib/plug_app/middleware/malformed_request.rb +0 -110
  103. data/templates/app/lib/plug_app/middleware/openapi_validation.rb +0 -83
  104. data/templates/app/lib/plug_app/middleware/tracing_attributes.rb +0 -46
  105. data/templates/app/lib/query_parameter.rb +0 -6
  106. data/templates/app/serializers/error_serializer.rb +0 -16
  107. data/templates/app/services/yetto_service.rb +0 -51
  108. data/templates/app/views/settings/new.json.jbuilder +0 -21
  109. data/templates/compose.yml +0 -5
  110. data/templates/config/initializers/000-oj.rb +0 -6
  111. data/templates/config/initializers/cors.rb +0 -19
  112. data/templates/config/initializers/filter_parameter_logging.rb +0 -25
  113. data/templates/config/initializers/inflections.rb +0 -20
  114. data/templates/config/initializers/lograge.rb +0 -25
  115. data/templates/config/initializers/opentelemetry.rb +0 -32
  116. data/templates/config/initializers/sidekiq.rb +0 -11
  117. data/templates/config/initializers/slack_webhook_logger.rb +0 -17
  118. data/templates/config/sidekiq.yml +0 -20
  119. data/templates/script/ngrok +0 -5
  120. data/templates/test/controllers/settings_controller_test.rb +0 -27
  121. data/templates/test/fixtures/plug_installation_settings/invalid.json +0 -3
  122. data/templates/test/fixtures/plug_installation_settings/valid.json +0 -3
  123. data/templates/test/jobs/update_yetto_job_test.rb +0 -26
  124. data/templates/test/support/api.rb +0 -76
  125. data/templates/test/support/webmocks/slack_webmock.rb +0 -24
  126. data/templates/test/support/webmocks/yetto_webmock.rb +0 -119
  127. data/templates/test/support/webmocks.rb +0 -5
@@ -1,19 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- module Headers
5
- module Yetto
6
- YETTO_DELIVERY_ID = "HTTP_X_YETTO_DELIVERY_ID"
7
-
8
- HEADER_EVENT = "HTTP_X_YETTO_EVENT"
9
- EVENT_AFTER_CREATE = "created"
10
- EVENT_AFTER_UPDATE = "updated"
11
- EVENT_AFTER_DESTROY = "destroyed"
12
-
13
- HEADER_RECORD_TYPE = "HTTP_X_YETTO_RECORD_TYPE"
14
- RECORD_TYPE_PLUG_INSTALLATION = "plug_installation"
15
- RECORD_TYPE_MESSAGE = "message"
16
-
17
- HEADER_SIGNATURE = "HTTP_X_YETTO_SIGNATURE"
18
- end
19
- end
@@ -1,5 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- module Headers
5
- end
@@ -1,22 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- module PathParameter
5
- module SettingsParameters
6
- extend T::Sig
7
-
8
- sig { returns(String) }
9
- def pparam_plug_installation_id
10
- yetto_path_params.fetch(:event, "")
11
- end
12
-
13
- sig { returns(T::Hash[Symbol, T.untyped]) }
14
- def settings_path_params
15
- return {} if params.blank?
16
-
17
- {
18
- plug_installation_id: params.fetch(:plug_installation_id, ""),
19
- }
20
- end
21
- end
22
- end
@@ -1,28 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- module PathParameter
5
- module YettoParameters
6
- extend T::Sig
7
-
8
- sig { returns(String) }
9
- def pparam_yetto_event
10
- yetto_path_params.fetch(:event, "")
11
- end
12
-
13
- sig { returns(String) }
14
- def pparam_yetto_record_type
15
- yetto_path_params.fetch(:record_type, "")
16
- end
17
-
18
- sig { returns(T::Hash[String, String]) }
19
- def yetto_path_params
20
- return {} if path_parameters.blank?
21
-
22
- {
23
- event: path_parameters.fetch(:event, ""),
24
- record_type: path_parameters.fetch(:record_type, ""),
25
- }
26
- end
27
- end
28
- end
@@ -1,8 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module PathParameter
5
- extend T::Sig
6
-
7
- delegate :path_parameters, to: :request
8
- end
@@ -1,37 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module PlugApp
5
- module HTTP
6
- extend T::Sig
7
-
8
- OK = "OK"
9
- OK_I = 200
10
-
11
- CREATED = "Created"
12
- CREATED_I = 201
13
- NO_CONTENT = "No Content"
14
- NO_CONTENT_I = 204
15
-
16
- FOUND = "Found"
17
- FOUND_I = 302
18
-
19
- NOT_FOUND = "Not Found"
20
- NOT_FOUND_I = 404
21
- BAD_REQUEST = "Bad Request"
22
- BAD_REQUEST_I = 400
23
- UNAUTHORIZED = "Unauthorized"
24
- UNAUTHORIZED_I = 401
25
- FORBIDDEN = "Forbidden"
26
- FORBIDDEN_I = 403
27
- NOT_ACCEPTABLE = "Not Acceptable"
28
- NOT_ACCEPTABLE_I = 406
29
- SERVICE_UNAVAILABLE = "Service Unavailable"
30
- SERVICE_UNAVAILABLE_I = 503
31
-
32
- sig { params(status: Integer).returns(T::Boolean) }
33
- def status_ok?(status)
34
- status == OK_I
35
- end
36
- end
37
- end
@@ -1,110 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module PlugApp
5
- module Middleware
6
- # There is no valid reason for a request to contain a malformed string
7
- # so just return HTTP 400 (Bad Request) if we receive one
8
- class MalformedRequest
9
- extend T::Sig
10
-
11
- include ActionController::HttpAuthentication::Basic
12
-
13
- NULL_BYTE_REGEX = T.let(Regexp.new(Regexp.escape("\u0000")).freeze, Regexp)
14
-
15
- sig { returns(T.untyped) }
16
- attr_reader :app
17
-
18
- sig { params(app: T.untyped).void }
19
- def initialize(app)
20
- @app = T.let(app, T.untyped)
21
- end
22
-
23
- sig { params(env: T.untyped).returns(T.untyped) }
24
- def call(env)
25
- return [PlugApp::HTTP::BAD_REQUEST_I, { "Content-Type" => "text/plain" }, [PlugApp::HTTP::BAD_REQUEST]] if request_contains_malformed_string?(env)
26
-
27
- app.call(env)
28
- end
29
-
30
- private
31
-
32
- sig { params(env: T.untyped).returns(T::Boolean) }
33
- def request_contains_malformed_string?(env)
34
- # Duplicate the env, so it is not modified when accessing the parameters
35
- # https://github.com/rails/rails/blob/34991a6ae2fc68347c01ea7382fa89004159e019/actionpack/lib/action_dispatch/http/parameters.rb#L59
36
- request = ActionDispatch::Request.new(env.dup)
37
-
38
- return true if malformed_path?(request.path)
39
- return true if credentials_malformed?(request)
40
-
41
- request.params.values.any? do |value|
42
- param_has_null_byte?(value)
43
- end
44
- rescue ActionController::BadRequest
45
- # If we can't build an ActionDispatch::Request something's wrong
46
- # This would also happen if `#params` contains invalid UTF-8
47
- # in this case we'll return a 400
48
- true
49
- end
50
-
51
- sig { params(path: String).returns(T::Boolean) }
52
- def malformed_path?(path)
53
- string_malformed?(Rack::Utils.unescape(path))
54
- rescue ArgumentError
55
- # Rack::Utils.unescape raised this, path is malformed.
56
- true
57
- end
58
-
59
- sig { params(request: T.untyped).returns(T::Boolean) }
60
- def credentials_malformed?(request)
61
- credentials = if has_basic_credentials?(request)
62
- decode_credentials(request).presence
63
- else
64
- request.authorization.presence
65
- end
66
-
67
- return false unless credentials
68
-
69
- string_malformed?(credentials)
70
- end
71
-
72
- sig { params(value: T.untyped, depth: Integer).returns(T::Boolean) }
73
- def param_has_null_byte?(value, depth = 0)
74
- # Guard against possible attack sending large amounts of nested params
75
- # Should be safe as deeply nested params are highly uncommon.
76
- return false if depth > 2
77
-
78
- depth += 1
79
-
80
- if value.respond_to?(:match)
81
- string_malformed?(value)
82
- elsif value.respond_to?(:values)
83
- value.values.any? do |hash_value|
84
- param_has_null_byte?(hash_value, depth)
85
- end
86
- elsif value.is_a?(Array)
87
- value.any? do |array_value|
88
- param_has_null_byte?(array_value, depth)
89
- end
90
- else
91
- false
92
- end
93
- end
94
-
95
- sig { params(string: String).returns(T::Boolean) }
96
- def string_malformed?(string)
97
- # We're using match instead of include because that raises an ArgumentError
98
- # when the string contains invalid UTF-8
99
- #
100
- # We try to encode the string from ASCII-8BIT to UTF8. If we failed to do
101
- # so for certain characters in the string, those chars are probably incomplete
102
- # multibyte characters.
103
- string.dup.force_encoding(Encoding::UTF_8).match?(NULL_BYTE_REGEX)
104
- rescue ArgumentError, Encoding::UndefinedConversionError
105
- # If we're here, we caught a malformed string. Return true
106
- true
107
- end
108
- end
109
- end
110
- end
@@ -1,83 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- require "openapi_first"
5
-
6
- module PlugApp
7
- module Middleware
8
- class OpenapiValidation
9
- API_PATH_PREFIX = "/api/"
10
- SPEC_PATH = Rails.root.join("lib/plug_app/schemas/api/2023-03-06/openapi.json")
11
- SPEC = OpenapiFirst.load(SPEC_PATH)
12
-
13
- def initialize(app)
14
- @app = app
15
- end
16
-
17
- def call(env)
18
- request = Rack::Request.new(env)
19
-
20
- return @app.call(env) unless request.path.starts_with?(API_PATH_PREFIX) && request.path.exclude?("/settings")
21
-
22
- begin
23
- # force content-type to JSON
24
- env["CONTENT_TYPE"] = "application/json" if env["CONTENT_TYPE"] != "application/json"
25
-
26
- validated_request = SPEC.validate_request(request)
27
-
28
- return @app.call(env) if validated_request.valid?
29
-
30
- case validated_request.error
31
- when OpenapiFirst::Schema::ValidationError
32
- error_arr = format_arr(validated_request.error.errors.map(&:message))
33
- Rails.logger.error(error_arr) if print_user_api_errors?
34
- [PlugApp::HTTP::BAD_REQUEST_I, { "Content-Type" => "application/json" }, [error_arr]]
35
- else
36
- case validated_request.error.type
37
- when :not_found
38
- [PlugApp::HTTP::NOT_FOUND_I, { "Content-Type" => "application/json" }, [format_str("Not Found")]]
39
- else
40
- error_message = if validated_request.error.errors.present?
41
- format_arr(validated_request.error.errors.map(&:message))
42
- else
43
- format_str(validated_request.error.message)
44
- end
45
-
46
- Rails.logger.error(error_message) if print_user_api_errors?
47
- [PlugApp::HTTP::BAD_REQUEST_I, { "Content-Type" => "application/json" }, [error_message]]
48
- end
49
- end
50
- rescue StandardError => e
51
- raise e unless Rails.env.production?
52
-
53
- logger.error(
54
- "openapi.request_validation.error",
55
- path: request.path,
56
- method: request.env["REQUEST_METHOD"],
57
- error_message: e.message,
58
- )
59
- end
60
- end
61
-
62
- private def format_str(error)
63
- {
64
- errors: [
65
- {
66
- message: error,
67
- },
68
- ],
69
- }.to_json
70
- end
71
-
72
- private def format_arr(errors)
73
- {
74
- errors: errors.each_with_object([]) do |error, arr|
75
- arr << {
76
- message: error,
77
- }
78
- end,
79
- }.to_json
80
- end
81
- end
82
- end
83
- end
@@ -1,46 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- require "openapi_first"
5
- require "active_support/parameter_filter"
6
-
7
- module PlugApp
8
- module Middleware
9
- class TracingAttributes
10
- extend T::Sig
11
-
12
- sig { returns(T.untyped) }
13
- attr_reader :app
14
-
15
- HTTP_REQUEST_BODY = "http.request.body"
16
- PLUG_APP_PATH_PREFIX = "/app/"
17
- RACK_REQUEST_BODY = "rack.input"
18
-
19
- sig { params(app: T.untyped).void }
20
- def initialize(app)
21
- @app = T.let(app, T.untyped)
22
- @filterer = ActiveSupport::ParameterFilter.new(Rails.application.config.filter_parameters)
23
- end
24
-
25
- sig { params(env: T.untyped).returns(T.untyped) }
26
- def call(env)
27
- OpenTelemetry::Trace.current_span.add_attributes({
28
- OpenTelemetry::VERSION => PlugApp::Application::GIT_SHA,
29
- OpenTelemetry::SemanticConventions::Trace::HTTP_REQUEST_CONTENT_LENGTH => env["CONTENT_LENGTH"].to_i,
30
- HTTP_REQUEST_BODY => filtered_params(env),
31
- })
32
-
33
- app.call(env)
34
- end
35
-
36
- def filtered_params(env)
37
- body = env[RACK_REQUEST_BODY]&.read
38
- return "{}" if body.blank? || body == "{}"
39
-
40
- @filterer.filter(JSON.parse(body)).to_json
41
- ensure
42
- env[RACK_REQUEST_BODY]&.try(:rewind)
43
- end
44
- end
45
- end
46
- end
@@ -1,6 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module QueryParameter
5
- extend T::Sig
6
- end
@@ -1,16 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- class ErrorSerializer
5
- class << self
6
- def format(message)
7
- {
8
- errors: [
9
- {
10
- message: message,
11
- },
12
- ],
13
- }.to_json
14
- end
15
- end
16
- end
@@ -1,51 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- class YettoService
5
- cattr_reader :yetto_client, instance_accessor: false do
6
- Httpsensible::Client.new(user_agent: "PlugApp/#{PlugApp::Application::GIT_SHA}")
7
- end
8
-
9
- # explicitly different than what's in environment.rb, because local
10
- # Yetto expects HTTP; environment.rb can use HTTPS because it passes through ngrok.io
11
- PROTOCOL = Rails.env.development? ? "http" : "https"
12
- YETTO_API_VERSION_TLD = "#{PROTOCOL}://#{YETTO_API_TLD}/#{YETTO_API_VERSION}"
13
- JWT_ALGORITHM = "RS256"
14
-
15
- class << self
16
- def perform_token_exchange(plug_installation_id)
17
- encoded_jwt = Httpsensible::JWT.encode_jwt(Hephaestus::YETTO_PLUG_PEM, Hephaestus::YETTO_PLUG_ID)
18
- response = yetto_client.with_headers({ "Authorization" => "Bearer #{encoded_jwt}" }).post("#{YETTO_API_VERSION_TLD}/plug/installations/#{plug_installation_id}/access_tokens")
19
- body = response.parsed_json_body
20
- body["token"]
21
- end
22
-
23
- def get_plug_installation(plug_installation_id)
24
- token = perform_token_exchange(plug_installation_id)
25
- yetto_client.with_headers("Authorization" => "Bearer #{token}").get("#{YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}")
26
- end
27
-
28
- def update_plug_installation(plug_installation_id, params)
29
- plug_installation = {}
30
- plug_installation[:settings] = params.fetch(:settings, {})
31
- plug_installation[:credentials] = params.fetch(:credentials, {})
32
-
33
- token = perform_token_exchange(plug_installation_id)
34
- yetto_client.with_headers("Authorization" => "Bearer #{token}").patch("#{YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}", json: plug_installation)
35
- end
36
-
37
- def update_message(plug_installation_id, message_id, params)
38
- payload = params[:payload]
39
- token = perform_token_exchange(plug_installation_id)
40
-
41
- yetto_client.with_headers("Authorization" => "Bearer #{token}").patch("#{YETTO_API_VERSION_TLD}/messages/#{message_id}", json: payload)
42
- end
43
-
44
- def create_message_reply(message_id, plug_installation_id, params)
45
- payload = params[:payload]
46
- token = perform_token_exchange(plug_installation_id)
47
-
48
- yetto_client.with_headers("Authorization" => "Bearer #{token}").post("#{YETTO_API_VERSION_TLD}/messages/#{message_id}/replies", json: payload)
49
- end
50
- end
51
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- json.version("2023-03-06")
4
- json.settings do
5
- json.array!([
6
- {
7
- component: "text_field",
8
- name: "from_name",
9
- heading: t(:some_example_heading),
10
- placeholder: "{{ organization['name'] }} - {{ inbox['name'] }}",
11
- label: t(:some_example),
12
- },
13
- {
14
- component: "email_field",
15
- name: "reply_to_email",
16
- heading: t(:another_example_heading),
17
- placeholder: "{{ inbox['slug'] }}@{{ organization['name'] | downcase }}.biz",
18
- label: t(:another_example_label),
19
- },
20
- ])
21
- end
@@ -1,5 +0,0 @@
1
- services:
2
- redis-db:
3
- image: redis:7-bookworm
4
- ports:
5
- - "6402:6402"
@@ -1,6 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- Oj.default_options = { mode: :rails }
5
-
6
- Oj.optimize_rails
@@ -1,19 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- # Be sure to restart your server when you modify this file.
5
-
6
- # Avoid CORS issues when API is called from the frontend app.
7
- # Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.
8
-
9
- # Read more: https://github.com/cyu/rack-cors
10
-
11
- # Rails.application.config.middleware.insert_before 0, Rack::Cors do
12
- # allow do
13
- # origins "example.com"
14
- #
15
- # resource "*",
16
- # headers: :any,
17
- # methods: [:get, :post, :put, :patch, :delete, :options, :head]
18
- # end
19
- # end
@@ -1,25 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- # Be sure to restart your server when you modify this file.
5
-
6
- # Configure parameters to be filtered from the log file. Use this to limit dissemination of
7
- # sensitive information. See the ActiveSupport::ParameterFilter documentation for supported
8
- # notations and behaviors.
9
- Rails.application.config.filter_parameters += [
10
- :passw,
11
- :secret,
12
- :token,
13
- :_key,
14
- :crypt,
15
- :salt,
16
- :certificate,
17
- :otp,
18
- :ssn,
19
- :credentials,
20
- :state,
21
- :access_token,
22
- :refresh_token,
23
- :html_content,
24
- :text_content,
25
- ]
@@ -1,20 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- # Be sure to restart your server when you modify this file.
5
-
6
- # Add new inflection rules using the following format. Inflections
7
- # are locale specific, and you may define rules for as many different
8
- # locales as you wish. All of these examples are active by default:
9
- # ActiveSupport::Inflector.inflections(:en) do |inflect|
10
- # inflect.plural /^(ox)$/i, "\\1en"
11
- # inflect.singular /^(ox)en/i, "\\1"
12
- # inflect.irregular "person", "people"
13
- # inflect.uncountable %w( fish sheep )
14
- # end
15
-
16
- # These inflection rules are supported but not enabled by default:
17
- ActiveSupport::Inflector.inflections(:en) do |inflect|
18
- inflect.acronym("API")
19
- inflect.acronym("HTTP")
20
- end
@@ -1,25 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- Rails.application.configure do
5
- config.lograge.enabled = true
6
- config.lograge.custom_options = lambda do |event|
7
- span = OpenTelemetry::Trace.current_span
8
- {
9
- time: event.time,
10
- trace_id: span.context.hex_trace_id,
11
- span_id: span.context.hex_span_id,
12
- }
13
- end
14
-
15
- config.lograge.custom_payload do |controller|
16
- payload = {
17
- host: controller.request.host,
18
- }
19
-
20
- payload
21
- end
22
-
23
- config.lograge.keep_original_rails_log = true
24
- config.lograge.logger = ActiveSupport::Logger.new(Rails.root.join("log", "lograge_#{Rails.env}.log"))
25
- end
@@ -1,32 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- unless Rails.env.development?
5
- # establish the environment for OTEL
6
- ENV["OTEL_EXPORTER_OTLP_ENDPOINT"] = Rails.application.credentials.fetch(:OTEL_EXPORTER_OTLP_ENDPOINT, ENV.fetch("OTEL_EXPORTER_OTLP_ENDPOINT", "https://api.honeycomb.io"))
7
- ENV["OTEL_EXPORTER_OTLP_HEADERS"] = Rails.application.credentials.fetch(:OTEL_EXPORTER_OTLP_HEADERS, ENV.fetch("OTEL_EXPORTER_OTLP_HEADERS", "x-honeycomb-team=your-api-key"))
8
- ENV["OTEL_SERVICE_NAME"] = Rails.application.credentials.fetch(:OTEL_SERVICE_NAME, ENV.fetch("OTEL_SERVICE_NAME", "your-service-name"))
9
-
10
- require "opentelemetry/sdk"
11
- require "opentelemetry/semantic_conventions"
12
-
13
- OpenTelemetry::SDK.configure do |c|
14
- c.logger = Rails.logger
15
-
16
- c.use_all("OpenTelemetry::Instrumentation::PG" => { db_statement: :obfuscate })
17
-
18
- if productionish?
19
- c.add_span_processor(
20
- OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
21
- OpenTelemetry::Exporter::OTLP::Exporter.new,
22
- ),
23
- )
24
- else # useful for testing instrumentation
25
- c.add_span_processor(
26
- OpenTelemetry::SDK::Trace::Export::SimpleSpanProcessor.new(
27
- OpenTelemetry::SDK::Trace::Export::SpanExporter.new,
28
- ),
29
- )
30
- end # development is intentionally disabled
31
- end
32
- end
@@ -1,11 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- Sidekiq.configure_server do |config|
5
- config.logger = Sidekiq::Logger.new($stdout)
6
- config.redis = { url: ENV.fetch("REDIS_URL", "redis://localhost:6379/1") }
7
- end
8
- Sidekiq.configure_client do |config|
9
- config.logger = Sidekiq::Logger.new($stdout)
10
- config.redis = { url: ENV.fetch("REDIS_URL", "redis://localhost:6379/1") }
11
- end
@@ -1,17 +0,0 @@
1
- # typed: false
2
- # frozen_string_literal: true
3
-
4
- SlackWebhookLogger.setup do |config|
5
- # Webhook URL
6
- #
7
- # The URL where messages will be sent.
8
- config.webhook_url = SLACK_LOG_URL
9
-
10
- # The minimum error level to see in Slack.
11
- #
12
- # All log levels are supported, but don't do anything less then :warn since Slack only allows one message
13
- # per minute.
14
- config.level = :WARN
15
-
16
- config.ignore_patterns = [/Can't verify CSRF token authenticity/, /is not a valid MIME type/]
17
- end
@@ -1,20 +0,0 @@
1
- # Sample configuration file for Sidekiq.
2
- # Options here can still be overridden by cmd line args.
3
- # Place this file at config/sidekiq.yml and Sidekiq will
4
- # pick it up automatically.
5
- ---
6
- :verbose: false
7
- :logfile: ./log/sidekiq.log
8
- :concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 10) %>
9
- :timeout: 25
10
- :max_retries: 3
11
-
12
- # https://phil.tech/2016/tips-on-sidekiq-queues/
13
- :queues:
14
- - [update_yetto, 10]
15
-
16
- - [default, 5]
17
- - [mailers, 3]
18
-
19
- - [active_storage_analysis, 1]
20
- - [active_storage_purge, 1]
@@ -1,5 +0,0 @@
1
- #!/bin/sh
2
-
3
- set -e
4
-
5
- ngrok http --region=us --hostname=plug-app.ngrok.io 6661