Add RubyGems support to package protection rules

What does this MR do and why?

Adds RubyGems to package protection rules. Maintainers can now stop lower roles from pushing or deleting gems that match a rule.

Closes #603267.

  • Rule type: rubygems is now a package type for protection rules. It covers the model enum and the GraphQL RUBYGEMS value. REST picks it up from the model enum. The settings form option is in a stacked frontend MR (!264749 (merged)), because backend and frontend GraphQL changes ship separately.
  • Push check: runs in Packages::Rubygems::ProcessGemService, after the gemspec is read and before the lease. A protected push raises ProtectedPackageError. Packages::ErrorHandling turns it into an error status with the message Gem '<name>' with version '<version>' is protected. Helm and NuGet work the same way.
  • Delete check: no new code. MarkPackageForDestructionService is already generic. It stays behind the packages_protected_packages_delete flag.
  • Deploy tokens: a deploy-token upload has no creator. Any matching rule blocks the push. This is existing CheckRuleExistenceService behavior and matches the docs table.
  • No feature flag: matches the Terraform module protection MR (c4a2572c). The whole RubyGems registry is already behind rubygem_packages.
  • No name validation: gem patterns have no format check, like Helm, NuGet, and Maven.
  • Merge order: merge !264749 (merged) in the same release. The RubyGems docs name the RubyGems option in the form.
  • No database changes: package_type is an existing integer enum.
Why the block is not a 409 or 403

RubyGems uploads are async. gem push gets a 201. Then the extraction worker reads the gem name. A synchronous error would need us to parse the gem during upload. That is out of scope here.

Generated files
  • GraphQL reference docs
  • Both introspection JSON files
  • OpenAPI v3 (generated)
  • OpenAPI v2: two enum lines added by hand. The local v2 generator rewrote the whole file, so I kept only the two enum lines.

References

Screenshots or screen recordings

N/A — backend only. The form option is in the stacked frontend MR.

How to set up and validate locally

  1. Enable rubygem_packages for a project in the Rails console.
  2. Go to the project's Settings > Packages and registries. Add a protection rule for package type RubyGems, pattern my_gem, minimum access level for push Maintainer.
  3. As a Developer, run gem push for my_gem. The push returns 201. The package then shows an error status with Gem 'my_gem' with version '<version>' is protected.
  4. As a Maintainer, push my_gem again. The package processes and succeeds.

Tests: 293 backend examples and 28 Jest tests pass. Rubocop is clean. The extraction worker spec has a 10-case matrix (roles, patterns, nil creator, wildcard). The process gem service spec has one new example.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

🤖 Generated with Claude Code

Edited by Tim Rizzi

Merge request reports

Loading
Loading