diff --git a/dependabot-core.gemspec b/dependabot-core.gemspec index 6b96026832..936f22c725 100644 --- a/dependabot-core.gemspec +++ b/dependabot-core.gemspec @@ -25,12 +25,12 @@ Gem::Specification.new do |spec| spec.add_dependency "docker_registry2", "~> 1.3", ">= 1.3.3" spec.add_dependency "excon", "~> 0.55" spec.add_dependency "gitlab", "~> 4.1" + spec.add_dependency "gpgme", "~> 2.0" spec.add_dependency "nokogiri", "~> 1.8" spec.add_dependency "octokit", "~> 4.6" spec.add_dependency "parseconfig", "~> 1.0" spec.add_dependency "parser", "~> 2.5" spec.add_dependency "toml-rb", "~> 1.1" - spec.add_dependency "gpgme", "~> 2.0" spec.add_development_dependency "rake" spec.add_development_dependency "rspec", "~> 3.7.0" diff --git a/lib/dependabot/pull_request_creator.rb b/lib/dependabot/pull_request_creator.rb index 99de3595da..f1c5498e41 100644 --- a/lib/dependabot/pull_request_creator.rb +++ b/lib/dependabot/pull_request_creator.rb @@ -10,11 +10,11 @@ class PullRequestCreator attr_reader :repo_name, :dependencies, :files, :base_commit, :github_client, :pr_message_footer, :target_branch, - :author_details, :custom_labels + :author_details, :signature_key, :custom_labels def initialize(repo:, base_commit:, dependencies:, files:, github_client:, pr_message_footer: nil, target_branch: nil, - author_details: nil, custom_labels: nil) + custom_labels: nil, author_details: nil, signature_key: nil) @dependencies = dependencies @repo_name = repo @base_commit = base_commit @@ -23,6 +23,7 @@ def initialize(repo:, base_commit:, dependencies:, files:, github_client:, @pr_message_footer = pr_message_footer @target_branch = target_branch @author_details = author_details + @signature_key = signature_key @custom_labels = custom_labels check_dependencies_have_previous_version @@ -48,6 +49,7 @@ def create pr_description: message_builder.pr_message, pr_name: message_builder.pr_name, author_details: author_details, + signature_key: signature_key, custom_labels: custom_labels ).create end diff --git a/lib/dependabot/pull_request_creator/github.rb b/lib/dependabot/pull_request_creator/github.rb index 699752a261..f80ad297bf 100644 --- a/lib/dependabot/pull_request_creator/github.rb +++ b/lib/dependabot/pull_request_creator/github.rb @@ -61,6 +61,7 @@ def create_commit options = author_details&.any? ? { author: author_details } : {} if options[:author]&.any? && signature_key + timestamp = Time.now.utc options[:signature] = commit_signature(tree, timestamp) options[:author][:date] = timestamp.iso8601 end @@ -171,7 +172,8 @@ def default_branch def commit_signature(tree, timestamp) time_str = timestamp.strftime("%s %z") - name, email = author_details[:name], author_details[:email] + name = author_details[:name] + email = author_details[:email] commit_object = [ "commit #{commit_message.length}\0tree #{tree.sha}", "parent #{base_commit}", diff --git a/lib/dependabot/pull_request_updater.rb b/lib/dependabot/pull_request_updater.rb index 219d31c48e..53df438864 100644 --- a/lib/dependabot/pull_request_updater.rb +++ b/lib/dependabot/pull_request_updater.rb @@ -5,16 +5,18 @@ module Dependabot class PullRequestUpdater attr_reader :watched_repo, :files, :base_commit, :github_client, - :pull_request_number, :author_details + :pull_request_number, :author_details, :signature_key def initialize(repo:, base_commit:, files:, github_client:, - pull_request_number:, author_details: nil) + pull_request_number:, author_details: nil, + signature_key: nil) @watched_repo = repo @base_commit = base_commit @files = files @github_client = github_client @pull_request_number = pull_request_number @author_details = author_details + @signature_key = signature_key end def update @@ -41,6 +43,13 @@ def create_commit tree = create_tree options = author_details&.any? ? { author: author_details } : {} + + if options[:author]&.any? && signature_key + timestamp = Time.now.utc + options[:signature] = commit_signature(tree, timestamp) + options[:author][:date] = timestamp.iso8601 + end + github_client.create_commit( watched_repo, commit_message, @@ -87,15 +96,39 @@ def update_branch(commit) ) rescue Octokit::UnprocessableEntity => error # Return quietly if the branch has been deleted - return nil if error.message.match?(/Reference does not exist/) + return nil if error.message.match?(/Reference does not exist/i) # Return quietly if the branch has been merged - return nil if error.message.match?(/Reference cannot be updated/) + return nil if error.message.match?(/Reference cannot be updated/i) raise end def commit_message github_client.git_commit(watched_repo, pull_request.head.sha).message end + + def commit_signature(tree, timestamp) + time_str = timestamp.strftime("%s %z") + name = author_details[:name] + email = author_details[:email] + commit_object = [ + "commit #{commit_message.length}\0tree #{tree.sha}", + "parent #{base_commit}", + "author #{name} <#{email}> #{time_str}", + "committer #{name} <#{email}> #{time_str}", + "", + commit_message + ] + data = commit_object.join("\n") + + Dir.mktmpdir do |dir| + GPGME::Engine.home_dir = dir + GPGME::Key.import(signature_key) + + crypto = GPGME::Crypto.new(armor: true) + opts = { mode: GPGME::SIG_MODE_DETACH, signer: email } + return crypto.sign(data, opts) + end + end end end