modulesync 2.0.1 → 2.2.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/.config/cucumber.yml +1 -0
- data/.github/workflows/ci.yml +34 -0
- data/.github/workflows/release.yml +32 -0
- data/.rubocop.yml +6 -1
- data/.rubocop_todo.yml +16 -35
- data/CHANGELOG.md +62 -0
- data/Gemfile +6 -4
- data/LICENSE +173 -12
- data/README.md +34 -4
- data/features/cli.feature +14 -6
- data/features/hook.feature +3 -5
- data/features/step_definitions/git_steps.rb +73 -35
- data/features/support/env.rb +4 -0
- data/features/update.feature +145 -345
- data/features/update/bad_context.feature +26 -0
- data/features/update/bump_version.feature +87 -0
- data/lib/modulesync.rb +60 -54
- data/lib/modulesync/cli.rb +5 -4
- data/lib/modulesync/cli/thor.rb +24 -0
- data/lib/modulesync/puppet_module.rb +37 -0
- data/lib/modulesync/repository.rb +162 -0
- data/lib/modulesync/source_code.rb +57 -0
- data/lib/monkey_patches.rb +9 -48
- data/modulesync.gemspec +5 -4
- data/spec/helpers/faker.rb +14 -0
- data/spec/helpers/faker/puppet_module_remote_repo.rb +146 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/unit/modulesync_spec.rb +6 -2
- metadata +43 -10
- data/.travis.yml +0 -28
- data/lib/modulesync/git.rb +0 -194
data/.travis.yml
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
---
|
2
|
-
sudo: false
|
3
|
-
language: ruby
|
4
|
-
cache: bundler
|
5
|
-
dist: focal
|
6
|
-
script: 'bundle exec rake test'
|
7
|
-
bundler_args: --without release
|
8
|
-
rvm:
|
9
|
-
- 2.5
|
10
|
-
- 2.6
|
11
|
-
- 2.7
|
12
|
-
notifications:
|
13
|
-
email: false
|
14
|
-
irc:
|
15
|
-
on_success: always
|
16
|
-
on_failure: always
|
17
|
-
channels:
|
18
|
-
- "chat.freenode.org#voxpupuli-notifications"
|
19
|
-
deploy:
|
20
|
-
provider: rubygems
|
21
|
-
api_key:
|
22
|
-
secure: "Tbf1EbLEobIIox+fftJZADZsfQQ6kl0urcMNetK7NJzFo/negD/WyJIUj3kro/B7buyYADEjTui/JR4o8EPbugfM3ie5vYOd5k3AesSzbdr4BSwGe/cGbGOB7/PZuGfFLkb94/FiCU2mIwibkbh1rHWGlBoPj7ntL0+5ZtdvsM4="
|
23
|
-
gem: modulesync
|
24
|
-
on:
|
25
|
-
rvm: 2.7
|
26
|
-
tags: true
|
27
|
-
all_branches: true
|
28
|
-
repo: voxpupuli/modulesync
|
data/lib/modulesync/git.rb
DELETED
@@ -1,194 +0,0 @@
|
|
1
|
-
require 'git'
|
2
|
-
require 'puppet_blacksmith'
|
3
|
-
|
4
|
-
module ModuleSync
|
5
|
-
module Git # rubocop:disable Metrics/ModuleLength
|
6
|
-
include Constants
|
7
|
-
|
8
|
-
def self.remote_branch_exists?(repo, branch)
|
9
|
-
repo.branches.remote.collect(&:name).include?(branch)
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.local_branch_exists?(repo, branch)
|
13
|
-
repo.branches.local.collect(&:name).include?(branch)
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.remote_branch_differ?(repo, local_branch, remote_branch)
|
17
|
-
!remote_branch_exists?(repo, remote_branch) ||
|
18
|
-
repo.diff("#{local_branch}..origin/#{remote_branch}").any?
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.default_branch(repo)
|
22
|
-
symbolic_ref = repo.branches.find { |b| b.full =~ %r{remotes/origin/HEAD} }
|
23
|
-
return unless symbolic_ref
|
24
|
-
%r{remotes/origin/HEAD\s+->\s+origin/(?<branch>.+?)$}.match(symbolic_ref.full)[:branch]
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.switch_branch(repo, branch)
|
28
|
-
unless branch
|
29
|
-
branch = default_branch(repo)
|
30
|
-
puts "Using repository's default branch: #{branch}"
|
31
|
-
end
|
32
|
-
return if repo.current_branch == branch
|
33
|
-
|
34
|
-
if local_branch_exists?(repo, branch)
|
35
|
-
puts "Switching to branch #{branch}"
|
36
|
-
repo.checkout(branch)
|
37
|
-
elsif remote_branch_exists?(repo, branch)
|
38
|
-
puts "Creating local branch #{branch} from origin/#{branch}"
|
39
|
-
repo.checkout("origin/#{branch}")
|
40
|
-
repo.branch(branch).checkout
|
41
|
-
else
|
42
|
-
repo.checkout('origin/master')
|
43
|
-
puts "Creating new branch #{branch}"
|
44
|
-
repo.branch(branch).checkout
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.pull(git_base, name, branch, project_root, opts)
|
49
|
-
puts "Syncing #{name}"
|
50
|
-
Dir.mkdir(project_root) unless Dir.exist?(project_root)
|
51
|
-
|
52
|
-
# Repo needs to be cloned in the cwd
|
53
|
-
if !Dir.exist?("#{project_root}/#{name}") || !Dir.exist?("#{project_root}/#{name}/.git")
|
54
|
-
puts 'Cloning repository fresh'
|
55
|
-
remote = opts[:remote] || (git_base.start_with?('file://') ? "#{git_base}#{name}" : "#{git_base}#{name}.git")
|
56
|
-
local = "#{project_root}/#{name}"
|
57
|
-
puts "Cloning from #{remote}"
|
58
|
-
repo = ::Git.clone(remote, local)
|
59
|
-
switch_branch(repo, branch)
|
60
|
-
# Repo already cloned, check out master and override local changes
|
61
|
-
else
|
62
|
-
# Some versions of git can't properly handle managing a repo from outside the repo directory
|
63
|
-
Dir.chdir("#{project_root}/#{name}") do
|
64
|
-
puts "Overriding any local changes to repositories in #{project_root}"
|
65
|
-
repo = ::Git.open('.')
|
66
|
-
repo.fetch
|
67
|
-
repo.reset_hard
|
68
|
-
switch_branch(repo, branch)
|
69
|
-
repo.pull('origin', branch) if remote_branch_exists?(repo, branch)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def self.update_changelog(repo, version, message, module_root)
|
75
|
-
changelog = "#{module_root}/CHANGELOG.md"
|
76
|
-
if File.exist?(changelog)
|
77
|
-
puts "Updating #{changelog} for version #{version}"
|
78
|
-
changes = File.readlines(changelog)
|
79
|
-
File.open(changelog, 'w') do |f|
|
80
|
-
date = Time.now.strftime('%Y-%m-%d')
|
81
|
-
f.puts "## #{date} - Release #{version}\n\n"
|
82
|
-
f.puts "#{message}\n\n"
|
83
|
-
# Add old lines again
|
84
|
-
f.puts changes
|
85
|
-
end
|
86
|
-
repo.add('CHANGELOG.md')
|
87
|
-
else
|
88
|
-
puts 'No CHANGELOG.md file found, not updating.'
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.bump(repo, m, message, module_root, changelog = false)
|
93
|
-
new = m.bump!
|
94
|
-
puts "Bumped to version #{new}"
|
95
|
-
repo.add('metadata.json')
|
96
|
-
update_changelog(repo, new, message, module_root) if changelog
|
97
|
-
repo.commit("Release version #{new}")
|
98
|
-
repo.push
|
99
|
-
new
|
100
|
-
end
|
101
|
-
|
102
|
-
def self.tag(repo, version, tag_pattern)
|
103
|
-
tag = tag_pattern % version
|
104
|
-
puts "Tagging with #{tag}"
|
105
|
-
repo.add_tag(tag)
|
106
|
-
repo.push('origin', tag)
|
107
|
-
end
|
108
|
-
|
109
|
-
def self.checkout_branch(repo, branch)
|
110
|
-
selected_branch = branch || repo.current_branch || 'master'
|
111
|
-
repo.branch(selected_branch).checkout
|
112
|
-
selected_branch
|
113
|
-
end
|
114
|
-
private_class_method :checkout_branch
|
115
|
-
|
116
|
-
# Git add/rm, git commit, git push
|
117
|
-
def self.update(name, files, options)
|
118
|
-
module_root = "#{options[:project_root]}/#{name}"
|
119
|
-
message = options[:message]
|
120
|
-
repo = ::Git.open(module_root)
|
121
|
-
branch = checkout_branch(repo, options[:branch])
|
122
|
-
files.each do |file|
|
123
|
-
if repo.status.deleted.include?(file)
|
124
|
-
repo.remove(file)
|
125
|
-
elsif File.exist?("#{module_root}/#{file}")
|
126
|
-
repo.add(file)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
begin
|
130
|
-
opts_commit = {}
|
131
|
-
opts_push = {}
|
132
|
-
opts_commit = { :amend => true } if options[:amend]
|
133
|
-
opts_push = { :force => true } if options[:force]
|
134
|
-
if options[:pre_commit_script]
|
135
|
-
script = "#{File.dirname(File.dirname(__FILE__))}/../contrib/#{options[:pre_commit_script]}"
|
136
|
-
`#{script} #{module_root}`
|
137
|
-
end
|
138
|
-
repo.commit(message, opts_commit)
|
139
|
-
if options[:remote_branch]
|
140
|
-
if remote_branch_differ?(repo, branch, options[:remote_branch])
|
141
|
-
repo.push('origin', "#{branch}:#{options[:remote_branch]}", opts_push)
|
142
|
-
end
|
143
|
-
else
|
144
|
-
repo.push('origin', branch, opts_push)
|
145
|
-
end
|
146
|
-
# Only bump/tag if pushing didn't fail (i.e. there were changes)
|
147
|
-
m = Blacksmith::Modulefile.new("#{module_root}/metadata.json")
|
148
|
-
if options[:bump]
|
149
|
-
new = bump(repo, m, message, module_root, options[:changelog])
|
150
|
-
tag(repo, new, options[:tag_pattern]) if options[:tag]
|
151
|
-
end
|
152
|
-
rescue ::Git::GitExecuteError => git_error
|
153
|
-
if git_error.message =~ /working (directory|tree) clean/
|
154
|
-
puts "There were no files to update in #{name}. Not committing."
|
155
|
-
return false
|
156
|
-
else
|
157
|
-
puts git_error
|
158
|
-
raise
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
true
|
163
|
-
end
|
164
|
-
|
165
|
-
# Needed because of a bug in the git gem that lists ignored files as
|
166
|
-
# untracked under some circumstances
|
167
|
-
# https://github.com/schacon/ruby-git/issues/130
|
168
|
-
def self.untracked_unignored_files(repo)
|
169
|
-
ignore_path = "#{repo.dir.path}/.gitignore"
|
170
|
-
ignored = File.exist?(ignore_path) ? File.read(ignore_path).split : []
|
171
|
-
repo.status.untracked.keep_if { |f, _| ignored.none? { |i| File.fnmatch(i, f) } }
|
172
|
-
end
|
173
|
-
|
174
|
-
def self.update_noop(name, options)
|
175
|
-
puts "Using no-op. Files in #{name} may be changed but will not be committed."
|
176
|
-
|
177
|
-
repo = ::Git.open("#{options[:project_root]}/#{name}")
|
178
|
-
checkout_branch(repo, options[:branch])
|
179
|
-
|
180
|
-
puts 'Files changed:'
|
181
|
-
repo.diff('HEAD', '--').each do |diff|
|
182
|
-
puts diff.patch
|
183
|
-
end
|
184
|
-
|
185
|
-
puts 'Files added:'
|
186
|
-
untracked_unignored_files(repo).each_key do |file|
|
187
|
-
puts file
|
188
|
-
end
|
189
|
-
|
190
|
-
puts "\n\n"
|
191
|
-
puts '--------------------------------'
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|