Skip to content

Commit a44fdca

Browse files
authored
Merge pull request #7 from akhundMurad/docs
chore(release): automate changelog generation and GitHub releases
2 parents 5980afb + 3d51703 commit a44fdca

7 files changed

Lines changed: 286 additions & 4 deletions

File tree

.github/workflows/publish.yaml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,61 @@ jobs:
7373

7474
- name: Deploy to GitHub Pages
7575
run: uv run mkdocs gh-deploy --force
76+
77+
changelog:
78+
runs-on: ubuntu-latest
79+
needs: [publish-package]
80+
permissions:
81+
contents: write
82+
steps:
83+
- name: Checkout
84+
uses: actions/checkout@v4
85+
with:
86+
fetch-depth: 0
87+
token: ${{ secrets.GITHUB_TOKEN }}
88+
89+
- name: Install git-cliff
90+
uses: taiki-e/install-action@git-cliff
91+
92+
- name: Generate full changelog
93+
run: git cliff -o CHANGELOG.md
94+
95+
- name: Generate release notes
96+
run: git cliff --latest --strip header -o RELEASE_NOTES.md
97+
98+
- name: Commit changelog
99+
run: |
100+
git config user.name "github-actions[bot]"
101+
git config user.email "github-actions[bot]@users.noreply.github.com"
102+
git add CHANGELOG.md
103+
git diff --staged --quiet || git commit -m "chore: update changelog for ${{ github.ref_name }}"
104+
git push origin HEAD:main
105+
106+
- name: Upload release notes
107+
uses: actions/upload-artifact@v4
108+
with:
109+
name: release-notes
110+
path: RELEASE_NOTES.md
111+
112+
github-release:
113+
runs-on: ubuntu-latest
114+
needs: [changelog]
115+
permissions:
116+
contents: write
117+
steps:
118+
- name: Download release notes
119+
uses: actions/download-artifact@v4
120+
with:
121+
name: release-notes
122+
123+
- name: Download dist
124+
uses: actions/download-artifact@v4
125+
with:
126+
name: dist
127+
path: dist/
128+
129+
- name: Create GitHub Release
130+
uses: softprops/action-gh-release@v2
131+
with:
132+
body_path: RELEASE_NOTES.md
133+
files: dist/*

CONTRIBUTING.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,40 @@ git checkout -b feature/my-feature
103103

104104
- Follow the existing coding style (enforced by ruff)
105105
- Add tests for new features in the appropriate `tests/` subdirectory
106-
- Keep commits focused and descriptive
106+
- Use [Conventional Commits](https://www.conventionalcommits.org/) for commit messages
107+
108+
### Commit Message Format
109+
110+
We use conventional commits to auto-generate the changelog. Format:
111+
112+
```
113+
<type>(<scope>): <description>
114+
115+
[optional body]
116+
```
117+
118+
**Types:**
119+
120+
| Type | Description |
121+
|------|-------------|
122+
| `feat` | New feature |
123+
| `fix` | Bug fix |
124+
| `docs` | Documentation only |
125+
| `refactor` | Code change that neither fixes a bug nor adds a feature |
126+
| `test` | Adding or updating tests |
127+
| `chore` | Maintenance tasks |
128+
| `perf` | Performance improvement |
129+
130+
**Examples:**
131+
132+
```bash
133+
feat(cli): add history trends command
134+
fix(rules): handle empty when block gracefully
135+
docs(readme): add installation instructions
136+
refactor(ir): simplify node merging logic
137+
```
138+
139+
The changelog is generated with `make changelog` (requires [git-cliff](https://git-cliff.org/)).
107140

108141
### 4. Run Tests and Checks
109142

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: install dev test lint format typecheck ty docs docs-build build clean help
1+
.PHONY: install dev test lint format typecheck ty docs docs-build build clean changelog help
22

33
install:
44
uv sync
@@ -31,6 +31,9 @@ docs-build:
3131
build:
3232
uv build
3333

34+
changelog:
35+
git cliff -o CHANGELOG.md
36+
3437
clean:
3538
rm -rf dist build *.egg-info .pytest_cache .mypy_cache .ruff_cache site
3639
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
@@ -47,4 +50,5 @@ help:
4750
@echo " docs - Serve documentation locally"
4851
@echo " docs-build - Build documentation"
4952
@echo " build - Build package"
53+
@echo " changelog - Generate CHANGELOG.md from commits"
5054
@echo " clean - Remove build artifacts"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,4 @@ $ pacta history trends .
146146

147147
## License
148148

149-
Apache-2.0. See [LICENSE](./LICENSE).
149+
Apache-2.0. See [LICENSE](https://github.com/akhundMurad/pacta/blob/main/LICENSE).

cliff.toml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# git-cliff configuration for generating CHANGELOG.md
2+
# Install: cargo install git-cliff (or brew install git-cliff)
3+
# Usage: git cliff -o CHANGELOG.md
4+
5+
[changelog]
6+
header = """
7+
# Changelog
8+
9+
All notable changes to this project will be documented in this file.
10+
11+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
12+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
13+
14+
"""
15+
body = """
16+
{% if version %}\
17+
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
18+
{% else %}\
19+
## [Unreleased]
20+
{% endif %}\
21+
{% for group, commits in commits | group_by(attribute="group") %}
22+
### {{ group | striptags | trim | upper_first }}
23+
{% for commit in commits %}
24+
- {% if commit.scope %}**{{ commit.scope }}:** {% endif %}\
25+
{{ commit.message | upper_first }}\
26+
{% endfor %}
27+
{% endfor %}\n
28+
"""
29+
footer = """
30+
{% for release in releases -%}
31+
{% if release.version -%}
32+
{% if release.previous.version -%}
33+
[{{ release.version | trim_start_matches(pat="v") }}]: \
34+
https://github.com/akhundMurad/pacta/compare/{{ release.previous.version }}...{{ release.version }}
35+
{% endif -%}
36+
{% else -%}
37+
[Unreleased]: https://github.com/akhundMurad/pacta/compare/{{ release.previous.version }}...HEAD
38+
{% endif -%}
39+
{% endfor %}
40+
"""
41+
trim = true
42+
43+
[git]
44+
conventional_commits = true
45+
filter_unconventional = true
46+
split_commits = false
47+
commit_parsers = [
48+
{ message = "^feat", group = "Added" },
49+
{ message = "^fix", group = "Fixed" },
50+
{ message = "^doc", group = "Documentation" },
51+
{ message = "^perf", group = "Performance" },
52+
{ message = "^refactor", group = "Changed" },
53+
{ message = "^style", group = "Changed" },
54+
{ message = "^test", group = "Testing" },
55+
{ message = "^chore\\(release\\)", skip = true },
56+
{ message = "^chore\\(deps\\)", skip = true },
57+
{ message = "^chore", group = "Miscellaneous" },
58+
{ body = ".*security", group = "Security" },
59+
]
60+
protect_breaking_commits = false
61+
filter_commits = false
62+
tag_pattern = "v[0-9].*"
63+
skip_tags = ""
64+
ignore_tags = ""
65+
topo_order = false
66+
sort_commits = "oldest"

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ dev = [
4040
"ty>=0.0.13",
4141
"mkdocs-material>=9.7.1",
4242
"ruff>=0.14.14",
43+
"pytest-cov>=7.0.0",
4344
]
4445

4546
[project.scripts]

0 commit comments

Comments
 (0)