puppetfile-resolver 0.5.0 → 0.6.0

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.
@@ -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