Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1274 prepare release if commit match regex #1278

Merged
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