From 46017bba520472212388cba18b3ef986297674ac Mon Sep 17 00:00:00 2001 From: Jeff Felchner Date: Fri, 19 Jan 2018 18:32:27 -0600 Subject: [PATCH] Add: ChamberVerification Hook When working with [settings verification](Verifying-Settings), it's important to remember to let the Approver know that settings have changed and that the current file signature will no longer match. You can enable it by creating an `.overcommit.yml` file and adding: ```yaml ChamberVerification: enabled: true ``` Whenever you commit any of your settings files, the hook will warn the user that the signature no longer matches and that the Approver needs to be notified. If you'd like to specify the name and email address of the Approver, you can add that to the configuration: ```yaml ChamberVerification: enabled: true approver_name: "Jeff Felchner" approver_email: "jeff@example.com" ``` --- config/default.yml | 8 +++ .../hook/pre_commit/chamber_verification.rb | 34 ++++++++++++ .../pre_commit/chamber_verification_spec.rb | 55 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 lib/overcommit/hook/pre_commit/chamber_verification.rb create mode 100644 spec/overcommit/hook/pre_commit/chamber_verification_spec.rb diff --git a/config/default.yml b/config/default.yml index d1c6ec30..2cba095b 100644 --- a/config/default.yml +++ b/config/default.yml @@ -213,6 +213,14 @@ PreCommit: install_command: 'gem install chamber' include: *chamber_settings_files + ChamberVerification: + enabled: false + description: 'Verify that all settings changes have been approved' + required_executable: 'chamber' + flags: ['sign', '--verify'] + install_command: 'gem install chamber' + include: *chamber_settings_files + CoffeeLint: enabled: false description: 'Analyze with coffeelint' diff --git a/lib/overcommit/hook/pre_commit/chamber_verification.rb b/lib/overcommit/hook/pre_commit/chamber_verification.rb new file mode 100644 index 00000000..457439ad --- /dev/null +++ b/lib/overcommit/hook/pre_commit/chamber_verification.rb @@ -0,0 +1,34 @@ +module Overcommit::Hook::PreCommit + # Runs `chamber sign --verify`. + # + # @see https://github.com/thekompanee/chamber/wiki/Git-Commit-Hooks#chamber-verification-pre-commit-hook + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + class ChamberVerification < Base + def run + approver_name = config.fetch('approver_name', 'your approver') + approver_email = config['approver_email'] ? " (#{config['approver_email']})" : nil + + result = execute(command) + + return :pass if result.stdout.empty? && result.stderr.empty? + return :pass if result.stderr =~ /no signature key was found/ + + output = [ + result.stdout.empty? ? nil : result.stdout, + result.stderr.empty? ? nil : result.stderr, + ]. + compact. + join("\n\n") + + output = "\n\n#{output}" unless output.empty? + + [ + :warn, + "One or more of your settings files does not match the signature.\n" \ + "Talk to #{approver_name}#{approver_email} about getting them " \ + "approved.#{output}", + ] + end + end + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity +end diff --git a/spec/overcommit/hook/pre_commit/chamber_verification_spec.rb b/spec/overcommit/hook/pre_commit/chamber_verification_spec.rb new file mode 100644 index 00000000..1dee1de9 --- /dev/null +++ b/spec/overcommit/hook/pre_commit/chamber_verification_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe Overcommit::Hook::PreCommit::ChamberVerification do + let(:config) { Overcommit::ConfigurationLoader.default_configuration } + let(:context) { double('context') } + subject { described_class.new(config, context) } + + before do + subject.stub(:applicable_files).and_return(['my_settings.yml']) + end + + context 'when chamber exits successfully' do + before do + result = double('result') + result.stub(:stdout).and_return('') + result.stub(:stderr).and_return('') + subject.stub(:execute).and_return(result) + end + + it { should pass } + end + + context 'when chamber exits unsuccessfully but because of missing keys' do + before do + result = double('result') + result.stub(:stdout).and_return('') + result.stub(:stderr).and_return('no signature key was found') + subject.stub(:execute).and_return(result) + end + + it { should pass } + end + + context 'when chamber exits unsucessfully via standard out' do + before do + result = double('result') + result.stub(:stdout).and_return('Some error message') + result.stub(:stderr).and_return('') + subject.stub(:execute).and_return(result) + end + + it { should warn } + end + + context 'when chamber exits unsucessfully via standard error' do + before do + result = double('result') + result.stub(:stdout).and_return('') + result.stub(:stderr).and_return('Some error message') + subject.stub(:execute).and_return(result) + end + + it { should warn } + end +end