Merge pull request #5438 from inspec/nm/fix-profile-git-fetcher

This commit is contained in:
Clinton Wolfe 2021-03-23 22:45:13 -04:00 committed by GitHub
commit c3f36b953d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 3 deletions

View file

@ -62,7 +62,6 @@ module Inspec::Fetcher
def fetch(destination_path)
@repo_directory = destination_path # Might be the cache, or vendoring, or something else
FileUtils.mkdir_p(destination_path) unless Dir.exist?(destination_path)
if cloned?
checkout
else
@ -126,10 +125,25 @@ module Inspec::Fetcher
elsif @tag
resolve_ref(@tag)
else
resolve_ref("master")
resolve_ref(default_ref)
end
end
def default_ref
command_string = "git remote show #{@remote_url}"
cmd = shellout(command_string)
unless cmd.exitstatus == 0
raise(Inspec::FetcherFailure, "Profile git dependency failed with default reference - #{@remote_url} - error running '#{command_string}': #{cmd.stderr}")
else
ref = cmd.stdout.lines.detect { |l| l.include? "HEAD branch:" }&.split(":")&.last&.strip
unless ref
raise(Inspec::FetcherFailure, "Profile git dependency failed with default reference - #{@remote_url} - error running '#{command_string}': NULL reference")
end
ref
end
end
def resolve_ref(ref_name)
command_string = "git ls-remote \"#{@remote_url}\" \"#{ref_name}*\""
cmd = shellout(command_string)

View file

@ -5,6 +5,26 @@ require "tmpdir"
describe "running profiles with git-based dependencies" do
include FunctionalHelper
let(:git_profiles) { "#{profile_path}/git-fetcher" }
let(:git_default_main_profile_url) { "https://github.com/inspec/inspec-test-profile-default-main.git" }
attr_accessor :out
def inspec(commandline, prefix = nil)
@stdout = @stderr = nil
self.out = super
end
def stdout
@stdout ||= out.stdout
.force_encoding(Encoding::UTF_8)
.gsub(/\e\[(\d+)(;\d+)*m/, "") # strip ANSI color codes
end
def stderr
@stderr ||= out.stderr
.force_encoding(Encoding::UTF_8)
.gsub(/\e\[(\d+)(;\d+)*m/, "") # strip ANSI color codes
end
#======================================================================#
# Git Repo Setup
@ -141,4 +161,17 @@ describe "running profiles with git-based dependencies" do
assert_exit_code(1, run_result) # General user error
end
end
#------------ Happy Case for default branch GIT fetching -------------------#
describe "running a remote GIT profile" do
it "should use default HEAD branch" do
inspec("exec #{git_default_main_profile_url}")
assert_empty stderr
assert_includes stdout, "Profile: InSpec Profile (default-main)"
assert_includes stdout, "Profile Summary: 1 successful control, 0 control failures, 0 controls skipped\n"
assert_includes stdout, "Test Summary: 2 successful, 0 failures, 0 skipped\n"
assert_exit_code 0, out
end
end
end

View file

@ -60,6 +60,16 @@ a7729ce65636d6d8b80159dd5dd7a40fdb6f2501\trefs/tags/anothertag^{}\n")
out
end
let(:git_remote_head_master) do
out = mock
out.stubs(:stdout).returns("HEAD branch: master\n")
out.stubs(:exitstatus).returns(0)
out.stubs(:stderr).returns("")
out.stubs(:error!).returns(false)
out.stubs(:run_command).returns(true)
out
end
before do
# git fetcher likes to make directories, let's stub that for every test
Dir.stubs(:mktmpdir).yields("test-tmp-dir")
@ -67,6 +77,10 @@ a7729ce65636d6d8b80159dd5dd7a40fdb6f2501\trefs/tags/anothertag^{}\n")
FileUtils.stubs(:mkdir_p)
end
def expect_git_remote_head_master(remote_url)
Mixlib::ShellOut.expects(:new).with("git remote show #{remote_url}", {}).returns(git_remote_head_master)
end
def expect_ls_remote(ref)
Mixlib::ShellOut.expects(:new).with("git ls-remote \"#{git_dep_dir}\" \"#{ref}*\"", {}).returns(git_ls_remote_output)
end
@ -83,7 +97,8 @@ a7729ce65636d6d8b80159dd5dd7a40fdb6f2501\trefs/tags/anothertag^{}\n")
FileUtils.expects(:cp_r).with("test-tmp-dir/.", "fetchpath")
end
it "resolves to the revision of master by default" do
it "resolves to the revision of master when head branch master" do
expect_git_remote_head_master(git_dep_dir)
expect_ls_remote("master")
result = fetcher.resolve({ git: git_dep_dir })
_(result.resolved_source).must_equal({ git: git_dep_dir, ref: git_master_ref })
@ -107,6 +122,7 @@ a7729ce65636d6d8b80159dd5dd7a40fdb6f2501\trefs/tags/anothertag^{}\n")
end
it "fetches to the given location" do
expect_git_remote_head_master(git_dep_dir)
expect_ls_remote("master")
expect_clone
expect_checkout(git_master_ref)
@ -117,6 +133,7 @@ a7729ce65636d6d8b80159dd5dd7a40fdb6f2501\trefs/tags/anothertag^{}\n")
it "doesn't refetch an already cloned repo" do
File.expects(:directory?).with("fetchpath/.git").at_least_once.returns(true)
expect_git_remote_head_master(git_dep_dir)
expect_ls_remote("master")
expect_checkout(git_master_ref, "fetchpath")
result = fetcher.resolve({ git: git_dep_dir })
@ -125,6 +142,7 @@ a7729ce65636d6d8b80159dd5dd7a40fdb6f2501\trefs/tags/anothertag^{}\n")
it "returns the repo_path that we fetched to as the archive_path" do
File.expects(:directory?).with("fetchpath/.git").at_least_once.returns(true)
expect_git_remote_head_master(git_dep_dir)
expect_ls_remote("master")
expect_checkout(git_master_ref, "fetchpath")
result = fetcher.resolve({ git: git_dep_dir })
@ -132,4 +150,44 @@ a7729ce65636d6d8b80159dd5dd7a40fdb6f2501\trefs/tags/anothertag^{}\n")
_(result.archive_path).must_equal "fetchpath"
end
end
describe "when given a repository with default branch main" do
let(:git_default_main) { "inspec-test-profile-default-main" }
let(:git_main_ref) { "69220a2ba6a3b276184f328e69a953e83e283323" }
let(:git_remote_head_main) do
out = mock
out.stubs(:stdout).returns("HEAD branch: main\n")
out.stubs(:exitstatus).returns(0)
out.stubs(:stderr).returns("")
out.stubs(:error!).returns(false)
out.stubs(:run_command).returns(true)
out
end
let(:git_ls_remote_output_for_main) do
out = mock
out.stubs(:stdout).returns("69220a2ba6a3b276184f328e69a953e83e283323\trefs/heads/main")
out.stubs(:exitstatus).returns(0)
out.stubs(:stderr).returns("")
out.stubs(:error!).returns(false)
out.stubs(:run_command).returns(true)
out
end
def expect_git_remote_head_main(remote_url)
Mixlib::ShellOut.expects(:new).with("git remote show #{remote_url}", {}).returns(git_remote_head_main)
end
def expect_ls_remote(ref)
Mixlib::ShellOut.expects(:new).with("git ls-remote \"#{git_default_main}\" \"#{ref}*\"", {}).returns(git_ls_remote_output_for_main)
end
it "resolves to the revision of main when head branch main" do
expect_git_remote_head_main(git_default_main)
expect_ls_remote("main")
result = fetcher.resolve({ git: git_default_main })
_(result.resolved_source).must_equal({ git: git_default_main, ref: git_main_ref })
end
end
end