feat: add semantic-release and conventional commit infrastructure

- Create pyproject.toml with python-semantic-release configuration
- Add release.yml workflow for automated releases
- Add commitlint pre-commit hook for conventional commits validation
- Add python-semantic-release to dev dependencies

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-08 07:52:06 +00:00
parent 80bcfba1d7
commit 04d18ee1f7
4 changed files with 282 additions and 1 deletions
+71
View File
@@ -0,0 +1,71 @@
name: Semantic Release
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: write
issues: write
pull-requests: write
packages: write
jobs:
release:
name: Semantic Release
runs-on: ubuntu-latest
if: github.repository == 'christianlouis/DocuElevate'
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install python-semantic-release
- name: Configure Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Run Semantic Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
semantic-release version --print
semantic-release version
semantic-release publish
- name: Update VERSION file if changed
run: |
if [ -f VERSION ]; then
git add VERSION
if ! git diff --staged --quiet; then
git commit -m "chore(release): update VERSION file [skip ci]"
git push
fi
fi
- name: Trigger Docker Build on Tag
if: startsWith(github.ref, 'refs/tags/')
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const ref = context.ref;
const tag = ref.replace('refs/tags/', '');
console.log(`New tag created: ${tag}`);
console.log('Docker build will be triggered automatically by the docker-build workflow');
+8
View File
@@ -69,3 +69,11 @@ repos:
.+\.json|
.env.demo
)$
# Conventional commits validation
- repo: https://github.com/compilerla/conventional-pre-commit
rev: v3.0.0
hooks:
- id: conventional-pre-commit
stages: [commit-msg]
args: []
+199
View File
@@ -0,0 +1,199 @@
[build-system]
requires = ["setuptools>=45", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "docuelevate"
dynamic = ["version"]
description = "Intelligent document processing system with AI-powered metadata extraction"
readme = "README.md"
requires-python = ">=3.11"
license = {text = "Apache-2.0"}
authors = [
{name = "Christian Louis", email = "christianlouis@users.noreply.github.com"}
]
keywords = ["document", "processing", "ocr", "ai", "metadata", "extraction"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
[project.urls]
Homepage = "https://github.com/christianlouis/DocuElevate"
Documentation = "https://github.com/christianlouis/DocuElevate/tree/main/docs"
Repository = "https://github.com/christianlouis/DocuElevate"
Issues = "https://github.com/christianlouis/DocuElevate/issues"
Changelog = "https://github.com/christianlouis/DocuElevate/blob/main/CHANGELOG.md"
[tool.setuptools.dynamic]
version = {file = "VERSION"}
[tool.semantic_release]
version_toml = []
version_variables = ["VERSION:__version__"]
version_source = "tag"
commit_version_number = true
tag_format = "v{version}"
major_on_zero = false
allow_zero_version = true
build_command = """
chmod +x scripts/generate_build_metadata.sh
./scripts/generate_build_metadata.sh
"""
[tool.semantic_release.branches.main]
match = "main"
prerelease = false
[tool.semantic_release.changelog]
template_dir = "templates"
changelog_file = "CHANGELOG.md"
exclude_commit_patterns = [
"^chore\\(release\\):",
"^Merge",
"^Bump version",
]
[tool.semantic_release.changelog.environment]
block_start_string = "{%"
block_end_string = "%}"
variable_start_string = "{{"
variable_end_string = "}}"
comment_start_string = "{#"
comment_end_string = "#}"
trim_blocks = false
lstrip_blocks = false
newline_sequence = "\n"
keep_trailing_newline = false
extensions = []
autoescape = true
[tool.semantic_release.commit_parser_options]
allowed_tags = [
"feat",
"fix",
"docs",
"style",
"refactor",
"perf",
"test",
"build",
"ci",
"chore",
]
minor_tags = ["feat"]
patch_tags = ["fix", "perf"]
default_bump_level = 0
[tool.semantic_release.remote]
name = "origin"
type = "github"
ignore_token_for_push = false
[tool.semantic_release.remote.token]
env = "GH_TOKEN"
[tool.semantic_release.publish]
dist_glob_patterns = []
upload_to_vcs_release = true
upload_to_pypi = false
upload_to_repository = false
# Black configuration
[tool.black]
line-length = 120
target-version = ['py311']
include = '\.pyi?$'
extend-exclude = '''
/(
# directories
\.eggs
| \.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| build
| dist
| migrations
)/
'''
# isort configuration
[tool.isort]
profile = "black"
line_length = 120
skip_gitignore = true
known_first_party = ["app"]
sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
# pytest configuration
[tool.pytest.ini_options]
minversion = "7.0"
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"-v",
"--strict-markers",
"--strict-config",
"--cov=app",
"--cov-report=term-missing",
"--cov-report=html",
"--cov-branch",
]
markers = [
"unit: Unit tests for individual functions/methods",
"integration: Integration tests for API endpoints and workflows",
"slow: Tests that take significant time to run",
"security: Security-related tests",
"requires_external: Tests requiring external services (OpenAI, Azure, etc.)",
"requires_db: Tests requiring database",
"requires_redis: Tests requiring Redis",
]
# mypy configuration
[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false
disallow_incomplete_defs = false
check_untyped_defs = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_no_return = true
warn_unreachable = true
strict_equality = true
ignore_missing_imports = true
# Coverage configuration
[tool.coverage.run]
source = ["app"]
omit = [
"*/tests/*",
"*/migrations/*",
"*/__pycache__/*",
"*/venv/*",
"*/env/*",
]
[tool.coverage.report]
precision = 2
show_missing = true
skip_covered = false
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
"@abstractmethod",
]
+4 -1
View File
@@ -23,4 +23,7 @@ safety>=3.0.0
pre-commit>=3.6.0
# License compliance
pip-licenses==5.5.1 # For license compliance checking
pip-licenses==5.5.1 # For license compliance checking
# Release automation
python-semantic-release>=9.0.0