Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 15 additions & 41 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,54 +83,28 @@ jobs:
with:
fetch-depth: 0

- name: Auto-generate Changelog
uses: BobAnkh/auto-generate-changelog@v1.3.0
with:
REPO_NAME: 'JnyJny/python-package-cookiecutter'
ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PATH: 'CHANGELOG.md'
COMMIT_MESSAGE: 'docs(CHANGELOG): update release notes'
TYPE: 'feat:Feature,bug:Bug Fixes,fix:Bug Fixes,docs:Documentation,refactor:Refactor,perf:Performance Improvements'
- name: Install git-cliff
run: pip install git-cliff

- name: Generate release notes for this tag
run: git cliff --latest --strip header > release_notes.md

- name: Update CHANGELOG.md
run: git cliff --output CHANGELOG.md

- name: Generate release notes
id: release_notes
- name: Commit updated CHANGELOG.md
run: |
set -euo pipefail

# Get the tag name
TAG_NAME=${GITHUB_REF#refs/tags/}
echo "Generating release notes for tag: $TAG_NAME"

# Get the previous tag
if PREVIOUS_TAG=$(git describe --tags --abbrev=0 ${TAG_NAME}^ 2>/dev/null); then
echo "Previous tag found: $PREVIOUS_TAG"
echo "## Changes since $PREVIOUS_TAG" >> release_notes.md
echo "" >> release_notes.md
git log --pretty=format:"- %s (%h)" ${PREVIOUS_TAG}..${TAG_NAME} >> release_notes.md
else
echo "No previous tag found, generating initial release notes"
echo "## Initial Release" >> release_notes.md
echo "" >> release_notes.md
echo "- Initial release of python-package-cookiecutter template" >> release_notes.md
fi

# Check if there's a CHANGELOG.md file
if [[ -f "CHANGELOG.md" ]]; then
echo "Adding CHANGELOG.md reference"
echo "" >> release_notes.md
echo "## Full Changelog" >> release_notes.md
echo "" >> release_notes.md
echo "See [CHANGELOG.md](CHANGELOG.md) for complete release notes." >> release_notes.md
fi

echo "Generated release notes:"
cat release_notes.md
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add CHANGELOG.md
git diff --cached --quiet || git commit -m "docs(CHANGELOG): update release notes"
git push origin HEAD:main

- name: Create GitHub Release
uses: ncipollo/release-action@v1
with:
bodyFile: "release_notes.md"
draft: false
prerelease: false
generateReleaseNotes: true
generateReleaseNotes: false
token: ${{ secrets.GITHUB_TOKEN }}
60 changes: 60 additions & 0 deletions cliff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# git-cliff configuration
# https://git-cliff.org/docs/configuration

[changelog]
header = """# CHANGELOG\n
All notable changes to this project will be documented in this file.\n
"""
body = """
{%- macro remote_url() -%}
https://github.com/JnyJny/python-package-cookiecutter
{%- endmacro -%}

{% if version -%}
## [{{ version | trim_start_matches(pat="v") }}]({{ self::remote_url() }}/releases/tag/{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }}
{% else -%}
## Unreleased
{% endif -%}

{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
- {{ commit.message | split(pat="\n") | first | trim }}\
{% if commit.remote.pr_number %} \
([#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}))\
{% endif %} \
([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{%- endfor %}
{% endfor %}
"""
footer = ""
trim = true

[git]
conventional_commits = true
filter_unconventional = false
split_commits = false
commit_parsers = [
{ message = "^Merge pull request", skip = true },
{ message = "^Merge branch", skip = true },
{ message = "^ci\\(deps\\)", skip = true },
{ message = "^ci:", skip = true },
{ message = "^docs\\(CHANGELOG\\)", skip = true },
{ message = "^v\\d+\\.\\d+", skip = true },

{ message = "^feat", group = "Features" },
{ message = "^fix", group = "Bug Fixes" },
{ message = "^doc", group = "Documentation" },
{ message = "^refactor", group = "Refactor" },
{ message = "^perf", group = "Performance" },
{ message = "^style", group = "Styling" },
{ message = "^test", group = "Testing" },

{ message = ".*", group = "Other" },
]
filter_commits = false
tag_pattern = "v[0-9].*"
skip_tags = ""
ignore_tags = ""
topo_order = false
sort_commits = "newest"
31 changes: 22 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dependencies = []
[dependency-groups]
dev = [
"cookiecutter>=2.6.0",
"git-cliff>=2.0.0",
"poethepoet>=0.35.0",
"pytest>=8.4.0",
"ruff>=0.11.13",
Expand Down Expand Up @@ -58,19 +59,31 @@ _push_tags = "git push --tags"
_update_pyproject = ["_add", "_commit", "_tag", "_push_tags", "_push"]

# Release management tasks
changelog.shell = "git log --pretty=format:'- %s (%h)' $(git describe --tags --abbrev=0 2>/dev/null || echo 'HEAD')..HEAD"
changelog.help = "[Release] Generate changelog since last tag."

release_notes.shell = "echo '## Release Notes' > RELEASE_NOTES.md && echo '' >> RELEASE_NOTES.md && git log --pretty=format:'- %s (%h)' $(git describe --tags --abbrev=0 2>/dev/null || echo 'HEAD')..HEAD >> RELEASE_NOTES.md"
release_notes.help = "[Release] Generate release notes file."

release_patch.sequence = [ "_patch_bump", "_update_pyproject"]
changelog.cmd = "git cliff"
changelog.help = "[Release] Generate full changelog to stdout."

release_notes.cmd = "git cliff --latest --strip header"
release_notes.help = "[Release] Generate release notes for the latest tag."

_preflight.shell = """
if [ "$(git branch --show-current)" != "main" ]; then
echo "ERROR: release must run from main branch" >&2
exit 1
fi
if [ -n "$(git status --porcelain)" ]; then
echo "ERROR: working tree is dirty" >&2
exit 1
fi
"""
_preflight.help = "Verify on main branch with clean working tree."

release_patch.sequence = [ "_preflight", "_patch_bump", "_update_pyproject"]
release_patch.help = "Publish patch release."

release_minor.sequence = [ "_minor_bump", "_update_pyproject"]
release_minor.sequence = [ "_preflight", "_minor_bump", "_update_pyproject"]
release_minor.help = "Publish minor release."

release_major.sequence = [ "_major_bump", "_update_pyproject"]
release_major.sequence = [ "_preflight", "_major_bump", "_update_pyproject"]
release_major.help = "Publish major release."

release.ref = "release_patch"
Expand Down
19 changes: 19 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 17 additions & 42 deletions {{ cookiecutter.package_name }}/.github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -130,55 +130,30 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
token: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %}

- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: dist-files
path: dist/

- name: Auto-generate Changelog
uses: BobAnkh/auto-generate-changelog@v1.2.5
with:
REPO_NAME: '{{ cookiecutter.github_username }}/{{ cookiecutter.package_name }}'
ACCESS_TOKEN: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %}
PATH: 'CHANGELOG.md'
COMMIT_MESSAGE: 'docs(CHANGELOG): update release notes'
TYPE: 'feat:Feature,bug:Bug Fixes,fix:Bug Fixes,docs:Documentation,refactor:Refactor,perf:Performance Improvements'

- name: Generate release notes
id: release_notes
- name: Install git-cliff
run: pip install git-cliff

- name: Generate release notes for this tag
run: git cliff --latest --strip header > release_notes.md

- name: Update CHANGELOG.md
run: git cliff --output CHANGELOG.md

- name: Commit updated CHANGELOG.md
run: |
set -euo pipefail

# Get the tag name
TAG_NAME=${GITHUB_REF#refs/tags/}
echo "Generating release notes for tag: $TAG_NAME"

# Get the previous tag
if PREVIOUS_TAG=$(git describe --tags --abbrev=0 ${TAG_NAME}^ 2>/dev/null); then
echo "Previous tag found: $PREVIOUS_TAG"
echo "## Changes since $PREVIOUS_TAG" >> release_notes.md
echo "" >> release_notes.md
git log --pretty=format:"- %s (%h)" ${PREVIOUS_TAG}..${TAG_NAME} >> release_notes.md
else
echo "No previous tag found, generating initial release notes"
echo "## Initial Release" >> release_notes.md
echo "" >> release_notes.md
echo "- Initial release of {{ cookiecutter.package_name }}" >> release_notes.md
fi

# Check if there's a CHANGELOG.md file
if [[ -f "CHANGELOG.md" ]]; then
echo "Adding CHANGELOG.md reference"
echo "" >> release_notes.md
echo "## Full Changelog" >> release_notes.md
echo "" >> release_notes.md
echo "See [CHANGELOG.md](CHANGELOG.md) for complete release notes." >> release_notes.md
fi

echo "Generated release notes:"
cat release_notes.md
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add CHANGELOG.md
git diff --cached --quiet || git commit -m "docs(CHANGELOG): update release notes"
git push origin HEAD:main

- name: Create GitHub Release
uses: ncipollo/release-action@v1
Expand All @@ -187,7 +162,7 @@ jobs:
bodyFile: "release_notes.md"
draft: false
prerelease: false
generateReleaseNotes: true
generateReleaseNotes: false
token: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %}

deploy-docs:
Expand Down
63 changes: 63 additions & 0 deletions {{ cookiecutter.package_name }}/cliff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# git-cliff configuration
# https://git-cliff.org/docs/configuration

[changelog]
header = """# CHANGELOG\n
All notable changes to this project will be documented in this file.\n
"""
body = """
{%- macro remote_url() -%}
https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.package_name }}
{%- endmacro -%}

{% if version -%}
## [{{ version | trim_start_matches(pat="v") }}]({{ self::remote_url() }}/releases/tag/{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }}
{% else -%}
## Unreleased
{% endif -%}

{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
- {{ commit.message | split(pat="\\n") | first | trim }}\
{% if commit.remote.pr_number %} \
([#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}))\
{% endif %} \
([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{%- endfor %}
{% endfor %}
"""
footer = ""
trim = true

[git]
conventional_commits = true
filter_unconventional = false
split_commits = false
commit_parsers = [
# Skip merge commits, dependabot CI bumps, changelog updates, and version bumps
{ message = "^Merge pull request", skip = true },
{ message = "^Merge branch", skip = true },
{ message = "^ci\\(deps\\)", skip = true },
{ message = "^ci:", skip = true },
{ message = "^docs\\(CHANGELOG\\)", skip = true },
{ message = "^v\\d+\\.\\d+", skip = true },

# Standard conventional commits
{ message = "^feat", group = "Features" },
{ message = "^fix", group = "Bug Fixes" },
{ message = "^doc", group = "Documentation" },
{ message = "^refactor", group = "Refactor" },
{ message = "^perf", group = "Performance" },
{ message = "^style", group = "Styling" },
{ message = "^test", group = "Testing" },

# Catch-all
{ message = ".*", group = "Other" },
]
filter_commits = false
tag_pattern = "v[0-9].*"
skip_tags = ""
ignore_tags = ""
topo_order = false
sort_commits = "newest"
Loading
Loading