Skip to content

Commit

Permalink
Refactor and extend dependabot pr body parsing + tests (#18)
Browse files Browse the repository at this point in the history
* move example dependabot pr bodies to standalone markdown files

* rename example links to attempt to trip up parser

* add dependabot pr body example that bumps submodule with short SHA

* move the commands boilerplate part into separate file

* add example with novel versioning scheme

* use macro to reduce duplication and add the two new example depandabot pr bodies

* also allow "Bumps" in pr body and trim '.' (dot) from new version string

* add another pr body example with novel versioning scheme

* skip parsing <details> section
  • Loading branch information
CramBL authored Dec 29, 2024
1 parent da546de commit 5979bdd
Show file tree
Hide file tree
Showing 9 changed files with 580 additions and 487 deletions.
4 changes: 2 additions & 2 deletions src/changelog/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,15 +243,15 @@ mod tests {

#[test]
fn test_find_old_version_docker_sha1() {
let test_str = "- Bump `docker/login-action` from 3d58c274f17dffee475a5520cbe67f0a882c4dbb to 7ca345011ac4304463197fac0e56eab1bc7e6af0 ([#39](https://github.com/luftkode/settings-manager/pull/39))";
let test_str = "- Bump `docker/login-action` from 3d58c274f17dffee475a5520cbe67f0a882c4dbb to 7ca345011ac4304463197fac0e56eab1bc7e6af0 ([#39](https://github.com/bumps_org/updates-versioner/pull/39))";
let old_ver = find_old_ver_from_line(test_str).unwrap();
assert_str_eq!(&old_ver, "3d58c274f17dffee475a5520cbe67f0a882c4dbb");
}

#[test]
fn test_find_old_version_actions_toolkit_semver() {
let test_str =
" 0.40.0 to 0.42.0</li> ([#39](https://github.com/luftkode/settings-manager/pull/39))";
" 0.40.0 to 0.42.0</li> ([#39](https://github.com/bumps_org/updates-versioner/pull/39))";
let old_ver = find_old_ver_from_line(test_str).unwrap();
assert_str_eq!(&old_ver, "0.40.0");
}
Expand Down
137 changes: 114 additions & 23 deletions src/dependabot_changes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ impl<'s> DependabotChange<'s> {
let to_pos = haystack.find("to").unwrap_or(haystack.len());

// Extract the dependency name (before "from")
let name = &haystack[from_version_character_pos()..from_pos].trim();
let name = &haystack[..from_pos].trim();

// Extract the old version (between "from" and "to")
let old_version = &haystack[from_pos + 4..to_pos].trim();

// Extract the new version (after "to")
let new_version = &haystack[to_pos + 2..].trim();
let new_version = &haystack[to_pos + 2..].trim().trim_end_matches(".");

Some(DependabotChange::new(name, old_version, new_version))
} else {
Expand Down Expand Up @@ -116,31 +116,38 @@ pub fn format_changes(changes: Vec<DependabotChange>) -> String {
markdown
}

const UPDATE_LINE_KEYWORD: &str = "Updates";
const UPDATE_LINE_KEYWORD_A: &str = "Updates";
const UPDATE_LINE_KEYWORD_B: &str = "Bumps";

/// Update keyword + 1 for the whitespace separator
const fn from_version_character_pos() -> usize {
UPDATE_LINE_KEYWORD.len() + 1
}
const UPDATE_KEYWORDS: [(&str, usize); 2] = [
(UPDATE_LINE_KEYWORD_A, UPDATE_LINE_KEYWORD_A.len()),
(UPDATE_LINE_KEYWORD_B, UPDATE_LINE_KEYWORD_B.len()),
];

fn parse_changes(body: &str) -> Vec<DependabotChange> {
let mut changes = Vec::new();

// Split the body into lines
let lines = body.lines();

// Loop through the lines
for line in lines {
// Look for lines that match the pattern of a version change
if let Some(start) = line.find(UPDATE_LINE_KEYWORD) {
let remaining = &line[start..];

if let Some(dependabot_change) = DependabotChange::from_str(remaining) {
changes.push(dependabot_change);
let mut skip_parsing = false;
for line in body.lines() {
// Skip content in a <details> section
if skip_parsing {
if line.starts_with("</details") {
skip_parsing = false;
}
} else if line.starts_with("<details") {
skip_parsing = true;
} else {
for &(keyword, keyword_len) in &UPDATE_KEYWORDS {
if let Some(start) = line.find(keyword) {
let remaining = &line[start + keyword_len + 1..]; // +1 for whitespace
if let Some(dependabot_change) = DependabotChange::from_str(remaining) {
changes.push(dependabot_change);
break;
}
}
}
}
}

changes
}

Expand All @@ -152,7 +159,21 @@ mod tests {

#[test]
fn test_parse_body() {
let changes_md = format_changes(parse_body(EXAMPLE_DEPENDABOT_BODY_SETTINGS_MANAGER));
let changes = parse_body(DEPENDABOT_BODY_2_ACTIONS_SHA_SEMVER);
assert_eq!(changes.len(), 2);
assert_eq!(
changes[0],
DependabotChange::new("`crate-ci/typos`", "1.27.0", "1.28.4")
);
assert_eq!(
changes[1],
DependabotChange::new(
"`docker/login-action`",
"3d58c274f17dffee475a5520cbe67f0a882c4dbb",
"7ca345011ac4304463197fac0e56eab1bc7e6af0"
)
);
let changes_md = format_changes(changes);
let expect_md = "\
- `crate-ci/typos`: 1.27.0 → 1.28.4\n\
- `docker/login-action`: 3d58c274f17dffee475a5520cbe67f0a882c4dbb → 7ca345011ac4304463197fac0e56eab1bc7e6af0\n";
Expand All @@ -161,14 +182,43 @@ mod tests {

#[test]
fn test_parse_example_to_changes() {
let changes = parse_changes(EXAMPLE_DEPENDABOT_BODY_SETTINGS_MANAGER);
let changes = parse_changes(DEPENDABOT_BODY_2_ACTIONS_SHA_SEMVER);
assert_eq!(changes.len(), 2);
}

#[test]
fn test_parse_example_to_changes_plotinator() {
let changes = parse_changes(EXAMPLE_DEPENDABOT_BODY_PLOTINATOR);
fn test_parse_example_to_changes_7_crates_semver() {
let changes = parse_changes(DEPENDABOT_BODY_7_CRATES_SEMVER);
assert_eq!(changes.len(), 8);
assert_eq!(
changes[0],
DependabotChange::new("`serde`", "1.0.215", "1.0.216")
);
assert_eq!(
changes[1],
DependabotChange::new("`chrono`", "0.4.38", "0.4.39")
);
assert_eq!(
changes[2],
DependabotChange::new("`semver`", "1.0.23", "1.0.24")
);
assert_eq!(
changes[3],
DependabotChange::new("`env_logger`", "0.11.5", "0.11.6")
);
assert_eq!(changes[4], DependabotChange::new("`zip`", "2.2.1", "2.2.2"));
assert_eq!(
changes[5],
DependabotChange::new("`wasm-bindgen-futures`", "0.4.47", "0.4.49")
);
assert_eq!(
changes[6],
DependabotChange::new("`web-sys`", "0.3.74", "0.3.76")
);
assert_eq!(
changes[7],
DependabotChange::new("`thiserror`", "2.0.4", "2.0.9")
);

let changes_md = format_changes(changes);
let expect_md = "\
Expand All @@ -182,4 +232,45 @@ mod tests {
- `thiserror`: 2.0.4 → 2.0.9\n";
assert_str_eq!(changes_md, expect_md);
}

#[test]
fn test_parse_body_1_submodule_short_sha() {
let changes = parse_changes(DEPENDABOT_BODY_1_SUBMODULE_SHORT_SHA);
assert_eq!(changes.len(), 1);
assert_eq!(
changes[0],
DependabotChange::new(
"[some-submodule](https://github.com/updates-org/some-submodule)",
"`b0c35f6`",
"`c8bd600`"
)
);
}

#[test]
fn test_parse_body_1_docker_novel_version() {
let changes = parse_changes(DEPENDABOT_BODY_1_DOCKER_NOVEL_VERSION);
assert_eq!(changes.len(), 1);
assert_eq!(
changes[0],
DependabotChange::new("ubi9/ubi", "9.4-1214.1726694543", "9.4-1214.1729773476")
);
}

#[test]
fn test_parse_body_skips_details_section() {
let pr_body = r"Bumps foo from 0.1.0a to 0.1.1b
<details>
Bumps bar from 0.1.0 to 0.2.0
</details>
Updates baz from 2024.1.2 to 2025.1.2-rc1
";
let changes = parse_body(pr_body);
assert_eq!(changes.len(), 2);
assert_eq!(changes[0], DependabotChange::new("foo", "0.1.0a", "0.1.1b"));
assert_eq!(
changes[1],
DependabotChange::new("baz", "2024.1.2", "2025.1.2-rc1")
);
}
}
12 changes: 6 additions & 6 deletions src/test_util/example_changelogs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Only set font styles when it changes instead of at every frame (leftover tech-debt from starting to learn egui)
- Make the loaded files window scrollable - resolves https://github.com/luftkode/plotinator3000/issues/118
- Make the loaded files window scrollable - resolves https://github.com/bumps_org/from-1.2.3-project-to-foo/issues/118
## [1.3.3]
Expand Down Expand Up @@ -186,7 +186,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fix
- Updater was looking for an install receipt which plotinator3000 no longer uses. The updater now proceeds without needing an install receipt.
- Updater was looking for an install receipt which from-1.2.3-project-to-foo no longer uses. The updater now proceeds without needing an install receipt.
## [1.0.1]
Expand All @@ -203,7 +203,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- `logviewer-rs` is now renamed to `Plotinator3000`, signifying that it is not really a logviewer and more of a plotting app that will plot any supported format, and do it very fast.
- `logviewer-rs` is now renamed to `from-1.2.3-project-to-foo`, signifying that it is not really a logviewer and more of a plotting app that will plot any supported format, and do it very fast.
## [0.28.0]
Expand Down Expand Up @@ -248,13 +248,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fix
- Web version of `plotinator3000` was broken due an integer overflow. When determining down sample level, a cast from 64-bit float to pointer size caused integer overflow on wasm due to wasm having a 32-bit pointer size.
- Web version of `from-1.2.3-project-to-foo` was broken due an integer overflow. When determining down sample level, a cast from 64-bit float to pointer size caused integer overflow on wasm due to wasm having a 32-bit pointer size.
## [0.24.0]
### Added
- Initial support for `HDF` files, starting with bifrost (TX) loop current. The feature is currently guarded behind a feature flag, enabling it is tracked at: https://github.com/luftkode/plotinator3000/issues/84.
- Initial support for `HDF` files, starting with bifrost (TX) loop current. The feature is currently guarded behind a feature flag, enabling it is tracked at: https://github.com/bumps_org/from-1.2.3-project-to-foo/issues/84.
### Changed
Expand Down Expand Up @@ -308,7 +308,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fix
- `Mbed status Log v2` mistakenly interpreted as `Mbed status Log v1` when loaded via a path (native `plotinator3000`)
- `Mbed status Log v2` mistakenly interpreted as `Mbed status Log v1` when loaded via a path (native `from-1.2.3-project-to-foo`)
## [0.19.0]
Expand Down
Loading

0 comments on commit 5979bdd

Please sign in to comment.