Skip to content

Commit

Permalink
feat: prepare release if commits respect the release_commits regex (#…
Browse files Browse the repository at this point in the history
…1278)

Co-authored-by: Marco Ieni <11428655+MarcoIeni@users.noreply.github.com>
  • Loading branch information
isidzukuri and MarcoIeni committed Feb 25, 2024
1 parent 99f9812 commit ba4787b
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .schema/latest.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"publish_no_verify": null,
"publish_timeout": null,
"release": null,
"release_commits": null,
"repo_url": null,
"semver_check": null
},
Expand Down Expand Up @@ -569,6 +570,14 @@
"null"
]
},
"release_commits": {
"title": "Release Commits",
"description": "Prepare release only if at least one commit respects this regex.",
"type": [
"string",
"null"
]
},
"repo_url": {
"title": "Repo URL",
"description": "GitHub/Gitea repository url where your project is hosted. It is used to generate the changelog release link. It defaults to the url of the default remote.",
Expand Down
3 changes: 3 additions & 0 deletions crates/release_plz/src/args/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ impl Update {
if let Some(registry) = &self.registry {
update = update.with_registry(registry.clone());
}
if let Some(release_commits) = config.workspace.release_commits {
update = update.with_release_commits(release_commits.clone())?;
}

Ok(update)
}
Expand Down
7 changes: 7 additions & 0 deletions crates/release_plz/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ pub struct Workspace {
/// It is used to generate the changelog release link.
/// It defaults to the url of the default remote.
pub repo_url: Option<Url>,
/// # Release Commits
/// Prepare release only if at least one commit respects this regex.
pub release_commits: Option<String>,
}

impl Workspace {
Expand Down Expand Up @@ -361,6 +364,7 @@ mod tests {
git_release_type = "prod"
git_release_draft = false
publish_timeout = "10m"
release_commits = "^feat:"
"#;

const BASE_PACKAGE_CONFIG: &str = r#"
Expand All @@ -387,6 +391,7 @@ mod tests {
pr_draft: false,
pr_labels: vec![],
publish_timeout: Some("10m".to_string()),
release_commits: Some("^feat:".to_string()),
},
package: [].into(),
}
Expand Down Expand Up @@ -504,6 +509,7 @@ mod tests {
..Default::default()
},
publish_timeout: Some("10m".to_string()),
release_commits: Some("^feat:".to_string()),
},
package: [PackageSpecificConfigWithName {
name: "crate1".to_string(),
Expand Down Expand Up @@ -536,6 +542,7 @@ mod tests {
pr_labels = ["label1"]
publish_timeout = "10m"
repo_url = "https://github.com/MarcoIeni/release-plz"
release_commits = "^feat:"
[changelog]
Expand Down
27 changes: 27 additions & 0 deletions crates/release_plz/tests/all/changelog.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
use crate::helpers::{test_context::TestContext, TEST_REGISTRY};

#[tokio::test]
#[cfg_attr(not(feature = "docker-tests"), ignore)]
async fn release_plz_does_not_open_release_pr_if_there_are_no_release_commits() {
let context = TestContext::new().await;

let config = r#"
[workspace]
release_commits = "^feat:"
"#;
context.write_release_plz_toml(config);

context.run_release_pr().success();

let opened_prs = context.opened_release_prs().await;
// no features are present in the commits, so release-plz doesn't open the release PR
assert_eq!(opened_prs.len(), 0);

std::fs::write(context.repo_dir().join("new.rs"), "// hi").unwrap();
context.repo.add_all_and_commit("feat: new file").unwrap();

context.run_release_pr().success();

// we added a feature, so release-plz opened the release PR
let opened_prs = context.opened_release_prs().await;
assert_eq!(opened_prs.len(), 1);
}

#[tokio::test]
#[cfg_attr(not(feature = "docker-tests"), ignore)]
async fn release_plz_adds_changelog_on_new_project() {
Expand Down
38 changes: 38 additions & 0 deletions crates/release_plz_core/src/diff.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use git_cliff_core::commit::Commit;
use regex::Regex;

use crate::semver_check::SemverCheck;

Expand Down Expand Up @@ -45,4 +46,41 @@ impl<'a> Diff<'a> {
}
}
}

/// Return `true` if any commit message matches the given pattern.
pub fn any_commit_matches(&self, pattern: &Regex) -> bool {
self.commits
.iter()
.any(|commit| pattern.is_match(&commit.message))
}
}

#[cfg(test)]
mod tests {
use super::*;

pub fn create_diff() -> Diff<'static> {
let mut diff = Diff::new(false);
diff.add_commits(&vec![Commit::new(
"1e6903d".to_string(),
"feature release".to_string(),
)]);
diff
}

#[test]
fn test_is_commit_message_matched() {
let diff = create_diff();
let pattern = Regex::new(r"^feat").unwrap();
let present = diff.any_commit_matches(&pattern);
assert!(present);
}

#[test]
fn test_is_commit_message_not_matched() {
let diff = create_diff();
let pattern = Regex::new(r"mismatch").unwrap();
let present = diff.any_commit_matches(&pattern);
assert!(!present);
}
}
19 changes: 19 additions & 0 deletions crates/release_plz_core/src/next_ver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ pub struct UpdateRequest {
repo_url: Option<RepoUrl>,
/// Package-specific configurations.
packages_config: PackagesConfig,
/// Release Commits
/// Prepare release only if at least one commit respects a regex.
release_commits: Option<Regex>,
}

#[derive(Debug, Clone, Default)]
Expand Down Expand Up @@ -213,6 +216,7 @@ impl UpdateRequest {
allow_dirty: false,
repo_url: None,
packages_config: PackagesConfig::default(),
release_commits: None,
})
}

Expand Down Expand Up @@ -296,6 +300,16 @@ impl UpdateRequest {
}
}

pub fn with_release_commits(self, release_commits: String) -> anyhow::Result<Self> {
let regex =
Regex::new(&release_commits).context("invalid release_commits regex pattern")?;

Ok(Self {
release_commits: Some(regex),
..self
})
}

pub fn local_manifest_dir(&self) -> anyhow::Result<&Path> {
self.local_manifest
.parent()
Expand Down Expand Up @@ -649,6 +663,11 @@ impl Updater<'_> {
}

for (p, diff) in packages_diffs {
if let Some(ref release_commits_regex) = self.req.release_commits {
if !diff.any_commit_matches(release_commits_regex) {
continue;
};
}
// Calculate next version without taking into account workspace version
let next_version = if let Some(max_workspace_version) = &new_workspace_version {
if workspace_version_pkgs.contains(p.name.as_str()) {
Expand Down
21 changes: 21 additions & 0 deletions website/docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pr_labels = ["release"] # add the `release` label to the release Pull Request
publish_allow_dirty = true # add `--allow-dirty` to `cargo publish`
semver_check = false # disable API breaking changes checks
publish_timeout = "10m" # set a timeout for `cargo publish`
release_commits = "^feat:" # prepare release only if at least one commit matches a regex

[[package]] # the double square brackets define a TOML table array
name = "package_a"
Expand Down Expand Up @@ -70,6 +71,7 @@ the following sections:
- [`publish_no_verify`](#the-publish_no_verify-field) — Don't verify package build.
- [`publish_timeout`](#the-publish_timeout-field)`cargo publish` timeout.
- [`release`](#the-release-field) - Enable the processing of the packages.
- [`release_commits`](#the-release_commits-field) - Customize which commits trigger a release.
- [`repo_url`](#the-repo_url-field) — Repository URL.
- [`semver_check`](#the-semver_check-field) — Run [cargo-semver-checks].
- [`[[package]]`](#the-package-section) — Package-specific configurations.
Expand Down Expand Up @@ -332,6 +334,25 @@ Example:
release = false
```

#### The `release_commits` field

In `release-plz update` and `release-plz release-pr`, `release-plz` bumps the version and updates the changelog
of the package only if at least one of the commits matches the `release_commits` regex.

You can use this if you think it is too noisy to raise PRs on every commit.

Examples:

- With `release_commits = "^feat:"`, release-plz will update the package only if there's a new feature.
- With `release_commits = "^(feat:|docs:)"`, release-plz will update the package only if there's a new feature or a documentation change.

By default, release-plz updates the package on every commit.

:::warning
The filtered commits are still included in the changelog.
To exclude certain commits from the changelog, use the [commit_parsers](#the-commit_parsers-field) field.
:::

#### The `repo_url` field

GitHub/Gitea repository URL where your project is hosted.
Expand Down

0 comments on commit ba4787b

Please sign in to comment.