Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions updater/bin/fetch_files.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# typed: strict
# frozen_string_literal: true

$LOAD_PATH.unshift(__dir__ + "/../lib")

$stdout.sync = true

require "dependabot/api_client"
require "dependabot/environment"
require "dependabot/service"
require "dependabot/setup"
require "dependabot/file_fetcher_command"
require "debug" if ENV["DEBUG"]

class UpdaterKilledError < StandardError; end

trap("TERM") do
puts "Received SIGTERM"
error = UpdaterKilledError.new("Updater process killed with SIGTERM")
tags = { "gh.dependabot_api.update_job.id": ENV.fetch("DEPENDABOT_JOB_ID", nil) }

api_client =
Dependabot::ApiClient.new(
Dependabot::Environment.api_url,
Dependabot::Environment.job_id,
Dependabot::Environment.job_token
)
Dependabot::Service.new(client: api_client).capture_exception(error: error, tags: tags)
exit
end

begin
# Clones into DEPENDABOT_REPO_CONTENTS_PATH. When that path is a shared volume the
# update container reuses the clone instead of making its own.
Dependabot::FileFetcherCommand.new.run
rescue Dependabot::RunFailure
exit 1
end
19 changes: 12 additions & 7 deletions updater/bin/run
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ set -e

command="$1"
if [ -z "$command" ]; then
echo "usage: run [update_files|update_graph]"
echo "usage: run [fetch_files|update_files|update_graph]"
exit 1
fi

# ignore fetch_files command for backward compatibility
if [ "$command" = "fetch_files" ]; then
echo "fetch_files command is no longer used directly"
exit 0
fi
case "$command" in
fetch_files|update_files|update_graph) ;;
*)
echo "usage: run [fetch_files|update_files|update_graph]"
exit 1
;;
esac

bundle exec ruby "bin/${command}.rb"
# exec so the Ruby process' exit code becomes the container's exit code: callers
# chain `run fetch_files && run update_files` and must be able to tell a fetch
# failure from a success.
exec bundle exec ruby "bin/${command}.rb"
18 changes: 16 additions & 2 deletions updater/lib/dependabot/file_fetcher_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ def perform_job # rubocop:disable Metrics/AbcSize
begin
connectivity_check if ENV["ENABLE_CONNECTIVITY_CHECK"] == "1"
normalize_single_directory
validate_target_branch
dependabot_ref_namespace_available?
validate_local_checkout
validate_target_branch unless local_checkout_only?
dependabot_ref_namespace_available? unless local_checkout_only?
clone_repo_contents
@base_commit_sha = file_fetcher.commit
raise "base commit SHA not found" unless @base_commit_sha
Expand Down Expand Up @@ -337,11 +338,24 @@ def validate_target_branch

sig { void }
def clone_repo_contents
return if local_checkout_only?
return unless job.clone?

file_fetcher.clone_repo_contents
end

sig { void }
def validate_local_checkout
return unless local_checkout_only? && !already_cloned?

raise "Local repository checkout not found at #{Environment.repo_contents_path}"
Comment thread
v-robaiken marked this conversation as resolved.
Outdated
end

sig { returns(T::Boolean) }
def local_checkout_only?
ENV["DEPENDABOT_LOCAL_CHECKOUT_ONLY"] == "true"
Comment thread
v-robaiken marked this conversation as resolved.
Outdated
end
Comment thread
v-robaiken marked this conversation as resolved.
Outdated

sig { returns(T::Boolean) }
def already_cloned?
return false unless Environment.repo_contents_path
Expand Down
28 changes: 28 additions & 0 deletions updater/spec/dependabot/file_fetcher_command_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,34 @@
expect(dependency_file.content_encoding).to eq("utf-8")
end

context "when only a local checkout may be used" do
let(:repo_contents_path) { Dir.mktmpdir }

before do
allow(Dependabot::Environment).to receive_messages(
repo_contents_path: repo_contents_path
)
stub_const("ENV", ENV.to_h.merge("DEPENDABOT_LOCAL_CHECKOUT_ONLY" => "true"))
end

after { FileUtils.rm_rf(repo_contents_path) }

it "reports an error instead of fetching the repository when the checkout is missing" do
expect(Dependabot::Bundler::FileFetcher).not_to receive(:new)
expect(api_client).to receive(:record_update_job_error).with(
hash_including(
error_type: "file_fetcher_error",
error_details: hash_including(
Dependabot::ErrorAttributes::MESSAGE => "Local repository checkout not found at #{repo_contents_path}"
)
)
)
expect(api_client).to receive(:mark_job_as_processed)

expect { perform_job }.to output(/Local repository checkout not found/).to_stdout_from_any_process
end
end

context "when empty directories are specified" do
before do
allow(Dependabot::Environment).to receive(:repo_contents_path).and_return(Dir.mktmpdir)
Expand Down
Loading