hooks-ruby 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7588a4a6fdf58e7c927dc4b20b9fa330db86db672f5c779a4c46d51e7e41f386
4
+ data.tar.gz: 02bdb939c52fd501387856f432a11a82f842d25053d9e73ef3967eb12be03c7a
5
+ SHA512:
6
+ metadata.gz: f11eddcaf09095e1d68bcfeeeba3660eab7e3a9bf42744d780987bfb4b54db7cfa6691c4cc435c5dbda4eb3ee60065a6f3c6239df87bf5b5587f638bb3c8d094
7
+ data.tar.gz: af806e9c8144ed2da97e723c3a4dfcb54f2fd8db85970e806aa3f2f56e6ef8ca665ae157066f1456126804c2bba8ba573d5f59f717de0249148d81d11f9e848d
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 GitHub
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,295 @@
1
+ # hooks
2
+
3
+ [![build](https://github.com/github/hooks/actions/workflows/build.yml/badge.svg)](https://github.com/github/hooks/actions/workflows/build.yml)
4
+ [![test](https://github.com/github/hooks/actions/workflows/test.yml/badge.svg)](https://github.com/github/hooks/actions/workflows/test.yml)
5
+ [![lint](https://github.com/github/hooks/actions/workflows/lint.yml/badge.svg)](https://github.com/github/hooks/actions/workflows/lint.yml)
6
+ [![integration](https://github.com/github/hooks/actions/workflows/integration.yml/badge.svg)](https://github.com/github/hooks/actions/workflows/integration.yml)
7
+ [![release](https://github.com/github/hooks/actions/workflows/release.yml/badge.svg)](https://github.com/github/hooks/actions/workflows/release.yml)
8
+
9
+ A Pluggable Webhook Server Framework written in Ruby.
10
+
11
+ ![hooks](docs/assets/hooks.png)
12
+
13
+ ## About ⭐
14
+
15
+ Hooks is a RESTful webhook server framework written in Ruby. It is designed to be simple, flexible, and extensible, allowing you to easily create and manage webhook endpoints for your applications. Hooks is designed to consolidate and process incoming webhook requests in a single place, making it easier to handle webhooks from multiple sources.
16
+
17
+ **Why Hooks?**: If you have to handle webhooks from multiple sources, you might end up with a lot of code that is similar but not quite the same. Hooks allows you to define a set of common behaviors and then extend them with plugins, so you can handle webhooks in a consistent way across your application.
18
+
19
+ ## Features 🚀
20
+
21
+ - **Pluggable Architecture**: Easily extend the functionality of your webhook server with plugins for authentication, handlers, and more.
22
+ - **Flexible Configuration**: Customize your webhook server via a simple configuration file, or programmatically with pure Ruby.
23
+ - **Built-in Auth Plugins**: Support for common authentication methods like HMAC, shared secrets, and more.
24
+
25
+ ## How It Works 🔧
26
+
27
+ Hooks is designed to be very easy to setup and use. It provides a simple DSL for defining webhook endpoints and then you can use plugins to handle the incoming requests and optionally authenticate them.
28
+
29
+ Here is a very high-level overview of how Hooks works:
30
+
31
+ 1. You define a global configuration file (e.g. `hooks.yml`) where you can specify where your webhook endpoint configs are located, and the directory where your plugins are located. Here is an example of a minimal configuration file:
32
+
33
+ ```yaml
34
+ # file: hooks.yml
35
+ handler_plugin_dir: ./plugins/handlers
36
+ auth_plugin_dir: ./plugins/auth
37
+ endpoints_dir: ./config/endpoints
38
+
39
+ log_level: debug
40
+
41
+ root_path: /webhooks
42
+ health_path: /health
43
+ version_path: /version
44
+
45
+ environment: development
46
+ ```
47
+
48
+ 2. Then in your `config/endpoints` directory, you can define all your webhook endpoints in separate files. Here is an example of a simple endpoint configuration file:
49
+
50
+ ```yaml
51
+ # file: config/endpoints/hello.yml
52
+ path: /hello
53
+ handler: MyCustomHandler # This is a custom handler plugin you would define in the plugins/handlers directory
54
+ ```
55
+
56
+ 3. Now create a corresponding handler plugin in the `plugins/handlers` directory. Here is an example of a simple handler plugin:
57
+
58
+ ```ruby
59
+ # file: plugins/handlers/my_custom_handler.rb
60
+ class MyCustomHandler < Hooks::Plugins::Handlers::Base
61
+ def call(payload:, headers:, config:)
62
+ # Process the incoming webhook - optionally use the payload and headers
63
+ # to perform some action or validation
64
+ # For this example, we will just return a success message
65
+ {
66
+ status: "success",
67
+ handler: "MyCustomHandler",
68
+ payload_received: payload,
69
+ timestamp: Time.now.iso8601
70
+ }
71
+ end
72
+ end
73
+ ```
74
+
75
+ That is pretty much it! Below you will find more detailed instructions on how to install and use Hooks, as well as how to create your own plugins. This high-level overview should give you a good idea of how Hooks works and how you can use it to handle webhooks in your applications. You may also be interested in using your own custom authentication plugins to secure your webhook endpoints, which is covered in the [Authentication](#authentication) section below.
76
+
77
+ ## Installation 💎
78
+
79
+ You can download this Gem from [GitHub Packages](https://github.com/github/hooks/pkgs/rubygems/hooks-ruby) or [RubyGems](https://rubygems.org/gems/hooks-ruby)
80
+
81
+ Via a Gemfile:
82
+
83
+ ```ruby
84
+ source "https://rubygems.org"
85
+
86
+ gem "hooks-ruby", "~> X.X.X" # Replace X.X.X with the latest version
87
+ ```
88
+
89
+ Once added to your Gemfile, run:
90
+
91
+ ```bash
92
+ bundle install
93
+ ```
94
+
95
+ ## Usage 💻
96
+
97
+ ### Basic
98
+
99
+ Here is a simple example of how to set up a Hooks server.
100
+
101
+ First, create a `config.ru` file:
102
+
103
+ ```ruby
104
+ # file: config.ru
105
+ require "hooks-ruby"
106
+
107
+ # See the config documentation below for the full list of available options
108
+ # For this example, we will just set use_catchall_route to true
109
+ config = {
110
+ use_catchall_route: true # will use the DefaultHandler for /webhooks/* - just an example/demo
111
+ }
112
+
113
+ # Builds the Hooks application with the provided configuration
114
+ app = Hooks.build(config: config)
115
+
116
+ # Run the Hooks application when the server starts
117
+ run app
118
+ ```
119
+
120
+ Run the hooks server via puma which is the recommended server for Hooks:
121
+
122
+ ```bash
123
+ bundle exec puma --tag hooks
124
+ ```
125
+
126
+ Send a webhook request to the server in a separate terminal:
127
+
128
+ ```bash
129
+ curl --request POST \
130
+ --url http://0.0.0.0:9292/webhooks/hello \
131
+ --header 'content-type: application/json' \
132
+ --data '{}'
133
+
134
+ # => { "message": "webhook processed successfully", "handler": "DefaultHandler", "timestamp": "2025-06-10T23:15:07-07:00" }
135
+ ```
136
+
137
+ Congratulations! You have successfully set up a basic Hooks server which will listen to anything under `/webhooks/*` and respond with a success message.
138
+
139
+ Keep reading to learn how to customize your Hooks server with different plugins for handlers, authentication, and more.
140
+
141
+ ### Advanced
142
+
143
+ This section will go into a more advanced and detailed example of how to setup a Hooks server with custom plugins, authentication, and more. This section also assumes you already have the `hooks-ruby` gem installed via a bundler Gemfile as shown in the [Installation](#installation-) section above.
144
+
145
+ Before we get into the details, here is a high-level overview of the steps involved:
146
+
147
+ 1. **Define your configuration**: Create a `hooks.yml` file to define your global configuration, including the directories for your plugins and endpoints.
148
+ 2. **Create your endpoint configurations**: Define your webhook endpoints in the `config/endpoints` directory, specifying the path and the handler plugin to use.
149
+ 3. **Implement your handler plugins**: Create custom handler plugins in the `plugins/handlers` directory to process incoming webhook requests.
150
+ 4. **Implement authentication plugins (optional)**: If you want to secure your webhook endpoints, create custom authentication plugins in the `plugins/auth` directory. Note that you might just be able to get away with using the built-in authentication plugins ([`hmac`](lib/hooks/plugins/auth/hmac.rb), or [`shared_secret`](lib/hooks/plugins/auth/shared_secret.rb)) for most use cases.
151
+
152
+ This example will assume the following directory structure:
153
+
154
+ ```text
155
+ ├── config/
156
+ │ ├── hooks.yml # global hooks config
157
+ │ ├── puma.rb # puma config
158
+ │ └── endpoints/
159
+ │ ├── hello.yml
160
+ │ └── goodbye.yml
161
+ └── plugins/
162
+ ├── handlers/ # custom handler plugins
163
+ │ ├── hello_handler.rb
164
+ │ └── goodbye_handler.rb
165
+ └── auth/
166
+ └── goodbye_auth.rb # custom auth plugin (optional)
167
+ ```
168
+
169
+ Let's go through each step in detail.
170
+
171
+ #### 1. Define your global Hooks configuration
172
+
173
+ First, create a `hooks.yml` file in the `config` directory. This file will define your global configuration for the Hooks server, including the directories for your plugins and endpoints. Here is an example of a minimal configuration file:
174
+
175
+ ```yaml
176
+ # file: config/hooks.yml
177
+ handler_plugin_dir: ./plugins/handlers
178
+ auth_plugin_dir: ./plugins/auth
179
+
180
+ # Available endpoints
181
+ # Each endpoint configuration file should be placed in the endpoints directory
182
+ endpoints_dir: ./config/endpoints
183
+
184
+ log_level: debug
185
+
186
+ # Path configuration
187
+ root_path: /webhooks # Base path for all webhook endpoints (e.g. /webhooks/hello)
188
+ health_path: /health
189
+ version_path: /version
190
+
191
+ # Runtime behavior
192
+ environment: development # or production
193
+ ```
194
+
195
+ #### 2. Create your endpoint configurations
196
+
197
+ Endpoint configurations are defined in the `config/endpoints` directory. Each endpoint configuration file should specify the path for the webhook endpoint and the handler plugin to use. Here is an example of two endpoint configuration files:
198
+
199
+ > Note: You can also define auth plugins for each endpoint if you want to secure them. For this example, the `/hello` endpoint will not have authentication, while the `/goodbye` endpoint will use a custom authentication plugin.
200
+
201
+ ```yaml
202
+ # file: config/endpoints/hello.yml
203
+ path: /hello # becomes /webhooks/hello based on the root_path in hooks.yml
204
+ handler: HelloHandler # This is a custom handler plugin you would define in the plugins/handlers
205
+ ```
206
+
207
+ ```yaml
208
+ # file: config/endpoints/goodbye.yml
209
+ path: /goodbye # becomes /webhooks/goodbye based on the root_path in hooks.yml
210
+ handler: GoodbyeHandler # This is another custom handler plugin you would define in the plugins/handlers
211
+
212
+ auth:
213
+ type: Goodbye # This is a custom authentication plugin you would define in the plugins/auth
214
+ secret_env_key: GOODBYE_API_KEY # the name of the environment variable containing the secret
215
+ header: Authorization
216
+ ```
217
+
218
+ #### 3. Implement your handler plugins
219
+
220
+ Create custom handler plugins in the `plugins/handlers` directory to process incoming webhook requests. Here is an example of a simple handler plugin for the `/hello` endpoint:
221
+
222
+ ```ruby
223
+ # file: plugins/handlers/hello_handler.rb
224
+ class HelloHandler < Hooks::Plugins::Handlers::Base
225
+ def call(payload:, headers:, config:)
226
+ # Process the incoming webhook - optionally use the payload and headers
227
+ # to perform some action or validation
228
+ # For this example, we will just return a success message
229
+ {
230
+ message: "webhook processed successfully",
231
+ handler: "HelloHandler",
232
+ timestamp: Time.now.iso8601
233
+ }
234
+ end
235
+ end
236
+ ```
237
+
238
+ And another handler plugin for the `/goodbye` endpoint:
239
+
240
+ ```ruby
241
+ # file: plugins/handlers/goodbye_handler.rb
242
+ class GoodbyeHandler < Hooks::Plugins::Handlers::Base
243
+ def call(payload:, headers:, config:)
244
+ # Ditto for the goodbye endpoint
245
+ {
246
+ message: "goodbye webhook processed successfully",
247
+ handler: "GoodbyeHandler",
248
+ timestamp: Time.now.iso8601
249
+ }
250
+ end
251
+ end
252
+ ```
253
+
254
+ #### 4. Implement authentication plugins (optional)
255
+
256
+ If you want to secure your webhook endpoints, you can create custom authentication plugins in the `plugins/auth` directory. Here is an example of a simple authentication plugin for the `/goodbye` endpoint:
257
+
258
+ ```ruby
259
+ # file: plugins/auth/goodbye.rb
260
+ # this is a custom authentication plugin for the Goodbye endpoint
261
+ # it is extremely simple and just checks if the Authorization header matches a secret for example purposes
262
+ module Hooks
263
+ module Plugins
264
+ module Auth
265
+ class Goodbye < Base
266
+ def self.valid?(payload:, headers:, config:)
267
+ # get the secret from environment variable as configured with secret_env_key
268
+ secret = fetch_secret(config, secret_env_key_name: :secret_env_key)
269
+
270
+ # check if the Authorization header matches the secret
271
+ auth_header = headers[config[:header]]
272
+ return false unless auth_header
273
+
274
+ # compare the Authorization header with the secret
275
+ Rack::Utils.secure_compare(auth_header, "Bearer #{secret}")
276
+ end
277
+ end
278
+ end
279
+ end
280
+ end
281
+ ```
282
+
283
+ #### Summary
284
+
285
+ What these steps have done is set up a Hooks server that listens for incoming webhook requests at `/webhooks/hello` and `/webhooks/goodbye`. The `/hello` endpoint will respond with a success message without any authentication, while the `/goodbye` endpoint will require a valid `Authorization` header that matches the secret defined in the environment variable `GOODBYE_API_KEY`. Before the `/goodbye` endpoint enters the defined handler, it will first check the authentication plugin to ensure the request is valid.
286
+
287
+ To see a live working version of this example, check out the [`spec/acceptance/`](spec/acceptance/) directory in this repository, which is used for acceptance testing the Hooks framework. It contains a complete example of how to set up a Hooks server with custom plugins, authentication, and more.
288
+
289
+ ### Authentication
290
+
291
+ See the [Auth Plugins](docs/auth_plugins.md) documentation for even more information on how to create your own custom authentication plugins.
292
+
293
+ ## Contributing 🤝
294
+
295
+ See the [Contributing](CONTRIBUTING.md) document for information on how to contribute to the Hooks project, including setting up your development environment, running tests, and releasing new versions.
data/bin/bundle ADDED
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'bundle' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "rubygems"
12
+
13
+ m = Module.new do
14
+ module_function
15
+
16
+ def invoked_as_script?
17
+ File.expand_path($0) == File.expand_path(__FILE__)
18
+ end
19
+
20
+ def env_var_version
21
+ ENV["BUNDLER_VERSION"]
22
+ end
23
+
24
+ def cli_arg_version
25
+ return unless invoked_as_script? # don't want to hijack other binstubs
26
+ return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27
+ bundler_version = nil
28
+ update_index = nil
29
+ ARGV.each_with_index do |a, i|
30
+ if update_index && update_index.succ == i && a.match?(Gem::Version::ANCHORED_VERSION_PATTERN)
31
+ bundler_version = a
32
+ end
33
+ next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34
+ bundler_version = $1
35
+ update_index = i
36
+ end
37
+ bundler_version
38
+ end
39
+
40
+ def gemfile
41
+ gemfile = ENV["BUNDLE_GEMFILE"]
42
+ return gemfile if gemfile && !gemfile.empty?
43
+
44
+ File.expand_path("../Gemfile", __dir__)
45
+ end
46
+
47
+ def lockfile
48
+ lockfile =
49
+ case File.basename(gemfile)
50
+ when "gems.rb" then gemfile.sub(/\.rb$/, ".locked")
51
+ else "#{gemfile}.lock"
52
+ end
53
+ File.expand_path(lockfile)
54
+ end
55
+
56
+ def lockfile_version
57
+ return unless File.file?(lockfile)
58
+ lockfile_contents = File.read(lockfile)
59
+ return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60
+ Regexp.last_match(1)
61
+ end
62
+
63
+ def bundler_requirement
64
+ @bundler_requirement ||=
65
+ env_var_version ||
66
+ cli_arg_version ||
67
+ bundler_requirement_for(lockfile_version)
68
+ end
69
+
70
+ def bundler_requirement_for(version)
71
+ return "#{Gem::Requirement.default}.a" unless version
72
+
73
+ bundler_gem_version = Gem::Version.new(version)
74
+
75
+ bundler_gem_version.approximate_recommendation
76
+ end
77
+
78
+ def load_bundler!
79
+ ENV["BUNDLE_GEMFILE"] ||= gemfile
80
+
81
+ activate_bundler
82
+ end
83
+
84
+ def activate_bundler
85
+ gem_error = activation_error_handling do
86
+ gem "bundler", bundler_requirement
87
+ end
88
+ return if gem_error.nil?
89
+ require_error = activation_error_handling do
90
+ require "bundler/version"
91
+ end
92
+ return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
93
+ warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
94
+ exit 42
95
+ end
96
+
97
+ def activation_error_handling
98
+ yield
99
+ nil
100
+ rescue StandardError, LoadError => e
101
+ e
102
+ end
103
+ end
104
+
105
+ m.load_bundler!
106
+
107
+ if m.invoked_as_script?
108
+ load Gem.bin_path("bundler", "bundle")
109
+ end
data/bin/erb ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'erb' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("erb", "erb")
data/bin/hooks ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'hooks' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("hooks-ruby", "hooks")
data/bin/htmldiff ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'htmldiff' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("diff-lcs", "htmldiff")
data/bin/irb ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'irb' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("irb", "irb")
data/bin/ldiff ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'ldiff' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("diff-lcs", "ldiff")
data/bin/puma ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'puma' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("puma", "puma")
data/bin/pumactl ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'pumactl' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("puma", "pumactl")
data/bin/racc ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'racc' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("racc", "racc")