docit 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e48afeb14f8b73781bf089a31b30616c00d4aa053f079668fbecbc7215ea13e2
4
+ data.tar.gz: dd1ea68be0fb59dd014af55bb457fe110e2da2227fe56a0216d75c5051046215
5
+ SHA512:
6
+ metadata.gz: ba5dadbd366f719b4420c515ad252380e4e5fd66137bb183e6b8d109426b0cf828eed12918658ea3a9af6e55d73f2c8e806e7a92c9d600d3a58e1fb643319576
7
+ data.tar.gz: 17690c65bec465a9b3479d80375a558a72bec94fd5677f8389e028d07d7b915e146bfa16b380ba0fb89aef33b848980033bcd38eb51ba04c6ef899c1c7c6663f
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: Bug Report
3
+ about: Report a bug to help us improve Docit
4
+ labels: bug
5
+ ---
6
+
7
+ ## Description
8
+
9
+ A clear and concise description of the bug.
10
+
11
+ ## Steps to Reproduce
12
+
13
+ 1. Configure Docit with `...`
14
+ 2. Add `swagger_doc` to `...`
15
+ 3. Visit `/api-docs`
16
+ 4. See error
17
+
18
+ ## Expected Behavior
19
+
20
+ What you expected to happen.
21
+
22
+ ## Actual Behavior
23
+
24
+ What actually happened. Include error messages or screenshots if applicable.
25
+
26
+ ## Environment
27
+
28
+ - **Ruby version:**
29
+ - **Rails version:**
30
+ - **Docit version:**
31
+ - **OS:**
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest a new feature for Docit
4
+ labels: enhancement
5
+ ---
6
+
7
+ ## Description
8
+
9
+ A clear and concise description of the feature you'd like.
10
+
11
+ ## Use Case
12
+
13
+ Explain the problem this feature would solve or the workflow it would improve.
14
+
15
+ ## Proposed Solution
16
+
17
+ Describe how you'd like it to work, including example DSL usage if applicable:
18
+
19
+ ```ruby
20
+ swagger_doc :index do
21
+ # your proposed syntax here
22
+ end
23
+ ```
24
+
25
+ ## Alternatives Considered
26
+
27
+ Any alternative solutions or workarounds you've considered.
@@ -0,0 +1,15 @@
1
+ ## What does this PR do?
2
+
3
+ A brief description of the changes.
4
+
5
+ ## Related Issue
6
+
7
+ Closes #
8
+
9
+ ## Checklist
10
+
11
+ - [ ] Tests added/updated for the changes
12
+ - [ ] All tests pass (`bundle exec rspec`)
13
+ - [ ] No new linter warnings (`bundle exec rubocop`)
14
+ - [ ] CHANGELOG.md updated (if user-facing change)
15
+ - [ ] Documentation updated (if applicable)
@@ -0,0 +1,30 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ ruby-version: ["3.2", "3.3", "3.4"]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Ruby ${{ matrix.ruby-version }}
21
+ uses: ruby/setup-ruby@v1
22
+ with:
23
+ ruby-version: ${{ matrix.ruby-version }}
24
+ bundler-cache: true
25
+
26
+ - name: Run tests
27
+ run: bundle exec rspec
28
+
29
+ - name: Run linter
30
+ run: bundle exec rubocop
data/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2026-04-08
4
+
5
+ - Initial release
6
+ - DSL: `swagger_doc` macro for inline controller documentation
7
+ - DSL: `use_docs` + `Docit::DocFile` for separate doc files (drf-spectacular style)
8
+ - Builders: request body, response, and parameter builders with nested object/array support
9
+ - Schema `$ref` components via `Docit.define_schema`
10
+ - File upload support (`type: :file` → `string/binary`)
11
+ - Configuration: auth schemes (bearer, basic, api_key), tag descriptions, server URLs
12
+ - Rails Engine: Swagger UI at mounted path, JSON spec endpoint
13
+ - Route introspection with eager-loading for development mode
14
+ - Install generator: `rails g docit:install`
15
+ - OpenAPI 3.0.3 spec generation
@@ -0,0 +1,39 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, religion, or sexual identity
10
+ and orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to a positive environment:
15
+
16
+ * Using welcoming and inclusive language
17
+ * Being respectful of differing viewpoints and experiences
18
+ * Gracefully accepting constructive criticism
19
+ * Focusing on what is best for the community
20
+ * Showing empathy towards other community members
21
+
22
+ Examples of unacceptable behavior:
23
+
24
+ * The use of sexualized language or imagery and unwelcome sexual attention or advances
25
+ * Trolling, insulting or derogatory comments, and personal or political attacks
26
+ * Public or private harassment
27
+ * Publishing others' private information without explicit permission
28
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
29
+
30
+ ## Enforcement
31
+
32
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
33
+ reported to the project maintainers at siegdomain1@gmail.com. All complaints will
34
+ be reviewed and investigated.
35
+
36
+ ## Attribution
37
+
38
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
39
+ version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,78 @@
1
+ # Contributing to Docit
2
+
3
+ Docit welcomes any form of contribution. Your contribution matters even if it is only a small one.
4
+
5
+ Contributions come in different shapes and sizes:
6
+
7
+ - Documentation improvements, clarifications & fixing typos
8
+ - Creating issues for feature requests & bug reports
9
+ - Creating pull requests for features and bug fixes
10
+ - Questions that highlight inconsistencies or workflow issues
11
+ - Adding support for additional authentication schemes or OpenAPI features
12
+
13
+ ## Issues
14
+
15
+ Generating OpenAPI schemas from Rails controllers is subtle work — the devil often lies in the details. A concise description with examples goes a long way. If possible, please include:
16
+
17
+ - A concise description of the problem
18
+ - Example controller code that produces the issue
19
+ - The generated (partial) OpenAPI spec showing the problem
20
+ - Stacktraces if an error occurred
21
+ - Docit / Ruby / Rails versions (`bundle show docit`, `ruby -v`, `rails -v`)
22
+
23
+ ## Pull requests
24
+
25
+ Docit aims for high test coverage and an extensive test suite. Tests enable us to maintain quality, reliability, and consistency as the gem grows.
26
+
27
+ - **Keep changes minimal.** Make the smallest invasive change that solves the problem. On receiving feedback, amend existing commits rather than adding fixup commits — use `git commit --amend` and `git push --force` to update your PR.
28
+ - **Get early feedback on non-trivial PRs.** Open an issue first to discuss the approach. We don't want to waste anyone's time.
29
+ - **Write tests.** Look at `spec/docit/` for unit test patterns and `spec/integration/` for engine tests. Small additions can go into `spec/docit/v2_features_spec.rb` or a new spec file for the feature.
30
+ - **All tests must pass.** Your PR must pass the full suite to be merged.
31
+
32
+ ## Getting started
33
+
34
+ ```bash
35
+ # Fork the repo on GitHub, then:
36
+ git clone https://github.com/YOURGITHUBNAME/docit.git
37
+ cd docit
38
+
39
+ # Install dependencies
40
+ bundle install
41
+
42
+ # Run the test suite
43
+ bundle exec rspec
44
+
45
+ # Run a specific test file
46
+ bundle exec rspec spec/docit/schema_generator_spec.rb
47
+
48
+ # Run a single test by line number
49
+ bundle exec rspec spec/docit/v2_features_spec.rb:30
50
+ ```
51
+
52
+ ## Project structure
53
+
54
+ ```
55
+ lib/docit.rb # Entry point, configuration, schema registry
56
+ lib/docit/configuration.rb # Config class (title, auth, tags)
57
+ lib/docit/registry.rb # Global operation store
58
+ lib/docit/dsl.rb # swagger_doc macro
59
+ lib/docit/operation.rb # Single endpoint documentation
60
+ lib/docit/builders/ # DSL builders (response, request_body, parameter)
61
+ lib/docit/schema_definition.rb # Reusable $ref schema definitions
62
+ lib/docit/schema_generator.rb # Registry → OpenAPI 3.0.3 spec
63
+ lib/docit/route_inspector.rb # Rails route introspection
64
+ lib/docit/engine.rb # Rails Engine (Swagger UI + spec endpoint)
65
+ app/controllers/docit/ui_controller.rb # Serves Swagger UI and JSON spec
66
+ lib/generators/docit/install/ # rails g docit:install generator
67
+ spec/dummy/ # Minimal Rails app for integration tests
68
+ ```
69
+
70
+ ## Code style
71
+
72
+ - Follow existing patterns in the codebase
73
+ - Use `frozen_string_literal: true` in all Ruby files
74
+ - Prefer keyword arguments for clarity (`location:` instead of positional args)
75
+ - Use `instance_eval(&block)` for DSL blocks
76
+ - Return defensive copies (`.dup`) from accessor methods that expose internal state
77
+
78
+ With that out of the way, we hope to hear from you soon.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 S13G
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,416 @@
1
+ # Docit
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/docit.svg)](https://rubygems.org/gems/docit)
4
+ [![CI](https://github.com/S13G/docket/actions/workflows/ci.yml/badge.svg)](https://github.com/S13G/docket/actions/workflows/ci.yml)
5
+ [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.2-red.svg)](https://www.ruby-lang.org)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ Decorator-style API documentation for Ruby on Rails. Write OpenAPI 3.0 docs as clean DSL macros directly on your controller actions: no separate doc files, no RSpec integration required. Just annotate and go.
9
+
10
+ Inspired by [drf-spectacular](https://github.com/tfranzel/drf-spectacular) for Django REST Framework.
11
+
12
+ ## Installation
13
+
14
+ Add Docit to your Gemfile:
15
+
16
+ ```ruby
17
+ gem "docit"
18
+ ```
19
+
20
+ Then run:
21
+
22
+ ```bash
23
+ bundle install
24
+ rails generate docit:install
25
+ ```
26
+
27
+ The generator does two things:
28
+
29
+ 1. Creates `config/initializers/docit.rb` with default settings
30
+ 2. Mounts the Swagger UI engine at `/api-docs` in your routes
31
+
32
+ Visit `/api-docs` to see your interactive API documentation.
33
+
34
+ ## Configuration
35
+
36
+ Edit `config/initializers/docit.rb`:
37
+
38
+ ```ruby
39
+ Docit.configure do |config|
40
+ config.title = "My API"
41
+ config.version = "1.0.0"
42
+ config.description = "Backend API documentation"
43
+
44
+ # Authentication: pick one (or multiple):
45
+ config.auth :bearer # Bearer token (JWT by default)
46
+ config.auth :basic # HTTP Basic
47
+ config.auth :api_key, name: "X-API-Key", # API key in header
48
+ location: "header"
49
+
50
+ # Tag descriptions (shown in Swagger UI sidebar):
51
+ config.tag "Users", description: "User account management"
52
+ config.tag "Auth", description: "Authentication endpoints"
53
+
54
+ # Server URLs (shown in Swagger UI server dropdown):
55
+ config.server "https://api.example.com", description: "Production"
56
+ config.server "https://staging.example.com", description: "Staging"
57
+ config.server "http://localhost:3000", description: "Development"
58
+ end
59
+ ```
60
+
61
+ ## Usage
62
+
63
+ Docit supports two styles for documenting endpoints. Choose whichever fits your project or mix both.
64
+
65
+ ### Style 1: Inline (simple APIs)
66
+
67
+ Add `swagger_doc` blocks directly in your controller:
68
+
69
+ ```ruby
70
+ class Api::V1::UsersController < ApplicationController
71
+ swagger_doc :index do
72
+ summary "List all users"
73
+ tags "Users"
74
+ response 200, "Users retrieved"
75
+ end
76
+ def index
77
+ # your code
78
+ end
79
+ end
80
+ ```
81
+
82
+ ### Style 2: Separate doc files (recommended for larger APIs)
83
+
84
+ Keep controllers clean by defining docs in dedicated files, just like drf-spectacular:
85
+
86
+ ```ruby
87
+ # app/docs/api/v1/users_docs.rb
88
+ module Api::V1::UsersDocs
89
+ extend Docit::DocFile
90
+
91
+ doc :index do
92
+ summary "List all users"
93
+ description "Returns a paginated list of users"
94
+ tags "Users"
95
+
96
+ parameter :page, location: :query, type: :integer, description: "Page number"
97
+
98
+ response 200, "Users retrieved" do
99
+ property :users, type: :array, items: :object do
100
+ property :id, type: :integer, example: 1
101
+ property :email, type: :string, example: "user@example.com"
102
+ end
103
+ property :total, type: :integer, example: 42
104
+ end
105
+ end
106
+
107
+ doc :create do
108
+ summary "Create a user"
109
+ tags "Users"
110
+
111
+ request_body required: true do
112
+ property :email, type: :string, required: true
113
+ property :password, type: :string, required: true, format: :password
114
+ end
115
+
116
+ response 201, "User created" do
117
+ property :id, type: :integer
118
+ end
119
+
120
+ response 422, "Validation failed" do
121
+ property :errors, type: :object do
122
+ property :email, type: :array, items: :string
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ # app/controllers/api/v1/users_controller.rb — stays clean!
129
+ class Api::V1::UsersController < ApplicationController
130
+ use_docs Api::V1::UsersDocs
131
+
132
+ def index
133
+ # pure business logic
134
+ end
135
+
136
+ def create
137
+ # pure business logic
138
+ end
139
+ end
140
+ ```
141
+
142
+ You can also mix both styles — use `use_docs` for most actions and add inline `swagger_doc` for one-offs:
143
+
144
+ ```ruby
145
+ class Api::V1::UsersController < ApplicationController
146
+ use_docs Api::V1::UsersDocs # loads :index and :create from doc file
147
+
148
+ swagger_doc :destroy do # inline doc for this one action
149
+ summary "Delete user"
150
+ tags "Users"
151
+ response 204, "Deleted"
152
+ end
153
+
154
+ def index; end
155
+ def create; end
156
+ def destroy; end
157
+ end
158
+ ```
159
+
160
+ ### Endpoint documentation DSL
161
+
162
+ The following examples work in both `swagger_doc` blocks and `doc` blocks.
163
+
164
+ ### Request bodies
165
+
166
+ ```ruby
167
+ swagger_doc :create do
168
+ summary "Create a user"
169
+ tags "Users"
170
+
171
+ request_body required: true do
172
+ property :email, type: :string, required: true, example: "user@example.com"
173
+ property :password, type: :string, required: true, format: :password
174
+ property :name, type: :string, example: "Jane Doe"
175
+ property :profile, type: :object do
176
+ property :bio, type: :string
177
+ property :avatar_url, type: :string, format: :uri
178
+ end
179
+ end
180
+
181
+ response 201, "User created" do
182
+ property :id, type: :integer, example: 1
183
+ property :email, type: :string, example: "user@example.com"
184
+ end
185
+
186
+ response 422, "Validation failed" do
187
+ property :errors, type: :object do
188
+ property :email, type: :array, items: :string
189
+ end
190
+ end
191
+ end
192
+ def create
193
+ # your code
194
+ end
195
+ ```
196
+
197
+ ### Path parameters
198
+
199
+ ```ruby
200
+ swagger_doc :show do
201
+ summary "Get a user"
202
+ tags "Users"
203
+
204
+ parameter :id, location: :path, type: :integer, required: true, description: "User ID"
205
+
206
+ response 200, "User found" do
207
+ property :id, type: :integer, example: 1
208
+ property :email, type: :string
209
+ property :name, type: :string
210
+ end
211
+
212
+ response 404, "User not found" do
213
+ property :error, type: :string, example: "Not found"
214
+ end
215
+ end
216
+ def show
217
+ # your code
218
+ end
219
+ ```
220
+
221
+ ### Enums
222
+
223
+ ```ruby
224
+ swagger_doc :index do
225
+ summary "List orders"
226
+ tags "Orders"
227
+
228
+ parameter :status, location: :query, type: :string,
229
+ enum: %w[pending shipped delivered],
230
+ description: "Filter by status"
231
+
232
+ response 200, "Orders list" do
233
+ property :orders, type: :array do
234
+ property :id, type: :integer
235
+ property :status, type: :string, enum: %w[pending shipped delivered]
236
+ end
237
+ end
238
+ end
239
+ ```
240
+
241
+ ### Security
242
+
243
+ Mark endpoints as requiring authentication:
244
+
245
+ ```ruby
246
+ swagger_doc :destroy do
247
+ summary "Delete a user"
248
+ tags "Users"
249
+ security :bearer_auth # references the scheme from your config
250
+
251
+ response 204, "User deleted"
252
+ response 401, "Unauthorized"
253
+ end
254
+ ```
255
+
256
+ ### Deprecated endpoints
257
+
258
+ ```ruby
259
+ swagger_doc :legacy_search do
260
+ summary "Search (legacy)"
261
+ tags "Search"
262
+ deprecated
263
+
264
+ response 200, "Results"
265
+ end
266
+ ```
267
+
268
+ ### Nested objects and arrays
269
+
270
+ ```ruby
271
+ response 200, "Success" do
272
+ property :user, type: :object do
273
+ property :id, type: :integer
274
+ property :name, type: :string
275
+ property :addresses, type: :array do
276
+ property :street, type: :string
277
+ property :city, type: :string
278
+ property :zip, type: :string
279
+ end
280
+ end
281
+ end
282
+ ```
283
+
284
+ ### Response examples
285
+
286
+ ```ruby
287
+ response 200, "User found" do
288
+ property :id, type: :integer
289
+ property :email, type: :string
290
+
291
+ example "admin_user",
292
+ { id: 1, email: "admin@example.com" },
293
+ description: "An admin user"
294
+
295
+ example "regular_user",
296
+ { id: 2, email: "user@example.com" },
297
+ description: "A regular user"
298
+ end
299
+ ```
300
+
301
+ ### Shared schemas (`$ref`)
302
+
303
+ Define reusable schemas once and reference them across multiple endpoints:
304
+
305
+ ```ruby
306
+ # In config/initializers/docit.rb or a dedicated file:
307
+ Docit.define_schema :User do
308
+ property :id, type: :integer, example: 1
309
+ property :email, type: :string, example: "user@example.com"
310
+ property :name, type: :string, example: "Jane Doe"
311
+ property :address, type: :object do
312
+ property :street, type: :string
313
+ property :city, type: :string
314
+ end
315
+ end
316
+
317
+ Docit.define_schema :Error do
318
+ property :error, type: :string, example: "Not found"
319
+ property :details, type: :array, items: :string
320
+ end
321
+ ```
322
+
323
+ Reference them in any endpoint with `schema ref:`:
324
+
325
+ ```ruby
326
+ swagger_doc :show do
327
+ summary "Get user"
328
+ tags "Users"
329
+
330
+ response 200, "User found" do
331
+ schema ref: :User
332
+ end
333
+
334
+ response 404, "Not found" do
335
+ schema ref: :Error
336
+ end
337
+ end
338
+
339
+ swagger_doc :create do
340
+ summary "Create user"
341
+ tags "Users"
342
+
343
+ request_body required: true do
344
+ schema ref: :User
345
+ end
346
+
347
+ response 201, "Created" do
348
+ schema ref: :User
349
+ end
350
+ end
351
+ ```
352
+
353
+ This outputs `$ref: '#/components/schemas/User'` in the spec — Swagger UI resolves it automatically.
354
+
355
+ ### File uploads
356
+
357
+ Use `type: :file` with `content_type: "multipart/form-data"` for file upload endpoints:
358
+
359
+ ```ruby
360
+ swagger_doc :upload_avatar do
361
+ summary "Upload avatar"
362
+ tags "Users"
363
+
364
+ request_body required: true, content_type: "multipart/form-data" do
365
+ property :avatar, type: :file, required: true, description: "Avatar image"
366
+ property :caption, type: :string
367
+ end
368
+
369
+ response 201, "Avatar uploaded" do
370
+ property :url, type: :string, format: :uri
371
+ end
372
+ end
373
+ ```
374
+
375
+ `type: :file` maps to `{ type: "string", format: "binary" }` in the OpenAPI spec.
376
+
377
+ ## How it works
378
+
379
+ 1. `swagger_doc` registers an **Operation** for each controller action in a global **Registry**
380
+ 2. When someone visits `/api-docs/spec`, Docit's **SchemaGenerator** combines all registered operations with your Rails routes (via **RouteInspector**) to produce an OpenAPI 3.0.3 JSON document
381
+ 3. The **Engine** serves Swagger UI at `/api-docs`, pointing it at the generated spec
382
+
383
+ The DSL is included in all controllers automatically via a Rails Engine initializer — no manual `include` needed if you're using `ActionController::API` or `ActionController::Base`.
384
+
385
+ ## Mounting at a different path
386
+
387
+ In `config/routes.rb`:
388
+
389
+ ```ruby
390
+ mount Docit::Engine => "/docs" # now at /docs instead of /api-docs
391
+ ```
392
+
393
+ ## JSON spec only
394
+
395
+ If you just want the raw OpenAPI JSON (e.g., for code generation):
396
+
397
+ ```
398
+ GET /api-docs/spec
399
+ ```
400
+
401
+ ## Development
402
+
403
+ ```bash
404
+ git clone https://github.com/S13G/docket.git
405
+ cd docit
406
+ bundle install
407
+ bundle exec rspec # run all tests
408
+ ```
409
+
410
+ ## Contributing
411
+
412
+ Bug reports and pull requests are welcome on [GitHub](https://github.com/S13G/docket).
413
+
414
+ ## License
415
+
416
+ [MIT](LICENSE.txt)
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]