inspec/test/functional/git_fetcher_test.rb
Vasundhara Jagdale 8ee7bc946d
CHEF-642 Fix for inspec exec fails with git fetcher if current directory does not have .git directory (#6626)
* Functional Test to verify git fetcher able to work in a directory where git is not initialized or does not contain the .git directory

Signed-off-by: Vasu1105 <vasundhara.jagdale@chef.io>

* Fix: If git branch, tag or reference information is not given it should clone the repo and checkout the default HEAD

Signed-off-by: Vasu1105 <vasundhara.jagdale@chef.io>

* Remove the logic to find default branch in case of branch, tag or ref is not provided as it's not required logically as we will be cloning the and checkout the default HEAD

Signed-off-by: Vasu1105 <vasundhara.jagdale@progress.com>

* This is a temporary change to make verify test working on this PR. Revert once the work is done for the git fetcher fix

Signed-off-by: Vasu1105 <vasundhara.jagdale@progress.com>

* Unit Test: Fix unit test

Signed-off-by: Vasu1105 <vasundhara.jagdale@progress.com>

* Verifies the git url before creating cache_key, if given relative path does not exist make sure it deletes the cache directory created to copy the cloned repo. It raises error if any git command fails

Signed-off-by: Vasu1105 <vasundhara.jagdale@progress.com>

* Reverted verify git repo url call from cache_key as cache_key and shifted that to resolve_ref which is already raising the error in case of git ls remote command fails

Signed-off-by: Vasu1105 <vasundhara.jagdale@progress.com>

* Unit test to cover the changes done for resolve_ref when branch, tag or ref is not given and
unit test for invalid git repo

Signed-off-by: Vasu1105 <vasundhara.jagdale@progress.com>

---------

Signed-off-by: Vasu1105 <vasundhara.jagdale@chef.io>
Signed-off-by: Vasu1105 <vasundhara.jagdale@progress.com>
2023-08-31 20:06:24 +05:30

188 lines
8.4 KiB
Ruby

require "functional/helper"
require "fileutils"
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
#======================================================================#
fixture_repos = %w{basic-local git-repo-01}
before(:all) do
skip_windows! # Right now, this is due to symlinking, break executes on L24 <nickchecked>
# Stacktrace on windows machine:
# Error:
# running profiles with git-based dependencies::running a profile with an ./ relative path dependency#test_0001_should find the top-level profile in the git-referenced child profile and execute that:
# Errno::ENOENT: No such file or directory @ apply2files - C:/Users/some/path/inspec/inspec/test/fixtures/profiles/git-fetcher/basic-local/.git
# C:/Ruby/lib/ruby/2.6.0/fileutils.rb:1437:in `unlink'
# C:/Ruby/lib/ruby/2.6.0/fileutils.rb:1437:in `block in remove_file'
# C:/Ruby/lib/ruby/2.6.0/fileutils.rb:1445:in `platform_support'
# C:/Ruby/lib/ruby/2.6.0/fileutils.rb:1436:in `remove_file'
# C:/Ruby/lib/ruby/2.6.0/fileutils.rb:775:in `remove_file'
# C:/Ruby/lib/ruby/2.6.0/fileutils.rb:562:in `block in rm'
# C:/Ruby/lib/ruby/2.6.0/fileutils.rb:561:in `each'
# C:/Ruby/lib/ruby/2.6.0/fileutils.rb:561:in `rm'
# C:/Users/some/path/inspec/inspec/test/functional/git_fetcher_test.rb:31:in `block (3 levels) in <top (required)>'
# C:/Users/some/path/inspec/inspec/test/functional/git_fetcher_test.rb:29:in `each'
# C:/Users/some/path/inspec/inspec/test/functional/git_fetcher_test.rb:29:in `block (2 levels) in <top (required)>'"
# We need a git repo for some of the profile test fixtures,
# but we can't store those directly in git.
# Here, one approach is to store the .git/ directory under a
# different name and then symlink to its proper name.
fixture_repos.each do |profile_name|
link_src = "#{git_profiles}/#{profile_name}/git-fixture"
link_dst = "#{git_profiles}/#{profile_name}/.git"
FileUtils.ln_sf(link_src, link_dst) # -f to tolerate existing links created during manual testing
end
end
after(:all) do
fixture_repos.each do |profile_name|
link = "#{git_profiles}/#{profile_name}/.git"
FileUtils.rm(link)
end
end
#======================================================================#
# Custom Local Assertions
#======================================================================#
def assert_relative_fetch_works(profile_name, expected_profiles, expected_controls)
run_result = run_inspec_process("exec #{git_profiles}/#{profile_name}", json: true)
assert_empty run_result.stderr
assert_json_controls_passing(run_result)
# Should know about the top-level profile and the child profile
assert_equal expected_profiles, (@json["profiles"].map { |p| p["name"] })
controls = @json["profiles"].map { |p| p["controls"] }.flatten.map { |c| c["id"] }.uniq
# Should have controls from the top-level and included child profile
expected_controls.each { |control| assert_includes controls, control }
# should not have controls from the profile defined at the top of the repo of the child profile
refute_includes controls, "red-dye"
end
#======================================================================#
# Basic Git Fetching
#======================================================================#
describe "running a profile with a basic local dependency" do
it "should work on a local checkout" do
run_result = run_inspec_process("exec #{git_profiles}/basic-local", json: true)
assert_empty run_result.stderr
assert_json_controls_passing(run_result)
end
end
# describe "running a profile with a basic remote dependency"
# TODO: move private SSH+git test from inspec_exec_test to here
#======================================================================#
# Revision Selection
#======================================================================#
# NOTE: test branch, rev, and tag capabilities are (lighty) tested in unit tests
#======================================================================#
# Relative Path Support
#======================================================================#
#------------ Happy Cases for Relative Path Support -------------------#
describe "running a profile with a shallow relative path dependency" do
it "should find the relative path profile and execute exactly those controls" do
assert_relative_fetch_works("relative-shallow", %w{relative-shallow child-01}, %w{top-level-01 child-01})
end
end
describe "running a profile with a deep relative path dependency" do
it "should find the relative path profile and execute exactly those controls" do
assert_relative_fetch_works("relative-deep", %w{relative-deep child-02}, %w{relative-deep-01 child-02})
end
end
describe "running a profile with a combination of relative path dependencies" do
it "should find the relative path profiles and execute exactly those controls" do
assert_relative_fetch_works(
"relative-combo",
%w{relative-combo child-01 child-02},
%w{relative-combo-01 child-01 child-02}
)
end
end
#------------ Edge Cases for Relative Path Support -------------------#
describe "running a profile with an '' relative path dependency" do
it "should find the top-level profile in the git-referenced child profile and execute that" do
assert_relative_fetch_works("relative-empty", %w{relative-empty basic-local}, %w{relative-empty-01 basic-local-01})
end
end
describe "running a profile with an ./ relative path dependency" do
it "should find the top-level profile in the git-referenced child profile and execute that" do
assert_relative_fetch_works("relative-dot-slash", %w{relative-dot-slash basic-local}, %w{relative-dot-slash-01 basic-local-01})
end
end
describe "running a profile with a relative path dependency that does not exist" do
it "should fail gracefully" do
run_result = run_inspec_process("exec #{git_profiles}/relative-nonesuch")
assert_empty run_result.stdout
refute_includes run_result.stderr, "Errno::ENOENT" # No ugly file missing error
assert_equal 1, run_result.stderr.lines.count # Not a giant stacktrace
# Spot check important parts of the message
assert_includes run_result.stderr, "Cannot find relative path"
assert_includes run_result.stderr, "no/such/path" # the actual missing path
assert_includes run_result.stderr, "profile in git repo"
# The containing git repo (the only identifier the user will have)
assert_includes run_result.stderr, "test/fixtures/profiles/git-fetcher/git-repo-01"
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
describe "running a remote GIT profile from directory which does not have .git directory" do
it "should use default HEAD branch" do
Dir.mktmpdir do |temp_dir_path|
Dir.chdir(temp_dir_path) do
inspec("exec #{git_default_main_profile_url}")
assert_empty stderr
end
end
end
end
end