modulesync 1.2.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.config/cucumber.yml +1 -0
- data/.github/workflows/ci.yml +29 -0
- data/.github/workflows/release.yml +30 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +8 -1
- data/.rubocop_todo.yml +16 -35
- data/CHANGELOG.md +82 -1
- data/Gemfile +5 -1
- data/HISTORY.md +227 -0
- data/README.md +29 -6
- data/Rakefile +24 -0
- 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 +163 -341
- data/features/update/bad_context.feature +26 -0
- data/features/update/bump_version.feature +87 -0
- data/lib/modulesync.rb +92 -51
- data/lib/modulesync/cli.rb +10 -4
- data/lib/modulesync/cli/thor.rb +24 -0
- data/lib/modulesync/pr/github.rb +25 -9
- data/lib/modulesync/pr/gitlab.rb +27 -13
- data/lib/modulesync/puppet_module.rb +37 -0
- data/lib/modulesync/repository.rb +158 -0
- data/lib/modulesync/source_code.rb +57 -0
- data/lib/modulesync/util.rb +4 -1
- data/lib/monkey_patches.rb +9 -48
- data/modulesync.gemspec +4 -4
- data/spec/helpers/faker.rb +14 -0
- data/spec/helpers/faker/puppet_module_remote_repo.rb +146 -0
- data/spec/unit/modulesync_spec.rb +7 -3
- metadata +30 -10
- data/.travis.yml +0 -27
- data/lib/modulesync/git.rb +0 -194
@@ -5,17 +5,21 @@ describe ModuleSync do
|
|
5
5
|
it 'loads the managed modules from the specified :managed_modules_conf' do
|
6
6
|
allow(ModuleSync).to receive(:find_template_files).and_return([])
|
7
7
|
allow(ModuleSync::Util).to receive(:parse_config).with('./config_defaults.yml').and_return({})
|
8
|
-
expect(ModuleSync).to receive(:managed_modules).with(
|
8
|
+
expect(ModuleSync).to receive(:managed_modules).with(no_args).and_return([])
|
9
9
|
|
10
10
|
options = { managed_modules_conf: 'test_file.yml' }
|
11
11
|
ModuleSync.update(options)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
context '::
|
15
|
+
context '::pr' do
|
16
16
|
describe "Raise Error" do
|
17
|
+
let(:puppet_module) do
|
18
|
+
ModuleSync::PuppetModule.new 'puppet-test', remote: 'dummy'
|
19
|
+
end
|
20
|
+
|
17
21
|
it 'raises an error when neither GITHUB_TOKEN nor GITLAB_TOKEN are set for PRs' do
|
18
|
-
expect { ModuleSync.
|
22
|
+
expect { ModuleSync.pr(puppet_module) }.to raise_error(RuntimeError).and output(/No GitHub or GitLab token specified for --pr/).to_stderr
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: modulesync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vox Pupuli
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aruba
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '1.
|
89
|
+
version: '1.7'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '1.
|
96
|
+
version: '1.7'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: gitlab
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,16 +126,22 @@ dependencies:
|
|
126
126
|
name: puppet-blacksmith
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- - "
|
129
|
+
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '3.0'
|
132
|
+
- - "<"
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '7'
|
132
135
|
type: :runtime
|
133
136
|
prerelease: false
|
134
137
|
version_requirements: !ruby/object:Gem::Requirement
|
135
138
|
requirements:
|
136
|
-
- - "
|
139
|
+
- - ">="
|
137
140
|
- !ruby/object:Gem::Version
|
138
141
|
version: '3.0'
|
142
|
+
- - "<"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '7'
|
139
145
|
- !ruby/object:Gem::Dependency
|
140
146
|
name: thor
|
141
147
|
requirement: !ruby/object:Gem::Requirement
|
@@ -158,13 +164,16 @@ executables:
|
|
158
164
|
extensions: []
|
159
165
|
extra_rdoc_files: []
|
160
166
|
files:
|
167
|
+
- ".config/cucumber.yml"
|
168
|
+
- ".github/workflows/ci.yml"
|
169
|
+
- ".github/workflows/release.yml"
|
161
170
|
- ".gitignore"
|
162
171
|
- ".rspec"
|
163
172
|
- ".rubocop.yml"
|
164
173
|
- ".rubocop_todo.yml"
|
165
|
-
- ".travis.yml"
|
166
174
|
- CHANGELOG.md
|
167
175
|
- Gemfile
|
176
|
+
- HISTORY.md
|
168
177
|
- LICENSE
|
169
178
|
- README.md
|
170
179
|
- Rakefile
|
@@ -175,18 +184,25 @@ files:
|
|
175
184
|
- features/step_definitions/git_steps.rb
|
176
185
|
- features/support/env.rb
|
177
186
|
- features/update.feature
|
187
|
+
- features/update/bad_context.feature
|
188
|
+
- features/update/bump_version.feature
|
178
189
|
- lib/modulesync.rb
|
179
190
|
- lib/modulesync/cli.rb
|
191
|
+
- lib/modulesync/cli/thor.rb
|
180
192
|
- lib/modulesync/constants.rb
|
181
|
-
- lib/modulesync/git.rb
|
182
193
|
- lib/modulesync/hook.rb
|
183
194
|
- lib/modulesync/pr/github.rb
|
184
195
|
- lib/modulesync/pr/gitlab.rb
|
196
|
+
- lib/modulesync/puppet_module.rb
|
185
197
|
- lib/modulesync/renderer.rb
|
198
|
+
- lib/modulesync/repository.rb
|
186
199
|
- lib/modulesync/settings.rb
|
200
|
+
- lib/modulesync/source_code.rb
|
187
201
|
- lib/modulesync/util.rb
|
188
202
|
- lib/monkey_patches.rb
|
189
203
|
- modulesync.gemspec
|
204
|
+
- spec/helpers/faker.rb
|
205
|
+
- spec/helpers/faker/puppet_module_remote_repo.rb
|
190
206
|
- spec/spec_helper.rb
|
191
207
|
- spec/unit/modulesync/pr/github_spec.rb
|
192
208
|
- spec/unit/modulesync/pr/gitlab_spec.rb
|
@@ -204,14 +220,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
204
220
|
requirements:
|
205
221
|
- - ">="
|
206
222
|
- !ruby/object:Gem::Version
|
207
|
-
version: 2.
|
223
|
+
version: 2.5.0
|
208
224
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
209
225
|
requirements:
|
210
226
|
- - ">="
|
211
227
|
- !ruby/object:Gem::Version
|
212
228
|
version: '0'
|
213
229
|
requirements: []
|
214
|
-
rubygems_version: 3.
|
230
|
+
rubygems_version: 3.2.15
|
215
231
|
signing_key:
|
216
232
|
specification_version: 4
|
217
233
|
summary: Puppet Module Synchronizer
|
@@ -221,6 +237,10 @@ test_files:
|
|
221
237
|
- features/step_definitions/git_steps.rb
|
222
238
|
- features/support/env.rb
|
223
239
|
- features/update.feature
|
240
|
+
- features/update/bad_context.feature
|
241
|
+
- features/update/bump_version.feature
|
242
|
+
- spec/helpers/faker.rb
|
243
|
+
- spec/helpers/faker/puppet_module_remote_repo.rb
|
224
244
|
- spec/spec_helper.rb
|
225
245
|
- spec/unit/modulesync/pr/github_spec.rb
|
226
246
|
- spec/unit/modulesync/pr/gitlab_spec.rb
|
data/.travis.yml
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
---
|
2
|
-
sudo: false
|
3
|
-
language: ruby
|
4
|
-
cache: bundler
|
5
|
-
dist: trusty
|
6
|
-
script: 'bundle exec rake test'
|
7
|
-
rvm:
|
8
|
-
- 2.0
|
9
|
-
- 2.1
|
10
|
-
- 2.2
|
11
|
-
- 2.3
|
12
|
-
- 2.4
|
13
|
-
- 2.5
|
14
|
-
- 2.6
|
15
|
-
- 2.7
|
16
|
-
notifications:
|
17
|
-
email: false
|
18
|
-
deploy:
|
19
|
-
provider: rubygems
|
20
|
-
api_key:
|
21
|
-
secure: "Tbf1EbLEobIIox+fftJZADZsfQQ6kl0urcMNetK7NJzFo/negD/WyJIUj3kro/B7buyYADEjTui/JR4o8EPbugfM3ie5vYOd5k3AesSzbdr4BSwGe/cGbGOB7/PZuGfFLkb94/FiCU2mIwibkbh1rHWGlBoPj7ntL0+5ZtdvsM4="
|
22
|
-
gem: modulesync
|
23
|
-
on:
|
24
|
-
rvm: 2.7
|
25
|
-
tags: true
|
26
|
-
all_branches: true
|
27
|
-
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
|