Skip to content

Commit

Permalink
Add new subcommands to changelogger for supporting file-per-change …
Browse files Browse the repository at this point in the history
…changelog (#3771)

## Motivation and Context
Adds new subcommands `--new` and `--ls` to `changelogger`

## Description
This is part 2 in a series of PRs supporting [file-per-change
changelog](https://smithy-lang.github.io/smithy-rs/design/rfcs/rfc0042_file_per_change_changelog.html).
This PR just adds utilities for humans and does NOT impact the current
dev workflow, smithy-rs CI, or our release pipeline.

#### A subcommand `--new`
We can use this subcommand when creating a new changelog entry markdown
file. An example usage:
```
$ changelogger new -t client -t aws-sdk-rust -r smithy-rs#1234 -a someone --bug-fix -m "Some changelog" \
# for long flags, replace -t with --applies-to, -r with --references, -a with --authors, and -m with --message \
# also remember to escape with \ when including backticks in the message at command line, e.g. \`pub\`

The following changelog entry has been written to "/Users/ysaito1001/src/smithy-rs/.changelog/5745197.md":
---
applies_to:
- aws-sdk-rust
- client
authors:
- someone
references:
- smithy-rs#1234
breaking: false
new_feature: false
bug_fix: true
---
Some changelog
```
The following CLI arguments are "logically" required
- `--applies-to`
- `--ref`
- `--author`
- `--message`

If any of the above is not passed a value at command line, then an
editor is opened for further edit (which editor to open can be
configured per the [edit crate](https://docs.rs/edit/0.1.5/edit/)).

Note that the YAML syntax above is different from the single line array
syntax [proposed in the
RFC](https://smithy-lang.github.io/smithy-rs/design/rfcs/rfc0042_file_per_change_changelog.html#the-proposed-developer-experience).
This is due to [a
limitation](dtolnay/serde-yaml#355) in
`serde-yaml` (which has been archived unfortunately), but the multi-line
values are still a valid YAML syntax and, most importantly, rendering
changelong entries will continue working. For now, I won't post-process
from the multi-line values syntax to the single line array syntax. One
can work around this by handwriting a changelog entry Markdown file in
`smithy-rs/.changelog` without using this subcommand.

#### A subcommand `--ls`
This subcommand will render a preview of changelog entries stored in
`smithy-rs/.changelog` and print it to the standard output. Example
usages (using the entry created at 5745197.md above):
```
$ changelogger ls -c smithy-rs \
# for long flag, replace -c with --change-set

Next changelog preview for smithy-rs
=====================================
**New this release:**
- 🐛 (client, [smithy-rs#1234](#1234), @Someone) Some changelog

**Contributors**
Thank you for your contributions! ❤
- @Someone ([smithy-rs#1234](#1234))
```
```
$ changelogger ls -c aws-sdk \
# for long flag, replace -c with --change-set

Next changelog preview for aws-sdk-rust
========================================
**New this release:**
- 🐛 ([smithy-rs#1234](#1234), @Someone) Some changelog

**Contributors**
Thank you for your contributions! ❤
- @Someone ([smithy-rs#1234](#1234))
```


## Testing
- Existing tests in CI
- Basic unit tests for subcommands

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
  • Loading branch information
ysaito1001 authored Jul 31, 2024
1 parent 36b50b3 commit 63753f3
Show file tree
Hide file tree
Showing 13 changed files with 462 additions and 92 deletions.
Empty file added .changelog/.keep
Empty file.
34 changes: 32 additions & 2 deletions tools/ci-build/changelogger/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions tools/ci-build/changelogger/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ opt-level = 0
[dependencies]
anyhow = "1.0.57"
clap = { version = "~3.2.1", features = ["derive"] }
edit = "0.1"
once_cell = "1.15.0"
ordinal = "0.3.2"
serde = { version = "1", features = ["derive"]}
serde_json = "1"
serde_yaml = "0.9"
smithy-rs-tool-common = { path = "../smithy-rs-tool-common" }
time = { version = "0.3.9", features = ["local-offset"]}
toml = "0.5.8"
Expand Down
14 changes: 14 additions & 0 deletions tools/ci-build/changelogger/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use clap::clap_derive::ArgEnum;
use smithy_rs_tool_common::changelog::{Changelog, HandAuthoredEntry, SdkModelEntry};
use smithy_rs_tool_common::git::Git;
use smithy_rs_tool_common::versions_manifest::VersionsManifest;
use std::fmt::{Display, Formatter};
use std::path::Path;

#[derive(ArgEnum, Copy, Clone, Debug, Eq, PartialEq)]
Expand All @@ -16,6 +17,19 @@ pub enum ChangeSet {
AwsSdk,
}

impl Display for ChangeSet {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
ChangeSet::SmithyRs => "smithy-rs",
ChangeSet::AwsSdk => "aws-sdk-rust",
}
)
}
}

pub struct ChangelogEntries {
pub aws_sdk_rust: Vec<ChangelogEntry>,
pub smithy_rs: Vec<ChangelogEntry>,
Expand Down
2 changes: 2 additions & 0 deletions tools/ci-build/changelogger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@

pub mod entry;
pub mod init;
pub mod ls;
pub mod new;
pub mod render;
pub mod split;
50 changes: 50 additions & 0 deletions tools/ci-build/changelogger/src/ls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

use crate::entry::{ChangeSet, ChangelogEntries};
use crate::render::render;
use anyhow::Context;
use clap::Parser;
use smithy_rs_tool_common::changelog::{ChangelogLoader, ValidationSet};
use smithy_rs_tool_common::git::find_git_repository_root;
use smithy_rs_tool_common::here;
use smithy_rs_tool_common::versions_manifest::CrateVersionMetadataMap;

#[derive(Parser, Debug, Eq, PartialEq)]
pub struct LsArgs {
/// Which set of changes to preview
#[clap(long, short, action)]
pub change_set: ChangeSet,
}

pub fn subcommand_ls(args: LsArgs) -> anyhow::Result<()> {
let mut dot_changelog = find_git_repository_root("smithy-rs", ".").context(here!())?;
dot_changelog.push(".changelog");

let loader = ChangelogLoader::default();
let changelog = loader.load_from_dir(dot_changelog.clone())?;

changelog.validate(ValidationSet::Render).map_err(|errs| {
anyhow::Error::msg(format!(
"failed to load {dot_changelog:?}: {errors}",
errors = errs.join("\n")
))
})?;

let entries = ChangelogEntries::from(changelog);

let (release_header, release_notes) = render(
match args.change_set {
ChangeSet::SmithyRs => &entries.smithy_rs,
ChangeSet::AwsSdk => &entries.aws_sdk_rust,
},
CrateVersionMetadataMap::new(),
&format!("\nNext changelog preview for {}", args.change_set),
);

println!("{release_header}{release_notes}");

Ok(())
}
74 changes: 68 additions & 6 deletions tools/ci-build/changelogger/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,49 @@

use anyhow::Result;
use changelogger::init::subcommand_init;
use changelogger::ls::subcommand_ls;
use changelogger::new::subcommand_new;
use changelogger::render::subcommand_render;
use changelogger::split::subcommand_split;
use clap::Parser;

#[derive(Parser, Debug, Eq, PartialEq)]
#[clap(name = "changelogger", author, version, about)]
pub enum Args {
/// Split SDK changelog entries into a separate file
Split(changelogger::split::SplitArgs),
/// Print to stdout the empty "next" CHANGELOG template
Init(changelogger::init::InitArgs),
/// Create a new changelog entry Markdown file in the `smithy-rs/.changelog` directory
New(changelogger::new::NewArgs),
/// Render a preview of changelog entries since the last release
Ls(changelogger::ls::LsArgs),
/// Render a TOML/JSON changelog into GitHub-flavored Markdown
Render(changelogger::render::RenderArgs),
/// Print to stdout the empty "next" CHANGELOG template.
Init(changelogger::init::InitArgs),
/// Split SDK changelog entries into a separate file
Split(changelogger::split::SplitArgs),
}

fn main() -> Result<()> {
match Args::parse() {
Args::Split(split) => subcommand_split(&split),
Args::Render(render) => subcommand_render(&render),
Args::Init(init) => subcommand_init(&init),
Args::New(new) => subcommand_new(new),
Args::Ls(ls) => subcommand_ls(ls),
Args::Render(render) => subcommand_render(&render),
Args::Split(split) => subcommand_split(&split),
}
}

#[cfg(test)]
mod tests {
use super::Args;
use changelogger::entry::ChangeSet;
use changelogger::ls::LsArgs;
use changelogger::new::NewArgs;
use changelogger::render::RenderArgs;
use changelogger::split::SplitArgs;
use clap::Parser;
use smithy_rs_tool_common::changelog::{Reference, Target};
use std::path::PathBuf;
use std::str::FromStr;

#[test]
fn args_parsing() {
Expand Down Expand Up @@ -188,5 +200,55 @@ mod tests {
])
.unwrap()
);

assert_eq!(
Args::New(NewArgs {
applies_to: Some(vec![Target::Client, Target::AwsSdk]),
authors: Some(vec!["external-contrib".to_owned(), "ysaito1001".to_owned()]),
references: Some(vec![
Reference::from_str("smithy-rs#1234").unwrap(),
Reference::from_str("aws-sdk-rust#5678").unwrap()
]),
breaking: false,
new_feature: true,
bug_fix: false,
message: Some("Implement a long-awaited feature for S3".to_owned()),
basename: None,
}),
Args::try_parse_from([
"./changelogger",
"new",
"--applies-to",
"client",
"--applies-to",
"aws-sdk-rust",
"--authors",
"external-contrib",
"--authors",
"ysaito1001",
"--references",
"smithy-rs#1234",
"--references",
"aws-sdk-rust#5678",
"--new-feature",
"--message",
"Implement a long-awaited feature for S3",
])
.unwrap()
);

assert_eq!(
Args::Ls(LsArgs {
change_set: ChangeSet::SmithyRs
}),
Args::try_parse_from(["./changelogger", "ls", "--change-set", "smithy-rs",]).unwrap()
);

assert_eq!(
Args::Ls(LsArgs {
change_set: ChangeSet::AwsSdk
}),
Args::try_parse_from(["./changelogger", "ls", "--change-set", "aws-sdk",]).unwrap()
);
}
}
Loading

0 comments on commit 63753f3

Please sign in to comment.