From 925389b67162e3f5299d9920bee83d26bd23a6f7 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Wed, 19 Apr 2023 12:12:27 +0800 Subject: [PATCH 001/146] feat: create CODEOWNERS file --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..4f08a45 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @shenxianpeng From fc991a60891a437cc42eeb215c65199ef6bb010a Mon Sep 17 00:00:00 2001 From: Peter Shen <129301690+sxp-dev@users.noreply.github.com> Date: Tue, 18 Apr 2023 22:16:11 -0600 Subject: [PATCH 002/146] fix: remove requirements (#93) --- .github/workflows/main.yml | 1 - requirements.txt | 1 - 2 files changed, 2 deletions(-) delete mode 100644 requirements.txt diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 38edf36..28601df 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,7 +7,6 @@ on: pull_request: paths: - "**.py" - - "**requirements*.txt" - pyproject.toml - ".github/workflows/main.yml" - "!docs/**" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index c3726e8..0000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pyyaml From 2f4f0c69d7a9eafb32008b1ff920938b726f7966 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 20:53:16 +0800 Subject: [PATCH 003/146] chore(deps): bump github/codeql-action from 2.2.11 to 2.3.0 (#94) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.2.11 to 2.3.0. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/d186a2a36cc67bfa1b860e6170d37fb9634742c7...b2c19fb9a2a485599ccf4ed5d65527d94bc57226) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index fb23251..978e27f 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@d186a2a36cc67bfa1b860e6170d37fb9634742c7 # v2.2.11 + uses: github/codeql-action/upload-sarif@b2c19fb9a2a485599ccf4ed5d65527d94bc57226 # v2.3.0 with: sarif_file: results.sarif From 93725cff09f68a83d9afa9ba7f35b6fec65ed8a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 15:34:38 +0800 Subject: [PATCH 004/146] chore(deps): bump github/codeql-action from 2.3.0 to 2.3.2 (#95) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.3.0 to 2.3.2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b2c19fb9a2a485599ccf4ed5d65527d94bc57226...f3feb00acb00f31a6f60280e6ace9ca31d91c76a) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 978e27f..5178b44 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@b2c19fb9a2a485599ccf4ed5d65527d94bc57226 # v2.3.0 + uses: github/codeql-action/upload-sarif@f3feb00acb00f31a6f60280e6ace9ca31d91c76a # v2.3.2 with: sarif_file: results.sarif From 7155346baea5b4f4b1329b187430054c615a4352 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 13:20:14 +0800 Subject: [PATCH 005/146] chore(deps): bump github/codeql-action from 2.3.2 to 2.3.3 (#96) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.3.2 to 2.3.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f3feb00acb00f31a6f60280e6ace9ca31d91c76a...29b1f65c5e92e24fe6b6647da1eaabe529cec70f) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 5178b44..1c6af8e 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@f3feb00acb00f31a6f60280e6ace9ca31d91c76a # v2.3.2 + uses: github/codeql-action/upload-sarif@29b1f65c5e92e24fe6b6647da1eaabe529cec70f # v2.3.3 with: sarif_file: results.sarif From 795fbd1d1095b435b7e2d914393597015693d45c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 13:48:49 +0800 Subject: [PATCH 006/146] ci: pre-commit autoupdate (#98) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.2.0 → v1.3.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.2.0...v1.3.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8c433c7..b138694 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.2.0 + rev: v1.3.0 hooks: - id: mypy additional_dependencies: [types-all] From efc4ed58cf9d9603a1de854ad0eb4a6f4af9d97e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 15:00:44 +0800 Subject: [PATCH 007/146] chore(deps): bump github/codeql-action from 2.3.3 to 2.3.5 (#99) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.3.3 to 2.3.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/29b1f65c5e92e24fe6b6647da1eaabe529cec70f...0225834cc549ee0ca93cb085b92954821a145866) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 1c6af8e..0d5d9cd 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@29b1f65c5e92e24fe6b6647da1eaabe529cec70f # v2.3.3 + uses: github/codeql-action/upload-sarif@0225834cc549ee0ca93cb085b92954821a145866 # v2.3.5 with: sarif_file: results.sarif From ba051ff5c3acb4070187d8d4f517efeca29b2d96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:48:36 +0800 Subject: [PATCH 008/146] chore(deps): bump github/codeql-action from 2.3.5 to 2.3.6 (#100) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.3.5 to 2.3.6. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/0225834cc549ee0ca93cb085b92954821a145866...83f0fe6c4988d98a455712a27f0255212bba9bd4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 0d5d9cd..3a9d363 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@0225834cc549ee0ca93cb085b92954821a145866 # v2.3.5 + uses: github/codeql-action/upload-sarif@83f0fe6c4988d98a455712a27f0255212bba9bd4 # v2.3.6 with: sarif_file: results.sarif From 75c11316521681a531ed3a7c105f8a0bffc14260 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 01:08:25 -0400 Subject: [PATCH 009/146] chore(deps): bump github/codeql-action from 2.3.6 to 2.13.4 (#101) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.3.6 to 2.13.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/83f0fe6c4988d98a455712a27f0255212bba9bd4...cdcdbb579706841c47f7063dda365e292e5cad7a) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 3a9d363..588180b 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@83f0fe6c4988d98a455712a27f0255212bba9bd4 # v2.3.6 + uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 with: sarif_file: results.sarif From 5e1004146e76397c604e6296d7a4f459c5472f8b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 09:33:26 +0800 Subject: [PATCH 010/146] ci: pre-commit autoupdate (#102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/codespell-project/codespell: v2.2.4 → v2.2.5](https://github.com/codespell-project/codespell/compare/v2.2.4...v2.2.5) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b138694..334fa4f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: additional_dependencies: [types-all] exclude: ^testing/resources/ - repo: https://github.com/codespell-project/codespell - rev: v2.2.4 + rev: v2.2.5 hooks: - id: codespell - repo: https://github.com/commit-check/commit-check From 25f58d7226c4f85fdc29db664f9a93a39ef7b824 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Tue, 20 Jun 2023 10:04:15 +0800 Subject: [PATCH 011/146] fix(docs): remove repo_type from conf.py (#103) --- docs/conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index f006dc5..125dc6e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -49,7 +49,6 @@ html_theme_options = { "repo_url": "https://github.com/commit-check/commit-check", "repo_name": "commit-check", - "repo_type": "github", "palette": [ { "media": "(prefers-color-scheme: light)", From adc0ad9383deabf7ced4b26857c82e162eac0cca Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 Jun 2023 07:17:29 +0800 Subject: [PATCH 012/146] ci: pre-commit autoupdate (#105) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.3.0 → v1.4.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.3.0...v1.4.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 334fa4f..f681f14 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.3.0 + rev: v1.4.1 hooks: - id: mypy additional_dependencies: [types-all] From 1079e03d80110288c9eb10176f817026bd221f0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Jun 2023 18:19:17 +0800 Subject: [PATCH 013/146] chore(deps): bump ossf/scorecard-action from 2.1.3 to 2.2.0 (#104) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.1.3 to 2.2.0. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/80e868c13c90f172d68d1f4501dee99e2479f7af...08b4669551908b1024bb425080c797723083c031) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 588180b..44c8926 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -37,7 +37,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@80e868c13c90f172d68d1f4501dee99e2479f7af # v2.1.3 + uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0 with: results_file: results.sarif results_format: sarif From b8a6fce0fc38c137c77e2611a85992b881a2968c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 17:50:29 +0800 Subject: [PATCH 014/146] ci: pre-commit autoupdate (#106) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/PyCQA/flake8: 6.0.0 → 6.1.0](https://github.com/PyCQA/flake8/compare/6.0.0...6.1.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f681f14..52cf095 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: - id: name-tests-test - id: requirements-txt-fixer - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 + rev: 6.1.0 hooks: - id: flake8 args: [--max-line-length=100, --ignore=E501] From c8d687d19cba76f189a8db836666fbf1d672f966 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 16 Aug 2023 13:55:03 +0800 Subject: [PATCH 015/146] ci: pre-commit autoupdate (#108) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.4.1 → v1.5.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.4.1...v1.5.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 52cf095..992d699 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.4.1 + rev: v1.5.0 hooks: - id: mypy additional_dependencies: [types-all] From a7db01123dcef80638215ad120b24382e9cb5c5f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:49:40 +0800 Subject: [PATCH 016/146] ci: pre-commit autoupdate (#109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.5.0 → v1.5.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.5.0...v1.5.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 992d699..fe2559e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.5.0 + rev: v1.5.1 hooks: - id: mypy additional_dependencies: [types-all] From 3624c908242361cb3fe21bd1e5581b4da3df1664 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 21:01:22 +0800 Subject: [PATCH 017/146] chore(deps): bump actions/checkout from 3 to 4 (#110) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 6 +++--- .github/workflows/publish-image.yml | 2 +- .github/workflows/publish-package.yml | 2 +- .github/workflows/scorecard.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 28601df..106cc67 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,7 +16,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: python-version: '3.x' @@ -64,7 +64,7 @@ jobs: os: ['windows-latest', ubuntu-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: python-version: ${{ matrix.py }} @@ -83,7 +83,7 @@ jobs: docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: python-version: "3.10" diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml index 7825360..d10b181 100644 --- a/.github/workflows/publish-image.yml +++ b/.github/workflows/publish-image.yml @@ -12,7 +12,7 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build and publish docker image if: github.event.inputs.tag != '' run: | diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index 9f92a74..d46fc8e 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -9,7 +9,7 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # use fetch --all for setuptools_scm to work with: fetch-depth: 0 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 44c8926..253a0b7 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,7 +32,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0 + uses: actions/checkout@v4 # v3.1.0 with: persist-credentials: false From fe4ddd1d428684cac329201a22c380384d8ee086 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 4 Oct 2023 07:13:16 +0800 Subject: [PATCH 018/146] ci: pre-commit autoupdate (#111) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fe2559e..04e7432 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: additional_dependencies: [types-all] exclude: ^testing/resources/ - repo: https://github.com/codespell-project/codespell - rev: v2.2.5 + rev: v2.2.6 hooks: - id: codespell - repo: https://github.com/commit-check/commit-check From 28a650ad813f34b71984de2f15bd2061abc15086 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:10:19 +0800 Subject: [PATCH 019/146] chore(deps): bump python from 3.11-slim to 3.12-slim (#113) Bumps python from 3.11-slim to 3.12-slim. --- updated-dependencies: - dependency-name: python dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9d54507..bb3aecd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11-slim +FROM python:3.12-slim ARG VERSION=="" From b0ec07c216c24eb10f1ed4b00c82c2dc2bb0c859 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:10:43 +0800 Subject: [PATCH 020/146] chore(deps): bump ossf/scorecard-action from 2.2.0 to 2.3.0 (#112) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.2.0 to 2.3.0. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/08b4669551908b1024bb425080c797723083c031...483ef80eb98fb506c348f7d62e28055e49fe2398) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 253a0b7..39f87b2 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -37,7 +37,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0 + uses: ossf/scorecard-action@483ef80eb98fb506c348f7d62e28055e49fe2398 # v2.3.0 with: results_file: results.sarif results_format: sarif From 9bb7790fa8af7bae76e03567912af20ca4e630de Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 10:28:25 +0800 Subject: [PATCH 021/146] ci: pre-commit autoupdate (#114) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.4.0 → v4.5.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.4.0...v4.5.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 04e7432..a3e76e1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ ci: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-yaml - id: check-toml From 9c545aa4d310d646979517a8cf633d489f5b7c07 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 17 Oct 2023 11:14:04 +0800 Subject: [PATCH 022/146] ci: pre-commit autoupdate (#115) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.5.1 → v1.6.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.5.1...v1.6.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a3e76e1..91ee2f0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.5.1 + rev: v1.6.0 hooks: - id: mypy additional_dependencies: [types-all] From daac2301b934d75232df75b2461dcc3570a37c7a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 11:40:33 +0800 Subject: [PATCH 023/146] ci: pre-commit autoupdate (#116) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.6.0 → v1.6.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.6.0...v1.6.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 91ee2f0..8c6f91a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.6.0 + rev: v1.6.1 hooks: - id: mypy additional_dependencies: [types-all] From d11b4805f5082821c1be3e8950623eea6e2f28f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 16:17:49 +0800 Subject: [PATCH 024/146] chore(deps): bump ossf/scorecard-action from 2.3.0 to 2.3.1 (#117) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/483ef80eb98fb506c348f7d62e28055e49fe2398...0864cf19026789058feabb7e87baa5f140aac736) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 39f87b2..9478ea0 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -37,7 +37,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@483ef80eb98fb506c348f7d62e28055e49fe2398 # v2.3.0 + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 with: results_file: results.sarif results_format: sarif From 3f0d4b37d3e3524b018a1ae501e1fe72d8bb60fd Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Thu, 2 Nov 2023 10:36:19 -0400 Subject: [PATCH 025/146] Support SLSA Provenance (#118) * fix: Docker image runs as root * chore: remove scorecard.yml * feat: support publish provenance * feat: add SLSA badge --- .github/workflows/main.yml | 2 +- .github/workflows/publish-package.yml | 27 ++++++++++ .github/workflows/scorecard.yml | 72 --------------------------- Dockerfile | 6 ++- README.rst | 4 ++ 5 files changed, 36 insertions(+), 75 deletions(-) delete mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 106cc67..7d8a517 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -99,7 +99,7 @@ jobs: name: "commit-check_docs" path: ${{ github.workspace }}/docs/_build/html - - name: Upload to github pages + - name: Upload docs to github pages # only publish doc changes from main branch if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' uses: peaceiris/actions-gh-pages@v3 diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index d46fc8e..bee061d 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -4,10 +4,13 @@ on: release: branches: [main] types: [published] + workflow_dispatch: jobs: publish: runs-on: ubuntu-latest + outputs: + hash: ${{ steps.hash.outputs.hash }} steps: - uses: actions/checkout@v4 # use fetch --all for setuptools_scm to work @@ -27,6 +30,17 @@ jobs: # Check distribution twine check dist/commit_check* + # Generate hashes used for provenance. + - name: Generate hash + id: hash + run: | + cd dist + HASHES=$(sha256sum * | base64 -w0) + echo "hashes=$HASHES" >> "$GITHUB_OUTPUT" + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce + with: + path: ./dist + - name: Publish package to TestPyPI if: github.event_name == 'workflow_dispatch' && github.repository == 'commit-check/commit-check' env: @@ -41,3 +55,16 @@ jobs: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} run: twine upload dist/commit_check* + + provenance: + needs: ['publish'] + permissions: + actions: read # To read the workflow path. + id-token: write # To sign the provenance. + contents: write # To add assets to a release. + # Can't pin with hash due to how this workflow works. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0 + with: + base64-subjects: ${{ needs.build.outputs.hash }} + upload-assets: true # Optional: Upload to a new release + continue-on-error: true diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml deleted file mode 100644 index 9478ea0..0000000 --- a/.github/workflows/scorecard.yml +++ /dev/null @@ -1,72 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. They are provided -# by a third-party and are governed by separate terms of service, privacy -# policy, and support documentation. - -name: Scorecard supply-chain security -on: - # For Branch-Protection check. Only the default branch is supported. See - # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection - branch_protection_rule: - # To guarantee Maintained check is occasionally updated. See - # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained - schedule: - - cron: '24 17 * * 0' - push: - branches: [ "main" ] - -# Declare default permissions as read only. -permissions: read-all - -jobs: - analysis: - name: Scorecard analysis - runs-on: ubuntu-latest - permissions: - # Needed to upload the results to code-scanning dashboard. - security-events: write - # Needed to publish results and get a badge (see publish_results below). - id-token: write - # Uncomment the permissions below if installing in a private repository. - # contents: read - # actions: read - - steps: - - name: "Checkout code" - uses: actions/checkout@v4 # v3.1.0 - with: - persist-credentials: false - - - name: "Run analysis" - uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 - with: - results_file: results.sarif - results_format: sarif - # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: - # - you want to enable the Branch-Protection check on a *public* repository, or - # - you are installing Scorecard on a *private* repository - # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. - # repo_token: ${{ secrets.SCORECARD_TOKEN }} - - # Public repositories: - # - Publish results to OpenSSF REST API for easy access by consumers - # - Allows the repository to include the Scorecard badge. - # - See https://github.com/ossf/scorecard-action#publishing-results. - # For private repositories: - # - `publish_results` will always be set to `false`, regardless - # of the value entered here. - publish_results: true - - # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF - # format to the repository Actions tab. - - name: "Upload artifact" - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 - with: - name: SARIF file - path: results.sarif - retention-days: 5 - - # Upload the results to GitHub's code scanning dashboard. - - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 - with: - sarif_file: results.sarif diff --git a/Dockerfile b/Dockerfile index bb3aecd..cc411cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM python:3.12-slim -ARG VERSION=="" +ARG VERSION LABEL com.github.actions.name="Commit Check" LABEL com.github.actions.description="Check commit message formatting, branch naming, commit author, email, and more." @@ -10,10 +10,12 @@ LABEL com.github.actions.color="gray-dark" LABEL repository="https://github.com/commit-check/commit-check" LABEL maintainer="shenxianpeng <20297606+shenxianpeng@users.noreply.github.com>" -RUN if [ -z "${VERSION}" ]; then \ +RUN if [ -z "$VERSION" ]; then \ pip3 install commit-check; \ else \ pip3 install commit-check==$VERSION; \ fi +USER nobody + ENTRYPOINT [ "commit-check" ] diff --git a/README.rst b/README.rst index 32e6071..3e5169e 100644 --- a/README.rst +++ b/README.rst @@ -21,6 +21,10 @@ Commit Check :target: https://github.com/commit-check/commit-check :alt: commit-check +.. image:: https://slsa.dev/images/gh-badge-level3.svg + :target: https://slsa.dev + :alt: SLSA + Overview -------- From e279852e6c6906ea5acf5a350a3c0be867a37386 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Thu, 2 Nov 2023 10:57:51 -0400 Subject: [PATCH 026/146] fix: publish provenance workflow issue (#119) --- .github/workflows/publish-package.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index bee061d..09adc1a 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -35,11 +35,11 @@ jobs: id: hash run: | cd dist - HASHES=$(sha256sum * | base64 -w0) + HASHES=$(sha256sum commit_check* | base64 -w0) echo "hashes=$HASHES" >> "$GITHUB_OUTPUT" - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce with: - path: ./dist + path: ./dist/commit_check* - name: Publish package to TestPyPI if: github.event_name == 'workflow_dispatch' && github.repository == 'commit-check/commit-check' @@ -65,6 +65,6 @@ jobs: # Can't pin with hash due to how this workflow works. uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0 with: - base64-subjects: ${{ needs.build.outputs.hash }} + base64-subjects: ${{ needs.publish.outputs.hash }} upload-assets: true # Optional: Upload to a new release continue-on-error: true From 62171d4ebbab66330667e0b32dfc58cf08b7144c Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Thu, 2 Nov 2023 11:08:49 -0400 Subject: [PATCH 027/146] fixup! fix: publish provenance workflow issue (#119) --- .github/workflows/publish-package.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index 09adc1a..fc82261 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -10,7 +10,7 @@ jobs: publish: runs-on: ubuntu-latest outputs: - hash: ${{ steps.hash.outputs.hash }} + hashes: ${{ steps.hash.outputs.hashes }} steps: - uses: actions/checkout@v4 # use fetch --all for setuptools_scm to work @@ -30,16 +30,12 @@ jobs: # Check distribution twine check dist/commit_check* - # Generate hashes used for provenance. - - name: Generate hash + - name: Generate subject id: hash run: | cd dist HASHES=$(sha256sum commit_check* | base64 -w0) echo "hashes=$HASHES" >> "$GITHUB_OUTPUT" - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce - with: - path: ./dist/commit_check* - name: Publish package to TestPyPI if: github.event_name == 'workflow_dispatch' && github.repository == 'commit-check/commit-check' @@ -65,6 +61,6 @@ jobs: # Can't pin with hash due to how this workflow works. uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0 with: - base64-subjects: ${{ needs.publish.outputs.hash }} + base64-subjects: ${{ needs.publish.outputs.hashes }} upload-assets: true # Optional: Upload to a new release continue-on-error: true From 6efbb0b772edf69c7a1b105898f543f59616e6ef Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 16:15:43 -0500 Subject: [PATCH 028/146] ci: pre-commit autoupdate (#120) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8c6f91a..b5b3b7e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.5.6 + rev: v0.6.2 hooks: - id: check-message - id: check-branch From a517e4764d6d68a0cfc5fb39f8ca7a4e50fb4eb4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 17:54:41 -0500 Subject: [PATCH 029/146] ci: pre-commit autoupdate (#121) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b5b3b7e..49c71eb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.6.1 + rev: v1.7.0 hooks: - id: mypy additional_dependencies: [types-all] From 4b762aaf1ecc2fc976c5ce02be86fca47f489f31 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 16:18:05 -0500 Subject: [PATCH 030/146] ci: pre-commit autoupdate (#123) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 49c71eb..dd2b2fd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.0 + rev: v1.7.1 hooks: - id: mypy additional_dependencies: [types-all] From af416f44f7e4e68490cc33455083dd96107cfb98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 12:43:42 +0800 Subject: [PATCH 031/146] chore(deps): bump actions/setup-python from 4 to 5 (#124) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 6 +++--- .github/workflows/publish-package.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7d8a517..543ad3d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: '3.x' @@ -65,7 +65,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.py }} @@ -84,7 +84,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: "3.10" - run: python -m pip install . -r docs/requirements.txt diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index fc82261..592020b 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -17,7 +17,7 @@ jobs: with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' From 74596cbd13d8d17881b64e67b0e64a76f7179e9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 00:02:23 -0500 Subject: [PATCH 032/146] chore(deps): bump actions/upload-artifact from 3 to 4 (#127) --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 543ad3d..4da01bc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,7 +34,7 @@ jobs: - name: Build wheel run: python3 -m pip wheel --no-deps -w dist . - name: Upload wheel as artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: commit-check_wheel path: ${{ github.workspace }}/dist/*.whl @@ -94,7 +94,7 @@ jobs: run: sphinx-build -E -W -b html . _build/html - name: Save built docs as artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "commit-check_docs" path: ${{ github.workspace }}/docs/_build/html From e8f6f49141ad7a081681ae133eb117013e992c18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 00:02:45 -0500 Subject: [PATCH 033/146] chore(deps): bump actions/download-artifact from 3 to 4 (#126) --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4da01bc..3c5cdc8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -70,7 +70,7 @@ jobs: python-version: ${{ matrix.py }} - name: Download wheel artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: commit-check_wheel path: dist From edbdde6f1592cb6d20da3c171262a54158773f12 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Mon, 18 Dec 2023 21:55:48 -0700 Subject: [PATCH 034/146] fix: #122 cache problem (#125) --- .github/workflows/main.yml | 2 +- .pre-commit-hooks.yaml | 6 +- commit_check/__init__.py | 3 + commit_check/commit.py | 49 +++++---- commit_check/error.py | 2 +- commit_check/main.py | 10 +- commit_check/util.py | 12 -- tests/commit_test.py | 219 ++++++++++++++++--------------------- tests/util_test.py | 31 ------ 9 files changed, 134 insertions(+), 200 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3c5cdc8..33c6308 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -60,7 +60,7 @@ jobs: strategy: fail-fast: false matrix: - py: ['3.7', '3.8', '3.9', '3.10'] + py: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] os: ['windows-latest', ubuntu-latest] runs-on: ${{ matrix.os }} steps: diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 7327dbd..57d5cdd 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -1,11 +1,11 @@ - id: check-message name: check commit message description: requiring commit message to match regex - entry: env IS_PRE_COMMIT=1 commit-check + entry: commit-check args: [--message] - pass_filenames: false + pass_filenames: true language: python - stages: [commit-msg, commit] + stages: [commit-msg, prepare-commit-msg] - id: check-branch name: check branch naming description: requiring branch naming to match regex diff --git a/commit_check/__init__.py b/commit_check/__init__.py index 6abc60a..e710065 100644 --- a/commit_check/__init__.py +++ b/commit_check/__init__.py @@ -1,4 +1,5 @@ """The commit-check package's base module.""" +from importlib.metadata import version RED = '\033[0;31m' GREEN = "\033[32m" @@ -50,3 +51,5 @@ """ CONFIG_FILE = '.commit-check.yml' + +__version__ = version("commit-check") diff --git a/commit_check/commit.py b/commit_check/commit.py index 6ceb1c7..555d96e 100644 --- a/commit_check/commit.py +++ b/commit_check/commit.py @@ -1,33 +1,39 @@ """Check git commit message formatting""" import re -import os from pathlib import PurePath from commit_check import YELLOW, RESET_COLOR, PASS, FAIL from commit_check.util import cmd_output, get_commits_info, print_error_message, print_suggestion -def check_commit_msg(checks: list) -> int: +def get_default_commit_msg_file() -> str: + """Get the default commit message file.""" + git_dir = cmd_output(['git', 'rev-parse', '--git-dir']).strip() + return str(PurePath(git_dir, "COMMIT_EDITMSG")) + + +def read_commit_msg(commit_msg_file) -> str: + """Read the commit message from the specified file.""" + try: + with open(commit_msg_file, 'r') as f: + return f.read() + except FileNotFoundError: + return str(get_commits_info("s")) + + +def check_commit_msg(checks: list, commit_msg_file: str) -> int: + if not commit_msg_file: + commit_msg_file = get_default_commit_msg_file() + + commit_msg = read_commit_msg(commit_msg_file) + for check in checks: + if check['regex'] == "": + print( + f"{YELLOW}Not found regex for commit message. skip checking.{RESET_COLOR}", + ) + return PASS + if check['check'] == 'message': - if check['regex'] == "": - print( - f"{YELLOW}Not found regex for commit message. skip checking.{RESET_COLOR}", - ) - return PASS - commit_msg = "" - if os.environ.get("IS_PRE_COMMIT"): - # check the message of the current commit - git_dir = cmd_output(['git', 'rev-parse', '--git-dir']).strip() - commit_msg_file = PurePath(git_dir, "COMMIT_EDITMSG") - try: - with open(commit_msg_file, 'r') as f: - commit_msg = f.read() - except FileNotFoundError: - # check the message of the last commit - commit_msg = str(get_commits_info("s")) - else: - # check the message of the last commit - commit_msg = str(get_commits_info("s")) result = re.match(check['regex'], commit_msg) if result is None: print_error_message( @@ -37,4 +43,5 @@ def check_commit_msg(checks: list) -> int: if check['suggest']: print_suggestion(check['suggest']) return FAIL + return PASS diff --git a/commit_check/error.py b/commit_check/error.py index 3c6c801..2bdfa9b 100644 --- a/commit_check/error.py +++ b/commit_check/error.py @@ -28,8 +28,8 @@ def error_handler() -> Generator[None, None, None]: def log_and_exit(msg: str, ret_code: int, exc: BaseException, formatted: str) -> None: error_msg = f'{msg}: {type(exc).__name__}: {exc}' - git_version = cmd_output(['git', '--version']) commit_check_version = cmd_output(['commit-check', '--version']) + git_version = cmd_output(['git', '--version']) store_dir = os.environ.get('COMMIT_CHECK_HOME') or os.path.join( os.environ.get('XDG_CACHE_HOME') or os.path.expanduser('~/.cache'), diff --git a/commit_check/main.py b/commit_check/main.py index 8c4ec84..ecd4165 100644 --- a/commit_check/main.py +++ b/commit_check/main.py @@ -8,9 +8,9 @@ from commit_check import branch from commit_check import commit from commit_check import author -from commit_check.util import validate_config, get_version +from commit_check.util import validate_config from commit_check.error import error_handler -from . import RESET_COLOR, YELLOW, CONFIG_FILE, DEFAULT_CONFIG, PASS +from . import RESET_COLOR, YELLOW, CONFIG_FILE, DEFAULT_CONFIG, PASS, __version__ def get_parser() -> argparse.ArgumentParser: @@ -24,7 +24,7 @@ def get_parser() -> argparse.ArgumentParser: '-v', '--version', action='version', - version=f'%(prog)s {get_version()}', + version=f'%(prog)s {__version__}', ) parser.add_argument( @@ -42,6 +42,8 @@ def get_parser() -> argparse.ArgumentParser: required=False, ) + parser.add_argument('commit_msg_file', nargs='?', help='commit message file') + parser.add_argument( '-b', '--branch', @@ -96,7 +98,7 @@ def main() -> int: ) else DEFAULT_CONFIG checks = config['checks'] if args.message: - retval = commit.check_commit_msg(checks) + retval = commit.check_commit_msg(checks, args.commit_msg_file) if args.author_name: retval = author.check_author(checks, "author_name") if args.author_email: diff --git a/commit_check/util.py b/commit_check/util.py index 4dfb0ad..7e77604 100644 --- a/commit_check/util.py +++ b/commit_check/util.py @@ -12,18 +12,6 @@ from commit_check import RED, GREEN, RESET_COLOR -def get_version() -> str: - """Get current tag name - :returns: A `str` describing the version. - """ - try: - commands = ['git', 'describe', '--tags'] - version = cmd_output(commands) - except CalledProcessError: - version = '' - return version - - def get_branch_name() -> str: """Identify current branch name. .. note:: diff --git a/tests/commit_test.py b/tests/commit_test.py index 25da670..3d180c5 100644 --- a/tests/commit_test.py +++ b/tests/commit_test.py @@ -1,137 +1,102 @@ -import os from commit_check import PASS, FAIL -from commit_check.commit import check_commit_msg +from commit_check.commit import check_commit_msg, get_default_commit_msg_file, read_commit_msg # used by get_commits_info mock FAKE_BRANCH_NAME = "fake_commits_info" # The location of check_commit_msg() LOCATION = "commit_check.commit" +# Commit message file +MSG_FILE = '.git/COMMIT_EDITMSG' -class TestCommit: +def test_get_default_commit_msg_file(mocker): + mocker.patch("commit_check.util.cmd_output", return_value="git_dir_output") + retval = get_default_commit_msg_file() + assert retval == ".git/COMMIT_EDITMSG" - def test_check_commit_without_env(self, mocker): - # Must call get_commits_info, re.match. - checks = [{ - "check": "message", - "regex": "dummy_regex" - }] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", - return_value=FAKE_BRANCH_NAME - ) - m_re_match = mocker.patch( - "re.match", - return_value="fake_rematch_resp" - ) - retval = check_commit_msg(checks) - assert retval == PASS - assert m_get_commits_info.call_count == 1 - assert m_re_match.call_count == 1 - - def test_check_commit_with_env(self, mocker): - # Must call get_commits_info, re.match. - checks = [{ - "check": "message", - "regex": "dummy_regex" - }] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", - return_value=FAKE_BRANCH_NAME - ) - m_re_match = mocker.patch( - "re.match", - return_value="fake_rematch_resp" - ) - os.environ["IS_PRE_COMMIT"] = "1" - retval = check_commit_msg(checks) - assert retval == PASS - assert m_get_commits_info.call_count == 1 - assert m_re_match.call_count == 1 - - def test_check_commit_with_empty_checks(self, mocker): - # Must NOT call get_commits_info, re.match. with `checks` param with length 0. - checks = [] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", - return_value=FAKE_BRANCH_NAME - ) - m_re_match = mocker.patch( - "re.match", - return_value="fake_commits_info" - ) - retval = check_commit_msg(checks) - assert retval == PASS - assert m_get_commits_info.call_count == 0 - assert m_re_match.call_count == 0 - - def test_check_commit_with_different_check(self, mocker): - # Must NOT call get_commit_info, re.match with not `message`. - checks = [{ - "check": "branch", - "regex": "dummy_regex" - }] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", - return_value=FAKE_BRANCH_NAME - ) - m_re_match = mocker.patch( - "re.match", - return_value="fake_commits_info" - ) - retval = check_commit_msg(checks) - assert retval == PASS - assert m_get_commits_info.call_count == 0 - assert m_re_match.call_count == 0 - - def test_check_commit_with_len0_regex(self, mocker, capfd): - # Must NOT call get_commits_info, re.match with `regex` with length 0. - checks = [ - { - "check": "message", - "regex": "" - } - ] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", - return_value=FAKE_BRANCH_NAME - ) - m_re_match = mocker.patch( - "re.match", - return_value="fake_rematch_resp" - ) - retval = check_commit_msg(checks) - assert retval == PASS - assert m_get_commits_info.call_count == 0 - assert m_re_match.call_count == 0 - out, _ = capfd.readouterr() - assert "Not found regex for commit message." in out - - def test_check_commit_with_result_none(self, mocker): - # Must call print_error_message, print_suggestion when re.match returns NONE. - checks = [{ + +def test_read_commit_msg_file_found(tmp_path): + # Create a temporary file with content + commit_msg_file = tmp_path / "commit_msg.txt" + content = "Test commit message" + commit_msg_file.write_text(content) + + result = read_commit_msg(commit_msg_file) + assert result == content + + +def test_read_commit_msg_file_not_found(mocker): + mocker.patch(f'{LOCATION}.get_commits_info', return_value="Last commit message") + result = read_commit_msg("nonexistent_file.txt") + assert result == "Last commit message" + + +def test_check_commit_with_empty_checks(mocker): + # Must NOT call get_commits_info, re.match. with `checks` param with length 0. + checks = [] + m_re_match = mocker.patch( + "re.match", + return_value="fake_commits_info" + ) + retval = check_commit_msg(checks, MSG_FILE) + assert retval == PASS + assert m_re_match.call_count == 0 + + +def test_check_commit_with_different_check(mocker): + # Must NOT call get_commit_info, re.match with not `message`. + checks = [{ + "check": "branch", + "regex": "dummy_regex" + }] + m_re_match = mocker.patch( + "re.match", + return_value="fake_commits_info" + ) + retval = check_commit_msg(checks, MSG_FILE) + assert retval == PASS + assert m_re_match.call_count == 0 + + +def test_check_commit_with_len0_regex(mocker, capfd): + # Must NOT call get_commits_info, re.match with `regex` with length 0. + checks = [ + { "check": "message", - "regex": "dummy_regex", - "error": "error", - "suggest": "suggest" - }] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", - return_value=FAKE_BRANCH_NAME - ) - m_re_match = mocker.patch( - "re.match", - return_value=None - ) - m_print_error_message = mocker.patch( - f"{LOCATION}.print_error_message" - ) - m_print_suggestion = mocker.patch( - f"{LOCATION}.print_suggestion" - ) - retval = check_commit_msg(checks) - assert retval == FAIL - assert m_get_commits_info.call_count == 1 - assert m_re_match.call_count == 1 - assert m_print_error_message.call_count == 1 - assert m_print_suggestion.call_count == 1 + "regex": "" + } + ] + m_re_match = mocker.patch( + "re.match", + return_value="fake_rematch_resp" + ) + retval = check_commit_msg(checks, MSG_FILE) + assert retval == PASS + assert m_re_match.call_count == 0 + out, _ = capfd.readouterr() + assert "Not found regex for commit message." in out + + +def test_check_commit_with_result_none(mocker): + # Must call print_error_message, print_suggestion when re.match returns NONE. + checks = [{ + "check": "message", + "regex": "dummy_regex", + "error": "error", + "suggest": "suggest" + }] + m_re_match = mocker.patch( + "re.match", + return_value=None + ) + m_print_error_message = mocker.patch( + f"{LOCATION}.print_error_message" + ) + m_print_suggestion = mocker.patch( + f"{LOCATION}.print_suggestion" + ) + retval = check_commit_msg(checks, MSG_FILE) + assert retval == FAIL + assert m_re_match.call_count == 1 + assert m_print_error_message.call_count == 1 + assert m_print_suggestion.call_count == 1 diff --git a/tests/util_test.py b/tests/util_test.py index 4e5f417..17823fa 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -1,5 +1,4 @@ import pytest -from commit_check.util import get_version from commit_check.util import get_branch_name from commit_check.util import get_commits_info from commit_check.util import cmd_output @@ -10,36 +9,6 @@ class TestUtil: - class TestGetVersion: - def test_get_version(self, mocker): - m_cmd_output = mocker.patch( - "commit_check.util.cmd_output", - return_value="fake_version" - ) - retval = get_version() - assert m_cmd_output.call_count == 1 - assert m_cmd_output.call_args[0][0] == [ - "git", "describe", "--tags" - ] - assert retval == "fake_version" - - def test_get_version_with_exception(self, mocker): - m_cmd_output = mocker.patch( - "commit_check.util.cmd_output", - return_value="fake_version" - ) - dummy_ret_code, dummy_cmd_name = 1, "dcmd" - m_cmd_output.side_effect = CalledProcessError( - dummy_ret_code, - dummy_cmd_name - ) - retval = get_version() - assert m_cmd_output.call_count == 1 - assert m_cmd_output.call_args[0][0] == [ - "git", "describe", "--tags" - ] - assert retval == "" - class TestGetBranchName: def test_get_branch_name(self, mocker): # Must call cmd_output with given argument. From 3754b86aa01616c535d1fcd401263e59507e8183 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 19 Dec 2023 13:03:35 +0800 Subject: [PATCH 035/146] chore: update .pre-commit-config.yaml --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dd2b2fd..f96bc44 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.6.2 + rev: edbdde6f1592cb6d20da3c171262a54158773f12 hooks: - id: check-message - id: check-branch From 23c76e56dab71ce16a3ec8ed25c2ee2ad71f51c1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 25 Dec 2023 12:43:01 -0700 Subject: [PATCH 036/146] ci: pre-commit autoupdate (#130) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f96bc44..70f6f11 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.1 + rev: v1.8.0 hooks: - id: mypy additional_dependencies: [types-all] @@ -31,7 +31,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: edbdde6f1592cb6d20da3c171262a54158773f12 + rev: v0.6.3 hooks: - id: check-message - id: check-branch From baebbf23ef68146b2814afc7edfc0265f8b15674 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Tue, 26 Dec 2023 00:54:53 -0700 Subject: [PATCH 037/146] feat: support checking commit signoff (#128) --- .commit-check.yml | 8 +++++ .pre-commit-config.yaml | 3 +- .pre-commit-hooks.yaml | 7 ++++ README.rst | 22 ++++-------- commit_check/__init__.py | 6 ++++ commit_check/commit.py | 24 +++++++++++++ commit_check/main.py | 47 +++++++++++++------------ commit_check/util.py | 32 +++++------------ pyproject.toml | 1 - tests/commit_test.py | 76 ++++++++++++++++++++++++++++++++-------- tests/main_test.py | 71 +++++++++++++++---------------------- tests/util_test.py | 35 ++++++------------ 12 files changed, 189 insertions(+), 143 deletions(-) diff --git a/.commit-check.yml b/.commit-check.yml index 853c91b..5f48f93 100644 --- a/.commit-check.yml +++ b/.commit-check.yml @@ -7,15 +7,23 @@ checks: [optional footer(s)]\n\n More details please refer to https://www.conventionalcommits.org" suggest: please check your commit message whether matches above regex + - check: branch regex: ^(bugfix|feature|release|hotfix|task)\/.+|(master)|(main)|(HEAD)|(PR-.+) error: "Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/" suggest: run command `git checkout -b type/branch_name` + - check: author_name regex: ^[A-Za-z ,.\'-]+$|.*(\[bot]) error: The committer name seems invalid suggest: run command `git config user.name "Your Name"` + - check: author_email regex: ^\S+@\S+\.\S+$ error: The committer email seems invalid suggest: run command `git config user.email yourname@example.com` + + - check: commit_signoff + regex: Signed-off-by + error: Signed-off-by not found in latest commit + suggest: run command `git commit -m "conventional commit message" --signoff` diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 70f6f11..c65c49a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,8 @@ repos: hooks: - id: check-message - id: check-branch - - id: check-author-email + # - id: check-author-email # uncomment if you need. + # - id: commit-signoff # uncomment if you need. - repo: local hooks: - id: pytest diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 57d5cdd..0ba4a51 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -27,3 +27,10 @@ args: [--author-email] pass_filenames: false language: python +- id: check-commit-signoff + name: check committer signoff + description: requiring committer to add a Signed-off-by trailer + entry: commit-check + args: [--commit-signoff] + pass_filenames: false + language: python diff --git a/README.rst b/README.rst index 3e5169e..f47acbd 100644 --- a/README.rst +++ b/README.rst @@ -28,20 +28,11 @@ Commit Check Overview -------- -Check commit message formatting, branch naming, committer name, email, and more. Alternative to Yet Another Commit Checker. +Commit Check is open source alternative to Yet Another Commit Checker. -- requiring commit message to match regex -- requiring branch naming to match regex -- requiring committer name and email to match regex -- customizing error message -- customizing suggest command +It supports checking commit message, branch naming, committer name/email, commit signoff and customizing error message and suggest command (tell me more, please). -Purpose -------- - -commit-check is a tool designed for teams. - -Its main purpose is to standardize the format of commit message, branch naming, etc, and makes it possible to: +commit-check is a tool designed for teams. Its main purpose is to standardize the format of commit message, branch naming, etc, and makes it possible to: - writing descriptive commit is easy to read - identify branch according to the branch type @@ -59,7 +50,7 @@ Create a config file ``.commit-check.yml`` under your repository root directory, Use default configuration ~~~~~~~~~~~~~~~~~~~~~~~~~ -- If you did't set ``.commit-check.yml``, ``commit-check`` will use the `default configuration `_. +- If you did't set ``.commit-check.yml``, ``commit-check`` will use the `default configuration `_. - i.e. the commit message will follow the rules of `conventional commits `_, branch naming follow bitbucket `branching model `_. @@ -91,6 +82,7 @@ Running as pre-commit hook - id: check-branch - id: check-author-name - id: check-author-email + - id: check-commit-signoff Running as CLI ~~~~~~~~~~~~~~ @@ -153,7 +145,7 @@ Check commit message failed (.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ - Invalid commit message => test + Type message check failed => my test commit message It doesn't match regex: ^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test){1}(\([\w\-\.]+\))?(!)?: ([\w ])+([\s\S]*) The commit message should be structured as follows: @@ -183,7 +175,7 @@ Check branch naming failed Commit rejected. - Invalid branch name => test + Type branch check failed => my-test-branch It doesn't match regex: ^(bugfix|feature|release|hotfix|task)\/.+|(master)|(main)|(HEAD)|(PR-.+) Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/ diff --git a/commit_check/__init__.py b/commit_check/__init__.py index e710065..8d745fb 100644 --- a/commit_check/__init__.py +++ b/commit_check/__init__.py @@ -42,6 +42,12 @@ 'error': 'The committer\'s email seems invalid', 'suggest': 'run command `git config user.email yourname@example.com`', }, + { + 'check': 'commit_signoff', + 'regex': 'Signed-off-by', + 'error': 'Signed-off-by not found in latest commit', + 'suggest': 'run command `git commit -m "conventional commit message" --signoff`', + }, ], } diff --git a/commit_check/commit.py b/commit_check/commit.py index 555d96e..6fb0010 100644 --- a/commit_check/commit.py +++ b/commit_check/commit.py @@ -45,3 +45,27 @@ def check_commit_msg(checks: list, commit_msg_file: str) -> int: return FAIL return PASS + + +def check_commit_signoff(checks: list) -> int: + for check in checks: + if check['check'] == 'commit_signoff': + if check['regex'] == "": + print( + f"{YELLOW}Not found regex for commit signoff. skip checking.{RESET_COLOR}", + ) + return PASS + + commit_msg = get_commits_info("s") + commit_hash = get_commits_info("H") + result = re.match(check['regex'], commit_msg) + if result is None: + print_error_message( + check['check'], check['regex'], + check['error'], commit_hash, + ) + if check['suggest']: + print_suggestion(check['suggest']) + return FAIL + + return PASS diff --git a/commit_check/main.py b/commit_check/main.py index ecd4165..0a8a020 100644 --- a/commit_check/main.py +++ b/commit_check/main.py @@ -10,7 +10,7 @@ from commit_check import author from commit_check.util import validate_config from commit_check.error import error_handler -from . import RESET_COLOR, YELLOW, CONFIG_FILE, DEFAULT_CONFIG, PASS, __version__ +from . import CONFIG_FILE, DEFAULT_CONFIG, PASS, __version__ def get_parser() -> argparse.ArgumentParser: @@ -31,7 +31,7 @@ def get_parser() -> argparse.ArgumentParser: '-c', '--config', default=CONFIG_FILE, - help='path to config file. default is .', + help='path to config file. default is . (current directory)', ) parser.add_argument( @@ -68,6 +68,14 @@ def get_parser() -> argparse.ArgumentParser: required=False, ) + parser.add_argument( + '-s', + '--commit-signoff', + help='check committer\'s signature', + action="store_true", + required=False, + ) + parser.add_argument( '-d', '--dry-run', @@ -85,26 +93,21 @@ def main() -> int: args = parser.parse_args() retval = PASS - if not any([args.message, args.branch, args.author_name, args.author_email]): - print( - f'\n{YELLOW}Nothing to do because `--message`, `--branch`, `--author-name`, `--author-email`', - f'was not specified.{RESET_COLOR}\n', - ) - parser.print_help() - else: - with error_handler(): - config = validate_config(args.config) if validate_config( - args.config, - ) else DEFAULT_CONFIG - checks = config['checks'] - if args.message: - retval = commit.check_commit_msg(checks, args.commit_msg_file) - if args.author_name: - retval = author.check_author(checks, "author_name") - if args.author_email: - retval = author.check_author(checks, "author_email") - if args.branch: - retval = branch.check_branch(checks) + with error_handler(): + config = validate_config(args.config) if validate_config( + args.config, + ) else DEFAULT_CONFIG + checks = config['checks'] + if args.message: + retval = commit.check_commit_msg(checks, args.commit_msg_file) + if args.author_name: + retval = author.check_author(checks, "author_name") + if args.author_email: + retval = author.check_author(checks, "author_email") + if args.branch: + retval = branch.check_branch(checks) + if args.commit_signoff: + retval = commit.check_commit_signoff(checks) if args.dry_run: retval = PASS diff --git a/commit_check/util.py b/commit_check/util.py index 7e77604..6c9bfd7 100644 --- a/commit_check/util.py +++ b/commit_check/util.py @@ -9,7 +9,7 @@ import yaml from pathlib import PurePath from subprocess import CalledProcessError -from commit_check import RED, GREEN, RESET_COLOR +from commit_check import RED, GREEN, YELLOW, RESET_COLOR def get_branch_name() -> str: @@ -35,6 +35,9 @@ def get_commits_info(format_string: str) -> str: - s - subject - an - author name - ae - author email + - b - body + - H - commit hash + more: https://git-scm.com/docs/pretty-formats :returns: A `str`. """ @@ -80,12 +83,12 @@ def validate_config(path_to_config: str) -> dict: return configuration -def print_error_message(check_type: str, regex: str, error: str, error_point: str): +def print_error_message(check_type: str, regex: str, error: str, reason: str): """Print error message. :param check_type: :param regex: :param error: - :param error_point: + :param reason: :returns: Give error messages to user """ @@ -102,26 +105,9 @@ def print_error_message(check_type: str, regex: str, error: str, error_point: st print(" ") print("Commit rejected. ") print(" ") - if check_type == "message": - print( - f"Invalid commit message => {RED}{error_point}{RESET_COLOR} ", end='', - ) - elif check_type == "branch": - print( - f"Invalid branch name => {RED}{error_point}{RESET_COLOR} ", end='', - ) - elif check_type == "author_name": - print( - f"Invalid author name => {RED}{error_point}{RESET_COLOR} ", end='', - ) - elif check_type == "author_email": - print( - f"Invalid email address => {RED}{error_point}{RESET_COLOR} ", end='', - ) - else: - print(f"commit-check does not support {check_type} yet.") - raise SystemExit(1) - print(f"\nIt doesn't match regex: {regex}") + print(f"Type {YELLOW}{check_type}{RESET_COLOR} check failed => {RED}{reason}{RESET_COLOR} ", end='',) + print("") + print(f"It doesn't match regex: {regex}") print("") print(error) diff --git a/pyproject.toml b/pyproject.toml index a672861..361ccf0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,6 @@ classifiers = [ "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", diff --git a/tests/commit_test.py b/tests/commit_test.py index 3d180c5..4666828 100644 --- a/tests/commit_test.py +++ b/tests/commit_test.py @@ -1,5 +1,5 @@ from commit_check import PASS, FAIL -from commit_check.commit import check_commit_msg, get_default_commit_msg_file, read_commit_msg +from commit_check.commit import check_commit_msg, get_default_commit_msg_file, read_commit_msg, check_commit_signoff # used by get_commits_info mock FAKE_BRANCH_NAME = "fake_commits_info" @@ -10,29 +10,27 @@ def test_get_default_commit_msg_file(mocker): - mocker.patch("commit_check.util.cmd_output", return_value="git_dir_output") retval = get_default_commit_msg_file() assert retval == ".git/COMMIT_EDITMSG" -def test_read_commit_msg_file_found(tmp_path): - # Create a temporary file with content - commit_msg_file = tmp_path / "commit_msg.txt" - content = "Test commit message" - commit_msg_file.write_text(content) +def test_read_commit_msg_from_existing_file(tmp_path): + # Create a temporary file with a known content + commit_msg_content = "Test commit message content." + commit_msg_file = tmp_path / "test_commit_msg.txt" + commit_msg_file.write_text(commit_msg_content) result = read_commit_msg(commit_msg_file) - assert result == content + assert result == commit_msg_content def test_read_commit_msg_file_not_found(mocker): - mocker.patch(f'{LOCATION}.get_commits_info', return_value="Last commit message") - result = read_commit_msg("nonexistent_file.txt") - assert result == "Last commit message" + m_commits_info = mocker.patch('commit_check.util.get_commits_info', return_value='mocked_commits_info') + read_commit_msg("non_existent_file.txt") + assert m_commits_info.call_count == 0 def test_check_commit_with_empty_checks(mocker): - # Must NOT call get_commits_info, re.match. with `checks` param with length 0. checks = [] m_re_match = mocker.patch( "re.match", @@ -44,7 +42,6 @@ def test_check_commit_with_empty_checks(mocker): def test_check_commit_with_different_check(mocker): - # Must NOT call get_commit_info, re.match with not `message`. checks = [{ "check": "branch", "regex": "dummy_regex" @@ -59,7 +56,6 @@ def test_check_commit_with_different_check(mocker): def test_check_commit_with_len0_regex(mocker, capfd): - # Must NOT call get_commits_info, re.match with `regex` with length 0. checks = [ { "check": "message", @@ -78,7 +74,6 @@ def test_check_commit_with_len0_regex(mocker, capfd): def test_check_commit_with_result_none(mocker): - # Must call print_error_message, print_suggestion when re.match returns NONE. checks = [{ "check": "message", "regex": "dummy_regex", @@ -100,3 +95,54 @@ def test_check_commit_with_result_none(mocker): assert m_re_match.call_count == 1 assert m_print_error_message.call_count == 1 assert m_print_suggestion.call_count == 1 + + +def test_check_commit_signoff(mocker): + checks = [{ + "check": "commit_signoff", + "regex": "dummy_regex", + "error": "error", + "suggest": "suggest" + }] + m_re_match = mocker.patch( + "re.match", + return_value=None + ) + m_print_error_message = mocker.patch( + f"{LOCATION}.print_error_message" + ) + m_print_suggestion = mocker.patch( + f"{LOCATION}.print_suggestion" + ) + retval = check_commit_signoff(checks) + assert retval == FAIL + assert m_re_match.call_count == 1 + assert m_print_error_message.call_count == 1 + assert m_print_suggestion.call_count == 1 + + +def test_check_commit_signoff_with_empty_regex(mocker): + checks = [{ + "check": "commit_signoff", + "regex": "", + "error": "error", + "suggest": "suggest" + }] + m_re_match = mocker.patch( + "re.match", + return_value="fake_commits_info" + ) + retval = check_commit_signoff(checks) + assert retval == PASS + assert m_re_match.call_count == 0 + + +def test_check_commit_signoff_with_empty_checks(mocker): + checks = [] + m_re_match = mocker.patch( + "re.match", + return_value="fake_commits_info" + ) + retval = check_commit_signoff(checks) + assert retval == PASS + assert m_re_match.call_count == 0 diff --git a/tests/main_test.py b/tests/main_test.py index ed9b78c..3fdc184 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -7,23 +7,18 @@ class TestMain: - @pytest.mark.parametrize("argv, check_commit_call_count, check_branch_call_count, check_author_call_count", [ - ([CMD, "--message"], 1, 0, 0), - ([CMD, "--branch"], 0, 1, 0), - ([CMD, "--author-name"], 0, 0, 1), - ([CMD, "--author-email"], 0, 0, 1), - ([CMD, "--message", "--author-email"], 1, 0, 1), - ([CMD, "--branch", "--message"], 1, 1, 0), - ([CMD, "--author-name", "--author-email"], 0, 0, 2), - ([CMD, "--message", "--branch", "--author-email"], 1, 1, 1), - ([ - CMD, - "--branch", - "--message", - "--author-name", - "--author-email" - ], 1, 1, 2), - ([CMD, "--dry-run"], 0, 0, 0), + @pytest.mark.parametrize("argv, check_commit_call_count, check_branch_call_count, check_author_call_count, check_commit_signoff_call_count", [ + ([CMD, "--message"], 1, 0, 0, 0), + ([CMD, "--branch"], 0, 1, 0, 0), + ([CMD, "--author-name"], 0, 0, 1, 0), + ([CMD, "--author-email"], 0, 0, 1, 0), + ([CMD, "--commit-signoff"], 0, 0, 0, 1), + ([CMD, "--message", "--author-email"], 1, 0, 1, 0), + ([CMD, "--branch", "--message"], 1, 1, 0, 0), + ([CMD, "--author-name", "--author-email"], 0, 0, 2, 0), + ([CMD, "--message", "--branch", "--author-email"], 1, 1, 1, 0), + ([CMD, "--branch", "--message", "--author-name", "--author-email"], 1, 1, 2, 0), + ([CMD, "--dry-run"], 0, 0, 0, 0), ]) def test_main( self, @@ -31,7 +26,8 @@ def test_main( argv, check_commit_call_count, check_branch_call_count, - check_author_call_count + check_author_call_count, + check_commit_signoff_call_count, ): mocker.patch( "commit_check.main.validate_config", @@ -42,17 +38,15 @@ def test_main( } ) m_check_commit = mocker.patch("commit_check.commit.check_commit_msg") - m_check_branch = mocker.patch( - "commit_check.branch.check_branch" - ) - m_check_author = mocker.patch( - "commit_check.author.check_author" - ) + m_check_branch = mocker.patch("commit_check.branch.check_branch") + m_check_author = mocker.patch("commit_check.author.check_author") + m_check_commit_signoff = mocker.patch("commit_check.commit.check_commit_signoff") sys.argv = argv main() assert m_check_commit.call_count == check_commit_call_count assert m_check_branch.call_count == check_branch_call_count assert m_check_author.call_count == check_author_call_count + assert m_check_commit_signoff.call_count == check_commit_signoff_call_count def test_main_help(self, mocker, capfd): mocker.patch( @@ -64,18 +58,16 @@ def test_main_help(self, mocker, capfd): } ) m_check_commit = mocker.patch("commit_check.commit.check_commit_msg") - m_check_branch = mocker.patch( - "commit_check.branch.check_branch" - ) - m_check_author = mocker.patch( - "commit_check.author.check_author" - ) + m_check_branch = mocker.patch("commit_check.branch.check_branch") + m_check_author = mocker.patch("commit_check.author.check_author") + m_check_commit_signoff = mocker.patch("commit_check.commit.check_commit_signoff") sys.argv = ["commit-check", "--h"] with pytest.raises(SystemExit): main() assert m_check_commit.call_count == 0 assert m_check_branch.call_count == 0 assert m_check_author.call_count == 0 + assert m_check_commit_signoff.call_count == 0 stdout, _ = capfd.readouterr() assert "usage: " in stdout @@ -89,18 +81,16 @@ def test_main_version(self, mocker): } ) m_check_commit = mocker.patch("commit_check.commit.check_commit_msg") - m_check_branch = mocker.patch( - "commit_check.branch.check_branch" - ) - m_check_author = mocker.patch( - "commit_check.author.check_author" - ) + m_check_branch = mocker.patch("commit_check.branch.check_branch") + m_check_author = mocker.patch("commit_check.author.check_author") + m_check_commit_signoff = mocker.patch("commit_check.commit.check_commit_signoff") sys.argv = ["commit-check", "--v"] with pytest.raises(SystemExit): main() assert m_check_commit.call_count == 0 assert m_check_branch.call_count == 0 assert m_check_author.call_count == 0 + assert m_check_commit_signoff.call_count == 0 def test_main_validate_config_ret_none(self, mocker): mocker.patch( @@ -108,12 +98,9 @@ def test_main_validate_config_ret_none(self, mocker): return_value={} ) m_check_commit = mocker.patch("commit_check.commit.check_commit_msg") - mocker.patch( - "commit_check.branch.check_branch" - ) - mocker.patch( - "commit_check.author.check_author" - ) + mocker.patch("commit_check.branch.check_branch") + mocker.patch("commit_check.author.check_author") + mocker.patch("commit_check.commit.check_commit_signoff") sys.argv = ["commit-check", "--message"] main() assert m_check_commit.call_count == 1 diff --git a/tests/util_test.py b/tests/util_test.py index 17823fa..1e3dd66 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -170,45 +170,32 @@ def test_validate_config_file_not_found(self, mocker): assert retval == {} class TestPrintErrorMessage: - @pytest.mark.parametrize("check_type, invalid_type_msg", [ - ("message", "Invalid commit message"), - ("branch", "Invalid branch name"), - ("author_name", "Invalid author name"), - ("author_email", "Invalid email address"), + @pytest.mark.parametrize("check_type, type_failed_msg", [ + ("message", "check failed =>"), + ("branch", "check failed =>"), + ("author_name", "check failed =>"), + ("author_email", "check failed =>"), + ("commit_signoff", "check failed =>"), ]) - def test_print_error_message(self, capfd, check_type, invalid_type_msg): + def test_print_error_message(self, capfd, check_type, type_failed_msg): # Must print on stdout with given argument. dummy_regex = "dummy regex" - dummy_error_point = "error point" + dummy_reason = "failure reason" dummy_error = "dummy error" print_error_message( check_type, dummy_regex, dummy_error, - dummy_error_point + dummy_reason ) stdout, _ = capfd.readouterr() assert "Commit rejected by Commit-Check" in stdout assert "Commit rejected." in stdout - assert invalid_type_msg in stdout + assert check_type in stdout + assert type_failed_msg in stdout assert f"It doesn't match regex: {dummy_regex}" in stdout assert dummy_error in stdout - def test_print_error_message_exit1(self, capfd): - # Must exit with 1 when not supported check type passed. - with pytest.raises(SystemExit) as e: - print_error_message( - "not_supported_check_type", - "", - "", - "not supported check type error" - ) - assert e.value.code == 1 - stdout, _ = capfd.readouterr() - assert "Commit rejected by Commit-Check" in stdout - assert "Commit rejected." in stdout - assert "commit-check does not support" in stdout - class TestPrintSuggestion: def test_print_suggestion(self, capfd): # Must print on stdout with given argument. From e931722d5d7cf70c5c512b90f5613ca9b622194a Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Fri, 29 Dec 2023 14:10:37 +0800 Subject: [PATCH 038/146] feat: Create release.yml --- .github/release.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/release.yml diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..d82f279 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,25 @@ +# https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes#configuration-options + +changelog: + exclude: + labels: + - ignore-for-release + categories: + - title: '🔥 Breaking Changes' + labels: + - 'breaking' + - title: 🏕 Features + labels: + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'bug' + - title: '👋 Deprecated' + labels: + - 'deprecation' + - title: 📦 Dependencies + labels: + - dependencies + - title: Other Changes + labels: + - "*" From 46eb66e4f391cab2eddaa5b4eb14be3a9cb201ea Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 13:19:34 -0700 Subject: [PATCH 039/146] ci: pre-commit autoupdate (#131) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c65c49a..079a6cc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.6.3 + rev: v0.7.0 hooks: - id: check-message - id: check-branch From e38a5658be2c3aa58f8a26ecae6de7d2c569a7e7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 11:20:57 +0800 Subject: [PATCH 040/146] ci: pre-commit autoupdate (#132) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/PyCQA/flake8: 6.1.0 → 7.0.0](https://github.com/PyCQA/flake8/compare/6.1.0...7.0.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 079a6cc..4a2244b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: - id: name-tests-test - id: requirements-txt-fixer - repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 args: [--max-line-length=100, --ignore=E501] From 2345c4a3579caa0c3c7dc2be9812715dfc882c38 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Mon, 15 Jan 2024 22:28:29 -0700 Subject: [PATCH 041/146] feat: Support release drafter (#133) --- .github/release-drafter.yml | 1 + .github/workflows/release-drafter.yml | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 .github/release-drafter.yml create mode 100644 .github/workflows/release-drafter.yml diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..0d0b1c9 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1 @@ +_extends: .github diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..d703049 --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,16 @@ +name: Release Drafter + +on: + push: + branches: + - "main" + workflow_dispatch: + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into the default branch + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.COMMIT_CHECK_TOKEN }} From fcb86f1cc2a534c057d9f3de0a9d22c28dfc201a Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Mon, 15 Jan 2024 22:48:39 -0700 Subject: [PATCH 042/146] feat: Create labeler.yml (#134) * feat: Create labeler.yml * feat: Create labeler.yml --- .github/labeler.yml | 4 ++++ .github/workflows/labeler.yml | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 .github/labeler.yml create mode 100644 .github/workflows/labeler.yml diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..ccd5268 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,4 @@ +# Add 'dependencies' label to pre-commit config files within the entire repository +dependencies: +- changed-files: + - any-glob-to-any-file: '.pre-commit*.yml' diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000..e57cd86 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,12 @@ +name: "Pull Request Labeler" +on: +- pull_request_target + +jobs: + labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v5 From 55dffadeea63204881184ae4873c48bfe57ccc7d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 12:27:47 +0800 Subject: [PATCH 043/146] ci: pre-commit autoupdate (#135) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/commit-check/commit-check: v0.7.0 → v0.7.1](https://github.com/commit-check/commit-check/compare/v0.7.0...v0.7.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4a2244b..b592bc2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.7.0 + rev: v0.7.1 hooks: - id: check-message - id: check-branch From d4d5e3b73eb6b6bf40f4f0c8f84d3a1b9fa9c322 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Mon, 29 Jan 2024 22:43:05 -0700 Subject: [PATCH 044/146] chore: update .pre-commit-config.yaml and readme (#136) * chore: update .gitpod.yml * docs: update README.rst * chore: update .pre-commit-config.yaml * chore: revert update .gitpod.yml --- .pre-commit-config.yaml | 2 ++ README.rst | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b592bc2..df596f8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,6 +4,8 @@ ci: autoupdate_commit_msg: 'ci: pre-commit autoupdate' skip: [pytest] +# prepare-commit-msg is used by hook id: check-message +default_install_hook_types: [pre-commit, prepare-commit-msg] repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 diff --git a/README.rst b/README.rst index f47acbd..f2e52d4 100644 --- a/README.rst +++ b/README.rst @@ -78,7 +78,7 @@ Running as pre-commit hook - repo: https://github.com/commit-check/commit-check rev: the tag or revision hooks: # support hooks - - id: check-message + - id: check-message # it requires hook prepare-commit-msg - id: check-branch - id: check-author-name - id: check-author-email From 3e48cb8d0ee7ddc5c7658f364341f610149ae827 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Mon, 29 Jan 2024 22:57:23 -0700 Subject: [PATCH 045/146] fix: update labeler.yml (#137) --- .github/workflows/labeler.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index e57cd86..6999350 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -10,3 +10,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/labeler@v5 + with: + sync-labels: true + configuration-path: .github/labeler.yml From b6640e55f5017eb0e939de483b230aa59debf383 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Tue, 30 Jan 2024 14:02:39 +0800 Subject: [PATCH 046/146] fix: update labeler.yml to add workflow_dispatch --- .github/workflows/labeler.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 6999350..60ec38e 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -1,6 +1,7 @@ name: "Pull Request Labeler" on: -- pull_request_target + pull_request_target: + workflow_dispatch: jobs: labeler: From d861a743f3579d6a995379d88c6658ee22924776 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Tue, 30 Jan 2024 14:09:30 +0800 Subject: [PATCH 047/146] fix: update labeler.yml regex --- .github/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index ccd5268..6f620c3 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,4 +1,4 @@ # Add 'dependencies' label to pre-commit config files within the entire repository dependencies: - changed-files: - - any-glob-to-any-file: '.pre-commit*.yml' + - any-glob-to-any-file: '.pre-commit-\w*.yaml' From 0b79a6b6ab2f815324ed310ee813cfa71b159a40 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Tue, 30 Jan 2024 14:11:45 +0800 Subject: [PATCH 048/146] fix: update labeler.yml to add actions/checkout --- .github/workflows/labeler.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 60ec38e..399105d 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -10,6 +10,7 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: + - uses: actions/checkout@v4 - uses: actions/labeler@v5 with: sync-labels: true From ed7be812593750770406c9190ce297e46b9b47ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 4 Feb 2024 22:45:23 -0500 Subject: [PATCH 049/146] chore(deps): bump release-drafter/release-drafter from 5 to 6 (#140) Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5 to 6. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v5...v6) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index d703049..1d51417 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -11,6 +11,6 @@ jobs: runs-on: ubuntu-latest steps: # Drafts your next Release notes as Pull Requests are merged into the default branch - - uses: release-drafter/release-drafter@v5 + - uses: release-drafter/release-drafter@v6 env: GITHUB_TOKEN: ${{ secrets.COMMIT_CHECK_TOKEN }} From da3e2c06b7850527692e7fb9d14104a4a6523745 Mon Sep 17 00:00:00 2001 From: Julio Faracco Date: Sun, 10 Mar 2024 04:04:14 -0300 Subject: [PATCH 050/146] feat: enhance signoff check by adding message body and a better regex (#141) * commit: Include the body when signoff is being checked The current implementation of signoff policy check is considering only the subject. This is wrong because the signoff line is added in the body of a commit message. Signed-off-by: Julio Faracco * Replace `get_commits_info` by `get_commit_info` This name of the function is actualy wrong because it fetches only one single commit. I also added a sha parameter to help in the future to fetch older commits from the tree. Then, we can analyse multiple commits as the original function name suggests. Signed-off-by: Julio Faracco * regex: Rebase the signoff regex to match the email too Before this commit, the signoff regex only looks for the exact word. This new proposal also checks if the commit has an email associated to it. Signed-off-by: Julio Faracco * tests: Update mock call of `get_commit_info` command This commit just updates the command line that is called by `get_commit_info` to reflect the latest changes. Signed-off-by: Julio Faracco * fix: update re.match to re.search to fix test failure --------- Signed-off-by: Julio Faracco Co-authored-by: shenxianpeng --- commit_check/__init__.py | 2 +- commit_check/author.py | 4 +-- commit_check/commit.py | 20 ++++++----- commit_check/util.py | 4 +-- tests/author_test.py | 76 ++++++++++++++++++++-------------------- tests/commit_test.py | 10 +++--- tests/util_test.py | 16 ++++----- 7 files changed, 68 insertions(+), 64 deletions(-) diff --git a/commit_check/__init__.py b/commit_check/__init__.py index 8d745fb..1c5982f 100644 --- a/commit_check/__init__.py +++ b/commit_check/__init__.py @@ -44,7 +44,7 @@ }, { 'check': 'commit_signoff', - 'regex': 'Signed-off-by', + 'regex': r'Signed-off-by:.*[A-Za-z0-9]\s+<[\w\.]+@([\w-]+\.)+[\w-]{2,4}>', 'error': 'Signed-off-by not found in latest commit', 'suggest': 'run command `git commit -m "conventional commit message" --signoff`', }, diff --git a/commit_check/author.py b/commit_check/author.py index 94a0b59..1ab3ba1 100644 --- a/commit_check/author.py +++ b/commit_check/author.py @@ -1,7 +1,7 @@ """Check git author name and email""" import re from commit_check import YELLOW, RESET_COLOR, PASS, FAIL -from commit_check.util import get_commits_info, print_error_message, print_suggestion +from commit_check.util import get_commit_info, print_error_message, print_suggestion def check_author(checks: list, check_type: str) -> int: @@ -16,7 +16,7 @@ def check_author(checks: list, check_type: str) -> int: format_str = "an" if check_type == 'author_email': format_str = "ae" - config_value = str(get_commits_info(format_str)) + config_value = str(get_commit_info(format_str)) result = re.match(check['regex'], config_value) if result is None: print_error_message( diff --git a/commit_check/commit.py b/commit_check/commit.py index 6fb0010..30b4dfe 100644 --- a/commit_check/commit.py +++ b/commit_check/commit.py @@ -2,7 +2,7 @@ import re from pathlib import PurePath from commit_check import YELLOW, RESET_COLOR, PASS, FAIL -from commit_check.util import cmd_output, get_commits_info, print_error_message, print_suggestion +from commit_check.util import cmd_output, get_commit_info, print_error_message, print_suggestion def get_default_commit_msg_file() -> str: @@ -17,11 +17,12 @@ def read_commit_msg(commit_msg_file) -> str: with open(commit_msg_file, 'r') as f: return f.read() except FileNotFoundError: - return str(get_commits_info("s")) + # Commit message is composed by subject and body + return str(get_commit_info("s") + "\n\n" + get_commit_info("b")) -def check_commit_msg(checks: list, commit_msg_file: str) -> int: - if not commit_msg_file: +def check_commit_msg(checks: list, commit_msg_file: str = "") -> int: + if commit_msg_file is None or commit_msg_file == "": commit_msg_file = get_default_commit_msg_file() commit_msg = read_commit_msg(commit_msg_file) @@ -47,7 +48,10 @@ def check_commit_msg(checks: list, commit_msg_file: str) -> int: return PASS -def check_commit_signoff(checks: list) -> int: +def check_commit_signoff(checks: list, commit_msg_file: str = "") -> int: + if commit_msg_file is None or commit_msg_file == "": + commit_msg_file = get_default_commit_msg_file() + for check in checks: if check['check'] == 'commit_signoff': if check['regex'] == "": @@ -56,9 +60,9 @@ def check_commit_signoff(checks: list) -> int: ) return PASS - commit_msg = get_commits_info("s") - commit_hash = get_commits_info("H") - result = re.match(check['regex'], commit_msg) + commit_msg = read_commit_msg(commit_msg_file) + commit_hash = get_commit_info("H") + result = re.search(check['regex'], commit_msg) if result is None: print_error_message( check['check'], check['regex'], diff --git a/commit_check/util.py b/commit_check/util.py index 6c9bfd7..ef8f89a 100644 --- a/commit_check/util.py +++ b/commit_check/util.py @@ -29,7 +29,7 @@ def get_branch_name() -> str: return branch_name.strip() -def get_commits_info(format_string: str) -> str: +def get_commit_info(format_string: str, sha: str = "HEAD") -> str: """Get latest commits information :param format_string: could be - s - subject @@ -43,7 +43,7 @@ def get_commits_info(format_string: str) -> str: """ try: commands = [ - 'git', 'log', '-n', '1', f"--pretty=format:%{format_string}", + 'git', 'log', '-n', '1', f"--pretty=format:%{format_string}", f"{sha}", ] output = cmd_output(commands) except CalledProcessError: diff --git a/tests/author_test.py b/tests/author_test.py index 04df99c..21f637d 100644 --- a/tests/author_test.py +++ b/tests/author_test.py @@ -7,17 +7,17 @@ class TestAuthor: class TestAuthorName: - # used by get_commits_info mock + # used by get_commit_info mock fake_author_value_an = "fake_author_name" def test_check_author(self, mocker): - # Must call get_commits_info, re.match. + # Must call get_commit_info, re.match. checks = [{ "check": "author_name", "regex": "dummy_regex" }] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", + m_get_commit_info = mocker.patch( + f"{LOCATION}.get_commit_info", return_value=self.fake_author_value_an ) m_re_match = mocker.patch( @@ -26,14 +26,14 @@ def test_check_author(self, mocker): ) retval = check_author(checks, "author_name") assert retval == PASS - assert m_get_commits_info.call_count == 1 + assert m_get_commit_info.call_count == 1 assert m_re_match.call_count == 1 def test_check_author_with_empty_checks(self, mocker): - # Must NOT call get_commits_info, re.match. with `checks` param with length 0. + # Must NOT call get_commit_info, re.match. with `checks` param with length 0. checks = [] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", + m_get_commit_info = mocker.patch( + f"{LOCATION}.get_commit_info", return_value=self.fake_author_value_an ) m_re_match = mocker.patch( @@ -42,7 +42,7 @@ def test_check_author_with_empty_checks(self, mocker): ) retval = check_author(checks, "author_name") assert retval == PASS - assert m_get_commits_info.call_count == 0 + assert m_get_commit_info.call_count == 0 assert m_re_match.call_count == 0 def test_check_author_with_different_check(self, mocker): @@ -51,8 +51,8 @@ def test_check_author_with_different_check(self, mocker): "check": "message", "regex": "dummy_regex" }] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", + m_get_commit_info = mocker.patch( + f"{LOCATION}.get_commit_info", return_value=self.fake_author_value_an ) m_re_match = mocker.patch( @@ -61,19 +61,19 @@ def test_check_author_with_different_check(self, mocker): ) retval = check_author(checks, "author_name") assert retval == PASS - assert m_get_commits_info.call_count == 0 + assert m_get_commit_info.call_count == 0 assert m_re_match.call_count == 0 def test_check_author_with_len0_regex(self, mocker, capfd): - # Must NOT call get_commits_info, re.match with `regex` with length 0. + # Must NOT call get_commit_info, re.match with `regex` with length 0. checks = [ { "check": "author_name", "regex": "" } ] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", + m_get_commit_info = mocker.patch( + f"{LOCATION}.get_commit_info", return_value=self.fake_author_value_an ) m_re_match = mocker.patch( @@ -82,7 +82,7 @@ def test_check_author_with_len0_regex(self, mocker, capfd): ) retval = check_author(checks, "author_name") assert retval == PASS - assert m_get_commits_info.call_count == 0 + assert m_get_commit_info.call_count == 0 assert m_re_match.call_count == 0 out, _ = capfd.readouterr() assert "Not found regex for author_name." in out @@ -95,8 +95,8 @@ def test_check_author_with_result_none(self, mocker): "error": "error", "suggest": "suggest" }] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", + m_get_commit_info = mocker.patch( + f"{LOCATION}.get_commit_info", return_value=self.fake_author_value_an ) m_re_match = mocker.patch( @@ -111,23 +111,23 @@ def test_check_author_with_result_none(self, mocker): ) retval = check_author(checks, "author_name") assert retval == FAIL - assert m_get_commits_info.call_count == 1 + assert m_get_commit_info.call_count == 1 assert m_re_match.call_count == 1 assert m_print_error_message.call_count == 1 assert m_print_suggestion.call_count == 1 class TestAuthorEmail: - # used by get_commits_info mock + # used by get_commit_info mock fake_author_value_ae = "fake_author_email" def test_check_author(self, mocker): - # Must call get_commits_info, re.match. + # Must call get_commit_info, re.match. checks = [{ "check": "author_email", "regex": "dummy_regex" }] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", + m_get_commit_info = mocker.patch( + f"{LOCATION}.get_commit_info", return_value=self.fake_author_value_ae ) m_re_match = mocker.patch( @@ -136,14 +136,14 @@ def test_check_author(self, mocker): ) retval = check_author(checks, "author_email") assert retval == PASS - assert m_get_commits_info.call_count == 1 + assert m_get_commit_info.call_count == 1 assert m_re_match.call_count == 1 def test_check_author_with_empty_checks(self, mocker): - # Must NOT call get_commits_info, re.match. with `checks` param with length 0. + # Must NOT call get_commit_info, re.match. with `checks` param with length 0. checks = [] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", + m_get_commit_info = mocker.patch( + f"{LOCATION}.get_commit_info", return_value=self.fake_author_value_ae ) m_re_match = mocker.patch( @@ -152,7 +152,7 @@ def test_check_author_with_empty_checks(self, mocker): ) retval = check_author(checks, "author_email") assert retval == PASS - assert m_get_commits_info.call_count == 0 + assert m_get_commit_info.call_count == 0 assert m_re_match.call_count == 0 def test_check_author_with_different_check(self, mocker): @@ -161,8 +161,8 @@ def test_check_author_with_different_check(self, mocker): "check": "message", "regex": "dummy_regex" }] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", + m_get_commit_info = mocker.patch( + f"{LOCATION}.get_commit_info", return_value=self.fake_author_value_ae ) m_re_match = mocker.patch( @@ -171,19 +171,19 @@ def test_check_author_with_different_check(self, mocker): ) retval = check_author(checks, "author_email") assert retval == PASS - assert m_get_commits_info.call_count == 0 + assert m_get_commit_info.call_count == 0 assert m_re_match.call_count == 0 def test_check_author_with_len0_regex(self, mocker, capfd): - # Must NOT call get_commits_info, re.match with `regex` with length 0. + # Must NOT call get_commit_info, re.match with `regex` with length 0. checks = [ { "check": "author_email", "regex": "" } ] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", + m_get_commit_info = mocker.patch( + f"{LOCATION}.get_commit_info", return_value=self.fake_author_value_ae ) m_re_match = mocker.patch( @@ -192,7 +192,7 @@ def test_check_author_with_len0_regex(self, mocker, capfd): ) retval = check_author(checks, "author_email") assert retval == PASS - assert m_get_commits_info.call_count == 0 + assert m_get_commit_info.call_count == 0 assert m_re_match.call_count == 0 out, _ = capfd.readouterr() assert "Not found regex for author_email." in out @@ -205,8 +205,8 @@ def test_check_author_with_result_none(self, mocker): "error": "error", "suggest": "suggest" }] - m_get_commits_info = mocker.patch( - f"{LOCATION}.get_commits_info", + m_get_commit_info = mocker.patch( + f"{LOCATION}.get_commit_info", return_value=self.fake_author_value_ae ) m_re_match = mocker.patch( @@ -221,7 +221,7 @@ def test_check_author_with_result_none(self, mocker): ) retval = check_author(checks, "author_email") assert retval == FAIL - assert m_get_commits_info.call_count == 1 + assert m_get_commit_info.call_count == 1 assert m_re_match.call_count == 1 assert m_print_error_message.call_count == 1 assert m_print_suggestion.call_count == 1 diff --git a/tests/commit_test.py b/tests/commit_test.py index 4666828..5642a52 100644 --- a/tests/commit_test.py +++ b/tests/commit_test.py @@ -1,7 +1,7 @@ from commit_check import PASS, FAIL from commit_check.commit import check_commit_msg, get_default_commit_msg_file, read_commit_msg, check_commit_signoff -# used by get_commits_info mock +# used by get_commit_info mock FAKE_BRANCH_NAME = "fake_commits_info" # The location of check_commit_msg() LOCATION = "commit_check.commit" @@ -25,7 +25,7 @@ def test_read_commit_msg_from_existing_file(tmp_path): def test_read_commit_msg_file_not_found(mocker): - m_commits_info = mocker.patch('commit_check.util.get_commits_info', return_value='mocked_commits_info') + m_commits_info = mocker.patch('commit_check.util.get_commit_info', return_value='mocked_commits_info') read_commit_msg("non_existent_file.txt") assert m_commits_info.call_count == 0 @@ -104,8 +104,8 @@ def test_check_commit_signoff(mocker): "error": "error", "suggest": "suggest" }] - m_re_match = mocker.patch( - "re.match", + m_re_search = mocker.patch( + "re.search", return_value=None ) m_print_error_message = mocker.patch( @@ -116,7 +116,7 @@ def test_check_commit_signoff(mocker): ) retval = check_commit_signoff(checks) assert retval == FAIL - assert m_re_match.call_count == 1 + assert m_re_search.call_count == 1 assert m_print_error_message.call_count == 1 assert m_print_suggestion.call_count == 1 diff --git a/tests/util_test.py b/tests/util_test.py index 1e3dd66..70ae5b7 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -1,6 +1,6 @@ import pytest from commit_check.util import get_branch_name -from commit_check.util import get_commits_info +from commit_check.util import get_commit_info from commit_check.util import cmd_output from commit_check.util import validate_config from commit_check.util import print_error_message @@ -49,20 +49,20 @@ class TestGetCommitInfo: ("ae"), ] ) - def test_get_commits_info(self, mocker, format_string): - # Must call get_commits_info with given argument. + def test_get_commit_info(self, mocker, format_string): + # Must call get_commit_info with given argument. m_cmd_output = mocker.patch( "commit_check.util.cmd_output", return_value=" fake commit message " ) - retval = get_commits_info(format_string) + retval = get_commit_info(format_string) assert m_cmd_output.call_count == 1 assert m_cmd_output.call_args[0][0] == [ - "git", "log", "-n", "1", f"--pretty=format:%{format_string}" + "git", "log", "-n", "1", f"--pretty=format:%{format_string}", "HEAD" ] assert retval == " fake commit message " - def test_get_commits_info_with_exception(self, mocker): + def test_get_commit_info_with_exception(self, mocker): # Must return empty string when exception raises in cmd_output. m_cmd_output = mocker.patch( "commit_check.util.cmd_output", @@ -75,10 +75,10 @@ def test_get_commits_info_with_exception(self, mocker): dummy_cmd_name ) format_string = "s" - retval = get_commits_info(format_string) + retval = get_commit_info(format_string) assert m_cmd_output.call_count == 1 assert m_cmd_output.call_args[0][0] == [ - "git", "log", "-n", "1", f"--pretty=format:%{format_string}" + "git", "log", "-n", "1", f"--pretty=format:%{format_string}", "HEAD" ] assert retval == "" From 8e766e502599912c19f8e04c320eb97d70502721 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Sun, 10 Mar 2024 15:30:45 +0800 Subject: [PATCH 051/146] fix: autolabeler by adding pull request events (#143) * fix: autolabeler by adding pull request events * fix: remove COMMIT_CHECK_TOKEN secrets * fix: use GITHUB_TOKEN instead --- .github/release.yml | 25 ------------------------- .github/workflows/release-drafter.yml | 7 ++++++- 2 files changed, 6 insertions(+), 26 deletions(-) delete mode 100644 .github/release.yml diff --git a/.github/release.yml b/.github/release.yml deleted file mode 100644 index d82f279..0000000 --- a/.github/release.yml +++ /dev/null @@ -1,25 +0,0 @@ -# https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes#configuration-options - -changelog: - exclude: - labels: - - ignore-for-release - categories: - - title: '🔥 Breaking Changes' - labels: - - 'breaking' - - title: 🏕 Features - labels: - - 'enhancement' - - title: '🐛 Bug Fixes' - labels: - - 'bug' - - title: '👋 Deprecated' - labels: - - 'deprecation' - - title: 📦 Dependencies - labels: - - dependencies - - title: Other Changes - labels: - - "*" diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 1d51417..7c8d6e7 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -1,9 +1,14 @@ +# https://github.com/release-drafter/release-drafter name: Release Drafter on: push: branches: - "main" + pull_request: + types: [opened, reopened, synchronize] + pull_request_target: + types: [opened, reopened, synchronize] workflow_dispatch: jobs: @@ -13,4 +18,4 @@ jobs: # Drafts your next Release notes as Pull Requests are merged into the default branch - uses: release-drafter/release-drafter@v6 env: - GITHUB_TOKEN: ${{ secrets.COMMIT_CHECK_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 67aa80ce83d2216914ce78709c47b751d05c3fa8 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Sun, 10 Mar 2024 15:39:06 +0800 Subject: [PATCH 052/146] refactor: remove pytest from pre-commit (#144) --- .github/workflows/main.yml | 2 +- .pre-commit-config.yaml | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 33c6308..4efa956 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -61,7 +61,7 @@ jobs: fail-fast: false matrix: py: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] - os: ['windows-latest', ubuntu-latest] + os: ['windows-latest', 'ubuntu-latest', 'macos-latest'] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index df596f8..5f7fe35 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,11 +39,3 @@ repos: - id: check-branch # - id: check-author-email # uncomment if you need. # - id: commit-signoff # uncomment if you need. -- repo: local - hooks: - - id: pytest - name: pytest - entry: pytest - language: system - pass_filenames: false - always_run: true From 33d922ecb9e10451d5d9b7b0929bb44a14eb9977 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Mon, 11 Mar 2024 15:57:03 +0800 Subject: [PATCH 053/146] docs: update README.rst and add CONTRIBUTING.md (#145) * docs: add CONTRIBUTING.md * docs: update README.rst * fix: remove ci skip pytest from pre-commit config * chore: update .pre-commit-config.yaml --- .pre-commit-config.yaml | 8 +++---- CONTRIBUTING.md | 17 +++++++++++++++ README.rst | 46 +++++++++++++++++++---------------------- 3 files changed, 42 insertions(+), 29 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5f7fe35..ed342a5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,6 @@ ci: autofix_commit_msg: 'ci: auto fixes from pre-commit.com hooks' autoupdate_commit_msg: 'ci: pre-commit autoupdate' - skip: [pytest] # prepare-commit-msg is used by hook id: check-message default_install_hook_types: [pre-commit, prepare-commit-msg] @@ -36,6 +35,7 @@ repos: rev: v0.7.1 hooks: - id: check-message - - id: check-branch - # - id: check-author-email # uncomment if you need. - # - id: commit-signoff # uncomment if you need. + # - id: check-branch # uncomment if you need. + # - id: check-author-name # uncomment if you need. + # - id: check-author-email # uncomment if you need. + # - id: commit-signoff # uncomment if you need. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..92cd278 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,17 @@ +# Contributing + +Thank you for investing your time in contributing to our project! We welcome feedback, bug reports, and pull requests! + +## New contributor guide + +Our development branch is `main`. When submitting pull requests, please adhere to the following guidelines: + +* Add tests for any new features and bug fixes. +* Put a reasonable amount of comments into the code. +* Fork [commit-check](https://github.com/commit-check/commit-check) on your GitHub user account. +* Create branch from `main`, make your changes on the new branch and then create a PR against `main` branch of commit-check repository. +* Separate unrelated changes into multiple pull requests for better review and management. + +By contributing any code or documentation to this repository (by raising pull requests or otherwise), you explicitly agree to the [License Agreement](https://github.com/commit-check/commit-check/blob/main/LICENSE). + +We appreciate your contributions to make Commit Check even better! diff --git a/README.rst b/README.rst index f2e52d4..4ec86be 100644 --- a/README.rst +++ b/README.rst @@ -28,39 +28,37 @@ Commit Check Overview -------- -Commit Check is open source alternative to Yet Another Commit Checker. +Commit Check supports checking commit messages, branch naming, committer name/email, commit signoff, customizing error messages, suggested commands and more. -It supports checking commit message, branch naming, committer name/email, commit signoff and customizing error message and suggest command (tell me more, please). - -commit-check is a tool designed for teams. Its main purpose is to standardize the format of commit message, branch naming, etc, and makes it possible to: +It is a powerful, free solution for individuals and teams aiming to standardize commit message formatting and branch naming, including - writing descriptive commit is easy to read - identify branch according to the branch type - triggering the specific types of commit/branch CI build - automatically generate changelogs +If you're using Bitbucket, it's an open source alternative to Yet Another Commit Checker. + Configuration ------------- -Use custom configuration +Use Custom Configuration ~~~~~~~~~~~~~~~~~~~~~~~~ -Create a config file ``.commit-check.yml`` under your repository root directory, e.g. `.commit-check.yml `_ +Create a config file ``.commit-check.yml`` under your repository's root directory, e.g., `.commit-check.yml `_ -Use default configuration +Use Default Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~ -- If you did't set ``.commit-check.yml``, ``commit-check`` will use the `default configuration `_. +- If you don't set ``.commit-check.yml``, Commit Check will use the `default configuration `_. -- i.e. the commit message will follow the rules of `conventional commits `_, - branch naming follow bitbucket `branching model `_. +- The commit message will follow the rules of `conventional commits `_, + branch naming follow Bitbucket's `branching model `_. Usage ----- -There are a variety of ways you can use commit-check as follows. - Running as GitHub Action ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -87,50 +85,48 @@ Running as pre-commit hook Running as CLI ~~~~~~~~~~~~~~ -Global installation +Global Installation .. code-block:: bash sudo pip3 install -U commit-check -User installation +User Installation .. code-block:: bash pip install -U commit-check -Install from git repo +Install from Git Repo .. code-block:: bash pip install git+https://github.com/commit-check/commit-check.git@main -Then you can run ``commit-check`` command line. More about ``commit-check --help`` please see `docs `_. +Then, run ``commit-check`` from the command line. For more information, see the `docs `_. Running as Git Hooks ~~~~~~~~~~~~~~~~~~~~ -To configure the hook, you need to create a new script file in the ``.git/hooks/`` directory of your Git repository. - -Here is an example script that you can use to set up the hook: +To configure the hook, create a script file in the ``.git/hooks/`` directory. .. code-block:: bash #!/bin/sh commit-check --message --branch --author-name --author-email -Save the script file to ``pre-push`` and make it executable by running the following command: +Save the script file as ``pre-push`` and make it executable: .. code-block:: bash chmod +x .git/hooks/pre-push -Then when you run ``git push`` command, this push hook will be run automatically. +Now, ``git push`` will trigger this hook automatically. Example ------- -Check commit message failed +Check Commit Message Failed .. code-block:: text @@ -158,7 +154,7 @@ Check commit message failed Suggest: please check your commit message whether matches above regex -Check branch naming failed +Check Branch Naming Failed .. code-block:: text @@ -185,7 +181,7 @@ Check branch naming failed Badging your repository ----------------------- -You can add a badge to your repository to show your contributors / users that you use commit-check! +You can add a badge to your repository to show that you use commit-check! .. image:: https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white :target: https://github.com/commit-check/commit-check @@ -214,7 +210,7 @@ Versioning follows `Semantic Versioning `_. Have question or feedback? -------------------------- -To provide feedback (requesting a feature or reporting a bug) please post to `issues `_. +Please post to `issues `_ for feedback, feature requests, or bug reports. License ------- From 7cf502e42b24a2df4eb63095a80bbbcecb57a6d7 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Mon, 11 Mar 2024 16:39:34 +0800 Subject: [PATCH 054/146] docs: add link to Yet Another Commit Checker --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 4ec86be..ace21ae 100644 --- a/README.rst +++ b/README.rst @@ -37,7 +37,7 @@ It is a powerful, free solution for individuals and teams aiming to standardize - triggering the specific types of commit/branch CI build - automatically generate changelogs -If you're using Bitbucket, it's an open source alternative to Yet Another Commit Checker. +If you're using Bitbucket, it's an open source alternative to `Yet Another Commit Checker `_. Configuration ------------- From 605d1edf29b9e36538b24eef3c2bad5c172732b4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 09:55:43 +0800 Subject: [PATCH 055/146] ci: pre-commit autoupdate (#146) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.8.0 → v1.9.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.8.0...v1.9.0) - [github.com/commit-check/commit-check: v0.7.1 → v0.7.3](https://github.com/commit-check/commit-check/compare/v0.7.1...v0.7.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ed342a5..ffa800e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.8.0 + rev: v1.9.0 hooks: - id: mypy additional_dependencies: [types-all] @@ -32,7 +32,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.7.1 + rev: v0.7.3 hooks: - id: check-message # - id: check-branch # uncomment if you need. From 33c6d74c45c0dcf8328e384bbeec5c07224d528a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 12:00:08 +0800 Subject: [PATCH 056/146] chore(deps): bump slsa-framework/slsa-github-generator (#147) Bumps [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator) from 1.9.0 to 1.10.0. - [Release notes](https://github.com/slsa-framework/slsa-github-generator/releases) - [Changelog](https://github.com/slsa-framework/slsa-github-generator/blob/main/CHANGELOG.md) - [Commits](https://github.com/slsa-framework/slsa-github-generator/compare/v1.9.0...v1.10.0) --- updated-dependencies: - dependency-name: slsa-framework/slsa-github-generator dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index 592020b..2fec59e 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -59,7 +59,7 @@ jobs: id-token: write # To sign the provenance. contents: write # To add assets to a release. # Can't pin with hash due to how this workflow works. - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0 + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.10.0 with: base64-subjects: ${{ needs.publish.outputs.hashes }} upload-assets: true # Optional: Upload to a new release From 9d26895cf1260a094f3f4b4819a4ff5c0e0d04a1 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Wed, 3 Apr 2024 15:43:16 +0800 Subject: [PATCH 057/146] fix: update labeler.yml (#148) * Update labeler.yml * fix: update labeler.yml --- .github/labeler.yml | 6 ++++-- .github/workflows/labeler.yml | 7 +------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 6f620c3..32c3403 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,4 +1,6 @@ -# Add 'dependencies' label to pre-commit config files within the entire repository +# Add 'dependencies' label for any changes by pre-commit ci. dependencies: - changed-files: - - any-glob-to-any-file: '.pre-commit-\w*.yaml' + - any-glob-to-any-file: .pre-commit-config.yaml + - base-branch: ['main'] + - head-branch: ['pre-commit-ci-update-config'] diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 399105d..e57cd86 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -1,7 +1,6 @@ name: "Pull Request Labeler" on: - pull_request_target: - workflow_dispatch: +- pull_request_target jobs: labeler: @@ -10,8 +9,4 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - uses: actions/labeler@v5 - with: - sync-labels: true - configuration-path: .github/labeler.yml From 1c852bb9a2c0b535729a5a27ae57d8feeeb0f1b5 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Sun, 7 Apr 2024 14:40:13 +0800 Subject: [PATCH 058/146] docs: uses RST substitution to put badges in 1 line (#149) * uses RST substitution to put badges in 1 line * fix: update labeler.yml * chore: delete .github/workflows/labeler.yml * chore: delete .github/labeler.yml --- .github/labeler.yml | 6 ------ .github/workflows/labeler.yml | 12 ------------ README.rst | 14 ++++++++------ 3 files changed, 8 insertions(+), 24 deletions(-) delete mode 100644 .github/labeler.yml delete mode 100644 .github/workflows/labeler.yml diff --git a/.github/labeler.yml b/.github/labeler.yml deleted file mode 100644 index 32c3403..0000000 --- a/.github/labeler.yml +++ /dev/null @@ -1,6 +0,0 @@ -# Add 'dependencies' label for any changes by pre-commit ci. -dependencies: -- changed-files: - - any-glob-to-any-file: .pre-commit-config.yaml - - base-branch: ['main'] - - head-branch: ['pre-commit-ci-update-config'] diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml deleted file mode 100644 index e57cd86..0000000 --- a/.github/workflows/labeler.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: "Pull Request Labeler" -on: -- pull_request_target - -jobs: - labeler: - permissions: - contents: read - pull-requests: write - runs-on: ubuntu-latest - steps: - - uses: actions/labeler@v5 diff --git a/README.rst b/README.rst index ace21ae..9e4a95e 100644 --- a/README.rst +++ b/README.rst @@ -1,30 +1,32 @@ Commit Check ============ -.. image:: https://img.shields.io/pypi/v/commit-check?logo=python&logoColor=white +.. |pypi-version| image:: https://img.shields.io/pypi/v/commit-check?logo=python&logoColor=white :target: https://pypi.org/project/commit-check/ :alt: PyPI -.. image:: https://github.com/commit-check/commit-check/actions/workflows/main.yml/badge.svg +.. |ci-badge| image:: https://github.com/commit-check/commit-check/actions/workflows/main.yml/badge.svg :target: https://github.com/commit-check/commit-check/actions/workflows/main.yml :alt: CI -.. image:: https://sonarcloud.io/api/project_badges/measure?project=commit-check_commit-check&metric=alert_status +.. |sonar-badge| image:: https://sonarcloud.io/api/project_badges/measure?project=commit-check_commit-check&metric=alert_status :target: https://sonarcloud.io/summary/new_code?id=commit-check_commit-check :alt: Quality Gate Status -.. image:: https://codecov.io/gh/commit-check/commit-check/branch/main/graph/badge.svg?token=GC2U5V5ZRT +.. |codecov-badge| image:: https://codecov.io/gh/commit-check/commit-check/branch/main/graph/badge.svg?token=GC2U5V5ZRT :target: https://codecov.io/gh/commit-check/commit-check :alt: CodeCov -.. image:: https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white +.. |commit-check-badge| image:: https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white :target: https://github.com/commit-check/commit-check :alt: commit-check -.. image:: https://slsa.dev/images/gh-badge-level3.svg +.. |slsa-badge| image:: https://slsa.dev/images/gh-badge-level3.svg :target: https://slsa.dev :alt: SLSA +|pypi-version| |ci-badge| |sonar-badge| |codecov-badge| |commit-check-badge| |slsa-badge| + Overview -------- From 2cb70f00a661955f498146f9766495cbb727cd46 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:04:33 +0800 Subject: [PATCH 059/146] chore(deps): bump peaceiris/actions-gh-pages from 3 to 4 (#151) --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4efa956..d7a2605 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -102,7 +102,7 @@ jobs: - name: Upload docs to github pages # only publish doc changes from main branch if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs/_build/html From f5eee40a591e0c13b12f7761f4c088611a4a83a4 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Wed, 17 Apr 2024 09:28:57 -0400 Subject: [PATCH 060/146] feat: call reusable workflows from .github repo (#152) --- .github/workflows/release-drafter.yml | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 7c8d6e7..d25c13e 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -1,21 +1,11 @@ -# https://github.com/release-drafter/release-drafter name: Release Drafter on: push: branches: - "main" - pull_request: - types: [opened, reopened, synchronize] - pull_request_target: - types: [opened, reopened, synchronize] workflow_dispatch: jobs: - update_release_draft: - runs-on: ubuntu-latest - steps: - # Drafts your next Release notes as Pull Requests are merged into the default branch - - uses: release-drafter/release-drafter@v6 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + draft-release: + uses: commit-check/.github/.github/workflows/release-drafter.yml@main From c84a9df6f31c949580d1aab4d59e5a698bd0c200 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:30:37 +0800 Subject: [PATCH 061/146] ci: pre-commit autoupdate (#150) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.5.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.5.0...v4.6.0) - [github.com/commit-check/commit-check: v0.7.3 → v0.7.4](https://github.com/commit-check/commit-check/compare/v0.7.3...v0.7.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ffa800e..fd0bc19 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ ci: default_install_hook_types: [pre-commit, prepare-commit-msg] repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-yaml - id: check-toml @@ -32,7 +32,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.7.3 + rev: v0.7.4 hooks: - id: check-message # - id: check-branch # uncomment if you need. From da48649b485f1cc35b27d6eea8e6f076d78a9267 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Wed, 17 Apr 2024 23:03:20 -0400 Subject: [PATCH 062/146] feat: add issue templates (#154) --- .../{bug.yml => bug-report.yml} | 1 + .github/ISSUE_TEMPLATE/config.yml | 8 ++++ .github/ISSUE_TEMPLATE/feature-request.yml | 38 +++++++++++++++++++ 3 files changed, 47 insertions(+) rename .github/ISSUE_TEMPLATE/{bug.yml => bug-report.yml} (97%) create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature-request.yml diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug-report.yml similarity index 97% rename from .github/ISSUE_TEMPLATE/bug.yml rename to .github/ISSUE_TEMPLATE/bug-report.yml index a9e720b..9c89022 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,5 +1,6 @@ name: Bug report description: something went wrong +labels: ["bug"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..375a8f2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +# Documentation for this file can be found at: +# https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository + +blank_issues_enabled: false +contact_links: + - name: "(maintainers only) Blank issue" + url: https://github.com/commit-check/commit-check/issues/new/ + about: For maintainers only. diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 0000000..6f24ab5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,38 @@ +name: Feature request +description: Suggest an idea for this project +labels: ["enhancement"] + +body: + - type: markdown + attributes: + value: >- + Hi there! + + We'd appreciate it if you could search on commit-check's existing issues prior to filing + a feature request. + + - type: textarea + attributes: + label: What's the problem this feature will solve? + description: >- + What are you trying to do, that you are unable to achieve with commit-check as it currently stands? + validations: + required: true + + - type: textarea + attributes: + label: Describe the solution you'd like + description: >- + Clear and concise description of what you want to happen. Please use examples + of real world use cases that this would help with, and how it solves the + problem described above. + validations: + required: true + + - type: textarea + attributes: + label: Additional context + description: >- + Add any other context, links, etc. relevant to the feature request. + validations: + required: true From 7fafe303a627c7cb0e0b66e0d7632776a61e1f19 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Thu, 18 Apr 2024 11:15:14 +0800 Subject: [PATCH 063/146] docs: update CONTRIBUTING.md --- CONTRIBUTING.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 92cd278..b2b7160 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,9 +9,36 @@ Our development branch is `main`. When submitting pull requests, please adhere t * Add tests for any new features and bug fixes. * Put a reasonable amount of comments into the code. * Fork [commit-check](https://github.com/commit-check/commit-check) on your GitHub user account. -* Create branch from `main`, make your changes on the new branch and then create a PR against `main` branch of commit-check repository. +* Create a branch from `main`, make your changes on the new branch, and then create a PR against the `main` branch of the commit-check repository. * Separate unrelated changes into multiple pull requests for better review and management. By contributing any code or documentation to this repository (by raising pull requests or otherwise), you explicitly agree to the [License Agreement](https://github.com/commit-check/commit-check/blob/main/LICENSE). We appreciate your contributions to make Commit Check even better! + +## Development + +### Debug commit-check pre-commit hook + +```bash +pre-commit try-repo ./../commit-check/ check-message --verbose --hook-stage prepare-commit-msg --commit-msg-filename .git/COMMIT_EDITMSG +``` + +### Debug commit-check wheel package + +```bash +python3 -m pip install --upgrade pip +pip install -e ./../commit-check/ +commit-check -m +``` + +### Test commit-check pre-commit hook on GitHub + +```yaml +- repo: https://github.com/commit-check/commit-check + rev: the tag or revision # update it to test commit hash + hooks: + - id: check-message + - id: check-branch + - id: check-author-email +``` From e2ce0014f53819f20a94f5ce048f29b1b5272282 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 18:51:54 -0400 Subject: [PATCH 064/146] ci: pre-commit autoupdate (#156) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fd0bc19..f967143 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.9.0 + rev: v1.10.0 hooks: - id: mypy additional_dependencies: [types-all] From 11de1099bcd8b251706cc334082dab7ec21fbb7b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 08:23:05 +0800 Subject: [PATCH 065/146] ci: pre-commit autoupdate (#157) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f967143..467425b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,7 +28,7 @@ repos: additional_dependencies: [types-all] exclude: ^testing/resources/ - repo: https://github.com/codespell-project/codespell - rev: v2.2.6 + rev: v2.3.0 hooks: - id: codespell - repo: https://github.com/commit-check/commit-check From f2ddd8ac55a7f8f861990b9cfb2b482319309ccc Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Fri, 7 Jun 2024 01:00:04 +0800 Subject: [PATCH 066/146] Create attestations for final package (#158) --- .github/workflows/publish-package.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index 2fec59e..63d49bc 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -30,6 +30,11 @@ jobs: # Check distribution twine check dist/commit_check* + - name: Create attestations + - uses: actions/attest-build-provenance@v1 + with: + subject-path: "dist/commit_check*" + - name: Generate subject id: hash run: | From b84a336f91135800e1392d8f96f3bca4dd6dc89a Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Fri, 7 Jun 2024 01:14:34 +0800 Subject: [PATCH 067/146] Drop python 3.7 and support 3.13.0-beta.1 in main CI (#159) * Drop python 3.7 and add 3.13 in main CI * Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d7a2605..8199536 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -60,7 +60,7 @@ jobs: strategy: fail-fast: false matrix: - py: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] + py: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13.0-beta.1'] os: ['windows-latest', 'ubuntu-latest', 'macos-latest'] runs-on: ${{ matrix.os }} steps: From 625d37dcdc214eb1c9bc917484d387b2480fb70a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jun 2024 01:19:16 +0800 Subject: [PATCH 068/146] chore(deps): bump slsa-framework/slsa-github-generator (#155) Bumps [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator) from 1.10.0 to 2.0.0. - [Release notes](https://github.com/slsa-framework/slsa-github-generator/releases) - [Changelog](https://github.com/slsa-framework/slsa-github-generator/blob/main/CHANGELOG.md) - [Commits](https://github.com/slsa-framework/slsa-github-generator/compare/v1.10.0...v2.0.0) --- updated-dependencies: - dependency-name: slsa-framework/slsa-github-generator dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Peter Shen --- .github/workflows/publish-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index 63d49bc..9c18002 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -64,7 +64,7 @@ jobs: id-token: write # To sign the provenance. contents: write # To add assets to a release. # Can't pin with hash due to how this workflow works. - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.10.0 + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0 with: base64-subjects: ${{ needs.publish.outputs.hashes }} upload-assets: true # Optional: Upload to a new release From 0ea2c9e2276a131b07d9c1923036bd794153c230 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Fri, 7 Jun 2024 01:21:54 +0800 Subject: [PATCH 069/146] Update publish-package.yml --- .github/workflows/publish-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index 9c18002..fa576c4 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -31,7 +31,7 @@ jobs: twine check dist/commit_check* - name: Create attestations - - uses: actions/attest-build-provenance@v1 + uses: actions/attest-build-provenance@v1 with: subject-path: "dist/commit_check*" From 8c137f6248eb0a342ec2bbeb0f4716f5680654f6 Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Fri, 7 Jun 2024 01:24:24 +0800 Subject: [PATCH 070/146] Update publish-package.yml --- .github/workflows/publish-package.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index fa576c4..f104e16 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -6,6 +6,10 @@ on: types: [published] workflow_dispatch: +permissions: + id-token: write + attestations: write + jobs: publish: runs-on: ubuntu-latest From 6225238f60e8c820f6669226deb9e8f052be8c20 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:34:57 +0800 Subject: [PATCH 071/146] ci: pre-commit autoupdate (#161) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/commit-check/commit-check: v0.7.4 → v0.8.0](https://github.com/commit-check/commit-check/compare/v0.7.4...v0.8.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 467425b..355cd76 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,7 +32,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.7.4 + rev: v0.8.0 hooks: - id: check-message # - id: check-branch # uncomment if you need. From 581a558b0aa16fd0736157ad5043644c408933cd Mon Sep 17 00:00:00 2001 From: Peter Shen Date: Tue, 11 Jun 2024 12:19:33 +0800 Subject: [PATCH 072/146] chore: remvoe slsa-github-generator (#160) removed slsa-framework/slsa-github-generator --- .github/workflows/publish-package.yml | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index f104e16..77c5179 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -13,8 +13,6 @@ permissions: jobs: publish: runs-on: ubuntu-latest - outputs: - hashes: ${{ steps.hash.outputs.hashes }} steps: - uses: actions/checkout@v4 # use fetch --all for setuptools_scm to work @@ -39,13 +37,6 @@ jobs: with: subject-path: "dist/commit_check*" - - name: Generate subject - id: hash - run: | - cd dist - HASHES=$(sha256sum commit_check* | base64 -w0) - echo "hashes=$HASHES" >> "$GITHUB_OUTPUT" - - name: Publish package to TestPyPI if: github.event_name == 'workflow_dispatch' && github.repository == 'commit-check/commit-check' env: @@ -60,16 +51,3 @@ jobs: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} run: twine upload dist/commit_check* - - provenance: - needs: ['publish'] - permissions: - actions: read # To read the workflow path. - id-token: write # To sign the provenance. - contents: write # To add assets to a release. - # Can't pin with hash due to how this workflow works. - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0 - with: - base64-subjects: ${{ needs.publish.outputs.hashes }} - upload-assets: true # Optional: Upload to a new release - continue-on-error: true From bc4f434d75f3afba25e42bafc3aa8c5fbd701fc1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 08:16:53 +0800 Subject: [PATCH 073/146] ci: pre-commit autoupdate (#162) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 355cd76..f56ffd2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: name-tests-test - id: requirements-txt-fixer - repo: https://github.com/PyCQA/flake8 - rev: 7.0.0 + rev: 7.1.0 hooks: - id: flake8 args: [--max-line-length=100, --ignore=E501] From 73e0b1955f43b85409217471f0313a92fbb4761c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 22:58:40 +0800 Subject: [PATCH 074/146] ci: pre-commit autoupdate (#163) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f56ffd2..50ed46a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.10.0 + rev: v1.10.1 hooks: - id: mypy additional_dependencies: [types-all] From 368b34ee849d47c0202532c2b1bedfe19f98bc80 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 15:46:11 +0300 Subject: [PATCH 075/146] ci: pre-commit autoupdate (#164) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.10.1 → v1.11.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.10.1...v1.11.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 50ed46a..2141aae 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.10.1 + rev: v1.11.0 hooks: - id: mypy additional_dependencies: [types-all] From 0d18eaf43da5b188eb4b61c6d4e9574c743b9b92 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 06:11:24 +0300 Subject: [PATCH 076/146] ci: pre-commit autoupdate (#165) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2141aae..17bb1aa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,13 +16,13 @@ repos: - id: name-tests-test - id: requirements-txt-fixer - repo: https://github.com/PyCQA/flake8 - rev: 7.1.0 + rev: 7.1.1 hooks: - id: flake8 args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.0 + rev: v1.11.1 hooks: - id: mypy additional_dependencies: [types-all] From 100eda88fa078c9966bbe2f91abda9b173afbfa3 Mon Sep 17 00:00:00 2001 From: Xianpeng Shen Date: Tue, 6 Aug 2024 14:25:53 +0300 Subject: [PATCH 077/146] fix: change mypy additional dependencies (#166) --- .github/workflows/main.yml | 1 + .pre-commit-config.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8199536..898121e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,6 +9,7 @@ on: - "**.py" - pyproject.toml - ".github/workflows/main.yml" + - ".pre-commit-config.yaml" - "!docs/**" workflow_dispatch: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 17bb1aa..316589e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: rev: v1.11.1 hooks: - id: mypy - additional_dependencies: [types-all] + additional_dependencies: [types-PyYAML] exclude: ^testing/resources/ - repo: https://github.com/codespell-project/codespell rev: v2.3.0 From ff2b870950aa0aa91430fcc4d0b939ad3902cb98 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 20:59:53 +0300 Subject: [PATCH 078/146] ci: pre-commit autoupdate (#167) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 316589e..f6a58ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,7 +32,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.8.0 + rev: v0.8.1 hooks: - id: check-message # - id: check-branch # uncomment if you need. From c63f047ee72a51c5a225254abe1b2885805e633e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2024 10:43:01 +0300 Subject: [PATCH 079/146] ci: pre-commit autoupdate (#168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.11.1 → v1.11.2](https://github.com/pre-commit/mirrors-mypy/compare/v1.11.1...v1.11.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f6a58ea..263c2dd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.1 + rev: v1.11.2 hooks: - id: mypy additional_dependencies: [types-PyYAML] From a2eafd45e11012d92eea7abbd93bc1aadfe79dff Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Wed, 11 Sep 2024 10:45:29 +0300 Subject: [PATCH 080/146] docs: update README.rst (#169) * docs: update README.rst * docs: update README.rst --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 9e4a95e..8e991a4 100644 --- a/README.rst +++ b/README.rst @@ -54,8 +54,8 @@ Use Default Configuration - If you don't set ``.commit-check.yml``, Commit Check will use the `default configuration `_. -- The commit message will follow the rules of `conventional commits `_, - branch naming follow Bitbucket's `branching model `_. +- The commit message will follow the rules of `Conventional Commits `_, + branch naming follow the rules of `Conventional Branch `_. Usage From 8f9dce006eeeb6ed296cd2d426b33bddfd0a39f0 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Thu, 12 Sep 2024 16:28:59 +0300 Subject: [PATCH 081/146] docs: update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 8e991a4..5319761 100644 --- a/README.rst +++ b/README.rst @@ -55,7 +55,7 @@ Use Default Configuration - If you don't set ``.commit-check.yml``, Commit Check will use the `default configuration `_. - The commit message will follow the rules of `Conventional Commits `_, - branch naming follow the rules of `Conventional Branch `_. + branch naming follow the rules of `Conventional Branch `_. Usage From 37114f997c469802b191f0a69ddda7a6262a9131 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Fri, 13 Sep 2024 13:32:01 +0300 Subject: [PATCH 082/146] docs: update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 5319761..fc20867 100644 --- a/README.rst +++ b/README.rst @@ -55,7 +55,7 @@ Use Default Configuration - If you don't set ``.commit-check.yml``, Commit Check will use the `default configuration `_. - The commit message will follow the rules of `Conventional Commits `_, - branch naming follow the rules of `Conventional Branch `_. + branch naming follow the rules of `Conventional Branch `_. Usage From 51af224f8784ba94f09cb5820612fa9c331e731b Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 24 Sep 2024 15:11:51 +0300 Subject: [PATCH 083/146] docs: Update README.rst (#171) closes #170 --- README.rst | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/README.rst b/README.rst index fc20867..e60af4e 100644 --- a/README.rst +++ b/README.rst @@ -30,25 +30,13 @@ Commit Check Overview -------- -Commit Check supports checking commit messages, branch naming, committer name/email, commit signoff, customizing error messages, suggested commands and more. +**Commit Check** is a free, powerful tool that enforces commit metadata standards, including commit message, branch naming, committer name/email, and commit signoff. Fully customizable with error messages and suggested commands, it ensures compliance across teams. -It is a powerful, free solution for individuals and teams aiming to standardize commit message formatting and branch naming, including - -- writing descriptive commit is easy to read -- identify branch according to the branch type -- triggering the specific types of commit/branch CI build -- automatically generate changelogs - -If you're using Bitbucket, it's an open source alternative to `Yet Another Commit Checker `_. +As an alternative to GitHub Enerprise `Metadata restrictions `_ and Bitbucket's paid puglin `Yet Another Commit Checker `_, Commit Check stands out by integrating DevOps principles and Infrastructure as Code (IaC). Configuration ------------- -Use Custom Configuration -~~~~~~~~~~~~~~~~~~~~~~~~ - -Create a config file ``.commit-check.yml`` under your repository's root directory, e.g., `.commit-check.yml `_ - Use Default Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -57,6 +45,10 @@ Use Default Configuration - The commit message will follow the rules of `Conventional Commits `_, branch naming follow the rules of `Conventional Branch `_. +Use Custom Configuration +~~~~~~~~~~~~~~~~~~~~~~~~ + +Create a config file ``.commit-check.yml`` under your repository's root directory, e.g., `.commit-check.yml `_ Usage ----- From 8125fd61f838a1e0f3407bcda28ae3a02583b874 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 24 Sep 2024 15:43:50 +0300 Subject: [PATCH 084/146] chore: Update pyproject.toml (#172) --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 361ccf0..ffeff98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,15 +6,15 @@ build-backend = "setuptools.build_meta" name = "commit-check" description = "Check commit message formatting, branch naming, commit author, email, and more." readme = "README.rst" -keywords = ["commit conventions", "conventional commits", "branch naming", "commit-check", "message", "lint message"] +keywords = ["commit conventions", "conventional commits", "conventional branch", "branch naming", "commit-check", "message", "lint message", "devops"] license = {text = "MIT License"} authors = [ - { name = "Peter Shen", email = "xianpeng.shen@gmail.com" }, + { name = "Xianpeng Shen", email = "xianpeng.shen@gmail.com" }, ] dependencies = ["pyyaml"] classifiers = [ # https://pypi.org/pypi?%3Aaction=list_classifiers - "Development Status :: 4 - Beta", + "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: MIT License", "Intended Audience :: Developers", "Natural Language :: English", From ca6f7229fbf09f0ee7e86af48d5a13ba433a72c4 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 24 Sep 2024 15:52:27 +0300 Subject: [PATCH 085/146] fix: update conf.py to fix copyright (#173) --- docs/conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 125dc6e..53d5b56 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -4,6 +4,7 @@ # For the full list of built-in configuration values, see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html import re +import datetime from pathlib import Path import io from sphinx.application import Sphinx @@ -12,7 +13,7 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information project = "commit-check" -copyright = "2023, shenxianpeng" +copyright = f"{datetime.date.today().year}, shenxianpeng" author = "shenxianpeng" # -- General configuration --------------------------------------------------- From 8b075209f5f945e3c4ccf82524da6d4f9239b698 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 30 Sep 2024 13:26:09 +0300 Subject: [PATCH 086/146] chore: update feature-request.yml (#175) --- .github/ISSUE_TEMPLATE/feature-request.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index 6f24ab5..ee8099e 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -8,7 +8,7 @@ body: value: >- Hi there! - We'd appreciate it if you could search on commit-check's existing issues prior to filing + We'd appreciate it if you could search on commit-check's existing issues before filing a feature request. - type: textarea @@ -23,9 +23,9 @@ body: attributes: label: Describe the solution you'd like description: >- - Clear and concise description of what you want to happen. Please use examples - of real world use cases that this would help with, and how it solves the - problem described above. + A clear and concise description of what you want to happen. Please use examples + of real-world use cases that this would help with, and how it solves the + the problem described above. validations: required: true @@ -35,4 +35,4 @@ body: description: >- Add any other context, links, etc. relevant to the feature request. validations: - required: true + required: false From 4c6da5c44dcde6f2b8d012d217852fe35c603bdf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 21:41:31 +0300 Subject: [PATCH 087/146] ci: pre-commit autoupdate (#176) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 263c2dd..d50df5f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,7 +32,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.8.1 + rev: v0.8.2 hooks: - id: check-message # - id: check-branch # uncomment if you need. From c4fa31c92ca6993ee3d19fbffcae59dbe74745a5 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Fri, 4 Oct 2024 21:05:02 +0300 Subject: [PATCH 088/146] feat: support new branch type chore/ (#178) --- .commit-check.yml | 4 ++-- README.rst | 4 ++-- commit_check/__init__.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.commit-check.yml b/.commit-check.yml index 5f48f93..bde24ab 100644 --- a/.commit-check.yml +++ b/.commit-check.yml @@ -9,8 +9,8 @@ checks: suggest: please check your commit message whether matches above regex - check: branch - regex: ^(bugfix|feature|release|hotfix|task)\/.+|(master)|(main)|(HEAD)|(PR-.+) - error: "Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/" + regex: ^(bugfix|feature|release|hotfix|task|chore)\/.+|(master)|(main)|(HEAD)|(PR-.+) + error: "Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/ chore/" suggest: run command `git checkout -b type/branch_name` - check: author_name diff --git a/README.rst b/README.rst index e60af4e..ff9c7e6 100644 --- a/README.rst +++ b/README.rst @@ -166,9 +166,9 @@ Check Branch Naming Failed Commit rejected. Type branch check failed => my-test-branch - It doesn't match regex: ^(bugfix|feature|release|hotfix|task)\/.+|(master)|(main)|(HEAD)|(PR-.+) + It doesn't match regex: ^(bugfix|feature|release|hotfix|task|chore)\/.+|(master)|(main)|(HEAD)|(PR-.+) - Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/ + Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/ chore/ Suggest: run command `git checkout -b type/branch_name` diff --git a/commit_check/__init__.py b/commit_check/__init__.py index 1c5982f..7d1ab0c 100644 --- a/commit_check/__init__.py +++ b/commit_check/__init__.py @@ -26,8 +26,8 @@ }, { 'check': 'branch', - 'regex': r'^(bugfix|feature|release|hotfix|task)\/.+|(master)|(main)|(HEAD)|(PR-.+)', - 'error': 'Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/', + 'regex': r'^(bugfix|feature|release|hotfix|task|chore)\/.+|(master)|(main)|(HEAD)|(PR-.+)', + 'error': 'Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/ chore/', 'suggest': 'run command `git checkout -b type/branch_name`', }, { From f5580b0ae8b97f7919e70adcde63dcf4f58253ad Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 22:48:23 +0300 Subject: [PATCH 089/146] ci: pre-commit autoupdate (#179) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d50df5f..d057436 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ ci: default_install_hook_types: [pre-commit, prepare-commit-msg] repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: check-yaml - id: check-toml @@ -32,7 +32,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.8.2 + rev: v0.8.3 hooks: - id: check-message # - id: check-branch # uncomment if you need. From d75e1a0cc98a9defbdc28725d3ecefcf634c4e79 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 21:41:25 +0300 Subject: [PATCH 090/146] ci: pre-commit autoupdate (#182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.11.2 → v1.12.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.11.2...v1.12.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d057436..c3cfbf1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.2 + rev: v1.12.1 hooks: - id: mypy additional_dependencies: [types-PyYAML] From 65cf99891800154a32e7eb66258a4dd012a3f57b Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 21 Oct 2024 21:47:22 +0300 Subject: [PATCH 091/146] chore: support Python 3.13 (#183) * chore: update main.yml to support Python 3.13 * Update pyproject.toml --- .github/workflows/main.yml | 2 +- pyproject.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 898121e..ceda0a7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -61,7 +61,7 @@ jobs: strategy: fail-fast: false matrix: - py: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13.0-beta.1'] + py: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] os: ['windows-latest', 'ubuntu-latest', 'macos-latest'] runs-on: ${{ matrix.os }} steps: diff --git a/pyproject.toml b/pyproject.toml index ffeff98..04c8982 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Utilities" , "Topic :: Software Development :: Build Tools", "Topic :: Software Development :: Libraries :: Python Modules", From d5c0ff4123b5eda462cf538a8704631b673acd6c Mon Sep 17 00:00:00 2001 From: Randolph Sapp Date: Mon, 28 Oct 2024 14:59:11 -0500 Subject: [PATCH 092/146] fix(email): do not attempt to validate address (#184) The regex expression to correctly validate an email address is incredibly long and unnecessarily complex for what we are trying to accomplish here [1]. Instead of validating the email address, let's just make sure two values separated with an "@" are present. [1] https://en.wikipedia.org/wiki/Email_address#Syntax Signed-off-by: Randolph Sapp --- commit_check/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commit_check/__init__.py b/commit_check/__init__.py index 7d1ab0c..a88235c 100644 --- a/commit_check/__init__.py +++ b/commit_check/__init__.py @@ -38,13 +38,13 @@ }, { 'check': 'author_email', - 'regex': r'^\S+@\S+\.\S+$', + 'regex': r'^.+@.+$', 'error': 'The committer\'s email seems invalid', 'suggest': 'run command `git config user.email yourname@example.com`', }, { 'check': 'commit_signoff', - 'regex': r'Signed-off-by:.*[A-Za-z0-9]\s+<[\w\.]+@([\w-]+\.)+[\w-]{2,4}>', + 'regex': r'Signed-off-by:.*[A-Za-z0-9]\s+<.+@.+>', 'error': 'Signed-off-by not found in latest commit', 'suggest': 'run command `git commit -m "conventional commit message" --signoff`', }, From cdba20ce6c1f95157c1409798327ecf726aea37c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:01:03 +0200 Subject: [PATCH 093/146] ci: pre-commit autoupdate (#185) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.12.1 → v1.13.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.12.1...v1.13.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c3cfbf1..378667b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.12.1 + rev: v1.13.0 hooks: - id: mypy additional_dependencies: [types-PyYAML] From 6d26de09940b82753e12896a44992a406a08b8c0 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 28 Oct 2024 22:12:16 +0200 Subject: [PATCH 094/146] fix: Update main.yml to fix codecov (#187) --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ceda0a7..3737c30 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -49,7 +49,7 @@ jobs: run: | coverage run --source commit_check -m pytest coverage report && coverage xml - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4.6.0 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./coverage.xml From dfabffc5da138ca653722669bce80b8a4e598903 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 29 Oct 2024 14:53:22 +0200 Subject: [PATCH 095/146] chore: update regex in .commit-check.yml (#188) --- .commit-check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.commit-check.yml b/.commit-check.yml index bde24ab..39d657c 100644 --- a/.commit-check.yml +++ b/.commit-check.yml @@ -19,11 +19,11 @@ checks: suggest: run command `git config user.name "Your Name"` - check: author_email - regex: ^\S+@\S+\.\S+$ + regex: ^.+@.+$ error: The committer email seems invalid suggest: run command `git config user.email yourname@example.com` - check: commit_signoff - regex: Signed-off-by + regex: Signed-off-by:.*[A-Za-z0-9]\s+<.+@.+> error: Signed-off-by not found in latest commit suggest: run command `git commit -m "conventional commit message" --signoff` From ae06ae5c866a44d595795a2a18d515ea9eed537a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:47:23 +0200 Subject: [PATCH 096/146] ci: pre-commit autoupdate (#189) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 378667b..066e559 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,7 +32,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.8.3 + rev: v0.8.5 hooks: - id: check-message # - id: check-branch # uncomment if you need. From 651c76bbbb56bd99808d954fc6fda936f3606496 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Nov 2024 23:18:30 +0200 Subject: [PATCH 097/146] chore(deps): bump python from 3.12-slim to 3.13-slim (#180) * chore(deps): bump python from 3.12-slim to 3.13-slim Bumps python from 3.12-slim to 3.13-slim. --- updated-dependencies: - dependency-name: python dependency-type: direct:production ... Signed-off-by: dependabot[bot] * feat: Update publish-image.yml to check Dockerfile * fix: Update publish-image.yml * fix: Update publish-image.yml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: shenxianpeng --- .github/workflows/publish-image.yml | 11 +++++++++-- Dockerfile | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml index d10b181..53649bc 100644 --- a/.github/workflows/publish-image.yml +++ b/.github/workflows/publish-image.yml @@ -1,18 +1,25 @@ name: publish image on: + push: + paths: + - 'Dockerfile' workflow_dispatch: inputs: tag: - description: 'which tag want to build' + description: 'Which tag want to build' default: '' - required: true + required: false jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: Build to check Dockerfile + if: github.event.inputs.tag == '' + run: | + docker build -f Dockerfile -t commit-check . - name: Build and publish docker image if: github.event.inputs.tag != '' run: | diff --git a/Dockerfile b/Dockerfile index cc411cf..7776999 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.12-slim +FROM python:3.13-slim ARG VERSION From 62a74a3a289070fc3e673971d223a1f52be891a6 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 11 Nov 2024 23:36:54 +0200 Subject: [PATCH 098/146] feat: add `merge_base` to check the branch is rebased (#192) * feat: check merge base (WIP) * feat: check merge base (WIP) * ci: auto fixes from pre-commit.com hooks * fix pre-commit check issues * Update commit_check/branch.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update .commit-check.yml Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * feat: add noxfile.py * ci: auto fixes from pre-commit.com hooks * fix pre-commit check * Update noxfile.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix: update merge_base feature * feat: refactor print error message * fix: update noxfile.py to fix workflow * fix: update noxfile.py to fix workflow * fix: update noxfile.py to fix finding wheel * fix: update noxfile.py * test: disable run commit-check * fix: revert main.yml * ci: auto fixes from pre-commit.com hooks * fix: removed does work test case * fix: update merge_base regex * fix: refactor code based on review * fix: update noxfile.py to fix lint * refactor: update commit-check.yml * test: add test for git_merge_base() * refactor: update util_test.py * feat: add new tests * refactor: update test * test: add tests for main and branch --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .commit-check.yml | 5 +++ .gitignore | 3 ++ commit_check/__init__.py | 6 ++++ commit_check/author.py | 4 ++- commit_check/branch.py | 32 +++++++++++++++++- commit_check/commit.py | 6 +++- commit_check/main.py | 10 ++++++ commit_check/util.py | 47 +++++++++++++++++++++----- noxfile.py | 71 ++++++++++++++++++++++++++++++++++++++++ requirements-dev.txt | 1 + tests/branch_test.py | 40 ++++++++++++++++++++-- tests/main_test.py | 34 ++++++++++++------- tests/util_test.py | 37 +++++++++++++++++++-- 13 files changed, 268 insertions(+), 28 deletions(-) create mode 100644 noxfile.py diff --git a/.commit-check.yml b/.commit-check.yml index 39d657c..9b0c319 100644 --- a/.commit-check.yml +++ b/.commit-check.yml @@ -27,3 +27,8 @@ checks: regex: Signed-off-by:.*[A-Za-z0-9]\s+<.+@.+> error: Signed-off-by not found in latest commit suggest: run command `git commit -m "conventional commit message" --signoff` + + - check: merge_base + regex: main # it can be master, develop, devel etc based on your project. + error: Current branch is not up to date with target branch + suggest: please ensure your branch is rebased with the target branch diff --git a/.gitignore b/.gitignore index 94f592d..6e9ea54 100644 --- a/.gitignore +++ b/.gitignore @@ -4,12 +4,15 @@ __pycache__ .mypy_cache .vscode venv +.venv UNKNOWN.egg-info dist build tests/__pycache__ .coverage coverage.xml +.nox +_build/ # docs docs/_build diff --git a/commit_check/__init__.py b/commit_check/__init__.py index a88235c..44d3c0d 100644 --- a/commit_check/__init__.py +++ b/commit_check/__init__.py @@ -48,6 +48,12 @@ 'error': 'Signed-off-by not found in latest commit', 'suggest': 'run command `git commit -m "conventional commit message" --signoff`', }, + { + 'check': 'merge_base', + 'regex': r'main', # it can be master, develop, devel etc based on your project. + 'error': 'Current branch is not up to date with target branch', + 'suggest': 'please ensure your branch is rebased with the target branch', + }, ], } diff --git a/commit_check/author.py b/commit_check/author.py index 1ab3ba1..a68397e 100644 --- a/commit_check/author.py +++ b/commit_check/author.py @@ -1,7 +1,7 @@ """Check git author name and email""" import re from commit_check import YELLOW, RESET_COLOR, PASS, FAIL -from commit_check.util import get_commit_info, print_error_message, print_suggestion +from commit_check.util import get_commit_info, print_error_header, print_error_message, print_suggestion def check_author(checks: list, check_type: str) -> int: @@ -19,6 +19,8 @@ def check_author(checks: list, check_type: str) -> int: config_value = str(get_commit_info(format_str)) result = re.match(check['regex'], config_value) if result is None: + if not print_error_header.has_been_called: + print_error_header() print_error_message( check['check'], check['regex'], check['error'], config_value, diff --git a/commit_check/branch.py b/commit_check/branch.py index b1ef580..2e23598 100644 --- a/commit_check/branch.py +++ b/commit_check/branch.py @@ -1,7 +1,7 @@ """Check git branch naming convention.""" import re from commit_check import YELLOW, RESET_COLOR, PASS, FAIL -from commit_check.util import get_branch_name, print_error_message, print_suggestion +from commit_check.util import get_branch_name, git_merge_base, print_error_header, print_error_message, print_suggestion def check_branch(checks: list) -> int: @@ -15,6 +15,8 @@ def check_branch(checks: list) -> int: branch_name = get_branch_name() result = re.match(check['regex'], branch_name) if result is None: + if not print_error_header.has_been_called: + print_error_header() print_error_message( check['check'], check['regex'], check['error'], branch_name, @@ -23,3 +25,31 @@ def check_branch(checks: list) -> int: print_suggestion(check['suggest']) return FAIL return PASS + + +def check_merge_base(checks: list) -> int: + """Check if the current branch is based on the latest target branch. + params checks: List of check configurations containing merge_base rules + + :returns PASS(0) if merge base check succeeds, FAIL(1) otherwise + """ + for check in checks: + if check['check'] == 'merge_base': + if check['regex'] == "": + print( + f"{YELLOW}Not found target branch for checking merge base. skip checking.{RESET_COLOR}", + ) + return PASS + current_branch = get_branch_name() + result = git_merge_base(check['regex'], current_branch) + if result != 0: + if not print_error_header.has_been_called: + print_error_header() + print_error_message( + check['check'], check['regex'], + check['error'], current_branch, + ) + if check['suggest']: + print_suggestion(check['suggest']) + return FAIL + return PASS diff --git a/commit_check/commit.py b/commit_check/commit.py index 30b4dfe..5505e77 100644 --- a/commit_check/commit.py +++ b/commit_check/commit.py @@ -2,7 +2,7 @@ import re from pathlib import PurePath from commit_check import YELLOW, RESET_COLOR, PASS, FAIL -from commit_check.util import cmd_output, get_commit_info, print_error_message, print_suggestion +from commit_check.util import cmd_output, get_commit_info, print_error_header, print_error_message, print_suggestion def get_default_commit_msg_file() -> str: @@ -37,6 +37,8 @@ def check_commit_msg(checks: list, commit_msg_file: str = "") -> int: if check['check'] == 'message': result = re.match(check['regex'], commit_msg) if result is None: + if not print_error_header.has_been_called: + print_error_header() print_error_message( check['check'], check['regex'], check['error'], commit_msg, @@ -64,6 +66,8 @@ def check_commit_signoff(checks: list, commit_msg_file: str = "") -> int: commit_hash = get_commit_info("H") result = re.search(check['regex'], commit_msg) if result is None: + if not print_error_header.has_been_called: + print_error_header() print_error_message( check['check'], check['regex'], check['error'], commit_hash, diff --git a/commit_check/main.py b/commit_check/main.py index 0a8a020..3a2e6f3 100644 --- a/commit_check/main.py +++ b/commit_check/main.py @@ -76,6 +76,14 @@ def get_parser() -> argparse.ArgumentParser: required=False, ) + parser.add_argument( + '-mb', + '--merge-base', + help='check common ancestors', + action="store_true", + required=False, + ) + parser.add_argument( '-d', '--dry-run', @@ -108,6 +116,8 @@ def main() -> int: retval = branch.check_branch(checks) if args.commit_signoff: retval = commit.check_commit_signoff(checks) + if args.merge_base: + retval = branch.check_merge_base(checks) if args.dry_run: retval = PASS diff --git a/commit_check/util.py b/commit_check/util.py index ef8f89a..a63d6c1 100644 --- a/commit_check/util.py +++ b/commit_check/util.py @@ -51,6 +51,23 @@ def get_commit_info(format_string: str, sha: str = "HEAD") -> str: return output +def git_merge_base(target_branch: str, current_branch: str) -> int: + """Check ancestors for a given commit. + :param target_branch: target branch + :param current_branch: default is HEAD + + :returns: 0 if ancestor exists, 1 if not, 128 if git command fails. + """ + try: + commands = ['git', 'merge-base', '--is-ancestor', f'{target_branch}', f'{current_branch}'] + result = subprocess.run( + commands, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8' + ) + return result.returncode + except CalledProcessError: + return 128 + + def cmd_output(commands: list) -> str: """Run command :param commands: list of commands @@ -83,14 +100,18 @@ def validate_config(path_to_config: str) -> dict: return configuration -def print_error_message(check_type: str, regex: str, error: str, reason: str): - """Print error message. - :param check_type: - :param regex: - :param error: - :param reason: +def track_print_call(func): + def wrapper(*args, **kwargs): + wrapper.has_been_called = True + return func(*args, **kwargs) + wrapper.has_been_called = False # Initialize as False + return wrapper - :returns: Give error messages to user + +@track_print_call +def print_error_header(): + """Print error message. + :returns: Print error head to user """ print("Commit rejected by Commit-Check. ") print(" ") @@ -105,10 +126,20 @@ def print_error_message(check_type: str, regex: str, error: str, reason: str): print(" ") print("Commit rejected. ") print(" ") + + +def print_error_message(check_type: str, regex: str, error: str, reason: str): + """Print error message. + :param check_type: + :param regex: + :param error: + :param reason: + + :returns: Give error messages to user + """ print(f"Type {YELLOW}{check_type}{RESET_COLOR} check failed => {RED}{reason}{RESET_COLOR} ", end='',) print("") print(f"It doesn't match regex: {regex}") - print("") print(error) diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 0000000..3600177 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,71 @@ +import nox +import glob + +nox.options.reuse_existing_virtualenvs = True +nox.options.reuse_venv = True +nox.options.sessions = ["lint"] + +REQUIREMENTS = { + "dev": "requirements-dev.txt", + "docs": "docs/requirements.txt", +} + +# ----------------------------------------------------------------------------- +# Development Commands +# ----------------------------------------------------------------------------- + + +@nox.session() +def lint(session): + session.install("pre-commit") + # only need pre-commit hook for local development + session.run("pre-commit", "install", "--hook-type", "pre-commit") + if session.posargs: + args = session.posargs + ["--all-files"] + else: + args = ["--all-files", "--show-diff-on-failure"] + + session.run("pre-commit", "run", *args) + + +@nox.session(name="test-hook") +def test_hook(session): + session.install("-e", ".") + session.install("pre-commit") + session.run("pre-commit", "try-repo", ".") + + +@nox.session() +def build(session): + session.run("python3", "-m", "pip", "wheel", "--no-deps", "-w", "dist", ".") + + +@nox.session(name="install-wheel", requires=["build"]) +def install_wheel(session): + whl_file = glob.glob("dist/*.whl") + session.install(str(whl_file[0])) + + +# @nox.session(name="commit-check", requires=["install-wheel"]) +@nox.session(name="commit-check", requires=["install-wheel"]) +def commit_check(session): + session.run( + "commit-check", + "--message", + "--branch", + "--author-email", + ) + + +@nox.session(requires=["install-wheel"]) +def coverage(session): + session.run("coverage", "run", "--source", "commit_check", "-m", "pytest") + session.run("coverage", "report") + session.run("coverage", "xml") + + +@nox.session() +def docs(session): + session.install("-e", ".") + session.install("-r", REQUIREMENTS["docs"]) + session.run("sphinx-build", "-E", "-W", "-b", "html", "docs", "_build/html") diff --git a/requirements-dev.txt b/requirements-dev.txt index 787fd29..cb4cde7 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,5 @@ coverage +nox pre-commit pytest pytest-mock diff --git a/tests/branch_test.py b/tests/branch_test.py index 7093eca..64ec3a4 100644 --- a/tests/branch_test.py +++ b/tests/branch_test.py @@ -1,13 +1,12 @@ from commit_check import PASS, FAIL -from commit_check.branch import check_branch +from commit_check.branch import check_branch, check_merge_base # used by get_branch_name mock FAKE_BRANCH_NAME = "fake_branch_name" -# The location of check_branch() LOCATION = "commit_check.branch" -class TestBranch: +class TestCheckBranch: def test_check_branch(self, mocker): # Must call get_branch_name, re.match at once. checks = [{ @@ -113,3 +112,38 @@ def test_check_branch_with_result_none(self, mocker): assert m_re_match.call_count == 1 assert m_print_error_message.call_count == 1 assert m_print_suggestion.call_count == 1 + + +class TestCheckMergeBase: + def test_check_merge_base_with_empty_checks(self, mocker): + checks = [] + m_check_merge = mocker.patch(f"{LOCATION}.check_merge_base") + retval = check_merge_base(checks) + assert retval == PASS + assert m_check_merge.call_count == 0 + + def test_check_merge_base_with_different_check(self, mocker): + checks = [{ + "check": "branch", + "regex": "main" + }] + m_check_merge = mocker.patch(f"{LOCATION}.check_merge_base") + retval = check_merge_base(checks) + assert retval == PASS + assert m_check_merge.call_count == 0 + + def test_check_merge_base_fail_with_messages(self, mocker, capfd): + checks = [{ + "check": "merge_base", + "regex": "develop", + "error": "Current branch is not", + "suggest": "Please rebase" + }] + mocker.patch(f"{LOCATION}.check_merge_base", return_value=1) + m_print_error = mocker.patch(f"{LOCATION}.print_error_message") + m_print_suggest = mocker.patch(f"{LOCATION}.print_suggestion") + + retval = check_merge_base(checks) + assert retval == FAIL + assert "Current branch is not" in m_print_error.call_args[0][2] + assert "Please rebase" in m_print_suggest.call_args[0][0] diff --git a/tests/main_test.py b/tests/main_test.py index 3fdc184..9d26ebe 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -7,18 +7,20 @@ class TestMain: - @pytest.mark.parametrize("argv, check_commit_call_count, check_branch_call_count, check_author_call_count, check_commit_signoff_call_count", [ - ([CMD, "--message"], 1, 0, 0, 0), - ([CMD, "--branch"], 0, 1, 0, 0), - ([CMD, "--author-name"], 0, 0, 1, 0), - ([CMD, "--author-email"], 0, 0, 1, 0), - ([CMD, "--commit-signoff"], 0, 0, 0, 1), - ([CMD, "--message", "--author-email"], 1, 0, 1, 0), - ([CMD, "--branch", "--message"], 1, 1, 0, 0), - ([CMD, "--author-name", "--author-email"], 0, 0, 2, 0), - ([CMD, "--message", "--branch", "--author-email"], 1, 1, 1, 0), - ([CMD, "--branch", "--message", "--author-name", "--author-email"], 1, 1, 2, 0), - ([CMD, "--dry-run"], 0, 0, 0, 0), + @pytest.mark.parametrize("argv, check_commit_call_count, check_branch_call_count, check_author_call_count, check_commit_signoff_call_count, check_merge_base_call_count", [ + ([CMD, "--message"], 1, 0, 0, 0, 0), + ([CMD, "--branch"], 0, 1, 0, 0, 0), + ([CMD, "--author-name"], 0, 0, 1, 0, 0), + ([CMD, "--author-email"], 0, 0, 1, 0, 0), + ([CMD, "--commit-signoff"], 0, 0, 0, 1, 0), + ([CMD, "--merge-base"], 0, 0, 0, 0, 1), + ([CMD, "--message", "--author-email"], 1, 0, 1, 0, 0), + ([CMD, "--branch", "--message"], 1, 1, 0, 0, 0), + ([CMD, "--author-name", "--author-email"], 0, 0, 2, 0, 0), + ([CMD, "--message", "--branch", "--author-email"], 1, 1, 1, 0, 0), + ([CMD, "--branch", "--message", "--author-name", "--author-email"], 1, 1, 2, 0, 0), + ([CMD, "--message", "--branch", "--author-name", "--author-email", "--commit-signoff", "--merge-base"], 1, 1, 2, 1, 1), + ([CMD, "--dry-run"], 0, 0, 0, 0, 0), ]) def test_main( self, @@ -28,6 +30,7 @@ def test_main( check_branch_call_count, check_author_call_count, check_commit_signoff_call_count, + check_merge_base_call_count, ): mocker.patch( "commit_check.main.validate_config", @@ -41,12 +44,14 @@ def test_main( m_check_branch = mocker.patch("commit_check.branch.check_branch") m_check_author = mocker.patch("commit_check.author.check_author") m_check_commit_signoff = mocker.patch("commit_check.commit.check_commit_signoff") + m_check_merge_base = mocker.patch("commit_check.branch.check_merge_base") sys.argv = argv main() assert m_check_commit.call_count == check_commit_call_count assert m_check_branch.call_count == check_branch_call_count assert m_check_author.call_count == check_author_call_count assert m_check_commit_signoff.call_count == check_commit_signoff_call_count + assert m_check_merge_base.call_count == check_merge_base_call_count def test_main_help(self, mocker, capfd): mocker.patch( @@ -61,6 +66,7 @@ def test_main_help(self, mocker, capfd): m_check_branch = mocker.patch("commit_check.branch.check_branch") m_check_author = mocker.patch("commit_check.author.check_author") m_check_commit_signoff = mocker.patch("commit_check.commit.check_commit_signoff") + m_check_merge_base = mocker.patch("commit_check.branch.check_merge_base") sys.argv = ["commit-check", "--h"] with pytest.raises(SystemExit): main() @@ -68,6 +74,7 @@ def test_main_help(self, mocker, capfd): assert m_check_branch.call_count == 0 assert m_check_author.call_count == 0 assert m_check_commit_signoff.call_count == 0 + assert m_check_merge_base.call_count == 0 stdout, _ = capfd.readouterr() assert "usage: " in stdout @@ -84,6 +91,7 @@ def test_main_version(self, mocker): m_check_branch = mocker.patch("commit_check.branch.check_branch") m_check_author = mocker.patch("commit_check.author.check_author") m_check_commit_signoff = mocker.patch("commit_check.commit.check_commit_signoff") + m_check_merge_base = mocker.patch("commit_check.branch.check_merge_base") sys.argv = ["commit-check", "--v"] with pytest.raises(SystemExit): main() @@ -91,6 +99,7 @@ def test_main_version(self, mocker): assert m_check_branch.call_count == 0 assert m_check_author.call_count == 0 assert m_check_commit_signoff.call_count == 0 + assert m_check_merge_base.call_count == 0 def test_main_validate_config_ret_none(self, mocker): mocker.patch( @@ -101,6 +110,7 @@ def test_main_validate_config_ret_none(self, mocker): mocker.patch("commit_check.branch.check_branch") mocker.patch("commit_check.author.check_author") mocker.patch("commit_check.commit.check_commit_signoff") + mocker.patch("commit_check.branch.check_merge_base") sys.argv = ["commit-check", "--message"] main() assert m_check_commit.call_count == 1 diff --git a/tests/util_test.py b/tests/util_test.py index 70ae5b7..42870ea 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -1,11 +1,15 @@ import pytest +import subprocess from commit_check.util import get_branch_name +from commit_check.util import git_merge_base from commit_check.util import get_commit_info from commit_check.util import cmd_output from commit_check.util import validate_config +from commit_check.util import print_error_header from commit_check.util import print_error_message from commit_check.util import print_suggestion from subprocess import CalledProcessError, PIPE +from unittest.mock import MagicMock class TestUtil: @@ -42,6 +46,30 @@ def test_get_branch_name_with_exception(self, mocker): ] assert retval == "" + class TestGitMergeBase: + @pytest.mark.parametrize("returncode,expected", [ + (0, 0), # ancestor exists + (1, 1), # no ancestor + (128, 128), # error case + ]) + def test_git_merge_base(self, mocker, returncode, expected): + mock_run = mocker.patch("subprocess.run") + if returncode == 128: + mock_run.side_effect = CalledProcessError(returncode, "git merge-base") + else: + mock_result = MagicMock() + mock_result.returncode = returncode + mock_run.return_value = mock_result + + result = git_merge_base("main", "feature") + + mock_run.assert_called_once_with( + ["git", "merge-base", "--is-ancestor", "main", "feature"], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8' + ) + + assert result == expected + class TestGetCommitInfo: @pytest.mark.parametrize("format_string", [ ("s"), @@ -170,6 +198,13 @@ def test_validate_config_file_not_found(self, mocker): assert retval == {} class TestPrintErrorMessage: + def test_print_error_header(self, capfd): + # Must print on stdout with given argument. + print_error_header() + stdout, _ = capfd.readouterr() + assert "Commit rejected by Commit-Check" in stdout + assert "Commit rejected." in stdout + @pytest.mark.parametrize("check_type, type_failed_msg", [ ("message", "check failed =>"), ("branch", "check failed =>"), @@ -189,8 +224,6 @@ def test_print_error_message(self, capfd, check_type, type_failed_msg): dummy_reason ) stdout, _ = capfd.readouterr() - assert "Commit rejected by Commit-Check" in stdout - assert "Commit rejected." in stdout assert check_type in stdout assert type_failed_msg in stdout assert f"It doesn't match regex: {dummy_regex}" in stdout From 3ec511288dccd104d66f50b8b80c8d760357d6d1 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 12 Nov 2024 20:00:53 +0200 Subject: [PATCH 099/146] fix: check target branch name and update help (#194) --- .commit-check.yml | 4 ++-- commit_check/__init__.py | 4 ++-- commit_check/branch.py | 3 ++- commit_check/main.py | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.commit-check.yml b/.commit-check.yml index 9b0c319..10f8d39 100644 --- a/.commit-check.yml +++ b/.commit-check.yml @@ -30,5 +30,5 @@ checks: - check: merge_base regex: main # it can be master, develop, devel etc based on your project. - error: Current branch is not up to date with target branch - suggest: please ensure your branch is rebased with the target branch + error: Current branch is not rebased onto target branch + suggest: Please ensure your branch is rebased with the target branch diff --git a/commit_check/__init__.py b/commit_check/__init__.py index 44d3c0d..61de524 100644 --- a/commit_check/__init__.py +++ b/commit_check/__init__.py @@ -51,8 +51,8 @@ { 'check': 'merge_base', 'regex': r'main', # it can be master, develop, devel etc based on your project. - 'error': 'Current branch is not up to date with target branch', - 'suggest': 'please ensure your branch is rebased with the target branch', + 'error': 'Current branch is not rebased onto target branch', + 'suggest': 'Please ensure your branch is rebased with the target branch', }, ], } diff --git a/commit_check/branch.py b/commit_check/branch.py index 2e23598..39bc7ec 100644 --- a/commit_check/branch.py +++ b/commit_check/branch.py @@ -40,8 +40,9 @@ def check_merge_base(checks: list) -> int: f"{YELLOW}Not found target branch for checking merge base. skip checking.{RESET_COLOR}", ) return PASS + target_branch = check['regex'] if "origin/" in check['regex'] else f"origin/{check['regex']}" current_branch = get_branch_name() - result = git_merge_base(check['regex'], current_branch) + result = git_merge_base(target_branch, current_branch) if result != 0: if not print_error_header.has_been_called: print_error_header() diff --git a/commit_check/main.py b/commit_check/main.py index 3a2e6f3..50b2350 100644 --- a/commit_check/main.py +++ b/commit_check/main.py @@ -79,7 +79,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument( '-mb', '--merge-base', - help='check common ancestors', + help='check branch is rebased onto target branch', action="store_true", required=False, ) From 67a65601bc5a03947d5da187e47f882023c51201 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Wed, 13 Nov 2024 00:34:45 +0200 Subject: [PATCH 100/146] chore: Update pyproject.toml to remove python 3.7 (#196) --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 04c8982..1e028b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,6 @@ classifiers = [ "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", From 166b751984cb378626cc2b03d2d3c0420c436ee5 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Wed, 13 Nov 2024 16:19:59 +0200 Subject: [PATCH 101/146] feat: support new pre-commit hook `check-merge-base` (#197) --- .pre-commit-config.yaml | 7 ++++--- .pre-commit-hooks.yaml | 17 ++++++++++++----- README.rst | 5 +++-- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 066e559..d65d917 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,10 +32,11 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.8.5 + rev: v0.9.1 hooks: - id: check-message # - id: check-branch # uncomment if you need. - # - id: check-author-name # uncomment if you need. - # - id: check-author-email # uncomment if you need. + - id: check-author-name # uncomment if you need. + - id: check-author-email # uncomment if you need. # - id: commit-signoff # uncomment if you need. + # - id: check-merge-base # uncomment if you need. diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 0ba4a51..1fca51a 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -1,6 +1,6 @@ - id: check-message name: check commit message - description: requiring commit message to match regex + description: ensures commit message to match regex entry: commit-check args: [--message] pass_filenames: true @@ -8,29 +8,36 @@ stages: [commit-msg, prepare-commit-msg] - id: check-branch name: check branch naming - description: requiring branch naming to match regex + description: ensures branch naming to match regex entry: commit-check args: [--branch] pass_filenames: false language: python - id: check-author-name name: check committer name - description: requiring committer name to match regex + description: ensures committer name to match regex entry: commit-check args: [--author-name] pass_filenames: false language: python - id: check-author-email name: check committer email - description: requiring committer email to match regex + description: ensures committer email to match regex entry: commit-check args: [--author-email] pass_filenames: false language: python - id: check-commit-signoff name: check committer signoff - description: requiring committer to add a Signed-off-by trailer + description: ensures committer to add a Signed-off-by trailer entry: commit-check args: [--commit-signoff] pass_filenames: false language: python +- id: check-merge-base + name: check merge base + description: ensures current branch is rebased onto target branch + entry: commit-check + args: [--merge-base] + pass_filenames: false + language: python diff --git a/README.rst b/README.rst index ff9c7e6..09d71eb 100644 --- a/README.rst +++ b/README.rst @@ -32,7 +32,7 @@ Overview **Commit Check** is a free, powerful tool that enforces commit metadata standards, including commit message, branch naming, committer name/email, and commit signoff. Fully customizable with error messages and suggested commands, it ensures compliance across teams. -As an alternative to GitHub Enerprise `Metadata restrictions `_ and Bitbucket's paid puglin `Yet Another Commit Checker `_, Commit Check stands out by integrating DevOps principles and Infrastructure as Code (IaC). +As an alternative to GitHub Enterprise `Metadata restrictions `_ and Bitbucket's paid puglin `Yet Another Commit Checker `_, Commit Check stands out by integrating DevOps principles and Infrastructure as Code (IaC). Configuration ------------- @@ -75,6 +75,7 @@ Running as pre-commit hook - id: check-author-name - id: check-author-email - id: check-commit-signoff + - id: check-merge-base Running as CLI ~~~~~~~~~~~~~~ @@ -107,7 +108,7 @@ To configure the hook, create a script file in the ``.git/hooks/`` directory. .. code-block:: bash #!/bin/sh - commit-check --message --branch --author-name --author-email + commit-check --message --branch --author-name --author-email --commit-signoff --merge-base Save the script file as ``pre-push`` and make it executable: From 82612aa8995e3bde0564fcd57bbe48380c1b9d7b Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Thu, 14 Nov 2024 20:57:14 +0200 Subject: [PATCH 102/146] chore: update .pre-commit-config.yaml (#198) --- .pre-commit-config.yaml | 4 ++-- README.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d65d917..101d2ee 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,11 +32,11 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.9.1 + rev: v0.9.2 hooks: - id: check-message # - id: check-branch # uncomment if you need. - id: check-author-name # uncomment if you need. - id: check-author-email # uncomment if you need. # - id: commit-signoff # uncomment if you need. - # - id: check-merge-base # uncomment if you need. + # - id: check-merge-base # requires download all git history diff --git a/README.rst b/README.rst index 09d71eb..465ab34 100644 --- a/README.rst +++ b/README.rst @@ -70,12 +70,12 @@ Running as pre-commit hook - repo: https://github.com/commit-check/commit-check rev: the tag or revision hooks: # support hooks - - id: check-message # it requires hook prepare-commit-msg + - id: check-message # requires hook prepare-commit-msg - id: check-branch - id: check-author-name - id: check-author-email - id: check-commit-signoff - - id: check-merge-base + - id: check-merge-base # requires download all git history Running as CLI ~~~~~~~~~~~~~~ From 1d194eb0561d11693f50564c1b8bcde3c07a9afa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 09:19:37 +0200 Subject: [PATCH 103/146] chore(deps): bump codecov/codecov-action from 4.6.0 to 5.0.2 (#199) --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3737c30..c7d0c3a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -49,7 +49,7 @@ jobs: run: | coverage run --source commit_check -m pytest coverage report && coverage xml - - uses: codecov/codecov-action@v4.6.0 + - uses: codecov/codecov-action@v5.0.2 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./coverage.xml From 7de6ac2f4884f77ff6c9a0308414b184dd6046c2 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 26 Nov 2024 16:59:50 +0200 Subject: [PATCH 104/146] feat: support nox and update readme (#202) * fix: update noxfile.py to fix Sessions defined in /workspace/commit-check/noxfile.py: * lint - test-hook - build - install-wheel - commit-check - coverage - docs sessions marked with * are selected, sessions marked with - are skipped. * feat: add docs-live * docs: update to add example * docs: update to add example * feat: use nox commands in pipeline * feat: use nox commands in pipeline * fix: remove cd to docs step * fix: get branch name to fix ci failure * fix: update noxfile.py * fix: add build session back * fix: install then run test * fix: install nox for test --- .github/workflows/main.yml | 32 +++++++++------------ README.rst | 59 +++++++++++++++++++++++++++----------- noxfile.py | 25 +++++++++------- requirements-dev.txt | 2 +- 4 files changed, 70 insertions(+), 48 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c7d0c3a..0a5169e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,34 +21,26 @@ jobs: - uses: actions/setup-python@v5 with: python-version: '3.x' - - - name: Install dependencies - run: | - pip install -r requirements-dev.txt - pip install -e . + - run: pip install -r requirements-dev.txt - name: Run pre-commit run: | - pre-commit run --all-files - pre-commit try-repo . + nox -s lint + nox -s test-hook - name: Build wheel - run: python3 -m pip wheel --no-deps -w dist . + run: nox -s build - name: Upload wheel as artifact uses: actions/upload-artifact@v4 with: name: commit-check_wheel path: ${{ github.workspace }}/dist/*.whl - name: Run commit-check - run: | - python3 -m pip install dist/*.whl - commit-check -h - commit-check --message --branch --author-email + run: nox -s commit-check - name: Collect Coverage - run: | - coverage run --source commit_check -m pytest - coverage report && coverage xml + run: nox -s coverage + - uses: codecov/codecov-action@v5.0.2 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -69,6 +61,7 @@ jobs: - uses: actions/setup-python@v5 with: python-version: ${{ matrix.py }} + - run: pip install -r requirements-dev.txt - name: Download wheel artifact uses: actions/download-artifact@v4 @@ -79,20 +72,21 @@ jobs: - name: Install test # using a wildcard as filename on Windows requires a bash shell shell: bash - run: python3 -m pip install dist/*.whl + run: nox -s install-wheel docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} # get current branch name - uses: actions/setup-python@v5 with: python-version: "3.10" - - run: python -m pip install . -r docs/requirements.txt + - run: pip install -r requirements-dev.txt - name: Build docs - working-directory: docs - run: sphinx-build -E -W -b html . _build/html + run: nox -s docs - name: Save built docs as artifact uses: actions/upload-artifact@v4 diff --git a/README.rst b/README.rst index 465ab34..2f19257 100644 --- a/README.rst +++ b/README.rst @@ -30,9 +30,11 @@ Commit Check Overview -------- -**Commit Check** is a free, powerful tool that enforces commit metadata standards, including commit message, branch naming, committer name/email, and commit signoff. Fully customizable with error messages and suggested commands, it ensures compliance across teams. +**Commit Check** is a free, powerful tool that enforces commit metadata standards, including commit message, branch naming, committer name/email, commit signoff and more. -As an alternative to GitHub Enterprise `Metadata restrictions `_ and Bitbucket's paid puglin `Yet Another Commit Checker `_, Commit Check stands out by integrating DevOps principles and Infrastructure as Code (IaC). +Fully customizable with error messages and suggested commands, it ensures compliance across teams. + +As an alternative to GitHub Enterprise `Metadata restrictions `_ and Bitbucket's paid plugin `Yet Another Commit Checker `_, Commit Check stands out by integrating DevOps principles and Infrastructure as Code (IaC). Configuration ------------- @@ -70,7 +72,7 @@ Running as pre-commit hook - repo: https://github.com/commit-check/commit-check rev: the tag or revision hooks: # support hooks - - id: check-message # requires hook prepare-commit-msg + - id: check-message # requires prepare-commit-msg hook - id: check-branch - id: check-author-name - id: check-author-email @@ -80,25 +82,25 @@ Running as pre-commit hook Running as CLI ~~~~~~~~~~~~~~ -Global Installation +Install globally .. code-block:: bash sudo pip3 install -U commit-check -User Installation +Install locally .. code-block:: bash pip install -U commit-check -Install from Git Repo +Install from source code .. code-block:: bash pip install git+https://github.com/commit-check/commit-check.git@main -Then, run ``commit-check`` from the command line. For more information, see the `docs `_. +Then, run ``commit-check --help`` from the command line. For more information, see the `docs `_. Running as Git Hooks ~~~~~~~~~~~~~~~~~~~~ @@ -118,8 +120,8 @@ Save the script file as ``pre-push`` and make it executable: Now, ``git push`` will trigger this hook automatically. -Example -------- +Examples +-------- Check Commit Message Failed @@ -155,24 +157,47 @@ Check Branch Naming Failed Commit rejected by Commit-Check. - (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) - / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ - __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ + (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) + / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ + __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ (_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._) - || E || || R || || R || || O || || R || - _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ + || E || || R || || R || || O || || R || + _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ (.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) - `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ + `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ Commit rejected. - Type branch check failed => my-test-branch + Type branch check failed => patch-1 It doesn't match regex: ^(bugfix|feature|release|hotfix|task|chore)\/.+|(master)|(main)|(HEAD)|(PR-.+) - Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/ chore/ Suggest: run command `git checkout -b type/branch_name` +Check Commit Signature Failed + +.. code-block:: text + + Commit rejected by Commit-Check. + + (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) + / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ + __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ + (_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._) + || E || || R || || R || || O || || R || + _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ + (.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) + `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ + + Commit rejected. + + Type commit_signoff check failed => c92ce259ff041c91859c7fb61afdbb391e769d0f + It doesn't match regex: Signed-off-by:.*[A-Za-z0-9]\s+<.+@.+> + Signed-off-by not found in latest commit + Suggest: run command `git commit -m "conventional commit message" --signoff` + + + Badging your repository ----------------------- diff --git a/noxfile.py b/noxfile.py index 3600177..109e2df 100644 --- a/noxfile.py +++ b/noxfile.py @@ -2,7 +2,6 @@ import glob nox.options.reuse_existing_virtualenvs = True -nox.options.reuse_venv = True nox.options.sessions = ["lint"] REQUIREMENTS = { @@ -42,23 +41,20 @@ def build(session): @nox.session(name="install-wheel", requires=["build"]) def install_wheel(session): + session.run("python3", "-m", "pip", "wheel", "--no-deps", "-w", "dist", ".") whl_file = glob.glob("dist/*.whl") session.install(str(whl_file[0])) -# @nox.session(name="commit-check", requires=["install-wheel"]) -@nox.session(name="commit-check", requires=["install-wheel"]) +@nox.session(name="commit-check") def commit_check(session): - session.run( - "commit-check", - "--message", - "--branch", - "--author-email", - ) + session.install(".") + session.run("commit-check", "--message", "--branch", "--author-email") -@nox.session(requires=["install-wheel"]) +@nox.session() def coverage(session): + session.install(".") session.run("coverage", "run", "--source", "commit_check", "-m", "pytest") session.run("coverage", "report") session.run("coverage", "xml") @@ -66,6 +62,13 @@ def coverage(session): @nox.session() def docs(session): - session.install("-e", ".") + session.install(".") session.install("-r", REQUIREMENTS["docs"]) session.run("sphinx-build", "-E", "-W", "-b", "html", "docs", "_build/html") + + +@nox.session(name="docs-live") +def docs_live(session): + session.install(".") + session.install("-r", REQUIREMENTS["docs"], "sphinx-autobuild") + session.run("sphinx-autobuild", "-b", "html", "docs", "_build/html") diff --git a/requirements-dev.txt b/requirements-dev.txt index cb4cde7..120645f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,5 @@ coverage -nox +git+https://github.com/wntrblm/nox.git@main pre-commit pytest pytest-mock From 369931a62fc3f0fe500ad7b19101878a641d0c17 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:37:08 +0200 Subject: [PATCH 105/146] chore(deps): bump actions/attest-build-provenance from 1 to 2 (#204) --- .github/workflows/publish-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index 77c5179..f9ce961 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -33,7 +33,7 @@ jobs: twine check dist/commit_check* - name: Create attestations - uses: actions/attest-build-provenance@v1 + uses: actions/attest-build-provenance@v2 with: subject-path: "dist/commit_check*" From b1cd769eada1ab64c01608a22d9082094013be63 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 29 Dec 2024 02:50:32 -0500 Subject: [PATCH 106/146] ci: pre-commit autoupdate (#206) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 101d2ee..9d278c3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.13.0 + rev: v1.14.0 hooks: - id: mypy additional_dependencies: [types-PyYAML] From c8602e5a88663264d90d22770ff38707ec724d84 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Thu, 2 Jan 2025 07:17:58 -0500 Subject: [PATCH 107/146] fix: update publish_dir to fix online docs (#207) --- .github/workflows/main.yml | 8 +++++--- .gitpod.yml | 2 +- pyproject.toml | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0a5169e..b190f6a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -54,14 +54,16 @@ jobs: fail-fast: false matrix: py: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] - os: ['windows-latest', 'ubuntu-latest', 'macos-latest'] + os: ['windows-latest', 'ubuntu-24.04', 'macos-latest'] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: ${{ matrix.py }} - - run: pip install -r requirements-dev.txt + - run: | + pip install --upgrade pip + pip install -r requirements-dev.txt - name: Download wheel artifact uses: actions/download-artifact@v4 @@ -100,4 +102,4 @@ jobs: uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/_build/html + publish_dir: ./_build/html diff --git a/.gitpod.yml b/.gitpod.yml index e6de223..8123636 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -3,6 +3,6 @@ # and commit this file to your remote git repository to share the goodness with others. tasks: - - before: pip install -r requirements-dev.txt + - before: pip install --upgrade pip && pip install -r requirements-dev.txt init: pre-commit install command: pip install -e . diff --git a/pyproject.toml b/pyproject.toml index 1e028b4..2710ff6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,7 @@ license = {text = "MIT License"} authors = [ { name = "Xianpeng Shen", email = "xianpeng.shen@gmail.com" }, ] +requires-python = ">=3.8" dependencies = ["pyyaml"] classifiers = [ # https://pypi.org/pypi?%3Aaction=list_classifiers From 8593c6bfdee08090e3b358c40f3448af1dc11618 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Thu, 2 Jan 2025 07:28:47 -0500 Subject: [PATCH 108/146] fixup: update path to fix online docs (#208) * fix: update publish_dir to fix online docs * fixup! fix: update publish_dir to fix online docs * chore: update ubuntu-latest to ubuntu-24.04 --- .github/workflows/main.yml | 6 +++--- .github/workflows/publish-image.yml | 2 +- .github/workflows/publish-package.yml | 2 +- docs/README.rst | 8 +++----- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b190f6a..9106468 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 @@ -77,7 +77,7 @@ jobs: run: nox -s install-wheel docs: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: @@ -94,7 +94,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: "commit-check_docs" - path: ${{ github.workspace }}/docs/_build/html + path: ${{ github.workspace }}/_build/html - name: Upload docs to github pages # only publish doc changes from main branch diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml index 53649bc..39dd16e 100644 --- a/.github/workflows/publish-image.yml +++ b/.github/workflows/publish-image.yml @@ -13,7 +13,7 @@ on: jobs: publish: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Build to check Dockerfile diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index f9ce961..9dcac79 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -12,7 +12,7 @@ permissions: jobs: publish: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 # use fetch --all for setuptools_scm to work diff --git a/docs/README.rst b/docs/README.rst index cdb46e5..d296410 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -9,15 +9,13 @@ From the root directory of the repository, do the following to steps .. code-block:: text - pip install -r docs/requirements.txt - - On Linux, you may need to use ``pip3`` instead. + pip install nox 2. Build the docs .. code-block:: text - sphinx-build docs docs/_build/html + nox -s docs - Browse the files in docs/_build/html with your internet browser to see the rendered + Browse the files in /_build/html with your internet browser to see the rendered output. From 91fb4bb67fbaa263b013a55b36403380fce83ab8 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 7 Jan 2025 03:55:01 -0500 Subject: [PATCH 109/146] feat: Create labeler.yml (#210) --- .github/workflows/labeler.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/workflows/labeler.yml diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000..52689d6 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,10 @@ +name: PR Autolabeler + +on: + # pull_request event is required for autolabeler + pull_request: + types: [opened, reopened, synchronize] + +jobs: + draft-release: + uses: commit-check/.github/.github/workflows/release-drafter.yml@main From 0032ba0408c74d47436f06ab456f80812b5f7b1b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 20:16:06 +0200 Subject: [PATCH 110/146] ci: pre-commit autoupdate (#209) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9d278c3..e3fed27 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,13 +22,13 @@ repos: args: [--max-line-length=100, --ignore=E501] exclude: ^commit_check/__init__.py - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.14.0 + rev: v1.14.1 hooks: - id: mypy additional_dependencies: [types-PyYAML] exclude: ^testing/resources/ - repo: https://github.com/codespell-project/codespell - rev: v2.3.0 + rev: v2.4.0 hooks: - id: codespell - repo: https://github.com/commit-check/commit-check From 91ee12b3f5045523cbdacd07390c0ce98f3b8231 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 28 Jan 2025 12:42:05 +0200 Subject: [PATCH 111/146] add more tests and update pre-commit hook to ruff (#211) * add test and update hook to ruff * feat: add more test * fix: update commit_test.py --- .pre-commit-config.yaml | 11 ++++++----- commit_check/branch.py | 4 ++-- commit_check/commit.py | 4 ++-- noxfile.py | 1 + tests/branch_test.py | 11 +++++++++++ tests/commit_test.py | 19 +++++++++++++++++++ tests/error_test.py | 26 ++++++++++++++++++++++++++ 7 files changed, 67 insertions(+), 9 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e3fed27..e1d96d8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,12 +15,13 @@ repos: - id: trailing-whitespace - id: name-tests-test - id: requirements-txt-fixer -- repo: https://github.com/PyCQA/flake8 - rev: 7.1.1 +- repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.9.3 hooks: - - id: flake8 - args: [--max-line-length=100, --ignore=E501] - exclude: ^commit_check/__init__.py + # Run the linter. + - id: ruff + args: [ --fix ] - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.14.1 hooks: diff --git a/commit_check/branch.py b/commit_check/branch.py index 39bc7ec..1cc8a35 100644 --- a/commit_check/branch.py +++ b/commit_check/branch.py @@ -16,7 +16,7 @@ def check_branch(checks: list) -> int: result = re.match(check['regex'], branch_name) if result is None: if not print_error_header.has_been_called: - print_error_header() + print_error_header() # pragma: no cover print_error_message( check['check'], check['regex'], check['error'], branch_name, @@ -45,7 +45,7 @@ def check_merge_base(checks: list) -> int: result = git_merge_base(target_branch, current_branch) if result != 0: if not print_error_header.has_been_called: - print_error_header() + print_error_header() # pragma: no cover print_error_message( check['check'], check['regex'], check['error'], current_branch, diff --git a/commit_check/commit.py b/commit_check/commit.py index 5505e77..60b8d2f 100644 --- a/commit_check/commit.py +++ b/commit_check/commit.py @@ -38,7 +38,7 @@ def check_commit_msg(checks: list, commit_msg_file: str = "") -> int: result = re.match(check['regex'], commit_msg) if result is None: if not print_error_header.has_been_called: - print_error_header() + print_error_header() # pragma: no cover print_error_message( check['check'], check['regex'], check['error'], commit_msg, @@ -67,7 +67,7 @@ def check_commit_signoff(checks: list, commit_msg_file: str = "") -> int: result = re.search(check['regex'], commit_msg) if result is None: if not print_error_header.has_been_called: - print_error_header() + print_error_header() # pragma: no cover print_error_message( check['check'], check['regex'], check['error'], commit_hash, diff --git a/noxfile.py b/noxfile.py index 109e2df..079df8a 100644 --- a/noxfile.py +++ b/noxfile.py @@ -55,6 +55,7 @@ def commit_check(session): @nox.session() def coverage(session): session.install(".") + session.install("-r", REQUIREMENTS["dev"]) session.run("coverage", "run", "--source", "commit_check", "-m", "pytest") session.run("coverage", "report") session.run("coverage", "xml") diff --git a/tests/branch_test.py b/tests/branch_test.py index 64ec3a4..083c5bd 100644 --- a/tests/branch_test.py +++ b/tests/branch_test.py @@ -122,6 +122,17 @@ def test_check_merge_base_with_empty_checks(self, mocker): assert retval == PASS assert m_check_merge.call_count == 0 + + def test_check_merge_base_with_empty_regex(self, mocker): + checks = [{ + "check": "merge_base", + "regex": "" + }] + m_check_merge = mocker.patch(f"{LOCATION}.check_merge_base") + retval = check_merge_base(checks) + assert retval == PASS + assert m_check_merge.call_count == 0 + def test_check_merge_base_with_different_check(self, mocker): checks = [{ "check": "branch", diff --git a/tests/commit_test.py b/tests/commit_test.py index 5642a52..a458636 100644 --- a/tests/commit_test.py +++ b/tests/commit_test.py @@ -30,6 +30,25 @@ def test_read_commit_msg_file_not_found(mocker): assert m_commits_info.call_count == 0 +def test_check_commit_msg_no_commit_msg_file(mocker): + mock_get_default_commit_msg_file = mocker.patch( + "commit_check.commit.get_default_commit_msg_file", + return_value=".git/COMMIT_EDITMSG" + ) + mock_read_commit_msg = mocker.patch( + "commit_check.commit.read_commit_msg", + return_value="Sample commit message" + ) + + checks = [{"regex": ".*", "check": "message", "error": "Invalid", "suggest": None}] + + result = check_commit_msg(checks, commit_msg_file="") + + mock_get_default_commit_msg_file.assert_called_once() + mock_read_commit_msg.assert_called_once_with(".git/COMMIT_EDITMSG") + assert result == 0 + + def test_check_commit_with_empty_checks(mocker): checks = [] m_re_match = mocker.patch( diff --git a/tests/error_test.py b/tests/error_test.py index 188a2b1..d0a2880 100644 --- a/tests/error_test.py +++ b/tests/error_test.py @@ -24,6 +24,32 @@ def test_error_handler_unexpected_error(): assert exit_info.value.code == 3 +def test_error_handler_cannot_access(mocker): + with pytest.raises(SystemExit): + store_dir = "/fake/commit-check" + log_path = os.path.join(store_dir, "commit-check.log") + mocker.patch.dict(os.environ, {"COMMIT_CHECK_HOME": store_dir}) + mock_os_access = mocker.patch("os.access", return_value=False) + mocker.patch("os.path.exists", return_value=True) + mocker.patch("os.makedirs") + mock_open = mocker.patch("builtins.open", mocker.mock_open()) + mocker.patch("commit_check.util.cmd_output", return_value="mock_version") + mocker.patch("sys.version", "Mock Python Version") + mocker.patch("sys.executable", "/mock/path/to/python") + + from commit_check.error import log_and_exit + log_and_exit( + msg="Test error message", + ret_code=1, + exc=ValueError("Test exception"), + formatted="Mocked formatted stack trace" + ) + + mock_os_access.assert_called_once_with(store_dir, os.W_OK) + mock_open.assert_called_with(log_path, "a") + mock_open().write.assert_any_call(f"Failed to write to log at {log_path}\n") + + @pytest.mark.xfail def test_log_and_exit(monkeypatch): monkeypatch.setenv("COMMIT_CHECK_HOME", "") From d9a8729bf047bf2a3d5e1ec90c2cc204aea44bac Mon Sep 17 00:00:00 2001 From: Bea McDonnell Date: Mon, 3 Feb 2025 00:54:54 -0800 Subject: [PATCH 112/146] fix: ensure all checks pass without overwriting previous failures (#213) * test: test multiple checks with different results * fix: ensure all checks pass without overwriting previous failures Passing checks could overwrite a previous failing check and result in returning with an exit code of 0 when a check failed * style: match formatting to other tests * style: revert automatic formatting * fix: add missing imports * chore: ignore missing return All code paths are covered here, checked by the assert * refactor: remove duplicate mock --- commit_check/main.py | 21 ++++++++------- tests/main_test.py | 64 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/commit_check/main.py b/commit_check/main.py index 50b2350..c6b8b32 100644 --- a/commit_check/main.py +++ b/commit_check/main.py @@ -10,7 +10,7 @@ from commit_check import author from commit_check.util import validate_config from commit_check.error import error_handler -from . import CONFIG_FILE, DEFAULT_CONFIG, PASS, __version__ +from . import CONFIG_FILE, DEFAULT_CONFIG, PASS, FAIL, __version__ def get_parser() -> argparse.ArgumentParser: @@ -99,7 +99,7 @@ def main() -> int: """The main entrypoint of commit-check program.""" parser = get_parser() args = parser.parse_args() - retval = PASS + check_results: list[int] = [] with error_handler(): config = validate_config(args.config) if validate_config( @@ -107,21 +107,22 @@ def main() -> int: ) else DEFAULT_CONFIG checks = config['checks'] if args.message: - retval = commit.check_commit_msg(checks, args.commit_msg_file) + check_results.append(commit.check_commit_msg(checks, args.commit_msg_file)) if args.author_name: - retval = author.check_author(checks, "author_name") + check_results.append(author.check_author(checks, "author_name")) if args.author_email: - retval = author.check_author(checks, "author_email") + check_results.append(author.check_author(checks, "author_email")) if args.branch: - retval = branch.check_branch(checks) + check_results.append(branch.check_branch(checks)) if args.commit_signoff: - retval = commit.check_commit_signoff(checks) + check_results.append(commit.check_commit_signoff(checks)) if args.merge_base: - retval = branch.check_merge_base(checks) + check_results.append(branch.check_merge_base(checks)) if args.dry_run: - retval = PASS - return retval + return PASS + + return PASS if all(val == PASS for val in check_results) else FAIL if __name__ == '__main__': diff --git a/tests/main_test.py b/tests/main_test.py index 9d26ebe..ca77032 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -1,7 +1,7 @@ import sys import pytest from commit_check.main import main -from commit_check import DEFAULT_CONFIG +from commit_check import DEFAULT_CONFIG, PASS, FAIL CMD = "commit-check" @@ -115,3 +115,65 @@ def test_main_validate_config_ret_none(self, mocker): main() assert m_check_commit.call_count == 1 assert m_check_commit.call_args[0][0] == DEFAULT_CONFIG["checks"] + + @pytest.mark.parametrize( + "argv, message_result, branch_result, author_name_result, author_email_result, commit_signoff_result, merge_base_result, final_result", + [ + ([CMD, "--message"], PASS, PASS, PASS, PASS, PASS, PASS, PASS), + ([CMD, "--message"], FAIL, PASS, PASS, PASS, PASS, PASS, FAIL), + ([CMD, "--message", "--commit-signoff"], FAIL, PASS, PASS, PASS, PASS, PASS, FAIL,), + ([CMD, "--message", "--commit-signoff"], PASS, PASS, PASS, PASS, FAIL, PASS, FAIL,), + ([CMD, "--message", "--author-name", "--author-email"], PASS, PASS, PASS, PASS, PASS, PASS, PASS,), + ([CMD, "--message", "--author-name", "--author-email"], FAIL, PASS, PASS, PASS, PASS, PASS, FAIL,), + ([CMD, "--message", "--author-name", "--author-email"], PASS, PASS, FAIL, PASS, PASS, PASS, FAIL,), + ([CMD, "--message", "--author-name", "--author-email"], PASS, PASS, PASS, FAIL, PASS, PASS, FAIL,), + ([CMD, "--message", "--author-name", "--author-email"], PASS, PASS, FAIL, FAIL, PASS, PASS, FAIL,), + ([CMD, "--message", "--branch", "--author-name", "--author-email", "--commit-signoff", "--merge-base", ], PASS, PASS, PASS, PASS, PASS, PASS, PASS,), + ([CMD, "--message", "--branch", "--author-name", "--author-email", "--commit-signoff", "--merge-base", ], FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,), + ([CMD, "--message", "--branch", "--author-name", "--author-email", "--commit-signoff", "--merge-base", ], FAIL, PASS, PASS, PASS, PASS, PASS, FAIL,), + ([CMD, "--dry-run"], FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, PASS), + ], + ) + def test_main_multiple_checks( + self, + mocker, + argv, + message_result, + branch_result, + author_name_result, + author_email_result, + commit_signoff_result, + merge_base_result, + final_result, + ): + mocker.patch( + "commit_check.main.validate_config", + return_value={}, + ) + + mocker.patch( + "commit_check.commit.check_commit_msg", return_value=message_result + ) + mocker.patch( + "commit_check.commit.check_commit_signoff", + return_value=commit_signoff_result, + ) + + mocker.patch("commit_check.branch.check_branch", return_value=branch_result) + mocker.patch( + "commit_check.branch.check_merge_base", return_value=merge_base_result + ) + + # this is messy. why isn't this a private implementation detail with a + # public check_author_name and check_author email? + def author_side_effect(_, check_type: str) -> int: # type: ignore[return] + assert check_type in ("author_name", "author_email") + if check_type == "author_name": + return author_name_result + elif check_type == "author_email": + return author_email_result + + mocker.patch("commit_check.author.check_author", side_effect=author_side_effect) + + sys.argv = argv + assert main() == final_result From 99bcd12c1efe36b3fa7659fce797d8910ce963c2 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 3 Feb 2025 11:06:08 +0200 Subject: [PATCH 113/146] refactor: consider early return optimization for dry-run (#214) --- commit_check/main.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/commit_check/main.py b/commit_check/main.py index c6b8b32..6faa070 100644 --- a/commit_check/main.py +++ b/commit_check/main.py @@ -99,6 +99,10 @@ def main() -> int: """The main entrypoint of commit-check program.""" parser = get_parser() args = parser.parse_args() + + if args.dry_run: + return PASS + check_results: list[int] = [] with error_handler(): @@ -119,9 +123,6 @@ def main() -> int: if args.merge_base: check_results.append(branch.check_merge_base(checks)) - if args.dry_run: - return PASS - return PASS if all(val == PASS for val in check_results) else FAIL From 346cde88c30f49afadbd0464fa727188dd862fcb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 03:20:55 +0200 Subject: [PATCH 114/146] ci: pre-commit autoupdate (#215) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e1d96d8..3faaa2b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.9.3 + rev: v0.9.4 hooks: # Run the linter. - id: ruff @@ -29,11 +29,11 @@ repos: additional_dependencies: [types-PyYAML] exclude: ^testing/resources/ - repo: https://github.com/codespell-project/codespell - rev: v2.4.0 + rev: v2.4.1 hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.9.2 + rev: v0.9.3 hooks: - id: check-message # - id: check-branch # uncomment if you need. From 8e6590d0ba11d8e057f177445380b9ca6ac27c36 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 01:13:35 +0200 Subject: [PATCH 115/146] ci: pre-commit autoupdate (#216) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3faaa2b..2953fc4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,13 +17,13 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.9.4 + rev: v0.9.6 hooks: # Run the linter. - id: ruff args: [ --fix ] - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.14.1 + rev: v1.15.0 hooks: - id: mypy additional_dependencies: [types-PyYAML] From 224970d124fac4997565de732ef0d8e21e208dcc Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sun, 16 Feb 2025 21:00:19 +0800 Subject: [PATCH 116/146] feat: add .readthedocs.yaml (#218) * feat: add .readthedocs.yaml * ci: auto fixes from pre-commit.com hooks --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .readthedocs.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..9bfb5c2 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,17 @@ +# Read the Docs configuration file for Sphinx projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +sphinx: + builder: "dirhtml" + configuration: docs/conf.py + +# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - requirements: docs/requirements.txt From 41e0244a12031740d786af555b780e39c248d5b0 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sun, 16 Feb 2025 21:18:16 +0800 Subject: [PATCH 117/146] fix: update docs requirements.txt (#219) * fix: Update requirements.txt * ci: auto fixes from pre-commit.com hooks --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/requirements.txt b/docs/requirements.txt index d078f24..af718d9 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1 +1,3 @@ + +. sphinx-immaterial From a237cda9cd94d40cb8caee59b7aa878e4589b5c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Koh=C3=A1nyi=20R=C3=B3bert?= Date: Sun, 23 Feb 2025 18:00:11 +0100 Subject: [PATCH 118/146] fix: allow accented letters in author name (#221) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: allow accented letters in author name Allow accented letters (e.g. áéó, etc.) in an author's name. * fix: remove duplicate unicode regex range * fix: add broader regex range to .yml as well * fix: remove duplicate regex key --- .commit-check.yml | 2 +- commit_check/__init__.py | 2 +- tests/author_test.py | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.commit-check.yml b/.commit-check.yml index 10f8d39..ad339d0 100644 --- a/.commit-check.yml +++ b/.commit-check.yml @@ -14,7 +14,7 @@ checks: suggest: run command `git checkout -b type/branch_name` - check: author_name - regex: ^[A-Za-z ,.\'-]+$|.*(\[bot]) + regex: ^[A-Za-zÀ-ÖØ-öø-ÿ\u0100-\u017F\u0180-\u024F ,.\'-]+$|.*(\[bot]) error: The committer name seems invalid suggest: run command `git config user.name "Your Name"` diff --git a/commit_check/__init__.py b/commit_check/__init__.py index 61de524..521f68f 100644 --- a/commit_check/__init__.py +++ b/commit_check/__init__.py @@ -32,7 +32,7 @@ }, { 'check': 'author_name', - 'regex': r'^[A-Za-z ,.\'-]+$|.*(\[bot])', + 'regex': r'^[A-Za-zÀ-ÖØ-öø-ÿ\u0100-\u017F\u0180-\u024F ,.\'-]+$|.*(\[bot])', 'error': 'The committer name seems invalid', 'suggest': 'run command `git config user.name "Your Name"`', }, diff --git a/tests/author_test.py b/tests/author_test.py index 21f637d..8936223 100644 --- a/tests/author_test.py +++ b/tests/author_test.py @@ -9,6 +9,7 @@ class TestAuthor: class TestAuthorName: # used by get_commit_info mock fake_author_value_an = "fake_author_name" + fake_accented_author_value_an = "fáké_áúthór_námé" def test_check_author(self, mocker): # Must call get_commit_info, re.match. @@ -29,6 +30,25 @@ def test_check_author(self, mocker): assert m_get_commit_info.call_count == 1 assert m_re_match.call_count == 1 + def test_check_author_with_accented_letters(self, mocker): + # Must call get_commit_info, re.match. + checks = [{ + "check": "author_name", + "regex": "dummy_regex" + }] + m_get_commit_info = mocker.patch( + f"{LOCATION}.get_commit_info", + return_value=self.fake_accented_author_value_an + ) + m_re_match = mocker.patch( + "re.match", + return_value="fake_rematch_resp" + ) + retval = check_author(checks, "author_name") + assert retval == PASS + assert m_get_commit_info.call_count == 1 + assert m_re_match.call_count == 1 + def test_check_author_with_empty_checks(self, mocker): # Must NOT call get_commit_info, re.match. with `checks` param with length 0. checks = [] From 9f02b131369fe59a354b4eb6e2c898f8d13d3e90 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 01:50:27 +0800 Subject: [PATCH 119/146] ci: pre-commit autoupdate (#224) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.6 → v0.9.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.6...v0.9.7) - [github.com/commit-check/commit-check: v0.9.3 → v0.9.4](https://github.com/commit-check/commit-check/compare/v0.9.3...v0.9.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2953fc4..b2a8641 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.9.6 + rev: v0.9.7 hooks: # Run the linter. - id: ruff @@ -33,7 +33,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.9.3 + rev: v0.9.4 hooks: - id: check-message # - id: check-branch # uncomment if you need. From 436c0c1048d0e4a4fb097e98cf20bb20b6bd194a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 01:42:33 +0800 Subject: [PATCH 120/146] ci: pre-commit autoupdate (#225) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.7 → v0.9.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.7...v0.9.9) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b2a8641..67a0323 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.9.7 + rev: v0.9.9 hooks: # Run the linter. - id: ruff From bd71280ead000d9cf6b584f23136471a9cd59d4e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Mar 2025 01:35:10 +0800 Subject: [PATCH 121/146] ci: pre-commit autoupdate (#226) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.9 → v0.9.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.9...v0.9.10) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 67a0323..1bc27cb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.9.9 + rev: v0.9.10 hooks: # Run the linter. - id: ruff From 6d7b4052d50f7facf9fde26ec3936968cf208907 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 31 Mar 2025 01:05:06 +0800 Subject: [PATCH 122/146] chore: drop unsupported python version 3.8 (#229) --- .github/workflows/main.yml | 2 +- pyproject.toml | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9106468..6333198 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -53,7 +53,7 @@ jobs: strategy: fail-fast: false matrix: - py: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] + py: ['3.9', '3.10', '3.11', '3.12', '3.13'] os: ['windows-latest', 'ubuntu-24.04', 'macos-latest'] runs-on: ${{ matrix.os }} steps: diff --git a/pyproject.toml b/pyproject.toml index 2710ff6..3563062 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ license = {text = "MIT License"} authors = [ { name = "Xianpeng Shen", email = "xianpeng.shen@gmail.com" }, ] -requires-python = ">=3.8" +requires-python = ">=3.9" dependencies = ["pyyaml"] classifiers = [ # https://pypi.org/pypi?%3Aaction=list_classifiers @@ -20,8 +20,6 @@ classifiers = [ "Intended Audience :: Developers", "Natural Language :: English", "Operating System :: OS Independent", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", From 8ad15262527eb83d10fc2f59b257b69df0158fc7 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 31 Mar 2025 01:14:06 +0800 Subject: [PATCH 123/146] feat: adopt PEP639 (#228) --- .pre-commit-config.yaml | 2 +- pyproject.toml | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1bc27cb..a8263d3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.9.10 + rev: v0.11.2 hooks: # Run the linter. - id: ruff diff --git a/pyproject.toml b/pyproject.toml index 3563062..c84d181 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=61", "setuptools-scm"] +requires = ["setuptools>=77", "setuptools-scm"] build-backend = "setuptools.build_meta" [project] @@ -7,7 +7,7 @@ name = "commit-check" description = "Check commit message formatting, branch naming, commit author, email, and more." readme = "README.rst" keywords = ["commit conventions", "conventional commits", "conventional branch", "branch naming", "commit-check", "message", "lint message", "devops"] -license = {text = "MIT License"} +license = "MIT" authors = [ { name = "Xianpeng Shen", email = "xianpeng.shen@gmail.com" }, ] @@ -16,7 +16,6 @@ dependencies = ["pyyaml"] classifiers = [ # https://pypi.org/pypi?%3Aaction=list_classifiers "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: MIT License", "Intended Audience :: Developers", "Natural Language :: English", "Operating System :: OS Independent", From b3c05ead4eeaa153d6d1b37a49e0dd3bf2b48379 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 31 Mar 2025 01:19:45 +0800 Subject: [PATCH 124/146] chore: update pre-commit.ci autoupdate to quarterly (#230) --- .pre-commit-config.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a8263d3..cc6ee16 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,8 +1,10 @@ -# https://pre-commit.com/ +# https://pre-commit.ci/ ci: autofix_commit_msg: 'ci: auto fixes from pre-commit.com hooks' autoupdate_commit_msg: 'ci: pre-commit autoupdate' + autoupdate_schedule: quarterly +# https://pre-commit.com/ # prepare-commit-msg is used by hook id: check-message default_install_hook_types: [pre-commit, prepare-commit-msg] repos: From 656ca71a8c7f0dd19e1305c85e1a345c8054c3c0 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sun, 6 Apr 2025 20:47:24 +0300 Subject: [PATCH 125/146] docs: remove .readthedocs.yaml (#231) * docs: remove .readthedocs.yaml * chore: conf.py clean up --- .readthedocs.yaml | 17 ----------------- docs/conf.py | 5 ----- 2 files changed, 22 deletions(-) delete mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml deleted file mode 100644 index 9bfb5c2..0000000 --- a/.readthedocs.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# Read the Docs configuration file for Sphinx projects -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details -version: 2 - -build: - os: ubuntu-22.04 - tools: - python: "3.12" - -sphinx: - builder: "dirhtml" - configuration: docs/conf.py - -# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html -python: - install: - - requirements: docs/requirements.txt diff --git a/docs/conf.py b/docs/conf.py index 53d5b56..2f3e1d9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -25,11 +25,6 @@ "sphinx.ext.viewcode", ] -intersphinx_mapping = { - "python": ("https://docs.python.org/3", None), - "requests": ("https://requests.readthedocs.io/en/latest/", None), -} - autodoc_member_order = "bysource" templates_path = ["_templates"] From 742fc42d011930827a7fc2b9129a7ef7dc15ba6d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 21:20:01 +0300 Subject: [PATCH 126/146] ci: pre-commit autoupdate (#232) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cc6ee16..cf938ad 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.11.2 + rev: v0.11.4 hooks: # Run the linter. - id: ruff @@ -35,7 +35,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.9.4 + rev: v0.9.5 hooks: - id: check-message # - id: check-branch # uncomment if you need. From 0219eb33ad5099ab9459c52c876d9c24dc8e1bc1 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sun, 1 Jun 2025 19:30:04 +0300 Subject: [PATCH 127/146] chore: move deps from `requirements.txt` to `pyproject.toml` (#233) * chore: remove requirements.txt files * install nox * install nox * Apply suggestions from code review Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * update noxfile.py * update noxfile.py and pyproject.tom * fix pyproject.toml * move sphinx-autobuild into pyproject.toml --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 14 +++++++++++--- .gitpod.yml | 4 ++-- docs/requirements.txt | 3 --- noxfile.py | 14 +++----------- pyproject.toml | 5 +++++ requirements-dev.txt | 5 ----- 6 files changed, 21 insertions(+), 24 deletions(-) delete mode 100644 docs/requirements.txt delete mode 100644 requirements-dev.txt diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6333198..e470c14 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,11 @@ jobs: - uses: actions/setup-python@v5 with: python-version: '3.x' - - run: pip install -r requirements-dev.txt + + - name: Install nox + run: | + python -m pip install --upgrade pip + python -m pip install nox - name: Run pre-commit run: | @@ -63,7 +67,7 @@ jobs: python-version: ${{ matrix.py }} - run: | pip install --upgrade pip - pip install -r requirements-dev.txt + pip install .[dev] - name: Download wheel artifact uses: actions/download-artifact@v4 @@ -85,7 +89,11 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.10" - - run: pip install -r requirements-dev.txt + + - name: Install nox + run: | + python -m pip install --upgrade pip + python -m pip install nox - name: Build docs run: nox -s docs diff --git a/.gitpod.yml b/.gitpod.yml index 8123636..4f2f475 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -3,6 +3,6 @@ # and commit this file to your remote git repository to share the goodness with others. tasks: - - before: pip install --upgrade pip && pip install -r requirements-dev.txt + - before: pip install --upgrade pip init: pre-commit install - command: pip install -e . + command: pip install -e .[dev] diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index af718d9..0000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ - -. -sphinx-immaterial diff --git a/noxfile.py b/noxfile.py index 079df8a..50599af 100644 --- a/noxfile.py +++ b/noxfile.py @@ -4,11 +4,6 @@ nox.options.reuse_existing_virtualenvs = True nox.options.sessions = ["lint"] -REQUIREMENTS = { - "dev": "requirements-dev.txt", - "docs": "docs/requirements.txt", -} - # ----------------------------------------------------------------------------- # Development Commands # ----------------------------------------------------------------------------- @@ -54,8 +49,7 @@ def commit_check(session): @nox.session() def coverage(session): - session.install(".") - session.install("-r", REQUIREMENTS["dev"]) + session.install('.[test]') session.run("coverage", "run", "--source", "commit_check", "-m", "pytest") session.run("coverage", "report") session.run("coverage", "xml") @@ -63,13 +57,11 @@ def coverage(session): @nox.session() def docs(session): - session.install(".") - session.install("-r", REQUIREMENTS["docs"]) + session.install('.[docs]') session.run("sphinx-build", "-E", "-W", "-b", "html", "docs", "_build/html") @nox.session(name="docs-live") def docs_live(session): - session.install(".") - session.install("-r", REQUIREMENTS["docs"], "sphinx-autobuild") + session.install('.[docs]') session.run("sphinx-autobuild", "-b", "html", "docs", "_build/html") diff --git a/pyproject.toml b/pyproject.toml index c84d181..3f0759e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,11 @@ tracker = "https://github.com/commit-check/commit-check/issues" # ... other project metadata fields as specified in: # https://packaging.python.org/en/latest/specifications/declaring-project-metadata/ +[project.optional-dependencies] +dev = ['nox'] +test = ['coverage', 'pytest', 'pytest-mock'] +docs = ['sphinx-immaterial', 'sphinx-autobuild'] + [tool.setuptools] zip-safe = false packages = ["commit_check"] diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 120645f..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,5 +0,0 @@ -coverage -git+https://github.com/wntrblm/nox.git@main -pre-commit -pytest -pytest-mock From 309bc74baf7b3a0b38049d8af0ef601ad44cdad4 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Fri, 13 Jun 2025 11:02:48 +0300 Subject: [PATCH 128/146] Potential fix Workflow does not contain permissions (#234) Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e470c14..3163c6c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,8 @@ name: main +permissions: + contents: write + on: push: branches: From 53ea82057400fea2b90b53b9614ef305cedead57 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Fri, 13 Jun 2025 11:05:37 +0300 Subject: [PATCH 129/146] fix: potential fix workflow does not contain permissions (#235) Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/release-drafter.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index d25c13e..0b36c74 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -6,6 +6,10 @@ on: - "main" workflow_dispatch: +permissions: + contents: read + pull-requests: write + jobs: draft-release: uses: commit-check/.github/.github/workflows/release-drafter.yml@main From 634075918a736be7440fa612d018ad5360283459 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Fri, 13 Jun 2025 11:21:17 +0300 Subject: [PATCH 130/146] fix: potential fix workflow does not contain permissions (#236) Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/publish-image.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml index 39dd16e..9c148f6 100644 --- a/.github/workflows/publish-image.yml +++ b/.github/workflows/publish-image.yml @@ -1,5 +1,8 @@ name: publish image +permissions: + contents: read + on: push: paths: From 6cdeb1405270b21f3e7df33b730a5decf871bdbc Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Fri, 13 Jun 2025 11:31:31 +0300 Subject: [PATCH 131/146] fix: potential fix workflow does not contain permissions (#237) Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/labeler.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 52689d6..659f080 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -1,5 +1,9 @@ name: PR Autolabeler +permissions: + contents: read + pull-requests: write + on: # pull_request event is required for autolabeler pull_request: From 485e745ec7b7a675680b93cd62d2138d3f10e4f4 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Fri, 13 Jun 2025 11:33:54 +0300 Subject: [PATCH 132/146] fix: Potential fix Workflow does not contain permissions #235 --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 0b36c74..182ecec 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: permissions: - contents: read + contents: write pull-requests: write jobs: From 031950fa5b33d7832a553c2cf9db23b365ba8617 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sun, 22 Jun 2025 16:53:25 +0200 Subject: [PATCH 133/146] chore: update CODEOWNERS (#238) * chore: update CODEOWNERS * chore: update CODEOWNERS * fix: Update labeler.yml to fix permission issue * chore: Update CODEOWNERS --- .github/CODEOWNERS | 2 +- .github/workflows/labeler.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4f08a45..9861b85 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @shenxianpeng +* @commit-check/commit-check-maintain diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 659f080..13e989a 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -1,7 +1,7 @@ name: PR Autolabeler permissions: - contents: read + contents: write pull-requests: write on: From 9f8b78e98c1b9a6448f0f41ac608c085d9698fad Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Wed, 25 Jun 2025 10:01:14 +0300 Subject: [PATCH 134/146] chore: Update CODEOWNERS --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9861b85..37cffb1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @commit-check/commit-check-maintain +* @commit-check/developers From d87094260d660c645b3f0ddd91f55baae7e136eb Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Fri, 4 Jul 2025 03:37:00 +0300 Subject: [PATCH 135/146] docs: update README.rst (#239) --- README.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 2f19257..b9ac03a 100644 --- a/README.rst +++ b/README.rst @@ -42,15 +42,14 @@ Configuration Use Default Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~ -- If you don't set ``.commit-check.yml``, Commit Check will use the `default configuration `_. +- **Commit Check** uses a `default configuration `_ if you do not provide a ``.commit-check.yml`` file. -- The commit message will follow the rules of `Conventional Commits `_, - branch naming follow the rules of `Conventional Branch `_. +- The default configuration enforces commit message rules based on the `Conventional Commits `_ specification and branch naming rules based on the `Conventional Branch `_ convention. Use Custom Configuration ~~~~~~~~~~~~~~~~~~~~~~~~ -Create a config file ``.commit-check.yml`` under your repository's root directory, e.g., `.commit-check.yml `_ +To customize the behavior, create a config file ``.commit-check.yml`` under your repository's root directory, e.g., `.commit-check.yml `_ Usage ----- From dac2281855bf9a39202e766b7caaf58fb3fbe8e2 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 7 Jul 2025 01:05:33 +0300 Subject: [PATCH 136/146] fix: display a clear message when there are no commits (#244) * fix: check if there are commit in the current branch * fix: check if there are commit in the current branch * add output when no commits found * docs: change output when no commits found * test: add more test for util --- .pre-commit-config.yaml | 4 +-- commit_check/util.py | 17 +++++++++++ tests/util_test.py | 66 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cf938ad..d289da2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,5 +41,5 @@ repos: # - id: check-branch # uncomment if you need. - id: check-author-name # uncomment if you need. - id: check-author-email # uncomment if you need. - # - id: commit-signoff # uncomment if you need. - # - id: check-merge-base # requires download all git history + # - id: check-commit-signoff # uncomment if you need. + # - id: check-merge-base # requires download all git history diff --git a/commit_check/util.py b/commit_check/util.py index a63d6c1..52b4eaa 100644 --- a/commit_check/util.py +++ b/commit_check/util.py @@ -29,6 +29,21 @@ def get_branch_name() -> str: return branch_name.strip() +def has_commits() -> bool: + """Check if there are any commits in the current branch. + :returns: `True` if there are commits, `False` otherwise. + """ + try: + subprocess.run( + ["git", "rev-parse", "--verify", "HEAD"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True + ) + return True + except subprocess.CalledProcessError: + return False + def get_commit_info(format_string: str, sha: str = "HEAD") -> str: """Get latest commits information :param format_string: could be @@ -41,6 +56,8 @@ def get_commit_info(format_string: str, sha: str = "HEAD") -> str: :returns: A `str`. """ + if has_commits() is False: + return 'Repo has no commits yet.' try: commands = [ 'git', 'log', '-n', '1', f"--pretty=format:%{format_string}", f"{sha}", diff --git a/tests/util_test.py b/tests/util_test.py index 42870ea..e42ba24 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -1,6 +1,7 @@ import pytest import subprocess from commit_check.util import get_branch_name +from commit_check.util import has_commits from commit_check.util import git_merge_base from commit_check.util import get_commit_info from commit_check.util import cmd_output @@ -46,6 +47,43 @@ def test_get_branch_name_with_exception(self, mocker): ] assert retval == "" + class TestHasCommits: + def test_has_commits_true(self, mocker): + # Must return True when git rev-parse HEAD succeeds + m_subprocess_run = mocker.patch( + "subprocess.run", + return_value=None + ) + retval = has_commits() + assert m_subprocess_run.call_count == 1 + assert m_subprocess_run.call_args[0][0] == [ + "git", "rev-parse", "--verify", "HEAD" + ] + assert m_subprocess_run.call_args[1] == { + 'stdout': subprocess.DEVNULL, + 'stderr': subprocess.DEVNULL, + 'check': True + } + assert retval is True + + def test_has_commits_false(self, mocker): + # Must return False when git rev-parse HEAD fails + m_subprocess_run = mocker.patch( + "subprocess.run", + side_effect=subprocess.CalledProcessError(128, "git rev-parse") + ) + retval = has_commits() + assert m_subprocess_run.call_count == 1 + assert m_subprocess_run.call_args[0][0] == [ + "git", "rev-parse", "--verify", "HEAD" + ] + assert m_subprocess_run.call_args[1] == { + 'stdout': subprocess.DEVNULL, + 'stderr': subprocess.DEVNULL, + 'check': True + } + assert retval is False + class TestGitMergeBase: @pytest.mark.parametrize("returncode,expected", [ (0, 0), # ancestor exists @@ -78,20 +116,45 @@ class TestGetCommitInfo: ] ) def test_get_commit_info(self, mocker, format_string): - # Must call get_commit_info with given argument. + # Must call get_commit_info with given argument when there are commits. + m_has_commits = mocker.patch( + "commit_check.util.has_commits", + return_value=True + ) m_cmd_output = mocker.patch( "commit_check.util.cmd_output", return_value=" fake commit message " ) retval = get_commit_info(format_string) + assert m_has_commits.call_count == 1 assert m_cmd_output.call_count == 1 assert m_cmd_output.call_args[0][0] == [ "git", "log", "-n", "1", f"--pretty=format:%{format_string}", "HEAD" ] assert retval == " fake commit message " + def test_get_commit_info_no_commits(self, mocker): + # Must return 'Repo has no commits yet.' when there are no commits. + m_has_commits = mocker.patch( + "commit_check.util.has_commits", + return_value=False + ) + m_cmd_output = mocker.patch( + "commit_check.util.cmd_output", + return_value=" fake commit message " + ) + format_string = "s" + retval = get_commit_info(format_string) + assert m_has_commits.call_count == 1 + assert m_cmd_output.call_count == 0 # Should not call cmd_output + assert retval == "Repo has no commits yet." + def test_get_commit_info_with_exception(self, mocker): # Must return empty string when exception raises in cmd_output. + m_has_commits = mocker.patch( + "commit_check.util.has_commits", + return_value=True + ) m_cmd_output = mocker.patch( "commit_check.util.cmd_output", return_value=" fake commit message " @@ -104,6 +167,7 @@ def test_get_commit_info_with_exception(self, mocker): ) format_string = "s" retval = get_commit_info(format_string) + assert m_has_commits.call_count == 1 assert m_cmd_output.call_count == 1 assert m_cmd_output.call_args[0][0] == [ "git", "log", "-n", "1", f"--pretty=format:%{format_string}", "HEAD" From 5a2b5e5c6c2eee858255600bc0e5a32e8d150a89 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 7 Jul 2025 12:30:44 +0300 Subject: [PATCH 137/146] feat: support codspeed (#245) * feat: support codspeed * Potential fix for code scanning alert no. 46: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/codspeed.yml | 44 ++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- tests/author_test.py | 12 ++++++++++ tests/branch_test.py | 11 ++++++++- tests/commit_test.py | 12 ++++++++++ tests/error_test.py | 5 ++++ tests/main_test.py | 5 ++++ tests/util_test.py | 17 +++++++++++++ 8 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/codspeed.yml diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml new file mode 100644 index 0000000..f4bbb59 --- /dev/null +++ b/.github/workflows/codspeed.yml @@ -0,0 +1,44 @@ +name: CodSpeed + +permissions: + contents: read + +on: + push: + branches: + - "main" + paths: + - "commit_check/**" + - "tests/**" + - ".github/workflows/codspeed.yml" + - "pyproject.toml" + pull_request: + branches: + - "main" + paths: + - "commit_check/**" + - "tests/**" + - ".github/workflows/codspeed.yml" + - "pyproject.toml" + # `workflow_dispatch` allows CodSpeed to trigger backtest + # performance analysis in order to generate initial data. + workflow_dispatch: + +jobs: + benchmarks: + name: Run benchmarks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install dependencies + run: pip install -e .[test] + + - name: Run benchmarks + uses: CodSpeedHQ/action@v3 + with: + token: ${{ secrets.CODSPEED_TOKEN }} + run: pytest tests/ --codspeed diff --git a/pyproject.toml b/pyproject.toml index 3f0759e..8c0db4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ tracker = "https://github.com/commit-check/commit-check/issues" [project.optional-dependencies] dev = ['nox'] -test = ['coverage', 'pytest', 'pytest-mock'] +test = ['coverage', 'pytest', 'pytest-mock', 'pytest-codspeed'] docs = ['sphinx-immaterial', 'sphinx-autobuild'] [tool.setuptools] diff --git a/tests/author_test.py b/tests/author_test.py index 8936223..fcc4939 100644 --- a/tests/author_test.py +++ b/tests/author_test.py @@ -1,3 +1,4 @@ +import pytest from commit_check import PASS, FAIL from commit_check.author import check_author @@ -11,6 +12,7 @@ class TestAuthorName: fake_author_value_an = "fake_author_name" fake_accented_author_value_an = "fáké_áúthór_námé" + @pytest.mark.benchmark def test_check_author(self, mocker): # Must call get_commit_info, re.match. checks = [{ @@ -30,6 +32,7 @@ def test_check_author(self, mocker): assert m_get_commit_info.call_count == 1 assert m_re_match.call_count == 1 + @pytest.mark.benchmark def test_check_author_with_accented_letters(self, mocker): # Must call get_commit_info, re.match. checks = [{ @@ -49,6 +52,7 @@ def test_check_author_with_accented_letters(self, mocker): assert m_get_commit_info.call_count == 1 assert m_re_match.call_count == 1 + @pytest.mark.benchmark def test_check_author_with_empty_checks(self, mocker): # Must NOT call get_commit_info, re.match. with `checks` param with length 0. checks = [] @@ -65,6 +69,7 @@ def test_check_author_with_empty_checks(self, mocker): assert m_get_commit_info.call_count == 0 assert m_re_match.call_count == 0 + @pytest.mark.benchmark def test_check_author_with_different_check(self, mocker): # Must NOT call get_commit_info, re.match with not `author_name`. checks = [{ @@ -84,6 +89,7 @@ def test_check_author_with_different_check(self, mocker): assert m_get_commit_info.call_count == 0 assert m_re_match.call_count == 0 + @pytest.mark.benchmark def test_check_author_with_len0_regex(self, mocker, capfd): # Must NOT call get_commit_info, re.match with `regex` with length 0. checks = [ @@ -107,6 +113,7 @@ def test_check_author_with_len0_regex(self, mocker, capfd): out, _ = capfd.readouterr() assert "Not found regex for author_name." in out + @pytest.mark.benchmark def test_check_author_with_result_none(self, mocker): # Must call print_error_message, print_suggestion when re.match returns NONE. checks = [{ @@ -140,6 +147,7 @@ class TestAuthorEmail: # used by get_commit_info mock fake_author_value_ae = "fake_author_email" + @pytest.mark.benchmark def test_check_author(self, mocker): # Must call get_commit_info, re.match. checks = [{ @@ -159,6 +167,7 @@ def test_check_author(self, mocker): assert m_get_commit_info.call_count == 1 assert m_re_match.call_count == 1 + @pytest.mark.benchmark def test_check_author_with_empty_checks(self, mocker): # Must NOT call get_commit_info, re.match. with `checks` param with length 0. checks = [] @@ -175,6 +184,7 @@ def test_check_author_with_empty_checks(self, mocker): assert m_get_commit_info.call_count == 0 assert m_re_match.call_count == 0 + @pytest.mark.benchmark def test_check_author_with_different_check(self, mocker): # Must NOT call get_commit_info, re.match with not `author_email`. checks = [{ @@ -194,6 +204,7 @@ def test_check_author_with_different_check(self, mocker): assert m_get_commit_info.call_count == 0 assert m_re_match.call_count == 0 + @pytest.mark.benchmark def test_check_author_with_len0_regex(self, mocker, capfd): # Must NOT call get_commit_info, re.match with `regex` with length 0. checks = [ @@ -217,6 +228,7 @@ def test_check_author_with_len0_regex(self, mocker, capfd): out, _ = capfd.readouterr() assert "Not found regex for author_email." in out + @pytest.mark.benchmark def test_check_author_with_result_none(self, mocker): # Must call print_error_message, print_suggestion when re.match returns NONE. checks = [{ diff --git a/tests/branch_test.py b/tests/branch_test.py index 083c5bd..34e3a3b 100644 --- a/tests/branch_test.py +++ b/tests/branch_test.py @@ -1,3 +1,4 @@ +import pytest from commit_check import PASS, FAIL from commit_check.branch import check_branch, check_merge_base @@ -7,6 +8,7 @@ class TestCheckBranch: + @pytest.mark.benchmark def test_check_branch(self, mocker): # Must call get_branch_name, re.match at once. checks = [{ @@ -26,6 +28,7 @@ def test_check_branch(self, mocker): assert m_get_branch_name.call_count == 1 assert m_re_match.call_count == 1 + @pytest.mark.benchmark def test_check_branch_with_empty_checks(self, mocker): # Must NOT call get_branch_name, re.match with `checks` param with length 0. checks = [] @@ -42,6 +45,7 @@ def test_check_branch_with_empty_checks(self, mocker): assert m_get_branch_name.call_count == 0 assert m_re_match.call_count == 0 + @pytest.mark.benchmark def test_check_branch_with_different_check(self, mocker): # Must NOT call get_branch_name, re.match with not `branch`. checks = [{ @@ -61,6 +65,7 @@ def test_check_branch_with_different_check(self, mocker): assert m_get_branch_name.call_count == 0 assert m_re_match.call_count == 0 + @pytest.mark.benchmark def test_check_branch_with_len0_regex(self, mocker, capfd): # Must NOT call get_branch_name, re.match with `regex` with length 0. checks = [ @@ -84,6 +89,7 @@ def test_check_branch_with_len0_regex(self, mocker, capfd): out, _ = capfd.readouterr() assert "Not found regex for branch naming." in out + @pytest.mark.benchmark def test_check_branch_with_result_none(self, mocker): # Must call print_error_message, print_suggestion when re.match returns NONE. checks = [{ @@ -115,6 +121,7 @@ def test_check_branch_with_result_none(self, mocker): class TestCheckMergeBase: + @pytest.mark.benchmark def test_check_merge_base_with_empty_checks(self, mocker): checks = [] m_check_merge = mocker.patch(f"{LOCATION}.check_merge_base") @@ -122,7 +129,7 @@ def test_check_merge_base_with_empty_checks(self, mocker): assert retval == PASS assert m_check_merge.call_count == 0 - + @pytest.mark.benchmark def test_check_merge_base_with_empty_regex(self, mocker): checks = [{ "check": "merge_base", @@ -133,6 +140,7 @@ def test_check_merge_base_with_empty_regex(self, mocker): assert retval == PASS assert m_check_merge.call_count == 0 + @pytest.mark.benchmark def test_check_merge_base_with_different_check(self, mocker): checks = [{ "check": "branch", @@ -143,6 +151,7 @@ def test_check_merge_base_with_different_check(self, mocker): assert retval == PASS assert m_check_merge.call_count == 0 + @pytest.mark.benchmark def test_check_merge_base_fail_with_messages(self, mocker, capfd): checks = [{ "check": "merge_base", diff --git a/tests/commit_test.py b/tests/commit_test.py index a458636..c733968 100644 --- a/tests/commit_test.py +++ b/tests/commit_test.py @@ -1,3 +1,4 @@ +import pytest from commit_check import PASS, FAIL from commit_check.commit import check_commit_msg, get_default_commit_msg_file, read_commit_msg, check_commit_signoff @@ -9,11 +10,13 @@ MSG_FILE = '.git/COMMIT_EDITMSG' +@pytest.mark.benchmark def test_get_default_commit_msg_file(mocker): retval = get_default_commit_msg_file() assert retval == ".git/COMMIT_EDITMSG" +@pytest.mark.benchmark def test_read_commit_msg_from_existing_file(tmp_path): # Create a temporary file with a known content commit_msg_content = "Test commit message content." @@ -24,12 +27,14 @@ def test_read_commit_msg_from_existing_file(tmp_path): assert result == commit_msg_content +@pytest.mark.benchmark def test_read_commit_msg_file_not_found(mocker): m_commits_info = mocker.patch('commit_check.util.get_commit_info', return_value='mocked_commits_info') read_commit_msg("non_existent_file.txt") assert m_commits_info.call_count == 0 +@pytest.mark.benchmark def test_check_commit_msg_no_commit_msg_file(mocker): mock_get_default_commit_msg_file = mocker.patch( "commit_check.commit.get_default_commit_msg_file", @@ -49,6 +54,7 @@ def test_check_commit_msg_no_commit_msg_file(mocker): assert result == 0 +@pytest.mark.benchmark def test_check_commit_with_empty_checks(mocker): checks = [] m_re_match = mocker.patch( @@ -60,6 +66,7 @@ def test_check_commit_with_empty_checks(mocker): assert m_re_match.call_count == 0 +@pytest.mark.benchmark def test_check_commit_with_different_check(mocker): checks = [{ "check": "branch", @@ -74,6 +81,7 @@ def test_check_commit_with_different_check(mocker): assert m_re_match.call_count == 0 +@pytest.mark.benchmark def test_check_commit_with_len0_regex(mocker, capfd): checks = [ { @@ -92,6 +100,7 @@ def test_check_commit_with_len0_regex(mocker, capfd): assert "Not found regex for commit message." in out +@pytest.mark.benchmark def test_check_commit_with_result_none(mocker): checks = [{ "check": "message", @@ -116,6 +125,7 @@ def test_check_commit_with_result_none(mocker): assert m_print_suggestion.call_count == 1 +@pytest.mark.benchmark def test_check_commit_signoff(mocker): checks = [{ "check": "commit_signoff", @@ -140,6 +150,7 @@ def test_check_commit_signoff(mocker): assert m_print_suggestion.call_count == 1 +@pytest.mark.benchmark def test_check_commit_signoff_with_empty_regex(mocker): checks = [{ "check": "commit_signoff", @@ -156,6 +167,7 @@ def test_check_commit_signoff_with_empty_regex(mocker): assert m_re_match.call_count == 0 +@pytest.mark.benchmark def test_check_commit_signoff_with_empty_checks(mocker): checks = [] m_re_match = mocker.patch( diff --git a/tests/error_test.py b/tests/error_test.py index d0a2880..ab9e948 100644 --- a/tests/error_test.py +++ b/tests/error_test.py @@ -3,6 +3,7 @@ from commit_check.error import error_handler, log_and_exit +@pytest.mark.benchmark def test_error_handler_RuntimeError(): with pytest.raises(SystemExit) as exit_info: with error_handler(): @@ -10,6 +11,7 @@ def test_error_handler_RuntimeError(): assert exit_info.value.code == 1 +@pytest.mark.benchmark def test_error_handler_KeyboardInterrupt(): with pytest.raises(SystemExit) as exit_info: with error_handler(): @@ -17,6 +19,7 @@ def test_error_handler_KeyboardInterrupt(): assert exit_info.value.code == 130 +@pytest.mark.benchmark def test_error_handler_unexpected_error(): with pytest.raises(SystemExit) as exit_info: with error_handler(): @@ -24,6 +27,7 @@ def test_error_handler_unexpected_error(): assert exit_info.value.code == 3 +@pytest.mark.benchmark def test_error_handler_cannot_access(mocker): with pytest.raises(SystemExit): store_dir = "/fake/commit-check" @@ -50,6 +54,7 @@ def test_error_handler_cannot_access(mocker): mock_open().write.assert_any_call(f"Failed to write to log at {log_path}\n") +@pytest.mark.benchmark @pytest.mark.xfail def test_log_and_exit(monkeypatch): monkeypatch.setenv("COMMIT_CHECK_HOME", "") diff --git a/tests/main_test.py b/tests/main_test.py index ca77032..c232efd 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -7,6 +7,7 @@ class TestMain: + @pytest.mark.benchmark @pytest.mark.parametrize("argv, check_commit_call_count, check_branch_call_count, check_author_call_count, check_commit_signoff_call_count, check_merge_base_call_count", [ ([CMD, "--message"], 1, 0, 0, 0, 0), ([CMD, "--branch"], 0, 1, 0, 0, 0), @@ -53,6 +54,7 @@ def test_main( assert m_check_commit_signoff.call_count == check_commit_signoff_call_count assert m_check_merge_base.call_count == check_merge_base_call_count + @pytest.mark.benchmark def test_main_help(self, mocker, capfd): mocker.patch( "commit_check.main.validate_config", @@ -78,6 +80,7 @@ def test_main_help(self, mocker, capfd): stdout, _ = capfd.readouterr() assert "usage: " in stdout + @pytest.mark.benchmark def test_main_version(self, mocker): mocker.patch( "commit_check.main.validate_config", @@ -101,6 +104,7 @@ def test_main_version(self, mocker): assert m_check_commit_signoff.call_count == 0 assert m_check_merge_base.call_count == 0 + @pytest.mark.benchmark def test_main_validate_config_ret_none(self, mocker): mocker.patch( "commit_check.main.validate_config", @@ -116,6 +120,7 @@ def test_main_validate_config_ret_none(self, mocker): assert m_check_commit.call_count == 1 assert m_check_commit.call_args[0][0] == DEFAULT_CONFIG["checks"] + @pytest.mark.benchmark @pytest.mark.parametrize( "argv, message_result, branch_result, author_name_result, author_email_result, commit_signoff_result, merge_base_result, final_result", [ diff --git a/tests/util_test.py b/tests/util_test.py index e42ba24..c426831 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -15,6 +15,7 @@ class TestUtil: class TestGetBranchName: + @pytest.mark.benchmark def test_get_branch_name(self, mocker): # Must call cmd_output with given argument. m_cmd_output = mocker.patch( @@ -28,6 +29,7 @@ def test_get_branch_name(self, mocker): ] assert retval == "fake_branch_name" + @pytest.mark.benchmark def test_get_branch_name_with_exception(self, mocker): # Must return empty string when exception raises in cmd_output. m_cmd_output = mocker.patch( @@ -48,6 +50,7 @@ def test_get_branch_name_with_exception(self, mocker): assert retval == "" class TestHasCommits: + @pytest.mark.benchmark def test_has_commits_true(self, mocker): # Must return True when git rev-parse HEAD succeeds m_subprocess_run = mocker.patch( @@ -66,6 +69,7 @@ def test_has_commits_true(self, mocker): } assert retval is True + @pytest.mark.benchmark def test_has_commits_false(self, mocker): # Must return False when git rev-parse HEAD fails m_subprocess_run = mocker.patch( @@ -85,6 +89,7 @@ def test_has_commits_false(self, mocker): assert retval is False class TestGitMergeBase: + @pytest.mark.benchmark @pytest.mark.parametrize("returncode,expected", [ (0, 0), # ancestor exists (1, 1), # no ancestor @@ -109,6 +114,7 @@ def test_git_merge_base(self, mocker, returncode, expected): assert result == expected class TestGetCommitInfo: + @pytest.mark.benchmark @pytest.mark.parametrize("format_string", [ ("s"), ("an"), @@ -133,6 +139,7 @@ def test_get_commit_info(self, mocker, format_string): ] assert retval == " fake commit message " + @pytest.mark.benchmark def test_get_commit_info_no_commits(self, mocker): # Must return 'Repo has no commits yet.' when there are no commits. m_has_commits = mocker.patch( @@ -149,6 +156,7 @@ def test_get_commit_info_no_commits(self, mocker): assert m_cmd_output.call_count == 0 # Should not call cmd_output assert retval == "Repo has no commits yet." + @pytest.mark.benchmark def test_get_commit_info_with_exception(self, mocker): # Must return empty string when exception raises in cmd_output. m_has_commits = mocker.patch( @@ -182,6 +190,7 @@ def __init__(self, returncode, stdout, stderr): self.stdout = stdout self.stderr = stderr + @pytest.mark.benchmark def test_cmd_output(self, mocker): # Must subprocess.run with given argument. m_subprocess_run = mocker.patch( @@ -192,6 +201,7 @@ def test_cmd_output(self, mocker): assert m_subprocess_run.call_count == 1 assert retval == "ok" + @pytest.mark.benchmark @pytest.mark.parametrize("returncode, stdout, stderr", [ (1, "ok", "err"), (0, None, "err"), @@ -216,6 +226,7 @@ def test_cmd_output_err(self, mocker, returncode, stdout, stderr): "stdout": PIPE } + @pytest.mark.benchmark @pytest.mark.parametrize("returncode, stdout, stderr", [ (1, "ok", ""), (0, None, ""), @@ -241,6 +252,7 @@ def test_cmd_output_err_with_len0_stderr(self, mocker, returncode, stdout, stder } class TestValidateConfig: + @pytest.mark.benchmark def test_validate_config(self, mocker): # Must call yaml.safe_load. mocker.patch("builtins.open") @@ -253,6 +265,7 @@ def test_validate_config(self, mocker): assert m_yaml_safe_load.call_count == 1 assert retval == dummy_resp + @pytest.mark.benchmark def test_validate_config_file_not_found(self, mocker): # Must return empty dictionary when FileNotFoundError raises in built-in open. mocker.patch("builtins.open").side_effect = FileNotFoundError @@ -262,6 +275,7 @@ def test_validate_config_file_not_found(self, mocker): assert retval == {} class TestPrintErrorMessage: + @pytest.mark.benchmark def test_print_error_header(self, capfd): # Must print on stdout with given argument. print_error_header() @@ -269,6 +283,7 @@ def test_print_error_header(self, capfd): assert "Commit rejected by Commit-Check" in stdout assert "Commit rejected." in stdout + @pytest.mark.benchmark @pytest.mark.parametrize("check_type, type_failed_msg", [ ("message", "check failed =>"), ("branch", "check failed =>"), @@ -294,12 +309,14 @@ def test_print_error_message(self, capfd, check_type, type_failed_msg): assert dummy_error in stdout class TestPrintSuggestion: + @pytest.mark.benchmark def test_print_suggestion(self, capfd): # Must print on stdout with given argument. print_suggestion("dummy suggest") stdout, _ = capfd.readouterr() assert "Suggest:" in stdout + @pytest.mark.benchmark def test_print_suggestion_exit1(self, capfd): # Must exit with 1 when "" passed with pytest.raises(SystemExit) as e: From 9ac3f4ce141c8efd33b4a3353755ace05c16a04a Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 7 Jul 2025 13:59:32 +0300 Subject: [PATCH 138/146] chore: delete .github/ISSUE_TEMPLATE/config.yml (#246) --- .github/ISSUE_TEMPLATE/config.yml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 375a8f2..0000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,8 +0,0 @@ -# Documentation for this file can be found at: -# https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository - -blank_issues_enabled: false -contact_links: - - name: "(maintainers only) Blank issue" - url: https://github.com/commit-check/commit-check/issues/new/ - about: For maintainers only. From 54738e64db30c0ea54bc077ef6e524637c841049 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 21:28:24 +0300 Subject: [PATCH 139/146] ci: pre-commit autoupdate (#248) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d289da2..8f6f962 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,13 +19,13 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.11.4 + rev: v0.12.2 hooks: # Run the linter. - id: ruff args: [ --fix ] - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.15.0 + rev: v1.16.1 hooks: - id: mypy additional_dependencies: [types-PyYAML] @@ -35,7 +35,7 @@ repos: hooks: - id: codespell - repo: https://github.com/commit-check/commit-check - rev: v0.9.5 + rev: v0.9.8 hooks: - id: check-message # - id: check-branch # uncomment if you need. From cf9d2454133417b01c155ffb4ba30648911d3ea0 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Wed, 9 Jul 2025 23:55:30 +0300 Subject: [PATCH 140/146] fix: use `git branch --show-current` to get branch name (#252) * fix: use git branch --show-current to get branch name * fix: set branch name to HEAD if empty --- commit_check/util.py | 5 +++-- tests/util_test.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/commit_check/util.py b/commit_check/util.py index 52b4eaa..fe8211f 100644 --- a/commit_check/util.py +++ b/commit_check/util.py @@ -22,8 +22,9 @@ def get_branch_name() -> str: :returns: A `str` describing the current branch name. """ try: - commands = ['git', 'rev-parse', '--abbrev-ref', 'HEAD'] - branch_name = cmd_output(commands) + # Git 2.22 and above supports `git branch --show-current` + commands = ['git', 'branch', '--show-current'] + branch_name = cmd_output(commands) or "HEAD" except CalledProcessError: branch_name = '' return branch_name.strip() diff --git a/tests/util_test.py b/tests/util_test.py index c426831..a9d9f51 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -25,7 +25,7 @@ def test_get_branch_name(self, mocker): retval = get_branch_name() assert m_cmd_output.call_count == 1 assert m_cmd_output.call_args[0][0] == [ - "git", "rev-parse", "--abbrev-ref", "HEAD" + "git", "branch", "--show-current" ] assert retval == "fake_branch_name" @@ -45,7 +45,7 @@ def test_get_branch_name_with_exception(self, mocker): retval = get_branch_name() assert m_cmd_output.call_count == 1 assert m_cmd_output.call_args[0][0] == [ - "git", "rev-parse", "--abbrev-ref", "HEAD" + "git", "branch", "--show-current" ] assert retval == "" From 55b000f5992da397487eacc5bbf39bf53d94fd5f Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Thu, 10 Jul 2025 01:08:48 +0300 Subject: [PATCH 141/146] fix: make sure git repo has commit before checking (#253) * fix: make sure git repo has commit before checking * chore: remove print * chore: add # pragma: no cover * chore: add # pragma: no cover --- commit_check/author.py | 5 ++++- commit_check/branch.py | 5 ++++- commit_check/commit.py | 9 ++++++++- commit_check/util.py | 2 -- tests/util_test.py | 15 ++++++--------- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/commit_check/author.py b/commit_check/author.py index a68397e..e3cfd20 100644 --- a/commit_check/author.py +++ b/commit_check/author.py @@ -1,10 +1,13 @@ """Check git author name and email""" import re from commit_check import YELLOW, RESET_COLOR, PASS, FAIL -from commit_check.util import get_commit_info, print_error_header, print_error_message, print_suggestion +from commit_check.util import get_commit_info, has_commits, print_error_header, print_error_message, print_suggestion def check_author(checks: list, check_type: str) -> int: + if has_commits() is False: + return PASS # pragma: no cover + for check in checks: if check['check'] == check_type: if check['regex'] == "": diff --git a/commit_check/branch.py b/commit_check/branch.py index 1cc8a35..b7446cc 100644 --- a/commit_check/branch.py +++ b/commit_check/branch.py @@ -1,7 +1,7 @@ """Check git branch naming convention.""" import re from commit_check import YELLOW, RESET_COLOR, PASS, FAIL -from commit_check.util import get_branch_name, git_merge_base, print_error_header, print_error_message, print_suggestion +from commit_check.util import get_branch_name, git_merge_base, print_error_header, print_error_message, print_suggestion, has_commits def check_branch(checks: list) -> int: @@ -33,6 +33,9 @@ def check_merge_base(checks: list) -> int: :returns PASS(0) if merge base check succeeds, FAIL(1) otherwise """ + if has_commits() is False: + return PASS # pragma: no cover + for check in checks: if check['check'] == 'merge_base': if check['regex'] == "": diff --git a/commit_check/commit.py b/commit_check/commit.py index 60b8d2f..ac1c63a 100644 --- a/commit_check/commit.py +++ b/commit_check/commit.py @@ -2,7 +2,7 @@ import re from pathlib import PurePath from commit_check import YELLOW, RESET_COLOR, PASS, FAIL -from commit_check.util import cmd_output, get_commit_info, print_error_header, print_error_message, print_suggestion +from commit_check.util import cmd_output, get_commit_info, print_error_header, print_error_message, print_suggestion, has_commits def get_default_commit_msg_file() -> str: @@ -22,6 +22,10 @@ def read_commit_msg(commit_msg_file) -> str: def check_commit_msg(checks: list, commit_msg_file: str = "") -> int: + """Check commit message against the provided checks.""" + if has_commits() is False: + return PASS # pragma: no cover + if commit_msg_file is None or commit_msg_file == "": commit_msg_file = get_default_commit_msg_file() @@ -51,6 +55,9 @@ def check_commit_msg(checks: list, commit_msg_file: str = "") -> int: def check_commit_signoff(checks: list, commit_msg_file: str = "") -> int: + if has_commits() is False: + return PASS # pragma: no cover + if commit_msg_file is None or commit_msg_file == "": commit_msg_file = get_default_commit_msg_file() diff --git a/commit_check/util.py b/commit_check/util.py index fe8211f..6d3c33b 100644 --- a/commit_check/util.py +++ b/commit_check/util.py @@ -57,8 +57,6 @@ def get_commit_info(format_string: str, sha: str = "HEAD") -> str: :returns: A `str`. """ - if has_commits() is False: - return 'Repo has no commits yet.' try: commands = [ 'git', 'log', '-n', '1', f"--pretty=format:%{format_string}", f"{sha}", diff --git a/tests/util_test.py b/tests/util_test.py index a9d9f51..8937005 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -123,7 +123,7 @@ class TestGetCommitInfo: ) def test_get_commit_info(self, mocker, format_string): # Must call get_commit_info with given argument when there are commits. - m_has_commits = mocker.patch( + mocker.patch( "commit_check.util.has_commits", return_value=True ) @@ -132,7 +132,6 @@ def test_get_commit_info(self, mocker, format_string): return_value=" fake commit message " ) retval = get_commit_info(format_string) - assert m_has_commits.call_count == 1 assert m_cmd_output.call_count == 1 assert m_cmd_output.call_args[0][0] == [ "git", "log", "-n", "1", f"--pretty=format:%{format_string}", "HEAD" @@ -142,24 +141,23 @@ def test_get_commit_info(self, mocker, format_string): @pytest.mark.benchmark def test_get_commit_info_no_commits(self, mocker): # Must return 'Repo has no commits yet.' when there are no commits. - m_has_commits = mocker.patch( + mocker.patch( "commit_check.util.has_commits", return_value=False ) - m_cmd_output = mocker.patch( + mocker.patch( "commit_check.util.cmd_output", return_value=" fake commit message " ) format_string = "s" retval = get_commit_info(format_string) - assert m_has_commits.call_count == 1 - assert m_cmd_output.call_count == 0 # Should not call cmd_output - assert retval == "Repo has no commits yet." + assert retval == " fake commit message " + @pytest.mark.benchmark def test_get_commit_info_with_exception(self, mocker): # Must return empty string when exception raises in cmd_output. - m_has_commits = mocker.patch( + mocker.patch( "commit_check.util.has_commits", return_value=True ) @@ -175,7 +173,6 @@ def test_get_commit_info_with_exception(self, mocker): ) format_string = "s" retval = get_commit_info(format_string) - assert m_has_commits.call_count == 1 assert m_cmd_output.call_count == 1 assert m_cmd_output.call_args[0][0] == [ "git", "log", "-n", "1", f"--pretty=format:%{format_string}", "HEAD" From 9d219e981ec71a9b5865dfa7539609d1384ee48d Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Thu, 10 Jul 2025 01:49:31 +0300 Subject: [PATCH 142/146] fix: add package write permission (#255) --- .github/workflows/publish-image.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml index 9c148f6..6e4fe40 100644 --- a/.github/workflows/publish-image.yml +++ b/.github/workflows/publish-image.yml @@ -2,6 +2,7 @@ name: publish image permissions: contents: read + packages: write on: push: From 41b53a9400dd3bfd6417eb790cf97fbaf48adbeb Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Fri, 11 Jul 2025 14:51:05 +0300 Subject: [PATCH 143/146] chore: remove Docker support (#257) --- .github/dependabot.yml | 4 ---- .github/workflows/publish-image.yml | 36 ----------------------------- Dockerfile | 21 ----------------- 3 files changed, 61 deletions(-) delete mode 100644 .github/workflows/publish-image.yml delete mode 100644 Dockerfile diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 95bb02f..755e981 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,10 +5,6 @@ version: 2 updates: - - package-ecosystem: docker - directory: / - schedule: - interval: "weekly" - package-ecosystem: github-actions directory: / schedule: diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml deleted file mode 100644 index 6e4fe40..0000000 --- a/.github/workflows/publish-image.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: publish image - -permissions: - contents: read - packages: write - -on: - push: - paths: - - 'Dockerfile' - workflow_dispatch: - inputs: - tag: - description: 'Which tag want to build' - default: '' - required: false - -jobs: - publish: - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v4 - - name: Build to check Dockerfile - if: github.event.inputs.tag == '' - run: | - docker build -f Dockerfile -t commit-check . - - name: Build and publish docker image - if: github.event.inputs.tag != '' - run: | - echo "tag = ${{ github.event.inputs.tag }}" - docker build -f Dockerfile --build-arg VERSION=${{ github.event.inputs.tag }} -t commit-check:${{ github.event.inputs.tag }} . - echo $CR_PAT | docker login ghcr.io -u shenxianpeng --password-stdin - docker tag commit-check:${{ github.event.inputs.tag }} ghcr.io/commit-check/commit-check:${{ github.event.inputs.tag }} - docker push ghcr.io/commit-check/commit-check:${{ github.event.inputs.tag }} - env: - CR_PAT: ${{ secrets.CR_PAT }} diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 7776999..0000000 --- a/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM python:3.13-slim - -ARG VERSION - -LABEL com.github.actions.name="Commit Check" -LABEL com.github.actions.description="Check commit message formatting, branch naming, commit author, email, and more." -LABEL com.github.actions.icon="code" -LABEL com.github.actions.color="gray-dark" - -LABEL repository="https://github.com/commit-check/commit-check" -LABEL maintainer="shenxianpeng <20297606+shenxianpeng@users.noreply.github.com>" - -RUN if [ -z "$VERSION" ]; then \ - pip3 install commit-check; \ - else \ - pip3 install commit-check==$VERSION; \ - fi - -USER nobody - -ENTRYPOINT [ "commit-check" ] From 2b9711cd369bdceb34b6418ee3d74b3ea3658d57 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sun, 13 Jul 2025 00:27:14 +0300 Subject: [PATCH 144/146] feat: add impreative mode (#258) * feat: add impreative mode * feat: introduce imperatives.py file * chore: rename to --imperative * chore: rename to --imperative * chore: fix docs formatting * feat: add check imperative hook --- .commit-check.yml | 5 + .pre-commit-config.yaml | 3 +- .pre-commit-hooks.yaml | 7 ++ README.rst | 3 +- commit_check/__init__.py | 6 + commit_check/commit.py | 95 +++++++++++++++ commit_check/imperatives.py | 237 ++++++++++++++++++++++++++++++++++++ commit_check/main.py | 10 ++ tests/commit_test.py | 223 ++++++++++++++++++++++++++++++++- tests/main_test.py | 34 +++--- 10 files changed, 606 insertions(+), 17 deletions(-) create mode 100644 commit_check/imperatives.py diff --git a/.commit-check.yml b/.commit-check.yml index ad339d0..d215d90 100644 --- a/.commit-check.yml +++ b/.commit-check.yml @@ -32,3 +32,8 @@ checks: regex: main # it can be master, develop, devel etc based on your project. error: Current branch is not rebased onto target branch suggest: Please ensure your branch is rebased with the target branch + + - check: imperative + regex: '' # Not used for imperative mood check + error: 'Commit message should use imperative mood (e.g., "Add feature" not "Added feature")' + suggest: 'Use imperative mood in commit message like "Add", "Fix", "Update", "Remove"' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8f6f962..58c47aa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,4 +42,5 @@ repos: - id: check-author-name # uncomment if you need. - id: check-author-email # uncomment if you need. # - id: check-commit-signoff # uncomment if you need. - # - id: check-merge-base # requires download all git history + # - id: check-merge-base # requires download all git history + # - id: check-imperative # uncomment if you need. diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 1fca51a..6a73596 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -41,3 +41,10 @@ args: [--merge-base] pass_filenames: false language: python +- id: check-imperative + name: check imperative mood + description: ensures commit message uses imperative mood + entry: commit-check + args: [--imperative] + pass_filenames: true + language: python diff --git a/README.rst b/README.rst index b9ac03a..35a68e1 100644 --- a/README.rst +++ b/README.rst @@ -77,6 +77,7 @@ Running as pre-commit hook - id: check-author-email - id: check-commit-signoff - id: check-merge-base # requires download all git history + - id: check-imperative Running as CLI ~~~~~~~~~~~~~~ @@ -109,7 +110,7 @@ To configure the hook, create a script file in the ``.git/hooks/`` directory. .. code-block:: bash #!/bin/sh - commit-check --message --branch --author-name --author-email --commit-signoff --merge-base + commit-check --message --branch --author-name --author-email --commit-signoff --merge-base --imperative Save the script file as ``pre-push`` and make it executable: diff --git a/commit_check/__init__.py b/commit_check/__init__.py index 521f68f..8b78762 100644 --- a/commit_check/__init__.py +++ b/commit_check/__init__.py @@ -54,6 +54,12 @@ 'error': 'Current branch is not rebased onto target branch', 'suggest': 'Please ensure your branch is rebased with the target branch', }, + { + 'check': 'imperative', + 'regex': r'', # Not used for imperative mood check + 'error': 'Commit message should use imperative mood (e.g., "Add feature" not "Added feature")', + 'suggest': 'Use imperative mood in commit message like "Add", "Fix", "Update", "Remove"', + }, ], } diff --git a/commit_check/commit.py b/commit_check/commit.py index ac1c63a..05a08e3 100644 --- a/commit_check/commit.py +++ b/commit_check/commit.py @@ -3,6 +3,12 @@ from pathlib import PurePath from commit_check import YELLOW, RESET_COLOR, PASS, FAIL from commit_check.util import cmd_output, get_commit_info, print_error_header, print_error_message, print_suggestion, has_commits +from commit_check.imperatives import IMPERATIVES + + +def _load_imperatives() -> set: + """Load imperative verbs from imperatives module.""" + return IMPERATIVES def get_default_commit_msg_file() -> str: @@ -84,3 +90,92 @@ def check_commit_signoff(checks: list, commit_msg_file: str = "") -> int: return FAIL return PASS + + +def check_imperative(checks: list, commit_msg_file: str = "") -> int: + """Check if commit message uses imperative mood.""" + if has_commits() is False: + return PASS # pragma: no cover + + if commit_msg_file is None or commit_msg_file == "": + commit_msg_file = get_default_commit_msg_file() + + for check in checks: + if check['check'] == 'imperative': + commit_msg = read_commit_msg(commit_msg_file) + + # Extract the subject line (first line of commit message) + subject = commit_msg.split('\n')[0].strip() + + # Skip if empty or merge commit + if not subject or subject.startswith('Merge'): + return PASS + + # For conventional commits, extract description after the colon + if ':' in subject: + description = subject.split(':', 1)[1].strip() + else: + description = subject + + # Check if the description uses imperative mood + if not _is_imperative(description): + if not print_error_header.has_been_called: + print_error_header() # pragma: no cover + print_error_message( + check['check'], 'imperative mood pattern', + check['error'], subject, + ) + if check['suggest']: + print_suggestion(check['suggest']) + return FAIL + + return PASS + + +def _is_imperative(description: str) -> bool: + """Check if a description uses imperative mood.""" + if not description: + return True + + # Get the first word of the description + first_word = description.split()[0].lower() + + # Load imperative verbs from file + imperatives = _load_imperatives() + + # Check for common past tense pattern (-ed ending) but be more specific + if (first_word.endswith('ed') and len(first_word) > 3 and + first_word not in {'red', 'bed', 'fed', 'led', 'wed', 'shed', 'fled'}): + return False + + # Check for present continuous pattern (-ing ending) but be more specific + if (first_word.endswith('ing') and len(first_word) > 4 and + first_word not in {'ring', 'sing', 'king', 'wing', 'thing', 'string', 'bring'}): + return False + + # Check for third person singular (-s ending) but be more specific + # Only flag if it's clearly a verb in third person singular form + if first_word.endswith('s') and len(first_word) > 3: + # Common nouns ending in 's' that should be allowed + common_nouns_ending_s = {'process', 'access', 'address', 'progress', 'express', 'stress', 'success', 'class', 'pass', 'mass', 'loss', 'cross', 'gross', 'boss', 'toss', 'less', 'mess', 'dress', 'press', 'bless', 'guess', 'chess', 'glass', 'grass', 'brass'} + + # Words ending in 'ss' or 'us' are usually not third person singular verbs + if first_word.endswith('ss') or first_word.endswith('us'): + return True # Allow these + + # If it's a common noun, allow it + if first_word in common_nouns_ending_s: + return True + + # Otherwise, it's likely a third person singular verb + return False + + # If we have imperatives loaded, check if the first word is imperative + if imperatives: + # Check if the first word is in our imperative list + if first_word in imperatives: + return True + + # If word is not in imperatives list, apply some heuristics + # If it passes all the negative checks above, it's likely imperative + return True diff --git a/commit_check/imperatives.py b/commit_check/imperatives.py new file mode 100644 index 0000000..0c3d091 --- /dev/null +++ b/commit_check/imperatives.py @@ -0,0 +1,237 @@ +# https://github.com/crate-ci/imperative/blob/master/assets/imperatives.txt +# Imperative forms of verbs +# +# This file contains the imperative form of frequently encountered +# docstring verbs. Some of these may be more commonly encountered as +# nouns, but blacklisting them for this may cause false positives. + +IMPERATIVES = { + 'accept', + 'access', + 'add', + 'adjust', + 'aggregate', + 'allow', + 'append', + 'apply', + 'archive', + 'assert', + 'assign', + 'attempt', + 'authenticate', + 'authorize', + 'break', + 'build', + 'cache', + 'calculate', + 'call', + 'cancel', + 'capture', + 'change', + 'check', + 'clean', + 'clear', + 'close', + 'collect', + 'combine', + 'commit', + 'compare', + 'compute', + 'configure', + 'confirm', + 'connect', + 'construct', + 'control', + 'convert', + 'copy', + 'count', + 'create', + 'customize', + 'declare', + 'decode', + 'decorate', + 'define', + 'delegate', + 'delete', + 'deprecate', + 'derive', + 'describe', + 'detect', + 'determine', + 'display', + 'download', + 'drop', + 'dump', + 'emit', + 'empty', + 'enable', + 'encapsulate', + 'encode', + 'end', + 'ensure', + 'enumerate', + 'establish', + 'evaluate', + 'examine', + 'execute', + 'exit', + 'expand', + 'expect', + 'export', + 'extend', + 'extract', + 'feed', + 'fetch', + 'fill', + 'filter', + 'finalize', + 'find', + 'fire', + 'fix', + 'flag', + 'force', + 'format', + 'forward', + 'generate', + 'get', + 'give', + 'go', + 'group', + 'handle', + 'help', + 'hold', + 'identify', + 'implement', + 'import', + 'indicate', + 'init', + 'initialise', + 'initialize', + 'initiate', + 'input', + 'insert', + 'instantiate', + 'intercept', + 'invoke', + 'iterate', + 'join', + 'keep', + 'launch', + 'list', + 'listen', + 'load', + 'log', + 'look', + 'make', + 'manage', + 'manipulate', + 'map', + 'mark', + 'match', + 'merge', + 'mock', + 'modify', + 'monitor', + 'move', + 'normalize', + 'note', + 'obtain', + 'open', + 'output', + 'override', + 'overwrite', + 'package', + 'pad', + 'parse', + 'partial', + 'pass', + 'perform', + 'persist', + 'pick', + 'plot', + 'poll', + 'populate', + 'post', + 'prepare', + 'print', + 'process', + 'produce', + 'provide', + 'publish', + 'pull', + 'put', + 'query', + 'raise', + 'read', + 'record', + 'refer', + 'refresh', + 'register', + 'reload', + 'remove', + 'rename', + 'render', + 'replace', + 'reply', + 'report', + 'represent', + 'request', + 'require', + 'reset', + 'resolve', + 'retrieve', + 'return', + 'roll', + 'rollback', + 'round', + 'run', + 'sample', + 'save', + 'scan', + 'search', + 'select', + 'send', + 'serialise', + 'serialize', + 'serve', + 'set', + 'show', + 'simulate', + 'source', + 'specify', + 'split', + 'start', + 'step', + 'stop', + 'store', + 'strip', + 'submit', + 'subscribe', + 'sum', + 'swap', + 'sync', + 'synchronise', + 'synchronize', + 'take', + 'tear', + 'test', + 'time', + 'transform', + 'translate', + 'transmit', + 'truncate', + 'try', + 'turn', + 'tweak', + 'update', + 'upload', + 'use', + 'validate', + 'verify', + 'view', + 'wait', + 'walk', + 'wrap', + 'write', + 'yield', +} diff --git a/commit_check/main.py b/commit_check/main.py index 6faa070..f81af48 100644 --- a/commit_check/main.py +++ b/commit_check/main.py @@ -92,6 +92,14 @@ def get_parser() -> argparse.ArgumentParser: required=False, ) + parser.add_argument( + '-i', + '--imperative', + help='check commit message uses imperative mood', + action="store_true", + required=False, + ) + return parser @@ -122,6 +130,8 @@ def main() -> int: check_results.append(commit.check_commit_signoff(checks)) if args.merge_base: check_results.append(branch.check_merge_base(checks)) + if args.imperative: + check_results.append(commit.check_imperative(checks, args.commit_msg_file)) return PASS if all(val == PASS for val in check_results) else FAIL diff --git a/tests/commit_test.py b/tests/commit_test.py index c733968..9a1235d 100644 --- a/tests/commit_test.py +++ b/tests/commit_test.py @@ -1,6 +1,6 @@ import pytest from commit_check import PASS, FAIL -from commit_check.commit import check_commit_msg, get_default_commit_msg_file, read_commit_msg, check_commit_signoff +from commit_check.commit import check_commit_msg, get_default_commit_msg_file, read_commit_msg, check_commit_signoff, check_imperative # used by get_commit_info mock FAKE_BRANCH_NAME = "fake_commits_info" @@ -177,3 +177,224 @@ def test_check_commit_signoff_with_empty_checks(mocker): retval = check_commit_signoff(checks) assert retval == PASS assert m_re_match.call_count == 0 + + +@pytest.mark.benchmark +def test_check_imperative_pass(mocker): + """Test imperative mood check passes for valid imperative mood.""" + checks = [{ + "check": "imperative", + "regex": "", + "error": "Commit message should use imperative mood", + "suggest": "Use imperative mood" + }] + + mocker.patch( + "commit_check.commit.read_commit_msg", + return_value="feat: Add new feature\n\nThis adds a new feature to the application." + ) + + retval = check_imperative(checks, MSG_FILE) + assert retval == PASS + + +@pytest.mark.benchmark +def test_check_imperative_fail_past_tense(mocker): + """Test imperative mood check fails for past tense.""" + checks = [{ + "check": "imperative", + "regex": "", + "error": "Commit message should use imperative mood", + "suggest": "Use imperative mood" + }] + + mocker.patch( + "commit_check.commit.read_commit_msg", + return_value="feat: Added new feature" + ) + + m_print_error_message = mocker.patch( + f"{LOCATION}.print_error_message" + ) + m_print_suggestion = mocker.patch( + f"{LOCATION}.print_suggestion" + ) + + retval = check_imperative(checks, MSG_FILE) + assert retval == FAIL + assert m_print_error_message.call_count == 1 + assert m_print_suggestion.call_count == 1 + + +@pytest.mark.benchmark +def test_check_imperative_fail_present_continuous(mocker): + """Test imperative mood check fails for present continuous.""" + checks = [{ + "check": "imperative", + "regex": "", + "error": "Commit message should use imperative mood", + "suggest": "Use imperative mood" + }] + + mocker.patch( + "commit_check.commit.read_commit_msg", + return_value="feat: Adding new feature" + ) + + m_print_error_message = mocker.patch( + f"{LOCATION}.print_error_message" + ) + m_print_suggestion = mocker.patch( + f"{LOCATION}.print_suggestion" + ) + + retval = check_imperative(checks, MSG_FILE) + assert retval == FAIL + assert m_print_error_message.call_count == 1 + assert m_print_suggestion.call_count == 1 + + +@pytest.mark.benchmark +def test_check_imperative_skip_merge_commit(mocker): + """Test imperative mood check skips merge commits.""" + checks = [{ + "check": "imperative", + "regex": "", + "error": "Commit message should use imperative mood", + "suggest": "Use imperative mood" + }] + + mocker.patch( + "commit_check.commit.read_commit_msg", + return_value="Merge branch 'feature/test' into main" + ) + + retval = check_imperative(checks, MSG_FILE) + assert retval == PASS + + +@pytest.mark.benchmark +def test_check_imperative_different_check_type(mocker): + """Test imperative mood check skips different check types.""" + checks = [{ + "check": "message", + "regex": "dummy_regex" + }] + + m_read_commit_msg = mocker.patch( + "commit_check.commit.read_commit_msg", + return_value="feat: Added new feature" + ) + + retval = check_imperative(checks, MSG_FILE) + assert retval == PASS + assert m_read_commit_msg.call_count == 0 + + +@pytest.mark.benchmark +def test_check_imperative_no_commits(mocker): + """Test imperative mood check passes when there are no commits.""" + checks = [{ + "check": "imperative", + "regex": "", + "error": "Commit message should use imperative mood", + "suggest": "Use imperative mood" + }] + + mocker.patch("commit_check.commit.has_commits", return_value=False) + + retval = check_imperative(checks, MSG_FILE) + assert retval == PASS + + +@pytest.mark.benchmark +def test_check_imperative_empty_checks(mocker): + """Test imperative mood check with empty checks list.""" + checks = [] + + m_read_commit_msg = mocker.patch( + "commit_check.commit.read_commit_msg", + return_value="feat: Added new feature" + ) + + retval = check_imperative(checks, MSG_FILE) + assert retval == PASS + assert m_read_commit_msg.call_count == 0 + + +@pytest.mark.benchmark +def test_is_imperative_valid_cases(): + """Test _is_imperative function with valid imperative mood cases.""" + from commit_check.commit import _is_imperative + + valid_cases = [ + "Add new feature", + "Fix bug in authentication", + "Update documentation", + "Remove deprecated code", + "Refactor user service", + "Optimize database queries", + "Create new component", + "Delete unused files", + "Improve error handling", + "Enhance user experience", + "Implement new API", + "Configure CI/CD pipeline", + "Setup testing framework", + "Handle edge cases", + "Process user input", + "Validate form data", + "Transform data format", + "Initialize application", + "Load configuration", + "Save user preferences", + "", # Empty description should pass + ] + + for case in valid_cases: + assert _is_imperative(case), f"'{case}' should be imperative mood" + + +@pytest.mark.benchmark +def test_is_imperative_invalid_cases(): + """Test _is_imperative function with invalid imperative mood cases.""" + from commit_check.commit import _is_imperative + + invalid_cases = [ + "Added new feature", + "Fixed bug in authentication", + "Updated documentation", + "Removed deprecated code", + "Refactored user service", + "Optimized database queries", + "Created new component", + "Deleted unused files", + "Improved error handling", + "Enhanced user experience", + "Implemented new API", + "Adding new feature", + "Fixing bug in authentication", + "Updating documentation", + "Removing deprecated code", + "Refactoring user service", + "Optimizing database queries", + "Creating new component", + "Deleting unused files", + "Improving error handling", + "Enhancing user experience", + "Implementing new API", + "Adds new feature", + "Fixes bug in authentication", + "Updates documentation", + "Removes deprecated code", + "Refactors user service", + "Optimizes database queries", + "Creates new component", + "Deletes unused files", + "Improves error handling", + "Enhances user experience", + "Implements new API", + ] + + for case in invalid_cases: + assert not _is_imperative(case), f"'{case}' should not be imperative mood" diff --git a/tests/main_test.py b/tests/main_test.py index c232efd..4e277a6 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -8,20 +8,22 @@ class TestMain: @pytest.mark.benchmark - @pytest.mark.parametrize("argv, check_commit_call_count, check_branch_call_count, check_author_call_count, check_commit_signoff_call_count, check_merge_base_call_count", [ - ([CMD, "--message"], 1, 0, 0, 0, 0), - ([CMD, "--branch"], 0, 1, 0, 0, 0), - ([CMD, "--author-name"], 0, 0, 1, 0, 0), - ([CMD, "--author-email"], 0, 0, 1, 0, 0), - ([CMD, "--commit-signoff"], 0, 0, 0, 1, 0), - ([CMD, "--merge-base"], 0, 0, 0, 0, 1), - ([CMD, "--message", "--author-email"], 1, 0, 1, 0, 0), - ([CMD, "--branch", "--message"], 1, 1, 0, 0, 0), - ([CMD, "--author-name", "--author-email"], 0, 0, 2, 0, 0), - ([CMD, "--message", "--branch", "--author-email"], 1, 1, 1, 0, 0), - ([CMD, "--branch", "--message", "--author-name", "--author-email"], 1, 1, 2, 0, 0), - ([CMD, "--message", "--branch", "--author-name", "--author-email", "--commit-signoff", "--merge-base"], 1, 1, 2, 1, 1), - ([CMD, "--dry-run"], 0, 0, 0, 0, 0), + @pytest.mark.parametrize("argv, check_commit_call_count, check_branch_call_count, check_author_call_count, check_commit_signoff_call_count, check_merge_base_call_count, check_imperative_call_count", [ + ([CMD, "--message"], 1, 0, 0, 0, 0, 0), + ([CMD, "--branch"], 0, 1, 0, 0, 0, 0), + ([CMD, "--author-name"], 0, 0, 1, 0, 0, 0), + ([CMD, "--author-email"], 0, 0, 1, 0, 0, 0), + ([CMD, "--commit-signoff"], 0, 0, 0, 1, 0, 0), + ([CMD, "--merge-base"], 0, 0, 0, 0, 1, 0), + ([CMD, "--imperative"], 0, 0, 0, 0, 0, 1), + ([CMD, "--message", "--author-email"], 1, 0, 1, 0, 0, 0), + ([CMD, "--branch", "--message"], 1, 1, 0, 0, 0, 0), + ([CMD, "--author-name", "--author-email"], 0, 0, 2, 0, 0, 0), + ([CMD, "--message", "--branch", "--author-email"], 1, 1, 1, 0, 0, 0), + ([CMD, "--branch", "--message", "--author-name", "--author-email"], 1, 1, 2, 0, 0, 0), + ([CMD, "--message", "--branch", "--author-name", "--author-email", "--commit-signoff", "--merge-base"], 1, 1, 2, 1, 1, 0), + ([CMD, "--message", "--imperative"], 1, 0, 0, 0, 0, 1), + ([CMD, "--dry-run"], 0, 0, 0, 0, 0, 0), ]) def test_main( self, @@ -32,6 +34,7 @@ def test_main( check_author_call_count, check_commit_signoff_call_count, check_merge_base_call_count, + check_imperative_call_count, ): mocker.patch( "commit_check.main.validate_config", @@ -46,6 +49,7 @@ def test_main( m_check_author = mocker.patch("commit_check.author.check_author") m_check_commit_signoff = mocker.patch("commit_check.commit.check_commit_signoff") m_check_merge_base = mocker.patch("commit_check.branch.check_merge_base") + m_check_imperative = mocker.patch("commit_check.commit.check_imperative") sys.argv = argv main() assert m_check_commit.call_count == check_commit_call_count @@ -53,6 +57,7 @@ def test_main( assert m_check_author.call_count == check_author_call_count assert m_check_commit_signoff.call_count == check_commit_signoff_call_count assert m_check_merge_base.call_count == check_merge_base_call_count + assert m_check_imperative.call_count == check_imperative_call_count @pytest.mark.benchmark def test_main_help(self, mocker, capfd): @@ -168,6 +173,7 @@ def test_main_multiple_checks( mocker.patch( "commit_check.branch.check_merge_base", return_value=merge_base_result ) + mocker.patch("commit_check.commit.check_imperative", return_value=PASS) # this is messy. why isn't this a private implementation detail with a # public check_author_name and check_author email? From 952b91fe468859833ce652218390408c210b3875 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sun, 13 Jul 2025 00:35:06 +0300 Subject: [PATCH 145/146] docs: add example for failed imperative mood checks (#259) docs: update README.md --- README.rst | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/README.rst b/README.rst index 35a68e1..bfda1a0 100644 --- a/README.rst +++ b/README.rst @@ -157,14 +157,14 @@ Check Branch Naming Failed Commit rejected by Commit-Check. - (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) - / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ - __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ + (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) + / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ + __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ (_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._) - || E || || R || || R || || O || || R || - _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ + || E || || R || || R || || O || || R || + _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ (.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) - `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ + `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ Commit rejected. @@ -180,14 +180,14 @@ Check Commit Signature Failed Commit rejected by Commit-Check. - (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) - / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ - __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ + (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) + / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ + __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ (_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._) - || E || || R || || R || || O || || R || - _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ + || E || || R || || R || || O || || R || + _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ (.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) - `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ + `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ Commit rejected. @@ -197,6 +197,28 @@ Check Commit Signature Failed Suggest: run command `git commit -m "conventional commit message" --signoff` +Check Imperative Mood Failed + +.. code-block:: text + + Commit rejected by Commit-Check. + + (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) + / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ + __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ + (_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._) + || E || || R || || R || || O || || R || + _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ + (.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) + `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ + + Commit rejected. + + Type imperative check failed => Added file + It doesn't match regex: imperative mood pattern + Commit message should use imperative mood (e.g., "Add feature" not "Added feature") + Suggest: Use imperative mood in commit message like "Add", "Fix", "Update", "Remove" + Badging your repository ----------------------- From 24912964ba2bab31f28bdd4c76e469da74e51acb Mon Sep 17 00:00:00 2001 From: Randolph Sapp Date: Mon, 14 Jul 2025 15:33:45 -0500 Subject: [PATCH 146/146] fix(message): protect the message regex check (#260) --- commit_check/commit.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/commit_check/commit.py b/commit_check/commit.py index 05a08e3..fccc5da 100644 --- a/commit_check/commit.py +++ b/commit_check/commit.py @@ -38,13 +38,13 @@ def check_commit_msg(checks: list, commit_msg_file: str = "") -> int: commit_msg = read_commit_msg(commit_msg_file) for check in checks: - if check['regex'] == "": - print( - f"{YELLOW}Not found regex for commit message. skip checking.{RESET_COLOR}", - ) - return PASS - if check['check'] == 'message': + if check['regex'] == "": + print( + f"{YELLOW}Not found regex for commit message. skip checking.{RESET_COLOR}", + ) + return PASS + result = re.match(check['regex'], commit_msg) if result is None: if not print_error_header.has_been_called: