From faa00c6e6cee3c4fa7bd06e5dd409d81ca4b6b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Sun, 31 Dec 2023 15:34:01 +0100 Subject: [PATCH] feat(changelog): improve skipping via `.cliffignore` and `--skip-commit` (#413) * feat(changelog): support `.cliffignore` for skipping commits * feat(args): add `--skip-commit` argument * docs(website): add documentation about skipping commits * refactor: support ignore file for multiple repositories --- .cliffignore | 4 ++ .github/fixtures/test-skip-commits/cliff.toml | 34 +++++++++++++++++ .github/fixtures/test-skip-commits/commit.sh | 11 ++++++ .../fixtures/test-skip-commits/expected.md | 22 +++++++++++ .github/workflows/test-fixtures.yml | 2 + git-cliff-core/src/config.rs | 2 +- git-cliff-core/src/lib.rs | 2 + git-cliff/src/args.rs | 8 ++++ git-cliff/src/lib.rs | 38 +++++++++++++++++-- website/docs/usage/adding-commits.md | 2 +- website/docs/usage/args.md | 2 + website/docs/usage/print-context.md | 2 +- website/docs/usage/skipping-commits.md | 22 +++++++++++ 13 files changed, 145 insertions(+), 6 deletions(-) create mode 100644 .cliffignore create mode 100644 .github/fixtures/test-skip-commits/cliff.toml create mode 100755 .github/fixtures/test-skip-commits/commit.sh create mode 100644 .github/fixtures/test-skip-commits/expected.md create mode 100644 website/docs/usage/skipping-commits.md diff --git a/.cliffignore b/.cliffignore new file mode 100644 index 00000000..c87fe4b --- /dev/null +++ b/.cliffignore @@ -0,0 +1,4 @@ +# skip commits by their SHA1 + +4f88dda8c746173ea59f920b7579b7f6c74bd6c8 +10c3194381f2cc4f93eb97404369568882ed8677 diff --git a/.github/fixtures/test-skip-commits/cliff.toml b/.github/fixtures/test-skip-commits/cliff.toml new file mode 100644 index 00000000..9a9d380 --- /dev/null +++ b/.github/fixtures/test-skip-commits/cliff.toml @@ -0,0 +1,34 @@ +[changelog] +# changelog header +header = """ +# Changelog\n +All notable changes to this project will be documented in this file.\n +""" +# template for the changelog body +# https://keats.github.io/tera/docs/#introduction +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | upper_first }} + {% for commit in commits %} + - {{ commit.message | upper_first }}\ + {% endfor %} +{% endfor %}\n +""" +# template for the changelog footer +footer = """ + +""" +# remove the leading and trailing whitespace from the templates +trim = true + +[git] +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^feat", group = "Features", default_scope = "app" }, + { message = "^fix", group = "Bug Fixes", scope = "cli" }, +] diff --git a/.github/fixtures/test-skip-commits/commit.sh b/.github/fixtures/test-skip-commits/commit.sh new file mode 100755 index 00000000..102ce6b --- /dev/null +++ b/.github/fixtures/test-skip-commits/commit.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -e + +git remote add origin https://github.com/orhun/git-cliff-readme-example +git pull origin master +git fetch --tags +{ + echo "06412ac1dd4071006c465dde6597a21d4367a158" + echo "81fbc6365484abf0b4f4b05d384175763ad8db44" + echo "e4fd3cf8e2e6f49c0b57f66416e886c37cbb3715" +} >>.cliffignore diff --git a/.github/fixtures/test-skip-commits/expected.md b/.github/fixtures/test-skip-commits/expected.md new file mode 100644 index 00000000..d2e5ab4 --- /dev/null +++ b/.github/fixtures/test-skip-commits/expected.md @@ -0,0 +1,22 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [unreleased] + +### Features + +- Support multiple file formats +- Use cache while fetching pages + +## [1.0.0] - 2021-07-18 + +### Bug Fixes + +- Rename help argument due to conflict + +### Features + +- Add ability to parse arrays + + diff --git a/.github/workflows/test-fixtures.yml b/.github/workflows/test-fixtures.yml index 9419617..af2d36b 100644 --- a/.github/workflows/test-fixtures.yml +++ b/.github/workflows/test-fixtures.yml @@ -61,6 +61,8 @@ jobs: command: --latest --unreleased - fixtures-name: test-keep-a-changelog-links-one-tag-bump-arg command: --bump + - fixtures-name: test-skip-commits + command: --skip-commit ad27b43e8032671afb4809a1a3ecf12f45c60e0e steps: - name: Checkout uses: actions/checkout@v4 diff --git a/git-cliff-core/src/config.rs b/git-cliff-core/src/config.rs index 081f2d1..acc7b87 100644 --- a/git-cliff-core/src/config.rs +++ b/git-cliff-core/src/config.rs @@ -137,7 +137,7 @@ impl Remote { } /// Parser for grouping commits. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize)] pub struct CommitParser { /// SHA1 of the commit. pub sha: Option, diff --git a/git-cliff-core/src/lib.rs b/git-cliff-core/src/lib.rs index e88318c..a2202fe 100644 --- a/git-cliff-core/src/lib.rs +++ b/git-cliff-core/src/lib.rs @@ -42,3 +42,5 @@ extern crate log; pub const DEFAULT_CONFIG: &str = "cliff.toml"; /// Default output file. pub const DEFAULT_OUTPUT: &str = "CHANGELOG.md"; +/// Default ignore file. +pub const IGNORE_FILE: &str = ".cliffignore"; diff --git a/git-cliff/src/args.rs b/git-cliff/src/args.rs index 5a3e5ac..a668634 100644 --- a/git-cliff/src/args.rs +++ b/git-cliff/src/args.rs @@ -137,6 +137,14 @@ pub struct Opt { num_args(1..) )] pub with_commit: Option>, + /// Sets commits that will be skipped in the changelog. + #[arg( + long, + env = "GIT_CLIFF_SKIP_COMMIT", + value_name = "SHA1", + num_args(1..) + )] + pub skip_commit: Option>, /// Prepends entries to the given changelog file. #[arg( short, diff --git a/git-cliff/src/lib.rs b/git-cliff/src/lib.rs index 8b98202..4ae3008 100644 --- a/git-cliff/src/lib.rs +++ b/git-cliff/src/lib.rs @@ -21,7 +21,10 @@ use args::{ use clap::ValueEnum; use git_cliff_core::changelog::Changelog; use git_cliff_core::commit::Commit; -use git_cliff_core::config::Config; +use git_cliff_core::config::{ + CommitParser, + Config, +}; use git_cliff_core::embed::{ BuiltinConfig, EmbeddedConfig, @@ -32,7 +35,10 @@ use git_cliff_core::error::{ }; use git_cliff_core::release::Release; use git_cliff_core::repo::Repository; -use git_cliff_core::DEFAULT_CONFIG; +use git_cliff_core::{ + DEFAULT_CONFIG, + IGNORE_FILE, +}; use secrecy::Secret; use std::env; use std::fs::{ @@ -397,10 +403,36 @@ pub fn run(mut args: Opt) -> Result<()> { } config.git.skip_tags = config.git.skip_tags.filter(|r| !r.as_str().is_empty()); - // Process the repository. + // Process the repositories. let repositories = args.repository.clone().unwrap_or(vec![env::current_dir()?]); let mut releases = Vec::::new(); for repository in repositories { + // Skip commits + let mut skip_list = Vec::new(); + let ignore_file = repository.join(IGNORE_FILE); + if ignore_file.exists() { + let contents = fs::read_to_string(ignore_file)?; + let commits = contents + .lines() + .filter(|v| !(v.starts_with('#') || v.trim().is_empty())) + .map(|v| String::from(v.trim())) + .collect::>(); + skip_list.extend(commits); + } + if let Some(ref skip_commit) = args.skip_commit { + skip_list.extend(skip_commit.clone()); + } + if let Some(commit_parsers) = config.git.commit_parsers.as_mut() { + for sha1 in skip_list { + commit_parsers.insert(0, CommitParser { + sha: Some(sha1.to_string()), + skip: Some(true), + ..Default::default() + }) + } + } + + // Process the repository. let repository = Repository::init(repository)?; releases.extend(process_repository( Box::leak(Box::new(repository)), diff --git a/website/docs/usage/adding-commits.md b/website/docs/usage/adding-commits.md index 447ea5b..788a409 100644 --- a/website/docs/usage/adding-commits.md +++ b/website/docs/usage/adding-commits.md @@ -1,5 +1,5 @@ --- -sidebar_position: 7 +sidebar_position: 8 --- # Adding custom commits diff --git a/website/docs/usage/args.md b/website/docs/usage/args.md index 377ba0d..f71b978 100644 --- a/website/docs/usage/args.md +++ b/website/docs/usage/args.md @@ -1,6 +1,7 @@ --- sidebar_position: 1 --- + # Command-line Arguments ``` @@ -32,6 +33,7 @@ git-cliff [FLAGS] [OPTIONS] [--] [RANGE] --include-path ... Sets the path to include related commits [env: GIT_CLIFF_INCLUDE_PATH=] --exclude-path ... Sets the path to exclude related commits [env: GIT_CLIFF_EXCLUDE_PATH=] --with-commit ... Sets custom commit messages to include in the changelog [env: GIT_CLIFF_WITH_COMMIT=] + --skip-commit ... Sets commits that will be skipped in the changelog [env: GIT_CLIFF_SKIP_COMMIT=] -p, --prepend Prepends entries to the given changelog file [env: GIT_CLIFF_PREPEND=] -o, --output [] Writes output to the given file [env: GIT_CLIFF_OUTPUT=] -t, --tag Sets the tag for the latest version [env: GIT_CLIFF_TAG=] diff --git a/website/docs/usage/print-context.md b/website/docs/usage/print-context.md index 4b13918..8335550 100644 --- a/website/docs/usage/print-context.md +++ b/website/docs/usage/print-context.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 9 --- # Print context diff --git a/website/docs/usage/skipping-commits.md b/website/docs/usage/skipping-commits.md new file mode 100644 index 00000000..a515cb2 --- /dev/null +++ b/website/docs/usage/skipping-commits.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 7 +--- + +# Skipping commits + +You can use `--skip-commit` argument to skip specific commits by their SHA1 value: + +```bash +git cliff --skip-commit a78bc368e9ee382a3016c0c4bab41f7de4503bcd +``` + +If you have multiple commits to skip, you can either use this argument multiple times or create `.cliffignore` at the root of your repository. + +For example: + +```bash +# contents of .cliffignore + +4f88dda8c746173ea59f920b7579b7f6c74bd6c8 +10c3194381f2cc4f93eb97404369568882ed8677 +```