diff --git a/.github/workflows/plugin-tests.yml b/.github/workflows/plugin-tests.yml new file mode 100644 index 0000000..971f452 --- /dev/null +++ b/.github/workflows/plugin-tests.yml @@ -0,0 +1,35 @@ +--- +name: ๐Ÿ“ธ Pytest (compare with snapshots) + +on: + pull_request: + push: {branches: master} + +jobs: + plugin-tests: + runs-on: ubuntu-latest + permissions: + contents: read + strategy: + matrix: + python-version: ['3.9', '3.10', '3.11', '3.12'] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: pip + + - name: Install dependencies + run: | + python -m venv venv + source venv/bin/activate + pip install --require-virtualenv --upgrade pip + pip install --require-virtualenv '.[test]' + + - name: Run pytest, compare output with stored snapshots + run: pytest -s diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 384a5dc..c54cd94 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,6 +3,8 @@ minimum_pre_commit_version: 3.3.0 default_install_hook_types: [pre-commit, commit-msg] default_stages: [commit] +exclude: '^tests/__snapshots__/' + repos: - repo: meta hooks: @@ -30,6 +32,8 @@ repos: rev: v1.11.2 hooks: - id: mypy + args: ['--config-file', 'pyproject.toml'] + exclude: 'tests/' - repo: https://github.com/asottile/pyupgrade rev: v3.17.0 @@ -66,18 +70,13 @@ repos: args: - --base64-limit=4 - --hex-limit=3 + exclude: 'tests/' - repo: https://github.com/lyz-code/yamlfix/ rev: 1.17.0 hooks: - id: yamlfix - - repo: https://github.com/espressif/cz-plugin-espressif - rev: v1.0.1 - hooks: - - id: update-changelog - files: ^pyproject\.toml$ - - repo: local hooks: - id: pip-compile diff --git a/CHANGELOG.md b/CHANGELOG.md index 5be43ec..54210ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,23 +1,33 @@ + + + + # CHANGELOG > All notable changes to this project are documented in this file. > This list is not exhaustive - only important changes, fixes, and new features in the code are reflected here. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) - - ---- +
+ Static Badge + Static Badge + Static Badge +
+
## Unreleased ### ๐Ÿ› Bug fixes -- **changelog**: fix double title, header and footer on 'cz bump' *(Tomas Sebestik - f715e63)* +- **changelog**: fix double title, header and footer on 'cz bump' *(Tomas Sebestik - cce3c00)* ### ๐Ÿ“– Documentation - **docker-example**: add run_command.txt for running demo container *(Tomas Sebestik - 0fa8c2e)* +### ๐Ÿ”ง Code refactoring + +- **python-3.9**: refactor syntax and typing for python 3.9 *(Tomas Sebestik - 8de6c1d)* + --- ## v1.1.0 (2024-09-24) @@ -54,7 +64,14 @@ --- -**[Espressif Systems CO LTD. (2024)](https://www.espressif.com/)** - -- [Commitizen tools plugin with Espressif code style](https://www.github.com/espressif/cz-plugin-espressif) -- [Espressif Coding Standards and Best Practices](https://www.github.com/espressif/standards) +
+ + + Commitizen Espressif plugin + ยท + Espressif Standards + +
+ Espressif Systems CO LTD. (2024) +
+
diff --git a/Justfile b/Justfile index d7b80d5..132768b 100644 --- a/Justfile +++ b/Justfile @@ -14,27 +14,15 @@ gitstyle := '%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s # Helper function for quick menu [private] -default: - @just --list +@default: + just --list -# .Edit this Justfile -edit-just: +# ... Edit this Justfile +@edit-just: $EDITOR ./Justfile -# PROJECT: Install development environment -install: - pip uninstall -y czespressif commitizen - pip install --require-virtualenv -e '.[dev]' - pip install --require-virtualenv --upgrade pip - - -# PROJECT: Re-compile requirements.txt from dev-dependencies in pyproject.toml -lock-requirements: - pip-compile --strip-extras --output-file=requirements.txt pyproject.toml > /dev/null - - # PROJECT: Release version info and list of commits since last release @version: cz bump --dry-run | grep -E 'change\(bump\)|tag to create|increment detected'; \ @@ -42,9 +30,15 @@ lock-requirements: git log -n 30 --graph --pretty="{{gitstyle}}" v{{current_version}}..HEAD -# PROJECT: Run pre-commit linter(s)/formatter(s) on entire codebase -repo-pre-commit hook="": - pre-commit run {{hook}} --all-files +# PROJECT: Install development environment +@install: + pip install --require-virtualenv -e '.[dev,test]' + pip install --require-virtualenv --upgrade pip + + +# PROJECT: Re-compile requirements.txt from dev-dependencies in pyproject.toml +@lock-requirements: + pip-compile --strip-extras --output-file=requirements.txt pyproject.toml > /dev/null # PROJECT: Remove caches, builds, reports and other generated files @@ -57,26 +51,52 @@ repo-pre-commit hook="": .ruff_cache \ *.egg-info \ **/__pycache__/ \ - **/*.test.md \ build \ demo \ dist \ - output/* \ : -# GIT: Revert the last commit - keeping changes staged -uncommit: - git reset --soft HEAD~1 +# PROJECT: Build and check distribution package +@build: + just clean + python -m build + twine check dist/* + + +# PROJECT: +@bump-test: + clear + pre-commit run --all-files + cz bump --dry-run + + +# PYTEST: Run tests with coverage report +@test: + pytest + +# PYTEST: Updade snapshots (known results) for pytest +@update-snapshots: + pytest --snapshot-update + + +# DOCKER: Test Build Docker image for demo +@docker-test-buildx: + cd docker && docker buildx build --platform linux/arm64,linux/amd64 -t tomasad/czespressif-demo . && cd - -# GIT: Unstage files without modifying them -unstage: - git reset HEAD -- +# DOCKER: Build and push Docker image for demo +@docker-push-buildx: + cd docker && docker buildx build --platform linux/arm64,linux/amd64 -t tomasad/czespressif-demo --push . && cd - + + +# DOCKER: Run Docker image for demo +@docker-run directory=".": + pushd {{directory}} && docker run --rm -v $(pwd):/app -u $(id -u):$(id -g) tomasad/czespressif-demo && popd # GIT: Show commits only on current branch -branch-commits base="master": +@branch-commits base="master": @if git rev-parse --verify "{{base}}" > /dev/null 2>&1; then \ git log --first-parent --no-merges --graph --pretty="{{gitstyle}}" {{base}}..HEAD; \ else \ @@ -86,92 +106,48 @@ branch-commits base="master": # GIT: Try commit again, open failed commit message it in the editor for corrections -recommit: +@recommit: git commit --edit --file=$(git rev-parse --git-dir)/COMMIT_EDITMSG # GIT: Run interactive "git rebase" command -rebase base="master": +@rebase base="master": git fetch origin {{base}} git rebase -i origin/{{base}} -# PROJECT: Build and pip install -@build: - just clean - pip uninstall -y czespressif commitizen - python -m build - twine check dist/* - pip install -e . - cz example >> /dev/null - +# ---------------------------------------------- -# TEST: Test the output of `cz bump` command -@test-cz-bump: +@generate-cz-bump: clear cz bump --dry-run | tee "output/cz-bump.test.md" -# TEST: Test the output of `cz example` command -@test-cz-example: +@generate-cz-example: clear cz example | tee "output/cz-example.test.md" -# TEST: Test the output of `cz info` command -@test-cz-info: +@generate-cz-info: clear cz info | tee "output/cz-info.test.md" -# TEST: Test the output of `cz schema` command -@test-cz-schema: +@generate-cz-schema: clear cz schema | tee "output/cz-schema.test.md" -# TEST: Test the output of `cz changelog` command -@test-changelog: +@generate-changelog: clear cz changelog --dry-run | tee "output/CHANGELOG.test.md" -# TEST: Test the output of `cz changelog --incremental` command -@test-changelog-incremental: +@generate-changelog-incremental: clear cz changelog --incremental --dry-run | tee "output/CHANGELOG-incremental.test.md" -# TEST: Test the output of `cz changelog v1.0.0` command -@test-release-notes: +@generate-release-notes: clear - cz changelog v1.0.0 --template="RELEASE_NOTES.md.j2" --dry-run | tee "output/RELEASE_NOTES.test.md" - - -# TEST GROUP: Screen test to see the output, generate all files to 'output' directory -test: - just version - echo "Maximize terminal ...." && sleep 5; clear - just test-cz-bump && sleep 2; clear - just test-cz-info && sleep 2; clear - just test-cz-example && sleep 2; clear - just test-cz-schema && sleep 2; clear - just test-changelog && sleep 5; clear - just test-changelog-incremental && sleep 5; clear - just test-release-notes && sleep 5; clear - echo "Resize terminal, tests ends ...." && sleep 2; clear - - -# DOCKER: Build and push Docker image for demo -docker-buildx-test: - cd docker && docker buildx build --platform linux/arm64,linux/amd64 -t tomasad/czespressif-demo . && cd - - - -# DOCKER: Build and push Docker image for demo -docker-buildx-push: - cd docker && docker buildx build --platform linux/arm64,linux/amd64 -t tomasad/czespressif-demo --push . && cd - - - -# DOCKER: Run Docker image for demo -docker-run go_dir=".": - pushd {{go_dir}} && docker run --rm -v $(pwd):/app -u $(id -u):$(id -g) tomasad/czespressif-demo && popd + cz changelog v1.1.0 --template="RELEASE_NOTES.md.j2" --dry-run | tee "output/RELEASE_NOTES.test.md" diff --git a/czespressif/config.py b/czespressif/config.py index 0d52910..bd71174 100644 --- a/czespressif/config.py +++ b/czespressif/config.py @@ -102,23 +102,25 @@ def known_types(self) -> list[CommitType]: return self.types + self.extra_types @property - def include_headers(self) -> bool: + def incremental(self) -> bool: + incr = False # Default is full changelog with headers + # Check if the CLI arguments contain a version or range ('v1.2.3' or '1.2.3..4.5.6') version_or_range = any(re.match(r'^\d+\.\d+\.\d+(\.\.\d+\.\d+\.\d+)?$', arg) for arg in sys.argv) or any(arg.startswith('v') for arg in sys.argv) if version_or_range: - return False + incr = True # Check if the CLI arguments contain the incremental flag ('--incremental') incremental_flag = '--incremental' in sys.argv if incremental_flag: - return False + incr = True # Check if the CLI arguments contain the bump command ('bump') bump = 'bump' in sys.argv if bump: - return False + incr = True - return True + return cast(bool, self.settings.get('incremental', incr)) @property def changelog_unreleased(self) -> bool: diff --git a/czespressif/templates/CHANGELOG.md.j2 b/czespressif/templates/CHANGELOG.md.j2 index ef87cc1..b2b914d 100644 --- a/czespressif/templates/CHANGELOG.md.j2 +++ b/czespressif/templates/CHANGELOG.md.j2 @@ -9,7 +9,7 @@ {# ---TEMPLATE START #} {# Render the changelog title and header only for full changelog, not for cz bump #} -{% if config.include_headers %} +{% if not config.incremental %} {{ config.changelog_title }}{# ---CHANGELOG TITLE--- #} {{ config.changelog_header }}{# ---CHANGELOG HEADER--- #} {% endif %} @@ -49,11 +49,9 @@ {% endif %}{# IF-Unreleased section--- #} {% endfor %}{# Release version--- #} {# Render the footer only for full changelog, not for cz bump #} -{% if config.changelog_footer and config.changelog_footer|length > 0 %}{# ---CHANGELOG FOOTER #} ----{# Add horizontal line before the footer, only if the footer is not empty #} +{% if not config.incremental %}{# ---CHANGELOG FOOTER #} +---{# Add horizontal line before the footer #} -{% if config.include_headers %} -{{ config.changelog_footer }}{# CHANGELOG FOOTER--- #} -{% endif %} -{% endif %} +{{ config.changelog_footer }} +{% endif %}{# CHANGELOG FOOTER--- #} {# TEMPLATE END--- #} diff --git a/pyproject.toml b/pyproject.toml index ec70744..b06ab39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,14 +26,14 @@ dependencies = ["commitizen>=3.29.0"] [project.optional-dependencies] - dev = [ - "just-bin~=1.26.0", - "pip-tools~=7.3", + dev = ["just-bin~=1.26.0", "pip-tools~=7.3", "pre-commit~=3.3.0", "twine~=5.1.1"] + test = [ "pytest-cov~=4.1.0", + "pytest-mock~=3.14.0", + "pytest-sugar~=1.0.0", "pytest~=7.4.0", - "twine~=5.1.1", + "syrupy~=4.7.0", ] - test = ["pytest-cov~=4.1.0", "pytest~=7.4.0"] [project.entry-points."commitizen.plugin"] czespressif = "czespressif:CzPluginEspressif" @@ -61,21 +61,21 @@ skip = 'tests/*' [tool.ruff] - extend-exclude = ["tests/.*"] - line-length = 160 - - [tool.ruff.format] - quote-style = "single" - - [tool.ruff.lint] - select = ["B", "C4", "C901", "E", "F", "I", "N", "PL", "S", "W"] - - [tool.ruff.lint.isort] - force-single-line = true - lines-between-types = 1 + extend-exclude = [] + format.docstring-code-format = true + format.quote-style = "single" + line-length = 160 + lint.exclude = ["tests"] + lint.isort.force-single-line = true + lint.isort.lines-between-types = 1 + lint.per-file-ignores."tests/*" = [ + "PLR0913", # PYLINT: Ignore Too many arguments in tests directory + "S101", # BANDIT: Ignore use of assert in tests directory + ] + lint.select = ["B", "C4", "C901", "E", "F", "I", "N", "PL", "S", "W"] [tool.mypy] - exclude = ["venv"] + exclude = ["^__init__.py$", "^build/.*", "^dist/.*", "^docs/.*", "^tests/.*"] ignore_missing_imports = true packages = "czespressif" pretty = true @@ -84,7 +84,9 @@ warn_return_any = true [tool.pytest.ini_options] - addopts = "-s --log-cli-level DEBUG --cov=sample_python_app --cov-report=term" + addopts = "--log-cli-level DEBUG --cov=czespressif --cov-report=term" + markers = ["settings: mark test to use custom czespressif settings from pyproject.toml"] + testpaths = "tests" [tool.coverage.run] omit = ["*/tests/*", "__*__.py"] diff --git a/tests/__snapshots__/test_changelog/test_changelog_cz_default_full.md b/tests/__snapshots__/test_changelog/test_changelog_cz_default_full.md new file mode 100644 index 0000000..64fc918 --- /dev/null +++ b/tests/__snapshots__/test_changelog/test_changelog_cz_default_full.md @@ -0,0 +1,54 @@ +## v1.3.0 (2024-08-30) + +### Feat + +- **api**: rollback changes to JWT token handling +- **ui**: improve loading animations for dashboard page + +### Fix + +- **logging**: switch from console logs to structured JSON logging +- correct typos in error messages displayed on UI + +## v1.2.0 (2024-07-15) + +### Refactor + +- optimize database queries for user data retrieval + +## v1.2.0.rc0 (2024-06-10) + +### Fix + +- **frontend**: correct layout issues in user profile page + +## v1.1.0 (2024-05-23) + +### Fix + +- **api**: update response codes for failed logins + +## v1.0.0 (2024-04-12) + +## v0.2.1 (2024-03-29) + +### Feat + +- **api**: implement new authentication mechanism with JWT tokens + +### Fix + +- resolve null pointer exception in user session management + +## v0.2.0 (2024-03-02) + +### Feat + +- **api**: implement new authentication mechanism with JWT tokens + +### Fix + +- resolve null pointer exception in user session management + +## v0.1.0 (2024-02-15) + diff --git a/tests/__snapshots__/test_changelog/test_changelog_cz_default_incremental.md b/tests/__snapshots__/test_changelog/test_changelog_cz_default_incremental.md new file mode 100644 index 0000000..5818dc7 --- /dev/null +++ b/tests/__snapshots__/test_changelog/test_changelog_cz_default_incremental.md @@ -0,0 +1,10 @@ +## v1.3.0 (2024-08-30) + +### Feat + +- **api**: rollback changes to JWT token handling + +### Fix + +- **logging**: switch from console logs to structured JSON logging + diff --git a/tests/__snapshots__/test_changelog/test_changelog_czespressif_full.md b/tests/__snapshots__/test_changelog/test_changelog_czespressif_full.md new file mode 100644 index 0000000..2f3bdeb --- /dev/null +++ b/tests/__snapshots__/test_changelog/test_changelog_czespressif_full.md @@ -0,0 +1,110 @@ + + + + +# CHANGELOG + +> All notable changes to this project are documented in this file. +> This list is not exhaustive - only important changes, fixes, and new features in the code are reflected here. + +
+ Static Badge + Static Badge + Static Badge +
+
+ +## v1.3.0 (2024-08-30) + +### โœจ New features + +- **api**: rollback changes to JWT token handling *(Alice Johnson - b5e7a2d)* +- **ui**: improve loading animations for dashboard page *(Diana White - c5d3e7a)* + +### ๐Ÿ› Bug fixes + +- **logging**: switch from console logs to structured JSON logging *(Eve Martin - d9b2c7e)* +- correct typos in error messages displayed on UI *(Bob Smith - b7a4c5b)* + +--- + +## v1.2.0 (2024-07-15) + +### ๐Ÿ”ง Code refactoring + +- optimize database queries for user data retrieval *(Charlie Green - e7c1d8b)* + +--- + +## v1.2.0.rc0 (2024-06-10) + +### ๐Ÿ› Bug fixes + +- **frontend**: correct layout issues in user profile page *(Bob Smith - c3e7b3b)* + +### ๐Ÿ“– Documentation + +- update API documentation for user endpoint *(Eve Martin - f8d7e1c)* + +--- + +## v1.1.0 (2024-05-23) + +### ๐Ÿ› Bug fixes + +- **api**: update response codes for failed logins *(Bob Smith - 1b7d1e7)* + +### ๐Ÿ—‘๏ธ Removals + +- delete old caching logic from request handlers *(Charlie Green - 8f0b3b9)* + +--- + +## v1.0.0 (2024-04-12) + +### ๐Ÿ“– Documentation + +- **frontend**: Update README for new build system integration *(Diana White - 7c6d91f)* + +--- + +## v0.2.1 (2024-03-29) + +### โœจ New features + +- **api**: implement new authentication mechanism with JWT tokens *(Alice Johnson - b2c7e8a)* + +### ๐Ÿ› Bug fixes + +- resolve null pointer exception in user session management *(Bob Smith - 4b1d62b)* + +--- + +## v0.2.0 (2024-03-02) + +### โœจ New features + +- **api**: implement new authentication mechanism with JWT tokens *(Alice Johnson - b2c7e8a)* + +### ๐Ÿ› Bug fixes + +- resolve null pointer exception in user session management *(Bob Smith - 4b1d62b)* + +--- + +## v0.1.0 (2024-02-15) + +--- + +
+ + + Commitizen Espressif plugin + ยท + Espressif Standards + +
+ Espressif Systems CO LTD. (2024) +
+
+ diff --git a/tests/__snapshots__/test_changelog/test_changelog_czespressif_full_no_emoji.md b/tests/__snapshots__/test_changelog/test_changelog_czespressif_full_no_emoji.md new file mode 100644 index 0000000..7212c71 --- /dev/null +++ b/tests/__snapshots__/test_changelog/test_changelog_czespressif_full_no_emoji.md @@ -0,0 +1,110 @@ + + + + +# CHANGELOG + +> All notable changes to this project are documented in this file. +> This list is not exhaustive - only important changes, fixes, and new features in the code are reflected here. + +
+ Static Badge + Static Badge + Static Badge +
+
+ +## v1.3.0 (2024-08-30) + +### New features + +- **api**: rollback changes to JWT token handling *(Alice Johnson - b5e7a2d)* +- **ui**: improve loading animations for dashboard page *(Diana White - c5d3e7a)* + +### Bug fixes + +- **logging**: switch from console logs to structured JSON logging *(Eve Martin - d9b2c7e)* +- correct typos in error messages displayed on UI *(Bob Smith - b7a4c5b)* + +--- + +## v1.2.0 (2024-07-15) + +### Code refactoring + +- optimize database queries for user data retrieval *(Charlie Green - e7c1d8b)* + +--- + +## v1.2.0.rc0 (2024-06-10) + +### Bug fixes + +- **frontend**: correct layout issues in user profile page *(Bob Smith - c3e7b3b)* + +### Documentation + +- update API documentation for user endpoint *(Eve Martin - f8d7e1c)* + +--- + +## v1.1.0 (2024-05-23) + +### Bug fixes + +- **api**: update response codes for failed logins *(Bob Smith - 1b7d1e7)* + +### Removals + +- delete old caching logic from request handlers *(Charlie Green - 8f0b3b9)* + +--- + +## v1.0.0 (2024-04-12) + +### Documentation + +- **frontend**: Update README for new build system integration *(Diana White - 7c6d91f)* + +--- + +## v0.2.1 (2024-03-29) + +### New features + +- **api**: implement new authentication mechanism with JWT tokens *(Alice Johnson - b2c7e8a)* + +### Bug fixes + +- resolve null pointer exception in user session management *(Bob Smith - 4b1d62b)* + +--- + +## v0.2.0 (2024-03-02) + +### New features + +- **api**: implement new authentication mechanism with JWT tokens *(Alice Johnson - b2c7e8a)* + +### Bug fixes + +- resolve null pointer exception in user session management *(Bob Smith - 4b1d62b)* + +--- + +## v0.1.0 (2024-02-15) + +--- + +
+ + + Commitizen Espressif plugin + ยท + Espressif Standards + +
+ Espressif Systems CO LTD. (2024) +
+
+ diff --git a/tests/__snapshots__/test_changelog/test_changelog_czespressif_incremental.md b/tests/__snapshots__/test_changelog/test_changelog_czespressif_incremental.md new file mode 100644 index 0000000..f2e2a7f --- /dev/null +++ b/tests/__snapshots__/test_changelog/test_changelog_czespressif_incremental.md @@ -0,0 +1,10 @@ +## v1.3.0 (2024-08-30) + +### โœจ New features + +- **api**: rollback changes to JWT token handling *(Alice Johnson - b5e7a2d)* + +### ๐Ÿ› Bug fixes + +- **logging**: switch from console logs to structured JSON logging *(Eve Martin - d9b2c7e)* + diff --git a/tests/__snapshots__/test_changelog/test_changelog_czespressif_incremental_no_emoji.md b/tests/__snapshots__/test_changelog/test_changelog_czespressif_incremental_no_emoji.md new file mode 100644 index 0000000..d1d90c2 --- /dev/null +++ b/tests/__snapshots__/test_changelog/test_changelog_czespressif_incremental_no_emoji.md @@ -0,0 +1,10 @@ +## v1.3.0 (2024-08-30) + +### New features + +- **api**: rollback changes to JWT token handling *(Alice Johnson - b5e7a2d)* + +### Bug fixes + +- **logging**: switch from console logs to structured JSON logging *(Eve Martin - d9b2c7e)* + diff --git a/tests/__snapshots__/test_czespressif/test_example.md b/tests/__snapshots__/test_czespressif/test_example.md new file mode 100644 index 0000000..7e92651 --- /dev/null +++ b/tests/__snapshots__/test_czespressif/test_example.md @@ -0,0 +1,56 @@ + +--- + +Commit message schema: + + (): + <... empty line ...> + + <... empty line ...> + (BREAKING CHANGE: )* + ()* + +--- + +Commit types in this project: + + feat: A new feature + fix: A bug fix + docs: Documentation only change + refactor: A changeset neither fixing a bug nor adding a feature + remove: Removing code or files + change: A change made to the codebase. + ci: Changes to CI configuration files and scripts + test: Adding missing or correcting existing tests + revert: Revert one or more commits + + +--- + +Short commit messages (one line): + + fix: fix something (present or imperative, no period) + fix(package): fix something + feat(name): add a new feature + refactor(package)!: this refactoring breaks the thing + +--- + +Full commit messages with body and footer: + + feat(something): add something new (present/imperative, no period) + + Here optionally comes the details - this is commit message body. + It can be multiline, hyphens, asterisks, are okay. + + BREAKING CHANGE: It breaks something! + Closes https://github.com/espressif//issues/ + +--- + +More info: + +- https://www.conventionalcommits.org/en/v1.0.0/#specification +- https://github.com/espressif/conventional-precommit-linter +- https://github.com/espressif/standards + \ No newline at end of file diff --git a/tests/__snapshots__/test_czespressif/test_info.md b/tests/__snapshots__/test_czespressif/test_info.md new file mode 100644 index 0000000..8ffbaf8 --- /dev/null +++ b/tests/__snapshots__/test_czespressif/test_info.md @@ -0,0 +1,4 @@ +This is a custom Commitizen plugin for Espressif Systems. +It is mainly used to generate consistent and beautiful changelog with minimum settings from target project. +Can be used for creating commit messages, that passes Espressif standards. +Customization from target project is possible, check this plugin GitHub repo \ No newline at end of file diff --git a/tests/__snapshots__/test_czespressif/test_schema.md b/tests/__snapshots__/test_czespressif/test_schema.md new file mode 100644 index 0000000..b6436f2 --- /dev/null +++ b/tests/__snapshots__/test_czespressif/test_schema.md @@ -0,0 +1,6 @@ +(): + + + +(BREAKING CHANGE: )* +()* \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..82ec801 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,74 @@ +from __future__ import annotations + +from dataclasses import dataclass +from random import getrandbits + +import pytest + +from commitizen.config import BaseConfig +from commitizen.git import GitCommit +from syrupy.extensions.single_file import SingleFileSnapshotExtension +from syrupy.extensions.single_file import WriteMode + +from czespressif.config import CzEspressifConfig +from czespressif.config import CzEspressifSettings + + +class MarkdownSnapshotExtension(SingleFileSnapshotExtension): + _file_extension = 'md' + _write_mode = WriteMode.TEXT + + +@pytest.fixture +def snapshot(snapshot): + return snapshot.use_extension(MarkdownSnapshotExtension) + + +def randbytes(size: int) -> bytes: + return bytearray(getrandbits(8) for _ in range(size)) + + +@dataclass +class Factory: + config: CzEspressifConfig + + def parsed_message(self, **kwargs) -> tuple[dict, GitCommit]: + parsed = {'type': 'change', 'scope': None, 'message': 'I am a message', **kwargs} + prefix = parsed['type'] + msg = [f'{prefix}: {parsed["message"]}'] + body = parsed.get('body') + if body is not None: + msg.extend(('', body)) + footer = parsed.get('footer') + if footer is not None: + msg.extend(('', footer)) + return parsed, self.commit('\n'.join(msg)) + + def commit(self, title: str, **kwargs) -> GitCommit: + return GitCommit(rev=str(randbytes(8)), title=title, **kwargs) + + +@pytest.fixture +def settings(request) -> CzEspressifSettings: + settings = CzEspressifSettings() + for marker in reversed(list(request.node.iter_markers('settings'))): + settings.update(marker.kwargs) + return settings + + +@pytest.fixture +def config(settings): + config = BaseConfig() + config.settings.update({'name': 'czespressif'}) + config.settings.update(settings) + return config + + +@pytest.fixture +def cze_config(settings) -> CzEspressifConfig: + return CzEspressifConfig(settings) + + +@pytest.fixture +def factory(cze_config: CzEspressifConfig) -> Factory: + return Factory(cze_config) diff --git a/tests/test_changelog.py b/tests/test_changelog.py new file mode 100644 index 0000000..fc43f0b --- /dev/null +++ b/tests/test_changelog.py @@ -0,0 +1,392 @@ +from __future__ import annotations + +from pathlib import Path + +import pytest + +from commitizen import git +from commitizen.changelog import Metadata +from commitizen.commands.changelog import Changelog +from commitizen.exceptions import DryRunExit +from pytest_mock import MockerFixture +from syrupy.extensions.single_file import SingleFileSnapshotExtension +from syrupy.extensions.single_file import WriteMode + +FIXTURES = Path(__file__).parent / 'fixtures/changelogs' + + +class MarkdownSnapshotExtension(SingleFileSnapshotExtension): + _file_extension = 'md' + _write_mode = WriteMode.TEXT + + +@pytest.fixture +def snapshot(snapshot): + return snapshot.use_extension(MarkdownSnapshotExtension) + + +COMMITS_DATA = [ + { + 'rev': '22c4820bd927ad017649bcf6e8d03e30ddc946e9', + 'title': 'change(bump): [skip-ci] release v1.2.0 โ†’ v1.3.0', + 'body': '', + 'author': 'Jane Hunter', + 'author_email': 'jane.hunter@espressif.com', + }, + { + 'rev': 'b5e7a2d4c9f547d8b5c7f2a9e7c5d4a8e2d6b7c4', + 'title': 'feat(api): rollback changes to JWT token handling', + 'body': '', + 'author': 'Alice Johnson', + 'author_email': 'alice.johnson@espressif.com', + }, + { + 'rev': 'd9b2c7e8f4b946a7f5c7a5b8d7f3e4c2b5a6f9d3', + 'title': 'fix(logging): switch from console logs to structured JSON logging', + 'body': '', + 'author': 'Eve Martin', + 'author_email': 'eve.martin@espressif.com', + }, + { + 'rev': 'f2e7d1b7c4b942a5a5d3c2f9a7f5b4d9e5c3b7e4', + 'title': 'test(api): write unit tests for new password reset feature', + 'body': '', + 'author': 'Eve Martin', + 'author_email': 'eve.martin@espressif.com', + }, + { + 'rev': 'b7a4c5b2d5e147c8b5f7a2e5d4c9e3b2a7f4d9e5', + 'title': 'fix: correct typos in error messages displayed on UI', + 'body': '', + 'author': 'Bob Smith', + 'author_email': 'bob.smith@espressif.com', + }, + { + 'rev': 'c5d3e7a2f2b945c7a5e7d2b9f5c4e3b8d7f9e2a4', + 'title': 'feat(ui): improve loading animations for dashboard page', + 'body': '', + 'author': 'Diana White', + 'author_email': 'diana.white@espressif.com', + }, + { + 'rev': 'e2d9a7f5b5e24c5f9b7d4f2c5a7e9b4c3d5e6f2a', + 'title': 'ci: add automated deployment script for production', + 'body': '', + 'author': 'Charlie Green', + 'author_email': 'charlie.green@espressif.com', + }, + { + 'rev': 'd25d90e96d5f6bdeeca1f340cce9f7b87f7c8c0e', + 'title': 'change(bump): [skip-ci] release v1.2.0.rc0 โ†’ v1.2.0', + 'body': '', + 'author': 'Jane Hunter', + 'author_email': 'jane.hunter@espressif.com', + }, + { + 'rev': 'd7e2f9b5c4b24b5a9a7b3d2f5c4e7f9c2b8e5d1f', + 'title': 'ci: configure linter to enforce new coding standards', + 'body': '', + 'author': 'Diana White', + 'author_email': 'diana.white@espressif.com', + }, + { + 'rev': 'f5c7b1e4e4b947d9a7b5f2c5e4f9d7a8b5c3e7d9', + 'title': 'change(bump): [skip-ci] release v1.1.0 โ†’ v1.2.0', + 'body': '', + 'author': 'Alice Johnson', + 'author_email': 'alice.johnson@espressif.com', + }, + { + 'rev': 'e7c1d8b6e2b549a8a5c6b3e2d9a7f5c4e2d7b6a9', + 'title': 'refactor: optimize database queries for user data retrieval', + 'body': '', + 'author': 'Charlie Green', + 'author_email': 'charlie.green@espressif.com', + }, + { + 'rev': '05d02b594c146c89cf2c5d5c1e773da93fdcd1a3', + 'title': 'change(bump): [skip-ci] release v1.1.0 โ†’ v1.2.0.rc0', + 'body': '', + 'author': 'Jane Hunter', + 'author_email': 'jane.hunter@espressif.com', + }, + { + 'rev': 'f8d7e1c27f0e4935bb5b5e8f5c4e3b0d4e8b6c4e', + 'title': 'docs: update API documentation for user endpoint', + 'body': '', + 'author': 'Eve Martin', + 'author_email': 'eve.martin@espressif.com', + }, + { + 'rev': 'c3e7b3b9d7e645e9b7a4f5b7e2c8e9c4f8b5d4e9', + 'title': 'fix(frontend): correct layout issues in user profile page', + 'body': '', + 'author': 'Bob Smith', + 'author_email': 'bob.smith@espressif.com', + }, + { + 'rev': '0b17d79a2baf456a72e04f8986469d8a69a845b1', + 'title': 'change(bump): [skip-ci] release v1.0.0 โ†’ v1.1.0', + 'body': '', + 'author': 'Ethan Mitchell', + 'author_email': 'ethan.mitchell@espressif.com', + }, + { + 'rev': '1b7d1e7f2d8444a9bf7f5c547e8b9a3f66e4c8d1', + 'title': 'fix(api): update response codes for failed logins', + 'body': '', + 'author': 'Bob Smith', + 'author_email': 'bob.smith@espressif.com', + }, + { + 'rev': '3d5b9c71e82b44b9b5c6a8e23f9e456fb7d5a4c1', + 'title': 'test: add integration tests for payment gateway module', + 'body': '', + 'author': 'Diana White', + 'author_email': 'diana.white@espressif.com', + }, + { + 'rev': 'd4a8fbc34eae47c9871b5cb83e7db791f4c2c7b0', + 'title': 'revert: remove deprecated functions from auth service', + 'body': '', + 'author': 'Alice Johnson', + 'author_email': 'alice.johnson@espressif.com', + }, + { + 'rev': '8f0b3b9f1e2a4b84a5b5c789e2c6a8d4d3b5c6f0', + 'title': 'remove: delete old caching logic from request handlers', + 'body': '', + 'author': 'Charlie Green', + 'author_email': 'charlie.green@espressif.com', + }, + { + 'rev': 'de8dfc7d65f1e9ed8fd264dbe62380a520e9853f', + 'title': 'change(bump): [skip-ci] release v0.2.1 โ†’ v1.0.0', + 'body': '', + 'author': 'Jane Hunter', + 'author_email': 'jane.hunter@espressif.com', + }, + { + 'rev': '7c6d91fae8bcd5239a3f8c4973e7e843f93c1be0', + 'title': 'docs(frontend): Update README for new build system integration', + 'body': '', + 'author': 'Diana White', + 'author_email': 'diana.white@espressif.com', + }, + { + 'rev': 'c8e7a2d4b0fb55ea9b6f55b637f31af8e2f9d935', + 'title': 'ci(pipeline): add test for new database migrations', + 'body': '', + 'author': 'Charlie Green', + 'author_email': 'charlie.green@espressif.com', + }, + { + 'rev': 'e2d5bca6e1f047a9bfcd7b72c39d3147d3b2d1ea', + 'title': 'change: refactor code to use async/await syntax', + 'body': '', + 'author': 'Eve Martin', + 'author_email': 'eve.martin@espressif.com', + }, + { + 'rev': 'f3c34c19173b142b0fc0140a50ab5c60317e522a', + 'title': 'change(bump): [skip-ci] release v0.2.0 โ†’ v0.2.1', + 'body': '', + 'author': 'Victor Moore', + 'author_email': 'victor.moore@espressif.com', + }, + { + 'rev': 'b2c7e8a4fc76d68baf9a5b8a7de5d3b7d4cbb745', + 'title': 'feat(api): implement new authentication mechanism with JWT tokens', + 'body': '', + 'author': 'Alice Johnson', + 'author_email': 'alice.johnson@espressif.com', + }, + { + 'rev': '4b1d62bfc7a942e8b123b17f8cba07d5ec4de1e6', + 'title': 'fix: resolve null pointer exception in user session management', + 'body': '', + 'author': 'Bob Smith', + 'author_email': 'bob.smith@espressif.com', + }, + { + 'rev': '18e5faebc94d1aecc3fd7c8cfb63d5197800041f', + 'title': 'change(bump): [skip-ci] release v0.1.0 โ†’ v0.2.0', + 'body': '', + 'author': 'Nina Shaw', + 'author_email': 'nina.shaw@espressif.com', + }, + { + 'rev': 'b2c7e8a4fc76d68baf9a5b8a7de5d3b7d4cbb745', + 'title': 'feat(api): implement new authentication mechanism with JWT tokens', + 'body': '', + 'author': 'Alice Johnson', + 'author_email': 'alice.johnson@espressif.com', + }, + { + 'rev': '4b1d62bfc7a942e8b123b17f8cba07d5ec4de1e6', + 'title': 'fix: resolve null pointer exception in user session management', + 'body': '', + 'author': 'Bob Smith', + 'author_email': 'bob.smith@espressif.com', + }, + { + 'rev': '7d1f8c5bd1b56a65e30e6bb7f5dd1c2c1b0e5d4c', + 'title': 'ci(init): initialize project with empty commit, initial tag', + 'body': '', + 'author': 'Tomas Sebestik', + 'author_email': 'tomas.sebestik@espressif.com', + }, +] + + +TAGS = [ + ('v1.3.0', '22c4820bd927ad017649bcf6e8d03e30ddc946e9', '2024-08-30'), + ('v1.2.0', 'd25d90e96d5f6bdeeca1f340cce9f7b87f7c8c0e', '2024-07-15'), + ('v1.2.0.rc0', '05d02b594c146c89cf2c5d5c1e773da93fdcd1a3', '2024-06-10'), + ('v1.1.0', '0b17d79a2baf456a72e04f8986469d8a69a845b1', '2024-05-23'), + ('v1.0.0', 'de8dfc7d65f1e9ed8fd264dbe62380a520e9853f', '2024-04-12'), + ('v0.2.1', 'f3c34c19173b142b0fc0140a50ab5c60317e522a', '2024-03-29'), + ('v0.2.0', '18e5faebc94d1aecc3fd7c8cfb63d5197800041f', '2024-03-02'), + ('v0.1.0', '7d1f8c5bd1b56a65e30e6bb7f5dd1c2c1b0e5d4c', '2024-02-15'), +] + + +@pytest.fixture +def gitcommits() -> list[git.GitCommit]: + return [git.GitCommit(**commit) for commit in COMMITS_DATA] + + +@pytest.fixture +def tags() -> list[git.GitTag]: + tags = [git.GitTag(*tag) for tag in TAGS] + return tags + + +@pytest.fixture +def render_changelog(config, gitcommits, tags, capsys, mocker: MockerFixture): + """ + Generate a changelog using the same flow as the cz changelog command. + """ + + def fixture(unreleased: bool = True, **kwargs) -> str: + incremental = kwargs.get('incremental', config.settings.get('incremental', False)) + + # Mock Git commits based on whether it's incremental or full + mocker.patch('commitizen.git.get_commits', return_value=gitcommits[:4] if incremental else gitcommits) + mocker.patch('commitizen.git.get_tags', return_value=tags) + + kwargs['dry_run'] = True + kwargs['incremental'] = incremental + kwargs['unreleased_version'] = unreleased + + cmd = Changelog(config, kwargs) + mocker.patch.object(cmd.changelog_format, 'get_metadata').return_value = Metadata(latest_version='1.3.0') + + capsys.readouterr() + + try: + cmd() + except DryRunExit: + pass + + return capsys.readouterr().out + + return fixture + + +### Czespressif plugin +### ------------------------------------------------- + + +def test_changelog_czespressif_full(render_changelog, snapshot): + """ + DEFAULT SETTINGS - Full changelog + Emulates command: 'cz changelog' ('cz ch') + With pyproject.toml: + [tool.commitizen] + name = "czespressif" + changelog_merge_prerelease = true + tag_format = "v$version" + """ + assert render_changelog() == snapshot + + +@pytest.mark.settings(incremental=True) +def test_changelog_czespressif_incremental(render_changelog, snapshot): + """ + DEFAULT SETTINGS - Incremental changelog + Emulates command: 'cz changelog v1.3.0' ('cz ch v1.3.0') + 'cz changelog v1.2.0..v1.3.0' ('cz ch v1.2.0..1.3.0') + 'cz bump' + With pyproject.toml: + [tool.commitizen] + name = "czespressif" + changelog_merge_prerelease = true + tag_format = "v$version" + """ + assert render_changelog() == snapshot + + +@pytest.mark.settings(use_emoji=False) +def test_changelog_czespressif_full_no_emoji(render_changelog, snapshot): + """ + WITHOUT EMOJI - Full changelog + Emulates command: 'cz changelog' ('cz ch') + With pyproject.toml: + [tool.commitizen] + name = "czespressif" + changelog_merge_prerelease = true + tag_format = "v$version" + use_emoji = false + """ + assert render_changelog() == snapshot + + +@pytest.mark.settings(use_emoji=False) +@pytest.mark.settings(incremental=True) +def test_changelog_czespressif_incremental_no_emoji(render_changelog, snapshot): + """ + WITHOUT EMOJI - Incremental changelog + Emulates command: 'cz changelog v1.3.0' ('cz ch v1.3.0') + 'cz changelog v1.2.0..v1.3.0' ('cz ch v1.2.0..1.3.0') + 'cz bump' + With pyproject.toml: + [tool.commitizen] + name = "czespressif" + changelog_merge_prerelease = true + tag_format = "v$version" + use_emoji = false + """ + assert render_changelog() == snapshot + + +### WITHOUT 'czespressif' plugin +### ------------------------------------------------- + + +@pytest.mark.settings(name='cz_conventional_commits') # This is the default value for Commitizen +def test_changelog_cz_default_full(render_changelog, snapshot): + """ + DEFAULT SETTINGS COMMITIZEN WITHOUT czespressif PLUGIN - Full changelog + Emulates command: 'cz changelog' ('cz ch') + With pyproject.toml: + [tool.commitizen] + changelog_merge_prerelease = true + tag_format = "v$version" + """ + assert render_changelog() == snapshot + + +@pytest.mark.settings(name='cz_conventional_commits') # This is the default value for Commitizen +def test_changelog_cz_default_incremental(render_changelog, snapshot): + """ + DEFAULT SETTINGS COMMITIZEN WITHOUT czespressif PLUGIN - Incremental changelog + Emulates command: 'cz changelog v1.3.0' ('cz ch v1.3.0') + 'cz changelog v1.2.0..v1.3.0' ('cz ch v1.2.0..1.3.0') + 'cz bump' + With pyproject.toml: + [tool.commitizen] + changelog_merge_prerelease = true + tag_format = "v$version" + """ + assert render_changelog(incremental=True) == snapshot diff --git a/tests/test_czespressif.py b/tests/test_czespressif.py index e69de29..f581c4d 100644 --- a/tests/test_czespressif.py +++ b/tests/test_czespressif.py @@ -0,0 +1,30 @@ +import re + +from czespressif.czespressif import CzPluginEspressif + + +def strip_ansi_codes(text: str) -> str: + """Strip ANSI color codes from a string for snapshot comparison.""" + ansi_escape = re.compile(r'(?:\x1B[@-_][0-?]*[ -/]*[@-~])') + return ansi_escape.sub('', text) + + +def test_example(config, snapshot): + """Testing the output returned by 'cz example' and comparing it with snapshot""" + cze_config = CzPluginEspressif(config) + example = strip_ansi_codes(cze_config.example()) + assert example == snapshot + + +def test_schema(config, snapshot): + """Testing the output returned by 'cz schema' and comparing it with snapshot""" + cze_config = CzPluginEspressif(config) + schema = cze_config.schema() + assert schema == snapshot + + +def test_info(config, snapshot): + """Testing the output returned by 'cz info' and comparing it with snapshot""" + cze_config = CzPluginEspressif(config) + info = strip_ansi_codes(cze_config.info()) + assert info == snapshot