simp-rake-helpers 4.1.1 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/rake -T
2
2
 
3
+ require 'simp/yum'
3
4
  require 'simp/rake/pkg'
4
5
  require 'simp/rake/build/constants'
5
6
  require 'simp/rake/build/rpmdeps'
@@ -15,19 +16,13 @@ module Simp::Rake::Build
15
16
  def initialize( base_dir )
16
17
  init_member_vars( base_dir )
17
18
 
18
- @mock = ENV['mock'] || '/usr/bin/mock'
19
+ @verbose = ENV.fetch('SIMP_PKG_verbose','no') == 'yes'
20
+ @rpm_build_metadata = 'last_rpm_build_metadata.yaml'
21
+
19
22
  define_tasks
20
23
  end
21
24
 
22
25
  def define_tasks
23
- task :help do
24
- puts <<-EOF.gsub(/^ /, '')
25
- SIMP_RAKE_CHOWN_EVERYTHING=(Y|N)
26
- If 'Y', builds are preceded by a massive chown -R mock on the entire source tree
27
-
28
- EOF
29
- end
30
-
31
26
  namespace :pkg do
32
27
  ##############################################################################
33
28
  # Main tasks
@@ -47,16 +42,10 @@ module Simp::Rake::Build
47
42
  @build_dirs = {
48
43
  :modules => get_module_dirs(args[:method]),
49
44
  :aux => [
50
- "#{@src_dir}/rsync",
51
45
  # Anything in here gets built!
52
- "#{@src_dir}/assets/*",
53
- # Legacy Compat
54
- "#{@src_dir}/utils",
55
- "#{@src_dir}/puppet/bootstrap"
46
+ "#{@src_dir}/assets/*"
56
47
  ],
57
- :doc => "#{@src_dir}/doc",
58
- :simp_cli => "#{@src_dir}/rubygems/simp_cli",
59
- :simp => "#{@src_dir}",
48
+ :doc => "#{@src_dir}/doc"
60
49
  }
61
50
 
62
51
  @build_dirs[:aux].map!{|dir| dir = Dir.glob(dir)}
@@ -68,68 +57,10 @@ module Simp::Rake::Build
68
57
  }
69
58
  end
70
59
 
71
- task :mock_prep => [:prep] do
72
- chown_everything = ENV.fetch( 'SIMP_RAKE_CHOWN_EVERYTHING', 'Y' ).chomp.index( %r{^(1|Y|true|yes)$}i ) || false
73
-
74
- verbose(true) do
75
- next unless chown_everything
76
-
77
- dirs_to_mod = []
78
- files_to_mod = []
79
-
80
- Find.find(@base_dir) do |path|
81
- Find.prune if File.symlink?(path)
82
- Find.prune if (File.basename(path) == '.git')
83
- Find.prune if (File.basename(path) =~ /^\..*cache/)
84
-
85
- safe_path = Shellwords.escape(path)
86
-
87
- mock_gid = Etc.getgrnam('mock').gid
88
-
89
- file_stat = File.stat(path)
90
-
91
- file_mode = file_stat.mode.to_s(2)[-12..-1].scan(/.{3}/)
92
- file_group_perms = file_mode[-2]
93
- file_group_read = (file_group_perms[0] == '1')
94
- file_group_execute = (file_group_perms[2] == '1')
95
- file_sgid = (file_mode[-4][1] == '1')
96
-
97
- if File.directory?(path)
98
- if (mock_gid != file_stat.gid) ||
99
- !file_group_read ||!file_group_execute || !file_sgid
100
- dirs_to_mod << safe_path
101
- end
102
- else
103
- if (mock_gid != file_stat.gid) || !file_group_read
104
- files_to_mod << safe_path
105
- end
106
- end
107
- end
108
-
109
- # Set the permissions properly for mock to dig through your source
110
- Parallel.map(
111
- dirs_to_mod,
112
- :in_processes => get_cpu_limit,
113
- :progress => 'Set "mock" dir perms'
114
- ) do |dir|
115
- %x{chgrp 'mock' #{dir} && chmod g+rXs #{dir}}
116
- end
117
-
118
- Parallel.map(
119
- files_to_mod,
120
- :in_processes => get_cpu_limit,
121
- :progress => 'Set "mock" file perms'
122
- ) do |file|
123
- %x{chgrp 'mock' #{file} && chmod g+r #{file}}
124
- end
125
- end
126
- end
127
-
128
60
  clean_failures = []
129
61
  clean_failures_lock = Mutex.new
130
62
 
131
- task :clean,[:chroot] => [:prep] do |t,args|
132
- validate_in_mock_group?
63
+ task :clean => [:prep] do |t,args|
133
64
  @build_dirs.each_pair do |k,dirs|
134
65
  Parallel.map(
135
66
  Array(dirs),
@@ -139,7 +70,7 @@ module Simp::Rake::Build
139
70
  Dir.chdir(dir) do
140
71
  begin
141
72
  rake_flags = Rake.application.options.trace ? '--trace' : ''
142
- %x{rake clean[#{args[:chroot]}] #{rake_flags}}
73
+ %x{rake clean #{rake_flags}}
143
74
  clean_failures_lock.synchronize do
144
75
  clean_failures << dir unless $?.success?
145
76
  end
@@ -156,12 +87,9 @@ module Simp::Rake::Build
156
87
  unless clean_failures.empty?
157
88
  fail(%(Error: The following directories had failures in #{task.name}:\n * #{clean_failures.join("\n * ")}))
158
89
  end
159
-
160
- %x{mock -r #{args[:chroot]} --scrub=all} if args[:chroot]
161
90
  end
162
91
 
163
- task :clobber,[:chroot] => [:prep] do |t,args|
164
- validate_in_mock_group?
92
+ task :clobber => [:prep] do |t,args|
165
93
  @build_dirs.each_pair do |k,dirs|
166
94
  Parallel.map(
167
95
  Array(dirs),
@@ -170,12 +98,13 @@ module Simp::Rake::Build
170
98
  ) do |dir|
171
99
  Dir.chdir(dir) do
172
100
  rake_flags = Rake.application.options.trace ? '--trace' : ''
173
- sh %{rake clobber[#{args[:chroot]}] #{rake_flags}}
101
+ sh %{rake clobber #{rake_flags}}
174
102
  end
175
103
  end
176
104
  end
177
105
  end
178
106
 
107
+ =begin
179
108
  desc <<-EOM
180
109
  Prepare the GPG key space for a SIMP build.
181
110
 
@@ -185,6 +114,7 @@ module Simp::Rake::Build
185
114
  ENV vars:
186
115
  - Set `SIMP_PKG_verbose=yes` to report file operations as they happen.
187
116
  EOM
117
+ =end
188
118
  task :key_prep,[:key] => [:prep] do |t,args|
189
119
  require 'securerandom'
190
120
  _verbose = ENV.fetch('SIMP_PKG_verbose','no') == 'yes'
@@ -330,78 +260,102 @@ module Simp::Rake::Build
330
260
  end
331
261
  end
332
262
 
333
- desc <<-EOM
334
- Build the entire SIMP release.
263
+ def populate_rpm_dir(rpm_dir)
264
+ srpm_dir = File.join(File.dirname(rpm_dir), 'SRPMS')
335
265
 
336
- Building this environment requires a working Mock setup (http://fedoraproject.org/wiki/Projects/Mock)
337
- * :chroot - The Mock chroot configuration to use. See the '--root' option in mock(1).
338
- * :docs - Build the docs. Set this to false if you wish to skip building the docs.
339
- * :key - The GPG key to sign the RPMs with. Defaults to 'dev'.
266
+ FileUtils.mkdir_p(rpm_dir)
267
+ FileUtils.mkdir_p(srpm_dir)
340
268
 
341
- ENV vars:
342
- - Set `SIMP_PKG_verbose=yes` to report file operations as they happen.
343
- EOM
344
- task :build,[:chroot,:docs,:key,:snapshot_release] => [:prep,:mock_prep,:key_prep] do |t,args|
269
+ rpm_metadata = %x(find -P #{@src_dir} -xdev -type f -name #{@rpm_build_metadata}).lines.map(&:strip).sort
345
270
 
346
- validate_in_mock_group?
347
- _verbose = ENV.fetch('SIMP_PKG_verbose','no') == 'yes'
271
+ fail("No #{@rpm_build_metadata} files found under #{@src_dir}") if rpm_metadata.empty?
348
272
 
349
- args.with_defaults(:key => 'dev')
350
- args.with_defaults(:docs => 'true')
273
+ rpm_metadata.each do |mf|
274
+ metadata = YAML.load_file(mf)
275
+ rpms = metadata['rpms']
276
+ srpms = metadata['srpms']
351
277
 
352
- output_dir = @pkg_dirs[:simp]
278
+ fail("No RPMs found at #{rpm_dir}") if (rpms.nil? || rpms.empty?)
353
279
 
354
- check_dvd_env
280
+ have_signed_rpm = false
355
281
 
356
- Rake::Task['pkg:simp_cli'].invoke(args[:chroot])
357
- Rake::Task['pkg:aux'].invoke(args[:chroot])
358
- if "#{args.docs}" == 'true'
359
- Rake::Task['pkg:doc'].invoke(args[:chroot])
360
- end
361
- Rake::Task['pkg:modules'].invoke(args[:chroot])
362
-
363
- # The main SIMP RPM must be built last!
364
- Rake::Task['pkg:simp'].invoke(args[:chroot],args[:snapshot_release])
282
+ Dir.chdir(rpm_dir) do
283
+ rpms.each_key do |rpm|
284
+ if @verbose
285
+ puts "Copying #{rpm} to #{rpm_dir}"
286
+ end
365
287
 
366
- # Prepare for the build!
367
- rm_rf(output_dir, :verbose => _verbose)
288
+ arch = rpms[rpm]['metadata'][:arch]
289
+ FileUtils.mkdir_p(arch)
368
290
 
369
- # Copy all the resulting files into the target output directory
370
- mkdir_p(output_dir)
291
+ FileUtils.cp(rpms[rpm]['path'], arch)
371
292
 
372
- @build_dirs.each_pair do |k,dirs|
373
- Array(dirs).each do |dir|
374
- rpms = Dir.glob("#{dir}/dist/*.rpm")
375
- srpms = []
376
- rpms.delete_if{|x|
377
- del = false
378
- if x =~ /\.src\.rpm$/
379
- del = true
380
- srpms << x
293
+ if rpms[rpm][:signature]
294
+ have_signed_rpm = true
381
295
  end
296
+ end
297
+ end
382
298
 
383
- del
384
- }
299
+ Dir.chdir(srpm_dir) do
300
+ srpms.each_key do |srpm|
301
+ if have_signed_rpm && !srpms[srpm][:signature]
302
+ if @verbose
303
+ puts "Found signed RPM - skipping copy of '#{srpm}'"
304
+ end
385
305
 
386
- srpms.each do |srpm|
387
- out_dir = "#{output_dir}/SRPMS"
388
- mkdir_p(out_dir, :verbose => _verbose) unless File.directory?(out_dir)
306
+ next
307
+ end
389
308
 
390
- unless uptodate?("#{out_dir}/#{File.basename(srpm)}",[srpm])
391
- cp(srpm, out_dir, :verbose => _verbose)
309
+ if @verbose
310
+ puts "Copying '#{srpm}' to '#{srpm_dir}'"
392
311
  end
393
- end
394
312
 
395
- rpms.each do |rpm|
396
- out_dir = "#{output_dir}/RPMS/#{rpm.split('.')[-2]}"
397
- mkdir_p(out_dir, :verbose => _verbose) unless File.directory?(out_dir)
313
+ arch = srpms[srpm]['metadata'][:arch]
314
+ FileUtils.mkdir_p(arch)
398
315
 
399
- unless uptodate?("#{out_dir}/#{File.basename(rpm)}",[rpm])
400
- cp(rpm, out_dir, :verbose => _verbose)
401
- end
316
+ FileUtils.cp(srpms[srpm]['path'], arch)
402
317
  end
403
318
  end
404
319
  end
320
+ end
321
+
322
+
323
+ =begin
324
+ desc <<-EOM
325
+ Build the entire SIMP release.
326
+
327
+ * :docs - Build the docs. Set this to false if you wish to skip building the docs.
328
+ * :key - The GPG key to sign the RPMs with. Defaults to 'dev'.
329
+
330
+ ENV vars:
331
+ - Set `SIMP_PKG_verbose=yes` to report file operations as they happen.
332
+ - Set `SIMP_YUM_makecache=no` if you do NOT want to rebuild the
333
+ build-specific YUM cache
334
+ EOM
335
+ =end
336
+ task :build,[:docs,:key] => [:prep,:key_prep] do |t,args|
337
+
338
+ _verbose = ENV.fetch('SIMP_PKG_verbose','no') == 'yes'
339
+
340
+ args.with_defaults(:key => 'dev')
341
+ args.with_defaults(:docs => 'true')
342
+
343
+ check_dvd_env
344
+
345
+ begin
346
+ yum_helper = Simp::YUM.new(
347
+ Simp::YUM.generate_yum_conf(File.join(@distro_build_dir, 'yum_data')),
348
+ ENV.fetch('SIMP_YUM_makecache','yes') == 'yes')
349
+ rescue Simp::YUM::Error
350
+ end
351
+
352
+ Rake::Task['pkg:aux'].invoke
353
+ if "#{args.docs}" == 'true'
354
+ Rake::Task['pkg:doc'].invoke
355
+ end
356
+ Rake::Task['pkg:modules'].invoke
357
+
358
+ populate_rpm_dir(@rpm_dir)
405
359
 
406
360
  Rake::Task['pkg:signrpms'].invoke(args[:key])
407
361
  end
@@ -409,35 +363,32 @@ module Simp::Rake::Build
409
363
  desc <<-EOM
410
364
  Build the Puppet module RPMs.
411
365
 
412
- Building this environment requires a working Mock setup (http://fedoraproject.org/wiki/Projects/Mock)
413
-
414
- * :chroot - The Mock chroot configuration to use. See the '--root' option in mock(1).
415
- * :method - The Puppetfile from which the repository information should be read. Defaults to 'tracking'
366
+ * :method - The Puppetfile from which the repository information
367
+ should be read. Defaults to 'tracking'
416
368
 
417
369
  ENV vars:
418
370
  - Set `SIMP_PKG_verbose=yes` to report file operations as they happen.
419
371
  EOM
420
- task :modules,[:chroot,:method] => [:prep,:mock_prep] do |t,args|
421
- build(args[:chroot],@build_dirs[:modules],t)
372
+ task :modules,[:method] => [:prep] do |t,args|
373
+ build(@build_dirs[:modules],t)
422
374
  end
423
375
 
424
376
  desc <<-EOM
425
377
  Build a single Puppet Module RPM.
426
378
 
427
- Building this environment requires a working Mock setup (http://fedoraproject.org/wiki/Projects/Mock)
428
-
429
379
  * :name - The path, or name, of the module to build. If a name is
430
380
  given, the Puppetfile.<method> will be used to find the
431
381
  module.
432
382
  Note: This is the *short* name. So, to build
433
383
  puppetlabs-stdlib, you would just enter 'stdlib'
434
- * :chroot - The Mock chroot configuration to use. See the '--root' option in mock(1).
435
384
  * :method - The Puppetfile from which the repository information should be read. Defaults to 'tracking'
436
385
 
437
386
  ENV vars:
438
387
  - Set `SIMP_PKG_verbose=yes` to report file operations as they happen.
388
+ - Set `SIMP_YUM_makecache=no` if you do NOT want to rebuild the
389
+ build-specific YUM cache
439
390
  EOM
440
- task :single,[:name,:chroot,:method] => [:prep, :mock_prep] do |t,args|
391
+ task :single,[:name,:method] => [:prep] do |t,args|
441
392
  fail("You must pass :name to '#{t.name}'") unless args[:name]
442
393
 
443
394
  mod_path = File.absolute_path(args[:name])
@@ -455,70 +406,45 @@ module Simp::Rake::Build
455
406
  mod_path = local_module[:path]
456
407
  end
457
408
 
409
+ begin
410
+ yum_helper = Simp::YUM.new(
411
+ Simp::YUM.generate_yum_conf(File.join(@distro_build_dir, 'yum_data')),
412
+ ENV.fetch('SIMP_YUM_makecache','yes') == 'yes')
413
+ rescue Simp::YUM::Error
414
+ end
415
+
458
416
  ENV['SIMP_PKG_rand_name'] = 'yes'
459
- build(args[:chroot], Array(mod_path), t)
417
+ build(Array(mod_path), t)
460
418
 
461
419
  puts("Your packages can be found in '#{mod_path}/dist'")
462
420
  end
463
421
 
464
- desc <<-EOM
465
- Build simp config rubygem RPM.
466
-
467
- * :method - The Puppetfile from which the repository information should be read. Defaults to 'tracking'
468
-
469
- ENV vars:
470
- - Set `SIMP_PKG_verbose=yes` to report file operations as they happen.
471
- EOM
472
- task :simp_cli,[:chroot] => [:prep,:mock_prep] do |t,args|
473
- build(args[:chroot], @build_dirs[:simp_cli], t)
474
- end
475
-
476
422
  desc <<-EOM
477
423
  Build the SIMP non-module RPMs.
478
424
 
479
- Building this environment requires a working Mock setup (http://fedoraproject.org/wiki/Projects/Mock)
480
-
481
425
  ENV vars:
482
426
  - Set `SIMP_PKG_verbose=yes` to report file operations as they happen.
483
- * :chroot - The Mock chroot configuration to use. See the '--root' option in mock(1).
484
427
  EOM
485
- task :aux,[:chroot] => [:prep,:mock_prep] do |t,args|
486
- build(args[:chroot],@build_dirs[:aux],t)
428
+ task :aux => [:prep] do |t,args|
429
+ build(@build_dirs[:aux],t)
487
430
  end
488
431
 
489
432
  desc <<-EOM
490
433
  Build the SIMP documentation.
491
434
 
492
- Building this environment requires a working Mock setup (http://fedoraproject.org/wiki/Projects/Mock)
493
- * :chroot - The Mock chroot configuration to use. See the '--root' option in mock(1).
494
-
495
435
  ENV vars:
496
436
  - Set `SIMP_PKG_verbose=yes` to report file operations as they happen.
497
437
  EOM
498
- task :doc,[:chroot] => [:prep,:mock_prep] do |t,args|
499
- build(args[:chroot],@build_dirs[:doc],t)
500
- end
501
-
502
- desc <<-EOM
503
- Build the main SIMP RPM.
504
-
505
- Building this environment requires a working Mock setup (http://fedoraproject.org/wiki/Projects/Mock)
506
- * :chroot - The Mock chroot configuration to use. See the '--root' option in mock(1).
507
- * :snapshot_release - Will add a define to the Mock to set snapshot_release to current date and time.
508
-
509
- ENV vars:
510
- - Set `SIMP_PKG_verbose=yes` to report file operations as they happen.
511
- EOM
512
- task :simp,[:chroot,:snapshot_release] => [:prep,:mock_prep] do |t,args|
513
- build(args[:chroot],@build_dirs[:simp],t,false,args[:snapshot_release])
438
+ task :doc => [:prep] do |t,args|
439
+ build(@build_dirs[:doc],t)
514
440
  end
515
441
 
516
442
  desc "Sign the RPMs."
517
- task :signrpms,[:key,:rpm_dir,:force] => [:prep,:key_prep,:mock_prep] do |t,args|
443
+ task :signrpms,[:key,:rpm_dir,:force] => [:prep,:key_prep] do |t,args|
518
444
  which('rpmsign') || raise(StandardError, 'Could not find rpmsign on your system. Exiting.')
519
445
 
520
446
  args.with_defaults(:key => 'dev')
521
- args.with_defaults(:rpm_dir => "#{@build_dir}/SIMP/*RPMS")
447
+ args.with_defaults(:rpm_dir => File.join(File.dirname(@rpm_dir), '*RPMS'))
522
448
  args.with_default(:force => 'false')
523
449
 
524
450
  force = (args[:force].to_s == 'false' ? false : true)
@@ -538,36 +464,62 @@ module Simp::Rake::Build
538
464
  :in_processes => get_cpu_limit,
539
465
  :progress => t.name
540
466
  ) do |rpm|
541
- rpminfo = %x{rpm -qip #{rpm} 2>/dev/null}.split("\n")
542
- if (force || !rpminfo.grep(/Signature\s+:\s+\(none\)/).empty?)
543
- Simp::RPM.signrpm(rpm,"#{@build_dir}/build_keys/#{args[:key]}")
544
- end
467
+ rpm_info = Simp::RPM.new(rpm)
468
+ Simp::RPM.signrpm(rpm, "#{@build_dir}/build_keys/#{args[:key]}") unless rpm_info.signature
545
469
  end
546
470
  end
547
471
 
472
+ =begin
548
473
  desc <<-EOM
549
474
  Check that RPMs are signed.
550
475
 
551
476
  Checks all RPM files in a directory to see if they are trusted.
552
477
  * :rpm_dir - A directory containing RPM files to check. Default #{@build_dir}/SIMP
553
- * :key_dir - The path to the GPG keys you want to check the packages against. Default #{@src_dir}/assets/simp-gpgkeys/
478
+ * :key_dir - The path to the GPG keys you want to check the packages against. Default #{@src_dir}/assets/gpgkeys/
554
479
  EOM
480
+ =end
555
481
  task :checksig,[:rpm_dir,:key_dir] => [:prep] do |t,args|
556
482
  begin
483
+
484
+ default_key_dir = File.join(@src_dir, 'assets', 'gpgkeys', 'GPGKEYS')
557
485
  args.with_defaults(:rpm_dir => @pkg_dirs[:simp])
558
- args.with_defaults(:key_dir => "#{@src_dir}/assets/simp-gpgkeys")
486
+ args.with_defaults(:key_dir => default_key_dir)
559
487
 
560
488
  rpm_dirs = Dir.glob(args[:rpm_dir])
561
489
 
562
490
  fail("Could not find files at #{args[:rpm_dir]}!") if rpm_dirs.empty?
563
491
 
564
492
  temp_gpg_dir = Dir.mktmpdir
493
+ at_exit { FileUtils.remove_entry(temp_gpg_dir) if File.exist?(temp_gpg_dir) }
565
494
 
566
495
  rpm_cmd = %{rpm --dbpath #{temp_gpg_dir}}
567
496
 
568
497
  %x{#{rpm_cmd} --initdb}
569
498
 
570
499
  public_keys = Dir.glob(File.join(args[:key_dir], '*'))
500
+
501
+ if public_keys.empty?
502
+ key_dirs_tried = [ args[:key_dir] ]
503
+
504
+ # try path to GPG keys for SIMP 6.1+
505
+ if (args[:key_dir] != default_key_dir) and File.exist?(default_key_dir)
506
+ key_dirs_tried << default_key_dir
507
+ public_keys = Dir.glob(File.join(default_key_dir, '*'))
508
+ end
509
+
510
+ if public_keys.empty?
511
+ # try path to GPG keys for SIMP 6.0
512
+ old_key_dir = File.join(@src_dir, 'assets', 'simp-gpgkeys', 'GPGKEYS')
513
+ if File.exist?(old_key_dir)
514
+ key_dirs_tried << old_key_dir
515
+ public_keys = Dir.glob(File.join(old_key_dir, '*'))
516
+ end
517
+ end
518
+
519
+ if public_keys.empty?
520
+ $stderr.puts "pkg:checksig: Warning no GPG keys found in #{key_dirs_tried}"
521
+ end
522
+ end
571
523
  public_keys += Dir.glob(File.join(@build_dir, 'build_keys', '*', 'RPM-GPG-KEY*'))
572
524
 
573
525
  # Only import thngs that look like GPG keys...
@@ -728,94 +680,271 @@ protect=1
728
680
  end
729
681
  end
730
682
 
683
+ desc <<-EOM
684
+ Print published status of all project RPMs
685
+ EOM
686
+ task :check_published => [:prep] do |t,args|
687
+ begin
688
+ yum_helper = Simp::YUM.new(
689
+ Simp::YUM.generate_yum_conf(File.join(@distro_build_dir, 'yum_data')),
690
+ ENV.fetch('SIMP_YUM_makecache','yes') == 'yes')
691
+ rescue Simp::YUM::Error
692
+ end
693
+
694
+ Parallel.map(
695
+ # Allow for shell globs
696
+ Array(@build_dirs.values).flatten.sort,
697
+ :in_processes => 1
698
+ ) do |dir|
699
+ fail("Could not find directory #{dir}") unless Dir.exist?(dir)
700
+
701
+ require_rebuild?(dir, yum_helper, { :verbose => true, :check_git => true, :prefix => '' })
702
+ end
703
+ end
704
+
731
705
  ##############################################################################
732
706
  # Helper methods
733
707
  ##############################################################################
734
708
 
709
+ # Generate a random string suitable for a rake task namespace
710
+ #
711
+ # This is used as a workaround for Parallelization
712
+ def generate_namespace
713
+ return (0...24).map{ (65 + rand(26)).chr }.join.downcase
714
+ end
715
+
716
+ # Check and see if 'dir' requires a rebuild based on published packages
717
+ #
718
+ # If 'fetch' is true => Download the RPM
719
+ # If 'verbose' is true => Print helpful information to stderr
720
+ # If 'check_git' is true => Print the git tag status if 'verbose' is true
721
+ # 'prefix' is used to prepend verbose messages
722
+ #
723
+ # FIXME
724
+ # - Method is too long
725
+ # - Method needs to be passed in class variables (@xxx) so that it
726
+ # can be pulled out into a library that is easily unit-testable
727
+ def require_rebuild?(dir, yum_helper, opts={ :unique_namespace => generate_namespace, :fetch => false, :verbose => @verbose, :check_git => false, :prefix => '' })
728
+ result = false
729
+
730
+
731
+ rpm_dependency_file = File.join(@base_dir, 'build', 'rpm', 'dependencies.yaml')
732
+
733
+ if File.exist?(rpm_dependency_file)
734
+ rpm_metadata = YAML.load(File.read(rpm_dependency_file))
735
+ end
736
+
737
+ Dir.chdir(dir) do
738
+ if File.exist?('metadata.json')
739
+ # Generate RPM metadata files
740
+ # - 'build/rpm_metadata/requires' file containing RPM
741
+ # dependency/obsoletes information from the
742
+ # 'dependencies.yaml' and the module's
743
+ # 'metadata.json'; always created
744
+ # - 'build/rpm_metadata/release' file containing RPM
745
+ # release qualifier from the 'dependencies.yaml';
746
+ # only created if release qualifier if specified in
747
+ # the 'dependencies.yaml'
748
+ Simp::Rake::Build::RpmDeps::generate_rpm_meta_files(dir, rpm_metadata) if rpm_metadata
749
+
750
+ new_rpm = Simp::Rake::Pkg.new(Dir.pwd, opts[:unique_namespace], @simp_version)
751
+ new_rpm_info = Simp::RPM.new(new_rpm.spec_file)
752
+ else
753
+ spec_file = Dir.glob(File.join('build', '*.spec'))
754
+ fail("No spec file found in #{dir}/build") if spec_file.empty?
755
+ new_rpm_info = Simp::RPM.new(spec_file.first)
756
+ end
757
+
758
+ if opts[:check_git]
759
+ require_tag = false
760
+
761
+ #FIXME The check below is insufficient. See logic in compare_latest_tag,
762
+ # which does a git diff between files checked out and latest tag to see
763
+ # if any changes to mission-relevant files have been made and if the
764
+ # version has been bumped, when such changes have been made.
765
+ #
766
+ # We remove any leading 'v' chars since some external projects use them
767
+ latest_tag = %x(git describe --abbrev=0 --tags 2>/dev/null).strip.gsub(/^v/,'')
768
+
769
+ # Legacy munge
770
+ # We remove any leading 'simp-', leading 'simp6.0.0-', or trailing
771
+ # '-post1' strings used previously for some projects. This munge
772
+ # logic can be remove in SIMP 7.
773
+ latest_tag.gsub!(/^simp-|^simp6.0.0-|-post1$/,'')
774
+
775
+ begin
776
+ rpm_version = Gem::Version.new(new_rpm_info.version)
777
+ rescue ArgumentError
778
+ $stderr.puts ">>#{new_rpm_info.basename}: Could not determine RPM version"
779
+ end
780
+
781
+ begin
782
+ if latest_tag.empty?
783
+ require_tag = true
784
+ else
785
+ latest_tag_version = Gem::Version.new(latest_tag)
786
+ end
787
+ rescue ArgumentError
788
+ $stderr.puts ">>#{new_rpm_info.basename}: Invalid git tag version '#{latest_tag}' "
789
+ end
790
+
791
+ if rpm_version && latest_tag_version
792
+ if rpm_version > latest_tag_version
793
+ require_tag = true
794
+ end
795
+ end
796
+
797
+ if opts[:verbose] && require_tag
798
+ $stderr.puts "#{opts[:prefix]}Git Release Tag Required: #{new_rpm_info.basename} #{latest_tag} => #{new_rpm_info.version}"
799
+ end
800
+ end
801
+
802
+ # Pull down any newer versions of the target RPM if we've been
803
+ # given a yum_helper
804
+ #
805
+ # Just build from scratch if something goes wrong
806
+ if yum_helper
807
+ # Most RPM spec files generate a single package, but we have
808
+ # a handful that generate multiple (sub-)packages
809
+ new_rpm_info.packages.each do |package|
810
+ begin
811
+ published_rpm = yum_helper.available_package(package)
812
+
813
+ if published_rpm
814
+ if new_rpm_info.package_newer?(package, published_rpm)
815
+ if opts[:verbose]
816
+ $stderr.puts "#{opts[:prefix]}RPM Publish Required: #{published_rpm} => #{new_rpm_info.rpm_name(package)}"
817
+
818
+ end
819
+ result = true
820
+ else
821
+ $stderr.puts "#{opts[:prefix]}Found Existing Remote RPM: #{published_rpm}" if opts[:verbose]
822
+ if opts[:fetch]
823
+ # Download remote RPM, unless already downloaded it.
824
+ if File.exist?(File.join('dist', published_rpm))
825
+ $stderr.puts "#{opts[:prefix]}#{published_rpm} previously downloaded" if opts[:verbose]
826
+ else
827
+ # We know the package exists. So in a brute-force fashion,
828
+ # we're going to retry a couple of times.
829
+ # (Real fix is for user to update retry and timeout parameters
830
+ # in their yum config).
831
+ tries = ENV.fetch('SIMP_YUM_retries','3').to_i
832
+ begin
833
+ yum_helper.download("#{package}", :target_dir => 'dist')
834
+ $stderr.puts "#{opts[:prefix]}Downloaded #{published_rpm}" if opts[:verbose]
835
+ rescue Simp::YUM::Error
836
+ tries -= 1
837
+ if tries > 0
838
+ retry
839
+ else
840
+ $stderr.puts ">>Failed to download existing remote RPM: #{published_rpm}. RPM will be locally rebuilt"
841
+ result = true
842
+ end
843
+ end
844
+ end
845
+ end
846
+ end
847
+ else
848
+ if opts[:verbose]
849
+ $stderr.puts "#{opts[:prefix]}RPM Publish Required: #{new_rpm_info.rpm_name(package)}"
850
+ end
851
+ result = true
852
+ end
853
+ rescue Simp::YUM::Error => e
854
+ $stderr.puts e if opts[:verbose]
855
+ end
856
+ end
857
+ elsif opts[:verbose]
858
+ $stderr.puts '>>Issue creating YUM configuration. Packages will be locally generated.'
859
+
860
+ result = true
861
+ end
862
+ end
863
+
864
+ return result
865
+ end
866
+
735
867
  # Takes a list of directories to hop into and perform builds within
736
- # Needs to be passed the chroot path as well
737
868
  #
738
869
  # The task must be passed so that we can output the calling name in the
739
870
  # status bar.
740
- def build(chroot,dirs,task,add_to_autoreq=true,snapshot_release=false)
741
- validate_in_mock_group?
871
+ def build(dirs, task, rebuild_for_arch=false, remake_yum_cache = false)
742
872
  _verbose = ENV.fetch('SIMP_PKG_verbose','no') == 'yes'
873
+ dbg_prefix = ' ' # prefix for debug messages
743
874
 
744
- rpm_dependency_file = File.join(@base_dir, 'build', 'rpm',
745
- 'dependencies.yaml')
746
-
747
- if File.exist?(rpm_dependency_file)
748
- rpm_metadata = YAML.load(File.read(rpm_dependency_file))
875
+ begin
876
+ yum_helper = Simp::YUM.new(
877
+ Simp::YUM.generate_yum_conf(File.join(@distro_build_dir, 'yum_data'))
878
+ )
879
+ rescue Simp::YUM::Error
749
880
  end
750
881
 
751
- metadata = Parallel.map(
882
+ Parallel.map(
752
883
  # Allow for shell globs
753
884
  Array(dirs),
754
885
  :in_processes => get_cpu_limit,
755
886
  :progress => task.name
756
887
  ) do |dir|
757
- result = []
758
-
759
888
  fail("Could not find directory #{dir}") unless Dir.exist?(dir)
760
889
 
761
890
  Dir.chdir(dir) do
762
891
  built_rpm = false
763
- unique_build = (get_cpu_limit != 1).to_s
764
892
 
765
893
  if _verbose
766
- $stderr.puts("Running 'rake pkg:rpm' on #{File.basename(dir)}")
894
+ $stderr.puts("\nPackaging #{File.basename(dir)}")
767
895
  end
768
896
 
769
897
  # We're building a module, override anything down there
770
898
  if File.exist?('metadata.json')
771
-
772
- # Generate RPM metadata files
773
- # - 'build/rpm_metadata/requires' file containing RPM
774
- # dependency/obsoletes information from the
775
- # 'dependencies.yaml' and the module's
776
- # 'metadata.json'; always created
777
- # - 'build/rpm_metadata/release' file containing RPM
778
- # release qualifier from the 'dependencies.yaml';
779
- # only created if release qualifier if specified in
780
- # the 'dependencies.yaml'
781
- Simp::Rake::Build::RpmDeps::generate_rpm_meta_files(dir, rpm_metadata)
782
-
783
- unique_namespace = (0...24).map{ (65 + rand(26)).chr }.join.downcase
784
-
785
- Simp::Rake::Pkg.new(Dir.pwd, nil, unique_namespace, @simp_version)
786
-
787
- Rake::Task["#{unique_namespace}:pkg:rpm"].invoke(chroot, unique_build, snapshot_release)
899
+ unique_namespace = generate_namespace
900
+ if require_rebuild?(dir, yum_helper, { :unique_namespace => unique_namespace, :fetch => true, :verbose => _verbose, :prefix => dbg_prefix})
901
+ $stderr.puts("#{dbg_prefix}Running 'rake pkg:rpm' on #{File.basename(dir)}") if _verbose
902
+ Rake::Task["#{unique_namespace}:pkg:rpm"].invoke
903
+ else
904
+ # Record metadata for the downloaded RPM
905
+ Simp::RPM::create_rpm_build_metadata(File.expand_path(dir))
906
+ end
788
907
 
789
908
  built_rpm = true
790
909
 
791
910
  # We're building one of the extra assets and should honor its Rakefile
911
+ # and RPM spec file.
792
912
  elsif File.exist?('Rakefile')
913
+ if require_rebuild?(dir, yum_helper, { :fetch => true, :verbose => _verbose, :prefix => dbg_prefix })
914
+ $stderr.puts("#{dbg_prefix}Running 'rake pkg:rpm' in #{File.basename(dir)}") if _verbose
915
+ rake_flags = Rake.application.options.trace ? '--trace' : ''
916
+ cmd = %{SIMP_BUILD_version=#{@simp_version} rake pkg:rpm #{rake_flags} 2>&1}
793
917
 
794
- rake_flags = Rake.application.options.trace ? '--trace' : ''
795
-
796
- cmd = %{SIMP_BUILD_version=#{@simp_version} rake pkg:rpm[#{chroot},#{unique_build},#{snapshot_release}] #{rake_flags} 2>&1}
918
+ build_success = true
919
+ begin
920
+ ::Bundler.with_clean_env do
921
+ %x{#{cmd}}
922
+ build_success = $?.success?
923
+ end
797
924
 
798
- build_success = true
799
- begin
800
- ::Bundler.with_clean_env do
801
- %x{#{cmd}}
802
- build_success = $?.success?
925
+ built_rpm = true
926
+ rescue
927
+ build_success = false
803
928
  end
804
929
 
805
- built_rpm = true
806
- rescue
807
- build_success = false
808
- end
930
+ unless build_success
931
+ if _verbose
932
+ $stderr.puts("First 'rake pkg:rpm' attempt for #{dir} failed, running bundle and trying again.")
933
+ end
809
934
 
810
- unless build_success
811
- if _verbose
812
- $stderr.puts("First 'rake pkg:rpm' attempt failed, running bundle and trying again.")
813
- end
935
+ ::Bundler.with_clean_env do
936
+ %x{bundle install --with development}
937
+ output = %x{#{cmd} 2>&1}
814
938
 
815
- ::Bundler.with_clean_env do
816
- %x{bundle install --with development}
817
- %x{#{cmd}}
939
+ unless $?.success?
940
+ raise("Error in #{dir} running #{cmd}\n#{output}")
941
+ end
942
+ end
818
943
  end
944
+ else
945
+ # Record metadata for the downloaded RPM
946
+ Simp::RPM::create_rpm_build_metadata(File.expand_path(dir))
947
+ built_rpm = true
819
948
  end
820
949
  else
821
950
  puts "Warning: '#{dir}' could not be built via Rake"
@@ -823,8 +952,7 @@ protect=1
823
952
 
824
953
  if built_rpm
825
954
  tarballs = Dir.glob('dist/*.tar.gz')
826
- srpms = Dir.glob('dist/*.src.rpm')
827
- rpms = (Dir.glob('dist/*.rpm') - srpms)
955
+ rpms = Dir.glob('dist/*.rpm').delete_if{|x| x =~ %r(\.src\.rpm$)}
828
956
 
829
957
  # Not all items generate tarballs
830
958
  tarballs.each do |pkg|
@@ -832,74 +960,14 @@ protect=1
832
960
  raise("Empty Tarball '#{pkg}' generated for #{dir}")
833
961
  end
834
962
  end
835
- raise("No SRPMs generated for #{dir}") if srpms.empty?
836
- raise("No RPMs generated for #{dir}") if rpms.empty?
837
-
838
- last_build = {
839
- 'git_hash' => %x{git show-ref --head HEAD}.chomp,
840
- 'rpms' => {}
841
- }
842
-
843
- # Glob all generated rpms, and add their metadata to a result array.
844
- rpms.each do |rpm|
845
- # get_info from each generated rpm, not the spec file, so macros in the
846
- # metadata have already been resolved in the mock chroot.
847
- metadata = Simp::RPM.get_info(rpm)
848
-
849
- if File.exist?('build/package_metadata.yaml')
850
- metadata.merge!(YAML.load_file('build/package_metadata.yaml'))
851
- end
852
-
853
- rpm_stat = File.stat(rpm)
854
-
855
- last_build['rpms'][rpm] = {
856
- 'metadata' => metadata,
857
- 'size' => rpm_stat.size
858
- }
859
963
 
860
- result << metadata
861
- end
862
-
863
- File.open('dist/.last_build_metadata', 'w') do |fh|
864
- fh.puts(last_build.to_yaml)
865
- end
964
+ raise("No RPMs generated for #{dir}") if rpms.empty?
866
965
  end
867
966
 
868
967
  if _verbose
869
- $stderr.puts("Finshed 'rake pkg:rpm' on #{File.basename(dir)}")
870
- end
871
- end
872
-
873
- result
874
- end
875
-
876
- metadata.each do |mod|
877
- # Each module could generate multiple rpms, each with its own metadata.
878
- # Iterate over them to add all built rpms to autorequires.
879
- mod.each do |module_pkginfo|
880
- next unless (module_pkginfo && module_pkginfo.is_a?(Hash))
881
-
882
- # Set up the autorequires
883
- if add_to_autoreq
884
- # Register the package with the autorequires
885
- mode = 'r+'
886
- mode = 'w+' unless File.exist?("#{@src_dir}/build/autorequires")
887
- autoreq_fh = File.open("#{@src_dir}/build/autorequires",mode)
888
-
889
- begin
890
- # Reads the autorequires file, then empties it
891
- autorequires = []
892
- autorequires += autoreq_fh.read.split("\n")
893
- autoreq_fh.rewind
894
- autoreq_fh.truncate(0)
895
-
896
- # The SIMP Rakefile expects the autorequires to be in this format.
897
- autorequires << "#{module_pkginfo[:name]} #{module_pkginfo[:version]} #{module_pkginfo[:release]}"
898
- autoreq_fh.puts(autorequires.sort.uniq.join("\n"))
899
- ensure
900
- autoreq_fh.flush
901
- autoreq_fh.close
902
- end
968
+ rpms = Dir.glob('dist/*.rpm')
969
+ # $stderr.puts("#{dbg_prefix}RPMS: #{rpms.join("\n#{dbg_prefix} ")}")
970
+ $stderr.puts("Finished #{File.basename(dir)}")
903
971
  end
904
972
  end
905
973
  end