Skip to content

Commit 796ec63

Browse files
WIP: test(CHANGELOG): add and use --emit-github-messages to cargo xtask changelog
TODO: Lines seem off in output. WTF? TODO: fix tests
1 parent cedc7f4 commit 796ec63

File tree

3 files changed

+42
-12
lines changed

3 files changed

+42
-12
lines changed

.github/workflows/changelog.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ jobs:
3939

4040
- name: Run `cargo xtask changelog …`
4141
run: |
42-
cargo xtask changelog "origin/${{ github.event.pull_request.base.ref }}"
42+
cargo xtask changelog --emit-github-messages "origin/${{ github.event.pull_request.base.ref }}"

xtask/src/changelog.rs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use xshell::Shell;
44
pub(crate) fn check_changelog(shell: Shell, mut args: Arguments) -> anyhow::Result<()> {
55
const CHANGELOG_PATH_RELATIVE: &str = "./CHANGELOG.md";
66

7+
let emit_github_messages = args.contains("--emit-github-messages");
8+
79
let from_branch = args
810
.free_from_str()
911
.ok()
@@ -60,7 +62,17 @@ pub(crate) fn check_changelog(shell: Shell, mut args: Arguments) -> anyhow::Resu
6062
}
6163

6264
for hunk in &hunks_in_a_released_section {
63-
eprintln!("{hunk}");
65+
eprintln!("{}", hunk.contents);
66+
67+
if emit_github_messages {
68+
let title = "Released changelog content changed";
69+
let message =
70+
"This PR changes changelog content that is already released.".to_owned();
71+
println!(
72+
"::error file=CHANGELOG.md,line={},endLine={},title={title}::{message}",
73+
hunk.change_start_line_num, hunk.change_end_line_num,
74+
)
75+
}
6476
}
6577
}
6678

@@ -76,6 +88,12 @@ pub(crate) fn check_changelog(shell: Shell, mut args: Arguments) -> anyhow::Resu
7688
}
7789
}
7890

91+
struct Hunk<'a> {
92+
change_start_line_num: u64,
93+
change_end_line_num: u64,
94+
contents: &'a str,
95+
}
96+
7997
/// Given some `changelog_contents` (in Markdown) containing the full end state of the provided
8098
/// `diff` (in [unified diff format]), return all hunks that are (1) below a `## Unreleased` section
8199
/// _and_ (2) above all other second-level (i.e., `## …`) headings.
@@ -90,7 +108,7 @@ pub(crate) fn check_changelog(shell: Shell, mut args: Arguments) -> anyhow::Resu
90108
/// `changelog_contents`. using hunk information to compare against `changelog_contents`.
91109
///
92110
/// Failing to uphold these assumptons is not unsafe, but will yield incorrect results.
93-
fn hunks_in_a_released_section<'a>(changelog_contents: &str, diff: &'a str) -> Vec<&'a str> {
111+
fn hunks_in_a_released_section<'a>(changelog_contents: &str, diff: &'a str) -> Vec<Hunk<'a>> {
94112
let mut changelog_lines = changelog_contents.lines();
95113

96114
let changelog_unreleased_line_num =
@@ -109,7 +127,7 @@ fn hunks_in_a_released_section<'a>(changelog_contents: &str, diff: &'a str) -> V
109127
SplitPrefixInclusive::new("\n@@", &diff[first_hunk_idx..]).map(|s| &s['\n'.len_utf8()..])
110128
};
111129
let hunks_in_a_released_section = hunks
112-
.filter(|hunk| {
130+
.filter_map(|hunk| {
113131
let (hunk_header, hunk_contents) = hunk.split_once('\n').unwrap();
114132

115133
// Reference: This is of the format `@@ -86,6 +88,10 @@ …`.
@@ -128,15 +146,25 @@ fn hunks_in_a_released_section<'a>(changelog_contents: &str, diff: &'a str) -> V
128146
.parse::<u64>()
129147
.unwrap();
130148

131-
let lines_until_first_change = hunk_contents
149+
let mut change_lines = hunk_contents
132150
.lines()
133-
.take_while(|l| l.starts_with(' '))
134-
.count() as u64;
135-
136-
let first_hunk_change_start_offset =
137-
post_change_hunk_start_offset + lines_until_first_change;
138-
139-
first_hunk_change_start_offset >= changelog_first_release_section_line_num
151+
.enumerate()
152+
.filter(|(_idx, l)| !l.starts_with(' '))
153+
.map(|(zero_based_idx, _l)| {
154+
post_change_hunk_start_offset + (zero_based_idx as u64)
155+
});
156+
157+
let change_start_line_num = change_lines.next().unwrap();
158+
159+
if change_start_line_num >= changelog_first_release_section_line_num {
160+
Some(Hunk {
161+
contents: hunk,
162+
change_start_line_num,
163+
change_end_line_num: change_lines.last().unwrap_or(change_start_line_num),
164+
})
165+
} else {
166+
None
167+
}
140168
})
141169
.collect::<Vec<_>>();
142170

xtask/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ Commands:
5252
5353
`<to_commit>` is the tip of the `git diff` that will be used for checking (1).
5454
55+
--emit-github-messages Emit GitHub workflow commands for nice integrations like error reporting in PR views.
56+
5557
miri
5658
Run all miri-compatible tests under miri. Requires a nightly toolchain
5759
with the x86_64-unknown-linux-gnu target and miri component installed.

0 commit comments

Comments
 (0)