From a2c41ca5e37c9be2049c04ad5d6ea3745be81bbc Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Sun, 7 Jun 2020 15:48:28 -0500 Subject: [PATCH 1/2] Rename Diffing methods to increase specificity Because `Diffing` is a module included in a larger context, rename several of its methods to increase their specificity. --- .../commands/credentials/credentials_command.rb | 2 +- .../credentials/credentials_command/diffing.rb | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/railties/lib/rails/commands/credentials/credentials_command.rb b/railties/lib/rails/commands/credentials/credentials_command.rb index dccff4d99a..999838de05 100644 --- a/railties/lib/rails/commands/credentials/credentials_command.rb +++ b/railties/lib/rails/commands/credentials/credentials_command.rb @@ -32,7 +32,7 @@ module Rails ensure_encryption_key_has_been_added if credentials.key.nil? ensure_credentials_have_been_added - ensure_rails_credentials_driver_is_set + ensure_diffing_driver_is_configured catch_editing_exceptions do change_credentials_in_system_editor diff --git a/railties/lib/rails/commands/credentials/credentials_command/diffing.rb b/railties/lib/rails/commands/credentials/credentials_command/diffing.rb index 1d34c68074..fa0b20be04 100644 --- a/railties/lib/rails/commands/credentials/credentials_command/diffing.rb +++ b/railties/lib/rails/commands/credentials/credentials_command/diffing.rb @@ -2,7 +2,7 @@ module Rails::Command::CredentialsCommand::Diffing # :nodoc: def enroll_project_in_credentials_diffing - if enrolled? + if enrolled_in_credentials_diffing? true else gitattributes.write(<<~end_of_template, mode: "a") @@ -15,23 +15,22 @@ module Rails::Command::CredentialsCommand::Diffing # :nodoc: end end - def ensure_rails_credentials_driver_is_set - set_driver if enrolled? && !driver_configured? + def ensure_diffing_driver_is_configured + configure_diffing_driver if enrolled_in_credentials_diffing? && !diffing_driver_configured? end private - def enrolled? + def enrolled_in_credentials_diffing? gitattributes.read.match?(/config\/credentials(\/\*)?\.yml\.enc diff=rails_credentials/) rescue Errno::ENOENT false end - def driver_configured? + def diffing_driver_configured? system "git config --get diff.rails_credentials.textconv", out: File::NULL end - def set_driver - puts "running" + def configure_diffing_driver system "git config diff.rails_credentials.textconv 'bin/rails credentials:diff'" end From eb7fe0b293e0ec4bc8195ace8a69af493b0baa52 Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Sun, 7 Jun 2020 19:23:06 -0500 Subject: [PATCH 2/2] Add `credentials:diff --disenroll` This allows users to undo `credentials:diff --enroll` without having to know the details of its implementation. --- railties/lib/rails/commands/credentials/USAGE | 6 ++- .../credentials/credentials_command.rb | 6 ++- .../credentials_command/diffing.rb | 29 +++++++++----- railties/test/commands/credentials_test.rb | 40 +++++++++++++++++-- 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/railties/lib/rails/commands/credentials/USAGE b/railties/lib/rails/commands/credentials/USAGE index 8d67e0e50d..673422d929 100644 --- a/railties/lib/rails/commands/credentials/USAGE +++ b/railties/lib/rails/commands/credentials/USAGE @@ -32,8 +32,8 @@ You could prepend that to your server's start command like this: === Set up Git to Diff Credentials -Rails provides `rails credentials:diff --enroll` to instruct Git to call `rails credentials:diff` -when `git diff` is run on a credentials file. +Rails provides `bin/rails credentials:diff --enroll` to instruct Git to call +`bin/rails credentials:diff` when `git diff` is run on a credentials file. Running the command enrolls the project such that all credentials files use the "rails_credentials" diff driver in .gitattributes. @@ -45,6 +45,8 @@ that isn't tracked Rails automatically ensures it's configured when running Otherwise each co-worker would have to run enable manually, including on each new repo clone. +To disenroll from this feature, run `bin/rails credentials:diff --disenroll`. + === Editing Credentials This will open a temporary file in `$EDITOR` with the decrypted contents to edit diff --git a/railties/lib/rails/commands/credentials/credentials_command.rb b/railties/lib/rails/commands/credentials/credentials_command.rb index 999838de05..f503f82e18 100644 --- a/railties/lib/rails/commands/credentials/credentials_command.rb +++ b/railties/lib/rails/commands/credentials/credentials_command.rb @@ -51,7 +51,10 @@ module Rails end option :enroll, type: :boolean, default: false, - desc: "Enrolls project in credential file diffing with `git diff`" + desc: "Enrolls project in credentials file diffing with `git diff`" + + option :disenroll, type: :boolean, default: false, + desc: "Disenrolls project from credentials file diffing" def diff(content_path = nil) if @content_path = content_path @@ -61,6 +64,7 @@ module Rails say credentials.read.presence || credentials.content_path.read else require_application! + disenroll_project_from_credentials_diffing if options[:disenroll] enroll_project_in_credentials_diffing if options[:enroll] end rescue ActiveSupport::MessageEncryptor::InvalidMessage diff --git a/railties/lib/rails/commands/credentials/credentials_command/diffing.rb b/railties/lib/rails/commands/credentials/credentials_command/diffing.rb index fa0b20be04..4ce3b3169b 100644 --- a/railties/lib/rails/commands/credentials/credentials_command/diffing.rb +++ b/railties/lib/rails/commands/credentials/credentials_command/diffing.rb @@ -1,29 +1,40 @@ # frozen_string_literal: true module Rails::Command::CredentialsCommand::Diffing # :nodoc: + GITATTRIBUTES_ENTRY = <<~END + config/credentials/*.yml.enc diff=rails_credentials + config/credentials.yml.enc diff=rails_credentials + END + def enroll_project_in_credentials_diffing if enrolled_in_credentials_diffing? - true + say "Project is already enrolled in credentials file diffing." else - gitattributes.write(<<~end_of_template, mode: "a") - config/credentials/*.yml.enc diff=rails_credentials - config/credentials.yml.enc diff=rails_credentials - end_of_template + gitattributes.write(GITATTRIBUTES_ENTRY, mode: "a") - say "Project successfully enrolled!" + say "Enrolled project in credentials file diffing!" say "Rails ensures the rails_credentials diff driver is set when running `credentials:edit`. See `credentials:help` for more." end end + def disenroll_project_from_credentials_diffing + if enrolled_in_credentials_diffing? + gitattributes.write(gitattributes.read.gsub(GITATTRIBUTES_ENTRY, "")) + gitattributes.delete if gitattributes.empty? + + say "Disenrolled project from credentials file diffing!" + else + say "Project is not enrolled in credentials file diffing." + end + end + def ensure_diffing_driver_is_configured configure_diffing_driver if enrolled_in_credentials_diffing? && !diffing_driver_configured? end private def enrolled_in_credentials_diffing? - gitattributes.read.match?(/config\/credentials(\/\*)?\.yml\.enc diff=rails_credentials/) - rescue Errno::ENOENT - false + gitattributes.file? && gitattributes.read.include?(GITATTRIBUTES_ENTRY) end def diffing_driver_configured? diff --git a/railties/test/commands/credentials_test.rb b/railties/test/commands/credentials_test.rb index 99effef92f..83bf8cac11 100644 --- a/railties/test/commands/credentials_test.rb +++ b/railties/test/commands/credentials_test.rb @@ -124,7 +124,7 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase test "diff enroll diffing" do - assert_match("successfully enrolled", run_diff_command(enroll: true)) + assert_match(/\benrolled project/i, run_diff_command(enroll: true)) assert_includes File.read(app_path(".gitattributes")), <<~EOM config/credentials/*.yml.enc diff=rails_credentials @@ -132,6 +132,40 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase EOM end + test "diff enroll diffing when already enrolled" do + run_diff_command(enroll: true) + + assert_match(/already enrolled/i, run_diff_command(enroll: true)) + + assert_equal 1, File.read(app_path(".gitattributes")).scan("config/credentials.yml.enc").length + end + + test "diff disenroll diffing" do + FileUtils.rm(app_path(".gitattributes")) + run_diff_command(enroll: true) + + assert_match(/\bdisenrolled project/i, run_diff_command(disenroll: true)) + + assert_not File.exist?(app_path(".gitattributes")) + end + + test "diff disenroll diffing with existing .gitattributes" do + File.write(app_path(".gitattributes"), "foo bar\n") + run_diff_command(enroll: true) + + run_diff_command(disenroll: true) + + assert_equal("foo bar\n", File.read(app_path(".gitattributes"))) + end + + test "diff disenroll diffing when not enrolled" do + FileUtils.rm(app_path(".gitattributes")) + + assert_match(/not enrolled/i, run_diff_command(disenroll: true)) + + assert_not File.exist?(app_path(".gitattributes")) + end + test "running edit after enrolling in diffing sets diff driver" do run_diff_command(enroll: true) run_edit_command @@ -191,8 +225,8 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase rails "credentials:show", args, **options end - def run_diff_command(path = nil, enroll: nil, **options) - args = enroll ? ["--enroll"] : [path] + def run_diff_command(path = nil, enroll: nil, disenroll: nil, **options) + args = [path, ("--enroll" if enroll), ("--disenroll" if disenroll)].compact rails "credentials:diff", args, **options end end