piotrmurach / tty

Toolkit for developing sleek command line apps.
https://ttytoolkit.org
MIT License
2.5k stars 78 forks source link

Initial project creation; 'teletype' command throws exception until gemspec is edited #69

Closed slowbro closed 3 years ago

slowbro commented 3 years ago

Describe the problem

A brief description of the issue/feature.

Steps to reproduce the problem

teletype new test-app
cd test-app
teletype help

Actual behaviour

When using any teletype command, you get a series of exceptions related to metadata:

[katelyn@h test-app]$ teletype help
Traceback (most recent call last):
    6: from /home/katelyn/.rvm/gems/ruby-2.6.5/bin/ruby_executable_hooks:10:in `<main>'
    5: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/executable-hooks-1.6.0/lib/executable-hooks/hooks.rb:49:in `run'
    4: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/executable-hooks-1.6.0/lib/executable-hooks/hooks.rb:49:in `each'
    3: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/executable-hooks-1.6.0/lib/executable-hooks/hooks.rb:50:in `block in run'
    2: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/rubygems-bundler-1.4.5/lib/rubygems_executable_plugin.rb:4:in `block in <top (required)>'
    1: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
/home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- rubygems-bundler/noexec (LoadError)
    33: from /home/katelyn/.rvm/gems/ruby-2.6.5/bin/ruby_executable_hooks:10:in `<main>'
    32: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/executable-hooks-1.6.0/lib/executable-hooks/hooks.rb:49:in `run'
    31: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/executable-hooks-1.6.0/lib/executable-hooks/hooks.rb:49:in `each'
    30: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/executable-hooks-1.6.0/lib/executable-hooks/hooks.rb:50:in `block in run'
    29: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/rubygems-bundler-1.4.5/lib/rubygems_executable_plugin.rb:4:in `block in <top (required)>'
    28: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:34:in `require'
    27: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:130:in `rescue in require'
    26: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:130:in `require'
    25: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/rubygems-bundler-1.4.5/lib/rubygems-bundler/noexec.rb:131:in `<top (required)>'
    24: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/rubygems-bundler-1.4.5/lib/rubygems-bundler/noexec.rb:124:in `check'
    23: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/rubygems-bundler-1.4.5/lib/rubygems-bundler/noexec.rb:92:in `setup'
    22: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/rubygems-bundler-1.4.5/lib/rubygems-bundler/noexec.rb:51:in `candidate?'
    21: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/definition.rb:203:in `missing_specs'
    20: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/definition.rb:247:in `resolve'
    19: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/definition.rb:744:in `converge_locked_specs'
    18: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/definition.rb:744:in `each'
    17: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/definition.rb:758:in `block in converge_locked_specs'
    16: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:108:in `specs'
    15: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:100:in `local_specs'
    14: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:165:in `load_spec_files'
    13: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:165:in `each'
    12: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:171:in `block in load_spec_files'
    11: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:157:in `validate_spec'
    10: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/rubygems_integration.rb:61:in `validate'
     9: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/ui/silent.rb:61:in `silence'
     8: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/rubygems_integration.rb:61:in `block in validate'
     7: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/specification.rb:2654:in `validate'
     6: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/specification_policy.rb:64:in `validate'
     5: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/specification_policy.rb:95:in `validate_metadata'
     4: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/specification_policy.rb:95:in `each'
     3: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/specification_policy.rb:114:in `block in validate_metadata'
     2: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/specification_policy.rb:399:in `error'
     1: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/2.6.0/delegate.rb:85:in `method_missing'
/home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/2.6.0/delegate.rb:85:in `call': metadata['homepage_uri'] has invalid link: "TODO: Put your gem's website or public repo URL here." (Gem::InvalidSpecificationException)
    24: from /home/katelyn/.rvm/gems/ruby-2.6.5/bin/ruby_executable_hooks:10:in `<main>'
    23: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/executable-hooks-1.6.0/lib/executable-hooks/hooks.rb:49:in `run'
    22: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/executable-hooks-1.6.0/lib/executable-hooks/hooks.rb:49:in `each'
    21: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/executable-hooks-1.6.0/lib/executable-hooks/hooks.rb:50:in `block in run'
    20: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/rubygems-bundler-1.4.5/lib/rubygems_executable_plugin.rb:4:in `block in <top (required)>'
    19: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:34:in `require'
    18: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:130:in `rescue in require'
    17: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:130:in `require'
    16: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/rubygems-bundler-1.4.5/lib/rubygems-bundler/noexec.rb:131:in `<top (required)>'
    15: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/rubygems-bundler-1.4.5/lib/rubygems-bundler/noexec.rb:124:in `check'
    14: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/rubygems-bundler-1.4.5/lib/rubygems-bundler/noexec.rb:92:in `setup'
    13: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/gems/2.6.0/gems/rubygems-bundler-1.4.5/lib/rubygems-bundler/noexec.rb:51:in `candidate?'
    12: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/definition.rb:203:in `missing_specs'
    11: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/definition.rb:247:in `resolve'
    10: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/definition.rb:744:in `converge_locked_specs'
     9: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/definition.rb:744:in `each'
     8: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/definition.rb:758:in `block in converge_locked_specs'
     7: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:108:in `specs'
     6: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:100:in `local_specs'
     5: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:165:in `load_spec_files'
     4: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:165:in `each'
     3: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:171:in `block in load_spec_files'
     2: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/source/path.rb:157:in `validate_spec'
     1: from /home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/rubygems_integration.rb:60:in `validate'
/home/katelyn/.rvm/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/bundler/rubygems_integration.rb:65:in `rescue in validate': The gemspec at /home/katelyn/code/test-app/test-app.gemspec is not valid. Please fix this gemspec. (Gem::InvalidSpecificationException)
The validation error was 'metadata['homepage_uri'] has invalid link: "TODO: Put your gem's website or public repo URL here."'

Other errors I ran into while stepping through the errors:

The validation error was '"FIXME" or "TODO" is not a description'

The validation error was 'metadata['source_code_uri'] has invalid link: "TODO: Put your gem's public repo URL here."'

The validation error was 'metadata['changelog_uri'] has invalid link: "TODO: Put your gem's CHANGELOG.md URL here."'

The validation error was '"TODO: Put your gem's website or public repo URL here." is not a valid HTTP URI'

Expected behaviour

I'd expect either a pretty message ("First, modify test-app.gemspec!"), or for the "TODO:" lines to be commented out. The issue was solved by commenting out the 'uri' metadata(s), and modifying the summary/description... but it wasn't immediately obvious (especially since I missed the 'validation error' and went straight to 'wait, what's wrong with rubygems-bundler/noexec?').

I think it could be fixed globally by changing the default spec like this:

-  spec.summary       = %q{TODO: Write a short summary, because RubyGems requires one.}
-  spec.description   = %q{TODO: Write a longer description or delete this line.}
-  spec.homepage      = "TODO: Put your gem's website or public repo URL here."
+  spec.summary       = %q{My new teletype app.}
+  spec.description   = %q{My new teletype app.}
+  #spec.homepage      = "TODO: Put your gem's website or public repo URL here."

   # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
   # to allow pushing to a single host or delete this section to allow pushing to any host.
   if spec.respond_to?(:metadata)
-    spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
+    #spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"

-    spec.metadata["homepage_uri"] = spec.homepage
-    spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
-    spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
+    spec.metadata["homepage_uri"] = spec.homepage if spec.homepage
+    #spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
+    #spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
   else
     raise "RubyGems 2.0 or newer is required to protect against " \
       "public gem pushes."

Alternatively, if the validations are coming from tty itself, maybe just printing a 'update your gemspec first!' message would be enough. Unsure what would be the best approach.

Describe your environment

piotrmurach commented 3 years ago

Agreed that's not great. I like your suggestion of teletype printing a message! This would work well enough for the immediate release v0.11.0. Then in the next release when the Bundler generator gets replaced, I would use tty-prompt to ask questions and use the answers to generate already populated gemspec file. At the moment it would be a lot of hassle to do this as I don't control Bundler executable and would rely on injecting this information with some regex matching which could be fairly brittle. Plus I don't fully agree with some of the defaults generated in the file anyway. I wrote an article about my lessons learnt writing gem specifications.