mswin-build 1.1.2 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 04dd66454d1375114da0bdc7c13e8caade4177d5
4
- data.tar.gz: d042c5b0f15c2e0434d5542c7387eedb87b313ba
3
+ metadata.gz: 3e3caa55131f9d640fb35fadfc93c7b53562d1b6
4
+ data.tar.gz: fc4f25f04c6fc563025922ae88155294221d229e
5
5
  SHA512:
6
- metadata.gz: 3afae83b34dba29b69425e3452f2eda1da721ab91ebae7d635a76013436bac846bfb7846378c3980a930e47f1a0cb0b7cf89cc3c249a75c34ff59f43d8cf03ec
7
- data.tar.gz: 1333f4d3a83d48fe9c7a6c497852193455e867600c24b31eb694c0def0a6c65784b060a89dd9e3084b794b8280511a125955cc8f648d6e609cd83d632ff5fa08
6
+ metadata.gz: 19093b7cd32b3583125ffbd81c7feceaac6d1e7b5a79105a7e6089615da62e045d2c40102544db76c09471059599c4e6f1ebf16cc59141116630b1b4822ad2f4
7
+ data.tar.gz: 301321b2a7e5fa1cb32749610ac4d9805db209a0ebc47164d0e7013e17fb832a39b241807f2b7ede812dc4037ad7ebb977cc40af7c40ec5432ab7cae648c9862
@@ -32,6 +32,7 @@ rescue RuntimeError => ex
32
32
  puts opt.help
33
33
  exit 1
34
34
  end
35
+ STDOUT.sync = true if $debug
35
36
 
36
37
  loop do
37
38
  ARGV.each do |target|
@@ -83,6 +83,7 @@ module MswinBuild
83
83
  ENV[name] = value
84
84
  end
85
85
  files = []
86
+ @fails = []
86
87
  Dir.mktmpdir("mswin-build", @config["tmpdir"]) do |tmpdir|
87
88
  files << baseinfo(tmpdir)
88
89
  files << checkout(tmpdir)
@@ -109,14 +110,23 @@ module MswinBuild
109
110
  files << rubyspec(tmpdir)
110
111
  end
111
112
  files << end_(tmpdir)
112
- logfile = gather_log(files, tmpdir)
113
+ logfile, failfile = gather_log(files, tmpdir)
114
+ files.each do |io|
115
+ if io
116
+ io.close
117
+ File.unlink(io.path)
118
+ end
119
+ end
113
120
  difffile = diff(tmpdir, logfile)
114
121
  logfile = gzip(logfile)
115
122
  @data[:compressed_loghtml_relpath] = File.join("log", File.basename(logfile))
116
123
  difffile = gzip(difffile)
117
124
  @data[:compressed_diffhtml_relpath] = File.join("log", File.basename(difffile))
118
- add_recent(logfile)
119
- add_summary(logfile)
125
+ failfile = gzip(failfile)
126
+ @data[:compressed_failhtml_relpath] = File.join("log", File.basename(failfile))
127
+
128
+ add_recent(logfile, difffile, failfile)
129
+ add_summary(logfile, difffile, failfile)
120
130
 
121
131
  MswinBuild.run_upload_hooks
122
132
  end
@@ -254,6 +264,7 @@ module MswinBuild
254
264
  end
255
265
 
256
266
  if status.nil? || !status.success?
267
+ @fails << io
257
268
  io.puts "exit #{status.to_i}" unless status.nil?
258
269
  io.puts "failed(#{name})"
259
270
  @title << "failed(#{name})" if check_retval || status.nil?
@@ -266,6 +277,7 @@ module MswinBuild
266
277
  end
267
278
  end
268
279
  rescue Timeout::Error
280
+ @fails << io
269
281
  io.puts
270
282
  io.printf "|output interval exceeds %.1f seconds. (CommandTimeout)", @config["timeout"][name] || @config["timeout"]["default"]
271
283
  io.puts $!.backtrace.join("\n| ")
@@ -292,7 +304,7 @@ module MswinBuild
292
304
  end
293
305
  anchor = u name.to_s.tr('_', '-')
294
306
  text = h name.to_s.tr('_', '-')
295
- io.puts %'<a name="#{anchor}">== #{text}</a> \# #{h Time.now.iso8601}'
307
+ io.puts %'<a name="#{anchor}">== #{text} \# #{h Time.now.iso8601}</a>'
296
308
  @links[name] = [anchor, text]
297
309
  end
298
310
 
@@ -309,6 +321,10 @@ module MswinBuild
309
321
  end
310
322
  end
311
323
 
324
+ def define_failure_start_pattern(io, *patterns)
325
+ io.instance_variable_set(:@failure_start_patterns, patterns)
326
+ end
327
+
312
328
  define_buildmethod(:baseinfo) do |io, tmpdir|
313
329
  @start_time = Time.now
314
330
  @data[:start_time] = @start_time.dup.utc.strftime('%Y%m%dT%H%M%SZ')
@@ -397,8 +413,10 @@ module MswinBuild
397
413
  end
398
414
 
399
415
  define_buildmethod(:btest) do |io, tmpdir|
416
+ define_failure_start_pattern(io, /: $/, /:\d+:in `/)
400
417
  ret = do_command(io, "btest", 'nmake -l "OPTS=-v -q" btest', true, false)
401
418
  if !ret && !ret.nil?
419
+ @fails << io unless @fails.include?(io)
402
420
  io.rewind
403
421
  if %r'^FAIL (\d+)/\d+' =~ io.read
404
422
  @title << "#{$1}BFail"
@@ -414,6 +432,7 @@ module MswinBuild
414
432
  define_buildmethod(:testrb) do |io, tmpdir|
415
433
  ret = do_command(io, "test.rb", "./miniruby sample/test.rb", true, false)
416
434
  if !ret && !ret.nil?
435
+ @fails << io unless @fails.include?(io)
417
436
  io.rewind
418
437
  if %r'^not ok/test: \d+ failed (\d+)' =~ io.read
419
438
  @title << "#{$1}NotOK"
@@ -470,16 +489,19 @@ module MswinBuild
470
489
  end
471
490
 
472
491
  define_buildmethod(:test_all) do |io, tmpdir|
492
+ define_failure_start_pattern(io, /\A *\d+\) (Failure|Error)/, /\A\d+ tests, \d+ assertions, [1-9]\d* failures, \d+ errors/, /\A\d+ tests, \d+ assertions, \d+ failures, [1-9]\d* errors/, /:\d+:in `/)
473
493
  ret = do_command(io, "test-all", "nmake -l TESTS=-v RUBYOPT=-w test-all", true, false, nil)
474
494
  if !ret && !ret.nil?
475
495
  io.rewind
476
496
  if %r'^\d+ tests, \d+ assertions, (\d+) failures, (\d+) errors, (\d+) skips' =~ io.read
477
497
  @title << "#{$1}F#{$2}E"
478
498
  if $1.to_i + $2.to_i > 0
499
+ @fails << io unless @fails.include?(io)
479
500
  @data["failure_test-all"] = "#{$1}F#{$2}E"
480
501
  @data[:result] = "failure"
481
502
  end
482
503
  else
504
+ @fails << io unless @fails.include?(io)
483
505
  @title << "failed(test-all)"
484
506
  @data["failure_test-all"] = "failed"
485
507
  @data[:result] = "failure"
@@ -488,6 +510,7 @@ module MswinBuild
488
510
  end
489
511
 
490
512
  define_buildmethod(:rubyspec) do |io, tmpdir|
513
+ define_failure_start_pattern(io, /\A1\)\n\z/, /:\d+:in `/)
491
514
  if ruby_version >= "2.5.0"
492
515
  ret = do_command(io, "rubyspec", 'nmake -l MSPECOPT="-V -f s" test-rubyspec', true, false, nil)
493
516
  if !ret && !ret.nil?
@@ -495,10 +518,12 @@ module MswinBuild
495
518
  if /^\d+ files?, \d+ examples?, \d+ expectations?, (\d+) failures?, (\d+) errors?, \d+ tagged/ =~ io.read
496
519
  @title << "rubyspec:#{$1}F#{$2}E"
497
520
  if $1.to_i + $2.to_i > 0
521
+ @fails << io unless @fails.include?(io)
498
522
  @data["failure_rubyspec"] = "#{$1}F#{$2}E"
499
523
  @data[:result] = "failure"
500
524
  end
501
525
  else
526
+ @fails << io unless @fails.include?(io)
502
527
  @title << "failed(rubyspec)"
503
528
  @data["failure_rubyspec"] = "failed"
504
529
  @data[:result] = "failure"
@@ -569,30 +594,51 @@ module MswinBuild
569
594
  end
570
595
 
571
596
  def gather_log(files, tmpdir)
572
- logdir = File.join(@config["logdir"], "log")
573
- FileUtils.mkdir_p(logdir)
574
- logfile = File.join(logdir, @data[:start_time] + '.log.html')
575
597
  warns = 0
576
598
  revision = nil
577
- open(File.join(tmpdir, "gathered"), "w") do |out|
578
- files.each_with_index do |io, i|
599
+ open(File.join(tmpdir, "gathered"), "wb") do |out|
600
+ files.each do |io|
579
601
  next unless io
580
602
  io.reopen(io.path, "r", encoding: "ascii-8bit")
581
- begin
582
- io.each_line do |line|
583
- line = h(line) unless /^<a / =~ line
584
- out.write line
585
- warns += line.scan(/warn/i).length
586
- if File.basename(io.path) == "checkout" && /^(?:SVN )?Last Changed Rev: (\d+)$/ =~ line
587
- revision = $1
588
- end
603
+ io.each_line do |line|
604
+ line = h(line) unless /^<a / =~ line
605
+ out.write line
606
+ warns += line.scan(/warn/i).length
607
+ if File.basename(io.path) == "checkout" && /^(?:SVN )?Last Changed Rev: (\d+)$/ =~ line
608
+ revision = $1
589
609
  end
590
- ensure
591
- io.close
592
- File.unlink(io.path) rescue nil
593
610
  end
594
611
  end
595
612
  end
613
+
614
+ open(File.join(tmpdir, "failed"), "wb") do |out|
615
+ if @fails.empty?
616
+ out.puts "No failures"
617
+ break
618
+ end
619
+
620
+ @fails.each do |io|
621
+ io.rewind
622
+ lines = io.read.lines
623
+ out.puts lines.shift
624
+ total = lines.size
625
+ patterns = io.instance_variable_defined?(:@failure_start_patterns) ? io.instance_variable_get(:@failure_start_patterns) : []
626
+ patterns << /\[BUG\]/
627
+ start = [0, total - 10].max
628
+ lines.each_with_index do |line, i|
629
+ if patterns.find{|pat| pat =~ line}
630
+ start = i
631
+ break
632
+ end
633
+ end
634
+ start = [0, start - 10].max # show 10 lines before the start point
635
+ out.puts "...(snip #{start} lines)..." if start > 0
636
+ lines.last(total - start).each do |line|
637
+ out.write h(line)
638
+ end
639
+ end
640
+ end
641
+
596
642
  title = @title[0, 2]
597
643
  @data[:warn] = "#{warns}W"
598
644
  if warns > 0
@@ -623,25 +669,46 @@ module MswinBuild
623
669
  title << v
624
670
  end
625
671
  end
672
+
626
673
  @data[:title] = title.join(' ')
627
- open(logfile, "w") do |out|
674
+
675
+ logdir = File.join(@config["logdir"], "log")
676
+ FileUtils.mkdir_p(logdir)
677
+ logfile = File.join(logdir, @data[:start_time] + '.log.html')
678
+ failfile = File.join(logdir, @data[:start_time] + '.fail.html')
679
+ open(logfile, "wb") do |out|
628
680
  header(out)
681
+ out.puts " <p><a href=\"#{File.basename(logfile) + '.gz'}\">#{@data[:start_time]}</a>(<a href=\"#{File.basename(failfile) + '.gz'}\">failure</a>)</p>"
629
682
  out.puts " <ul>"
630
683
  @links.each_value do |anchor, text, result = nil|
631
684
  out.puts %' <li><a href="\##{anchor}">#{text}</a>#{" #{result}" if result}</li>'
632
685
  end
633
686
  out.puts " </ul>"
634
687
  out.puts " <pre>"
635
- out.write IO.read(File.join(tmpdir, "gathered"))
688
+ out.write insert_href(IO.read(File.join(tmpdir, "gathered"), encoding: 'ascii-8bit'), File.basename(logfile) + ".gz")
636
689
  out.puts " </pre>"
637
690
  footer(out)
638
691
  end
639
- logfile
692
+
693
+ open(failfile, "wb") do |out|
694
+ header(out)
695
+ out.puts " <ul>"
696
+ @links.each_value do |anchor, text, result = nil|
697
+ out.puts %' <li><a href="\##{anchor}">#{text}</a> #{result}</li>' if result
698
+ end
699
+ out.puts " </ul>"
700
+ out.puts " <pre>"
701
+ out.write insert_href(IO.read(File.join(tmpdir, "failed"), encoding: 'ascii-8bit'), File.basename(failfile) + ".gz", File.basename(logfile) + ".gz")
702
+ out.puts " </pre>"
703
+ footer(out)
704
+ end
705
+
706
+ return logfile, failfile
640
707
  end
641
708
 
642
709
  def diff(tmpdir, logfile)
643
710
  filename = logfile.sub(/\.log/, ".diff")
644
- open(filename, "w") do |out|
711
+ open(filename, "wb") do |out|
645
712
  header(out)
646
713
  out.puts %'<p>Skipped. See the <a href="#{u File.basename(logfile)}.gz">full build log</a>.</p>'
647
714
  footer(out)
@@ -654,15 +721,19 @@ module MswinBuild
654
721
  file + ".gz"
655
722
  end
656
723
 
657
- def add_recent(logfile)
658
- add_recent_summary(logfile, :recent)
724
+ def insert_href(html, file, orig = nil)
725
+ html.gsub(/^<a name="(.+?)">(== .*)$/, "<a name=\"\\1\" href=\"#{file}\#\\1\">\\2#{%' (<a href=\"#{orig}\#\\1\">full</a>)' if orig}")
726
+ end
727
+
728
+ def add_recent(logfile, difffile, failfile)
729
+ add_recent_summary(logfile, difffile, failfile, :recent)
659
730
  end
660
731
 
661
- def add_summary(logfile)
662
- add_recent_summary(logfile, :summary)
732
+ def add_summary(logfile, difffile, failfile)
733
+ add_recent_summary(logfile, difffile, failfile, :summary)
663
734
  end
664
735
 
665
- def add_recent_summary(logfile, mode)
736
+ def add_recent_summary(logfile, difffile, failfile, mode)
666
737
  if mode == :recent
667
738
  filename = File.join(@config["logdir"], "recent.html")
668
739
  else
@@ -679,14 +750,14 @@ module MswinBuild
679
750
 
680
751
  title = @title.join(' ')
681
752
  time = @data[:start_time]
682
- latest = %'<a href="log/#{u time}.log.html.gz" name="#{u time}">#{h time}</a> #{h title} (<a href="log/#{u time}.diff.html.gz">#{@diff ? h(@diff) : "no diff"}</a>)<br>'
753
+ latest = %'<a href="log/#{File.basename(logfile)}" name="#{u time}">#{h time}</a>(<a href="log/#{File.basename(failfile)}">failure</a>) #{h title} (<a href="log/#{File.basename(difffile)}">#{@diff ? h(@diff) : "no diff"}</a>)<br>'
683
754
  if mode == :recent
684
755
  old = old[0..99]
685
756
  old.unshift(latest)
686
757
  else
687
758
  old.push(latest)
688
759
  end
689
- open(filename, "w") do |f|
760
+ open(filename, "wb") do |f|
690
761
  f.print <<-EOH
691
762
  <html>
692
763
  <head>
@@ -739,7 +810,7 @@ module MswinBuild
739
810
  }.join("\t")
740
811
  old.unshift(latest)
741
812
 
742
- open(filename, "w") do |f|
813
+ open(filename, "wb") do |f|
743
814
  old.take(100).each do |line|
744
815
  f.puts line
745
816
  end
@@ -1,3 +1,3 @@
1
1
  module MswinBuild
2
- VERSION = "1.1.2"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -2,6 +2,7 @@ require "fileutils"
2
2
  require "tmpdir"
3
3
  require "tempfile"
4
4
  require "test/unit"
5
+ require "zlib"
5
6
  require "mswin-build/builder.rb"
6
7
 
7
8
  module ProcessMock
@@ -71,7 +72,7 @@ env:
71
72
 
72
73
  def teardown
73
74
  @yaml.close!
74
- FileUtils.rm_r(@tmpdir)
75
+ FileUtils.rm_rf(@tmpdir)
75
76
  end
76
77
 
77
78
  def run_builder(**opt, &blk)
@@ -128,6 +129,7 @@ env:
128
129
  files = Dir.glob(File.join(@tmpdir, "log", "*"))
129
130
  assert files.reject! {|e| /\.log\.html\.gz\z/ =~ e}
130
131
  assert files.reject! {|e| /\.diff\.html\.gz\z/ =~ e}
132
+ assert files.reject! {|e| /\.fail\.html\.gz\z/ =~ e}
131
133
  assert_empty files
132
134
  end
133
135
 
@@ -166,7 +168,7 @@ env:
166
168
 
167
169
  recent = File.read(File.join(@tmpdir, "recent.html"))
168
170
  assert_match(/\bsuccess\b/, recent)
169
- assert_match(/^<a href="[^"]+" name="[^"]+">[^<]+<\/a> r12345 /, recent)
171
+ assert_match(/^<a href="[^"]+" name="[^"]+">[^<]+<\/a>\(<a href="[^"]+">failure<\/a>\) r12345 /, recent) #"
170
172
  assert_not_match(/\bfailed\b/, recent)
171
173
  assert_not_match(/\bskipped\b/, recent)
172
174
 
@@ -196,7 +198,7 @@ env:
196
198
 
197
199
  recent = File.read(File.join(@tmpdir, "recent.html"))
198
200
  assert_match(/\bsuccess\b/, recent)
199
- assert_match(/^<a href="[^"]+" name="[^"]+">[^<]+<\/a> r12345 /, recent)
201
+ assert_match(/^<a href="[^"]+" name="[^"]+">[^<]+<\/a>\(<a href="[^"]+">failure<\/a>\) r12345 /, recent) #"
200
202
  assert_not_match(/\bfailed\b/, recent)
201
203
 
202
204
  recent = File.read(File.join(@tmpdir, "recent.ltsv"))
@@ -204,6 +206,26 @@ env:
204
206
  assert_match(/\bruby_rev:r12345\b/, recent)
205
207
  assert_match(/"http\\x3A\/\/[^:]+":12345\b/, recent)
206
208
  assert_not_match(/\btitle:[^\t]*\b(failed|success|\dE\dF)\b/, recent)
209
+
210
+ logs = Dir.glob(File.join(@tmpdir, "log", "*.log.html.gz"))
211
+ assert logs.count > 0, "some logs must be written"
212
+ logs.each do |log|
213
+ fn = Regexp.escape(File.basename(log))
214
+ fn2 = fn.sub(/log/, "fail")
215
+ Zlib::GzipReader.open(log) do |gz|
216
+ html = gz.read
217
+ assert_match(/<p><a href="#{fn}">[^<]+<\/a>\(<a href="#{fn2}">failure<\/a>\)<\/p>/, html)
218
+ assert_match(/^<a name="(.+?)" href="#{fn}\#\1">== /, html)
219
+ end
220
+ end
221
+
222
+ fails = Dir.glob(File.join(@tmpdir, "log", "*.fail.html.gz"))
223
+ assert fails.count > 0, "some fail htmls must be written"
224
+ fails.each do |log|
225
+ Zlib::GzipReader.open(log) do |gz|
226
+ assert_match(/^No failures$/, gz.read)
227
+ end
228
+ end
207
229
  end
208
230
 
209
231
  def test_run_btest_failure
@@ -233,6 +255,16 @@ env:
233
255
  assert_match(/\bfailure_btest:3BFail\b/, recent)
234
256
  assert_match(/\btitle:[^\t]*\b3BFail\b/, recent)
235
257
  assert_not_match(/\btitle:[^\t]*\bfailed\b/, recent)
258
+
259
+ fails = Dir.glob(File.join(@tmpdir, "log", "*.fail.html.gz"))
260
+ assert fails.count > 0, "some fail htmls must be written"
261
+ fails.each do |log|
262
+ fn = Regexp.escape(File.basename(log))
263
+ fn2 = fn.sub(/fail/, "log")
264
+ Zlib::GzipReader.open(log) do |gz|
265
+ assert_match(/^<a name="(btest)" href="#{fn}\#\1">== .*\(<a href="#{fn2}\#\1">full<\/a>\)$/, gz.read)
266
+ end
267
+ end
236
268
  end
237
269
 
238
270
  def test_run_testrb_failure
@@ -262,6 +294,16 @@ env:
262
294
  assert_match(/\bfailure_test.rb:4NotOK\b/, recent)
263
295
  assert_match(/\btitle:[^\t]*\b4NotOK\b/, recent)
264
296
  assert_not_match(/\btitle:[^\t]*\bfailed\b/, recent)
297
+
298
+ fails = Dir.glob(File.join(@tmpdir, "log", "*.fail.html.gz"))
299
+ assert fails.count > 0, "some fail htmls must be written"
300
+ fails.each do |log|
301
+ fn = Regexp.escape(File.basename(log))
302
+ fn2 = fn.sub(/fail/, "log")
303
+ Zlib::GzipReader.open(log) do |gz|
304
+ assert_match(/^<a name="(test\.rb)" href="#{fn}\#\1">== .*\(<a href="#{fn2}\#\1">full<\/a>\)$/, gz.read)
305
+ end
306
+ end
265
307
  end
266
308
 
267
309
  def test_run_test_all_failure
@@ -291,6 +333,16 @@ env:
291
333
  assert_match(/\bfailure_test-all:2F1E\b/, recent)
292
334
  assert_match(/\btitle:[^\t]*\b2F1E\b/, recent)
293
335
  assert_not_match(/\btitle:[^\t]*\bfailed\b/, recent)
336
+
337
+ fails = Dir.glob(File.join(@tmpdir, "log", "*.fail.html.gz"))
338
+ assert fails.count > 0, "some fail htmls must be written"
339
+ fails.each do |log|
340
+ fn = Regexp.escape(File.basename(log))
341
+ fn2 = fn.sub(/fail/, "log")
342
+ Zlib::GzipReader.open(log) do |gz|
343
+ assert_match(/^<a name="(test-all)" href="#{fn}\#\1">== .*\(<a href="#{fn2}\#\1">full<\/a>\)$/, gz.read)
344
+ end
345
+ end
294
346
  end
295
347
 
296
348
  def test_run_timeout
@@ -316,6 +368,16 @@ env:
316
368
  assert_match(/\bresult:failure\b/, recent)
317
369
  assert_match(/\bfailure_test-all:failed\(test-all CommandTimeout\)/, recent)
318
370
  assert_match(/\btitle:[^\t]*\bfailed\(test-all CommandTimeout\)/, recent)
371
+
372
+ fails = Dir.glob(File.join(@tmpdir, "log", "*.fail.html.gz"))
373
+ assert fails.count > 0, "some fail htmls must be written"
374
+ fails.each do |log|
375
+ fn = Regexp.escape(File.basename(log))
376
+ fn2 = fn.sub(/fail/, "log")
377
+ Zlib::GzipReader.open(log) do |gz|
378
+ assert_match(/^<a name="(.+?)" href="#{fn}\#\1">== .*\(<a href="#{fn2}\#\1">full<\/a>\)$/, gz.read)
379
+ end
380
+ end
319
381
  end
320
382
 
321
383
  def test_get_current_revision
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mswin-build
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - U.Nakamura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-20 00:00:00.000000000 Z
11
+ date: 2017-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler