{"id":13879624,"url":"https://github.com/Shopify/deprecation_toolkit","last_synced_at":"2025-07-16T15:32:43.683Z","repository":{"id":32701453,"uuid":"123532853","full_name":"Shopify/deprecation_toolkit","owner":"Shopify","description":"⚒Eliminate deprecations from your codebase ⚒","archived":false,"fork":false,"pushed_at":"2024-10-28T09:50:46.000Z","size":262,"stargazers_count":470,"open_issues_count":11,"forks_count":40,"subscribers_count":378,"default_branch":"main","last_synced_at":"2024-10-28T12:55:23.429Z","etag":null,"topics":["deprecations","gem-upgrade","testing"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Shopify.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-02T05:05:47.000Z","updated_at":"2024-10-28T09:50:49.000Z","dependencies_parsed_at":"2024-08-02T08:49:24.161Z","dependency_job_id":"b03949f8-0651-4324-a792-9af1a6ac92d5","html_url":"https://github.com/Shopify/deprecation_toolkit","commit_stats":{"total_commits":111,"total_committers":23,"mean_commits":4.826086956521739,"dds":0.6306306306306306,"last_synced_commit":"b0a29adb29ec9d2db139904cbdee6583a2b6f9c9"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2Fdeprecation_toolkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2Fdeprecation_toolkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2Fdeprecation_toolkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2Fdeprecation_toolkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Shopify","download_url":"https://codeload.github.com/Shopify/deprecation_toolkit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226143895,"owners_count":17580245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deprecations","gem-upgrade","testing"],"created_at":"2024-08-06T08:02:27.106Z","updated_at":"2024-11-24T08:31:33.153Z","avatar_url":"https://github.com/Shopify.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# ⚒ Deprecation Toolkit ⚒\n\n## Introduction\n\nDeprecation Toolkit is a gem that helps you get rid of deprecations in your codebase.\nHaving deprecations in your application usually means that something will break whenever you upgrade third-party dependencies. The sooner the better to fix them!\nFixing all deprecations at once might be tough depending on the size of your app and the number of deprecations. You might have to progressively resolve them while making sure your team doesn't add new ones. This is where this gem comes handy!\n\n## How it works\n\nThe Deprecation Toolkit gem works by using a [shitlist approach](https://www.youtube.com/watch?v=20pj_ajDBOg).\nFirst, the gem records all existing deprecations into `.yml` files. When running a test that have non-recorded deprecations after the initial recording, Deprecation Toolkit triggers a behavior of your choice (by default it raises an error).\n\n## Recording Deprecations\n\nAs said above, the Deprecation Toolkit works by using a shitlist approach. You have two ways to record deprecations.\nEither set `DeprecationToolkit::Configuration.behavior` to `DeprecationToolkit::Behaviors::Record` (see the Configuration Reference below)\nOr run your tests with the `--record-deprecations` flag (or simply the `-r` shortcut)\n```sh\nrails test \u003cpath_to_my_test.rb\u003e -r\n```\n\n## Configuration Reference\n\n### 🔨 `#DeprecationToolkit::Configuration#deprecation_path`\n\nYou can control where recorded deprecations are saved and read from. By default, deprecations are recorded in the `test/deprecations` folder.\n\nThe `deprecation_path` either accepts a string or a proc. The proc is called with the path of the running test file.\n\n```ruby\nDeprecationToolkit::Configuration.deprecation_path = 'test/deprecations'\nDeprecationToolkit::Configuration.deprecation_path = -\u003e (test_location) do\n  if test_location == 'admin_test.rb'\n    'test/deprecations/admin'\n  else\n    'test/deprecations/storefront'\n  end\nend\n```\n\n### 🔨 `#DeprecationToolkit::Configuration#behavior`\n\nBehaviors define what happens when non-recorded deprecations are encountered.\n\nThis gem provides 4 behaviors, the default one being `DeprecationToolkit::Behaviors::Raise`.\n\n* `DeprecationToolkit::Behaviors::Raise` will raise either:\n  - `DeprecationToolkit::Behaviors::DeprecationIntroduced` error if a new deprecation is introduced.\n  - `DeprecationToolkit::Behaviors::DeprecationRemoved` error if a deprecation was removed (compare to the one recorded in the shitlist).\n* `DeprecationToolkit::Behaviors::Record` will record deprecations.\n* `DeprecationToolkit::Behaviors::CIRecordHelper` See separate explanation below.\n* `DeprecationToolkit::Behaviors::Disabled` will do nothing.\n  - This is useful if you want to disable this gem for a moment without removing the gem from your Gemfile.\n\n```ruby\nDeprecationToolkit::Configuration.behavior = DeprecationToolkit::Behaviors::Record\n```\n\nYou can also create your own behavior object and perform the logic you want. Your behavior needs to respond to `trigger`.\n\n```ruby\nclass StatsdBehavior\n  def trigger(test, deprecations, recorded_deprecations)\n     # Could send some statsd event for example\n  end\nend\n\nDeprecationToolkit::Configuration.behavior = StatsdBehavior.new\n```\n\n#### DeprecationToolkit::Behaviors::CIRecordHelper\n\nThis is a special type of behaviour meant to help you record deprecations if you have a lof of them.\nImagine if you have thousands of tests and need to record deprecations for each on your machine, this is going to take ages.\nRecording deprecations on CI with the regular `Record` behavior isn't possible because of the way CI parallelize test in multiple container (Multiple tests from the same file runs in parallel in diferrent machines, the deprecation files that get created are then splitted. Regrouping them is a nightmare.)\n\nThis behavior will output a JSON representation of your deprecations. Your CI should have a way to download the log generated from the test run. Download it on your locale machine. Finally run the rake task `FILEPATH=\u003cpath_to_downloaded_log\u003e deprecation_toolkit:record_from_ci_output`.\nThis task will parse your CI log and grab the output generated by the DeprecationToolkit and will finally convert everything back to YML files.\n\n### 🔨 `#DeprecationToolkit::Configuration#allowed_deprecations`\n\nYou can ignore some deprecations using `allowed_deprecations`. `allowed_deprecations` accepts an array of Regexp and Procs.\n\nWhenever a deprecation matches one of the regex, it is ignored.\n\n```ruby\nDeprecationToolkit::Configuration.allowed_deprecations = [/Hello World/]\n\nActiveSupport::Deprecation.warn('Hello World') # ignored by Deprecation Toolkit\n```\n\nWhen passing procs, each proc will get passed the deprecation message and the callstack.\nThis is useful if you want to whitelist deprecations based on the caller.\n\n```ruby\nDeprecationToolkit::Configuration.allowed_deprecations = [\n  -\u003e(message, stack) { message ~= 'Foo' \u0026\u0026 stack.first.label == 'method_triggering_deprecation' }\n]\n\ndef method_triggering_deprecation\n  ActiveSupport::Deprecation.warn('Foo') # Ignored by the the DeprecationToolkit\nend\n```\n\n### 🔨 `#DeprecationToolkit::Configuration#warnings_treated_as_deprecation`\n\nMost gems don't use `ActiveSupport::Deprecation` to deprecate their code but instead just use `Kernel#warn` to output\na message in the console.\n\nDeprecation Toolkit allows you to configure which warnings should be treated as deprecations in order for you\nto keep track of them as if they were regular deprecations.\n\nThis setting accepts an array of regular expressions. To match on all warnings, you can provide a empty regex:\n\n```ruby\nDeprecationToolkit::Configuration.warnings_treated_as_deprecation = [//]\n```\n\nIn addition to regexps, anything that responds to `===` can be a matcher, for instance a proc:\n\n```ruby\nDeprecationToolkit::Configuration.warnings_treated_as_deprecation = [\n  -\u003e(warning) { !warning.match?(/not a deprecation/)}\n]\n```\n\n### 🔨 `#DeprecationToolkit::Configuration#deprecation_file_path_format`\n\nDeprecationToolkit allows you to choose the file path format for deprecation files.\n\nFor Minitest, it defaults to using class name so the following code would correspond to `#{deprecation_path}/deprecation_toolkit/behaviors/raise_test.yml`\n\n```ruby\nmodule DeprecationToolkit\n  module Behaviors\n    class RaiseTest \u003c ActiveSupport::TestCase\n    end\n  end\nend\n```\n\nFor rspec if defaults to the file location with spec removed. `/spec/models/user_spec.rb` would correspond to `/models/user.yml`.\n\nIf you have a specific use case you can configure this with a custom format using a proc. The proc is called with an instance of the test.\n\n```ruby\nConfiguration.deprecation_file_path_format = -\u003e (test) do\n  Kernel.const_source_location(test.class.name)[0].sub(%r{^./test/}, \"\").sub(/_test.rb$/, \"\")\nend\n```\n\n## RSpec\n\nBy default Deprecation Toolkit uses Minitest as its test runner. To use Deprecation Toolkit with RSpec you'll have to configure it.\n\n```ruby\nDeprecationToolkit::Configuration.test_runner = :rspec\n```\n\nAlso make sure to require the before/after hooks in your `spec_helper.rb` or `rails_helper.rb`.\n\n```ruby\nrequire \"deprecation_toolkit/rspec\"\n```\n\nIt's possible to record deprecations while running your specs by adding an ENV['DEPRECATION_BEHAVIOR'] variable to your test run. Run your specs with this ENV set to `\"record-deprecations\"`, `\"record\"` (or simply the `\"r\"` shortcut).\n\n```sh\nDEPRECATION_BEHAVIOR=\"record\" bundle exec rspec path/to/file_spec.rb\n```\n\n## Usage without Rails\n\nWithout Rails, you'll need to make sure your `ActiveSupport::Deprecation` instances use the [`:notify` behavior](https://api.rubyonrails.org/classes/ActiveSupport/Deprecation/Behavior.html#method-i-behavior-3D) and the `attach_to` is the underscored version of the deprecator's `gem_name` (this is how the `:notify` behavior works):\n\n```ruby\n# defined in the gem:\nMyGem.deprecator = ActiveSupport::Deprecation.new(\"2.0\", \"MyGem::Something\")\n\n# in the test helper:\nMyGem.deprecator.behavior = :notify\n\nDeprecationToolkit::Configuration.configure do |config|\n  config.attach_to = MyGem.deprecator.gem_name.underscore.tr(\"/\", \"_\")\n  # or more simply\n  # config.attach_to = \"my_gem_something\"\n  config.behavior = :notify\nend\n```\n\n## License\n\nDeprecation Toolkit is licensed under the [MIT license](LICENSE.txt).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FShopify%2Fdeprecation_toolkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FShopify%2Fdeprecation_toolkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FShopify%2Fdeprecation_toolkit/lists"}