ra10ke 0.6.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +11 -0
- data/.github/workflows/release.yml +32 -0
- data/.github/workflows/test.yml +35 -0
- data/.gitignore +3 -0
- data/.ruby-version +1 -1
- data/.travis.yml +1 -0
- data/CHANGELOG.md +56 -2
- data/Gemfile +9 -0
- data/HISTORY.md +118 -0
- data/README.md +48 -2
- data/Rakefile +13 -0
- data/lib/ra10ke/dependencies.rb +34 -12
- data/lib/ra10ke/deprecation.rb +72 -0
- data/lib/ra10ke/duplicates.rb +79 -0
- data/lib/ra10ke/git_repo.rb +116 -0
- data/lib/ra10ke/puppetfile_parser.rb +7 -0
- data/lib/ra10ke/validate.rb +19 -60
- data/lib/ra10ke/version.rb +1 -1
- data/lib/ra10ke.rb +8 -0
- data/ra10ke.gemspec +5 -2
- data/spec/fixtures/Puppetfile +3 -1
- data/spec/fixtures/Puppetfile_with_bad_refs +3 -0
- data/spec/fixtures/Puppetfile_with_commit +3 -0
- data/spec/fixtures/Puppetfile_with_control_branch +23 -0
- data/spec/fixtures/Puppetfile_with_duplicates +50 -0
- data/spec/fixtures/refs/debug.txt +0 -0
- data/spec/fixtures/refs/gitlab.txt +285 -0
- data/spec/fixtures/refs/r10k.txt +120 -0
- data/spec/fixtures/{reflist.txt → refs/reflist.txt} +0 -0
- data/spec/ra10ke/dependencies_spec.rb +72 -0
- data/spec/ra10ke/deprecation_spec.rb +37 -0
- data/spec/ra10ke/duplicates_spec.rb +31 -0
- data/spec/ra10ke/git_repo_spec.rb +88 -0
- data/spec/ra10ke/puppetfile_parser_spec.rb +5 -3
- data/spec/ra10ke/validate_spec.rb +96 -33
- data/spec/ra10ke_spec.rb +6 -4
- data/spec/spec_helper.rb +28 -0
- metadata +52 -8
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
module Ra10ke
|
6
|
+
class GitRepo
|
7
|
+
attr_reader :url
|
8
|
+
|
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
|
+
def initialize(url)
|
15
|
+
@url = url
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get the current branch for a Git repo
|
19
|
+
# @param path [String] - The path to the repository to check
|
20
|
+
# @return [String] - The current active branch of the Git repo
|
21
|
+
def self.current_branch(path)
|
22
|
+
Dir.chdir(path) do
|
23
|
+
data, success = run_command(CURRENT_BRANCH_CMD)
|
24
|
+
return success ? data.strip : nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [Array] - the raw data from the git ls-remote command as lines array
|
29
|
+
# return empty array if url or command failed
|
30
|
+
def remote_refs
|
31
|
+
@remote_refs ||= begin
|
32
|
+
data, success = run_command("#{REMOTE_REFS_CMD} #{url}")
|
33
|
+
success ? data.lines : []
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Boolean] true if the git url is valid
|
38
|
+
def valid_url?
|
39
|
+
!remote_refs.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Boolean] - return true if the commit sha is valid
|
43
|
+
# @param url [String] - the git string either https or ssh url
|
44
|
+
# @param ref [String] - the sha id
|
45
|
+
def valid_commit?(sha)
|
46
|
+
return false if sha.nil? || sha.empty?
|
47
|
+
return true if valid_ref?(sha)
|
48
|
+
|
49
|
+
# cloning is a last resort if for some reason we cannot
|
50
|
+
# remotely get via ls-remote
|
51
|
+
Dir.mktmpdir do |dir|
|
52
|
+
run_command("#{CLONE_CMD} #{url} #{dir}", silent: true)
|
53
|
+
Dir.chdir(dir) do
|
54
|
+
_, status = run_command("#{SHOW_CMD} #{sha}", silent: true)
|
55
|
+
status
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Boolean] - return true if the ref is valid
|
61
|
+
# @param url [String] - the git string either https or ssh url
|
62
|
+
# @param ref [String] - the ref object, branch name, tag name, or commit sha, defaults to HEAD
|
63
|
+
def valid_ref?(ref = 'HEAD')
|
64
|
+
return false if ref.nil?
|
65
|
+
|
66
|
+
found = all_refs.find do |data|
|
67
|
+
# we don't need to bother with these types
|
68
|
+
next if data[:type] == :pull || data[:type] == :merge_request
|
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
|
75
|
+
|
76
|
+
# @return [Array] - an array of all the refs associated with the remote repository
|
77
|
+
# @param url [String] - the git string either https or ssh url
|
78
|
+
# @example
|
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 ||= begin
|
86
|
+
remote_refs.each_with_object([]) do |line, refs|
|
87
|
+
sha, ref = line.split("\t")
|
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 }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# useful for mocking easily
|
103
|
+
# @param cmd [String]
|
104
|
+
# @param silent [Boolean] set to true if you wish to send output to /dev/null, false by default
|
105
|
+
# @return [Array]
|
106
|
+
def self.run_command(cmd, silent: false)
|
107
|
+
out_args = silent ? '2>&1 > /dev/null' : '2>&1'
|
108
|
+
out = `#{cmd} #{out_args}`
|
109
|
+
[out, $CHILD_STATUS.success?]
|
110
|
+
end
|
111
|
+
|
112
|
+
def run_command(cmd, silent: false)
|
113
|
+
self.class.run_command(cmd, silent: silent)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -12,6 +12,13 @@ module Ra10ke
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
# @return [Array] - returns a array of hashes that contain modules from the Forge
|
16
|
+
def forge_modules(file = puppetfile)
|
17
|
+
modules(file).reject do |mod|
|
18
|
+
mod[:args].key?(:git)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
15
22
|
# @param puppetfile [String] - the absolute path to the puppetfile
|
16
23
|
# @return [Array] - returns an array of module hashes that represent the puppetfile
|
17
24
|
# @example
|
data/lib/ra10ke/validate.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'ra10ke/monkey_patches'
|
4
|
-
require 'tempfile'
|
5
4
|
require 'table_print'
|
6
5
|
require 'ra10ke/puppetfile_parser'
|
7
6
|
require 'English'
|
7
|
+
require 'ra10ke/git_repo'
|
8
8
|
|
9
9
|
module Ra10ke
|
10
10
|
module Validate
|
@@ -13,7 +13,7 @@ module Ra10ke
|
|
13
13
|
BAD_EMOJI = ENV['BAD_EMOJI'] || '😨'
|
14
14
|
|
15
15
|
# Validate the git urls and refs
|
16
|
-
def define_task_validate(*
|
16
|
+
def define_task_validate(*)
|
17
17
|
desc 'Validate the git urls and branches, refs, or tags'
|
18
18
|
task :validate do
|
19
19
|
gitvalididation = Ra10ke::Validate::Validation.new(get_puppetfile.puppetfile_path)
|
@@ -32,7 +32,7 @@ module Ra10ke
|
|
32
32
|
|
33
33
|
class Validation
|
34
34
|
include Ra10ke::PuppetfileParser
|
35
|
-
|
35
|
+
|
36
36
|
attr_reader :puppetfile
|
37
37
|
|
38
38
|
def initialize(file)
|
@@ -41,69 +41,28 @@ module Ra10ke
|
|
41
41
|
abort("Puppetfile does not exist at #{puppetfile}") unless File.readable?(puppetfile)
|
42
42
|
end
|
43
43
|
|
44
|
-
# @return [Boolean] - return true if the ref is valid
|
45
|
-
# @param url [String] - the git string either https or ssh url
|
46
|
-
# @param ref [String] - the ref object, branch name, tag name, or commit sha, defaults to HEAD
|
47
|
-
def valid_ref?(url, ref = 'HEAD')
|
48
|
-
raise ArgumentError unless ref
|
49
|
-
found = all_refs(url).find do |data|
|
50
|
-
# we don't need to bother with these types
|
51
|
-
next if data[:type] == :pull || data[:type] == :merge_request
|
52
|
-
# is the name equal to the tag or branch? Is the commit sha equal?
|
53
|
-
data[:name].eql?(ref) || data[:sha].slice(0,8).eql?(ref.slice(0,8))
|
54
|
-
end
|
55
|
-
!found.nil?
|
56
|
-
end
|
57
|
-
|
58
|
-
# @return [Hash] - a hash of all the refs associated with the remote repository
|
59
|
-
# @param url [String] - the git string either https or ssh url
|
60
|
-
# @example
|
61
|
-
# {"0ec707e431367bbe2752966be8ab915b6f0da754"=>{:ref=>"refs/heads/74110ac", :type=>:branch, :subtype=>nil, :name=>"74110ac"},
|
62
|
-
# "07bb5d2d94db222dca5860eb29c184e8970f36f4"=>{:ref=>"refs/pull/74/head", :type=>:pull, :subtype=>:head, :name=>"74"},
|
63
|
-
# "156ca9a8ea69e056e86355b27d944e59d1b3a1e1"=>{:ref=>"refs/heads/master", :type=>:branch, :subtype=>nil, :name=>"master"},
|
64
|
-
# "fcc0532bbc5a5b65f3941738339e9cc7e3d767ce"=>{:ref=>"refs/pull/249/head", :type=>:pull, :subtype=>:head, :name=>"249"},
|
65
|
-
# "8d54891fa5df75890ee15d53080c2a81b4960f92"=>{:ref=>"refs/pull/267/head", :type=>:pull, :subtype=>:head, :name=>"267"} }
|
66
|
-
def all_refs(url)
|
67
|
-
data = `git ls-remote --symref #{url}`
|
68
|
-
raise "Error downloading #{url}" unless $CHILD_STATUS.success?
|
69
|
-
data.lines.reduce([]) do |refs, line|
|
70
|
-
sha, ref = line.split("\t")
|
71
|
-
next refs if sha.eql?('ref: refs/heads/master')
|
72
|
-
_, type, name, subtype = ref.chomp.split('/')
|
73
|
-
next refs unless name
|
74
|
-
type = :tag if type.eql?('tags')
|
75
|
-
type = type.to_sym
|
76
|
-
subtype = subtype.to_sym if subtype
|
77
|
-
type = :branch if type.eql?(:heads)
|
78
|
-
refs << { sha: sha, ref: ref.chomp, type: type, subtype: subtype, name: name }
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# @return [Boolean] - return true if the commit sha is valid
|
83
|
-
# @param url [String] - the git string either https or ssh url
|
84
|
-
# @param ref [String] - the sha id
|
85
|
-
def valid_commit?(url, sha)
|
86
|
-
return false if sha.nil? || sha.empty?
|
87
|
-
return true if valid_ref?(url, sha)
|
88
|
-
Dir.mktmpdir do |dir|
|
89
|
-
`git clone --no-tags #{url} #{dir} 2>&1 > /dev/null`
|
90
|
-
Dir.chdir(dir) do
|
91
|
-
`git show #{sha} 2>&1 > /dev/null`
|
92
|
-
$CHILD_STATUS.success?
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
44
|
# @return [Array[Hash]] array of module information and git status
|
98
45
|
def all_modules
|
99
|
-
begin
|
46
|
+
@all_modules ||= begin
|
47
|
+
r10k_branch = Ra10ke::GitRepo.current_branch(File.dirname(puppetfile))
|
100
48
|
git_modules(puppetfile).map do |mod|
|
101
|
-
|
102
|
-
|
49
|
+
repo = Ra10ke::GitRepo.new(mod[:args][:git])
|
50
|
+
ref = mod[:args][:ref] || mod[:args][:tag] || mod[:args][:branch] || mod[:args][:commit]
|
51
|
+
# If using control_branch, try to guesstimate what the target branch should be
|
52
|
+
if ref == ':control_branch'
|
53
|
+
ref = ENV['CONTROL_BRANCH'] \
|
54
|
+
|| r10k_branch \
|
55
|
+
|| mod[:args][:default_branch_override] \
|
56
|
+
|| ENV['CONTROL_BRANCH_FALLBACK'] \
|
57
|
+
|| mod[:args][:default_branch] \
|
58
|
+
|| 'main'
|
59
|
+
end
|
60
|
+
valid_ref = repo.valid_ref?(ref) || repo.valid_commit?(mod[:args][:ref])
|
103
61
|
{
|
104
62
|
name: mod[:name],
|
105
|
-
url:
|
63
|
+
url: repo.url,
|
106
64
|
ref: ref,
|
65
|
+
valid_url?: repo.valid_url?,
|
107
66
|
valid_ref?: valid_ref,
|
108
67
|
status: valid_ref ? Ra10ke::Validate::GOOD_EMOJI : Ra10ke::Validate::BAD_EMOJI
|
109
68
|
}
|
data/lib/ra10ke/version.rb
CHANGED
data/lib/ra10ke.rb
CHANGED
@@ -4,6 +4,8 @@ require 'ra10ke/version'
|
|
4
4
|
require 'ra10ke/solve'
|
5
5
|
require 'ra10ke/syntax'
|
6
6
|
require 'ra10ke/dependencies'
|
7
|
+
require 'ra10ke/deprecation'
|
8
|
+
require 'ra10ke/duplicates'
|
7
9
|
require 'ra10ke/install'
|
8
10
|
require 'ra10ke/validate'
|
9
11
|
require 'git'
|
@@ -14,6 +16,8 @@ module Ra10ke
|
|
14
16
|
include Ra10ke::Solve
|
15
17
|
include Ra10ke::Syntax
|
16
18
|
include Ra10ke::Dependencies
|
19
|
+
include Ra10ke::Deprecation
|
20
|
+
include Ra10ke::Duplicates
|
17
21
|
include Ra10ke::Install
|
18
22
|
include Ra10ke::Validate
|
19
23
|
|
@@ -33,6 +37,8 @@ module Ra10ke
|
|
33
37
|
define_task_solve_dependencies(*args)
|
34
38
|
define_task_syntax(*args)
|
35
39
|
define_task_dependencies(*args)
|
40
|
+
define_task_deprecation(*args)
|
41
|
+
define_task_duplicates(*args)
|
36
42
|
define_task_install(*args)
|
37
43
|
define_task_validate(*args)
|
38
44
|
end
|
@@ -40,6 +46,8 @@ module Ra10ke
|
|
40
46
|
|
41
47
|
def get_puppetfile
|
42
48
|
R10K::Puppetfile.new(@basedir, @moduledir, @puppetfile_path, @puppetfile_name, @force)
|
49
|
+
rescue ArgumentError # R10k < 2.6.0
|
50
|
+
R10K::Puppetfile.new(@basedir, @moduledir, @puppetfile_path || File.join(@basedir, @puppetfile_name || 'Puppetfile'))
|
43
51
|
end
|
44
52
|
end
|
45
53
|
end
|
data/ra10ke.gemspec
CHANGED
@@ -14,14 +14,17 @@ Gem::Specification.new do |spec|
|
|
14
14
|
|
15
15
|
spec.files = `git ls-files`.split($/)
|
16
16
|
spec.require_paths = ["lib"]
|
17
|
-
spec.required_ruby_version = '>= 2.
|
17
|
+
spec.required_ruby_version = '>= 2.4.0'
|
18
18
|
|
19
19
|
spec.add_dependency "rake"
|
20
20
|
spec.add_dependency "puppet_forge"
|
21
21
|
spec.add_dependency "r10k"
|
22
22
|
spec.add_dependency "git"
|
23
23
|
spec.add_dependency "solve"
|
24
|
-
spec.add_dependency 'semverse', '
|
24
|
+
spec.add_dependency 'semverse', '>= 2.0'
|
25
25
|
spec.add_dependency 'table_print', '~> 1.5.6'
|
26
26
|
spec.add_development_dependency 'rspec', '~> 3.6'
|
27
|
+
spec.add_development_dependency 'pry'
|
28
|
+
spec.add_development_dependency 'simplecov'
|
27
29
|
end
|
30
|
+
|
data/spec/fixtures/Puppetfile
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
forge 'http://forge.puppetlabs.com'
|
4
4
|
|
5
|
+
mod 'choria/choria', '0.26.2'
|
5
6
|
mod 'puppetlabs/inifile', '2.2.0'
|
7
|
+
mod 'puppetlabs-ruby', '1.0.1'
|
6
8
|
mod 'puppetlabs/stdlib', '4.24.0'
|
7
9
|
mod 'puppetlabs/concat', '4.0.0'
|
8
10
|
mod 'puppetlabs/ntp', '6.4.1'
|
@@ -40,7 +42,7 @@ mod 'dotfiles',
|
|
40
42
|
|
41
43
|
mod 'splunk',
|
42
44
|
git: 'https://github.com/cudgel/splunk.git',
|
43
|
-
branch: '
|
45
|
+
branch: 'dev'
|
44
46
|
|
45
47
|
mod 'puppet',
|
46
48
|
git: 'https://github.com/voxpupuli/puppet-module.git',
|
@@ -0,0 +1,23 @@
|
|
1
|
+
mod 'puppet-hiera_master',
|
2
|
+
git: 'https://github.com/voxpupuli/puppet-hiera_master.git',
|
3
|
+
branch: master
|
4
|
+
|
5
|
+
mod 'puppet-hiera_control',
|
6
|
+
git: 'https://github.com/voxpupuli/puppet-hiera_control.git',
|
7
|
+
branch: :control_branch
|
8
|
+
|
9
|
+
mod 'puppet-hiera_controlwithdefault',
|
10
|
+
git: 'https://github.com/voxpupuli/puppet-hiera_control.git',
|
11
|
+
branch: :control_branch,
|
12
|
+
default_branch: 'master'
|
13
|
+
|
14
|
+
mod 'puppet-hiera_controlwithdefaultoverride',
|
15
|
+
git: 'https://github.com/voxpupuli/puppet-hiera_control.git',
|
16
|
+
branch: :control_branch,
|
17
|
+
default_branch_override: 'master',
|
18
|
+
default_branch: 'devel'
|
19
|
+
|
20
|
+
mod 'puppet-hiera_fakecontrol',
|
21
|
+
git: 'https://github.com/voxpupuli/puppet-hiera_fakecontrol.git',
|
22
|
+
branch: control_branch
|
23
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
forge 'http://forge.puppetlabs.com'
|
4
|
+
|
5
|
+
mod 'abstractit/puppet', '2.4.1'
|
6
|
+
mod 'puppet/gitlab', '4.0.1'
|
7
|
+
mod 'puppetlabs/inifile', '2.2.0'
|
8
|
+
mod 'puppetlabs/stdlib', '4.24.0'
|
9
|
+
mod 'puppetlabs/concat', '4.0.0'
|
10
|
+
mod 'puppetlabs/ntp', '6.4.1'
|
11
|
+
mod 'theforeman/puppet', '12.0.1'
|
12
|
+
|
13
|
+
# introduced for tomcat module collaboration with uws
|
14
|
+
mod 'puppet-archive', '3.1.1'
|
15
|
+
|
16
|
+
mod 'gitlab',
|
17
|
+
git: 'https://github.com/vshn/puppet-gitlab',
|
18
|
+
ref: '00397b86dfb3487d9df768cbd3698d362132b5bf' # master
|
19
|
+
|
20
|
+
mod 'r10k',
|
21
|
+
git: 'https://github.com/acidprime/r10k',
|
22
|
+
tag: 'v3.1.1'
|
23
|
+
|
24
|
+
mod 'gms',
|
25
|
+
git: 'https://github.com/npwalker/abrader-gms',
|
26
|
+
branch: 'gitlab_disable_ssl_verify_support'
|
27
|
+
|
28
|
+
mod 'pltraining-rbac',
|
29
|
+
git: 'https://github.com/puppetlabs/pltraining-rbac',
|
30
|
+
ref: '2f60e1789a721ce83f8df061e13f8bf81cd4e4ce'
|
31
|
+
|
32
|
+
mod 'puppet-acl',
|
33
|
+
git: 'https://github.com/dobbymoodge/puppet-acl.git',
|
34
|
+
branch: 'master'
|
35
|
+
|
36
|
+
mod 'deploy',
|
37
|
+
git: 'https://github.com/cudgel/deploy.git',
|
38
|
+
branch: 'master'
|
39
|
+
|
40
|
+
mod 'dotfiles',
|
41
|
+
git: 'https://github.com/cudgel/puppet-dotfiles.git',
|
42
|
+
branch: 'master'
|
43
|
+
|
44
|
+
mod 'splunk',
|
45
|
+
git: 'https://github.com/cudgel/splunk.git',
|
46
|
+
branch: 'dev'
|
47
|
+
|
48
|
+
mod 'puppet',
|
49
|
+
git: 'https://github.com/voxpupuli/puppet-module.git',
|
50
|
+
branch: 'master'
|
File without changes
|