gurney_client 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e7470d3ea652657be230f28b42b3035ee0e2c47122dc297533428831fc20b2b
4
- data.tar.gz: 7e3bf5796d850cc8e600959a348f521d9d7ee10f5f7e329da391c0b125f57db0
3
+ metadata.gz: f97820b2ae67e568a14d65e7d5d700d97ee0cb402e755237f4bd2c3f735105d1
4
+ data.tar.gz: 2c6adc8f7f8c608b5d0a7b728ad1847e44e524b3e7449aee997becd70ac3178a
5
5
  SHA512:
6
- metadata.gz: c04cfc2febd10dcb6be12b4b8466f5c11d308954c57a7588a0bb41100f64eabc4656867af4d97d1c2d40ee607d5a3206e8fc3c0477021d04efd471c599abd540
7
- data.tar.gz: cb327dd15bfd5aea5c30a87ff271555c17c9e29c8ec35379fa9bdb4ce3fd21b935e6ba80d1a0057abdd7f75b76d263da1089b209bce7576c857ca570f0f563e8
6
+ metadata.gz: 55ba64f495bfc3cd10f60e4caff368b26d341075d10d89fc1742bd17dd0af044d3cc8788daeea36ca403cadc947c3a196866bd140066d3e451cffc561c891a81
7
+ data.tar.gz: 4054647a511f7936c6c9e1f6c18ee65d76df6bc582d35ad290fac0e79010f1696431c5c7ed130c701392d1860af012ccbdeb1ad37cc7c1dab953c351fdb8d841
data/CHANGELOG.md CHANGED
@@ -1,13 +1,44 @@
1
- # Gurney changelog
1
+ # Changelog
2
2
 
3
- ## 0.4.0 (2024-11-15)
3
+ All notable changes to this project will be documented in this file.
4
+ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
5
+
6
+ ## Unreleased
7
+
8
+ ### Compatible changes
9
+
10
+ ### Breaking changes
11
+
12
+
13
+ ## 0.6.0 2025-06-16
14
+
15
+ ### Compatible changes
16
+ * Added: New option `--prefix` to specify the location of the dependency files
17
+ in case they are not on root level of your git repository.
18
+
19
+
20
+ ## 0.5.0 2025-03-26
21
+
22
+ ### Compatible changes
23
+ * Dependencies are also parsed from package-lock.json and pnpm-lock.yaml if present.
24
+
25
+
26
+ ## 0.4.0 2024-11-15
27
+
28
+ ### Compatible changes
4
29
  * Added: Reporting of the repository path as identifier. Should it ever change,
5
30
  it is an indicator for an unchanged gurney.yml in a project fork, and the
6
31
  API may respond with an error.
7
32
 
8
- ## 0.3.0 (2024-11-14)
33
+
34
+ ## 0.3.0 2024-11-14
35
+
36
+ ### Compatible changes
9
37
  * Added: Compatibility with Ruby 3
10
38
  * Fixed: Support UTF-8 chars in branch names
11
39
 
12
- ## 0.2.3 (2023-05-24)
40
+
41
+ ## 0.2.3 2023-05-24
42
+
43
+ ### Compatible changes
13
44
  * Added: Suppress Bundler's "the Bundler version is older than the one in the lockfile" warning.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gurney_client (0.4.0)
4
+ gurney_client (0.6.0)
5
5
  bundler (< 3)
6
6
  colorize (~> 0.8)
7
7
  git (~> 1.5)
data/README.md CHANGED
@@ -22,6 +22,7 @@ Usage: gurney [options]
22
22
  -h, --hook Run as a Git post-receive hook
23
23
  --client-hook Run as a Git pre-push hook
24
24
  -p, --project-id [PROJECT ID] Specify project id for API
25
+ --prefix [PATH] Specify the prefix of dependency paths
25
26
  --help Print this help
26
27
  ```
27
28
 
@@ -41,6 +41,10 @@ module Gurney
41
41
  options.project_id = project_id
42
42
  end
43
43
 
44
+ opts.on('', '--prefix [PATH]', 'Specify the prefix of dependency paths') do |prefix|
45
+ options.prefix = prefix
46
+ end
47
+
44
48
  opts.on_tail('', '--help', 'Prints this help') do
45
49
  puts opts
46
50
  exit
data/lib/gurney/cli.rb CHANGED
@@ -40,7 +40,8 @@ module Gurney
40
40
  end
41
41
 
42
42
  config_file = MAIN_BRANCHES.find do |branch|
43
- file = read_file(options.hook, branch, options.config_file)
43
+ git_file_reader = GitFileReader.new(git, branch, read_from_git: options.hook)
44
+ file = git_file_reader.read(options.config_file)
44
45
  break file if file
45
46
  end
46
47
  if options.hook && !config_file
@@ -55,8 +56,9 @@ module Gurney
55
56
  options.api_token ||= config&.api_token
56
57
  options.api_url ||= config&.api_url
57
58
  options.project_id ||= config&.project_id
59
+ options.prefix ||= config&.prefix
58
60
 
59
- missing_options = [:project_id, :branches, :api_url, :api_token].select { |option| options.send(option).nil? }
61
+ missing_options = [:project_id, :branches, :api_url, :api_token, :prefix].select { |option| options.send(option).nil? }
60
62
  # Use the line below in development
61
63
  # missing_options = [:project_id, :branches, :api_token].select { |option| options.send(option).nil? }
62
64
  raise Gurney::Error.new("Incomplete config - missing #{missing_options.map(&:inspect).join(', ')}.") unless missing_options.empty?
@@ -64,18 +66,8 @@ module Gurney
64
66
 
65
67
  def run
66
68
  reporting_branches.each do |branch|
67
- dependencies = []
68
-
69
- yarn_source = Gurney::Source::Yarn.new(yarn_lock: read_file(options.hook || options.client_hook, branch, 'yarn.lock'))
70
- dependencies.concat yarn_source.dependencies || []
71
-
72
- bundler_source = Gurney::Source::Bundler.new(gemfile_lock: read_file(options.hook || options.client_hook, branch, 'Gemfile.lock'))
73
- dependencies.concat bundler_source.dependencies || []
74
-
75
- ruby_version_source = Gurney::Source::RubyVersion.new(ruby_version: read_file(options.hook || options.client_hook, branch, '.ruby-version'))
76
- dependencies.concat ruby_version_source.dependencies || []
77
-
78
- dependencies.compact!
69
+ git_file_reader = GitFileReader.new(git, branch, read_from_git: options.hook || options.client_hook, prefix: options.prefix)
70
+ dependencies = DependencyCollector.new(git_file_reader).collect_all
79
71
 
80
72
  api = Gurney::Api.new(base_url: options.api_url, token: options.api_token)
81
73
  api.post_dependencies(dependencies: dependencies, branch: branch, project_id: options.project_id, repo_path: git.repo.path)
@@ -115,17 +107,5 @@ module Gurney
115
107
  branches
116
108
  end
117
109
 
118
- def read_file(from_git, branch, filename)
119
- if from_git
120
- begin
121
- git.show("#{branch}:#{filename}")
122
- rescue Git::GitExecuteError
123
- # happens if branch does not exist
124
- end
125
- else
126
- File.read(filename) if File.exist?(filename)
127
- end
128
- end
129
-
130
110
  end
131
111
  end
data/lib/gurney/config.rb CHANGED
@@ -3,13 +3,14 @@ require 'yaml'
3
3
  module Gurney
4
4
  class Config
5
5
 
6
- attr_accessor :branches, :api_url, :api_token, :project_id
6
+ attr_accessor :branches, :api_url, :api_token, :project_id, :prefix
7
7
 
8
- def initialize(branches: nil, api_url: nil, api_token: nil, project_id: nil)
8
+ def initialize(branches: nil, api_url: nil, api_token: nil, project_id: nil, prefix: '.')
9
9
  @branches = branches
10
10
  @api_url = api_url
11
11
  @api_token = api_token&.to_s
12
12
  @project_id = project_id&.to_s
13
+ @prefix = prefix&.to_s
13
14
  end
14
15
 
15
16
  def self.from_yaml(yaml)
@@ -0,0 +1,64 @@
1
+ module Gurney
2
+ class DependencyCollector
3
+
4
+ def initialize(git_file_reader)
5
+ @git_file_reader = git_file_reader
6
+ end
7
+
8
+ def collect_all
9
+ dependencies = []
10
+
11
+ dependencies.concat npm_dependencies
12
+ dependencies.concat bundler_dependencies
13
+ dependencies.concat ruby_version_dependencies
14
+
15
+ dependencies.compact
16
+ end
17
+
18
+ private
19
+
20
+ def bundler_dependencies
21
+ bundler_source = Gurney::Source::Bundler.new(gemfile_lock: @git_file_reader.read('Gemfile.lock'))
22
+ bundler_source.dependencies || []
23
+ end
24
+
25
+ def ruby_version_dependencies
26
+ ruby_version_source = Gurney::Source::RubyVersion.new(ruby_version: @git_file_reader.read('.ruby-version'))
27
+ ruby_version_source.dependencies || []
28
+ end
29
+
30
+ def npm_dependencies
31
+ npm_dependencies = []
32
+
33
+ if yarn_lock
34
+ yarn_source = Gurney::Source::Yarn.new(yarn_lock: yarn_lock)
35
+ npm_dependencies.concat(yarn_source.dependencies || [])
36
+ end
37
+
38
+ if package_lock_json
39
+ npm_source = Gurney::Source::Npm.new(package_lock_json: package_lock_json)
40
+ npm_dependencies.concat(npm_source.dependencies || [])
41
+ end
42
+
43
+ if pnpm_lock
44
+ pnpm_source = Gurney::Source::Pnpm.new(pnpm_lock: pnpm_lock)
45
+ npm_dependencies.concat(pnpm_source.dependencies || [])
46
+ end
47
+
48
+ npm_dependencies
49
+ end
50
+
51
+ def yarn_lock
52
+ @yarn_lock ||= @git_file_reader.read('yarn.lock')
53
+ end
54
+
55
+ def package_lock_json
56
+ @package_lock_json = @git_file_reader.read('package-lock.json')
57
+ end
58
+
59
+ def pnpm_lock
60
+ @pnpm_lock = @git_file_reader.read('pnpm-lock.yaml')
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,25 @@
1
+ module Gurney
2
+ class GitFileReader
3
+
4
+ def initialize(git, branch, read_from_git:, prefix: '.')
5
+ @git = git
6
+ @branch = branch
7
+ @read_from_git = read_from_git
8
+ @prefix = prefix
9
+ end
10
+
11
+ def read(filename)
12
+ prefixed_filename = File.join(@prefix, filename)
13
+ if @read_from_git
14
+ begin
15
+ @git.show("#{@branch}:#{prefixed_filename}")
16
+ rescue Git::GitExecuteError
17
+ # happens if branch does not exist
18
+ end
19
+ else
20
+ File.read(prefixed_filename) if File.exist?(prefixed_filename)
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,58 @@
1
+ require 'json'
2
+ require 'colorize'
3
+
4
+ module Gurney
5
+ module Source
6
+ class Npm < Base
7
+
8
+ SUPPORTED_LOCKFILE_VERSIONS = [2, 3].freeze
9
+
10
+ def initialize(package_lock_json:)
11
+ @package_lock_json = package_lock_json
12
+ end
13
+
14
+ def present?
15
+ !@package_lock_json&.empty?
16
+ end
17
+
18
+ def dependencies
19
+ if present?
20
+ parsed_lock = JSON.parse(@package_lock_json)
21
+
22
+ if SUPPORTED_LOCKFILE_VERSIONS.include?(parsed_lock['lockfileVersion'])
23
+ extract_dependencies(parsed_lock)
24
+ else
25
+ puts "package-lock.json: Lockfile version #{parsed_lock['lockfileVersion']} is unsupported. No npm dependencies reported.".yellow
26
+ []
27
+ end
28
+ end
29
+ rescue JSON::ParserError => e
30
+ raise Gurney::Error.new("Invalid package-lock.json format: #{e.message}")
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :package_lock_json
36
+
37
+ def extract_dependencies(parsed_lock)
38
+ dependencies = []
39
+
40
+ if parsed_lock['packages']
41
+ parsed_lock['packages'].each do |path_to_package, details|
42
+ next if path_to_package == ''
43
+
44
+ name = path_to_package.sub(/^node_modules\//, '') # remove "node_modules/" prefix to get package name
45
+ dependencies << Dependency.new(
46
+ ecosystem: 'npm',
47
+ name: name,
48
+ version: details['version']
49
+ )
50
+ end
51
+ end
52
+
53
+ dependencies
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,54 @@
1
+ require 'yaml'
2
+ require 'colorize'
3
+
4
+ module Gurney
5
+ module Source
6
+ class Pnpm < Base
7
+ def initialize(pnpm_lock:)
8
+ @pnpm_lock = pnpm_lock
9
+ end
10
+
11
+ def present?
12
+ !@pnpm_lock&.empty?
13
+ end
14
+
15
+ def dependencies
16
+ if present?
17
+ parsed_lock = YAML.safe_load(@pnpm_lock)
18
+
19
+ major_version = parsed_lock['lockfileVersion'].split('.').first
20
+ if major_version == '9'
21
+ extract_dependencies(parsed_lock)
22
+ else
23
+ puts "pnpm-lock.yaml: Lockfile version #{major_version} is unsupported. No npm dependencies reported.".yellow
24
+ []
25
+ end
26
+ end
27
+ rescue Psych::SyntaxError => e
28
+ raise Gurney::Error.new("Invalid pnpm-lock.yaml format: #{e.message}")
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :pnpm_lock
34
+
35
+ def extract_dependencies(parsed_lock)
36
+ dependencies = []
37
+
38
+ # dependency_id has format <scoped_pkg_name>@<pkg_version>
39
+ # see https://github.com/pnpm/spec/blob/master/lockfile/9.0.md#packages
40
+ parsed_lock['packages'].each_key do |dependency_id|
41
+ name, _, version = dependency_id.rpartition('@')
42
+ dependencies << Dependency.new(
43
+ ecosystem: 'npm',
44
+ name: name,
45
+ version: version
46
+ )
47
+ end
48
+
49
+ dependencies
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -1,3 +1,3 @@
1
1
  module Gurney
2
- VERSION = '0.4.0'
2
+ VERSION = '0.6.0'
3
3
  end
data/lib/gurney.rb CHANGED
@@ -1,8 +1,12 @@
1
1
  require_relative 'gurney/version'
2
2
  require_relative 'gurney/config'
3
+ require_relative 'gurney/git_file_reader'
3
4
  require_relative 'gurney/dependency'
5
+ require_relative 'gurney/dependency_collector'
4
6
  require_relative 'gurney/source/base'
5
7
  require_relative 'gurney/source/yarn'
8
+ require_relative 'gurney/source/npm'
9
+ require_relative 'gurney/source/pnpm'
6
10
  require_relative 'gurney/source/bundler'
7
11
  require_relative 'gurney/source/ruby_version'
8
12
  require_relative 'gurney/api'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gurney_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Schaflitzl
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-15 00:00:00.000000000 Z
11
+ date: 2025-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -93,8 +93,12 @@ files:
93
93
  - lib/gurney/cli/option_parser.rb
94
94
  - lib/gurney/config.rb
95
95
  - lib/gurney/dependency.rb
96
+ - lib/gurney/dependency_collector.rb
97
+ - lib/gurney/git_file_reader.rb
96
98
  - lib/gurney/source/base.rb
97
99
  - lib/gurney/source/bundler.rb
100
+ - lib/gurney/source/npm.rb
101
+ - lib/gurney/source/pnpm.rb
98
102
  - lib/gurney/source/ruby_version.rb
99
103
  - lib/gurney/source/yarn.rb
100
104
  - lib/gurney/version.rb
@@ -118,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
122
  - !ruby/object:Gem::Version
119
123
  version: '0'
120
124
  requirements: []
121
- rubygems_version: 3.0.3.1
125
+ rubygems_version: 3.3.27
122
126
  signing_key:
123
127
  specification_version: 4
124
128
  summary: Gurney is a small tool to extract yarn and RubyGems dependencies from project