New Upstream Snapshot - ruby-cri

Ready changes

Summary

Merged new upstream version: 2.15.11+git20220108.2.b25555a (was: 2.15.11+git20220108.1.b25555a).

Resulting package

Built on 2023-01-20T09:22 (took 2m50s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-snapshots ruby-cri-docapt install -t fresh-snapshots ruby-cri

Lintian Result

Diff

diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000..430b12a
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,230 @@
+inherit_from: .rubocop_todo.yml
+
+require:
+  - rubocop-minitest
+  - rubocop-rake
+
+AllCops:
+  TargetRubyVersion: 2.5
+  DisplayCopNames: true
+
+Layout/SpaceBeforeBrackets: # (new in 1.7)
+  Enabled: true
+Lint/AmbiguousAssignment: # (new in 1.7)
+  Enabled: true
+Lint/DuplicateBranch: # (new in 1.3)
+  Enabled: true
+Lint/DuplicateRegexpCharacterClassElement: # (new in 1.1)
+  Enabled: true
+Lint/EmptyBlock: # (new in 1.1)
+  Enabled: true
+Lint/EmptyClass: # (new in 1.3)
+  Enabled: true
+Lint/NoReturnInBeginEndBlocks: # (new in 1.2)
+  Enabled: true
+Lint/ToEnumArguments: # (new in 1.1)
+  Enabled: true
+Lint/UnexpectedBlockArity: # (new in 1.5)
+  Enabled: true
+Lint/UnmodifiedReduceAccumulator: # (new in 1.1)
+  Enabled: true
+Style/ArgumentsForwarding: # (new in 1.1)
+  Enabled: true
+Style/CollectionCompact: # (new in 1.2)
+  Enabled: true
+Style/DocumentDynamicEvalDefinition: # (new in 1.1)
+  Enabled: true
+Style/HashExcept: # (new in 1.7)
+  Enabled: true
+Style/NegatedIfElseCondition: # (new in 1.2)
+  Enabled: true
+Style/NilLambda: # (new in 1.3)
+  Enabled: true
+Style/RedundantArgument: # (new in 1.4)
+  Enabled: true
+Style/SwapValues: # (new in 1.1)
+  Enabled: true
+Minitest/AssertInDelta: # (new in 0.10)
+  Enabled: true
+Minitest/AssertionInLifecycleHook: # (new in 0.10)
+  Enabled: true
+Minitest/AssertKindOf: # (new in 0.10)
+  Enabled: true
+Minitest/AssertOutput: # (new in 0.10)
+  Enabled: true
+Minitest/AssertPathExists: # (new in 0.10)
+  Enabled: true
+Minitest/AssertSilent: # (new in 0.10)
+  Enabled: true
+Minitest/LiteralAsActualArgument: # (new in 0.10)
+  Enabled: true
+Minitest/MultipleAssertions: # (new in 0.10)
+  Enabled: true
+Minitest/RefuteInDelta: # (new in 0.10)
+  Enabled: true
+Minitest/RefuteKindOf: # (new in 0.10)
+  Enabled: true
+Minitest/RefutePathExists: # (new in 0.10)
+  Enabled: true
+Minitest/TestMethodName: # (new in 0.10)
+  Enabled: true
+Minitest/UnspecifiedException: # (new in 0.10)
+  Enabled: true
+Gemspec/DateAssignment: # new in 1.10
+  Enabled: true
+Gemspec/RequireMFA: # new in 1.23
+  Enabled: true
+Layout/LineEndStringConcatenationIndentation: # new in 1.18
+  Enabled: true
+Lint/AmbiguousOperatorPrecedence: # new in 1.21
+  Enabled: true
+Lint/AmbiguousRange: # new in 1.19
+  Enabled: true
+Lint/DeprecatedConstants: # new in 1.8
+  Enabled: true
+Lint/EmptyInPattern: # new in 1.16
+  Enabled: true
+Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
+  Enabled: true
+Lint/LambdaWithoutLiteralBlock: # new in 1.8
+  Enabled: true
+Lint/NumberedParameterAssignment: # new in 1.9
+  Enabled: true
+Lint/OrAssignmentToConstant: # new in 1.9
+  Enabled: true
+Lint/RedundantDirGlobSort: # new in 1.8
+  Enabled: true
+Lint/RequireRelativeSelfPath: # new in 1.22
+  Enabled: true
+Lint/SymbolConversion: # new in 1.9
+  Enabled: true
+Lint/TripleQuotes: # new in 1.9
+  Enabled: true
+Lint/UselessRuby2Keywords: # new in 1.23
+  Enabled: true
+Naming/BlockForwarding: # new in 1.24
+  Enabled: true
+Security/IoMethods: # new in 1.22
+  Enabled: true
+Style/EndlessMethod: # new in 1.8
+  Enabled: true
+Style/FileRead: # new in 1.24
+  Enabled: true
+Style/FileWrite: # new in 1.24
+  Enabled: true
+Style/HashConversion: # new in 1.10
+  Enabled: true
+Style/IfWithBooleanLiteralBranches: # new in 1.9
+  Enabled: true
+Style/InPatternThen: # new in 1.16
+  Enabled: true
+Style/MapToHash: # new in 1.24
+  Enabled: true
+Style/MultilineInPatternThen: # new in 1.16
+  Enabled: true
+Style/NumberedParameters: # new in 1.22
+  Enabled: true
+Style/NumberedParametersLimit: # new in 1.22
+  Enabled: true
+Style/OpenStructUse: # new in 1.23
+  Enabled: true
+Style/QuotedSymbols: # new in 1.16
+  Enabled: true
+Style/RedundantSelfAssignmentBranch: # new in 1.19
+  Enabled: true
+Style/SelectByRegexp: # new in 1.22
+  Enabled: true
+Style/StringChars: # new in 1.12
+  Enabled: true
+
+# Trailing commas in a multiline context makes diffs nicer.
+Style/TrailingCommaInArrayLiteral:
+  EnforcedStyleForMultiline: comma
+
+# Trailing commas in a multiline context makes diffs nicer.
+Style/TrailingCommaInHashLiteral:
+  EnforcedStyleForMultiline: comma
+
+# Trailing commas in a multiline context makes diffs nicer.
+Style/TrailingCommaInArguments:
+  EnforcedStyleForMultiline: comma
+
+# This allows for semantic exceptions
+Style/RaiseArgs:
+  Enabled: false
+
+# We should embrace UTF-8, not shun it.
+Style/AsciiComments:
+  Enabled: false
+
+# Explicitly returning nil in an else is sometimes more clear.
+Style/EmptyElse:
+  Enabled: false
+
+# If/unless at the end of the line makes it harder to miss control flow.
+Style/IfUnlessModifier:
+  Enabled: false
+
+# This doesn’t always make sense.
+Style/GuardClause:
+  Enabled: false
+
+# ----- ENABLED (new) -----
+
+# These cops are new and need to be manually enabled.
+
+Lint/RaiseException:
+  Enabled: true
+
+Lint/StructNewOverride:
+  Enabled: true
+
+Style/HashEachMethods:
+  Enabled: true
+
+Style/HashTransformKeys:
+  Enabled: true
+
+Style/HashTransformValues:
+  Enabled: true
+
+# ----- DISABLED (tests) -----
+
+# These cops are disabled in test cases only.
+
+Style/Documentation:
+  Exclude:
+    - "test/**/*.rb"
+
+Style/GlobalVars:
+  Exclude:
+    - "test/**/*.rb"
+
+Lint/NestedMethodDefinition:
+  Exclude:
+    - "test/**/*.rb"
+
+# ----- DISABLED (metrics) -----
+
+# Cops for metrics are disabled because they should not cause tests to fail.
+
+Metrics/AbcSize:
+  Enabled: false
+
+Metrics/ClassLength:
+  Enabled: false
+
+Metrics/CyclomaticComplexity:
+  Enabled: false
+
+Layout/LineLength:
+  Enabled: false
+
+Metrics/MethodLength:
+  Enabled: false
+
+Metrics/PerceivedComplexity:
+  Enabled: false
+
+Metrics/ParameterLists:
+  Enabled: false
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
new file mode 100644
index 0000000..002082b
--- /dev/null
+++ b/.rubocop_todo.yml
@@ -0,0 +1,106 @@
+# This configuration was generated by
+# `rubocop --auto-gen-config --exclude-limit 300`
+# on 2020-12-30 22:12:01 UTC using RuboCop version 1.7.0.
+# The point is for the user to remove these configuration records
+# one by one as the offenses are removed from the code base.
+# Note that changes in the inspected code, or installation of new
+# versions of RuboCop, may require this file to be generated again.
+
+# Offense count: 1
+# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches.
+Lint/DuplicateBranch:
+  Exclude:
+    - 'lib/cri/command.rb'
+
+# Offense count: 8
+# Configuration parameters: AllowComments, AllowEmptyLambdas.
+Lint/EmptyBlock:
+  Exclude:
+    - 'test/test_command.rb'
+    - 'test/test_command_dsl.rb'
+
+# Offense count: 2
+# Cop supports --auto-correct.
+Minitest/AssertEmpty:
+  Exclude:
+    - 'test/test_argument_list.rb'
+
+# Offense count: 6
+# Cop supports --auto-correct.
+Minitest/AssertIncludes:
+  Exclude:
+    - 'test/test_command.rb'
+
+# Offense count: 5
+# Cop supports --auto-correct.
+Minitest/AssertNil:
+  Exclude:
+    - 'test/test_argument_list.rb'
+    - 'test/test_command.rb'
+
+# Offense count: 1
+# Cop supports --auto-correct.
+Minitest/RefuteEmpty:
+  Exclude:
+    - 'test/test_argument_list.rb'
+
+# Offense count: 1
+# Cop supports --auto-correct.
+Minitest/RefuteFalse:
+  Exclude:
+    - 'test/test_parser.rb'
+
+# Offense count: 9
+# Cop supports --auto-correct.
+Minitest/RefuteIncludes:
+  Exclude:
+    - 'test/test_command.rb'
+
+# Offense count: 1
+# Cop supports --auto-correct.
+Minitest/RefuteRespondTo:
+  Exclude:
+    - 'test/test_argument_list.rb'
+
+# Offense count: 1
+Rake/Desc:
+  Exclude:
+    - 'Rakefile'
+
+# Offense count: 13
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: separated, grouped
+Style/AccessorGrouping:
+  Exclude:
+    - 'lib/cri/option_definition.rb'
+    - 'lib/cri/param_definition.rb'
+    - 'lib/cri/parser.rb'
+
+# Offense count: 1
+# Cop supports --auto-correct.
+Style/ExplicitBlockArgument:
+  Exclude:
+    - 'lib/cri/argument_list.rb'
+
+# Offense count: 1
+# Configuration parameters: AllowedMethods.
+# AllowedMethods: respond_to_missing?
+Style/OptionalBooleanParameter:
+  Exclude:
+    - 'lib/cri/string_formatter.rb'
+
+# Offense count: 18
+# Cop supports --auto-correct.
+Style/StringConcatenation:
+  Exclude:
+    - 'lib/cri/command.rb'
+    - 'lib/cri/help_renderer.rb'
+    - 'lib/cri/option_definition.rb'
+    - 'lib/cri/string_formatter.rb'
+    - 'samples/sample_basic_root.rb'
+    - 'samples/sample_capture_opts_as_args.rb'
+    - 'samples/sample_nested.rb'
+    - 'samples/sample_params.rb'
+    - 'samples/sample_simple.rb'
+    - 'scripts/release'
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..5ebfe2a
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,9 @@
+language: ruby
+rvm:
+  - 2.5
+  - 2.6
+  - 2.7
+  - 3.0
+before_install:
+  - gem update --remote bundler
+  - gem update --system
diff --git a/Gemfile.lock b/Gemfile.lock
deleted file mode 100644
index ebee8ec..0000000
--- a/Gemfile.lock
+++ /dev/null
@@ -1,75 +0,0 @@
-PATH
-  remote: .
-  specs:
-    cri (2.15.11)
-
-GEM
-  remote: https://rubygems.org/
-  specs:
-    ast (2.4.1)
-    coveralls (0.8.23)
-      json (>= 1.8, < 3)
-      simplecov (~> 0.16.1)
-      term-ansicolor (~> 1.3)
-      thor (>= 0.19.4, < 2.0)
-      tins (~> 1.6)
-    docile (1.3.4)
-    json (2.5.1)
-    m (1.5.1)
-      method_source (>= 0.6.7)
-      rake (>= 0.9.2.2)
-    method_source (1.0.0)
-    minitest (5.14.2)
-    parallel (1.20.1)
-    parser (3.0.0.0)
-      ast (~> 2.4.1)
-    rainbow (3.0.0)
-    rake (13.0.3)
-    regexp_parser (2.0.3)
-    rexml (3.2.4)
-    rubocop (1.7.0)
-      parallel (~> 1.10)
-      parser (>= 2.7.1.5)
-      rainbow (>= 2.2.2, < 4.0)
-      regexp_parser (>= 1.8, < 3.0)
-      rexml
-      rubocop-ast (>= 1.2.0, < 2.0)
-      ruby-progressbar (~> 1.7)
-      unicode-display_width (>= 1.4.0, < 2.0)
-    rubocop-ast (1.3.0)
-      parser (>= 2.7.1.5)
-    rubocop-minitest (0.10.2)
-      rubocop (>= 0.87, < 2.0)
-    rubocop-rake (0.5.1)
-      rubocop
-    ruby-progressbar (1.11.0)
-    simplecov (0.16.1)
-      docile (~> 1.1)
-      json (>= 1.8, < 3)
-      simplecov-html (~> 0.10.0)
-    simplecov-html (0.10.2)
-    sync (0.5.0)
-    term-ansicolor (1.7.1)
-      tins (~> 1.0)
-    thor (1.0.1)
-    tins (1.26.0)
-      sync
-    unicode-display_width (1.7.0)
-    yard (0.9.26)
-
-PLATFORMS
-  x86_64-darwin-20
-
-DEPENDENCIES
-  coveralls
-  cri!
-  m (~> 1.5)
-  minitest
-  rake
-  rubocop
-  rubocop-minitest (~> 0.10.2)
-  rubocop-rake (~> 0.5.1)
-  yard
-
-BUNDLED WITH
-   2.2.3
diff --git a/LICENSE b/LICENSE
index 6ee7146..86543b4 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2015 Denis Defreyne and contributors
+Copyright (c) 2015–ω Denis Defreyne and contributors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/cri.gemspec b/cri.gemspec
index 73351d7..483d7fb 100644
--- a/cri.gemspec
+++ b/cri.gemspec
@@ -20,4 +20,5 @@ Gem::Specification.new do |s|
 
   s.rdoc_options     = ['--main', 'README.md']
   s.extra_rdoc_files = ['LICENSE', 'README.md', 'NEWS.md']
+  s.metadata['rubygems_mfa_required'] = 'true'
 end
diff --git a/debian/changelog b/debian/changelog
index 7fe2b5c..613e922 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+ruby-cri (2.15.11+git20220108.2.b25555a-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+  * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Fri, 20 Jan 2023 09:20:30 -0000
+
 ruby-cri (2.15.11-1) unstable; urgency=medium
 
   * Team upload.
diff --git a/debian/patches/0001-remove-badges-from-README-to-avoid-privacy-breach.patch b/debian/patches/0001-remove-badges-from-README-to-avoid-privacy-breach.patch
index 38ca74b..4e63dda 100644
--- a/debian/patches/0001-remove-badges-from-README-to-avoid-privacy-breach.patch
+++ b/debian/patches/0001-remove-badges-from-README-to-avoid-privacy-breach.patch
@@ -10,10 +10,10 @@ Author: Cédric Boutillier <boutil@debian.org>
  README.md | 7 -------
  1 file changed, 7 deletions(-)
 
-diff --git a/README.md b/README.md
-index 963f3a1..161d6b4 100644
---- a/README.md
-+++ b/README.md
+Index: ruby-cri.git/README.md
+===================================================================
+--- ruby-cri.git.orig/README.md
++++ ruby-cri.git/README.md
 @@ -1,12 +1,5 @@
  # Cri
  
diff --git a/lib/cri/help_renderer.rb b/lib/cri/help_renderer.rb
index 822544f..06de630 100644
--- a/lib/cri/help_renderer.rb
+++ b/lib/cri/help_renderer.rb
@@ -78,7 +78,7 @@ module Cri
 
       text << "\n"
       text << fmt.format_as_title('description', @io) << "\n"
-      text << fmt.wrap_and_indent(@cmd.description, LINE_WIDTH, DESC_INDENT) + "\n"
+      text << (fmt.wrap_and_indent(@cmd.description, LINE_WIDTH, DESC_INDENT) + "\n")
     end
 
     def append_subcommands(text)
@@ -120,7 +120,7 @@ module Cri
         string << '-X'
 
         if opt_defn.long
-          string << ' --' + opt_defn.long
+          string << (' --' + opt_defn.long)
         end
 
         case opt_defn.argument
@@ -213,7 +213,7 @@ module Cri
       opt_text_len += 2 + opt_defn.long.size if opt_defn.long
       opt_text_len += long_value_postfix.size
 
-      '    ' + opt_text + ' ' * (length + OPT_DESC_SPACING - opt_text_len)
+      '    ' + opt_text + (' ' * (length + OPT_DESC_SPACING - opt_text_len))
     end
   end
 end
diff --git a/samples/sample_basic_root.rb b/samples/sample_basic_root.rb
new file mode 100644
index 0000000..dc82911
--- /dev/null
+++ b/samples/sample_basic_root.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
+require 'cri'
+
+cmd = Cri::Command.new_basic_root.modify do
+  name        'nanoc'
+  usage       'nanoc [options] [command] [options]'
+  summary     'manages and builds static web sites'
+  description 'nanoc is a tool for building static sites.'
+end
+
+cmd.define_command do
+  name        'compile'
+  usage       'compile [options]'
+  summary     'compiles a web site'
+  description 'This loads all data, compiles it and writes it to the disk.'
+  no_params
+
+  run do |_opts, _args|
+    puts 'Compiling…'
+    sleep 1
+    puts 'Done.'
+  end
+end
+
+cmd.run(ARGV)
diff --git a/samples/sample_capture_opts_as_args.rb b/samples/sample_capture_opts_as_args.rb
new file mode 100644
index 0000000..3b56076
--- /dev/null
+++ b/samples/sample_capture_opts_as_args.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
+require 'cri'
+
+super_cmd = Cri::Command.define do
+  name        'super'
+  usage       'does something super'
+  summary     'does super stuff'
+  description 'This command does super stuff.'
+
+  option    :a, :aaa, 'opt a', argument: :optional
+  required  :b, :bbb, 'opt b'
+  flag      :d, :ddd, 'opt d'
+  optional  :c, :ccc, 'opt c'
+  forbidden :e, :eee, 'opt e'
+end
+
+super_cmd.define_command do
+  name        'sub'
+  usage       'does something subby'
+  summary     'does subby stuff'
+  description 'This command does subby stuff.'
+  skip_option_parsing
+
+  run do |opts, args|
+    $stdout.puts 'in subcommand'
+
+    $stdout.puts "arguments: #{args.inspect}"
+    $stdout.puts "options:   #{opts.inspect}"
+  end
+end
+
+super_cmd.add_command Cri::Command.new_basic_help
+
+super_cmd.run(ARGV)
diff --git a/samples/sample_nested.rb b/samples/sample_nested.rb
new file mode 100644
index 0000000..1116419
--- /dev/null
+++ b/samples/sample_nested.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
+require 'cri'
+
+super_cmd = Cri::Command.define do
+  name        'super'
+  usage       'does something super'
+  summary     'does super stuff'
+  description 'This command does super stuff.'
+
+  option    :a, :aaa, 'opt a', argument: :optional
+  required  :b, :bbb, 'opt b'
+  flag      :d, :ddd, 'opt d'
+  optional  :c, :ccc, 'opt c'
+  forbidden :e, :eee, 'opt e'
+end
+
+super_cmd.define_command do
+  name        'sub'
+  usage       'does something subby'
+  summary     'does subby stuff'
+  description 'This command does subby stuff.'
+
+  option    :m, :mmm, 'opt m', argument: :optional
+  required  :n, :nnn, 'opt n'
+  flag      :p, :ppp, 'opt p'
+  forbidden :q, :qqq, 'opt q'
+  optional  :o, :ooo, 'opt o'
+
+  run do |opts, args|
+    $stdout.puts 'Sub-awesome!'
+
+    $stdout.puts "arguments: #{args.inspect}"
+    $stdout.puts "options:   #{opts.inspect}"
+  end
+end
+
+super_cmd.add_command Cri::Command.new_basic_help
+
+super_cmd.run(ARGV)
diff --git a/samples/sample_params.rb b/samples/sample_params.rb
new file mode 100644
index 0000000..a71b7c2
--- /dev/null
+++ b/samples/sample_params.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
+require 'cri'
+
+command = Cri::Command.define do
+  name        'sync'
+  usage       '[options] source target'
+  summary     'syncronises two locations'
+  description 'bla bla'
+
+  flag :v, :verbose, 'be verbose'
+  param :source
+  param :target
+
+  run do |opts, args|
+    puts 'Executing!'
+    p(opts: opts, args: args)
+  end
+end
+
+puts command.help
+command.run(ARGV)
diff --git a/samples/sample_simple.rb b/samples/sample_simple.rb
new file mode 100644
index 0000000..e596a10
--- /dev/null
+++ b/samples/sample_simple.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
+require 'cri'
+
+command = Cri::Command.define do
+  name        'moo'
+  usage       'usage: moo [options]'
+  summary     'does stuff'
+  description <<~DESC
+    This command does a lot of stuff. I really mean a lot. Well actually I am
+    lying. It doesn’t do that much. In fact, it barely does anything. It’s merely
+    a sample command to show off Cri!
+  DESC
+
+  option    :a,  :aaa,   'opt a', argument: :optional
+  required  :b,  :bbb,   'opt b'
+  optional  :c,  :ccc,   'opt c'
+  flag      :d,  :ddd,   'opt d'
+  forbidden :e,  :eee,   'opt e'
+  flag      :f,  :fff,   'opt f', hidden: true
+  flag      :g,  :ggg,   'this is an option with a very long description that should reflow nicely'
+  flag      :s,  nil,    'option with only a short form'
+  flag      nil, 'long', 'option with only a long form'
+  optional  :i,  :iii,   'opt i', default: 'donkey'
+
+  run do |opts, args|
+    puts 'Executing!'
+    p(opts: opts, args: args)
+  end
+end
+
+puts command.help
+command.run(ARGV)
diff --git a/scripts/release b/scripts/release
new file mode 100755
index 0000000..8b1183c
--- /dev/null
+++ b/scripts/release
@@ -0,0 +1,88 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'fileutils'
+require 'octokit'
+
+def run(*args)
+  puts 'I will execute the following:'
+  puts '    ' + args.map { |a| a =~ /\s/ ? a.inspect : a }.join(' ')
+  print 'Is this correct? [y/N] '
+  res = gets
+  unless res.strip.casecmp('y').zero?
+    warn 'Answer was not Y; release aborted.'
+    exit 1
+  end
+
+  system('echo', *args)
+  system(*args)
+
+  print 'Continue? [y/N] '
+  res = gets
+  unless res.strip.casecmp('y').zero?
+    warn 'Answer was not Y; release aborted.'
+    exit 1
+  end
+end
+
+puts '=== Logging in to GitHub’s API…'
+client = Octokit::Client.new(netrc: true)
+puts
+
+puts '=== Deleting old *.gem files…'
+Dir['*.gem'].each do |fn|
+  puts "  #{fn}…"
+  FileUtils.rm_f(fn)
+end
+puts
+
+puts '=== Building new gem…'
+run('gem', 'build', 'cri.gemspec')
+puts
+
+puts '=== Reading version…'
+require './lib/cri/version'
+puts "Version = #{Cri::VERSION}"
+puts
+
+puts '=== Verifying that release does not yet exist…'
+releases = client.releases('ddfreyne/cri')
+release = releases.find { |r| r.tag_name == Cri::VERSION }
+if release
+  warn 'Release already exists!'
+  warn 'ABORTED!'
+  exit 1
+end
+puts
+
+puts '=== Creating Git tag…'
+run('git', 'tag', '--sign', '--annotate', Cri::VERSION, '--message', "Version #{Cri::VERSION}")
+puts
+
+puts '=== Pushing Git data…'
+run('git', 'push', 'origin', '--tags')
+puts
+
+puts '=== Pushing gem…'
+run('gem', 'push', "cri-#{Cri::VERSION}.gem")
+puts
+
+puts '=== Reading release notes…'
+release_notes =
+  File.readlines('NEWS.md')
+      .drop(4)
+      .take_while { |l| l !~ /^## / }
+      .join
+puts
+
+puts '=== Creating release on GitHub…'
+sleep 3 # Give GitHub some time to detect the new tag
+is_prerelease = Cri::VERSION =~ /a|b|rc/ || Cri::VERSION =~ /^0/
+client.create_release(
+  'ddfreyne/cri', Cri::VERSION,
+  prerelease: !is_prerelease.nil?,
+  body: release_notes
+)
+puts
+
+puts 'DONE!'

Debdiff

File lists identical (after any substitutions)

No differences were encountered between the control files of package ruby-cri

No differences were encountered between the control files of package ruby-cri-doc

More details

Full run details