Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate alternatives for every git source #3417

68 changes: 36 additions & 32 deletions common/lib/dependabot/shared_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,47 +161,21 @@ def self.with_git_configured(credentials:)
reset_global_git_config(backup_git_config_path)
end

def self.credential_helper_path
File.join(__dir__, "../../bin/git-credential-store-immutable")
end

# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/PerceivedComplexity
def self.configure_git_to_use_https_with_credentials(credentials)
File.open(GIT_CONFIG_GLOBAL_PATH, "w") do |file|
file << "# Generated by dependabot/dependabot-core"
end
configure_git_to_use_https
configure_git_credentials(credentials)
end

def self.configure_git_to_use_https
# NOTE: we use --global here (rather than --system) so that Dependabot
# can be run without privileged access
run_shell_command(
"git config --global --replace-all url.https://github.com/."\
"insteadOf ssh://[email protected]/"
)
run_shell_command(
"git config --global --add url.https://github.com/."\
"insteadOf ssh://[email protected]:"
)
run_shell_command(
"git config --global --add url.https://github.com/."\
"insteadOf [email protected]:"
)
run_shell_command(
"git config --global --add url.https://github.com/."\
"insteadOf [email protected]/"
)
run_shell_command(
"git config --global --add url.https://github.com/."\
"insteadOf git://github.com/"
)
end

# rubocop:disable Metrics/PerceivedComplexity
def self.configure_git_credentials(credentials)
# Then add a file-based credential store that loads a file in this repo.
# Under the hood this uses git credential-store, but it's invoked through
# a wrapper binary that only allows non-mutating commands. Without this,
# whenever the credentials are deemed to be invalid, they're erased.
credential_helper_path =
File.join(__dir__, "../../bin/git-credential-store-immutable")
run_shell_command(
"git config --global credential.helper "\
"'!#{credential_helper_path} --file #{Dir.pwd}/git.store'",
Expand All @@ -219,6 +193,9 @@ def self.configure_git_credentials(credentials)
github_credentials.find { |c| !c["password"]&.start_with?("v1.") } ||
github_credentials.first

# Make sure we always have https alternatives for github.com.
configure_git_to_use_https("github.com") if github_credential.nil?

deduped_credentials = credentials -
github_credentials +
[github_credential].compact
Expand All @@ -234,13 +211,40 @@ def self.configure_git_credentials(credentials)
"@#{cred.fetch('host')}"

git_store_content += authenticated_url + "\n"
configure_git_to_use_https(cred.fetch("host"))
end

# Save the file
File.write("git.store", git_store_content)
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/PerceivedComplexity

def self.configure_git_to_use_https(host)
jurre marked this conversation as resolved.
Show resolved Hide resolved
# NOTE: we use --global here (rather than --system) so that Dependabot
# can be run without privileged access
run_shell_command(
"git config --global --replace-all url.https://#{host}/."\
"insteadOf ssh://git@#{host}/"
)
run_shell_command(
"git config --global --add url.https://#{host}/."\
"insteadOf ssh://git@#{host}:"
)
run_shell_command(
"git config --global --add url.https://#{host}/."\
"insteadOf git@#{host}:"
)
run_shell_command(
"git config --global --add url.https://#{host}/."\
"insteadOf git@#{host}/"
)
run_shell_command(
"git config --global --add url.https://#{host}/."\
"insteadOf git://#{host}/"
)
end

def self.reset_git_repo(path)
Dir.chdir(path) do
run_shell_command("git reset HEAD --hard")
Expand Down
134 changes: 134 additions & 0 deletions common/spec/dependabot/shared_helpers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -314,4 +314,138 @@
)
end
end

describe ".with_git_configured" do
config_header = "Generated by dependabot/dependabot-core"

credentials_helper = <<~CONFIG.chomp
[credential]
helper = !#{Dependabot::SharedHelpers.credential_helper_path} --file #{Dir.pwd}/git.store
CONFIG

def alternatives(host)
<<~CONFIG.chomp
[url "https://#{host}/"]
insteadOf = ssh://git@#{host}/
insteadOf = ssh://git@#{host}:
insteadOf = git@#{host}:
insteadOf = git@#{host}/
insteadOf = git://#{host}/
CONFIG
end

let(:credentials) { [] }

def with_git_configured(&block)
Dependabot::SharedHelpers.with_git_configured(credentials: credentials) { block.call }
end

let(:configured_git_config) { with_git_configured { `cat ~/.gitconfig` } }
let(:configured_git_credentials) { with_git_configured { `cat #{Dir.pwd}/git.store` } }

context "when providing no extra credentials" do
let(:credentials) { [] }

it "creates a .gitconfig that contains the Dependabot header" do
expect(configured_git_config).to include(config_header)
end

it "creates a .gitconfig that contains the credentials helper" do
expect(configured_git_config).to include(credentials_helper)
end

it "creates a .gitconfig that contains the github.com alternatives" do
expect(configured_git_config).to include(alternatives("github.com"))
end

it "creates a git credentials store that is empty" do
expect(configured_git_credentials).to eq("")
end
end

context "when providing github.com credentials" do
let(:credentials) do
[
{
"type" => "git_source",
"host" => "github.com",
"username" => "x-access-token",
"password" => "fake-token"
}
]
end

it "creates a .gitconfig that contains the Dependabot header" do
expect(configured_git_config).to include(config_header)
end

it "creates a .gitconfig that contains the credentials helper" do
expect(configured_git_config).to include(credentials_helper)
end

it "creates a .gitconfig that contains the github.com alternatives" do
expect(configured_git_config).to include(alternatives("github.com"))
end

it "creates a git credentials store that contains github.com credentials" do
expect(configured_git_credentials).to eq("https://x-access-token:[email protected]\n")
end
end

context "when providing multiple github.com credentials" do
let(:credentials) do
[
{
"type" => "git_source",
"host" => "github.com",
"username" => "x-access-token",
"password" => "v1.fake-token"
},
{
"type" => "git_source",
"host" => "github.com",
"username" => "x-access-token",
"password" => "fake-token"
}
]
end

it "creates a git credentials store that contains non-app-token github.com credentials" do
expect(configured_git_credentials).to eq("https://x-access-token:[email protected]\n")
end
end

context "when providing private git_source credentials" do
let(:credentials) do
[
{
"type" => "git_source",
"host" => "private.com",
"username" => "x-access-token",
"password" => "fake-token"
}
]
end

it "creates a .gitconfig that contains the Dependabot header" do
expect(configured_git_config).to include(config_header)
end

it "creates a .gitconfig that contains the credentials helper" do
expect(configured_git_config).to include(credentials_helper)
end

it "creates a .gitconfig that contains the github.com alternatives" do
expect(configured_git_config).to include(alternatives("github.com"))
end

it "creates a .gitconfig that contains the private.com alternatives" do
expect(configured_git_config).to include(alternatives("private.com"))
end

it "creates a git credentials store that contains private git credentials" do
expect(configured_git_credentials).to eq("https://x-access-token:[email protected]\n")
end
end
end
end