Skip to content
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

Sponsor links for NuGet packages #12922

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open

Sponsor links for NuGet packages #12922

wants to merge 2 commits into from

Conversation

JonDouglas
Copy link
Contributor

@JonDouglas JonDouglas commented Oct 5, 2023

This proposal introduces a way to bring visibility of ways to sponsor a NuGet package and its respective open source project.

Rendered Proposal

Please 👍 or 👎 this comment to help us with the direction of this feature & leave as much feedback/questions/concerns as you'd like on this issue itself and we will get back to you shortly.

Thank You 🎉

Related: NuGet/NuGetGallery#9339

@andybooth
Copy link

andybooth commented Oct 5, 2023

Does using sponsor@type and Sponsors@Include imply a fixed list of sponsor platforms that will have to be part of the msbuild tooling?

Comment on lines +68 to +70
<Sponsors Include="Patreon" Url="https://www.patreon.com/mypatreonusername"/>
<Sponsors Include="GitHub Sponsors" Url="https://github.com/sponsors/mygithubusername"/>
<Sponsors Include="Tidelift" Url="https://tidelift.com/subscription/pkg/mypackagename"/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we support a Custom type as well? For example, some people prefer to sponsor projects through the means of crypto donations, so it would be nice to include a personal webpage that contains a list of your wallets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had not thought of crypto when writing this. Let's keep this comment up to see if that's something interesting to the community. I was mostly thinking of reputable sponsorship platforms which may or may not support it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having a fallback plain link type would still be nice regardless, at least to support lesser known donation platforms

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the support of custom sponsorship types, it's a two part question. One is what is supported in the data model (i.e. what will NuGet pack allow in the .nuspec or .csproj metadata) and what is supported on package sources (e.g. NuGet.org). I think we should be permissive in the data model (e.g. freeform or even optional type) and allow package sources to be a bit stricter (e.g. NuGet.org may say it must be an HTTPS URL and have a set of allowed types or no type at all giving a well understood fallback experience).

This is the approach we have taken with package type and repository metadata and it's served us okay. There are drawbacks of a looser data model but I think it's best to encourage innovation in the values rather than lock down to a fixed set that we have to revise every so often and with dubious criteria.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was mostly thinking of reputable sponsorship platforms which may or may not support it.

Not all countries have access to what you most likely call a "reputable sponsorship platform" (such as patreon and github sponsors).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WhiteBlackGoose I'm mostly going off of other ecosystems here. They support a handful of platforms. Are there certain platforms not supported in your country or countries we should be aware about for this first iteration?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I see URLs in package metadata, I immediately think about how spammers would abuse it. Not sure if it is in scope of the spec, but we should consider using rel='nofollow' for platforms unknown to Gallery if we choose to render them in the first place.


Package authors will be able to express their sponsorship needs through new `sponsor` package metadata specifying a popular verified funding mechanism (GitHub Sponsors, Patreon, etc). This may consist of a list of reputable funding providers such as patreon, tidelift, github sponsors, and the relative link to each.

Package consumers will be able to see packages looking for funding through different mechanisms. One will be at `restore` time where a new message will be outputted to summarize all the funding requirements in the individual has opt-in to a feature flag such as `<NuGetSponsor>true</NuGetSponsor>`. For more information about any specific package's sponsorship needs, a developer will be able to use a CLI command like `dotnet sponsor package <PACKAGE_NAME>` to learn more about how they can contribute financially. Within an IDE such as Visual Studio, there will be a new sponsorship affordance in the package details page that a developer can click on.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can <NuGetSponsor>true</NuGetSponsor> be included in the default csproj template? Similar to how ImplicitUsings and Nullable were introduced (on by default for new projects, but opt-in in principle).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would also be nice to have something similar to npm fund. It can generate a tree of your project dependencies with sponsor links for each organization/author.

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can <NuGetSponsor>true</NuGetSponsor> be included in the default csproj template? Similar to how ImplicitUsings and Nullable were introduced (on by default for new projects, but opt-in in principle).

See the future possibilities section.

Would also be nice to have something similar to npm fund. It can generate a tree of your project dependencies with sponsor links for each organization/author.

image

See the section showing the list command. Ideally you would use --include-transitives as well to show a similar graph.

<!-- What parts of the proposal do you expect to resolve before this gets accepted? -->
<!-- What parts of the proposal need to be resolved before the proposal is stabilized? -->
<!-- What related issues would you consider out of scope for this proposal but can be addressed in the future? -->
- The name `Sponsor` today is mostly inspired by GitHub Sponsors and the Visual Studio Code extension Sponsor button. Many other package registry's use the term `funding`, which may be a better name for this functionality. We can do pulse surveys to find the right name.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what's it worth, GitHub also uses funding.yml to define sponsorship options

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be fairly easy to convert funding.yml in the relevant MSBuild items 👍 .

@JonDouglas
Copy link
Contributor Author

Does using sponsor@type and Sponsors@Include imply a fixed list of sponsor platforms that will have to be part of the msbuild tooling?

Right now they would just be added to an ItemGroup, but the big question here is whether you can define any custom sponsor url or is there a fixed list of reputable ones? There are challenges with both, so we'd want to hear perspectives on what should be supported.

Copy link

@baronfel baronfel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.NET CLI would be happy to have this :)

Comment on lines +112 to +114
#### dotnet sponsor package <PACKAGE_NAME>

When an individual is feeling generous to sponsor a package, they can run the `dotnet sponsor package <PACKAGE_NAME>` command which will open up the default browser on their machine with the url of the first sponsor defined in the package metadata.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a little squeamish about creating a new top-level verb in the CLI for this, but there are no commands contributed by .NET SDK Tools on NuGet.org that I can see that would be squatting the verb, and other ecosystems also have it as a top-level. I'd be interested in thoughts about other commands the sponsor verb might grow in the future as a thought exercise.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not dotnet nuget sponsor?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the CLI we don't generally make as much of a distinction about which piece of tech is contributing the functionality - we try to focus on the action the user is taking, then do whatever transformations are required to make that happen. An example of this is dotnet add package - the user wants to add a package to a project, they don't necessarily care if it's nuget.exe doing it or the CLI itself, etc. Same theory here - the action is the important thing, not the specific tool that's used to achieve the action.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, don't make software too "smart", just print a set of links. By saving one click you make it impossible to use it in a script and view other options than the first one. dotnet add doesn't randomly download the first package from nuget.org :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WhiteBlackGoose It's a good point. This behavior was inspired by what npm does and I talked to their PM on this and what their rationale was for default behavior. Agreed that providing users choice for how they want to donate is ideal. But we also want to make it frictionless to suggest their preferred way. Hopefully that helps clear up the rationale here.

Comment on lines +68 to +70
<Sponsors Include="Patreon" Url="https://www.patreon.com/mypatreonusername"/>
<Sponsors Include="GitHub Sponsors" Url="https://github.com/sponsors/mygithubusername"/>
<Sponsors Include="Tidelift" Url="https://tidelift.com/subscription/pkg/mypackagename"/>
Copy link

@ltrzesniewski ltrzesniewski Oct 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most MSBuild item names are singular (like PackageReference for instance). I think Sponsor would be better suited.

Or maybe PackageSponsor to make it closer to the NuGet-specific properties?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sponsor sounds like it should refer to a person, so maybe Sponsorship instead? Or SponsorLink?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like Sponsor (singular) too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, will take this into account in the next pass.

Copy link
Contributor

@maartenba maartenba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally like the proposal, added a few comments.

<!-- What lessons from other communities can we learn from? -->
<!-- Are there any resources that are relevant to this proposal? -->

- [npm funding package.json metadata](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#funding)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With npm being in Microsoft as well (through GitHub), is there any data that shows whether this works for npm packages or not? Might be worth checking as part of the discussion/proposal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I actually reached out to npm and VS Code Marketplace. The summary can be found in the drawbacks section.

https://github.com/NuGet/Home/blob/sponsor-link/proposed/2023/sponsor-link.md#drawbacks

In Visual Studio's NuGet package manager UI, there will be a new link that says `Sponsor` which will open up a webpage to the first defined sponsor in the package metadata.

![Visual Studio Sponsor Experience](../2023/resources/VisualStudioSponsors.png)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can a section about API implementation be added? Will this be part of the search API or included in individual registrations? (search would be preferred as then getting the sponsorship info is only one API request).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will add it as we work on the technical explanation.


## Explanation

### Functional explanation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will there be an option to opt-out for a subset of package ids? This would be to filter out packages that are already being sponsored, which would reduce the signal to noise ratio in big dependency trees.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Let's leave this comment open for now however to understand the need for personalizing this functionality.

We simply display packages that contain the metadata. We do not track nor know what packages are being sponsored or to what satisfactory.


![NuGet.org Sponsor Experience](../2023/resources/NuGetOrgSponsors.png)

#### Visual Studio
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On IDE integration, some additional thinking may be required. Say I search for package A, which needs sponsorship, but it depends on package B that is a key infrastructure dependency for package A and it also would like sponsorship, how do I learn about this?

Similarly when package A has no sponsorship info but depends on package B which does, how do I learn about package B's sponsorship needs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is only a decent experience for this if a package is already installed. One could use the https://devblogs.microsoft.com/nuget/introducing-transitive-dependencies-in-visual-studio/ functionality to click and find out more about transitive packages and their sponsorship needs.

There is no experience for transitive packages in browsing. Only the top-level package will be clickable to see the sponsor link.

No future plans in this area right now as trying to keep the scope to an initial experience.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @JonDouglas. The problem of lifting metadata from transitive dependencies up to the top level at browsing (pre-installation) time is not unique to sponsorship. It exists for deprecation, target frameworks, vulnerabilities, ownership, etc. We should keep this first step as simple and not try to solve that broader system issue here.


## Explanation

### Functional explanation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What with dual-licensed packages, or "freemium" like IdentityServer, ImageSharp, ... - can they in this scheme add a link to their purchasing pages?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest. I don't have an opinion. We should keep in mind #12922 (comment) in these cases if this helps bring awareness to these unique sponsorship needs.


This proposal introduces an end-to-end experience of bringing visibility to the sponsorship requirements of open source packages on the NuGet.org registry and make NuGet tooling aware of it. This is to ensure that the sponsorship requirements make it down to the developers who are using open source software in a non-disruptive way.

Package authors will be able to express their sponsorship needs through new `sponsor` package metadata specifying a popular verified funding mechanism (GitHub Sponsors, Patreon, etc). This may consist of a list of reputable funding providers such as patreon, tidelift, github sponsors, and the relative link to each.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Package authors will be able to express their sponsorship needs through new `sponsor` package metadata specifying a popular verified funding mechanism (GitHub Sponsors, Patreon, etc). This may consist of a list of reputable funding providers such as patreon, tidelift, github sponsors, and the relative link to each.
Package authors will be able to express their sponsorship needs through new `sponsor` package metadata specifying a popular verified funding mechanism (GitHub Sponsors, Patreon, etc). This may consist of a list of reputable funding providers such as patreon, tidelift, github sponsors, and the respective link to each.

Relative link is a bit confusing :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, will add!

<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>My package description.</description>
</metadata>
<sponsors>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this should be under the <metadata> element like <packageTypes> and <repository>.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes. Good point. Didn't see the <packageTypes> prior art. Will move up in first revision.


```xml
<ItemGroup>
<Sponsors Include="Patreon" Url="https://www.patreon.com/mypatreonusername"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the Include should have the URL value, not the type. Akin to @Tyrrrz's comment, having a fallback URL behavior would be more straight forward if you can just drop an optional Type attribute.

Another way to think of this is the URL is sort of the unique part of the sponsorship item and the type is additional metadata to enhance the experience (e.g. a targeting icon in the UI or even deeper integration based on knowledge of the sponsorship type).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea!

@kzu
Copy link

kzu commented Oct 6, 2023

I'd like to see a sponsorable icon in the search results list itself, as proposed in https://developercommunity.visualstudio.com/t/Add-sponsorlink-visibility-in-the-NuGet/10456467? which looks like the following:

image

My eyes intuitively go to the results pane, not the details one. I rarely look in that direction.


On NuGet.org there will be a new `Sponsor this package` button which will open up a webpage to the first defined sponsor in the package metadata. Given there can be multiple sponsors, there may be an additional experience where one can click "all sponsors" and un-collapse the other options available.

![NuGet.org Sponsor Experience](../2023/resources/NuGetOrgSponsors.png)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do these experiences look like when there are multiple sponsorship URLs and/or types?

An analogy could be to how multiple sponsors are listed on the repository page on GitHub. Example, ILSpy:
https://github.com/icsharpcode/ILSpy
image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current design is minimized for the most prominent sponsor. This is a pretty common pattern for social media and other sponsorship platforms. We can explore collapsable controls to show additional sponsors, but designed this for simplicity sake (this is intentional to show and have 1).


On the opposite end, there may be a positive perception of awareness to a largely ignored problem. That individuals can bring more awareness to sponsorship needs and even build tooling on-top of this functionality to empower the .NET OSS community further.

## Rationale and alternatives
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see two other mechanisms to deliver sponsor metadata from author to consumer:

  1. Package owners can set sponsorship information on the package source web UI at the user or organization level. You'd set it up once and it would automatically flow to all of your packages that you directly own. We would have a similar "how to display multiple sponsorships" question that your package metadata allows but it comes from the fact that packages can have multiple owners.
  2. Package owners can set sponsorship information on the package source web UI at the package ID level. There could perhaps be an option to set it on all of the IDs you own, and automatically as new IDs get uploaded for the first time.

These are alternatives to baking the metadata into the .nuspec.

Some questions to help guide the decision:

  1. Is sponsorship information immutable per package version? Is it really an immutable concept?
    • I think the answer is most often no because we've faced frustration from package authors about immutable project URL when their DNS lapses or they change their repository location but not the content of the source tree.
  2. Do package owners want to advertise sponsorship on some versions but not others?
    • I think probably not. Ideally, it's show on all versions, right? But showing it only on the latest version (or newly published versions) is probably good enough since we know consumers browse latest metadata most often.
  3. Do package owners want to have different sponsorship information per package they own?
    • I don't have an answer for this. The package metadata model allows this, the package ID-level metadata model allows this. The user/org-level metadata model does not allow this.
  4. Is there a reasonable way to get server-only metadata on the Installed tab in VS. Said another way, do you want sponsorship information for offline contexts?
    • If we want to show sponsorship on the Installed tab, either we need to fetch and cache it or it need to be inside the package. This begins to feel a lot like the Vulnerability metadata problem where you want to light it up quickly without a million server round trips in restore. In other words, if the sponsor metadata is not in the package (it only lives on the server) we would need to build a high-performance mechanism for restore to report all transitive sponsorships.

Taking a server-side metadata option that I suggested may be much cheaper from the implementation perspective. We just need to do the protocol changes to share this new metadata and some NuGet.org UI. But there are drawbacks in the experience as listed above.

Copy link
Contributor Author

@JonDouglas JonDouglas Oct 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My research and cross-ecosystem comparisons/talks with other pkg mgmt pms suggests this should all be done inside the confines of a package. Anything registry specific may be challenging to understand and formally document.

That way people can change their sponsors as their project develops. Maybe they always have sponsor data, maybe they meet their goals and remove the metadata in future releases or change it to a cause they would rather promote than themselves. etc.

Maybe this is a good polling opportunity. Do people want to declare sponsors at pack time or publish time.

🚀 - Pack (NuGet tooling)
❤️ - Publish (NuGet.org)

@egil
Copy link

egil commented Oct 6, 2023

It wasn't clear to me from the text whether this is already covered, but transitive packages sponsor needs should also be highlighted.

@JonDouglas
Copy link
Contributor Author

It wasn't clear to me from the text whether this is already covered, but transitive packages sponsor needs should also be highlighted.

Yes, there are multiple experiences already and other threads above about this already. I want to be transparent and say that majority of developers don't even know what a transitive package is(based on regular surveys and interviews), but we do have options and tools to show them as of recently.

There are some great ideas from others here, but I'm not so sure how much we can additionally add without scope creep in this proposal. You will be able to click through transitive packages and view their details. You will be able to use dotnet list commands to show them as well and declared sponsorships. I can highlight these use-cases better as I think that's the challenge you're calling out. i.e. --include-transitive and our recent transitive dependencies feature in Visual Studio.

@JonDouglas
Copy link
Contributor Author

I'd like to see a sponsorable icon in the search results list itself, as proposed in https://developercommunity.visualstudio.com/t/Add-sponsorlink-visibility-in-the-NuGet/10456467? which looks like the following:

image

My eyes intuitively go to the results pane, not the details one. I rarely look in that direction.

Looks nice. Might be nice to pair a future filter too for "Needs sponsorship". See #12704

<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>My package description.</description>
</metadata>
<sponsors>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somehow, I believe that the word sponsors might be interpreted as referring to current sponsors for a particular package. However, the intention is to notify consumers that the package author is seeking sponsorship for the maintenance of this package. I believe that the word sponsorship may be more appropriate here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thought here, I think we need a better name such as funding or requiresFunding: true and then list options

@ghost ghost added the Status:No recent activity No recent activity. label Nov 15, 2023
@ghost
Copy link

ghost commented Nov 15, 2023

This PR has been automatically marked as stale because it has no activity for 30 days. It will be closed if no further activity occurs within another 15 days of this comment, unless it has a "Status:Do not auto close" label. If it is closed, you may reopen it anytime when you're ready again, as long as you don't delete the branch.

@JonDouglas
Copy link
Contributor Author

Thanks StaleBot... I will be OOF for a few weeks, but this proposal looks like it is in a good enough shape to proceed. I will take a pass at the open feedback in December and we'll work to get this finalized to merge.

@ghost ghost removed the Status:No recent activity No recent activity. label Nov 15, 2023
@jeffkl jeffkl added the Status:Do not auto close Do not auto close for PRs needs long review process label Nov 21, 2023
@ghost ghost added the Status:No recent activity No recent activity. label Dec 21, 2023
@ghost
Copy link

ghost commented Dec 21, 2023

This PR has been automatically marked as stale because it has no activity for 30 days. It will be closed if no further activity occurs within another 15 days of this comment, unless it has a "Status:Do not auto close" label. If it is closed, you may reopen it anytime when you're ready again, as long as you don't delete the branch.

@FlorianRappl
Copy link

Months have passed and I wonder what's blocking this?

@dotnet-policy-service dotnet-policy-service bot removed the Status:No recent activity No recent activity. label Mar 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status:Do not auto close Do not auto close for PRs needs long review process
Projects
None yet
Development

Successfully merging this pull request may close these issues.