cem_win_spec 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/lib/cem_win_spec/fixture_cache.rb +43 -9
- data/lib/cem_win_spec/module_archive_builder.rb +28 -33
- data/lib/cem_win_spec/rake_tasks.rb +15 -7
- data/lib/cem_win_spec/test_runner.rb +1 -1
- data/lib/cem_win_spec/version.rb +1 -1
- data/lib/cem_win_spec/win_exec/cmd/winrm_cmd.rb +2 -2
- data/lib/cem_win_spec.rb +26 -6
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c99510b91f69ac85f4e529d51134f797546bca8ee7ede74629a08620280b4c6
|
4
|
+
data.tar.gz: 57aa64d9931b08ce6a1e49178303643ded631334b43612707ee7383fb8c07426
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdc2ba16b32de3f4e5eff3f327d5407cb7d377cb836ae971b9c7dd57b771d8b1e7d7347c312006e52e77302c8ff2c61c899d5f82e39336aefa8bfb41dca0e865
|
7
|
+
data.tar.gz: 07f97ff0b736be471fea8cd9db08ce10c070353e03c5e523fc301b75a39a6689e77149ea95933d55c7cda5110f93983e562305bf4020472025fadde500293a31
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cem_win_spec (0.1.
|
4
|
+
cem_win_spec (0.1.6)
|
5
5
|
parallel_tests (~> 3.4)
|
6
6
|
puppet_forge (~> 4.1)
|
7
7
|
winrm (~> 2.3)
|
@@ -15,7 +15,7 @@ GEM
|
|
15
15
|
coderay (1.1.3)
|
16
16
|
diff-lcs (1.5.0)
|
17
17
|
erubi (1.12.0)
|
18
|
-
faraday (2.7.
|
18
|
+
faraday (2.7.10)
|
19
19
|
faraday-net_http (>= 2.0, < 3.1)
|
20
20
|
ruby2_keywords (>= 0.0.4)
|
21
21
|
faraday-follow_redirects (0.3.0)
|
@@ -8,6 +8,8 @@ require 'puppet_forge'
|
|
8
8
|
require 'yaml'
|
9
9
|
|
10
10
|
module CemWinSpec
|
11
|
+
class FixtureCacheError < StandardError; end
|
12
|
+
|
11
13
|
# Class for managing cached fixtures
|
12
14
|
# Fixture caching is used to speed up test runs by reusing the same
|
13
15
|
# Puppet modules between test runs instead of downloading them each time.
|
@@ -24,11 +26,10 @@ module CemWinSpec
|
|
24
26
|
attr_reader :cache_dir, :cache_entries
|
25
27
|
|
26
28
|
def initialize
|
27
|
-
|
28
|
-
|
29
|
+
validate_platform!
|
29
30
|
@cache_dir = CACHE_DIR
|
30
31
|
@cache_entries = setup_and_load_cache
|
31
|
-
@entries_digest =
|
32
|
+
@entries_digest = hexdigest(@cache_entries.to_s)
|
32
33
|
@dependencies = dependencies_from_metadata
|
33
34
|
setup!
|
34
35
|
end
|
@@ -43,6 +44,8 @@ module CemWinSpec
|
|
43
44
|
puts "Downloading #{name} #{data[:version]}..."
|
44
45
|
download_and_cache(name, data[:release_slug], data[:checksum])
|
45
46
|
end
|
47
|
+
rescue StandardError => e
|
48
|
+
handle_error(e, 'Failed to setup fixture cache')
|
46
49
|
ensure
|
47
50
|
save_cache_entries
|
48
51
|
end
|
@@ -52,16 +55,37 @@ module CemWinSpec
|
|
52
55
|
raise "Directory #{fixtures_dir} does not exist" unless File.directory?(fixtures_dir)
|
53
56
|
|
54
57
|
@cache_entries.each do |_, path|
|
55
|
-
::FileUtils.cp_r(path, fixtures_dir)
|
56
|
-
interim_mod_path = File.join(fixtures_dir, File.basename(path))
|
57
58
|
final_mod_path = File.join(fixtures_dir, File.basename(path).split('-').last)
|
58
|
-
::FileUtils.
|
59
|
-
|
59
|
+
::FileUtils.remove_entry_secure(final_mod_path) if File.exist?(final_mod_path)
|
60
|
+
::FileUtils.cp_r(path, final_mod_path)
|
61
|
+
puts "Copied #{path} to #{final_mod_path}"
|
60
62
|
end
|
63
|
+
rescue StandardError => e
|
64
|
+
handle_error(e, "Failed to copy fixtures to #{fixtures_dir}")
|
61
65
|
end
|
62
66
|
|
63
67
|
private
|
64
68
|
|
69
|
+
def validate_platform!
|
70
|
+
return if Gem.win_platform?
|
71
|
+
|
72
|
+
$stderr.puts 'ERROR: FixtureCache must run on Windows'
|
73
|
+
raise FixtureCacheError, 'FixtureCache must run on Windows'
|
74
|
+
end
|
75
|
+
|
76
|
+
def hexdigest(str)
|
77
|
+
Digest(:SHA256).hexdigest(str)
|
78
|
+
end
|
79
|
+
|
80
|
+
def handle_error(e, msg = 'Fixture cache error')
|
81
|
+
$stderr.puts "ERROR: #{msg}: #{e}"
|
82
|
+
raise e if e.is_a?(FixtureCacheError)
|
83
|
+
|
84
|
+
new_err = FixtureCacheError.new("#{msg}: #{e}")
|
85
|
+
new_err.set_backtrace(e.backtrace)
|
86
|
+
raise new_err
|
87
|
+
end
|
88
|
+
|
65
89
|
def dependencies_from_metadata
|
66
90
|
raise "File metadata.json not found in current directory #{Dir.pwd}" unless File.exist?('metadata.json')
|
67
91
|
|
@@ -81,6 +105,8 @@ module CemWinSpec
|
|
81
105
|
release_slug: latest_valid_release.slug,
|
82
106
|
}
|
83
107
|
end
|
108
|
+
rescue StandardError => e
|
109
|
+
handle_error(e, 'Failed to get dependencies from metadata.json')
|
84
110
|
end
|
85
111
|
|
86
112
|
def dep_version_req_satisfied?(version_req, version)
|
@@ -88,6 +114,8 @@ module CemWinSpec
|
|
88
114
|
raise "Invalid version requirement #{version_req}" unless reqs.to_a.length > 1
|
89
115
|
|
90
116
|
reqs.to_a[1..-1].all? { |req| version_req_satisfied?(req, version) }
|
117
|
+
rescue StandardError => e
|
118
|
+
handle_error(e, 'Failed checking version requirement satisfaction')
|
91
119
|
end
|
92
120
|
|
93
121
|
def version_req_satisfied?(version_req, version)
|
@@ -95,7 +123,7 @@ module CemWinSpec
|
|
95
123
|
end
|
96
124
|
|
97
125
|
def module_checksum(name, version_req, version)
|
98
|
-
|
126
|
+
hexdigest("#{name}#{version_req}#{version}")
|
99
127
|
end
|
100
128
|
|
101
129
|
def manifest
|
@@ -114,6 +142,8 @@ module CemWinSpec
|
|
114
142
|
end
|
115
143
|
puts "Loading cache manifest #{manifest}..."
|
116
144
|
YAML.load_file(manifest)
|
145
|
+
rescue StandardError => e
|
146
|
+
handle_error(e, 'Failed to setup and load cache')
|
117
147
|
end
|
118
148
|
|
119
149
|
def cached?(checksum)
|
@@ -132,13 +162,17 @@ module CemWinSpec
|
|
132
162
|
File.join(module_cache_dir, 'temp'))
|
133
163
|
cache_entries[checksum] = File.join(module_cache_dir, name)
|
134
164
|
puts "Downloaded #{release_slug} to #{File.join(module_cache_dir, name)}"
|
165
|
+
rescue StandardError => e
|
166
|
+
handle_error(e, "Failed to download and cache #{name} with slug #{release_slug} and checksum #{checksum}")
|
135
167
|
end
|
136
168
|
|
137
169
|
def save_cache_entries
|
138
|
-
return if @entries_digest ==
|
170
|
+
return if @entries_digest == hexdigest(cache_entries.to_s)
|
139
171
|
|
140
172
|
File.write(manifest, cache_entries.to_yaml)
|
141
173
|
puts "Saved cache manifest #{manifest}"
|
174
|
+
rescue StandardError => e
|
175
|
+
handle_error(e, "Failed to save cache manifest #{manifest}")
|
142
176
|
end
|
143
177
|
end
|
144
178
|
end
|
@@ -8,50 +8,37 @@ module CemWinSpec
|
|
8
8
|
class ModuleArchiveBuilder
|
9
9
|
include CemWinSpec::Logging
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
tasks
|
19
|
-
types
|
20
|
-
.fixtures.yml
|
21
|
-
.gitignore
|
22
|
-
.rspec
|
23
|
-
.rubocop.yml
|
24
|
-
.yardopts
|
25
|
-
hiera.yaml
|
26
|
-
Gemfile
|
27
|
-
metadata.json
|
28
|
-
Rakefile
|
11
|
+
FILE_EXCLUDELIST = %w[
|
12
|
+
.git/**/*
|
13
|
+
data/benchmarks/**/*
|
14
|
+
dev/**/*
|
15
|
+
spec/fixtures/modules/*
|
16
|
+
pkg/**/*
|
17
|
+
Gemfile.lock
|
29
18
|
].freeze
|
30
19
|
|
31
|
-
attr_reader :module_dir, :
|
20
|
+
attr_reader :module_dir, :excludelist, :tempdir, :archive
|
32
21
|
|
33
|
-
def initialize(module_dir = Dir.pwd,
|
22
|
+
def initialize(module_dir = Dir.pwd, excludelist: FILE_EXCLUDELIST)
|
34
23
|
@module_dir = module_dir
|
35
24
|
@module_name = File.basename(module_dir)
|
36
|
-
@
|
25
|
+
@excludelist = excludelist
|
37
26
|
end
|
38
27
|
|
39
28
|
alias path archive
|
40
29
|
|
41
|
-
def build
|
30
|
+
def build(remove_when_complete: true)
|
42
31
|
create_tempdir
|
43
32
|
copy_module_to_tempdir
|
44
33
|
remove_unwanted_files
|
45
34
|
create_archive
|
46
35
|
if block_given?
|
47
36
|
begin
|
48
|
-
yield archive
|
49
|
-
ensure
|
50
|
-
FileUtils.rm_rf(archive) if archive && File.exist?(archive)
|
37
|
+
yield File.join(tempdir, archive)
|
51
38
|
end
|
52
39
|
end
|
53
40
|
ensure
|
54
|
-
FileUtils.rm_rf(tempdir) if tempdir && File.exist?(tempdir)
|
41
|
+
FileUtils.rm_rf(tempdir) if remove_when_complete && tempdir && File.exist?(tempdir)
|
55
42
|
end
|
56
43
|
|
57
44
|
private
|
@@ -62,22 +49,30 @@ module CemWinSpec
|
|
62
49
|
end
|
63
50
|
|
64
51
|
def copy_module_to_tempdir
|
65
|
-
FileUtils.cp_r(module_dir, tempdir)
|
52
|
+
FileUtils.cp_r(module_dir, tempdir, preserve: false)
|
66
53
|
logger.debug "Copied #{module_dir} to #{tempdir}"
|
67
54
|
@temp_module_dir = File.join(tempdir, @module_name)
|
68
55
|
end
|
69
56
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
57
|
+
def unwanted_files
|
58
|
+
unwanted = []
|
59
|
+
Dir.glob('**/*', File::FNM_DOTMATCH, base: @temp_module_dir) do |f|
|
60
|
+
next if %w[. ..].include?(f)
|
61
|
+
|
62
|
+
unwanted << File.join(@temp_module_dir, f) if excludelist.any? { |e| File.fnmatch?(e, f, File::FNM_DOTMATCH) }
|
75
63
|
end
|
64
|
+
unwanted
|
65
|
+
end
|
66
|
+
|
67
|
+
def remove_unwanted_files
|
68
|
+
FileUtils.rm_rf(unwanted_files, verbose: (logger.level.first <= Logger::DEBUG))
|
76
69
|
end
|
77
70
|
|
78
71
|
def create_archive
|
79
72
|
@archive = "#{@module_name}.tar.gz"
|
80
|
-
|
73
|
+
Dir.chdir(tempdir) do
|
74
|
+
`COPYFILE_DISABLE=1 tar -czf #{archive} --no-acls --no-xattrs #{@module_name}`
|
75
|
+
end
|
81
76
|
logger.info "Created module archive #{archive}"
|
82
77
|
end
|
83
78
|
end
|
@@ -81,7 +81,7 @@ namespace 'cem_win_spec' do
|
|
81
81
|
task :prep do
|
82
82
|
puts 'Preparing spec data...'
|
83
83
|
data_fix = cem_win_spec_base_path_in_fixtures(cem_win_spec_data_dir)
|
84
|
-
if
|
84
|
+
if Dir.exist?(data_fix)
|
85
85
|
puts "Removing old #{data_fix} directory..."
|
86
86
|
::FileUtils.remove_entry_secure(data_fix)
|
87
87
|
end
|
@@ -91,16 +91,23 @@ namespace 'cem_win_spec' do
|
|
91
91
|
raise 'Spec data copy failed!'
|
92
92
|
end
|
93
93
|
hiera_fix = cem_win_spec_base_path_in_fixtures(cem_win_spec_hiera_conf)
|
94
|
+
if File.file?(hiera_fix)
|
95
|
+
puts "Removing old #{hiera_fix} file..."
|
96
|
+
::FileUtils.remove_entry_secure(hiera_fix)
|
97
|
+
end
|
94
98
|
puts "Copying Hiera config to #{hiera_fix}..."
|
95
99
|
::FileUtils.cp(cem_win_spec_hiera_conf, hiera_fix)
|
96
|
-
unless File.exist?(hiera_fix)
|
97
|
-
|
98
|
-
end
|
100
|
+
raise 'Hiera config copy failed!' unless File.exist?(hiera_fix)
|
101
|
+
|
99
102
|
puts 'Spec data prepared successfully'
|
100
|
-
puts '
|
101
|
-
mod_fix = cem_win_spec_base_path_in_fixtures('modules')
|
103
|
+
puts 'Setting up module fixture cache...'
|
102
104
|
cache = CemWinSpec::FixtureCache.new
|
105
|
+
puts 'Copying module fixtures to spec fixtures directory...'
|
106
|
+
mod_fix = cem_win_spec_base_path_in_fixtures('modules')
|
103
107
|
cache.copy_fixtures_to(mod_fix)
|
108
|
+
puts 'Removing old module symlink...'
|
109
|
+
link_path = File.join(mod_fix, 'cem_windows')
|
110
|
+
::FileUtils.remove_entry_secure(link_path) if File.exist?(link_path)
|
104
111
|
puts 'Module fixtures prepared successfully'
|
105
112
|
end
|
106
113
|
|
@@ -108,9 +115,10 @@ namespace 'cem_win_spec' do
|
|
108
115
|
task :parallel_spec_standalone do
|
109
116
|
spec_files = Rake::FileList[cem_win_spec_pattern]
|
110
117
|
pargs = ['--type', 'rspec']
|
111
|
-
pargs << '--
|
118
|
+
pargs << '--verbose' if cem_win_spec_trace
|
112
119
|
rspec_args = ['--']
|
113
120
|
rspec_args << '--fail-fast' if cem_win_spec_fail_fast
|
121
|
+
rspec_args << '--backtrace' if cem_win_spec_trace
|
114
122
|
rspec_args.concat(['--format', cem_win_spec_format])
|
115
123
|
pargs.concat(rspec_args)
|
116
124
|
pargs << '--'
|
@@ -68,7 +68,7 @@ module CemWinSpec
|
|
68
68
|
module_archive_build { |a| remote_upload(a, remote_working_dir) }
|
69
69
|
module_dir = "#{remote_working_dir}\\#{File.basename(module_archive_path, '.tar.gz')}"
|
70
70
|
logger.debug "Module uploaded to #{module_dir}.tar.gz, extracting..."
|
71
|
-
remote_run("tar -xzf #{module_dir}.tar.gz
|
71
|
+
remote_run("tar -C #{remote_working_dir} -xzf #{module_dir}.tar.gz")
|
72
72
|
logger.debug "Module extracted to #{module_dir}"
|
73
73
|
module_dir
|
74
74
|
end
|
data/lib/cem_win_spec/version.rb
CHANGED
@@ -29,8 +29,8 @@ module CemWinSpec
|
|
29
29
|
begin
|
30
30
|
shell = conn.shell(:powershell)
|
31
31
|
output = shell.run(command(cmd)) do |stdout, stderr|
|
32
|
-
logger << stdout
|
33
|
-
logger << stderr
|
32
|
+
logger << stdout if stdout
|
33
|
+
logger << stderr if stderr
|
34
34
|
end
|
35
35
|
rescue WinRM::WinRMAuthorizationError => e
|
36
36
|
@available = false
|
data/lib/cem_win_spec.rb
CHANGED
@@ -56,16 +56,37 @@ module CemWinSpec
|
|
56
56
|
raise ArgumentError, "Unknown operation: #{operation}"
|
57
57
|
end
|
58
58
|
rescue StandardError => e
|
59
|
-
|
60
|
-
|
61
|
-
|
59
|
+
if operation == :spec
|
60
|
+
begin
|
61
|
+
logger.warn "Error running spec: #{e.message}"
|
62
|
+
logger.debug e.backtrace.join("\n")
|
63
|
+
retry_spec_on_error(runner, module_dir, **options)
|
64
|
+
rescue StandardError => err
|
65
|
+
handle_run_error(err)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
handle_run_error(e)
|
69
|
+
end
|
62
70
|
end
|
63
71
|
end
|
64
72
|
|
73
|
+
def self.handle_run_error(err)
|
74
|
+
logger.fatal "Error: #{err.message}"
|
75
|
+
logger.debug err.backtrace.join("\n")
|
76
|
+
exit 1
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.retry_spec_on_error(runner, module_dir, **options)
|
80
|
+
logger.info 'Cleaning cache and trying again...'
|
81
|
+
clean_fixture_cache_out = clean_fixture_cache(runner, module_dir, **options)
|
82
|
+
check_output!(clean_fixture_cache_out, runner)
|
83
|
+
spec_out = run_spec(runner, module_dir, **options)
|
84
|
+
check_output!(spec_out, runner)
|
85
|
+
end
|
86
|
+
|
65
87
|
def self.setup_remote_environment(runner)
|
66
88
|
runner.enable_long_paths.run
|
67
89
|
runner.enable_symlinks.run
|
68
|
-
runner.enable_symlinks.run
|
69
90
|
working_dir_out = runner.create_working_dir.run
|
70
91
|
working_dir = working_dir_out.stdout.chomp
|
71
92
|
logger.debug "Working dir: #{working_dir}"
|
@@ -99,8 +120,7 @@ module CemWinSpec
|
|
99
120
|
def self.check_output!(output, runner = nil)
|
100
121
|
unless output.success?
|
101
122
|
runner&.iap_tunnel&.stop(wait: false, log: false)
|
102
|
-
|
103
|
-
exit output.exitcode
|
123
|
+
raise "Command failed with exit code #{output.exitcode}"
|
104
124
|
end
|
105
125
|
end
|
106
126
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cem_win_spec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Heston Snodgrass
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: winrm
|
@@ -139,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
139
|
- !ruby/object:Gem::Version
|
140
140
|
version: '0'
|
141
141
|
requirements: []
|
142
|
-
rubygems_version: 3.4.
|
142
|
+
rubygems_version: 3.4.18
|
143
143
|
signing_key:
|
144
144
|
specification_version: 4
|
145
145
|
summary: Write a short summary, because RubyGems requires one.
|