puppetfile-resolver 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tempfile'
4
+ require 'English'
5
+ require 'puppetfile-resolver/util'
6
+ require 'puppetfile-resolver/spec_searchers/common'
7
+ require 'puppetfile-resolver/spec_searchers/git_configuration'
8
+ require 'puppetfile-resolver/util'
9
+ require 'uri'
10
+
11
+ module PuppetfileResolver
12
+ module SpecSearchers
13
+ module Git
14
+ module GClone
15
+ # @summary clones the remote url and reads the metadata file
16
+ # @returns [String] the content of the metadata file
17
+ def self.metadata(puppetfile_module, resolver_ui, config)
18
+ repo_url = puppetfile_module.remote
19
+
20
+ unless PuppetfileResolver::Util.git?
21
+ resolver_ui.debug { 'Git executible not found, unable to use git clone resolution' }
22
+
23
+ return nil
24
+ end
25
+ return nil if repo_url.nil?
26
+ return nil unless valid_http_url?(repo_url)
27
+
28
+ metadata_file = 'metadata.json'
29
+
30
+ ref = puppetfile_module.ref ||
31
+ puppetfile_module.tag ||
32
+ puppetfile_module.commit ||
33
+ puppetfile_module.branch ||
34
+ 'HEAD'
35
+
36
+ resolver_ui.debug { "Querying git repository #{repo_url}" }
37
+
38
+ clone_and_read_file(repo_url, ref, metadata_file, config)
39
+ end
40
+
41
+ # @summary clones the git url and reads the file at the given ref
42
+ # a temp directory will be created and then destroyed during
43
+ # the cloning and reading process
44
+ # @param ref [String] the git ref, branch, commit, tag
45
+ # @param file [String] the file you wish to read
46
+ # @returns [String] the content of the file
47
+ def self.clone_and_read_file(url, ref, file, config)
48
+ clone_cmd = ['git', 'clone', '--bare', '--depth=1', '--single-branch']
49
+ err_msg = ''
50
+ if config.git.proxy
51
+ err_msg += " with proxy #{config.git.proxy}: "
52
+ proxy = "--config \"http.proxy=#{config.git.proxy}\" --config \"https.proxy=#{config.proxy}\""
53
+ clone_cmd.push(proxy)
54
+ end
55
+
56
+ Dir.mktmpdir(nil, config.git.clone_dir) do |dir|
57
+ clone_cmd.push("--branch=#{ref}") if ref != 'HEAD'
58
+ clone_cmd.push(url, dir)
59
+ out, err_out, process = ::PuppetfileResolver::Util.run_command(clone_cmd)
60
+ err_msg += out
61
+ raise err_msg unless process.success?
62
+ Dir.chdir(dir) do
63
+ content, err_out, process = ::PuppetfileResolver::Util.run_command(['git', 'show', "#{ref}:#{file}"])
64
+ raise 'InvalidContent' unless process.success? && content.length > 2
65
+ return content
66
+ end
67
+ end
68
+ end
69
+
70
+ def self.valid_http_url?(url)
71
+ # uri does not work with git urls, return true
72
+ return true if url.start_with?('git@')
73
+
74
+ uri = URI.parse(url)
75
+ uri.is_a?(URI::HTTP) && !uri.host.nil?
76
+ rescue URI::InvalidURIError
77
+ false
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puppetfile-resolver/util'
4
+ require 'puppetfile-resolver/spec_searchers/common'
5
+ require 'puppetfile-resolver/spec_searchers/git_configuration'
6
+
7
+ module PuppetfileResolver
8
+ module SpecSearchers
9
+ module Git
10
+ module GitHub
11
+ def self.metadata(puppetfile_module, resolver_ui, config)
12
+ repo_url = nil
13
+ if puppetfile_module.remote.start_with?('git@github.com:')
14
+ repo_url = puppetfile_module.remote.slice(15..-1)
15
+ repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
16
+ elsif puppetfile_module.remote.start_with?('https://github.com/')
17
+ repo_url = puppetfile_module.remote.slice(19..-1)
18
+ repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
19
+ end
20
+ return nil if repo_url.nil?
21
+
22
+ metadata_url = 'https://raw.githubusercontent.com/' + repo_url + '/'
23
+ if puppetfile_module.ref
24
+ metadata_url += puppetfile_module.ref + '/'
25
+ elsif puppetfile_module.tag
26
+ metadata_url += puppetfile_module.tag + '/'
27
+ else
28
+ # Default to master. Should it raise?
29
+ metadata_url += 'master/'
30
+ end
31
+ metadata_url += 'metadata.json'
32
+
33
+ resolver_ui.debug { "Querying GitHub with #{metadata_url}" }
34
+ err_msg = "Unable to find module at #{puppetfile_module.remote}"
35
+ err_msg += config.proxy ? " with proxy #{config.proxy}: " : ': '
36
+ response = nil
37
+
38
+ begin
39
+ response = ::PuppetfileResolver::Util.net_http_get(metadata_url, config.proxy)
40
+ rescue ::StandardError => e
41
+ raise err_msg + e.message
42
+ end
43
+
44
+ if response.code != '200'
45
+ resolver_ui.debug(err_msg + "Expected HTTP Code 200, but received #{response.code}")
46
+ return ''
47
+ end
48
+ response.body
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puppetfile-resolver/util'
4
+ require 'puppetfile-resolver/spec_searchers/common'
5
+ require 'puppetfile-resolver/spec_searchers/git_configuration'
6
+
7
+ module PuppetfileResolver
8
+ module SpecSearchers
9
+ module Git
10
+ module GitLab
11
+ def self.metadata(puppetfile_module, resolver_ui, config)
12
+ repo_url = nil
13
+ if puppetfile_module.remote.start_with?('git@gitlab.com:')
14
+ repo_url = puppetfile_module.remote.slice(15..-1)
15
+ repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
16
+ elsif puppetfile_module.remote.start_with?('https://gitlab.com/')
17
+ repo_url = puppetfile_module.remote.slice(19..-1)
18
+ repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
19
+ end
20
+ return nil if repo_url.nil?
21
+
22
+ # Example URL
23
+ # https://gitlab.com/simp/pupmod-simp-crypto_policy/-/raw/0.1.4/metadata.json
24
+ metadata_url = 'https://gitlab.com/' + repo_url + '/-/raw/'
25
+ if puppetfile_module.ref
26
+ metadata_url += puppetfile_module.ref + '/'
27
+ elsif puppetfile_module.tag
28
+ metadata_url += puppetfile_module.tag + '/'
29
+ else
30
+ # Default to master. Should it raise?
31
+ metadata_url += 'master/'
32
+ end
33
+ metadata_url += 'metadata.json'
34
+
35
+ resolver_ui.debug { "Querying GitLab with #{metadata_url}" }
36
+ err_msg = "Unable to find module at #{puppetfile_module.remote}"
37
+ err_msg += config.proxy ? " with proxy #{config.proxy}: " : ': '
38
+ response = nil
39
+
40
+ begin
41
+ response = ::PuppetfileResolver::Util.net_http_get(metadata_url, config.proxy)
42
+ rescue ::StandardError => e
43
+ raise err_msg + e.message
44
+ end
45
+
46
+ if response.code != '200'
47
+ resolver_ui.debug(err_msg + "Expected HTTP Code 200, but received #{response.code}")
48
+ return ''
49
+ end
50
+ response.body
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -3,6 +3,9 @@
3
3
  require 'puppetfile-resolver/util'
4
4
  require 'puppetfile-resolver/spec_searchers/common'
5
5
  require 'puppetfile-resolver/spec_searchers/git_configuration'
6
+ require 'puppetfile-resolver/spec_searchers/git/github'
7
+ require 'puppetfile-resolver/spec_searchers/git/gitlab'
8
+ require 'puppetfile-resolver/spec_searchers/git/gclone'
6
9
 
7
10
  module PuppetfileResolver
8
11
  module SpecSearchers
@@ -12,54 +15,21 @@ module PuppetfileResolver
12
15
  # Has the information been cached?
13
16
  return cache.load(dep_id) if cache.exist?(dep_id)
14
17
 
15
- # We _could_ git clone this, but it'll take too long. So for now, just
16
- # try and resolve github based repositories by crafting a URL
18
+ # The git clone method takes around (1s) depending on repo size. Not sure if the
19
+ # other methods take longer or shorter but I preserved the legacy code for now.
20
+ # Technically, the gclone class could replace the other classes and speed up
21
+ # this process here.
22
+ metadata = GitHub.metadata(puppetfile_module, resolver_ui, config) ||
23
+ GitLab.metadata(puppetfile_module, resolver_ui, config) ||
24
+ GClone.metadata(puppetfile_module, resolver_ui, config)
17
25
 
18
- repo_url = nil
19
- if puppetfile_module.remote.start_with?('git@github.com:')
20
- repo_url = puppetfile_module.remote.slice(15..-1)
21
- repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
22
- end
23
- if puppetfile_module.remote.start_with?('https://github.com/')
24
- repo_url = puppetfile_module.remote.slice(19..-1)
25
- repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
26
- end
27
-
28
- return [] if repo_url.nil?
29
-
30
- metadata_url = 'https://raw.githubusercontent.com/' + repo_url + '/'
31
- if puppetfile_module.ref
32
- metadata_url += puppetfile_module.ref + '/'
33
- elsif puppetfile_module.tag
34
- metadata_url += puppetfile_module.tag + '/'
35
- else
36
- # Default to master. Should it raise?
37
- metadata_url += 'master/'
38
- end
39
- metadata_url += 'metadata.json'
40
-
41
- require 'net/http'
42
- require 'uri'
43
-
44
- resolver_ui.debug { "Querying GitHub with #{metadata_url}" }
45
- err_msg = "Unable to find module at #{puppetfile_module.remote}"
46
- err_msg += config.proxy ? " with proxy #{config.proxy}: " : ': '
47
- response = nil
48
-
49
- begin
50
- response = ::PuppetfileResolver::Util.net_http_get(metadata_url, config.proxy)
51
- rescue ::StandardError => e
52
- raise err_msg + e.message
53
- end
54
-
55
- if response.code != '200'
56
- resolver_ui.debug(err_msg + "Expected HTTP Code 200, but received #{response.code}")
26
+ if metadata.nil? || metadata.empty?
27
+ # Cache that we couldn't find the metadata
57
28
  cache.save(dep_id, [])
58
29
  return []
59
30
  end
60
31
 
61
- # TODO: symbolise_object should be in a Util namespace
62
- metadata = ::PuppetfileResolver::Util.symbolise_object(::JSON.parse(response.body))
32
+ metadata = ::PuppetfileResolver::Util.symbolise_object(::JSON.parse(metadata))
63
33
  result = [Models::ModuleSpecification.new(
64
34
  name: metadata[:name],
65
35
  origin: :git,
@@ -3,7 +3,7 @@
3
3
  module PuppetfileResolver
4
4
  module SpecSearchers
5
5
  class GitConfiguration
6
- attr_accessor :proxy
6
+ attr_accessor :proxy, :clone_dir
7
7
  end
8
8
  end
9
9
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'open3'
4
+
3
5
  module PuppetfileResolver
4
6
  module Util
5
7
  def self.symbolise_object(object)
@@ -43,5 +45,22 @@ module PuppetfileResolver
43
45
  Net::HTTP.start(*start_args, http_options) { |http| return http.request(Net::HTTP::Get.new(uri)) }
44
46
  nil
45
47
  end
48
+
49
+ # @summary runs the command on the shell
50
+ # @param cmd [Array] an array of command and args
51
+ # @returns [Array] the result of running the comand and the process
52
+ # @example run_command(['git', '--version'])
53
+ def self.run_command(cmd)
54
+ Open3.capture3(*cmd)
55
+ end
56
+
57
+ # @summary checks if git is installed and on the path
58
+ # @returns [Boolean] true if git is found in the path
59
+ def self.git?
60
+ Open3.capture3('git', '--version')
61
+ true
62
+ rescue Errno::ENOENT
63
+ false
64
+ end
46
65
  end
47
66
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PuppetfileResolver
4
- VERSION ||= '0.5.0'
4
+ VERSION ||= '0.6.0'
5
5
  end
@@ -3,10 +3,8 @@ require 'spec_helper'
3
3
  require 'puppetfile-resolver/resolver'
4
4
  require 'puppetfile-resolver/puppetfile'
5
5
 
6
-
7
6
  describe 'KitchenSink Tests' do
8
7
  it 'should resolve a complete Puppetfile' do
9
-
10
8
  content = <<-PUPFILE
11
9
  forge 'https://forge.puppet.com'
12
10
 
@@ -14,6 +12,10 @@ describe 'KitchenSink Tests' do
14
12
  :git => 'https://github.com/puppetlabs/puppetlabs-powershell',
15
13
  :tag => 'v4.0.0'
16
14
 
15
+ mod 'simpkv',
16
+ :git => 'https://gitlab.com/simp/pupmod-simp-simpkv.git',
17
+ :tag => '0.7.1'
18
+
17
19
  mod 'puppetlabs/stdlib', '6.3.0'
18
20
 
19
21
  # Local module path module
@@ -35,6 +37,9 @@ describe 'KitchenSink Tests' do
35
37
  expect(result.specifications).to include('powershell')
36
38
  expect(result.specifications['powershell'].version.to_s).to eq('4.0.0')
37
39
 
40
+ expect(result.specifications).to include('simpkv')
41
+ expect(result.specifications['simpkv'].version.to_s).to eq('0.7.1')
42
+
38
43
  expect(result.specifications).to include('stdlib')
39
44
  expect(result.specifications['stdlib'].version.to_s).to eq('6.3.0')
40
45
 
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ require 'puppetfile-resolver/spec_searchers/git/gclone'
3
+ require 'puppetfile-resolver/spec_searchers/git_configuration'
4
+ require 'logger'
5
+ require 'json'
6
+
7
+ describe PuppetfileResolver::SpecSearchers::Git::GClone do
8
+ PuppetfileModule = Struct.new(:remote, :ref, :branch, :commit, :tag, keyword_init: true)
9
+ config = PuppetfileResolver::SpecSearchers::Configuration.new
10
+ config.local.puppet_module_paths = [File.join(FIXTURES_DIR, 'modulepath')]
11
+
12
+ let(:url) do
13
+ 'https://github.com/puppetlabs/puppetlabs-powershell'
14
+ end
15
+
16
+ let(:puppetfile_module) do
17
+ PuppetfileModule.new(remote: url)
18
+ end
19
+
20
+
21
+ context 'valid url' do
22
+ it 'reads metadata' do
23
+ content = subject.metadata(puppetfile_module, Logger.new(STDERR), config)
24
+ expect(JSON.parse(content)['name']).to eq('puppetlabs-powershell')
25
+ end
26
+
27
+ context 'with ref' do
28
+
29
+ let(:puppetfile_module) do
30
+ PuppetfileModule.new(remote: url, ref: '2.1.2')
31
+ end
32
+
33
+ it 'reads metadata' do
34
+ content = subject.metadata(puppetfile_module, Logger.new(STDERR), config)
35
+ expect(JSON.parse(content)['name']).to eq('puppetlabs-powershell')
36
+ end
37
+ end
38
+ end
39
+
40
+ context 'invalid url' do
41
+ let(:url) do
42
+ 'https://github.com/puppetlabs/puppetlabs-powershellbad'
43
+ end
44
+
45
+ it 'throws exception' do
46
+ expect{subject.metadata(puppetfile_module, Logger.new(STDERR), config)}
47
+ .to raise_exception(RuntimeError)
48
+ end
49
+ end
50
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppetfile-resolver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Glenn Sarti
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-16 00:00:00.000000000 Z
11
+ date: 2022-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: molinillo
@@ -85,6 +85,9 @@ files:
85
85
  - lib/puppetfile-resolver/spec_searchers/forge.rb
86
86
  - lib/puppetfile-resolver/spec_searchers/forge_configuration.rb
87
87
  - lib/puppetfile-resolver/spec_searchers/git.rb
88
+ - lib/puppetfile-resolver/spec_searchers/git/gclone.rb
89
+ - lib/puppetfile-resolver/spec_searchers/git/github.rb
90
+ - lib/puppetfile-resolver/spec_searchers/git/gitlab.rb
88
91
  - lib/puppetfile-resolver/spec_searchers/git_configuration.rb
89
92
  - lib/puppetfile-resolver/spec_searchers/local.rb
90
93
  - lib/puppetfile-resolver/spec_searchers/local_configuration.rb
@@ -103,6 +106,7 @@ files:
103
106
  - spec/unit/puppetfile-resolver/puppetfile/document_spec.rb
104
107
  - spec/unit/puppetfile-resolver/puppetfile/parser/r10k_eval_spec.rb
105
108
  - spec/unit/puppetfile-resolver/resolver_spec.rb
109
+ - spec/unit/puppetfile-resolver/spec_searchers/git/gclone_spec.rb
106
110
  homepage: https://glennsarti.github.io/puppetfile-resolver/
107
111
  licenses:
108
112
  - Apache-2.0
@@ -137,3 +141,4 @@ test_files:
137
141
  - spec/unit/puppetfile-resolver/puppetfile/document_spec.rb
138
142
  - spec/unit/puppetfile-resolver/puppetfile/parser/r10k_eval_spec.rb
139
143
  - spec/unit/puppetfile-resolver/resolver_spec.rb
144
+ - spec/unit/puppetfile-resolver/spec_searchers/git/gclone_spec.rb