Skip to content

Commit

Permalink
Merge pull request #39567 from jonathanhefner/credentials-diff-disenroll
Browse files Browse the repository at this point in the history
Add `credentials:diff --disenroll`
  • Loading branch information
rafaelfranca committed Dec 29, 2020
2 parents 4ed00c4 + eb7fe0b commit 156fe36
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 23 deletions.
6 changes: 4 additions & 2 deletions railties/lib/rails/commands/credentials/USAGE
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def edit

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
Expand All @@ -51,7 +51,10 @@ def show
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
Expand All @@ -61,6 +64,7 @@ def diff(content_path = nil)
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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,47 @@
# 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?
true
if enrolled_in_credentials_diffing?
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 ensure_rails_credentials_driver_is_set
set_driver if enrolled? && !driver_configured?
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?
gitattributes.read.match?(/config\/credentials(\/\*)?\.yml\.enc diff=rails_credentials/)
rescue Errno::ENOENT
false
def enrolled_in_credentials_diffing?
gitattributes.file? && gitattributes.read.include?(GITATTRIBUTES_ENTRY)
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

Expand Down
40 changes: 37 additions & 3 deletions railties/test/commands/credentials_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,48 @@ 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
config/credentials.yml.enc diff=rails_credentials
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
Expand Down Expand Up @@ -191,8 +225,8 @@ def run_show_command(environment: nil, **options)
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

0 comments on commit 156fe36

Please sign in to comment.