-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: Crate changelog field #3779
base: master
Are you sure you want to change the base?
Changes from all commits
1aa9906
452e2cd
4e99d94
f36581d
ef9c719
2ac646d
bb7b340
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,305 @@ | ||||||
- Feature Name: crate-changelog-field | ||||||
- Start Date: 2025-02-25 | ||||||
- RFC PR: (leave this empty) | ||||||
- Rust Issue: (leave this empty) | ||||||
|
||||||
# Summary | ||||||
[summary]: #summary | ||||||
|
||||||
Add changelog support to `cargo`, [crates.io](https://crates.io/) and [doc.rs](https://doc.rs/). | ||||||
|
||||||
# Motivation | ||||||
[motivation]: #motivation | ||||||
|
||||||
Citing [keepachangelog.com](http://keepachangelog.com): | ||||||
|
||||||
> What is a changelog? | ||||||
> | ||||||
> A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of a project. | ||||||
> | ||||||
> Why keep a changelog? | ||||||
> | ||||||
> To make it easier for users and contributors to see precisely what notable changes have been made between each release (or version) of the project. | ||||||
> | ||||||
> Who needs a changelog? | ||||||
> | ||||||
> People do. Whether consumers or developers, the end users of software are | ||||||
> human beings who care about what's in the software. When the software changes, | ||||||
> people want to know why and how. | ||||||
|
||||||
Encouraging crate authors to keep changelogs and increase its visibility for | ||||||
crate users will definitely benefit crates ecosystem. | ||||||
|
||||||
From a consumer's perspective, this feature could make the discovery of the changelog much easier. | ||||||
For instance, the "crates" plugin could leaverage this field to show a link to | ||||||
the changelog when a user hovers on a dependency in `Cargo.toml`. | ||||||
|
||||||
 | ||||||
|
||||||
Current situation: a consumer usually needs to jump through several hops to find the changelog: | ||||||
|
||||||
```mermaid | ||||||
flowchart LR; | ||||||
editor["crates" plugin in vscode] | ||||||
crates-io[crates.io crate page] | ||||||
doc-rs[doc.rs crate page] | ||||||
crate-web[crate website] | ||||||
github[crate repository] | ||||||
google["Google search result"] | ||||||
repo-changelog[changelog in repository] | ||||||
web-changelog[changelog on a website] | ||||||
doc-changelog[changelog on doc.rs] | ||||||
editor --> crates-io | ||||||
editor --> doc-rs | ||||||
crates-io --> github | ||||||
github --> repo-changelog | ||||||
github --> web-changelog | ||||||
github --> doc-changelog | ||||||
google --> crates-io | ||||||
google --> github | ||||||
google --> doc-rs | ||||||
google -->|unlikely| repo-changelog | ||||||
google --> web-changelog | ||||||
google --> doc-changelog | ||||||
google --> crate-web | ||||||
crate-web --> web-changelog | ||||||
crate-web --> repo-changelog | ||||||
crate-web --> doc-changelog | ||||||
doc-rs --> doc-changelog | ||||||
doc-rs --> web-changelog | ||||||
doc-rs --> crates-io | ||||||
doc-rs --> crate-web | ||||||
doc-rs --> github | ||||||
``` | ||||||
|
||||||
This topic was brought several times, most notable notions are: | ||||||
|
||||||
- [Previously closed RFC](https://github.com/rust-lang/rfcs/pull/2129) | ||||||
- [Rustaceans: Please Keep a Changelog!](https://blog.dbrgn.ch/2015/12/1/rust-crates-keep-a-changelog/) ([reddit](https://www.reddit.com/r/rust/comments/3v1ndl/)) | ||||||
- [Cargo issue](https://github.com/rust-lang/cargo/issues/2188) | ||||||
- [Reddit thread](https://www.reddit.com/r/rust/comments/6vvhjh/) | ||||||
|
||||||
# Guide-level explanation | ||||||
[guide-level-explanation]: #guide-level-explanation | ||||||
|
||||||
An optional `changelog` field is available, which is currently in the format | ||||||
of a URL to an external resource. | ||||||
|
||||||
Examples: | ||||||
|
||||||
```toml | ||||||
[package] | ||||||
name = "foo" | ||||||
version = "0.1.0" | ||||||
changelog = "https://github.com/foo-org/foo/releases" | ||||||
``` | ||||||
|
||||||
```toml | ||||||
[package] | ||||||
name = "bar" | ||||||
version = "1.0.0" | ||||||
changelog = "https://github.com/bar-org/bar/blob/main/CHANGELOG.md" | ||||||
``` | ||||||
|
||||||
For crates with `changelog` field, crates.io and docs.rs show a link to the | ||||||
changelog in the corresponding page of the crate. | ||||||
|
||||||
# Reference-level explanation | ||||||
[reference-level-explanation]: #reference-level-explanation | ||||||
|
||||||
## Cargo | ||||||
|
||||||
A new `changelog` field will be added to crate manifest, | ||||||
which only accepts valid URL for now. | ||||||
However, it is explicitly stated that in the future the field could be | ||||||
extended to handle other formats than URL and such a change is not considered | ||||||
breaking. | ||||||
So external tools should expect that the field could contain contents that are | ||||||
not valid URL and handle it with caution. | ||||||
|
||||||
For a cargo workspace, it is possible for several crates to share a changelog | ||||||
via the usage of `changelog.workspace`, just like | ||||||
[`documentation.workspace`](https://doc.rust-lang.org/cargo/reference/workspaces.html#the-package-table). | ||||||
|
||||||
For now, `cargo publish` will check if the `changelog` field is a valid URL, | ||||||
unless `--no-verify` is also specified. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If its a url, shouldn't that be part of the schema and always error (on any command), if present? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My initial idea was that when non-url path become supported for But I agree with @weihanglo that we should use a different flag because There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If parsers are supposed to get any meaning from the field, it likely needs one format. Alternative formats could be handled with alternate fields (like license and license-file) or dotted keys (e.g. this could be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Agree with this. It depends on how much functionality we expect from this field. |
||||||
`cargo publish` does not check if the URL in the `changelog` field points | ||||||
to a valid changelog resource. | ||||||
|
||||||
## Crates.io and docs.rs | ||||||
|
||||||
A new link to the changelog will show up in crates.io and docs.rs for crates | ||||||
that uses the `changelog` field. | ||||||
|
||||||
crates.io and docs.rs should again check if the field is valid URL. | ||||||
If the field is not valid URL, nothing shows. | ||||||
|
||||||
For docs.rs, this link can be added to the `Links` section of the | ||||||
`<crate-name>-<version>` drop-down menu. | ||||||
|
||||||
For crates.io, this link can be placed in the right(in desktop mode) sidebar, | ||||||
alongside with other links like `Repository` and `Documentation`. | ||||||
And additionally, the link can show in the crate cards in crates.io search | ||||||
results, as `Homepage` and `Repository` links also show there. | ||||||
|
||||||
# Drawbacks | ||||||
[drawbacks]: #drawbacks | ||||||
|
||||||
- This proposal does not check if the `changelog` field points to a valid | ||||||
external changelog, requiring crate authors to do that check themselves. | ||||||
- This proposal does not require the changelog to be present in the crate, | ||||||
making offline usage of the `chagelog` field impractical. | ||||||
- This proposal does not constrain the format of the changelog, making it hard | ||||||
for external tools to consume the contents of the changelog. | ||||||
Comment on lines
+145
to
+153
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another drawback: this requires treating packages in a workspace as a pet (individual care), rather than cattle (only group care) which we've been moving away from with features like workspace inheritance, automatic docs.rs links etc. If I were to use this in a workspace, I have to manually set up the link when creating or moving a workspace member without any way to verify it until I push to the upstream repo. By the time the new package is merged, I'm unlikely to remember to go back and test the link. I'm also unlikely to remember to test when publishing. Most likely, I'll only discover there is a problem when someone reports it. Today, the amount of per-package metadata I have to enter is minimal and is almost all verified locally or at least before publish. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These last few comments let me to conclusion that But I feel I'm running too far with this idea in the context of this RFC. Whatever angle I look at this, I see (as with The whole idea only makes sense of the changelog shows changes for particular release, not some generic journal of changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't just require deeper git integration (and lack of support for other vcs') but Cargo to know your tag format and to handle changes in tag formats. As mentioned elsewhere, commits are also a fairly low quality changelog. That can be improved through conventions but then we'd need to enforce those conventions. Those conventions also do not help when a commit crosses multiple packages.
The challenge is doing so without running into the problems #2129 ran into. At least with this RFC, if I were to feel comfortable setting this up for all workspace members, I would tweak my changlogs so the anchors are more predictable and setup a |
||||||
- Although `changelog` URL usually won't change from release to release, | ||||||
sometimes a crate might change its `changelog` URL, which could invalidate | ||||||
the `changelog` URLs in previously published versions. This is a clear indication | ||||||
that `changelog` URL is inheritly a piece of mutable metadata that could be kept per | ||||||
crate instead of per crate version. However, currently there is no ideal solution | ||||||
to handle mutable metadata associated with crates. | ||||||
|
||||||
# Rationale and Alternatives | ||||||
[rationale-and-alternatives]: #rationale-and-alternatives | ||||||
|
||||||
## Rationale | ||||||
[rationale]: #rationale | ||||||
|
||||||
Most of the time, the producer of changelogs are crate authors | ||||||
and the consumer of changelogs are other crate authors. | ||||||
For human consumption, it is ideal to have the changelog in a rendered format. | ||||||
But handling rendering of various formats in crates.io is a heavy task. | ||||||
However, many existing crates already have changelogs available in their | ||||||
repository and the websites backing their repositories can already render the | ||||||
changelogs. So, in order to avoid unnecessary efforts, this RFC proposes to | ||||||
just use a valid URL for the `changelog` field. | ||||||
|
||||||
## Alternative: Previously closed RFC | ||||||
[alternative-previously-closed-rfc]: #alternative-previously-closed-rfc | ||||||
|
||||||
[Previously closed RFC](https://github.com/rust-lang/rfcs/pull/2129) | ||||||
proposed to use a strictly formatted Markdown file or an external link for the | ||||||
changelog field. The strict format, while ideal for machine consumption, | ||||||
imposes too much constraint and lead to a refusal. | ||||||
|
||||||
Another critic of the previous RFC is that if this field is just a link that will be displayed, | ||||||
then it seems to not bring much value over placing a link within a README. | ||||||
However, placing a link in README adds another indirection for discovering the changelog, | ||||||
and it effectively prevents other sources from making the changelog more discoverable. | ||||||
For example, third-party editor plugins showing crate information in the context of cargo | ||||||
manifest files cannot leverage the link from README to make changelog more discoverable. | ||||||
|
||||||
## Alternative: Local File | ||||||
[alternative-local-file]: #alternative-local-file | ||||||
|
||||||
The `changelog` field can be a path to a file within the crate, | ||||||
which opens the possibility for crates.io to render it directly. | ||||||
However, people have different opinions when it comes to what format the | ||||||
changelog should use. While markdown is currently the most popular choice, | ||||||
plain text and reStructuredText are also in use. | ||||||
Instead of handling the rendering of various different formats of changelog in | ||||||
crates.io, it is much easier to just have an external link, where an external | ||||||
website handles the rendering of the changelog so that crate authors can use | ||||||
any format they see fit for their changelogs. | ||||||
|
||||||
And changelogs grow over time, which can take significant amount of disk spaces | ||||||
for crates.io, considering that usually every single release of a crate | ||||||
will contain all changelogs up to that release. | ||||||
This particular drawback can be solved by introducing new linting rules. | ||||||
|
||||||
From another perspective, using an external link can guarantee that we can | ||||||
always link to the latest changelog, which is supposed to contain all | ||||||
changelog entries from initial versions to unreleased commits. | ||||||
If we adopt the local file approach, when we view an outdated version of a | ||||||
crate on docs.rs, we only get a link to the outdated changelog, which is not | ||||||
helpful for viewing the breaking changes introduced in new versions, requiring | ||||||
another click on the doc.rs page to switch to the latest version. | ||||||
|
||||||
## Alternative: Do Nothing | ||||||
[alternative-do-nothing]: #alternative-do-nothing | ||||||
|
||||||
It has been several years after the initial changelog RFC. | ||||||
We can continue to live without this enhancement. | ||||||
|
||||||
It is possible to create an external registry that collects the links of | ||||||
changelogs. However, such effort is neither scalable nor ideal. | ||||||
|
||||||
# Prior art | ||||||
[prior-art]: #prior-art | ||||||
kxxt marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
## NPM | ||||||
|
||||||
[Before npm v7, files named `CHANGES` / `CHANGELOG` / `HISTORY` are always included regardless of settings](https://docs.npmjs.com/cli/v6/configuring-npm/package-json#files). | ||||||
In npm v7, [those files are no longer always included](https://github.com/npm/npm-packlist/pull/61). | ||||||
npm does not impose any constraint on the format of those files. | ||||||
And the website of npm registry doesn't make the changelog more accessible to users. | ||||||
|
||||||
[A changelog RFC that purposes to introduce `changelog` command to npm](https://github.com/npm/rfcs/pull/8) | ||||||
was approved in 2018 but got [withdrawn](https://github.com/npm/rfcs/blob/main/withdrawn/0002-changelog.md) later in 2021. | ||||||
This command makes it easy to view the changelog for a library. | ||||||
|
||||||
The main points for withdrawal are | ||||||
|
||||||
- npm no longer always include `CHANGES` / `CHANGELOG` / `HISTORY` files after v7. | ||||||
- Managing changelog is considered outside of the scope of the **npm cli** | ||||||
- The RFC is long inactive after being approved. | ||||||
- Current **npm cli** team is unlikely to implement it | ||||||
|
||||||
## PyPI | ||||||
|
||||||
`pyproject.toml` supports `project.urls` table which includes a list of URLs associated with the project. | ||||||
And these URLs are displayed on the left sidebar of the project page on PyPI. | ||||||
|
||||||
```toml | ||||||
[project.urls] | ||||||
Homepage = "https://example.com" | ||||||
Documentation = "https://readthedocs.org" | ||||||
Repository = "https://github.com/me/spam.git" | ||||||
Issues = "https://github.com/me/spam/issues" | ||||||
Changelog = "https://github.com/me/spam/blob/master/CHANGELOG.md" | ||||||
``` | ||||||
|
||||||
They keeps [a list of well-known labels](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#urls) | ||||||
which includes `changelog`(with alias `changes`, `whatsnew` and `history`) and `releasenotes`. | ||||||
|
||||||
A [search](https://grep.app/search?f.lang=TOML&f.lang.pattern=toml&f.path.pattern=pyproject.toml&q=Changelog+%3D) | ||||||
for the usage of `changelog` url in `pyproject.toml` yields many results. | ||||||
|
||||||
## CRAN | ||||||
|
||||||
The R community follows the GNU convention for [`NEWS`](https://www.gnu.org/prep/standards/standards.html#NEWS-File) | ||||||
and [`ChangeLog`](https://www.gnu.org/prep/standards/standards.html#Change-Logs) files. | ||||||
|
||||||
The `NEWS` file contains a list of user-visible changes worth mentioning. Items for old versions are not discarded. | ||||||
When `NEWS` file become too big, some of the older items should be moved into `ONEWS` file and | ||||||
a note referring the user to that file should be put at the end of `NEWS` file. | ||||||
|
||||||
The `NEWS` file can be in plaintext(`NEWS`), Markdown(`NEWS.md`) or R document(`inst/NEWS.Rd`) formats. | ||||||
|
||||||
|
||||||
The `Changelog` file is more detailed and accurate, including developer-facing changes. | ||||||
|
||||||
By default, `NEWS` file will be included into a CRAN package but `Changelog` will not, | ||||||
as documented in the [package structure of an R package](https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Package-structure-1). | ||||||
|
||||||
The CRAN website shows a link to the [rendered `NEWS` file](https://cran.r-project.org/web/packages/ggplot2/news/news.html) | ||||||
on the package's web page. | ||||||
|
||||||
R also provides a function `news()` for building and querying R or package news information, | ||||||
which comes handy when in a REPL or IDE like RStudio. | ||||||
|
||||||
# Unresolved questions | ||||||
[unresolved]: #unresolved-questions | ||||||
|
||||||
|
||||||
# Future possibilities | ||||||
[future-possibilities]: #future-possibilities | ||||||
|
||||||
Future RFC could make other formats of the `changelog` field possible | ||||||
as this RFC has explicitly reserved that possibility. | ||||||
|
||||||
Future RFC could introduce `changelog.generator`/`changelog.format` fields | ||||||
which could indicate the generator or the format of the changelog. | ||||||
This is helpful for machine consumption. | ||||||
|
||||||
Future RFC could introduce a clippy warning that warns if the crate does not | ||||||
contain a `changelog` field. |
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.
Mechanism vs policy is tricky.
From a mechanism perspective, this seems ok (these two pieces fit together, let people create whatever solution they want).
From a policy perspective, I worry this will lead to a lot of incorrect links. A
repository
link is rightfully shared in a workspace.clap
,clap_derive
, andclap_builer
can rightfully share a changelog. But once its inworkspace.package
, it is unclear what all its relevant for. For example,cargo new
will automatically inherit everything inworkspace.package
which can lead to inheriting irrelevant changelogs. For example, if I runcargo new clap_complete_fish
, I'll getclap
s changelog. That could be easy to overlook and only find out if you test our your own links once published.The example is given of
documentation.workspace
. We didn't think too much on what field to include (there are other, more clear cases of regrets for what we allowed to inherit) and have often overlooked that because it rarely needs to be set these days because crates.io infers it.