hephaestus 0.3.1 → 0.5.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/bin/hephaestus +1 -0
  4. data/lib/hephaestus/app_builder.rb +6 -3
  5. data/lib/hephaestus/generators/app_generator.rb +46 -43
  6. data/lib/hephaestus/generators/config_generator.rb +2 -3
  7. data/lib/hephaestus/generators/core_generator.rb +1 -1
  8. data/lib/hephaestus/generators/deployment_generator.rb +6 -0
  9. data/lib/hephaestus/version.rb +1 -1
  10. data/lib/hephaestus.rb +8 -3
  11. data/templates/.github/workflows/licenses.yml +1 -1
  12. data/templates/.github/workflows/lint.yml +1 -1
  13. data/templates/.github/workflows/security.yml +1 -1
  14. data/templates/.github/workflows/sorbet.yml +1 -1
  15. data/templates/.licensed.yml +6 -0
  16. data/templates/Dockerfile +2 -2
  17. data/templates/Gemfile.erb +4 -1
  18. data/templates/app/controllers/app_controller.rb +3 -3
  19. data/templates/app/controllers/concerns/authable.rb +2 -2
  20. data/templates/app/controllers/settings_controller.rb +8 -0
  21. data/templates/app/controllers/yetto_controller.rb +11 -0
  22. data/templates/app/jobs/update_yetto_job.rb +6 -4
  23. data/templates/app/lib/body_parameter/yetto_parameters.rb +93 -9
  24. data/templates/app/lib/headers/yetto.rb +3 -1
  25. data/templates/app/lib/path_parameter/yetto_parameters.rb +6 -3
  26. data/templates/app/lib/plug_app/http.rb +3 -0
  27. data/templates/app/lib/plug_app/switches/message_created.jsonc +25 -0
  28. data/templates/app/services/yetto_service.rb +19 -14
  29. data/templates/compose.yml +1 -1
  30. data/templates/config/initializers/000-oj.rb +6 -0
  31. data/templates/config/initializers/environment.rb +5 -1
  32. data/templates/lib/plug_app/schemas/api/2023-03-06/components/parameters/headers/yetto.json +1 -1
  33. data/templates/lib/plug_app/schemas/api/2023-03-06/components/schemas/yetto.json +1 -1
  34. data/templates/lib/plug_app/schemas/api/2023-03-06/openapi.json +4 -4
  35. data/templates/lib/plug_app/schemas/api/2023-03-06/paths/yetto/{after_create_message.json → message_created.json} +1 -1
  36. data/templates/lib/plug_app/schemas/api/2023-03-06/paths/yetto/{after_create_plug_installation.json → plug_installation_created.json} +1 -1
  37. data/templates/test/controllers/yetto_controller_test.rb +7 -7
  38. data/templates/test/fixtures/files/plug_installation_settings/invalid.json +3 -0
  39. data/templates/test/fixtures/files/plug_installation_settings/valid.json +3 -0
  40. data/templates/test/fixtures/plug_installation_settings/invalid.json +3 -0
  41. data/templates/test/fixtures/plug_installation_settings/valid.json +3 -0
  42. data/templates/test/support/api.rb +6 -4
  43. data/templates/test/support/webmocks/yetto_webmock.rb +36 -17
  44. data/templates/vendor/fly/fly-production.toml +24 -22
  45. data/templates/vendor/fly/fly-staging.toml +24 -21
  46. metadata +11 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b95d21bfd57de5966b0e84d88b1405b86858be61eba98db2540cd4321169fe3c
4
- data.tar.gz: a1a812f73c093ec210675c9f5f736893c0170aece8f06ce92cb43ff9df39467c
3
+ metadata.gz: 35a7bffcd76ad59ed8a990221e201641e0931d5959d3a23eb1ff38e6cab6e196
4
+ data.tar.gz: 3a8041e10782f1feae394c607ff0b2884454bf2497973b204e1038d8318a8b19
5
5
  SHA512:
6
- metadata.gz: d967799d74078769fe825e5b03cfae506da34b023ff2e07edbe97ec91283592a50e664d280a1c2394ceefdd2047952ca36628e602789d224758d9bc91b45952b
7
- data.tar.gz: '08804720c39e023bfd1abc2ac87de38fc9badf9509fc8b3f161f0528862653bfb18727da01aab24ce56012e4346ef6abb2f6f78746c1e681a533787b49df2bd0'
6
+ metadata.gz: 343b21a22b01d3dec66e68ab5d807612930f2f46ed0fc5daa3d473745ce5db89978a3cd605b13ecb24cae51101e072dd5dbd891ed424855ce0724fd0233227c7
7
+ data.tar.gz: 8127efafa530a873c67a014ea0beef448b768c908bb4629a668eef1abcfe8b1527886447ad3757298d07f33483cab8e7a9c9b3f9839d7d0f88d7a04fb56f79ca
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [v0.4.0] - 29-09-2023
2
+ ## What's Changed
3
+ * Yet more changes by @gjtorikian in https://github.com/yettoapp/hephaestus/pull/10
4
+
5
+
6
+ **Full Changelog**: https://github.com/yettoapp/hephaestus/compare/v0.3.1...v0.4.0
7
+ ## [v0.3.1] - 18-09-2023
8
+ **Full Changelog**: https://github.com/yettoapp/hephaestus/compare/v0.3.0...v0.3.1
1
9
  ## [v0.3.0] - 12-09-2023
2
10
  ## What's Changed
3
11
  * Bump actions/checkout from 3 to 4 by @dependabot in https://github.com/yettoapp/hephaestus/pull/8
data/bin/hephaestus CHANGED
@@ -70,5 +70,6 @@ ARGV.push("--minimal")
70
70
  ARGV.push("--no-skip-active-job")
71
71
  ARGV.push("--skip-asset-pipeline")
72
72
  ARGV.push("--skip-active-record")
73
+ ARGV.push("--skip-docker")
73
74
 
74
75
  Hephaestus::AppGenerator.start
@@ -73,7 +73,7 @@ module Hephaestus
73
73
  def setup_slack_logger
74
74
  config = <<~EOD
75
75
  config.after_initialize do
76
- Rails.logger.extend(ActiveSupport::Logger.broadcast(SlackWebhookLogger.logger))
76
+ Rails.logger.broadcast_to(SlackWebhookLogger.logger)
77
77
  end
78
78
  EOD
79
79
  configure_environment("production", config)
@@ -158,14 +158,17 @@ module Hephaestus
158
158
  def replace_generic_variables
159
159
  say(set_color("Replacing generic variable names...", :cyan))
160
160
  replace_in_files(destination_root, /App(?!lication)/, short_app_name.capitalize)
161
- replace_in_files(destination_root, %r{(?<!yetto)app(?!lication|/|roximate)}, short_app_name.downcase)
161
+ replace_in_files(destination_root, %r{(?<!yetto|sw|plugs\.yetto\.)app(?!lication|/|roximate)}, short_app_name.downcase)
162
162
  replace_in_files(destination_root, "PlugApp", app_name.underscore.camelcase)
163
163
  replace_in_files(destination_root, "plug-app", app_name.dasherize)
164
+ replace_in_files("destination_root}/.github/workflows/test.yml", "plug-app", app_name.dasherize)
164
165
  replace_in_files(destination_root, "PLUG_APP", app_name.underscore.upcase)
165
166
  replace_in_files(destination_root, "plug_app", app_name.underscore)
166
167
 
167
- # this is erroneously changed
168
+ # these are erroneously changed
168
169
  replace_in_file("script/server", "/usr/src/#{short_app_name.downcase}", "/usr/src/app")
170
+ replace_in_file("vendor/fly/fly-production.toml", "#{short_app_name.downcase} = ", "app = ")
171
+ replace_in_file("vendor/fly/fly-staging.toml", "#{short_app_name.downcase} = ", "app =")
169
172
  end
170
173
 
171
174
  private
@@ -28,37 +28,10 @@ module Hephaestus
28
28
  super
29
29
  end
30
30
 
31
- # NOTE: this function name is important as it overrides
32
- # a Rails function of the same name (that function performs work
33
- # that we don't want to do)
34
- def leftovers
35
- build(:replace_generic_variables)
36
-
37
- say(set_color("Generating `hephaestus:license`...", :cyan))
38
- capture_stdout do
39
- generate("hephaestus:license")
40
- end
41
- say(set_color("Generating `hephaestus:rubocop`...", :cyan))
42
- capture_stdout do
43
- generate("hephaestus:rubocop")
44
- end
45
- say(set_color("Generating `hephaestus:sorbet`...", :cyan))
46
- capture_stdout do
47
- generate("hephaestus:sorbet")
48
- end
49
- say(set_color("Creating first commit...", :cyan))
50
- capture_stdout do
51
- invoke(:commit)
52
- end
53
-
54
- build(:restore_gemfile)
55
- invoke(:outro)
56
- end
57
-
58
31
  def hephaestus_customization
59
32
  say(set_color("Invoking Hephaestus customizations...", :cyan))
60
33
 
61
- run("rails app:update:bin", capture: true)
34
+ run("rails app:update:bin")
62
35
  invoke(:customize_gemfile)
63
36
 
64
37
  invoke(:copy_github_actions)
@@ -79,6 +52,8 @@ module Hephaestus
79
52
  build(:replace_gemfile)
80
53
  capture_stdout do
81
54
  bundle_command("install")
55
+ bundle_command("update")
56
+ bundle_command("binstub foreman")
82
57
  bundle_command("lock --add-platform x86_64-linux")
83
58
  end
84
59
  end
@@ -171,6 +146,33 @@ module Hephaestus
171
146
  end
172
147
  end
173
148
 
149
+ # NOTE: this function name is important as it overrides
150
+ # a Rails function of the same name (that function performs work
151
+ # that we don't want to do)
152
+ def leftovers
153
+ build(:replace_generic_variables)
154
+
155
+ say(set_color("Generating `hephaestus:license`...", :cyan))
156
+ capture_stdout do
157
+ generate("hephaestus:license")
158
+ end
159
+ say(set_color("Generating `hephaestus:rubocop`...", :cyan))
160
+ capture_stdout do
161
+ generate("hephaestus:rubocop")
162
+ end
163
+ say(set_color("Generating `hephaestus:sorbet`...", :cyan))
164
+ capture_stdout do
165
+ generate("hephaestus:sorbet")
166
+ end
167
+ say(set_color("Creating first commit...", :cyan))
168
+ capture_stdout do
169
+ invoke(:commit)
170
+ end
171
+
172
+ build(:restore_gemfile)
173
+ invoke(:outro)
174
+ end
175
+
174
176
  def commit
175
177
  run("git add .")
176
178
  run("git commit -m 'Initial commit'", capture: true)
@@ -202,11 +204,12 @@ module Hephaestus
202
204
 
203
205
  * Set `settings/branches` to protect `production`
204
206
  * ✅ Require status checks to pass before merging
205
- * 🖊️ Status checks that are required: `test`, `ruby / brakeman`, `ruby / bundle-audit`.
207
+ * 🖊️ Status checks that are required: `ruby / test_without_services`, `docker / test-build`, `ruby / brakeman`, `ruby / bundle-audit`.
208
+
206
209
  You can only set those 👆 after you've opened the first PR on GitHub. Crazy, I know!!
207
210
  But, doing so is *essential* for automerge to function properly.
208
211
 
209
- * Speaking of which, in `/settings`
212
+ * In `/settings`:
210
213
  * ✅ Allow auto-merge
211
214
  * ✅ Automatically delete head branches
212
215
  OUTPUT
@@ -229,22 +232,22 @@ module Hephaestus
229
232
  end
230
233
 
231
234
  private def capture_stdout
232
- stream = "stdout"
233
- captured_stream = Tempfile.new(stream)
234
- stream_io = eval("$#{stream}", binding, __FILE__, __LINE__)
235
- origin_stream = stream_io.dup
236
- stream_io.reopen(captured_stream)
235
+ # stream = "stdout"
236
+ # captured_stream = Tempfile.new(stream)
237
+ # stream_io = eval("$#{stream}", binding, __FILE__, __LINE__)
238
+ # origin_stream = stream_io.dup
239
+ # stream_io.reopen(captured_stream)
237
240
 
238
241
  yield
239
242
 
240
- stream_io.rewind
241
- captured_stream.read
242
- ensure
243
- unless captured_stream.nil?
244
- captured_stream.close
245
- captured_stream.unlink
246
- end
247
- stream_io.reopen(origin_stream) unless stream_io.nil?
243
+ # stream_io.rewind
244
+ # captured_stream.read
245
+
246
+ # unless captured_stream.nil?
247
+ # captured_stream.close
248
+ # captured_stream.unlink
249
+ # end
250
+ # stream_io.reopen(origin_stream) unless stream_io.nil?
248
251
  end
249
252
  end
250
253
  end
@@ -89,11 +89,10 @@ module Hephaestus
89
89
 
90
90
  # events into the plug, usually from yetto
91
91
  get "/api/2023-03-06/settings", to: "settings#new"
92
- post "/api/2023-03-06/:event/:record_type", to: "yetto#event"
92
+ post "/api/2023-03-06/:record_type/:event", to: "yetto#event"
93
93
 
94
94
  # inbound message
95
- post "/app/2023-03-06/webhook/:organization_id/:inbox_id/:plug_installation_id", to: "app#webhook"
96
- # post "/app/2023-03-06/webhook/inbound", to: "app#process_inbound" # for generic inbound pings
95
+ post "/$app/2023-03-06/webhook/inbound", to: "app#webhook"
97
96
 
98
97
  # Staff pages
99
98
  get "staff", to: "staff#index"
@@ -19,7 +19,7 @@ module Hephaestus
19
19
  end
20
20
 
21
21
  def jobs
22
- copy_file("app/jobs/application_job.rb", "app/jobs/application_job.rb")
22
+ copy_file("app/jobs/application_job.rb", "app/jobs/application_job.rb", force: true)
23
23
  copy_file("app/jobs/update_yetto_job.rb", "app/jobs/update_yetto_job.rb")
24
24
  end
25
25
 
@@ -20,5 +20,11 @@ module Hephaestus
20
20
  copy_file("Dockerfile", "Dockerfile")
21
21
  copy_file("bin/docker-entrypoint", "bin/docker-entrypoint")
22
22
  end
23
+
24
+ def fly
25
+ directory("vendor/fly", "vendor/fly")
26
+ copy_file("Dockerfile", "Dockerfile")
27
+ copy_file("bin/docker-entrypoint", "bin/docker-entrypoint")
28
+ end
23
29
  end
24
30
  end
@@ -2,7 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Hephaestus
5
- VERSION = "0.3.1"
5
+ VERSION = "0.5.0"
6
6
  RAILS_VERSION = "~> 7.0"
7
7
  RUBY_VERSION = File
8
8
  .read("#{File.dirname(__FILE__)}/../../.ruby-version")
data/lib/hephaestus.rb CHANGED
@@ -11,10 +11,15 @@ require "debug" if debugging?
11
11
 
12
12
  require "hephaestus/version"
13
13
  require "hephaestus/exit_on_failure"
14
+
14
15
  require "hephaestus/generators/app_generator"
15
- Dir.glob(File.join(__dir__, "hephaestus", "generators", "*.rb")).each do |file|
16
- require file
17
- end
16
+ require "hephaestus/generators/config_generator"
17
+ require "hephaestus/generators/core_generator"
18
+ require "hephaestus/generators/deployment_generator"
19
+ require "hephaestus/generators/lib_generator"
20
+ require "hephaestus/generators/license_generator"
21
+ require "hephaestus/generators/rubocop_generator"
22
+ require "hephaestus/generators/sorbet_generator"
18
23
 
19
24
  require "hephaestus/actions"
20
25
  require "hephaestus/actions/strip_comments_action"
@@ -13,7 +13,7 @@ jobs:
13
13
  verify:
14
14
  runs-on: ubuntu-latest
15
15
  steps:
16
- - uses: actions/checkout@v3
16
+ - uses: actions/checkout@v4
17
17
  with:
18
18
  ref: ${{ github.head_ref }}
19
19
  token: ${{ secrets.GH_SISYPHUS_YETTO_REPO_TOKEN }}
@@ -12,7 +12,7 @@ jobs:
12
12
  rubocop:
13
13
  runs-on: ubuntu-latest
14
14
  steps:
15
- - uses: actions/checkout@v3
15
+ - uses: actions/checkout@v4
16
16
 
17
17
  - uses: yettoapp/actions/pr-contains-files@main
18
18
  id: pr_contains_ruby
@@ -12,4 +12,4 @@ jobs:
12
12
  ruby:
13
13
  uses: yettoapp/actions/.github/workflows/ruby_security_checks.yml@main
14
14
  secrets:
15
- token: ${{ secrets.GITHUB_TOKEN }}
15
+ gh_token: ${{ secrets.GH_SISYPHUS_YETTO_REPO_TOKEN }}
@@ -11,7 +11,7 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
 
13
13
  steps:
14
- - uses: actions/checkout@v3
14
+ - uses: actions/checkout@v4
15
15
  with:
16
16
  ref: ${{ github.head_ref }}
17
17
  token: ${{ secrets.GH_SISYPHUS_YETTO_REPO_TOKEN }}
@@ -11,10 +11,16 @@ allowed:
11
11
 
12
12
  ignored:
13
13
  bundler:
14
+ - base64 # BSD-2-Clause ("This file is released under the same license as ruby.")
15
+ - bigdecimal # BSD-2-Clause ("This file is released under the same license as ruby.")
14
16
  - bundler-audit # GPL-3.0; but also, only used in CI/test
15
17
  - date # BSD-2-Clause
18
+ - drb # BSD-2-Clause ("This file is released under the same license as ruby.")
19
+ - io-console # BSD-2-Clause
20
+ - mutex_m # BSD-2-Clause ("This file is released under the same license as ruby.")
16
21
  - net-protocol # BSD-2-Clause
17
22
  - racc # BSD-2-Clause
23
+ - reline # BSD-2-Clause ("This file is released under the same license as ruby.")
18
24
  - ruby2_keywords # BSD-2-Clause; ignored because of custom LICENSE text
19
25
  - sidekiq # LGPL-3.0; ignored because of custom LICENSE text
20
26
 
data/templates/Dockerfile CHANGED
@@ -4,8 +4,8 @@
4
4
  ARG RUBY_VERSION=3.2.1
5
5
  FROM ruby:$RUBY_VERSION-slim as base
6
6
 
7
- # Rails app lives here
8
- WORKDIR /plug-github
7
+ # The plug-app code lives here
8
+ WORKDIR /plug-app
9
9
 
10
10
  # Set production environment
11
11
  ARG RAILS_ENV="production"
@@ -44,6 +44,9 @@ gem "opentelemetry-instrumentation-active_job", "~> 0.5"
44
44
  gem "opentelemetry-instrumentation-redis", "~> 0.25"
45
45
  gem "opentelemetry-instrumentation-sidekiq", "~> 0.23"
46
46
 
47
+ # massively improved JSON parsing
48
+ gem "oj", "~> 3.16"
49
+
47
50
  # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
48
51
  gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
49
52
 
@@ -114,4 +117,4 @@ group :ci do
114
117
  gem "bundle-audit", "~> 0.1"
115
118
  end
116
119
 
117
- gem "hephaestus", group: [:development, :test]
120
+ gem "hephaestus", group: [:development, :test]
@@ -8,12 +8,12 @@ class AppController < ApplicationController
8
8
  include PathParameter::AppParameters
9
9
  include BodyParameter::AppParameters
10
10
 
11
- before_action :from__app_?
11
+ before_action :from_app?
12
12
 
13
13
  # Inbound message from ${App}
14
14
  def webhook
15
- # Error if necesary parameters from ${App} are missing
16
- return bad_request unless has_inbound__app__params?
15
+ # Error if necessary parameters from ${App} are missing
16
+ return bad_request unless has_inbound_app_params?
17
17
 
18
18
  response = YettoService.get_plug_installation(pparam_organization_id, pparam_inbox_id, pparam_plug_installation_id)
19
19
 
@@ -26,8 +26,8 @@ module Authable
26
26
 
27
27
  # status is annoyingly set to 401, but we want
28
28
  # to hide that an issue exists
29
- response.status = PlugApp::HTTP::BAD_REQUEST_I
30
- response.body = ::ErrorSerializer.format(PlugApp::HTTP::BAD_REQUEST)
29
+ self.status = PlugApp::HTTP::BAD_REQUEST_I
30
+ self.response_body = ::ErrorSerializer.format(PlugApp::HTTP::BAD_REQUEST)
31
31
  end
32
32
 
33
33
  sig { void }
@@ -6,6 +6,14 @@ class SettingsController < ApplicationController
6
6
 
7
7
  include PathParameter::SettingsParameters
8
8
 
9
+ before_action :ensure_json_request
10
+ sig { void }
11
+ def ensure_json_request
12
+ return if request.format.json?
13
+
14
+ not_acceptable
15
+ end
16
+
9
17
  sig { void }
10
18
  def new
11
19
  @step = T.let(params.fetch(:step, 1).to_i || 1, T.nilable(Integer))
@@ -3,6 +3,7 @@
3
3
 
4
4
  class YettoController < ApplicationController
5
5
  include BodyParameter::YettoParameters
6
+ include PathParameter
6
7
  include PathParameter::YettoParameters
7
8
  include Authable
8
9
 
@@ -10,11 +11,21 @@ class YettoController < ApplicationController
10
11
 
11
12
  before_action :from_yetto?
12
13
 
14
+ AFTER_CREATE_MESSAGE_SWITCH = JSON.parse(Rails.root.join("app/lib/plug_app/switches/message_created.jsonc").read)
15
+
13
16
  def event
14
17
  case pparam_yetto_event
15
18
  when Headers::Yetto::EVENT_AFTER_CREATE
16
19
  case pparam_yetto_record_type
17
20
  when Headers::Yetto::RECORD_TYPE_PLUG_INSTALLATION
21
+ create_inbox_switch_data = {
22
+ type: "create_inbox_switch",
23
+ inbox: { id: bparam_inbox_id },
24
+ plug_installation: { id: bparam_plug_installation_id },
25
+ payload: AFTER_CREATE_MESSAGE_SWITCH,
26
+ }
27
+
28
+ UpdateYettoJob.perform_later(create_inbox_switch_data)
18
29
 
19
30
  no_content
20
31
  when Headers::Yetto::RECORD_TYPE_MESSAGE
@@ -5,22 +5,24 @@
5
5
  # This can be used to update installation data or message data
6
6
 
7
7
  class UpdateYettoJob < ApplicationJob
8
- queue_as :default
8
+ queue_as :update_yetto
9
9
 
10
10
  def perform(params)
11
11
  type = params.delete(:type)
12
12
 
13
- organization_id = params.fetch(:organization, {}).fetch(:id, nil)
14
13
  inbox_id = params.fetch(:inbox, {}).fetch(:id, nil)
15
14
  plug_installation_id = params.fetch(:plug_installation, {}).fetch(:id, nil)
15
+ message_id = params.fetch(:message, {}).fetch(:id, nil)
16
16
 
17
17
  case type
18
18
  when "update_plug_installation"
19
19
  YettoService.update_installation(plug_installation_id, params)
20
20
  when "create_inbox_switch"
21
21
  YettoService.create_inbox_switch(inbox_id, plug_installation_id, params)
22
- when "create_message"
23
- YettoService.create_message(inbox_id, plug_installation_id, params)
22
+ when "create_message_reply"
23
+ YettoService.create_message_reply(message_id, plug_installation_id, params)
24
+ when "add_message_metadata"
25
+ YettoService.update_message(message_id, plug_installation_id, params)
24
26
  end
25
27
  end
26
28
  end
@@ -5,25 +5,47 @@ module BodyParameter
5
5
  module YettoParameters
6
6
  extend T::Sig
7
7
 
8
- sig { returns(T::Boolean) }
9
- def has_update_plug_installation_params?
10
- return false if update_plug_installation_params.blank?
8
+ sig { returns(String) }
9
+ def bparam_organization_id
10
+ plug_installation_params[:organization][:id]
11
+ end
12
+
13
+ sig { returns(String) }
14
+ def bparam_inbox_id
15
+ plug_installation_params[:inbox][:id]
16
+ end
17
+
18
+ sig { returns(String) }
19
+ def bparam_plug_installation_id
20
+ plug_installation_params[:plug_installation][:id]
21
+ end
22
+
23
+ sig { returns(String) }
24
+ def bparam_plug_id
25
+ plug_installation_params[:plug][:id]
26
+ end
11
27
 
12
- true
28
+ sig { returns(T::Hash[Symbol, String]) }
29
+ def bparam_plug_installation_settings
30
+ plug_installation_params[:plug_installation][:settings]
13
31
  end
14
32
 
15
33
  sig { returns(T::Hash[Symbol, String]) }
16
- def update_plug_installation_params
34
+ def plug_installation_params
17
35
  return {} if params.blank?
18
36
 
19
- return {} if (plug_installation_id = params.fetch(:plug_installation, {}).fetch(:id, "")).blank?
20
- return {} if (organization_id = params.fetch(:organization, {}).fetch(:id, "")).blank?
21
- return {} if (plug_id = params.fetch(:plug, {}).fetch(:id, "")).blank?
22
- return {} if (inbox_id = params.fetch(:inbox, {}).fetch(:id, "")).blank?
37
+ plug_installation = params.fetch(:plug_installation, {})
38
+ plug_installation_id = plug_installation.fetch(:id, "")
39
+ settings = plug_installation.fetch(:settings, {}).to_unsafe_hash
40
+
41
+ organization_id = params.fetch(:organization, {}).fetch(:id, "")
42
+ plug_id = params.fetch(:plug, {}).fetch(:id, "")
43
+ inbox_id = params.fetch(:inbox, {}).fetch(:id, "")
23
44
 
24
45
  {
25
46
  plug_installation: {
26
47
  id: plug_installation_id,
48
+ settings: settings,
27
49
  },
28
50
  organization: {
29
51
  id: organization_id,
@@ -36,5 +58,67 @@ module BodyParameter
36
58
  },
37
59
  }
38
60
  end
61
+
62
+ sig { returns(String) }
63
+ def bparam_message_id
64
+ message_params[:message][:id]
65
+ end
66
+
67
+ sig { returns(String) }
68
+ def bparam_message_text_content
69
+ message_params[:message][:text_content]
70
+ end
71
+
72
+ sig { returns(String) }
73
+ def bparam_message_conversation_id
74
+ message_params[:message][:conversation][:id]
75
+ end
76
+
77
+ sig { returns(String) }
78
+ def bparam_message_conversation_title
79
+ message_params[:message][:conversation][:title]
80
+ end
81
+
82
+ sig { returns(String) }
83
+ def bparam_message_author_name
84
+ message_params[:message].fetch(:author, {}).fetch(:name, "Noone")
85
+ end
86
+
87
+ sig { returns(T::Hash[Symbol, String]) }
88
+ def bparam_message_metadata
89
+ message_params[:message][:metadata]
90
+ end
91
+
92
+ sig { returns(T::Hash[Symbol, String]) }
93
+ def message_params
94
+ return {} if params.blank?
95
+
96
+ message = params.fetch(:message, {})
97
+ message_id = message.fetch(:id, "")
98
+ text_content = message.fetch(:text_content, "")
99
+ conversation = message.fetch(:conversation, {})
100
+ conversation_id = conversation.fetch(:id, "")
101
+ title = conversation.fetch(:title, "")
102
+ created_by_user = message.fetch(:created_by_user, {})
103
+ created_by_plug = message.fetch(:created_by_plug, {})
104
+ author = (created_by_user.presence || created_by_plug)
105
+ name = author.fetch(:name, "")
106
+ metadata = message.fetch(:metadata, {}).to_unsafe_hash
107
+
108
+ {
109
+ message: {
110
+ id: message_id,
111
+ text_content: text_content,
112
+ conversation: {
113
+ id: conversation_id,
114
+ title: title,
115
+ },
116
+ author: {
117
+ name: name,
118
+ },
119
+ metadata: metadata,
120
+ },
121
+ }
122
+ end
39
123
  end
40
124
  end
@@ -6,7 +6,9 @@ module Headers
6
6
  YETTO_DELIVERY_ID = "HTTP_X_YETTO_DELIVERY_ID"
7
7
 
8
8
  HEADER_EVENT = "HTTP_X_YETTO_EVENT"
9
- EVENT_AFTER_CREATE = "after_create"
9
+ EVENT_AFTER_CREATE = "created"
10
+ EVENT_AFTER_UPDATE = "updated"
11
+ EVENT_AFTER_DESTROY = "destroyed"
10
12
 
11
13
  HEADER_RECORD_TYPE = "HTTP_X_YETTO_RECORD_TYPE"
12
14
  RECORD_TYPE_PLUG_INSTALLATION = "plug_installation"
@@ -15,11 +15,14 @@ module PathParameter
15
15
  yetto_path_params.fetch(:record_type, "")
16
16
  end
17
17
 
18
- sig { returns(ActionController::Parameters) }
18
+ sig { returns(T::Hash[String, String]) }
19
19
  def yetto_path_params
20
- return ActionController::Parameters.new if params.blank?
20
+ return {} if path_parameters.blank?
21
21
 
22
- params.permit(:event, :record_type)
22
+ {
23
+ event: path_parameters.fetch(:event, ""),
24
+ record_type: path_parameters.fetch(:record_type, ""),
25
+ }
23
26
  end
24
27
  end
25
28
  end
@@ -13,6 +13,9 @@ module PlugApp
13
13
  NO_CONTENT = "No Content"
14
14
  NO_CONTENT_I = 204
15
15
 
16
+ FOUND = "Found"
17
+ FOUND_I = 302
18
+
16
19
  NOT_FOUND = "Not Found"
17
20
  NOT_FOUND_I = 404
18
21
  BAD_REQUEST = "Bad Request"
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "Send internal comments to App",
3
+ "configuration": {
4
+ "version": "2023-03-06",
5
+ "events": {
6
+ "message.created": {
7
+ "conditions": {
8
+ "if": "{% data.message.visibility == 'internal' and data.message.text_content contains '@App' %}"
9
+ },
10
+ "actions": [
11
+ {
12
+ "name": "Send to App",
13
+ "uses": "send_to_plug",
14
+ "with": {
15
+ "plug_id": "{{ data.switch.created_by_plug.id }}",
16
+ "message": "{{ data.message }}",
17
+ "plug_installation": "{{ data.plug_installation }}",
18
+ "inbox": "{{ data.inbox }}"
19
+ }
20
+ }
21
+ ]
22
+ }
23
+ }
24
+ }
25
+ }
@@ -6,48 +6,53 @@ class YettoService
6
6
  Httpsensible::Client.new(user_agent: "PlugApp/#{PlugApp::Application::GIT_SHA}")
7
7
  end
8
8
 
9
- PROTOCOL = Rails.env.development? ? "http" : "https"
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://"
10
12
  YETTO_API_VERSION_TLD = "#{PROTOCOL}://#{YETTO_API_TLD}/#{YETTO_API_VERSION}"
11
13
  JWT_ALGORITHM = "RS256"
12
14
 
13
15
  class << self
14
16
  def perform_token_exchange(plug_installation_id)
15
17
  encoded_jwt = Httpsensible::JWT.encode_jwt(YETTO_PLUG_PEM, YETTO_PLUG_ID)
16
- response = yetto_client.with(headers: { "Authorization" => "Bearer #{encoded_jwt}" }).post("#{YETTO_API_VERSION_TLD}/plugs/installations/#{plug_installation_id}/access_tokens")
18
+ response = yetto_client.with_headers({ "Authorization" => "Bearer #{encoded_jwt}" }).post("#{YETTO_API_VERSION_TLD}/plug/installations/#{plug_installation_id}/access_tokens")
17
19
  body = response.parsed_json_body
18
20
  body["token"]
19
21
  end
20
22
 
21
23
  def get_plug_installation(plug_installation_id)
22
24
  token = perform_token_exchange(plug_installation_id)
23
- yetto_client.with(headers: { "Authorization" => "Bearer #{token}" }).get("#{YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}")
25
+ yetto_client.with_headers("Authorization" => "Bearer #{token}").get("#{YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}")
24
26
  end
25
27
 
26
28
  def update_installation(plug_installation_id, params)
27
29
  plug_installation = {}
28
- plug_installation[:settings] = params[:plug_installation].fetch(:settings, {})
29
- plug_installation[:credentials] = params[:plug_installation].fetch(:credentials, {})
30
+ plug_installation[:settings] = params.fetch(:settings, {})
31
+ plug_installation[:credentials] = params.fetch(:credentials, {})
30
32
 
31
33
  token = perform_token_exchange(plug_installation_id)
32
- yetto_client.with(headers: { "Authorization" => "Bearer #{token}" }).patch("#{YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}", json: plug_installation)
34
+ yetto_client.with_headers("Authorization" => "Bearer #{token}").patch("#{YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}", json: plug_installation)
33
35
  end
34
36
 
35
37
  def create_inbox_switch(inbox_id, plug_installation_id, params)
36
- inbox_id = params.fetch(:inbox).fetch(:id)
38
+ payload = params[:payload]
39
+ token = perform_token_exchange(plug_installation_id)
37
40
 
38
- payload = {
39
- name: "After install",
40
- }
41
+ yetto_client.with_headers("Authorization" => "Bearer #{token}").post("#{YETTO_API_VERSION_TLD}/inboxes/#{inbox_id}/switches", json: payload)
42
+ end
41
43
 
44
+ def update_message(message_id, plug_installation_id, params)
45
+ payload = params[:payload]
42
46
  token = perform_token_exchange(plug_installation_id)
43
- yetto_client.with(headers: { "Authorization" => "Bearer #{token}" }).post("#{YETTO_API_VERSION_TLD}/inboxes/#{inbox_id}/switches", json: payload)
47
+
48
+ yetto_client.with_headers("Authorization" => "Bearer #{token}").patch("#{YETTO_API_VERSION_TLD}/messages/#{message_id}", json: payload)
44
49
  end
45
50
 
46
- def create_message(inbox_id, plug_installation_id, params)
51
+ def create_message_reply(message_id, plug_installation_id, params)
47
52
  payload = params[:payload]
48
-
49
53
  token = perform_token_exchange(plug_installation_id)
50
- yetto_client.with(headers: { "Authorization" => "Bearer #{token}" }).post("#{YETTO_API_VERSION_TLD}/inboxes/#{inbox_id}/messages", json: payload)
54
+
55
+ yetto_client.with_headers("Authorization" => "Bearer #{token}").post("#{YETTO_API_VERSION_TLD}/messages/#{message_id}/replies", json: payload)
51
56
  end
52
57
  end
53
58
  end
@@ -4,4 +4,4 @@ services:
4
4
  redis-db:
5
5
  image: redis:7-bookworm
6
6
  ports:
7
- - "6389:6379"
7
+ - "6402:6402"
@@ -0,0 +1,6 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ Oj.default_options = { mode: :rails }
5
+
6
+ Oj.optimize_rails
@@ -16,7 +16,7 @@ YETTO_API_VERSION = ENV.fetch("YETTO_API_VERSION", "2023-03-06")
16
16
 
17
17
  SLACK_LOG_URL = Rails.application.credentials.fetch(:SLACK_LOG_URL, ENV.fetch("SLACK_LOG_URL", "https://slack.com/the_log_room"))
18
18
 
19
- PROTOCOL = Rails.env.development? ? "http://" : "https://"
19
+ PROTOCOL = "https"
20
20
  PLUG_APP_URL = if Rails.env.production?
21
21
  "app.plugs.yetto.app"
22
22
  elsif Rails.env.staging?
@@ -34,3 +34,7 @@ YETTO_PLUG_ID = Rails.application.credentials.fetch(:YETTO_PLUG_ID, ENV.fetch("Y
34
34
  def productionish?
35
35
  Rails.env.production? || Rails.env.staging?
36
36
  end
37
+
38
+ def print_user_api_errors?
39
+ (Rails.env.development? || Rails.env.staging?) || ENV.fetch("DEBUG", false)
40
+ end
@@ -6,7 +6,7 @@
6
6
  "required": true,
7
7
  "schema": {
8
8
  "type": "string",
9
- "pattern": "^after_{create|update|destroy}$"
9
+ "pattern": "^{created|updated|destroyed}$"
10
10
  }
11
11
  },
12
12
  "RecordType": {
@@ -98,7 +98,7 @@
98
98
  },
99
99
  "additionalProperties": false
100
100
  },
101
- "CreateApp": {
101
+ "ConfigureApp": {
102
102
  "type": "object",
103
103
  "required": [
104
104
  "plug_installation",
@@ -17,11 +17,11 @@
17
17
  }
18
18
  ],
19
19
  "paths": {
20
- "/api/2023-03-06/after_create/plug_installation": {
21
- "$ref": "paths/yetto/after_create_plug_installation.json"
20
+ "/api/2023-03-06/plug_installation/created": {
21
+ "$ref": "paths/yetto/plug_installation_created.json"
22
22
  },
23
- "/api/2023-03-06/after_create/message": {
24
- "$ref": "paths/yetto/after_create_message.json"
23
+ "/api/2023-03-06/message/created": {
24
+ "$ref": "paths/yetto/message_created.json"
25
25
  },
26
26
  "/app/2023-03-06/{plugInstallationId}": {
27
27
  "$ref": "paths/app.json"
@@ -4,7 +4,7 @@
4
4
  "Yetto"
5
5
  ],
6
6
  "description": "After a message is created in Yetto, this delivers it.",
7
- "operationId": "Create a new App",
7
+ "operationId": "Create a new message",
8
8
  "requestBody": {
9
9
  "required": true,
10
10
  "content": {
@@ -10,7 +10,7 @@
10
10
  "content": {
11
11
  "application/json": {
12
12
  "schema": {
13
- "$ref": "../../components/schemas/yetto.json#/CreateAppSwitch"
13
+ "$ref": "../../components/schemas/yetto.json#/ConfigureApp"
14
14
  }
15
15
  }
16
16
  }
@@ -60,37 +60,37 @@ class YettoControllerTest < ActionDispatch::IntegrationTest
60
60
 
61
61
  def headers(body)
62
62
  {
63
- Headers::Yetto::HEADER_EVENT => "after_create",
63
+ Headers::Yetto::HEADER_EVENT => "created",
64
64
  Headers::Yetto::HEADER_RECORD_TYPE => "plug_installation",
65
65
  Headers::Yetto::HEADER_SIGNATURE => yetto_auth_header(body),
66
66
  }
67
67
  end
68
68
 
69
69
  test "it handles null headers" do
70
- api(:post, "/after_create/plug_installation", headers: nil)
70
+ api(:post, "/plug_installation/created", headers: nil)
71
71
 
72
72
  assert_response :bad_request
73
73
  end
74
74
 
75
75
  test "it handles missing headers" do
76
- api(:post, "/after_create/plug_installation", headers: {})
76
+ api(:post, "/plug_installation/created", headers: {})
77
77
 
78
78
  assert_response :bad_request
79
79
  end
80
80
 
81
81
  test "it handles incorrect headers" do
82
- api(:post, "/after_create/plug_installation", headers: { "X-Yetto-Signature" => "Basic jabroni:lies" })
82
+ api(:post, "/plug_installation/created", headers: { "X-Yetto-Signature" => "Basic jabroni:lies" })
83
83
 
84
84
  assert_response :bad_request
85
85
 
86
- api(:post, "/after_create/plug_installation", headers: { "X-Yetto-Signature" => "sha256=123456" })
86
+ api(:post, "/plug_installation/created", headers: { "X-Yetto-Signature" => "sha256=123456" })
87
87
 
88
88
  assert_response :bad_request
89
89
  end
90
90
 
91
91
  test "it handles missing body" do
92
92
  body = {}
93
- api(:post, "/after_create/plug_installation", headers: headers(body), body: body)
93
+ api(:post, "/plug_installation/created", headers: headers(body), body: body)
94
94
 
95
95
  assert_response :bad_request
96
96
  end
@@ -122,7 +122,7 @@ class YettoControllerTest < ActionDispatch::IntegrationTest
122
122
  id: "inbx_#{Faker::Alphanumeric.alphanumeric(number: 26).upcase}",
123
123
  },
124
124
  }
125
- api(:post, "/after_create/plug_installation", headers: headers_with_one_body, body: body_two)
125
+ api(:post, "/plug_installation/created", headers: headers_with_one_body, body: body_two)
126
126
 
127
127
  assert_response :bad_request
128
128
  end
@@ -0,0 +1,3 @@
1
+ {
2
+ "token_type": "bearer"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "github_installations": "gh_installation_id"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "token_type": "bearer"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "github_installations": "gh_installation_id"
3
+ }
@@ -5,11 +5,11 @@ module API
5
5
  module TestHelpers
6
6
  include Rack::Test::Methods
7
7
 
8
- def plug(method, path, headers: {}, version: nil, body: {})
8
+ def plug(method, path, headers: {}, version: nil, body: {}, parse: true)
9
9
  version ||= PlugApp::CURRENT_VERSION
10
10
  prepended_path = prepend_plug_path(version, path)
11
11
 
12
- http_call(method, prepended_path, headers: headers, version: version, body: body)
12
+ http_call(method, prepended_path, headers: headers, version: version, body: body, parse: parse)
13
13
  end
14
14
 
15
15
  def api(method, path, headers: {}, version: nil, body: {})
@@ -19,7 +19,7 @@ module API
19
19
  http_call(method, prepended_path, headers: headers, version: version, body: body)
20
20
  end
21
21
 
22
- def http_call(method, path, headers: {}, version: nil, body: {})
22
+ def http_call(method, path, headers: {}, version: nil, body: {}, parse: true)
23
23
  # explicitly assert headers cannot be nil
24
24
  if headers.nil?
25
25
  send(method, path, body.to_json)
@@ -29,7 +29,7 @@ module API
29
29
  send(method, path, body.to_json, headers)
30
30
  end
31
31
 
32
- JSON.parse(last_response.body) if last_response.body.present?
32
+ JSON.parse(last_response.body) if last_response.body.present? && parse
33
33
  end
34
34
 
35
35
  def assert_response(expected_status, expected_body = nil)
@@ -42,6 +42,8 @@ module API
42
42
  PlugApp::HTTP::OK_I
43
43
  when :created
44
44
  PlugApp::HTTP::CREATED_I
45
+ when :redirect
46
+ PlugApp::HTTP::FOUND_I
45
47
  when :no_content
46
48
  PlugApp::HTTP::NO_CONTENT_I
47
49
  when :bad_request
@@ -8,28 +8,30 @@ module Webmocks
8
8
  end
9
9
 
10
10
  def assert_requested_post_access_token(plug_installation_id)
11
- assert_requested(:post, "#{::YettoService::YETTO_API_VERSION_TLD}/plugs/installations/#{plug_installation_id}/access_tokens")
11
+ assert_requested(:post, "#{::YettoService::YETTO_API_VERSION_TLD}/plug/installations/#{plug_installation_id}/access_tokens")
12
12
  end
13
13
 
14
14
  def stub_post_access_token(plug_installation_id)
15
15
  response = {
16
16
  token: Faker::Alphanumeric.alphanumeric(number: 26).upcase,
17
17
  }
18
- stub_request(:post, "#{::YettoService::YETTO_API_VERSION_TLD}/plugs/installations/#{plug_installation_id}/access_tokens")
18
+ stub_request(:post, "#{::YettoService::YETTO_API_VERSION_TLD}/plug/installations/#{plug_installation_id}/access_tokens")
19
19
  .to_return(
20
20
  body: response.to_json,
21
21
  )
22
22
  end
23
23
 
24
- def assert_requested_get_plug_installation(plug_installation_id)
24
+ def assert_requested_get_inbox_plug_installation(plug_installation_id)
25
25
  assert_requested_post_access_token(plug_installation_id)
26
26
  assert_requested(:get, "#{::YettoService::YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}")
27
27
  end
28
28
 
29
- def stub_get_plug_installation(plug_installation_id, response = nil, status: 200)
29
+ def stub_get_inbox_plug_installation(organization_id, inbox_id, plug_installation_id, response = {}, valid: true, status: 200, expires_at: 8.hours.from_now)
30
30
  stub_post_access_token(plug_installation_id)
31
31
 
32
- response ||= {
32
+ github_installations = JSON.parse(file_fixture_path("plug_installation_settings", valid ? "valid.json" : "invalid.json").read).deep_symbolize_keys
33
+
34
+ response = {
33
35
  installed_on_inbox: {
34
36
  id: inbox_id,
35
37
  organization: {
@@ -40,10 +42,13 @@ module Webmocks
40
42
  plug: {
41
43
  id: "plg_#{Faker::Alphanumeric.alphanumeric(number: 26).upcase}",
42
44
  },
43
- settings: {
44
- from_email: "new@from.company",
45
+ settings: github_installations,
46
+ credentials: {
47
+ access_token: Faker::Alphanumeric.alphanumeric(number: 26).upcase,
48
+ refresh_access_token: "refresher",
49
+ expires_at: expires_at.iso8601,
45
50
  },
46
- }
51
+ }.merge(response)
47
52
 
48
53
  stub_request(:get, "#{::YettoService::YETTO_API_VERSION_TLD}/installations/#{plug_installation_id}")
49
54
  .to_return(
@@ -73,16 +78,34 @@ module Webmocks
73
78
  )
74
79
  end
75
80
 
76
- def assert_requested_create_message(inbox_id)
81
+ def assert_requested_create_message(plug_installation_id, message_id)
77
82
  assert_requested_post_access_token(plug_installation_id)
78
83
 
79
- assert_requested(:post, "#{::YettoService::YETTO_API_VERSION_TLD}/inboxes/#{inbox_id}/messages")
84
+ assert_requested(:post, "#{::YettoService::YETTO_API_VERSION_TLD}/messages/#{message_id}/replies")
80
85
  end
81
86
 
82
- def stub_create_message(inbox_id, payload)
87
+ def stub_create_message(plug_installation_id, message_id, payload)
83
88
  stub_post_access_token(plug_installation_id)
84
89
 
85
- stub_request(:post, "#{::YettoService::YETTO_API_VERSION_TLD}/inboxes/#{inbox_id}/messages")
90
+ stub_request(:post, "#{::YettoService::YETTO_API_VERSION_TLD}/messages/#{message_id}/replies")
91
+ # .with(
92
+ # body: payload,
93
+ # )
94
+ # .to_return(
95
+ # status: 200,
96
+ # headers: { content_type: "application/json; charset=utf-8" },
97
+ # body: {}.to_json,
98
+ # )
99
+ end
100
+
101
+ def assert_requested_update_message_metadata(plug_installation_id, message_id)
102
+ assert_requested_post_access_token(plug_installation_id)
103
+ assert_requested(:patch, "#{::YettoService::YETTO_API_VERSION_TLD}/messages/#{message_id}")
104
+ end
105
+
106
+ def stub_update_message_metadata(plug_installation_id, message_id, payload)
107
+ stub_post_access_token(plug_installation_id)
108
+ stub_request(:patch, "#{::YettoService::YETTO_API_VERSION_TLD}/messages/#{message_id}")
86
109
  .with(
87
110
  body: payload,
88
111
  )
@@ -98,13 +121,9 @@ module Webmocks
98
121
  assert_requested(:post, "#{::YettoService::YETTO_API_VERSION_TLD}/inboxes/#{inbox_id}/switches")
99
122
  end
100
123
 
101
- def stub_create_inbox_switch(inbox_id, plug_installation_id, params)
124
+ def stub_create_inbox_switch(inbox_id, plug_installation_id, payload)
102
125
  stub_post_access_token(plug_installation_id)
103
126
 
104
- payload = {
105
- name: "After install",
106
- }
107
-
108
127
  stub_request(:post, "#{::YettoService::YETTO_API_VERSION_TLD}/inboxes/#{inbox_id}/switches")
109
128
  .with(
110
129
  body: payload,
@@ -1,4 +1,3 @@
1
- # fly.toml app configuration file generated for plug-app on 2023-05-05T07:11:14-04:00
2
1
  #
3
2
  # See https://fly.io/docs/reference/configuration/ for information about how to use this file.
4
3
  #
@@ -7,32 +6,35 @@ app = "plug-app-production"
7
6
  primary_region = "iad"
8
7
 
9
8
  [env]
10
- RAILS_ENV = "production"
11
- LD_PRELOAD_PATH = "/usr/lib/x86_64-linux-gnu/libjemalloc.so.2"
9
+ RAILS_ENV = "production"
10
+ LD_PRELOAD_PATH = "/usr/lib/x86_64-linux-gnu/libjemalloc.so.2"
12
11
 
13
12
  [processes]
14
- web = "./bin/rails server"
15
- worker = "bundle exec sidekiq"
13
+ web = "./bin/rails server"
14
+ worker = "bundle exec sidekiq"
16
15
 
17
16
  [http_service]
18
- internal_port = 3000
19
- force_https = true
20
- auto_stop_machines = true
21
- auto_start_machines = true
22
- min_machines_running = 1
23
- processes = ["web"]
24
- [http_service.concurrency]
25
- type = "requests"
26
- soft_limit = 200
27
- hard_limit = 250
17
+ internal_port = 3000
18
+ force_https = true
19
+ auto_stop_machines = true
20
+ auto_start_machines = true
21
+ min_machines_running = 1
22
+ processes = ["web"]
23
+ [http_service.concurrency]
24
+ type = "requests"
25
+ soft_limit = 200
26
+ hard_limit = 250
28
27
 
29
28
  [checks]
30
- [checks.alive]
31
- type = "tcp"
32
- interval = "15s"
33
- timeout = "2s"
34
- grace_period = "5s"
29
+ [checks.alive]
30
+ type = "tcp"
31
+ interval = "15s"
32
+ timeout = "2s"
33
+ grace_period = "5s"
35
34
 
36
35
  [[statics]]
37
- guest_path = "/plug-app/public"
38
- url_prefix = "/"
36
+ guest_path = "/plug-app/public"
37
+ url_prefix = "/"
38
+
39
+ [deploy]
40
+ strategy = "bluegreen"
@@ -2,32 +2,35 @@ app = "plug-app-staging"
2
2
  primary_region = "iad"
3
3
 
4
4
  [env]
5
- RAILS_ENV = "plug-app-staging"
6
- LD_PRELOAD_PATH = "/usr/lib/x86_64-linux-gnu/libjemalloc.so.2"
5
+ RAILS_ENV = "plug-app-staging"
6
+ LD_PRELOAD_PATH = "/usr/lib/x86_64-linux-gnu/libjemalloc.so.2"
7
7
 
8
8
  [processes]
9
- web = "./bin/rails server"
10
- worker = "bundle exec sidekiq"
9
+ web = "./bin/rails server"
10
+ worker = "bundle exec sidekiq"
11
11
 
12
12
  [http_service]
13
- internal_port = 3000
14
- force_https = true
15
- auto_stop_machines = true
16
- auto_start_machines = true
17
- min_machines_running = 0
18
- processes = ["web"]
19
- [http_service.concurrency]
20
- type = "requests"
21
- soft_limit = 200
22
- hard_limit = 250
13
+ internal_port = 3000
14
+ force_https = true
15
+ auto_stop_machines = true
16
+ auto_start_machines = true
17
+ min_machines_running = 0
18
+ processes = ["web"]
19
+ [http_service.concurrency]
20
+ type = "requests"
21
+ soft_limit = 200
22
+ hard_limit = 250
23
23
 
24
24
  [checks]
25
- [checks.alive]
26
- type = "tcp"
27
- interval = "15s"
28
- timeout = "2s"
29
- grace_period = "5s"
25
+ [checks.alive]
26
+ type = "tcp"
27
+ interval = "15s"
28
+ timeout = "2s"
29
+ grace_period = "5s"
30
30
 
31
31
  [[statics]]
32
- guest_path = "/plug-app/public"
33
- url_prefix = "/"
32
+ guest_path = "/plug-app/public"
33
+ url_prefix = "/"
34
+
35
+ [deploy]
36
+ strategy = "immediate"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hephaestus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garen Torikian
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-18 00:00:00.000000000 Z
11
+ date: 2023-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -171,6 +171,7 @@ files:
171
171
  - templates/app/lib/plug_app/middleware/not_found.rb
172
172
  - templates/app/lib/plug_app/middleware/openapi_validation.rb
173
173
  - templates/app/lib/plug_app/middleware/tracing_attributes.rb
174
+ - templates/app/lib/plug_app/switches/message_created.jsonc
174
175
  - templates/app/lib/query_parameter.rb
175
176
  - templates/app/serializers/error_serializer.rb
176
177
  - templates/app/services/http_service.rb
@@ -178,6 +179,7 @@ files:
178
179
  - templates/app/views/settings/new.json.jbuilder
179
180
  - templates/bin/docker-entrypoint
180
181
  - templates/compose.yml
182
+ - templates/config/initializers/000-oj.rb
181
183
  - templates/config/initializers/cors.rb
182
184
  - templates/config/initializers/environment.rb
183
185
  - templates/config/initializers/filter_parameter_logging.rb
@@ -197,8 +199,8 @@ files:
197
199
  - templates/lib/plug_app/schemas/api/2023-03-06/components/schemas/yetto.json
198
200
  - templates/lib/plug_app/schemas/api/2023-03-06/openapi.json
199
201
  - templates/lib/plug_app/schemas/api/2023-03-06/paths/plug.json
200
- - templates/lib/plug_app/schemas/api/2023-03-06/paths/yetto/after_create_message.json
201
- - templates/lib/plug_app/schemas/api/2023-03-06/paths/yetto/after_create_plug_installation.json
202
+ - templates/lib/plug_app/schemas/api/2023-03-06/paths/yetto/message_created.json
203
+ - templates/lib/plug_app/schemas/api/2023-03-06/paths/yetto/plug_installation_created.json
202
204
  - templates/lib/tasks/test_tasks.rake
203
205
  - templates/script/ci
204
206
  - templates/script/edit-credentials
@@ -214,6 +216,10 @@ files:
214
216
  - templates/test/controllers/settings_controller_test.rb
215
217
  - templates/test/controllers/yetto_controller_test.rb
216
218
  - templates/test/fixtures/files/fake_pem_file/fake.pem
219
+ - templates/test/fixtures/files/plug_installation_settings/invalid.json
220
+ - templates/test/fixtures/files/plug_installation_settings/valid.json
221
+ - templates/test/fixtures/plug_installation_settings/invalid.json
222
+ - templates/test/fixtures/plug_installation_settings/valid.json
217
223
  - templates/test/integration/.keep
218
224
  - templates/test/jobs/update_yetto_job_test.rb
219
225
  - templates/test/mailers/.keep
@@ -245,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
245
251
  - !ruby/object:Gem::Version
246
252
  version: 3.4.7
247
253
  requirements: []
248
- rubygems_version: 3.4.19
254
+ rubygems_version: 3.4.20
249
255
  signing_key:
250
256
  specification_version: 4
251
257
  summary: Generate a Rails app that can be used to create plugs for Yetto.