-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scoped gems proposal #40
base: master
Are you sure you want to change the base?
Conversation
I feel like namespaces with the syntax (I also added a link to the rendered doc to the top of the PR description for easy access.) |
The Edit (5/5) - I had updated the RFC explaining the technical challenges/limitations of using |
If we can't get proper organisations, this might be a good first step. I'd be a tiny bit concerned this works us into a position where supporting proper organisations is harder. It's definitely concerning when you create a gem like |
That is valid feedback. I would think that a user's scope can be easily transferred to an organization concept in the future assuming the scoped username shares the future organization name (i.e. Though what do you mean by "proper" organizations? I assume you mean some Rails modeling that groups a bunch of owners together under some entity. Since gems can have multiple owners (already an "organization" if you will), I thought this solution fit in nicely. This proposal can certainly have a concept of such an organization entity and use the same gem naming pattern. Also, regarding the |
Part of my concern is asserting that "async-foo" is official and "async-foob" is not. |
Ah. I want to be clear that |
At first glimpse, I like this idea. It does not break too many things and seems relatively simple in implementation. My only worry is, that it won't be compatible with PURL format: https://github.com/package-url/purl-spec convention where the namespace is defined before the name:
though it could be fixed by the routing itself in the rubygems. |
Interesting, I have never heard of PURL. Though looking at npm's example |
I was thinking about this for long time. My biggest concern is transition time. I was thinking about some kind of backward compatible naming scheme (at least for fallback). For example if we decide to do namespacing using "rails/activerecord" scheme, we can fallback for older RubyGems/Bundler by using "rails--activerecord" (or similar, double dash is used only in few gems we can yank currently according to DB dump). |
Similar to that concern, I have a concern that people might squat transitional names if that's what we decide on...for example, it would be bad if I could create a rails--activerecord gem now anticipating the real gem moving to the new format |
I think "anticipated" squatting can be mitigated (simi mentioned yanking). |
@simi Are you suggesting scoped gems ALSO reserve Ruby namespaces? I.e. |
We can reject gems with
No, we don't check anything in the code and I think it would be super complex to start doing that. |
Hi! I like this feature proposal, and I think there's one extra benefit that hasn't been mentioned: it makes "soft-forking" easier. Say Rails wants to temporarily fork the "mail" gem, to provide a better experience until mail gem owners can get to addressing some important issues. Right now, the only way is to come up with a new name, and it's not clear how to properly communicate that the fork is only something temporary, and not meant to completely sunset the forked gem. Releasing My main concern is namespace squatting too. I'm not sure I understand the current proposal and how do we prevent it. Can rubygems.org users create "custom scopes" (different from their usernames)? If that's the case, what prevents any random user to create the Regarding old clients, is the Personally, my preferred naming scheme is the one suggested by @indirect, although I understand it would require more work due to the ambiguous "/". I'm not too sure about how to migrate to the new scheme, it seems quite complicated. I guess duplicate pushing would be best, maybe enhancing the clients to ease it, for example, something like |
@deivid-rodriguez Thanks for the feedback!
I reserved
Yeah, I can see reasons to want it. I started with this approach first but it introduced some complications. Specifically, we'd have to handle these cases:
I'm ok with duplication as it would certainly be the safest option. In practice, as a gem maintainer with 300+ gems, it's not as feasible and probably causes some customer confusion. I think a one-way one-level alias might make sense, but we'd have to handle gem install locations too, perhaps a symlink between |
👋 I'm positive to add this feature. But I'm not sure what the best syntax about We can choose:
Does anyone summaries scoped namespace feature of other package manager? |
I think one of these is the most reasonable:
the latter seems to be the format used by npm IIRC, but I think the former can be slightly better (what's the reason for/motivation of |
I think the motivation for the at-sign is to clearly distinguish the scope ( |
A tricky question about scoped packages: in Node, it is completely fine to have both In RubyGems, it would be (presumably) impossible to have both Can a dependency on |
@indirect if I'm understanding the original proposal:
Is that correct? |
yes but my points was, that the notion of "scope" is not part of purl because of namespaces. However I understand the reasoning here and backwards compatibility. Few registries slowly drift towards purl: https://github.com/package-url/purl-spec @indirect on top of that, for node you can have two versions of the same package in the same repo. About the namespaces: would be good to estimate how many gems actually use their correct namespace vs patching other things or using completely different namespaces. |
@mullermp I guess you're right, we would need to deal with squatting as just another type of possible abuse, and define clear rules about it. @indirect I think in the particular case of Anyways, this small benefit is just something that came to my mind as a potential extra benefit, but it's not even mentioned in the RFC. I think this RFC only proposes a way to allow gem name collision, but does not impose anything on what top level module a given gem should define. |
Another question is how to resolve dependencies? Should we use full (including namespace) gem identifier everywhere (including Gemfile.lock and gemspec dependencies specification)? I see the problem in compatibility again in here. We need to ensure transition is as smooth as possible. |
Yes, I think the new name should be used everywhere, otherwise it's impossible to differentiate differently scoped gems with the same name, no? I don't think there's much that can be done about compatibility, unfortunately, except for going down the route you suggested before: choosing a name scheme that's currently valid, just mostly unused. It would definitely make things smoother, although not so nice. I'm not fully sure which option is best. To elaborate on what I said before about Bundler being able to "trampoline", the idea is that, say, support for the new naming scheme is added on Bundler 2.4. And someone upgrades to Bundler 2.4.0 to be able to bundle |
@deivid-rodriguez my idea was to support both old/new name scheme (at least for some time). At RubyGems.org it could just check the client version (or we can make some additional header to ask for new scheme) and respond with given scheme.
Would work the same for some time. The latter one just will not be compatible with older RubyGems and Bundler. I can ask about PURL and plans of other packing repo maintainers at next OSSF meeting. |
Mmmm... I think we should provide a migration mechanism so that gem authors can opt in to the new naming scheme, while still being compatible with the old naming scheme. So even if the I'm not really sure how we can make the above work, but if we could do it, what would be the purpose of |
|
||
A scoped gem is any gem that is named following the pattern `gem@scope`, where “gem” is the name of the gem, and “scope” is an organization's reserved gem scope. Gem scopes are globally unique across all organizations. | ||
|
||
As an example, consider a scoped gem defined as `[email protected]`. Note that both the gemspec’s `name` and the required file `lib/[email protected]` follows the `gem@scope` pattern: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per my comment about "weird"... I just thought that: [email protected]
looked a lot like an email, especially if gemspec
were a TLD (seems that it isn't, nor is .rb).
I'm not saying the gem@scope
pattern isn't good (and other symbols have other problems), but just something to be aware of. 🤔
When I download a gem named Adherence to this naming convention, combined with the unique constraint on gem names helps prevent/reduce namespace collisions. So if Wouldn't it make more sense to put the owner organisation in the Gem's metadata (a new, dedicated field, not the actual |
I'm late to the conversation, but couldn't we add an I'm really not following the purpose of the '@' for scoping, and why the org name wouldn't be enough scoping. I'm also trying to remember what Perl did for package management. I thought they had some way to scope them already, but my memory is fuzzy. |
How would I structure:
It would be good to understand what is best practice to see if the proposed model fits real world use cases (or what real world use cases fit the proposed model). |
I believe that the proposal would have you create (to pick one of them) @djberg96 I think we should add an organization (or, if you prefer, scope) field to the gemfile, but I think that there is value in making the organization/scope part of the scoping capabilities at the command-line and in Bundler without getting excessively verbose. I would prefer to do any one of the following $ gem install @mime-types/core
$ gem install mime-types@core
$ gem install core@mime-types Over: $ gem install mime-types --organization mime-types
$ gem install core --organization mime-types Similarly, I would prefer for Bundler In general, I think that this is a cogent RFC, but it feels incomplete to me, as I think that it needs to have a clearer indication that scoped packages (either personal I’m not sure we should wait for perfect before we act on this, if we act on this. I think that there are several issues here of which the scoping of gem names is only one. This gets into:
In some ways, a lot of this (except name scoping) could be fixed if we had a better way of implementing signed gems (and verifying those signatures), rather than using namespaces and Rubygems.org as pure sources of truth. But, as someone who did sign gems early on and found the process excruciating (and no one verified them anyway), I don’t think that’s going to be a solution to any of these problems. Not quite sure how to move forward on this. It’s a good RFC. I’m not sure it is good enough, but I also don’t know that waiting for a better RFC is going to give us anything this decade. |
But if organisation was part of the gem metadata instead of the gem name, then there would be no ambiguity in the gem name (due to the uniqueness constraint), and therefore specifying the organisation would be unnecessary, no? |
I really like the idea of adding scopes. Like many others, I just find that the Ruby modules: Go back in Rubygems' own history to the original gemcutter and we had Consider also that Ruby gems themselves often live in GitHub, where they might be named Or look at the already discussed example of For those who care about code aesthetics and are prone to aligning related lines (including myself): gem 'async/async' # feels normal
gem 'async/http'
gem 'async/websocket'
# vs
gem 'async@async' # awkward!
gem 'http@async'
gem 'websocket@async' I'd strongly prefer to see the Ruby ecosystem choose a path that's consistent with everyone else and go with I'll also suggest that consistency with other languages and ecosystems keeps things more accessible to new Ruby developers. If we invert the common ordering, then it's one more thing that blog posts and books will have to address. It adds mental overhead. |
This comment was marked as abuse.
This comment was marked as abuse.
I agree that this won't prevent typo squatting since, as @andy-tycho says, you could just as well typo-squat an organization, unless we add some sort of auth hook, which is outside the scope of the project. Where an org/scope attribute would come in handy would be for plugins that could hook into it as they see fit. Any sort of auth could be handled by the plugin author instead of us, and then users could choose to use that plugin or not. It's not a huge deal to me either way, and it can potentially be handled by metadata of course, but it's more likely to be used IMO if it's a Specification attribute. |
With respect to |
I’m not sure what you’re saying here, @cyclotron3k. I think that there is potential value in having scoping be part of a name to expand the "universe" of available package names. The points raised about how namespacing works in Ruby (e.g., when you use While I don’t think that Rubygems should be enforcing any names inside the gems (after all, there can be value in publishing a gem that monkey patches another gem to fix a bug in the original gem that hasn’t been updated…), I think that we (the Ruby community) could consider how scoped gems should expose their namespaces. I know that I haven’t really been part of any of the previous discussions on this topic (mostly because I haven’t been aware of them), but I think that they’re fascinating. @mullermp, thank you for writing this RFC and getting the discussion going to a wider viewpoint. Even though this is really a proposed Rubygems RFC, I wonder if this might not be something that should be raised on ruby-core. It’s not part of MRI implementation as such, but Rubygems and Bundler are so deeply part of the overall Ruby development experience at this point, it probably needs additional eyes on it. |
Hi all- I'd like to leave an idea here that perhaps should be a separate RFC: if/when rubygems.org starts to add scoped gems support, it feels like that should be on an annual subscription service that goes directly to supporting the costs of running/maintaining rubygems.org. RubyCentral and many sponsors (see the footer on rubygems.org) covers these costs now, but this feels like a great way for the community to actively buy-in and support the central piece of the ecosystem we rely on, and especially with a feature that is geared towards organizations that have the ability to pay for services they use. I don't know what the right amount to charge is - maybe a community survey should be held to determine that $ amount. Alternatives to gem scoping would still work fine: dashes in gem names, or a company hosting their own private gem server, so I am hoping that will be seen a reasonable workaround if an organization cannot afford the charge or refuses to pay. ❤️ |
Under Alternative 3, the original proposal hints at "implementation and legacy complications" arising from the use of While I like the aesthetic of Let's use
Now, comparing to
Alternative 3 also mentions escaping Further, it still doesn't resolve ambiguity with That's a lot of change and seems to me like it would require bumping Rubygems to 4.x as it's pointing towards breaking backward compatibility. If it requires changing the behavior of |
I agree with @halostatue that scopes should be part of the Potential places for naming collisions (with In all cases, if |
I think scoped gems is an interesting idea, but I'm not sure if there is a way to support it without changing the Ruby language itself. In other languages, you can import different packages with the same name and scope them within the file you are working in. In Ruby, gems are essentially globally namespaced. The problem that was raised in this proposal about wanting to use a forked version is already achieved through the use of bundler: # Gemfile
gem 'mail', github: 'rails/mail' This makes it clear that we are using a forked version of a gem. Thus all gems that have a dependency on If this definition were pushed down to the gemspec level, this would make things very complicated, and even dangerous. Let's say Rails wants to depend on a forked version of a gem using something like So, I think this is already achieved in a reasonable way using Bundler. Might be nice to have an easy way to be able to download a gem from GitHub without having to clone it. Like |
I think the value as a gem maintainer I see in scopes is two things:
I've run into both of the above problems. Both of them are about predictability and risk management. The biggest problem I see is:
My feeling is, organisations or scopes should not change the name resolution process we already have, but instead provide a better more secure way for users to procure gems. If we are thinking big picture, I'd suggest:
The good thing about this model is it allows you to fork a gem (as rails did with mail) and plug it in as a named dependency without breaking dependency resolution (because you'd need a different name to push it to rubygems.org). This design don't require any changes to name handling and I don't think we should change the name handling because it will break every system that depends on name-based dependency resolution etc. Based on my above suggestions, it would not be possible to install both |
This comment was marked as abuse.
This comment was marked as abuse.
This comment was marked as off-topic.
This comment was marked as off-topic.
I don't think we should provide a scope mechanism that allows differently-named gems to provide the same global Ruby constants. I survived GitHub's original gem server, and I still have scars from trying to use an app whose gems depended on both To me, @ioquatix's proposal to treat orgs as additional gem sources sounds like the most likely to work under the constraints we have today. For example, gems that depend on |
Hey everyone. 👋 After reading through the RFC and this discussion, I want to add some thoughts/observations in hopes that this enriches the discussion (although I might be somewhat counter to André's concerns above -- maybe because I'm missing context to earlier days with GiHub's original gem server): Gem Specification ScopesIn terms of gem specifications, I want to focus specifically on the use of Gem::Specification.new do |spec|
spec.scope = "dry" # This is important for many reasons which I'll highlight shortly.
spec.name = "monads"
# Truncated for brevity.
end As the author and maintainer of Gemsmith -- a gem for building gems -- this would allow organizations and individual contributors to configure this information once via Gemsmith's XDG configuration. This equates to being able to build a gem as follows: # Uses global scope as exists today or pulls scope from XDG configuration (if configured).
# This is a nice productivity boost when building multiple gems within the same scope.
gemsmith --build demo
# Uses custom scope which overrides any XDG configured local or global scope.
# Definitely tedious when creating multiple gems within the same scope -- if not using an XDG configuration -- but handy for one-time overrides.
gemsmith --build monads --scope dry This also means that Gemsmith -- and Bundler -- wouldn't have to add special logic for parsing a gem name -- at creation -- by splitting gemsmith --build dry@monads At (@) Symbol AvoidanceBuilding upon what I've demonstrated above, I'd like to push for avoiding the use of the at symbol (@) within the gem name, package, and URL altogether for the following reasons:
I'd like to suggest as an alternative which is to keep scope information in the gem specification. Then both Bundler and RubyGems would be able to do the following: Paths (gem installation and management) # Global scope as exists today.
$HOME/<truncated>/3.1.2/lib/ruby/gems/3.1.0/gems/dry-monads-1.4.0
# Scoped as being proposed.
# NOTE: `@` is removed in favor of using `dry` as a scoped directory structure.
$HOME/<truncated>/3.1.2/lib/ruby/gems/3.1.0/gems/dry/monads-1.4.0 URLs (gem lookup)
ℹ️ In all of the above use cases -- and as emphasized in the RFC -- the gem namespace would remain the same regardless of using global or specialized scope. Example: module Dry
module Monads
end
end The only difference is how Bundler finds and resolves the gem locally (i.e. either using the scope if defined or falling back to global if not) and how RubyGems lists the gem in the URL (which also depends upon the gem specification). Graceful Degradation, Soft Forking, and MigrationSo far everything I've been proposing allows for graceful degradation, soft forking, and gem transition support. By this, I mean gems can exist as they are today with support for scoped coexistence while falling back to the existing and established format. To summarize: Gem Specification # Valid
Gem::Specification.new do |spec|
spec.name = "dry-monads"
# Truncated for brevity.
end
# Valid
Gem::Specification.new do |spec|
spec.scope = "dry"
spec.name = "monads"
# Truncated for brevity.
end Paths # Valid (global)
$HOME/<truncated>/3.1.2/lib/ruby/gems/3.1.0/gems/dry-monads-1.4.0
# Valid (scoped)
$HOME/<truncated>/3.1.2/lib/ruby/gems/3.1.0/gems/dry/monads-1.4.0 URLs
All of this means that you can do the following:
None of what I've written above addresses the name squatting problem, though. That is still a complication which has been mentioned in this discussion but probably warrants a different proposal. |
@bkuhlmann I think your suggestion is aligned on the end goals: scopes need a way to avoid global namespace conflicts. 👍🏻 I might have missed it, but l didn’t see anything in your post to address “scoped forks”, like the Rails org creating their own Mail gem that is an alternative/replacement for the global Mail gem. How would you handle that? |
This comment was marked as abuse.
This comment was marked as abuse.
This comment was marked as off-topic.
This comment was marked as off-topic.
@halostatue I agree with @djberg96 mainly for the reason that we already have got possibilities to "scope" gems. We can already do |
I would love for the "prominent locomotives and shapers of the Ruby world" to comment and contribute to this RFC! |
I think that this could be a good change for the future of Ruby as a whole. My main concern is backwards compatibility with existing applications. Though, they're probably running an older version of Ruby and rubygems anyways, so it likely wouldn't matter as long as the API was backwards compatible. Ultimately, what is the goal of scoped gems and what problem is it solving? Based on the conversations above, it looks clear that the scoped gems is providing "confidence" that a consumed gem is from a certain organization. If this is the goal, then sure, it is moving in the right direction. However, there was other mentions of consuming potentially malicious gems and squatting on names. Sure, this would help combat the squatting on gem names as things are now scoped. However, I'd push back on the malicious gems bit. Someone could create a fake org scope like As far as the naming convention. I'll go with the flow. I don't have a preference on gem@scope or scope@gem or @scope/gem. gem@scope does give a more normal feel as it is similar to user@server. |
I want to thank everyone for providing their feedback and perspectives on this. I think the next step here is to consolidate/parse the feedback and determine what changes are needed. At a glance, the idea seems to be overwhelmingly positive, but the approach (naming and usage) is mixed. I understand that we can't please everyone. Hopefully we can strike a happy medium here. |
Yeah, fair point. I don't address that very well and I'm not sure I have a good answer other than what I commented on earlier and what Samuel mentions in his comment (i.e. the Rails Mail gem example) without thinking through the directory and URL path design a bit more (as well as eliciting more feedback). I agree there are caveats to think through and address better. Something that would be a huge help is to see the RFC be brought up-to-date with the current discussion so, at a high level, everyone is back on the same page and can help progress the design even further. Matt: Maybe you can update your RFC -- if you are not already in the process of doing this -- to detail the directory path design as mentioned in these comments and discussion? If your RFC was brought up-to-date with the current discussion then it'd be easier to iterate on this a bit more? |
Would it be helpful for me to write a RFC for the proposal I outlined too? Even if it's just as a counter point? |
rendered proposal
Hello RubyGems team, and all those that come across this.
In this PR, I have included a proposal for a feature called "scoped gems". In short, the proposal is to widen the gem naming specification to include a new character
@
to group related gems together under a specific organization reserved suffix. The naming pattern followsgem_name@scope
. On the first gem push (new record), if the gem is scoped (follows the pattern), the gem's scope will be validated to have been created by a user from an organization that reserved the scope. A scoped gem can be installed and required as normal gems are today.For example, consider
aws-sdk-s3
, the S3 gem for AWS. If this gem were scoped, it could be published ass3@aws-sdk
(or more generically,<service>@aws-sdk
). This gem can only be created by a user in the AWS organization (which has reserved theaws-sdk
scope). A user can install this gem withgem install s3@aws-sdk
and require it withrequire 's3@aws-sdk'
.The main benefits of this feature are that organizations can publish their own groups of gems (i.e. multiple organizations can have a "configuration" gem), and organizations are able to reserve gem names (via
@scope
suffix, similar to a reserved prefix). A developer can be reasonably sure that any new gem such asnew-cool-feature@rails
is an official Rails gem, ornew-s3-service@aws-sdk
is an official AWS SDK client, or evensocket@ruby
to be an official stdlib gem! This reservation system combats "fake" "similarly named" gems that are branded as official that attempt to steal personal information.Please leave any feedback and I would be happy to amend the approach/design.