Repository: ruby/rubygems (Ruby)

Issue:
`gem fetch` always reports success even when it fails
### Describe the problem as clearly as you can

I expect the `gem` CLI to exit with non-zero (i.e. failure) status when it runs a command that fails. This works as expected with some commands like `gem install`:

```
$ gem install this-is-not-a-gem && echo 'success!' || echo 'failed!'
ERROR:  Could not find a valid gem 'this-is-not-a-gem' (>= 0) in any repository
ERROR:  Possible alternatives: this_is_a_gem, thisisstable
failed!
```

But `gem fetch` appears to _always_ report success, even when it fails:

```
$ gem fetch this-is-not-a-gem && echo 'success!' || echo 'failed!'
ERROR:  Could not find a valid gem 'this-is-not-a-gem' (>= 0) in any repository
ERROR:  Possible alternatives: this_is_a_gem, thisisstable
success!
```

This can make problems hard to track down if `gem fetch` is used in a larger script (such as on CI)--the script will happily keep executing past a failed `gem fetch` and then you'll get some other error later on due to the expected gem not being fetched.

Note: I have not tested all other `gem` commands to see if they correctly exit with non-zero on failure, but it'd be good to audit the `gem` command to verify that all other sub-commands behave properly when fixing this.

### Did you try upgrading RubyGems?

Yes, I'm on the latest:

```
$ gem update --system
Latest version already installed. Done.
$ gem -v
3.5.18
```

### Post steps to reproduce the problem

Run this:

```
$ gem fetch this-is-not-a-gem && echo 'success!' || echo 'failed!'
```

### Which command did you run?

`gem fetch`

### What were you expecting to happen?

I expect `gem fetch` to exit with non-zero status when it really fails.

### What actually happened?

`gem fetch` exited with a zero/success status, even though it failed.

### Run `gem env` and paste the output below

```
RubyGems Environment:
  - RUBYGEMS VERSION: 3.5.18
  - RUBY VERSION: 3.3.4 (2024-07-09 patchlevel 94) [arm64-darwin23]
  - INSTALLATION DIRECTORY: /Users/myron/.rvm/gems/ruby-3.3.4
  - USER INSTALLATION DIRECTORY: /Users/myron/.gem/ruby/3.3.0
  - RUBY EXECUTABLE: /Users/myron/.rvm/rubies/ruby-3.3.4/bin/ruby
  - GIT EXECUTABLE: /opt/homebrew/bin/git
  - EXECUTABLE DIRECTORY: /Users/myron/.rvm/gems/ruby-3.3.4/bin
  - SPEC CACHE DIRECTORY: /Users/myron/.cache/gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /Users/myron/.rvm/rubies/ruby-3.3.4/etc
  - RUBYGEMS PLATFORMS:
     - ruby
     - arm64-darwin-23
  - GEM PATHS:
     - /Users/myron/.rvm/gems/ruby-3.3.4
     - /Users/myron/.rvm/rubies/ruby-3.3.4/lib/ruby/gems/3.3.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => true
     - :bulk_threshold => 1000
     - "benchmark" => false
     - "gem" => "--no-document"
     - :sources => ["REDACTED1", "REDACTED2"]
  - REMOTE SOURCES:
     - REDACTED1
     - REDACTED2
  - SHELL PATH:
     - /Users/myron/bin
     - /Users/myron/.rvm/gems/ruby-3.3.4/bin
     - /Users/myron/.rvm/gems/ruby-3.3.4@global/bin
     - /Users/myron/.rvm/rubies/ruby-3.3.4/bin
     - /opt/homebrew/bin
     - /opt/homebrew/sbin
     - /usr/local/bin
     - /usr/local/sbin
     - /usr/bin
     - /bin
     - /usr/sbin
     - /sbin
     - /opt/local/bin
     - /Users/myron/.rvm/bin
     - /usr/local/git/bin
```



Discussion: #8007 should fix this. I did not audit other commands though.



Fix (patch):
diff --git a/lib/rubygems/commands/fetch_command.rb b/lib/rubygems/commands/fetch_command.rb
index f7f5b62306a5..c524cf792293 100644
--- a/lib/rubygems/commands/fetch_command.rb
+++ b/lib/rubygems/commands/fetch_command.rb
@@ -63,6 +63,17 @@ def check_version # :nodoc:
 
   def execute
     check_version
+
+    exit_code = fetch_gems
+
+    terminate_interaction exit_code
+  end
+
+  private
+
+  def fetch_gems
+    exit_code = 0
+
     version = options[:version]
 
     platform  = Gem.platforms.last
@@ -86,10 +97,13 @@ def execute
 
       if spec.nil?
         show_lookup_failure gem_name, gem_version, errors, suppress_suggestions, options[:domain]
+        exit_code |= 2
         next
       end
       source.download spec
       say "Downloaded #{spec.full_name}"
     end
+
+    exit_code
   end
 end