Skip to content

Commit 3c00b19

Browse files
committed
Auto merge of #13771 - noritada:feature/release-notes-on-github-releases, r=lnicola
Add xtask for publishing release notes in Markdown on GitHub Releases from a changelog in AsciiDoc This PR provides `xtask publish-release-notes` to convert a changelog written in AsciiDoc to Markdown and update descriptions (release notes) of a corresponding entry on GitHub Releases. This AsciiDoc parser is not capable of processing every AsciiDoc document, but I have surveyed a set of existing changelog entries and have confirmed that the following notations used can be converted properly. In the future, I would like to improve the parser to accept any AsciiDoc. Alternatively, the parser could be moved out of the project. Your feedback would be appreciated! Closes #13191 ### Supported AsciiDoc syntax many occurrences - [x] documentation header - [x] section header - [x] `*`-prefixed basic unordered single level list item - [x] list continuation using `+` - [x] block image macro `image::...[]` with empty alt - [x] block image macro `image::...[]` with non-empty alt - [x] block video marco `video::...[]` with `options=loop` - [x] inline hard line break `+` - [x] inline custom macro `commit:...[]` - [x] inline custom macro `release:...[]` - [x] inline custom macro `pr:...[]` - [x] inline unconstrained bold text `**...**` - [x] inline constrained monospace ``` `...` ``` [thisweek/_posts/2019-07-24-changelog-0.adoc](https://github.com/rust-analyzer/rust-analyzer.github.io/tree/src/thisweek/_posts#:~:text=2019%2D07%2D24%2Dchangelog%2D0.adoc) - [x] paragraphs - [x] mixture of `*` and `-` for unordered list item prefix - [x] inline external link `https://...[]` [thisweek/_posts/2020-01-13-changelog-7.adoc](https://github.com/rust-analyzer/rust-analyzer.github.io/tree/src/thisweek/_posts#:~:text=2020%2D01%2D13%2Dchangelog%2D7.adoc) - [x] list item with multiline principal text with indent - [x] inline image macro `image:...[]` [thisweek/_posts/2020-03-02-changelog-14.adoc](https://github.com/rust-analyzer/rust-analyzer.github.io/blob/src/thisweek/_posts/2020-03-02-changelog-14.adoc) - [x] empty lines between list items - [x] nested unordered list item with `**` - [x] inline macro `kbd:[...]` [thisweek/_posts/2020-03-16-changelog-16.adoc](https://github.com/rust-analyzer/rust-analyzer.github.io/blob/src/thisweek/_posts/2020-03-16-changelog-16.adoc) - [x] `[source]`-prefixed listing [thisweek/_posts/2020-04-06-changelog-19.adoc](https://github.com/rust-analyzer/rust-analyzer.github.io/blob/src/thisweek/_posts/2020-04-06-changelog-19.adoc) - [x] list item with multiline principal text without indent - [x] `[source,lang]`-prefixed listing - [x] `.`-prefiexed ordered list item - [x] list item immediately after list continuation paragraph without an empty line in between [thisweek/_posts/2020-04-20-changelog-21.adoc](https://github.com/rust-analyzer/rust-analyzer.github.io/blob/src/thisweek/_posts/2020-04-20-changelog-21.adoc) - [x] title line for block image [thisweek/_posts/2020-12-21-changelog-56.adoc](https://github.com/rust-analyzer/rust-analyzer.github.io/blob/src/thisweek/_posts/2020-12-21-changelog-56.adoc) - [x] block video `video::...[]` with `options="autoplay,loop"`
2 parents 761b127 + fccc094 commit 3c00b19

File tree

7 files changed

+932
-3
lines changed

7 files changed

+932
-3
lines changed

docs/dev/README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ Look for `fn benchmark_xxx` tests for a quick way to reproduce performance probl
200200

201201
## Release Process
202202

203-
Release process is handled by `release`, `dist` and `promote` xtasks, `release` being the main one.
203+
Release process is handled by `release`, `dist`, `publish-release-notes` and `promote` xtasks, `release` being the main one.
204204

205205
`release` assumes that you have checkouts of `rust-analyzer`, `rust-analyzer.github.io`, and `rust-lang/rust` in the same directory:
206206

@@ -231,8 +231,9 @@ Release steps:
231231
* create a new changelog in `rust-analyzer.github.io`
232232
3. While the release is in progress, fill in the changelog
233233
4. Commit & push the changelog
234-
5. Tweet
235-
6. Inside `rust-analyzer`, run `cargo xtask promote` -- this will create a PR to rust-lang/rust updating rust-analyzer's subtree.
234+
5. Run `cargo xtask publish-release-notes <CHANGELOG>` -- this will convert the changelog entry in AsciiDoc to Markdown and update the body of GitHub Releases entry.
235+
6. Tweet
236+
7. Inside `rust-analyzer`, run `cargo xtask promote` -- this will create a PR to rust-lang/rust updating rust-analyzer's subtree.
236237
Self-approve the PR.
237238

238239
If the GitHub Actions release fails because of a transient problem like a timeout, you can re-run the job from the Actions console.

xtask/src/flags.rs

+15
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ xflags::xflags! {
3434
cmd dist {
3535
optional --client-patch-version version: String
3636
}
37+
/// Read a changelog AsciiDoc file and update the GitHub Releases entry in Markdown.
38+
cmd publish-release-notes {
39+
/// Only run conversion and show the result.
40+
optional --dry-run
41+
/// Target changelog file.
42+
required changelog: String
43+
}
3744
cmd metrics {
3845
optional --dry-run
3946
}
@@ -59,6 +66,7 @@ pub enum XtaskCmd {
5966
Release(Release),
6067
Promote(Promote),
6168
Dist(Dist),
69+
PublishReleaseNotes(PublishReleaseNotes),
6270
Metrics(Metrics),
6371
Bb(Bb),
6472
}
@@ -90,6 +98,13 @@ pub struct Dist {
9098
pub client_patch_version: Option<String>,
9199
}
92100

101+
#[derive(Debug)]
102+
pub struct PublishReleaseNotes {
103+
pub changelog: String,
104+
105+
pub dry_run: bool,
106+
}
107+
93108
#[derive(Debug)]
94109
pub struct Metrics {
95110
pub dry_run: bool,

xtask/src/main.rs

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ mod flags;
1515
mod install;
1616
mod release;
1717
mod dist;
18+
mod publish;
1819
mod metrics;
1920

2021
use anyhow::bail;
@@ -36,6 +37,7 @@ fn main() -> anyhow::Result<()> {
3637
flags::XtaskCmd::Release(cmd) => cmd.run(sh),
3738
flags::XtaskCmd::Promote(cmd) => cmd.run(sh),
3839
flags::XtaskCmd::Dist(cmd) => cmd.run(sh),
40+
flags::XtaskCmd::PublishReleaseNotes(cmd) => cmd.run(sh),
3941
flags::XtaskCmd::Metrics(cmd) => cmd.run(sh),
4042
flags::XtaskCmd::Bb(cmd) => {
4143
{

xtask/src/publish.rs

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
mod notes;
2+
3+
use crate::flags;
4+
use anyhow::{anyhow, bail, Result};
5+
use std::env;
6+
use xshell::{cmd, Shell};
7+
8+
impl flags::PublishReleaseNotes {
9+
pub(crate) fn run(self, sh: &Shell) -> Result<()> {
10+
let asciidoc = sh.read_file(&self.changelog)?;
11+
let mut markdown = notes::convert_asciidoc_to_markdown(std::io::Cursor::new(&asciidoc))?;
12+
let file_name = check_file_name(self.changelog)?;
13+
let tag_name = &file_name[0..10];
14+
let original_changelog_url = create_original_changelog_url(&file_name);
15+
let additional_paragraph =
16+
format!("\nSee also [original changelog]({original_changelog_url}).");
17+
markdown.push_str(&additional_paragraph);
18+
if self.dry_run {
19+
println!("{markdown}");
20+
} else {
21+
update_release(sh, tag_name, &markdown)?;
22+
}
23+
Ok(())
24+
}
25+
}
26+
27+
fn check_file_name<P: AsRef<std::path::Path>>(path: P) -> Result<String> {
28+
let file_name = path
29+
.as_ref()
30+
.file_name()
31+
.ok_or_else(|| anyhow!("file name is not specified as `changelog`"))?
32+
.to_string_lossy();
33+
34+
let mut chars = file_name.chars();
35+
if file_name.len() >= 10
36+
&& chars.next().unwrap().is_ascii_digit()
37+
&& chars.next().unwrap().is_ascii_digit()
38+
&& chars.next().unwrap().is_ascii_digit()
39+
&& chars.next().unwrap().is_ascii_digit()
40+
&& chars.next().unwrap() == '-'
41+
&& chars.next().unwrap().is_ascii_digit()
42+
&& chars.next().unwrap().is_ascii_digit()
43+
&& chars.next().unwrap() == '-'
44+
&& chars.next().unwrap().is_ascii_digit()
45+
&& chars.next().unwrap().is_ascii_digit()
46+
{
47+
Ok(file_name.to_string())
48+
} else {
49+
bail!("unexpected file name format; no date information prefixed")
50+
}
51+
}
52+
53+
fn create_original_changelog_url(file_name: &str) -> String {
54+
let year = &file_name[0..4];
55+
let month = &file_name[5..7];
56+
let day = &file_name[8..10];
57+
let mut stem = &file_name[11..];
58+
if let Some(stripped) = stem.strip_suffix(".adoc") {
59+
stem = stripped;
60+
}
61+
format!("https://rust-analyzer.github.io/thisweek/{year}/{month}/{day}/{stem}.html")
62+
}
63+
64+
fn update_release(sh: &Shell, tag_name: &str, release_notes: &str) -> Result<()> {
65+
let token = match env::var("GITHUB_TOKEN") {
66+
Ok(token) => token,
67+
Err(_) => bail!("Please obtain a personal access token from https://github.com/settings/tokens and set the `GITHUB_TOKEN` environment variable."),
68+
};
69+
let accept = "Accept: application/vnd.github+json";
70+
let authorization = format!("Authorization: Bearer {token}");
71+
let api_version = "X-GitHub-Api-Version: 2022-11-28";
72+
let release_url = "https://api.github.com/repos/rust-lang/rust-analyzer/releases";
73+
74+
let release_json = cmd!(
75+
sh,
76+
"curl -sf -H {accept} -H {authorization} -H {api_version} {release_url}/tags/{tag_name}"
77+
)
78+
.read()?;
79+
let release_id = cmd!(sh, "jq .id").stdin(release_json).read()?;
80+
81+
let mut patch = String::new();
82+
write_json::object(&mut patch)
83+
.string("tag_name", tag_name)
84+
.string("target_commitish", "master")
85+
.string("name", tag_name)
86+
.string("body", release_notes)
87+
.bool("draft", false)
88+
.bool("prerelease", false);
89+
let _ = cmd!(
90+
sh,
91+
"curl -sf -X PATCH -H {accept} -H {authorization} -H {api_version} {release_url}/{release_id} -d {patch}"
92+
)
93+
.read()?;
94+
95+
Ok(())
96+
}
97+
98+
#[cfg(test)]
99+
mod tests {
100+
use super::*;
101+
102+
#[test]
103+
fn original_changelog_url_creation() {
104+
let input = "2019-07-24-changelog-0.adoc";
105+
let actual = create_original_changelog_url(input);
106+
let expected = "https://rust-analyzer.github.io/thisweek/2019/07/24/changelog-0.html";
107+
assert_eq!(actual, expected);
108+
}
109+
}

0 commit comments

Comments
 (0)