ra10ke 4.5.1 → 4.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 +4 -4
- data/.github/labeler.yml +5 -0
- data/.github/workflows/labeler.yml +17 -0
- data/.github/workflows/release.yml +2 -2
- data/.github/workflows/test.yml +2 -2
- data/CHANGELOG.md +8 -0
- data/lib/ra10ke/dependencies.rb +1 -2
- data/lib/ra10ke/git_repo.rb +43 -80
- data/lib/ra10ke/version.rb +1 -1
- data/ra10ke.gemspec +1 -1
- data/spec/ra10ke/dependencies_git_conversion_spec.rb +53 -0
- data/spec/ra10ke/git_repo_spec.rb +198 -22
- metadata +7 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a77b7170e6dfb723d530dc22553a16ca198a0b361ca3a2aac5169b05fb0e4c89
|
|
4
|
+
data.tar.gz: b8025d8e38a8051a8a3cf4baa8b214e74b96c8ea5230364a37b23ac22f210a61
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0047a09a069462ef4d25e9778b83558aa29e9c282106e1f32eafd1fcc87df65d25e31fb9becccfa4d4ae47e4b61d930dafc15fcd56cd56b4669801675c3c415f
|
|
7
|
+
data.tar.gz: 4d809b1fa050a40ab3e1a265999eb47c1eb337609586b06c87b7fa3537303e42721a6d8ad8c84bd3264d2b0a183e3f2a91334054520730b39bde47193fc346de
|
data/.github/labeler.yml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 🏷️ Pull Request Labeler
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
- pull_request_target
|
|
6
|
+
|
|
7
|
+
permissions: {}
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
labeler:
|
|
11
|
+
name: Labeler
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
if: github.repository_owner == 'voxpupuli' || github.repository_owner == 'OpenVoxProject'
|
|
14
|
+
permissions:
|
|
15
|
+
pull-requests: write
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
|
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
name: Build the gem
|
|
16
16
|
runs-on: ubuntu-24.04
|
|
17
17
|
steps:
|
|
18
|
-
- uses: actions/checkout@
|
|
18
|
+
- uses: actions/checkout@v7
|
|
19
19
|
- name: Install Ruby
|
|
20
20
|
uses: ruby/setup-ruby@v1
|
|
21
21
|
with:
|
|
@@ -76,7 +76,7 @@ jobs:
|
|
|
76
76
|
uses: actions/download-artifact@v8
|
|
77
77
|
with:
|
|
78
78
|
name: gem-artifact
|
|
79
|
-
- uses: rubygems/configure-rubygems-credentials@v2.
|
|
79
|
+
- uses: rubygems/configure-rubygems-credentials@v2.1.0
|
|
80
80
|
- name: Publish gem to rubygems.org
|
|
81
81
|
shell: bash
|
|
82
82
|
run: gem push *.gem
|
data/.github/workflows/test.yml
CHANGED
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
outputs:
|
|
17
17
|
ruby: ${{ steps.ruby.outputs.versions }}
|
|
18
18
|
steps:
|
|
19
|
-
- uses: actions/checkout@
|
|
19
|
+
- uses: actions/checkout@v7
|
|
20
20
|
- name: Install Ruby ${{ matrix.ruby }}
|
|
21
21
|
uses: ruby/setup-ruby@v1
|
|
22
22
|
with:
|
|
@@ -35,7 +35,7 @@ jobs:
|
|
|
35
35
|
ruby: ${{ fromJSON(needs.rubocop_and_matrix.outputs.ruby) }}
|
|
36
36
|
name: Ruby ${{ matrix.ruby }}
|
|
37
37
|
steps:
|
|
38
|
-
- uses: actions/checkout@
|
|
38
|
+
- uses: actions/checkout@v7
|
|
39
39
|
- name: Install Ruby ${{ matrix.ruby }}
|
|
40
40
|
uses: ruby/setup-ruby@v1
|
|
41
41
|
with:
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [v4.6.0](https://github.com/voxpupuli/ra10ke/tree/v4.6.0) (2026-10-13)
|
|
6
|
+
|
|
7
|
+
[Full Changelog](https://github.com/voxpupuli/ra10ke/compare/v4.5.1...v4.6.0)
|
|
8
|
+
|
|
9
|
+
**Implemented enhancements:**
|
|
10
|
+
|
|
11
|
+
- feat: use git-gem in git\_repo class; drop support for git-gem version v1.x [\#152](https://github.com/voxpupuli/ra10ke/pull/152) ([rwaffen](https://github.com/rwaffen))
|
|
12
|
+
|
|
5
13
|
## [v4.5.1](https://github.com/voxpupuli/ra10ke/tree/v4.5.1) (2026-05-11)
|
|
6
14
|
|
|
7
15
|
[Full Changelog](https://github.com/voxpupuli/ra10ke/compare/v4.5.0...v4.5.1)
|
data/lib/ra10ke/dependencies.rb
CHANGED
|
@@ -165,8 +165,7 @@ module Ra10ke::Dependencies
|
|
|
165
165
|
"https://#{::Regexp.last_match(1)}/#{::Regexp.last_match(2)}"
|
|
166
166
|
end
|
|
167
167
|
repo = ::Ra10ke::GitRepo.new(source_url)
|
|
168
|
-
|
|
169
|
-
ref_name = ref ? ref[:name] : "bad url or tag #{mod.expected_version} is missing"
|
|
168
|
+
ref_name = repo.get_ref_like(mod.expected_version) || "bad url or tag #{mod.expected_version} is missing"
|
|
170
169
|
<<~EOF
|
|
171
170
|
mod '#{mod.name}',
|
|
172
171
|
:git => '#{source_url}',
|
data/lib/ra10ke/git_repo.rb
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require '
|
|
3
|
+
require 'git'
|
|
4
|
+
require 'tmpdir'
|
|
4
5
|
|
|
5
6
|
module Ra10ke
|
|
6
7
|
class GitRepo
|
|
7
8
|
attr_reader :url
|
|
8
9
|
|
|
9
|
-
REMOTE_REFS_CMD = 'git ls-remote --symref'
|
|
10
|
-
CLONE_CMD = 'git clone --no-tags'
|
|
11
|
-
CURRENT_BRANCH_CMD = 'git symbolic-ref --short HEAD'
|
|
12
|
-
SHOW_CMD = 'git show'
|
|
13
|
-
|
|
14
10
|
def initialize(url)
|
|
15
11
|
@url = url
|
|
16
12
|
end
|
|
@@ -19,18 +15,19 @@ module Ra10ke
|
|
|
19
15
|
# @param path [String] - The path to the repository to check
|
|
20
16
|
# @return [String] - The current active branch of the Git repo
|
|
21
17
|
def self.current_branch(path)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
branch = Git.open(path).current_branch
|
|
19
|
+
branch unless branch == 'HEAD' || branch.to_s.empty?
|
|
20
|
+
rescue Git::Error, ArgumentError
|
|
21
|
+
nil
|
|
26
22
|
end
|
|
27
23
|
|
|
28
|
-
# @return [
|
|
29
|
-
# return empty
|
|
24
|
+
# @return [Hash] - remote refs grouped by the git gem
|
|
25
|
+
# return empty hash if the command failed
|
|
30
26
|
def remote_refs
|
|
31
27
|
@remote_refs ||= begin
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
Git.ls_remote(url)
|
|
29
|
+
rescue Git::Error
|
|
30
|
+
{}
|
|
34
31
|
end
|
|
35
32
|
end
|
|
36
33
|
|
|
@@ -39,89 +36,55 @@ module Ra10ke
|
|
|
39
36
|
!remote_refs.empty?
|
|
40
37
|
end
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return false if sha.nil? || sha.empty?
|
|
47
|
-
return true if valid_ref?(sha)
|
|
39
|
+
def valid_commit?(ref)
|
|
40
|
+
return false if ref.nil? || ref.empty?
|
|
41
|
+
return true if valid_ref?(ref)
|
|
42
|
+
return false unless valid_url?
|
|
48
43
|
|
|
49
|
-
# cloning is a last resort if for some reason we cannot
|
|
50
|
-
# remotely get via ls-remote
|
|
51
44
|
Dir.mktmpdir do |dir|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
status
|
|
56
|
-
end
|
|
45
|
+
repo = Git.clone(url, dir, bare: true)
|
|
46
|
+
repo.rev_parse("#{ref}^{commit}")
|
|
47
|
+
true
|
|
57
48
|
end
|
|
49
|
+
rescue Git::Error
|
|
50
|
+
false
|
|
58
51
|
end
|
|
59
52
|
|
|
60
|
-
# @
|
|
61
|
-
# @
|
|
62
|
-
# @param ref [String] - the ref object, branch name, tag name, or commit sha, defaults to HEAD
|
|
53
|
+
# @param ref [String] branch name, tag name, HEAD, or a full/abbreviated SHA
|
|
54
|
+
# @return [Boolean]
|
|
63
55
|
def valid_ref?(ref = 'HEAD')
|
|
64
|
-
return false if ref.nil?
|
|
56
|
+
return false if ref.nil? || ref.empty?
|
|
65
57
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
# is the name equal to the tag or branch? Is the commit sha equal?
|
|
71
|
-
data[:name].eql?(ref) || data[:sha].slice(0, 8).eql?(ref.slice(0, 8))
|
|
72
|
-
end
|
|
73
|
-
!found.nil?
|
|
74
|
-
end
|
|
58
|
+
head = remote_refs.fetch('head', {})
|
|
59
|
+
return true if ref == 'HEAD' && !head.empty?
|
|
60
|
+
return true if sha_match?(head[:sha], ref)
|
|
75
61
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
# [{:sha=>"0ec707e431367bbe2752966be8ab915b6f0da754", :ref=>"refs/heads/74110ac", :type=>:branch, :subtype=>nil, :name=>"74110ac"},
|
|
80
|
-
# :sha=>"07bb5d2d94db222dca5860eb29c184e8970f36f4", :ref=>"refs/pull/74/head", :type=>:pull, :subtype=>:head, :name=>"74"},
|
|
81
|
-
# :sha=>"156ca9a8ea69e056e86355b27d944e59d1b3a1e1", :ref=>"refs/heads/master", :type=>:branch, :subtype=>nil, :name=>"master"},
|
|
82
|
-
# :sha=>"fcc0532bbc5a5b65f3941738339e9cc7e3d767ce", :ref=>"refs/pull/249/head", :type=>:pull, :subtype=>:head, :name=>"249"},
|
|
83
|
-
# :sha=>"8d54891fa5df75890ee15d53080c2a81b4960f92", :ref=>"refs/pull/267/head", :type=>:pull, :subtype=>:head, :name=>"267"}]
|
|
84
|
-
def all_refs
|
|
85
|
-
@all_refs ||= remote_refs.each_with_object([]) do |line, refs|
|
|
86
|
-
sha, ref = line.split("\t")
|
|
87
|
-
next refs if line.include?('redirecting')
|
|
88
|
-
next refs if sha.eql?('ref: refs/heads/master')
|
|
89
|
-
|
|
90
|
-
_, type, name, subtype = ref.chomp.split('/')
|
|
91
|
-
next refs unless name
|
|
92
|
-
|
|
93
|
-
type = :tag if type.eql?('tags')
|
|
94
|
-
type = type.to_sym
|
|
95
|
-
subtype = subtype.to_sym if subtype
|
|
96
|
-
type = :branch if type.eql?(:heads)
|
|
97
|
-
refs << { sha: sha, ref: ref.chomp, type: type, subtype: subtype, name: name }
|
|
62
|
+
%w[branches tags].any? do |type|
|
|
63
|
+
refs = remote_refs.fetch(type, {})
|
|
64
|
+
refs.key?(ref) || refs.values.any? { |data| sha_match?(data[:sha], ref) }
|
|
98
65
|
end
|
|
99
66
|
end
|
|
100
67
|
|
|
101
|
-
# @
|
|
102
|
-
#
|
|
103
|
-
# @param ref_name [String]
|
|
104
|
-
# @return [String] the matching ref_name or nil
|
|
68
|
+
# @param ref_name [String] substring to find in a tag name
|
|
69
|
+
# @return [String, nil] matching tag name
|
|
105
70
|
def get_ref_like(ref_name)
|
|
106
|
-
return nil
|
|
71
|
+
return nil if ref_name.nil? || ref_name.empty?
|
|
107
72
|
|
|
108
|
-
|
|
109
|
-
|
|
73
|
+
remote_refs.fetch('tags', {}).each_key.find do |name|
|
|
74
|
+
!name.end_with?('^{}') && name.include?(ref_name)
|
|
110
75
|
end
|
|
111
76
|
end
|
|
112
77
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
end
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def sha_match?(sha, ref)
|
|
81
|
+
return false unless sha
|
|
82
|
+
|
|
83
|
+
# \A and \z anchor the entire string; [0-9a-f] allows only hexadecimal digits.
|
|
84
|
+
# {8,64} accepts abbreviations of at least 8 digits up to a full SHA-256; i allows uppercase.
|
|
85
|
+
return false unless ref.match?(/\A[0-9a-f]{8,64}\z/i)
|
|
122
86
|
|
|
123
|
-
|
|
124
|
-
self.class.run_command(cmd, silent: silent)
|
|
87
|
+
sha.start_with?(ref.downcase)
|
|
125
88
|
end
|
|
126
89
|
end
|
|
127
90
|
end
|
data/lib/ra10ke/version.rb
CHANGED
data/ra10ke.gemspec
CHANGED
|
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
|
|
|
16
16
|
spec.require_paths = ['lib']
|
|
17
17
|
spec.required_ruby_version = '>= 3.1.0'
|
|
18
18
|
|
|
19
|
-
spec.add_dependency 'git', '>=
|
|
19
|
+
spec.add_dependency 'git', '>= 2.0', '< 5.0'
|
|
20
20
|
spec.add_dependency 'puppet_forge', '~> 6.0'
|
|
21
21
|
spec.add_dependency 'r10k', '~> 5.0'
|
|
22
22
|
spec.add_dependency 'rake', '~> 13.0', '>= 13.0.6'
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'ra10ke'
|
|
5
|
+
|
|
6
|
+
RSpec.describe Ra10ke::Dependencies do
|
|
7
|
+
let(:url) { 'https://example.invalid/module.git' }
|
|
8
|
+
let(:metadata) do
|
|
9
|
+
PuppetForge::V3::Module.new(homepage_url: url, current_release: { metadata: { source: url } })
|
|
10
|
+
end
|
|
11
|
+
let(:forge_module) do
|
|
12
|
+
R10K::Module::Forge.new('example-module', fixtures_dir, version: '1.0.0')
|
|
13
|
+
end
|
|
14
|
+
let(:puppetfile) { instance_double(R10K::Puppetfile, load!: nil, forge: nil, modules: [forge_module]) }
|
|
15
|
+
let(:task_owner) { Ra10ke::RakeTask.new }
|
|
16
|
+
|
|
17
|
+
around do |example|
|
|
18
|
+
original_application = Rake.application
|
|
19
|
+
Rake.application = Rake::Application.new
|
|
20
|
+
example.run
|
|
21
|
+
ensure
|
|
22
|
+
Rake.application = original_application
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
before do
|
|
26
|
+
allow(forge_module).to receive_messages(v3_module: metadata, name: 'example-module')
|
|
27
|
+
allow(task_owner).to receive(:get_puppetfile).and_return(puppetfile)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'prints the matching tag name returned by GitRepo' do
|
|
31
|
+
allow(Git).to receive(:ls_remote).with(url).and_return(
|
|
32
|
+
'tags' => { 'v1.0.0' => { ref: 'refs', sha: 'abc12345' } },
|
|
33
|
+
)
|
|
34
|
+
expected = <<~PUPPETFILE
|
|
35
|
+
mod 'example-module',
|
|
36
|
+
:git => '#{url}',
|
|
37
|
+
:ref => 'v1.0.0'
|
|
38
|
+
|
|
39
|
+
PUPPETFILE
|
|
40
|
+
expect { Rake::Task['r10k:print_git_conversion'].execute }.to output(expected).to_stdout
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'prints the existing error message when no tag matches' do
|
|
44
|
+
allow(Git).to receive(:ls_remote).with(url).and_return({})
|
|
45
|
+
expected = <<~PUPPETFILE
|
|
46
|
+
mod 'example-module',
|
|
47
|
+
:git => '#{url}',
|
|
48
|
+
:ref => 'bad url or tag 1.0.0 is missing'
|
|
49
|
+
|
|
50
|
+
PUPPETFILE
|
|
51
|
+
expect { Rake::Task['r10k:print_git_conversion'].execute }.to output(expected).to_stdout
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
|
-
require 'ra10ke/
|
|
4
|
+
require 'ra10ke/git_repo'
|
|
5
5
|
|
|
6
6
|
RSpec.describe 'Ra10ke::GitRepo' do
|
|
7
7
|
let(:url) { 'https://github.com/vshn/puppet-gitlab' }
|
|
@@ -10,11 +10,12 @@ RSpec.describe 'Ra10ke::GitRepo' do
|
|
|
10
10
|
expect(Ra10ke::GitRepo.new(url)).to be_a Ra10ke::GitRepo
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
it '
|
|
13
|
+
it 'only fetches remote refs once' do
|
|
14
14
|
i = Ra10ke::GitRepo.new(url)
|
|
15
|
-
expect(
|
|
15
|
+
expect(Git).to receive(:ls_remote).with(url).once.and_return({})
|
|
16
16
|
i.valid_url?
|
|
17
|
-
i.
|
|
17
|
+
i.valid_ref?
|
|
18
|
+
i.get_ref_like('1.0.0')
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
describe 'good url' do
|
|
@@ -24,28 +25,56 @@ RSpec.describe 'Ra10ke::GitRepo' do
|
|
|
24
25
|
Ra10ke::GitRepo.new(url)
|
|
25
26
|
end
|
|
26
27
|
|
|
27
|
-
let(:reflist)
|
|
28
|
+
let(:reflist) do
|
|
29
|
+
File.readlines(File.join(fixtures_dir, 'refs', 'gitlab.txt')).each_with_object({}) do |line, refs|
|
|
30
|
+
sha, ref = line.strip.split("\t")
|
|
31
|
+
if ref == 'HEAD'
|
|
32
|
+
refs['head'] = { ref: ref, sha: sha }
|
|
33
|
+
else
|
|
34
|
+
prefix, type, name = ref.split('/', 3)
|
|
35
|
+
type = 'branches' if type == 'heads'
|
|
36
|
+
refs[type] ||= {}
|
|
37
|
+
refs[type][name] = { ref: prefix, sha: sha }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
28
41
|
|
|
29
42
|
before do
|
|
30
|
-
allow(
|
|
43
|
+
allow(Git).to receive(:ls_remote).with(url).and_return(reflist)
|
|
31
44
|
end
|
|
32
45
|
|
|
33
|
-
it '#remote_refs
|
|
34
|
-
expect(instance.remote_refs).to
|
|
46
|
+
it '#remote_refs returns the gem hash unchanged' do
|
|
47
|
+
expect(instance.remote_refs).to equal(reflist)
|
|
35
48
|
end
|
|
36
49
|
|
|
37
50
|
it '#remote_refs contains refs' do
|
|
38
|
-
expect(instance.remote_refs
|
|
51
|
+
expect(instance.remote_refs['head']).to eq(ref: 'HEAD', sha: '1b3322d525e96bf7d0565b08703e2a44c90e7b4a')
|
|
39
52
|
end
|
|
40
53
|
|
|
41
54
|
it '#get_ref_like' do
|
|
42
|
-
expect(instance.get_ref_like('
|
|
55
|
+
expect(instance.get_ref_like('5.0.0')).to eq('v5.0.0')
|
|
43
56
|
end
|
|
44
57
|
|
|
45
58
|
it '#valid_ref?' do
|
|
46
59
|
expect(instance.valid_ref?('master')).to be true
|
|
47
60
|
end
|
|
48
61
|
|
|
62
|
+
it 'accepts HEAD explicitly and as the default ref' do
|
|
63
|
+
expect(instance.valid_ref?('HEAD')).to be true
|
|
64
|
+
expect(instance.valid_ref?).to be true
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'excludes pull and merge request refs from validation' do
|
|
68
|
+
allow(Git).to receive(:ls_remote).with(url).and_return(
|
|
69
|
+
'pull' => { '74/head' => { ref: 'refs', sha: 'abc12345' } },
|
|
70
|
+
'merge_request' => { '12/merge' => { ref: 'refs', sha: 'def12345' } },
|
|
71
|
+
)
|
|
72
|
+
expect(instance.valid_ref?('74')).to be false
|
|
73
|
+
expect(instance.valid_ref?('abc12345')).to be false
|
|
74
|
+
expect(instance.valid_ref?('12')).to be false
|
|
75
|
+
expect(instance.valid_ref?('def12345')).to be false
|
|
76
|
+
end
|
|
77
|
+
|
|
49
78
|
it '#valid_commit?' do
|
|
50
79
|
expect(instance.valid_commit?('master')).to be true
|
|
51
80
|
end
|
|
@@ -55,8 +84,9 @@ RSpec.describe 'Ra10ke::GitRepo' do
|
|
|
55
84
|
end
|
|
56
85
|
|
|
57
86
|
it '#valid_commit? but invalid sha' do
|
|
58
|
-
|
|
59
|
-
allow(
|
|
87
|
+
repo = instance_double(Git::Base)
|
|
88
|
+
allow(Git).to receive(:clone).with(url, kind_of(String), bare: true).and_return(repo)
|
|
89
|
+
allow(repo).to receive(:rev_parse).with('invalid^{commit}').and_raise(Git::Error)
|
|
60
90
|
expect(instance.valid_commit?('invalid')).to be false
|
|
61
91
|
end
|
|
62
92
|
|
|
@@ -64,13 +94,28 @@ RSpec.describe 'Ra10ke::GitRepo' do
|
|
|
64
94
|
expect(instance.valid_url?).to be true
|
|
65
95
|
end
|
|
66
96
|
|
|
67
|
-
it '
|
|
68
|
-
|
|
69
|
-
expect(
|
|
70
|
-
expect(
|
|
71
|
-
|
|
72
|
-
|
|
97
|
+
it 'accepts full and abbreviated SHAs but checks all supplied characters' do
|
|
98
|
+
sha = reflist['head'][:sha]
|
|
99
|
+
expect(instance.valid_ref?(sha)).to be true
|
|
100
|
+
expect(instance.valid_ref?(sha[0, 8])).to be true
|
|
101
|
+
expect(instance.valid_ref?(sha[0, 12])).to be true
|
|
102
|
+
expect(instance.valid_ref?("#{sha[0, 8]}#{'0' * 32}")).to be false
|
|
103
|
+
expect(instance.valid_ref?("#{sha}0")).to be false
|
|
104
|
+
expect(instance.valid_ref?(sha[0, 7])).to be false
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'validates the peeled commit SHA of an annotated tag' do
|
|
108
|
+
expect(instance.valid_ref?('1febd15f90d32e6b3d6c242a70db386b2ef1942c')).to be true
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'searches only tag names and skips peeled tag entries' do
|
|
112
|
+
allow(Git).to receive(:ls_remote).with(url).and_return(
|
|
113
|
+
'branches' => { 'feature/5.0.0' => { ref: 'refs', sha: 'abc12345' } },
|
|
114
|
+
'tags' => { 'v5.0.0^{}' => { ref: 'refs', sha: 'abc12345' }, 'v5.0.0' => { ref: 'refs', sha: 'def12345' } },
|
|
73
115
|
)
|
|
116
|
+
expect(instance.get_ref_like('5.0.0')).to eq('v5.0.0')
|
|
117
|
+
expect(instance.get_ref_like('feature')).to be_nil
|
|
118
|
+
expect(instance.get_ref_like('^{}')).to be_nil
|
|
74
119
|
end
|
|
75
120
|
end
|
|
76
121
|
|
|
@@ -81,12 +126,143 @@ RSpec.describe 'Ra10ke::GitRepo' do
|
|
|
81
126
|
end
|
|
82
127
|
|
|
83
128
|
before do
|
|
84
|
-
allow(
|
|
129
|
+
allow(Git).to receive(:ls_remote).with(url).and_raise(Git::Error)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'returns empty remote refs and rejects HEAD' do
|
|
133
|
+
expect(instance.remote_refs).to eq({})
|
|
134
|
+
expect(instance.valid_ref?).to be false
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
describe 'failed remote lookup' do
|
|
139
|
+
it 'caches the failure and reports an invalid URL' do
|
|
140
|
+
repo = Ra10ke::GitRepo.new(url)
|
|
141
|
+
expect(Git).to receive(:ls_remote).with(url).once.and_raise(Git::Error)
|
|
142
|
+
expect(repo.valid_url?).to be false
|
|
143
|
+
expect(repo.remote_refs).to eq({})
|
|
144
|
+
expect(repo.get_ref_like('missing')).to be_nil
|
|
145
|
+
expect(Git).not_to receive(:clone)
|
|
146
|
+
expect(repo.valid_commit?('missing')).to be false
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
describe '#valid_commit?' do
|
|
151
|
+
let(:instance) { Ra10ke::GitRepo.new(url) }
|
|
152
|
+
|
|
153
|
+
before do
|
|
154
|
+
allow(Git).to receive(:ls_remote).with(url).and_return('head' => { ref: 'HEAD', sha: 'a' * 40 })
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'does not clone for an empty SHA' do
|
|
158
|
+
expect(Git).not_to receive(:clone)
|
|
159
|
+
expect(instance.valid_commit?('')).to be false
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it 'stops after a failed clone and removes the temporary directory' do
|
|
163
|
+
clone_dir = nil
|
|
164
|
+
expect(Git).to receive(:clone).with(url, kind_of(String), bare: true) do |_, dir|
|
|
165
|
+
clone_dir = dir
|
|
166
|
+
raise Git::Error
|
|
167
|
+
end
|
|
168
|
+
expect(instance.valid_commit?('missing')).to be false
|
|
169
|
+
expect(File.exist?(clone_dir)).to be false
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
describe '.current_branch' do
|
|
174
|
+
it 'handles nil returned by older git gem versions for detached HEAD' do
|
|
175
|
+
repo = instance_double(Git::Base, current_branch: nil)
|
|
176
|
+
allow(Git).to receive(:open).with('repo').and_return(repo)
|
|
177
|
+
expect(Ra10ke::GitRepo.current_branch('repo')).to be_nil
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it 'returns nil for a directory without a repository' do
|
|
181
|
+
Dir.mktmpdir do |dir|
|
|
182
|
+
expect(Ra10ke::GitRepo.current_branch(dir)).to be_nil
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it 'returns nil for a missing directory' do
|
|
187
|
+
Dir.mktmpdir do |dir|
|
|
188
|
+
expect(Ra10ke::GitRepo.current_branch(File.join(dir, 'missing'))).to be_nil
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
describe 'with a local repository' do
|
|
194
|
+
let(:tmpdir) { Dir.mktmpdir('ra10ke git repo ') }
|
|
195
|
+
let(:path) { File.join(tmpdir, 'source repo') }
|
|
196
|
+
let(:local_repo) { Git.init(path) }
|
|
197
|
+
let(:older_sha) { local_repo.revparse('HEAD~1') }
|
|
198
|
+
|
|
199
|
+
around do |example|
|
|
200
|
+
example.run
|
|
201
|
+
ensure
|
|
202
|
+
FileUtils.remove_entry(tmpdir)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
before do
|
|
206
|
+
local_repo.config('user.name', 'Ra10ke Test')
|
|
207
|
+
local_repo.config('user.email', 'ra10ke@example.invalid')
|
|
208
|
+
local_repo.config('commit.gpgsign', 'false')
|
|
209
|
+
local_repo.config('tag.gpgsign', 'false')
|
|
210
|
+
File.write(File.join(path, 'file'), 'first')
|
|
211
|
+
local_repo.add('file')
|
|
212
|
+
local_repo.commit('first')
|
|
213
|
+
File.write(File.join(path, 'file'), 'second')
|
|
214
|
+
local_repo.add('file')
|
|
215
|
+
local_repo.commit('second')
|
|
216
|
+
local_repo.add_tag('v1.0.0')
|
|
217
|
+
local_repo.add_tag('v2.0.0', annotate: true, message: 'annotated tag')
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it 'returns the branch without changing the working directory' do
|
|
221
|
+
cwd = Dir.pwd
|
|
222
|
+
expect(Ra10ke::GitRepo.current_branch(path)).to eq(local_repo.current_branch)
|
|
223
|
+
expect(Dir.pwd).to eq(cwd)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it 'returns nil for detached HEAD' do
|
|
227
|
+
local_repo.checkout(older_sha)
|
|
228
|
+
expect(Ra10ke::GitRepo.current_branch(path)).to be_nil
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it 'finds branches, lightweight tags and annotated tags' do
|
|
232
|
+
repo = Ra10ke::GitRepo.new(path)
|
|
233
|
+
expect(repo.valid_url?).to be true
|
|
234
|
+
expect(repo.valid_ref?(local_repo.current_branch)).to be true
|
|
235
|
+
expect(repo.valid_ref?('v1.0.0')).to be true
|
|
236
|
+
expect(repo.valid_ref?('v2.0.0')).to be true
|
|
237
|
+
expect(repo.get_ref_like('2.0.0')).to eq('v2.0.0')
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it 'preserves branch and tag names containing slashes' do
|
|
241
|
+
local_repo.branch('feature/example').create
|
|
242
|
+
local_repo.add_tag('release/v1.0.0')
|
|
243
|
+
repo = Ra10ke::GitRepo.new(path)
|
|
244
|
+
expect(repo.valid_ref?('feature/example')).to be true
|
|
245
|
+
expect(repo.valid_ref?('release/v1.0.0')).to be true
|
|
246
|
+
expect(repo.get_ref_like('release/')).to eq('release/v1.0.0')
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
it 'recognizes remote HEAD from the gem lookup' do
|
|
250
|
+
repo = Ra10ke::GitRepo.new(path)
|
|
251
|
+
expect(repo.valid_ref?).to be true
|
|
252
|
+
expect(repo.valid_ref?(local_repo.revparse('HEAD'))).to be true
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it 'rejects a blob object during the commit fallback check' do
|
|
256
|
+
repo = Ra10ke::GitRepo.new(path)
|
|
257
|
+
blob_sha = local_repo.rev_parse('HEAD:file')
|
|
258
|
+
expect(repo.valid_commit?(blob_sha)).to be false
|
|
85
259
|
end
|
|
86
260
|
|
|
87
|
-
it '
|
|
88
|
-
|
|
89
|
-
expect(
|
|
261
|
+
it 'clones to validate a commit that is not advertised by a ref' do
|
|
262
|
+
repo = Ra10ke::GitRepo.new(path)
|
|
263
|
+
expect(repo.valid_ref?(older_sha)).to be false
|
|
264
|
+
expect(repo.valid_commit?(older_sha)).to be true
|
|
265
|
+
expect(repo.valid_commit?('invalid')).to be false
|
|
90
266
|
end
|
|
91
267
|
end
|
|
92
268
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ra10ke
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Theo Chatzimichos
|
|
@@ -16,7 +16,7 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '2.0'
|
|
20
20
|
- - "<"
|
|
21
21
|
- !ruby/object:Gem::Version
|
|
22
22
|
version: '5.0'
|
|
@@ -26,7 +26,7 @@ dependencies:
|
|
|
26
26
|
requirements:
|
|
27
27
|
- - ">="
|
|
28
28
|
- !ruby/object:Gem::Version
|
|
29
|
-
version: '
|
|
29
|
+
version: '2.0'
|
|
30
30
|
- - "<"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
32
|
version: '5.0'
|
|
@@ -168,7 +168,9 @@ extensions: []
|
|
|
168
168
|
extra_rdoc_files: []
|
|
169
169
|
files:
|
|
170
170
|
- ".github/dependabot.yml"
|
|
171
|
+
- ".github/labeler.yml"
|
|
171
172
|
- ".github/release.yml"
|
|
173
|
+
- ".github/workflows/labeler.yml"
|
|
172
174
|
- ".github/workflows/release.yml"
|
|
173
175
|
- ".github/workflows/test.yml"
|
|
174
176
|
- ".gitignore"
|
|
@@ -207,6 +209,7 @@ files:
|
|
|
207
209
|
- spec/fixtures/refs/gitlab.txt
|
|
208
210
|
- spec/fixtures/refs/r10k.txt
|
|
209
211
|
- spec/fixtures/refs/reflist.txt
|
|
212
|
+
- spec/ra10ke/dependencies_git_conversion_spec.rb
|
|
210
213
|
- spec/ra10ke/dependencies_spec.rb
|
|
211
214
|
- spec/ra10ke/deprecation_spec.rb
|
|
212
215
|
- spec/ra10ke/diff_spec.rb
|
|
@@ -235,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
235
238
|
- !ruby/object:Gem::Version
|
|
236
239
|
version: '0'
|
|
237
240
|
requirements: []
|
|
238
|
-
rubygems_version: 4.0.
|
|
241
|
+
rubygems_version: 4.0.20
|
|
239
242
|
specification_version: 4
|
|
240
243
|
summary: Syntax check for the Puppetfile, check for outdated installed puppet modules
|
|
241
244
|
test_files: []
|