webhukhs 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yard-lint.yml +1 -0
- data/AGENTS.md +9 -11
- data/Appraisals +2 -2
- data/CHANGELOG.md +13 -0
- data/README.md +98 -10
- data/Rakefile +7 -0
- data/example/Gemfile +5 -6
- data/example/Gemfile.lock +260 -141
- data/example/app/webhooks/acme_handler.rb +16 -0
- data/example/app/webhooks/flaky_handler.rb +8 -0
- data/example/app/webhooks/signed_handler.rb +10 -0
- data/example/config/initializers/webhukhs.rb +4 -3
- data/example/config/routes.rb +3 -0
- data/example/db/migrate/20240601000000_add_headers_to_webhukhs_webhooks.rb +7 -0
- data/example/db/schema.rb +2 -1
- data/example/db/seeds.rb +71 -7
- data/gemfiles/{rails_7.1.gemfile → rails_7.2.gemfile} +1 -4
- data/gemfiles/rails_7.2.gemfile.lock +477 -0
- data/gemfiles/rails_8.0.gemfile +0 -3
- data/gemfiles/rails_8.0.gemfile.lock +74 -4
- data/gemfiles/rails_8.1.gemfile +0 -3
- data/gemfiles/rails_8.1.gemfile.lock +74 -4
- data/gemfiles/rails_master.gemfile +0 -3
- data/lib/webhukhs/admin/application_controller.rb +32 -0
- data/lib/webhukhs/admin/assets/admin.css +476 -0
- data/lib/webhukhs/admin/assets/admin.js +111 -0
- data/lib/webhukhs/admin/config/routes.rb +6 -0
- data/lib/webhukhs/admin/engine.rb +20 -0
- data/lib/webhukhs/admin/received_webhook_presenter.rb +63 -0
- data/lib/webhukhs/admin/received_webhooks_controller.rb +60 -0
- data/lib/webhukhs/admin/view_helper.rb +50 -0
- data/lib/webhukhs/admin/views/layouts/webhukhs/admin/application.html.erb +22 -0
- data/lib/webhukhs/admin/views/webhukhs/admin/received_webhooks/index.html.erb +50 -0
- data/lib/webhukhs/admin/views/webhukhs/admin/received_webhooks/show.html.erb +55 -0
- data/lib/webhukhs/admin.rb +17 -0
- data/lib/webhukhs/engine.rb +0 -4
- data/lib/webhukhs/models/received_webhook.rb +3 -0
- data/lib/webhukhs/version.rb +1 -1
- data/test/admin_test.rb +334 -0
- data/test/base_handler_test.rb +3 -3
- data/test/browser/admin_click_through.rb +208 -0
- data/test/processing_job_test.rb +15 -28
- data/test/received_webhook_test.rb +16 -0
- data/test/test_app.rb +2 -0
- data/test/test_helper.rb +9 -6
- data/test/webhukhs_test.rb +20 -62
- metadata +165 -8
- data/example/.ruby-version +0 -1
- data/gemfiles/rails_7.1.gemfile.lock +0 -412
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cae5927b7426085a8e140f6bdb4565423d43d1b72c65b65c9602b72bd81a1338
|
|
4
|
+
data.tar.gz: e77b5321fbd8b814b3d6265da104ec9b4e77ffc36a2d0b0c62e67ae1c1f3ff05
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 40519e7b2ca3b8c8e4bbf924f78d86269f6f4b68b1a72f3a7f963ec87fde656f49db69c6268de76f19b22ec762e3e14078c9839f44e080b41bc1e99131ecb449
|
|
7
|
+
data.tar.gz: 2a8e469254e9f76b46068a9b06001157f570f33a6cab931c2ee23cada3c13eadbff765c368cba58e6a62a1d657db8d142a2f89d2b8fe94b4034eb76f45cb4e6c
|
data/.yard-lint.yml
CHANGED
data/AGENTS.md
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
You are working in a Ruby project that uses mutation testing.
|
|
1
|
+
You are working in a Ruby project that uses mutation testing, but also tracks line and branch coverage.
|
|
2
2
|
|
|
3
3
|
## Goal
|
|
4
4
|
|
|
5
|
-
Achieve 100% mutation coverage. Verify with:
|
|
5
|
+
Achieve 100% line, branch and mutation coverage. Verify with:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
SIMPLECOV=1 bundle exec rspec
|
|
9
|
+
```
|
|
6
10
|
|
|
7
11
|
```
|
|
8
12
|
bundle exec mutant run
|
|
9
13
|
```
|
|
10
14
|
|
|
11
|
-
When iterating, prefer `--fail-fast` so you address one surviving
|
|
15
|
+
When iterating mutant coverage, prefer `--fail-fast` so you address one surviving
|
|
12
16
|
mutant at a time:
|
|
13
17
|
|
|
14
18
|
```
|
|
15
19
|
bundle exec mutant run --fail-fast
|
|
16
20
|
```
|
|
17
21
|
|
|
18
|
-
## When you find
|
|
22
|
+
## When you find coverage issue
|
|
19
23
|
|
|
20
24
|
Decide which bucket it falls into:
|
|
21
25
|
|
|
@@ -36,16 +40,10 @@ the user.
|
|
|
36
40
|
|
|
37
41
|
## Constraints
|
|
38
42
|
|
|
39
|
-
- Line coverage must stay at 100%. Verify with:
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
SIMPLECOV=1 bundle exec rspec
|
|
43
|
-
```
|
|
44
|
-
|
|
45
43
|
- You may not skip mutants by configuring mutant to ignore them.
|
|
46
44
|
No `expressions:` filters, no `coverage_criteria:` tweaks.
|
|
47
45
|
- You may not use `send` or `__send__` to invoke private methods
|
|
48
|
-
in tests just to satisfy
|
|
46
|
+
in tests just to satisfy coverage requirement.
|
|
49
47
|
- You may not stub or mock the system under test (`Age`).
|
|
50
48
|
|
|
51
49
|
## Done
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ This format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 0.8.0
|
|
9
|
+
## Added
|
|
10
|
+
- An optional, read-only admin engine (`require "webhukhs/admin"`, mount `Webhukhs::Admin::Engine`) to list,
|
|
11
|
+
sort, filter and inspect received webhooks
|
|
12
|
+
- `bin/dev`, which runs the `example` app - now with the admin mounted, more handlers and seed data
|
|
13
|
+
|
|
14
|
+
## Fixed
|
|
15
|
+
- Form-encoded webhooks were stored with an empty body: Rails had already read the body stream to parse
|
|
16
|
+
the params by the time Webhukhs got to it
|
|
17
|
+
|
|
18
|
+
## Changed
|
|
19
|
+
- Rails 7.2 or newer is now required (and with it Ruby 3.1), and the test matrix runs Rails 7.2 instead of 7.1
|
|
20
|
+
|
|
8
21
|
## 0.7.0
|
|
9
22
|
## Added
|
|
10
23
|
- Codebase is fully mutant tested now and test coverage increased
|
data/README.md
CHANGED
|
@@ -19,32 +19,116 @@ Generate migrations and initializer file.
|
|
|
19
19
|
|
|
20
20
|
`bin/rails g webhukhs:install`
|
|
21
21
|
|
|
22
|
-
Mount webhukhs engine in
|
|
22
|
+
Mount webhukhs engine in `config/routes.rb` file (simple approach, with only one dynamic route showing up in `rails routes`)
|
|
23
23
|
|
|
24
24
|
```ruby
|
|
25
25
|
mount Webhukhs::Engine, at: "/webhooks"
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
Advanced mounting approach (all webhooks paths will be shown in `rails routes`)
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
Webhukhs.configuration.active_handlers.each_key do |service_id|
|
|
32
|
+
post "/webhooks/#{service_id}",
|
|
33
|
+
to: "webhukhs/receive_webhooks#create",
|
|
34
|
+
defaults: { service_id: service_id },
|
|
35
|
+
as: :"#{service_id.tr('-', '_')}_webhook"
|
|
36
|
+
end
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Define a class for your first handler (let's call it `ExampleHandler`) and inherit it from `Webhukhs::BaseHandler`. We recommend `app/webhooks`, but any place known to autoloading will do.
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
# app/webhooks/example_handler.rb
|
|
43
|
+
class ExampleHandler < Webhukhs::BaseHandler
|
|
44
|
+
# Called asynchronously to process a stored webhook.
|
|
45
|
+
def process(received_webhook)
|
|
46
|
+
payload = JSON.parse(received_webhook.body, symbolize_names: true)
|
|
47
|
+
# handle payload...
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Optional: verify the request signature before processing.
|
|
51
|
+
# Return false to mark the webhook as failed_validation.
|
|
52
|
+
def valid?(action_dispatch_request)
|
|
53
|
+
action_dispatch_request.headers["X-Secret-Token"] == ENV["EXAMPLE_WEBHOOK_SECRET"]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Optional: use a sender-supplied ID for deduplication.
|
|
57
|
+
def extract_event_id_from_request(action_dispatch_request)
|
|
58
|
+
action_dispatch_request.headers["X-Event-Id"] || SecureRandom.uuid
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Add the handler to your `webhukhs.rb` config file:
|
|
29
64
|
|
|
30
65
|
```ruby
|
|
31
66
|
Webhukhs.configure do |config|
|
|
32
67
|
config.active_handlers = {
|
|
33
|
-
"
|
|
68
|
+
"example" => "ExampleHandler"
|
|
34
69
|
}
|
|
35
70
|
end
|
|
36
71
|
```
|
|
37
72
|
|
|
38
|
-
|
|
39
|
-
- `example` folder contains a demo app with engine fully configured.
|
|
40
|
-
- We provide a number of webhook handlers which demonstrate certain features of Webhukhs. You will find them in `handler-examples`.
|
|
73
|
+
Now you will be able to accept webhooks on `/webhooks/example` path.
|
|
41
74
|
|
|
42
|
-
##
|
|
75
|
+
## Admin
|
|
76
|
+
|
|
77
|
+
Webhukhs comes with a read-only admin for looking at the webhooks you have received: a sortable,
|
|
78
|
+
filterable list, and a page per webhook with its body (pretty-printed when it is JSON) and the
|
|
79
|
+
request headers it arrived with. It is not loaded by default - require it in your Gemfile (it has to be
|
|
80
|
+
loaded before the app boots, so `config/routes.rb` is too late):
|
|
43
81
|
|
|
44
|
-
|
|
82
|
+
```ruby
|
|
83
|
+
gem "webhukhs", require: ["webhukhs", "webhukhs/admin"]
|
|
84
|
+
```
|
|
45
85
|
|
|
46
|
-
|
|
47
|
-
|
|
86
|
+
and mount it:
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
# config/routes.rb
|
|
90
|
+
Rails.application.routes.draw do
|
|
91
|
+
mount Webhukhs::Admin::Engine, at: "/admin/webhooks"
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The admin does no authentication of its own, and webhook bodies tend to carry personal data and
|
|
96
|
+
secrets - so mount it behind whatever guards the rest of your admin. For example, with Devise:
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
authenticate :user, ->(user) { user.admin? } do
|
|
100
|
+
mount Webhukhs::Admin::Engine, at: "/admin/webhooks"
|
|
101
|
+
end
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
or with HTTP basic auth:
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
webhukhs_admin = Rack::Builder.new do
|
|
108
|
+
use Rack::Auth::Basic do |username, password|
|
|
109
|
+
ActiveSupport::SecurityUtils.secure_compare(username, ENV.fetch("ADMIN_USER")) &
|
|
110
|
+
ActiveSupport::SecurityUtils.secure_compare(password, ENV.fetch("ADMIN_PASSWORD"))
|
|
111
|
+
end
|
|
112
|
+
run Webhukhs::Admin::Engine
|
|
113
|
+
end
|
|
114
|
+
mount webhukhs_admin, at: "/admin/webhooks"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The admin brings its own CSS and JS, served by [Assiette](https://github.com/julik/assiette) from
|
|
118
|
+
inside the engine - it does not touch your asset pipeline (Propshaft, Sprockets or anything else) and needs
|
|
119
|
+
no build step.
|
|
120
|
+
|
|
121
|
+
To try it out, run `bin/dev` from a checkout of this repository. It starts the app in `example`
|
|
122
|
+
with some webhooks seeded, and the admin at http://localhost:3000/admin/webhukhs.
|
|
123
|
+
|
|
124
|
+
## More Examples
|
|
125
|
+
- `example` folder contains a demo app with the engine and the admin fully configured - run it with `bin/dev`.
|
|
126
|
+
- We provide a number of webhook handlers which demonstrate certain features of Webhukhs. You will find them in `handler-examples`.
|
|
127
|
+
|
|
128
|
+
## Requirements
|
|
129
|
+
|
|
130
|
+
- Ruby >= 3.1
|
|
131
|
+
- Rails >= 7.2
|
|
48
132
|
|
|
49
133
|
## Error reporter
|
|
50
134
|
|
|
@@ -64,6 +148,10 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
|
64
148
|
|
|
65
149
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
66
150
|
|
|
151
|
+
The admin also has a click-through test in a real (headless) Chrome, which `rake test` leaves out.
|
|
152
|
+
Run it with `bundle exec rake test:browser` - it needs Chrome or Chromium installed, and finds it
|
|
153
|
+
by itself or through `BROWSER_PATH`.
|
|
154
|
+
|
|
67
155
|
## Contributing
|
|
68
156
|
|
|
69
157
|
Bug reports and pull requests are welcome on GitHub at https://github.com/skatkov/webhukhs.
|
data/Rakefile
CHANGED
|
@@ -23,4 +23,11 @@ Rake::TestTask.new(:test) do |t|
|
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
# Needs Chrome, so it stays out of the default task
|
|
27
|
+
Rake::TestTask.new("test:browser") do |t|
|
|
28
|
+
t.libs << "test"
|
|
29
|
+
t.libs << "lib"
|
|
30
|
+
t.test_files = FileList["test/browser/**/*.rb"]
|
|
31
|
+
end
|
|
32
|
+
|
|
26
33
|
task default: [:test, :standard]
|
data/example/Gemfile
CHANGED
|
@@ -3,23 +3,22 @@
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
|
5
5
|
|
|
6
|
-
ruby "3.2.2"
|
|
7
|
-
|
|
8
6
|
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
|
|
9
|
-
gem "rails", ">= 7.
|
|
7
|
+
gem "rails", ">= 7.2"
|
|
10
8
|
|
|
11
9
|
# The modern asset pipeline for Rails [https://github.com/rails/propshaft]
|
|
12
10
|
gem "propshaft"
|
|
13
11
|
|
|
14
12
|
# Use sqlite3 as the database for Active Record
|
|
15
|
-
gem "sqlite3", "
|
|
13
|
+
gem "sqlite3", ">= 2.1"
|
|
16
14
|
|
|
17
15
|
# Use the Puma web server [https://github.com/puma/puma]
|
|
18
|
-
gem "puma", "
|
|
16
|
+
gem "puma", ">= 6.0"
|
|
19
17
|
|
|
20
18
|
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
|
21
19
|
gem "tzinfo-data", platforms: %i[mingw mswin x64_mingw jruby]
|
|
22
|
-
|
|
20
|
+
# The admin is optional, and has to be required before the app boots
|
|
21
|
+
gem "webhukhs", path: "../", require: ["webhukhs", "webhukhs/admin"]
|
|
23
22
|
|
|
24
23
|
group :development, :test do
|
|
25
24
|
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|