diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e91898d..d91a25a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ name: CI on: pull_request: - branches: [master] + branches: [master, release] permissions: {} # no workflow-level permissions; each job declares its own diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7cb2321..ffecbe6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,6 +7,9 @@ # 3. github-release — create a GitHub Release with all assets attached. # 4. deploy-docs — generate and deploy versioned docs to GitHub Pages. # +# The tagged commit must be reachable from the 'release' branch. Tags pushed +# from master (or any other branch) will fail the ancestry check in step 1. +# # One-time setup required: # - Create a "pypi" environment in GitHub repo Settings > Environments. # - Register a Trusted Publisher on PyPI (account > Publishing): @@ -36,12 +39,26 @@ jobs: version: ${{ steps.version.outputs.version }} permissions: id-token: write - contents: read + contents: write steps: - name: Checkout uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: - persist-credentials: false + persist-credentials: true + fetch-depth: 0 + + - name: Verify tag is on the release branch + run: | + TAG_COMMIT="$(git rev-parse "${GITHUB_SHA}^{commit}")" + if git rev-parse --is-shallow-repository | grep -q true; then + git fetch origin release --unshallow + else + git fetch origin release + fi + if ! git merge-base --is-ancestor "$TAG_COMMIT" origin/release; then + echo "::error::Tagged commit is not on the release branch. Cherry-pick or merge to 'release' first." + exit 1 + fi - name: Install uv uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5 @@ -66,6 +83,21 @@ jobs: exit 1 fi + - name: Build changelog with towncrier + run: | + uv sync --group dev + uv run towncrier build --yes \ + --version "${{ steps.version.outputs.version }}" \ + --date "$(date -u +%Y-%m-%d)" + + - name: Commit changelog + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add CHANGELOG.md changes/ + git diff --cached --quiet || git commit -m "docs: changelog for v${{ steps.version.outputs.version }}" + git push origin HEAD + - name: Build sdist and wheel run: uv build @@ -226,6 +258,22 @@ jobs: permissions: contents: write steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + ref: main + + - name: Extract changelog for this version + id: changelog + run: | + VERSION="${{ needs.pypi-publish.outputs.version }}" + awk "/^## \[${VERSION}\]/{found=1; next} /^## \[/{if(found) exit} found{print}" \ + CHANGELOG.md > release_notes.md + if [ ! -s release_notes.md ]; then + echo "## What's Changed" > release_notes.md + echo "See [CHANGELOG.md](https://github.com/boscorat/bank_statement_parser/blob/main/CHANGELOG.md) for details." >> release_notes.md + fi + - name: Download Python dists uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: @@ -241,7 +289,7 @@ jobs: - name: Create release uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 with: - generate_release_notes: true + body_path: release_notes.md files: | dist/* packages/* diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..7a11dc9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,23 @@ +# Changelog + +All notable changes to the `uk-bank-statement-parser` package will be documented in this file. + +This project follows [Semantic Versioning](https://semver.org/) and uses [towncrier](https://towncrier.readthedocs.io/) for changelog management. Fragments live in the `changes/` directory. + +## [0.3.0] - 2026-06-28 + +### Features + +- First official stable release under Semantic Versioning. +- Async parallel PDF processing via `StatementBatch` with `turbo=True`. +- Star-schema data mart with DimTime, DimAccount, DimStatement, FactTransaction, and FactBalance. +- Configurable bank import patterns via TOML files in `project/config/import/`. +- PDF anonymisation support (optional dependency: `uk-bank-statement-anonymiser`). +- Forex rate lookup with configurable API sources. +- Export to Excel, CSV, JSON, and reporting data feeds. +- System packages (`.deb` and `.rpm`) via fpm in CI. +- Versioned documentation via mkdocs-material + mike. + +### Breaking Changes + +- The `filetype='both'` parameter (deprecated since 0.2.0) has been removed. Use `filetype='all'` instead. diff --git a/changes/.gitkeep b/changes/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/changes/_template.md.jinja b/changes/_template.md.jinja new file mode 100644 index 0000000..9682847 --- /dev/null +++ b/changes/_template.md.jinja @@ -0,0 +1,15 @@ +{% for section, _ in sections.items() %} +{% if section != "Internal" %} + +### {{ section }} + +{% for category, _, fragments in definitions.items() if fragments[section] %} +#### {{ category }} + +{% for text, _ in fragments[section] %} +- {{ text }} +{% endfor %} + +{% endfor %} +{% endif %} +{% endfor %} diff --git a/docs/changelog.md b/docs/changelog.md new file mode 120000 index 0000000..04c99a5 --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1 @@ +../CHANGELOG.md \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 4130fd6..3e1c330 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -55,6 +55,7 @@ extra: nav: - Home: index.md - Quick Start: guides/quick-start.md + - Changelog: changelog.md - Contributing: - Adding a New Bank: guides/contributing-new-bank.md - Local Testing: guides/local-testing.md diff --git a/pyproject.toml b/pyproject.toml index 3c68397..8bd915b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uk-bank-statement-parser" -version = "0.2.1rc13" +version = "0.3.0" description = "Parse bank statement PDFs, extract transactions, and persist to Parquet and SQLite." readme = "README.md" license = "LGPL-3.0-or-later" @@ -8,19 +8,29 @@ authors = [ { name = "Jason Farrar", email = "farrar.jason1@gmail.com" } ] requires-python = ">=3.11" -keywords = ["bank-statement", "pdf", "parser", "transactions", "polars", "sqlite", "parquet"] classifiers = [ - "Development Status :: 3 - Alpha", + "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: Financial and Insurance Industry", "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Office/Business :: Financial", + "Topic :: Text Processing :: Markup", + "Natural Language :: English", "Topic :: Software Development :: Libraries :: Python Modules", "Typing :: Typed", ] + +keywords = [ + "bank-statement", "pdf", "parser", "uk", "finance", "bank statement", + "hsbc", "natwest", "tsb", "halifax", "toml" +] + dependencies = [ "dacite>=1.9.2", "pdfplumber>=0.11.9", @@ -36,9 +46,12 @@ bsp = "bank_statement_parser.cli:main" bsp-dev = "bank_statement_parser:dev.main" [project.urls] -Homepage = "https://github.com/boscorat/bank_statement_parser" +Homepage = "https://boscorat.github.io/bank_statement_parser/latest" +Documentation = "https://boscorat.github.io/bank_statement_parser/latest" Repository = "https://github.com/boscorat/bank_statement_parser" -Issues = "https://github.com/boscorat/bank_statement_parser/issues" +"Bug Tracker" = "https://github.com/boscorat/bank_statement_parser/issues" +Changelog = "https://github.com/boscorat/bank_statement_parser/blob/master/CHANGELOG.md" + [build-system] requires = ["uv_build>=0.9.8,<0.12.0"] @@ -58,6 +71,7 @@ dev = [ "mike>=2.0.0", "mkdocs-material>=9.0.0", "pymdown-extensions>=10.0.0", + "towncrier>=24.8.0", ] [tool.pytest.ini_options] @@ -70,3 +84,21 @@ line-length = 140 target-version = "py311" lint.ignore = ["E402"] # Module-level imports intentionally organized by section with comments lint.unfixable = ["F401"] + +[tool.towncrier] +package = "uk-bank-statement-parser" +filename = "CHANGELOG.md" +directory = "changes" +title_format = "## [{version}] - {project_date}" +underlines = ["", "", ""] +template = "changes/_template.md.jinja" +type = [ + { name = "Features", showcontent = true, filename = "feature" }, + { name = "Bug Fixes", showcontent = true, filename = "bugfix" }, + { name = "Deprecations", showcontent = true, filename = "deprecation" }, + { name = "Security", showcontent = true, filename = "security" }, + { name = "Performance", showcontent = true, filename = "performance" }, + { name = "Breaking Changes", showcontent = true, filename = "breaking" }, + { name = "Documentation", showcontent = false, filename = "doc" }, + { name = "Internal", showcontent = false, filename = "internal" }, +] diff --git a/uv.lock b/uv.lock index 88470cb..04578b1 100644 --- a/uv.lock +++ b/uv.lock @@ -1501,6 +1501,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, ] +[[package]] +name = "towncrier" +version = "25.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "jinja2" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/eb/5bf25a34123698d3bbab39c5bc5375f8f8bcbcc5a136964ade66935b8b9d/towncrier-25.8.0.tar.gz", hash = "sha256:eef16d29f831ad57abb3ae32a0565739866219f1ebfbdd297d32894eb9940eb1", size = 76322, upload-time = "2025-08-30T11:41:55.393Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/06/8ba22ec32c74ac1be3baa26116e3c28bc0e76a5387476921d20b6fdade11/towncrier-25.8.0-py3-none-any.whl", hash = "sha256:b953d133d98f9aeae9084b56a3563fd2519dfc6ec33f61c9cd2c61ff243fb513", size = 65101, upload-time = "2025-08-30T11:41:53.644Z" }, +] + [[package]] name = "typing-extensions" version = "4.15.0" @@ -1536,7 +1549,7 @@ wheels = [ [[package]] name = "uk-bank-statement-parser" -version = "0.2.1rc13" +version = "0.3.0" source = { editable = "." } dependencies = [ { name = "dacite" }, @@ -1559,6 +1572,7 @@ dev = [ { name = "pytest" }, { name = "ruff" }, { name = "scalene" }, + { name = "towncrier" }, { name = "zensical" }, ] @@ -1581,6 +1595,7 @@ dev = [ { name = "pytest", specifier = ">=9.0.2" }, { name = "ruff", specifier = ">=0.14.9" }, { name = "scalene", specifier = ">=2.0.1" }, + { name = "towncrier", specifier = ">=24.8.0" }, { name = "zensical", specifier = ">=0.0.24" }, ]