Skip to content

Commit 0b059fb

Browse files
authored
Add support for changelog entry markdown files (#3763)
## Motivation and Context [RFC: File-per-change changelog](https://smithy-lang.github.io/smithy-rs/design/rfcs/rfc0042_file_per_change_changelog.html#rfc-file-per-change-changelog) ## Description This PR is the first of the two implementing the proposal outlined in the RFC, and it focuses on the initial 4 bullets in the [Changes checklist](https://smithy-lang.github.io/smithy-rs/design/rfcs/rfc0042_file_per_change_changelog.html#changes-checklist). Crucially, this update does not modify the workflow for developers regarding changelog entries (editing `CHANGELOG.next.toml` remains necessary) or impact the `smithy-rs` CI process and our release pipeline. The PR introduces support for deserializing the following Markdown front matter in the YAML format described in the RFC, e.g. ``` --- # Adding `aws-sdk-rust` here duplicates this entry into the SDK changelog. applies_to: ["client", "server", "aws-sdk-rust"] authors: ["author1", "author2"] references: ["smithy-rs#1234", "aws-sdk-rust#1234"] # The previous `meta` section is broken up into its constituents: breaking: false # This replaces "tada": new_feature: false bug_fix: false --- Some message for the change. ``` These changelog entry Markdown files will be saved in the `smithy-rs/.changelog` directory: ``` ┌───────────┐ │ smithy-rs │ └─────┬─────┘ │ │ ┌───────────┐ ├────┤.changelog │ └─────┬─────┘ │ ├─────test1.md │ └─────test2.md ``` For a concrete example, see a test `end_to_end_changelog_entry_markdown_files` that directly converts from `end_to_end_changelog` and uses Markdown files (the expected test results remain the same). The next PR is expected to - add new subcommands to `changelogger` to a) create a Markdown file and b) preview changelog entries pending to be released - port existing `CHANGELOG.next.toml` at that time to individual Markdown files - update `sdk-lints` to disallow the existence of `CHANGELOG.next.toml` - pass a directory path for `smithy-rs/.changelog` to `--source` (one for [split](https://github.com/smithy-lang/smithy-rs/blob/dc970b37386b155eced5d41262ce0a7fc4a34a91/tools/ci-scripts/generate-smithy-rs-release#L22) and one for [render](https://github.com/smithy-lang/smithy-rs/blob/dc970b37386b155eced5d41262ce0a7fc4a34a91/tools/ci-scripts/generate-smithy-rs-release#L22)) and to [--source-to-truncate](https://github.com/smithy-lang/smithy-rs/blob/dc970b37386b155eced5d41262ce0a7fc4a34a91/tools/ci-scripts/generate-smithy-rs-release#L23C1-L23C47) (the 4th bullet effectively does the cutover to the new changelog mode) ## Testing - Added `parse_markdown` and `end_to_end_changelog_entry_markdown_files` for testing new changelog format (the rest of the tests showing up in the diff are moved from different places) - Confirmed via [a release dry-run](https://github.com/smithy-lang/smithy-rs/actions/runs/9947165056) that this PR does not break the existing `smithy-rs` release process - Confirmed that this PR does not break the use of `changelogger` in our internal release process ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._
1 parent 8d23be1 commit 0b059fb

File tree

8 files changed

+671
-197
lines changed

8 files changed

+671
-197
lines changed

tools/ci-build/changelogger/Cargo.lock

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/ci-build/changelogger/src/render.rs

+197-53
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ use once_cell::sync::Lazy;
1010
use ordinal::Ordinal;
1111
use serde::Serialize;
1212
use smithy_rs_tool_common::changelog::{
13-
Changelog, HandAuthoredEntry, Reference, SdkModelChangeKind, SdkModelEntry, ValidationSet,
13+
Changelog, ChangelogLoader, HandAuthoredEntry, Reference, SdkModelChangeKind, SdkModelEntry,
14+
ValidationSet,
1415
};
1516
use smithy_rs_tool_common::git::{find_git_repository_root, Git, GitCLI};
1617
use smithy_rs_tool_common::versions_manifest::{CrateVersionMetadataMap, VersionsManifest};
1718
use std::env;
1819
use std::fmt::Write;
20+
use std::fs;
1921
use std::path::{Path, PathBuf};
2022
use time::OffsetDateTime;
2123

@@ -244,9 +246,14 @@ fn render_table_row(columns: [&str; 2], out: &mut String) {
244246

245247
fn load_changelogs(args: &RenderArgs) -> Result<Changelog> {
246248
let mut combined = Changelog::new();
249+
let loader = ChangelogLoader::default();
247250
for source in &args.source {
248-
let changelog = Changelog::load_from_file(source)
249-
.map_err(|errs| anyhow::Error::msg(format!("failed to load {source:?}: {errs:#?}")))?;
251+
let changelog = if source.is_dir() {
252+
loader.load_from_dir(source)
253+
} else {
254+
loader.load_from_file(source)
255+
}
256+
.map_err(|errs| anyhow::Error::msg(format!("failed to load {source:?}: {errs:#?}")))?;
250257
changelog.validate(ValidationSet::Render).map_err(|errs| {
251258
anyhow::Error::msg(format!(
252259
"failed to load {source:?}: {errors}",
@@ -321,8 +328,14 @@ fn update_changelogs(
321328
update.push_str(&current);
322329
std::fs::write(&args.changelog_output, update).context("failed to write rendered changelog")?;
323330

324-
std::fs::write(&args.source_to_truncate, EXAMPLE_ENTRY.trim())
325-
.context("failed to truncate source")?;
331+
if args.source_to_truncate.is_dir() {
332+
fs::remove_dir_all(&args.source_to_truncate)
333+
.and_then(|_| fs::create_dir(&args.source_to_truncate))
334+
.with_context(|| format!("failed to empty directory {:?}", &args.source_to_truncate))?;
335+
} else {
336+
fs::write(&args.source_to_truncate, EXAMPLE_ENTRY.trim())
337+
.with_context(|| format!("failed to truncate source {:?}", &args.source_to_truncate))?;
338+
}
326339
eprintln!("Changelogs updated!");
327340
Ok(())
328341
}
@@ -494,18 +507,189 @@ fn render(
494507
#[cfg(test)]
495508
mod test {
496509
use super::{date_based_release_metadata, render, Changelog, ChangelogEntries, ChangelogEntry};
510+
use smithy_rs_tool_common::changelog::ChangelogLoader;
497511
use smithy_rs_tool_common::{
498512
changelog::SdkAffected,
499513
package::PackageCategory,
500514
versions_manifest::{CrateVersion, CrateVersionMetadataMap},
501515
};
516+
use std::fs;
517+
use tempfile::TempDir;
502518
use time::OffsetDateTime;
503519

504520
fn render_full(entries: &[ChangelogEntry], release_header: &str) -> String {
505521
let (header, body) = render(entries, CrateVersionMetadataMap::new(), release_header);
506522
format!("{header}{body}")
507523
}
508524

525+
const SMITHY_RS_EXPECTED_END_TO_END: &str = r#"v0.3.0 (January 4th, 2022)
526+
==========================
527+
**Breaking Changes:**
528+
- :warning: (all, [smithy-rs#445](https://github.com/smithy-lang/smithy-rs/issues/445)) I made a major change to update the code generator
529+
530+
**New this release:**
531+
- :tada: (all, [smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446), [aws-sdk#123](https://github.com/aws/aws-sdk/issues/123), @external-contrib, @other-external-dev) I made a change to update the code generator
532+
- :tada: (all, [smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446), [smithy-rs#447](https://github.com/smithy-lang/smithy-rs/issues/447), @external-contrib, @other-external-dev) I made a change to update the code generator
533+
534+
**Update guide:**
535+
blah blah
536+
- (all, [smithy-rs#200](https://github.com/smithy-lang/smithy-rs/issues/200), @another-contrib) I made a minor change
537+
538+
**Contributors**
539+
Thank you for your contributions! ❤
540+
- @another-contrib ([smithy-rs#200](https://github.com/smithy-lang/smithy-rs/issues/200))
541+
- @external-contrib ([smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446), [smithy-rs#447](https://github.com/smithy-lang/smithy-rs/issues/447))
542+
- @other-external-dev ([smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446), [smithy-rs#447](https://github.com/smithy-lang/smithy-rs/issues/447))
543+
544+
"#;
545+
546+
const AWS_SDK_EXPECTED_END_TO_END: &str = r#"v0.1.0 (January 4th, 2022)
547+
==========================
548+
**Breaking Changes:**
549+
- :warning: ([smithy-rs#445](https://github.com/smithy-lang/smithy-rs/issues/445)) I made a major change to update the AWS SDK
550+
551+
**New this release:**
552+
- :tada: ([smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446), @external-contrib) I made a change to update the code generator
553+
554+
**Service Features:**
555+
- `aws-sdk-ec2` (0.12.0): Some API change
556+
- `aws-sdk-s3` (0.14.0): Some new API to do X
557+
558+
**Service Documentation:**
559+
- `aws-sdk-ec2` (0.12.0): Updated some docs
560+
561+
**Contributors**
562+
Thank you for your contributions! ❤
563+
- @external-contrib ([smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446))
564+
565+
"#;
566+
567+
#[test]
568+
fn end_to_end_changelog_entry_markdown_files() {
569+
let temp_dir = TempDir::new().unwrap();
570+
let smithy_rs_entry1 = r#"---
571+
applies_to: ["client", "server"]
572+
authors: ["rcoh", "jdisanti"]
573+
references: ["smithy-rs#445"]
574+
breaking: true
575+
new_feature: false
576+
bug_fix: false
577+
---
578+
I made a major change to update the code generator
579+
"#;
580+
let smithy_rs_entry2 = r#"---
581+
applies_to: ["client", "server"]
582+
authors: ["external-contrib", "other-external-dev"]
583+
references: ["smithy-rs#446", "aws-sdk#123"]
584+
breaking: false
585+
new_feature: true
586+
bug_fix: false
587+
---
588+
I made a change to update the code generator
589+
"#;
590+
let smithy_rs_entry3 = r#"---
591+
applies_to: ["client", "server"]
592+
authors: ["another-contrib"]
593+
references: ["smithy-rs#200"]
594+
breaking: false
595+
new_feature: false
596+
bug_fix: false
597+
---
598+
I made a minor change
599+
"#;
600+
let aws_sdk_entry1 = r#"---
601+
applies_to: ["aws-sdk-rust"]
602+
authors: ["rcoh"]
603+
references: ["smithy-rs#445"]
604+
breaking: true
605+
new_feature: false
606+
bug_fix: false
607+
---
608+
I made a major change to update the AWS SDK
609+
"#;
610+
let aws_sdk_entry2 = r#"---
611+
applies_to: ["aws-sdk-rust"]
612+
authors: ["external-contrib"]
613+
references: ["smithy-rs#446"]
614+
breaking: false
615+
new_feature: true
616+
bug_fix: false
617+
---
618+
I made a change to update the code generator
619+
"#;
620+
let smithy_rs_entry4 = r#"---
621+
applies_to: ["client", "server"]
622+
authors: ["external-contrib", "other-external-dev"]
623+
references: ["smithy-rs#446", "smithy-rs#447"]
624+
breaking: false
625+
new_feature: true
626+
bug_fix: false
627+
---
628+
I made a change to update the code generator
629+
630+
**Update guide:**
631+
blah blah
632+
"#;
633+
634+
// We won't handwrite changelog entries for model updates, and they are still provided in
635+
// the TOML format.
636+
let model_updates = r#"
637+
[[aws-sdk-model]]
638+
module = "aws-sdk-s3"
639+
version = "0.14.0"
640+
kind = "Feature"
641+
message = "Some new API to do X"
642+
643+
[[aws-sdk-model]]
644+
module = "aws-sdk-ec2"
645+
version = "0.12.0"
646+
kind = "Documentation"
647+
message = "Updated some docs"
648+
649+
[[aws-sdk-model]]
650+
module = "aws-sdk-ec2"
651+
version = "0.12.0"
652+
kind = "Feature"
653+
message = "Some API change"
654+
"#;
655+
656+
[
657+
smithy_rs_entry1,
658+
smithy_rs_entry2,
659+
smithy_rs_entry3,
660+
aws_sdk_entry1,
661+
aws_sdk_entry2,
662+
smithy_rs_entry4,
663+
]
664+
.iter()
665+
.enumerate()
666+
.for_each(|(i, contents)| {
667+
let changelog_entry_markdown_file = temp_dir.path().join(format!("test{i}.md"));
668+
fs::write(&changelog_entry_markdown_file, contents.as_bytes()).unwrap();
669+
});
670+
671+
let mut changelog = ChangelogLoader::default()
672+
.load_from_dir(temp_dir.path())
673+
.expect("valid changelog");
674+
675+
changelog.merge(
676+
ChangelogLoader::default()
677+
.parse_str(model_updates)
678+
.expect("valid changelog"),
679+
);
680+
681+
let ChangelogEntries {
682+
aws_sdk_rust,
683+
smithy_rs,
684+
} = changelog.into();
685+
686+
let smithy_rs_rendered = render_full(&smithy_rs, "v0.3.0 (January 4th, 2022)");
687+
pretty_assertions::assert_str_eq!(SMITHY_RS_EXPECTED_END_TO_END, smithy_rs_rendered);
688+
689+
let aws_sdk_rendered = render_full(&aws_sdk_rust, "v0.1.0 (January 4th, 2022)");
690+
pretty_assertions::assert_str_eq!(AWS_SDK_EXPECTED_END_TO_END, aws_sdk_rendered);
691+
}
692+
509693
#[test]
510694
fn end_to_end_changelog() {
511695
let changelog_toml = r#"
@@ -568,61 +752,19 @@ version = "0.12.0"
568752
kind = "Feature"
569753
message = "Some API change"
570754
"#;
571-
let changelog: Changelog = Changelog::parse_str(changelog_toml).expect("valid changelog");
755+
let changelog: Changelog = ChangelogLoader::default()
756+
.parse_str(changelog_toml)
757+
.expect("valid changelog");
572758
let ChangelogEntries {
573759
aws_sdk_rust,
574760
smithy_rs,
575761
} = changelog.into();
576762

577763
let smithy_rs_rendered = render_full(&smithy_rs, "v0.3.0 (January 4th, 2022)");
578-
let smithy_rs_expected = r#"
579-
v0.3.0 (January 4th, 2022)
580-
==========================
581-
**Breaking Changes:**
582-
- :warning: (all, [smithy-rs#445](https://github.com/smithy-lang/smithy-rs/issues/445)) I made a major change to update the code generator
583-
584-
**New this release:**
585-
- :tada: (all, [smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446), [aws-sdk#123](https://github.com/aws/aws-sdk/issues/123), @external-contrib, @other-external-dev) I made a change to update the code generator
586-
- :tada: (all, [smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446), [smithy-rs#447](https://github.com/smithy-lang/smithy-rs/issues/447), @external-contrib, @other-external-dev) I made a change to update the code generator
587-
588-
**Update guide:**
589-
blah blah
590-
- (all, [smithy-rs#200](https://github.com/smithy-lang/smithy-rs/issues/200), @another-contrib) I made a minor change
591-
592-
**Contributors**
593-
Thank you for your contributions! ❤
594-
- @another-contrib ([smithy-rs#200](https://github.com/smithy-lang/smithy-rs/issues/200))
595-
- @external-contrib ([smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446), [smithy-rs#447](https://github.com/smithy-lang/smithy-rs/issues/447))
596-
- @other-external-dev ([smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446), [smithy-rs#447](https://github.com/smithy-lang/smithy-rs/issues/447))
597-
598-
"#
599-
.trim_start();
600-
pretty_assertions::assert_str_eq!(smithy_rs_expected, smithy_rs_rendered);
764+
pretty_assertions::assert_str_eq!(SMITHY_RS_EXPECTED_END_TO_END, smithy_rs_rendered);
601765

602766
let aws_sdk_rust_rendered = render_full(&aws_sdk_rust, "v0.1.0 (January 4th, 2022)");
603-
let aws_sdk_expected = r#"
604-
v0.1.0 (January 4th, 2022)
605-
==========================
606-
**Breaking Changes:**
607-
- :warning: ([smithy-rs#445](https://github.com/smithy-lang/smithy-rs/issues/445)) I made a major change to update the AWS SDK
608-
609-
**New this release:**
610-
- :tada: ([smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446), @external-contrib) I made a change to update the code generator
611-
612-
**Service Features:**
613-
- `aws-sdk-ec2` (0.12.0): Some API change
614-
- `aws-sdk-s3` (0.14.0): Some new API to do X
615-
616-
**Service Documentation:**
617-
- `aws-sdk-ec2` (0.12.0): Updated some docs
618-
619-
**Contributors**
620-
Thank you for your contributions! ❤
621-
- @external-contrib ([smithy-rs#446](https://github.com/smithy-lang/smithy-rs/issues/446))
622-
623-
"#
624-
.trim_start();
625-
pretty_assertions::assert_str_eq!(aws_sdk_expected, aws_sdk_rust_rendered);
767+
pretty_assertions::assert_str_eq!(AWS_SDK_EXPECTED_END_TO_END, aws_sdk_rust_rendered);
626768
}
627769

628770
#[test]
@@ -670,7 +812,9 @@ meta = { breaking = false, tada = true, bug = false }
670812
references = ["smithy-rs#446"]
671813
author = "rcoh"
672814
"#;
673-
let changelog: Changelog = Changelog::parse_str(sample).expect("valid changelog");
815+
let changelog: Changelog = ChangelogLoader::default()
816+
.parse_str(sample)
817+
.expect("valid changelog");
674818
let ChangelogEntries {
675819
aws_sdk_rust: _,
676820
smithy_rs,

0 commit comments

Comments
 (0)